aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig42
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/amba-clcd.c10
-rw-r--r--drivers/video/arcfb.c1
-rw-r--r--drivers/video/atafb.c2
-rw-r--r--drivers/video/aty/atyfb_base.c3
-rw-r--r--drivers/video/aty/radeon_i2c.c1
-rw-r--r--drivers/video/au1100fb.c6
-rw-r--r--drivers/video/au1200fb.c2
-rw-r--r--drivers/video/backlight/locomolcd.c4
-rw-r--r--drivers/video/bf54x-lq043fb.c6
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c2
-rw-r--r--drivers/video/bw2.c8
-rw-r--r--drivers/video/carminefb.c2
-rw-r--r--drivers/video/cg14.c10
-rw-r--r--drivers/video/cg3.c8
-rw-r--r--drivers/video/cg6.c10
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/console/bitblit.c2
-rw-r--r--drivers/video/console/fbcon.c37
-rw-r--r--drivers/video/console/fbcon.h1
-rw-r--r--drivers/video/console/fbcon_ccw.c2
-rw-r--r--drivers/video/console/fbcon_cw.c2
-rw-r--r--drivers/video/console/fbcon_ud.c2
-rw-r--r--drivers/video/console/vgacon.c2
-rw-r--r--drivers/video/controlfb.c2
-rw-r--r--drivers/video/cyber2000fb.c3
-rw-r--r--drivers/video/efifb.c111
-rw-r--r--drivers/video/epson1355fb.c2
-rw-r--r--drivers/video/fbcvt.c2
-rw-r--r--drivers/video/fbmem.c67
-rw-r--r--drivers/video/ffb.c8
-rw-r--r--drivers/video/fsl-diu-fb.c145
-rw-r--r--drivers/video/fsl-diu-fb.h223
-rw-r--r--drivers/video/gbefb.c22
-rw-r--r--drivers/video/i810/i810.h1
-rw-r--r--drivers/video/igafb.c5
-rw-r--r--drivers/video/imxfb.c85
-rw-r--r--drivers/video/intelfb/intelfb_i2c.c1
-rw-r--r--drivers/video/jz4740_fb.c847
-rw-r--r--drivers/video/leo.c10
-rw-r--r--drivers/video/matrox/i2c-matroxfb.c2
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.c5
-rw-r--r--drivers/video/matrox/matroxfb_base.h4
-rw-r--r--drivers/video/matrox/matroxfb_maven.c2
-rw-r--r--drivers/video/mb862xx/mb862xxfb.c4
-rw-r--r--drivers/video/mbx/mbxdebugfs.c6
-rw-r--r--drivers/video/metronomefb.c2
-rw-r--r--drivers/video/msm/mddi.c4
-rw-r--r--drivers/video/msm/mdp.c1
-rw-r--r--drivers/video/offb.c3
-rw-r--r--drivers/video/omap/blizzard.c2
-rw-r--r--drivers/video/omap/lcd_apollon.c3
-rw-r--r--drivers/video/omap/lcd_omap3beagle.c2
-rw-r--r--drivers/video/omap2/displays/Kconfig2
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c10
-rw-r--r--drivers/video/omap2/displays/panel-generic.c6
-rw-r--r--drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c6
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c6
-rw-r--r--drivers/video/omap2/displays/panel-taal.c567
-rw-r--r--drivers/video/omap2/displays/panel-toppoly-tdo35s.c14
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c6
-rw-r--r--drivers/video/omap2/dss/Makefile2
-rw-r--r--drivers/video/omap2/dss/core.c3
-rw-r--r--drivers/video/omap2/dss/dispc.c286
-rw-r--r--drivers/video/omap2/dss/display.c4
-rw-r--r--drivers/video/omap2/dss/dsi.c464
-rw-r--r--drivers/video/omap2/dss/dss.c6
-rw-r--r--drivers/video/omap2/dss/dss.h11
-rw-r--r--drivers/video/omap2/dss/dss_features.c191
-rw-r--r--drivers/video/omap2/dss/dss_features.h50
-rw-r--r--drivers/video/omap2/dss/manager.c237
-rw-r--r--drivers/video/omap2/dss/overlay.c26
-rw-r--r--drivers/video/omap2/dss/rfbi.c2
-rw-r--r--drivers/video/omap2/omapfb/Kconfig2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c188
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c255
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c70
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h29
-rw-r--r--drivers/video/omap2/vram.c29
-rw-r--r--drivers/video/p9100.c8
-rw-r--r--drivers/video/platinumfb.c4
-rw-r--r--drivers/video/pmag-ba-fb.c6
-rw-r--r--drivers/video/pmagb-b-fb.c12
-rw-r--r--drivers/video/pxa168fb.c57
-rw-r--r--drivers/video/q40fb.c4
-rw-r--r--drivers/video/s3c-fb.c811
-rw-r--r--drivers/video/savage/savagefb-i2c.c9
-rw-r--r--drivers/video/savage/savagefb.h1
-rw-r--r--drivers/video/sh_mipi_dsi.c505
-rw-r--r--drivers/video/sh_mobile_hdmi.c1110
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c202
-rw-r--r--drivers/video/sis/sis_main.c3
-rw-r--r--drivers/video/sunxvr1000.c8
-rw-r--r--drivers/video/tcx.c10
-rw-r--r--drivers/video/tdfxfb.c4
-rw-r--r--drivers/video/tgafb.c2
-rw-r--r--drivers/video/uvesafb.c7
-rw-r--r--drivers/video/vesafb.c2
-rw-r--r--drivers/video/vt8623fb.c2
-rw-r--r--drivers/video/w100fb.c4
-rw-r--r--drivers/video/xen-fbfront.c2
-rw-r--r--drivers/video/xilinxfb.c30
103 files changed, 5655 insertions, 1364 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 162a0b7ee4c2..27c1fb4b1e0d 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -17,6 +17,8 @@ source "drivers/gpu/vga/Kconfig"
17 17
18source "drivers/gpu/drm/Kconfig" 18source "drivers/gpu/drm/Kconfig"
19 19
20source "drivers/gpu/stub/Kconfig"
21
20config VGASTATE 22config VGASTATE
21 tristate 23 tristate
22 default n 24 default n
@@ -49,7 +51,7 @@ menuconfig FB
49 You need an utility program called fbset to make full use of frame 51 You need an utility program called fbset to make full use of frame
50 buffer devices. Please read <file:Documentation/fb/framebuffer.txt> 52 buffer devices. Please read <file:Documentation/fb/framebuffer.txt>
51 and the Framebuffer-HOWTO at 53 and the Framebuffer-HOWTO at
52 <http://www.munted.org.uk/programming/Framebuffer-HOWTO-1.2.html> for more 54 <http://www.munted.org.uk/programming/Framebuffer-HOWTO-1.3.html> for more
53 information. 55 information.
54 56
55 Say Y here and to the driver for your graphics board below if you 57 Say Y here and to the driver for your graphics board below if you
@@ -955,7 +957,7 @@ config FB_EPSON1355
955 Build in support for the SED1355 Epson Research Embedded RAMDAC 957 Build in support for the SED1355 Epson Research Embedded RAMDAC
956 LCD/CRT Controller (since redesignated as the S1D13505) as a 958 LCD/CRT Controller (since redesignated as the S1D13505) as a
957 framebuffer. Product specs at 959 framebuffer. Product specs at
958 <http://www.erd.epson.com/vdc/html/products.htm>. 960 <http://vdc.epson.com/>.
959 961
960config FB_S1D13XXX 962config FB_S1D13XXX
961 tristate "Epson S1D13XXX framebuffer support" 963 tristate "Epson S1D13XXX framebuffer support"
@@ -966,7 +968,7 @@ config FB_S1D13XXX
966 help 968 help
967 Support for S1D13XXX framebuffer device family (currently only 969 Support for S1D13XXX framebuffer device family (currently only
968 working with S1D13806). Product specs at 970 working with S1D13806). Product specs at
969 <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm> 971 <http://vdc.epson.com/>
970 972
971config FB_ATMEL 973config FB_ATMEL
972 tristate "AT91/AT32 LCD Controller support" 974 tristate "AT91/AT32 LCD Controller support"
@@ -1323,7 +1325,7 @@ config FB_RADEON
1323 don't need to choose this to run the Radeon in plain VGA mode. 1325 don't need to choose this to run the Radeon in plain VGA mode.
1324 1326
1325 There is a product page at 1327 There is a product page at
1326 http://apps.ati.com/ATIcompare/ 1328 http://products.amd.com/en-us/GraphicCardResult.aspx
1327 1329
1328config FB_RADEON_I2C 1330config FB_RADEON_I2C
1329 bool "DDC/I2C for ATI Radeon support" 1331 bool "DDC/I2C for ATI Radeon support"
@@ -1395,7 +1397,7 @@ config FB_ATY_CT
1395 Say Y here to support use of ATI's 64-bit Rage boards (or other 1397 Say Y here to support use of ATI's 64-bit Rage boards (or other
1396 boards based on the Mach64 CT, VT, GT, and LT chipsets) as a 1398 boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
1397 framebuffer device. The ATI product support page for these boards 1399 framebuffer device. The ATI product support page for these boards
1398 is at <http://support.ati.com/products/pc/mach64/>. 1400 is at <http://support.ati.com/products/pc/mach64/mach64.html>.
1399 1401
1400config FB_ATY_GENERIC_LCD 1402config FB_ATY_GENERIC_LCD
1401 bool "Mach64 generic LCD support (EXPERIMENTAL)" 1403 bool "Mach64 generic LCD support (EXPERIMENTAL)"
@@ -1871,6 +1873,7 @@ config FB_MBX_DEBUG
1871config FB_FSL_DIU 1873config FB_FSL_DIU
1872 tristate "Freescale DIU framebuffer support" 1874 tristate "Freescale DIU framebuffer support"
1873 depends on FB && FSL_SOC 1875 depends on FB && FSL_SOC
1876 select FB_MODE_HELPERS
1874 select FB_CFB_FILLRECT 1877 select FB_CFB_FILLRECT
1875 select FB_CFB_COPYAREA 1878 select FB_CFB_COPYAREA
1876 select FB_CFB_IMAGEBLIT 1879 select FB_CFB_IMAGEBLIT
@@ -1895,6 +1898,13 @@ config FB_W100
1895 1898
1896 If unsure, say N. 1899 If unsure, say N.
1897 1900
1901config SH_MIPI_DSI
1902 tristate
1903 depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
1904
1905config SH_LCD_MIPI_DSI
1906 bool
1907
1898config FB_SH_MOBILE_LCDC 1908config FB_SH_MOBILE_LCDC
1899 tristate "SuperH Mobile LCDC framebuffer support" 1909 tristate "SuperH Mobile LCDC framebuffer support"
1900 depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK 1910 depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
@@ -1903,9 +1913,20 @@ config FB_SH_MOBILE_LCDC
1903 select FB_SYS_IMAGEBLIT 1913 select FB_SYS_IMAGEBLIT
1904 select FB_SYS_FOPS 1914 select FB_SYS_FOPS
1905 select FB_DEFERRED_IO 1915 select FB_DEFERRED_IO
1916 select SH_MIPI_DSI if SH_LCD_MIPI_DSI
1906 ---help--- 1917 ---help---
1907 Frame buffer driver for the on-chip SH-Mobile LCD controller. 1918 Frame buffer driver for the on-chip SH-Mobile LCD controller.
1908 1919
1920config FB_SH_MOBILE_HDMI
1921 tristate "SuperH Mobile HDMI controller support"
1922 depends on FB_SH_MOBILE_LCDC
1923 select FB_MODE_HELPERS
1924 select SOUND
1925 select SND
1926 select SND_SOC
1927 ---help---
1928 Driver for the on-chip SH-Mobile HDMI controller.
1929
1909config FB_TMIO 1930config FB_TMIO
1910 tristate "Toshiba Mobile IO FrameBuffer support" 1931 tristate "Toshiba Mobile IO FrameBuffer support"
1911 depends on FB && MFD_CORE 1932 depends on FB && MFD_CORE
@@ -1930,7 +1951,7 @@ config FB_TMIO_ACCELL
1930 1951
1931config FB_S3C 1952config FB_S3C
1932 tristate "Samsung S3C framebuffer support" 1953 tristate "Samsung S3C framebuffer support"
1933 depends on FB && ARCH_S3C64XX 1954 depends on FB && S3C_DEV_FB
1934 select FB_CFB_FILLRECT 1955 select FB_CFB_FILLRECT
1935 select FB_CFB_COPYAREA 1956 select FB_CFB_COPYAREA
1936 select FB_CFB_IMAGEBLIT 1957 select FB_CFB_IMAGEBLIT
@@ -2229,6 +2250,15 @@ config FB_BROADSHEET
2229 and could also have been called by other names when coupled with 2250 and could also have been called by other names when coupled with
2230 a bridge adapter. 2251 a bridge adapter.
2231 2252
2253config FB_JZ4740
2254 tristate "JZ4740 LCD framebuffer support"
2255 depends on FB && MACH_JZ4740
2256 select FB_SYS_FILLRECT
2257 select FB_SYS_COPYAREA
2258 select FB_SYS_IMAGEBLIT
2259 help
2260 Framebuffer support for the JZ4740 SoC.
2261
2232source "drivers/video/omap/Kconfig" 2262source "drivers/video/omap/Kconfig"
2233source "drivers/video/omap2/Kconfig" 2263source "drivers/video/omap2/Kconfig"
2234 2264
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index ddc2af2ba45b..485e8ed1318c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -123,6 +123,8 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
123obj-$(CONFIG_FB_PS3) += ps3fb.o 123obj-$(CONFIG_FB_PS3) += ps3fb.o
124obj-$(CONFIG_FB_SM501) += sm501fb.o 124obj-$(CONFIG_FB_SM501) += sm501fb.o
125obj-$(CONFIG_FB_XILINX) += xilinxfb.o 125obj-$(CONFIG_FB_XILINX) += xilinxfb.o
126obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
127obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
126obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o 128obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
127obj-$(CONFIG_FB_OMAP) += omap/ 129obj-$(CONFIG_FB_OMAP) += omap/
128obj-y += omap2/ 130obj-y += omap2/
@@ -131,6 +133,7 @@ obj-$(CONFIG_FB_CARMINE) += carminefb.o
131obj-$(CONFIG_FB_MB862XX) += mb862xx/ 133obj-$(CONFIG_FB_MB862XX) += mb862xx/
132obj-$(CONFIG_FB_MSM) += msm/ 134obj-$(CONFIG_FB_MSM) += msm/
133obj-$(CONFIG_FB_NUC900) += nuc900fb.o 135obj-$(CONFIG_FB_NUC900) += nuc900fb.o
136obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
134 137
135# Platform or fallback drivers go here 138# Platform or fallback drivers go here
136obj-$(CONFIG_FB_UVESA) += uvesafb.o 139obj-$(CONFIG_FB_UVESA) += uvesafb.o
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index afe21e6eb544..1c2c68356ea7 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -80,7 +80,10 @@ static void clcdfb_disable(struct clcd_fb *fb)
80 /* 80 /*
81 * Disable CLCD clock source. 81 * Disable CLCD clock source.
82 */ 82 */
83 clk_disable(fb->clk); 83 if (fb->clk_enabled) {
84 fb->clk_enabled = false;
85 clk_disable(fb->clk);
86 }
84} 87}
85 88
86static void clcdfb_enable(struct clcd_fb *fb, u32 cntl) 89static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
@@ -88,7 +91,10 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
88 /* 91 /*
89 * Enable the CLCD clock source. 92 * Enable the CLCD clock source.
90 */ 93 */
91 clk_enable(fb->clk); 94 if (!fb->clk_enabled) {
95 fb->clk_enabled = true;
96 clk_enable(fb->clk);
97 }
92 98
93 /* 99 /*
94 * Bring up by first enabling.. 100 * Bring up by first enabling..
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index f3d7440f0072..3ec4923c2d84 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -2,7 +2,6 @@
2 * linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board 2 * linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board
3 * 3 *
4 * Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz> 4 * Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz>
5 * http://www.intworks.biz/arclcd
6 * 5 *
7 * This file is subject to the terms and conditions of the GNU General Public 6 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for 7 * License. See the file COPYING in the main directory of this archive for
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index f3aada20fa02..5b2b5ef4edba 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -1718,11 +1718,9 @@ static int falcon_setcolreg(unsigned int regno, unsigned int red,
1718 (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) | 1718 (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1719 (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) | 1719 (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1720 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12); 1720 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1721#ifdef ATAFB_FALCON
1722 ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) | 1721 ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
1723 ((green & 0xfc00) >> 5) | 1722 ((green & 0xfc00) >> 5) |
1724 ((blue & 0xf800) >> 11)); 1723 ((blue & 0xf800) >> 11));
1725#endif
1726 } 1724 }
1727 return 0; 1725 return 0;
1728} 1726}
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index f8d69ad36830..5bf91236c701 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2970,7 +2970,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
2970 struct atyfb_par *par = info->par; 2970 struct atyfb_par *par = info->par;
2971 struct device_node *dp; 2971 struct device_node *dp;
2972 char prop[128]; 2972 char prop[128];
2973 int node, len, i, j, ret; 2973 phandle node;
2974 int len, i, j, ret;
2974 u32 mem, chip_id; 2975 u32 mem, chip_id;
2975 2976
2976 /* 2977 /*
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index 359fc64e761a..78d1f4cd1fe0 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -7,7 +7,6 @@
7 7
8 8
9#include <linux/i2c.h> 9#include <linux/i2c.h>
10#include <linux/i2c-id.h>
11#include <linux/i2c-algo-bit.h> 10#include <linux/i2c-algo-bit.h>
12 11
13#include <asm/io.h> 12#include <asm/io.h>
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 40f61320ce16..34b2fc472fe8 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -95,7 +95,7 @@ struct fb_bitfield rgb_bitfields[][4] =
95 { { 8, 4, 0 }, { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } }, 95 { { 8, 4, 0 }, { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } },
96}; 96};
97 97
98static struct fb_fix_screeninfo au1100fb_fix __initdata = { 98static struct fb_fix_screeninfo au1100fb_fix __devinitdata = {
99 .id = "AU1100 FB", 99 .id = "AU1100 FB",
100 .xpanstep = 1, 100 .xpanstep = 1,
101 .ypanstep = 1, 101 .ypanstep = 1,
@@ -103,7 +103,7 @@ static struct fb_fix_screeninfo au1100fb_fix __initdata = {
103 .accel = FB_ACCEL_NONE, 103 .accel = FB_ACCEL_NONE,
104}; 104};
105 105
106static struct fb_var_screeninfo au1100fb_var __initdata = { 106static struct fb_var_screeninfo au1100fb_var __devinitdata = {
107 .activate = FB_ACTIVATE_NOW, 107 .activate = FB_ACTIVATE_NOW,
108 .height = -1, 108 .height = -1,
109 .width = -1, 109 .width = -1,
@@ -458,7 +458,7 @@ static struct fb_ops au1100fb_ops =
458 458
459/* AU1100 LCD controller device driver */ 459/* AU1100 LCD controller device driver */
460 460
461static int __init au1100fb_drv_probe(struct platform_device *dev) 461static int __devinit au1100fb_drv_probe(struct platform_device *dev)
462{ 462{
463 struct au1100fb_device *fbdev = NULL; 463 struct au1100fb_device *fbdev = NULL;
464 struct resource *regs_res; 464 struct resource *regs_res;
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index e77e8e4280fb..4ea187d93768 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1079,7 +1079,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
1079 * clock can only be obtain by dividing this value by an even integer. 1079 * clock can only be obtain by dividing this value by an even integer.
1080 * Fallback to a slower pixel clock if necessary. */ 1080 * Fallback to a slower pixel clock if necessary. */
1081 pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); 1081 pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
1082 pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2)); 1082 pixclock = min3(pixclock, fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2);
1083 1083
1084 if (AU1200_LCD_MAX_CLK % pixclock) { 1084 if (AU1200_LCD_MAX_CLK % pixclock) {
1085 int diff = AU1200_LCD_MAX_CLK % pixclock; 1085 int diff = AU1200_LCD_MAX_CLK % pixclock;
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index 7571bc26071e..d2f59015d517 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -2,7 +2,7 @@
2 * Backlight control code for Sharp Zaurus SL-5500 2 * Backlight control code for Sharp Zaurus SL-5500
3 * 3 *
4 * Copyright 2005 John Lenz <lenz@cs.wisc.edu> 4 * Copyright 2005 John Lenz <lenz@cs.wisc.edu>
5 * Maintainer: Pavel Machek <pavel@suse.cz> (unless John wants to :-) 5 * Maintainer: Pavel Machek <pavel@ucw.cz> (unless John wants to :-)
6 * GPL v2 6 * GPL v2
7 * 7 *
8 * This driver assumes single CPU. That's okay, because collie is 8 * This driver assumes single CPU. That's okay, because collie is
@@ -246,6 +246,6 @@ static void __exit locomolcd_exit(void)
246module_init(locomolcd_init); 246module_init(locomolcd_init);
247module_exit(locomolcd_exit); 247module_exit(locomolcd_exit);
248 248
249MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>, Pavel Machek <pavel@suse.cz>"); 249MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>, Pavel Machek <pavel@ucw.cz>");
250MODULE_DESCRIPTION("Collie LCD driver"); 250MODULE_DESCRIPTION("Collie LCD driver");
251MODULE_LICENSE("GPL"); 251MODULE_LICENSE("GPL");
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index b020ba7f1cf2..e7d0f525041e 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -241,12 +241,12 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
241 u16 disp = fbi->mach_info->disp; 241 u16 disp = fbi->mach_info->disp;
242 242
243 if (gpio_request(disp, DRIVER_NAME)) { 243 if (gpio_request(disp, DRIVER_NAME)) {
244 printk(KERN_ERR "Requesting GPIO %d faild\n", disp); 244 printk(KERN_ERR "Requesting GPIO %d failed\n", disp);
245 return -EFAULT; 245 return -EFAULT;
246 } 246 }
247 247
248 if (peripheral_request_list(eppi_req_18, DRIVER_NAME)) { 248 if (peripheral_request_list(eppi_req_18, DRIVER_NAME)) {
249 printk(KERN_ERR "Requesting Peripherals faild\n"); 249 printk(KERN_ERR "Requesting Peripherals failed\n");
250 gpio_free(disp); 250 gpio_free(disp);
251 return -EFAULT; 251 return -EFAULT;
252 } 252 }
@@ -256,7 +256,7 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
256 u16 eppi_req_24[] = EPPI0_24; 256 u16 eppi_req_24[] = EPPI0_24;
257 257
258 if (peripheral_request_list(eppi_req_24, DRIVER_NAME)) { 258 if (peripheral_request_list(eppi_req_24, DRIVER_NAME)) {
259 printk(KERN_ERR "Requesting Peripherals faild\n"); 259 printk(KERN_ERR "Requesting Peripherals failed\n");
260 peripheral_free_list(eppi_req_18); 260 peripheral_free_list(eppi_req_18);
261 gpio_free(disp); 261 gpio_free(disp);
262 return -EFAULT; 262 return -EFAULT;
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 7a50272eaab9..3cf77676947c 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -192,7 +192,7 @@ static int bfin_t350mcqb_request_ports(int action)
192{ 192{
193 if (action) { 193 if (action) {
194 if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) { 194 if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) {
195 printk(KERN_ERR "Requesting Peripherals faild\n"); 195 printk(KERN_ERR "Requesting Peripherals failed\n");
196 return -EFAULT; 196 return -EFAULT;
197 } 197 }
198 } else 198 } else
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 09f1b9b462f4..4dc13467281d 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -273,7 +273,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par,
273 return 0; 273 return 0;
274} 274}
275 275
276static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match) 276static int __devinit bw2_probe(struct platform_device *op, const struct of_device_id *match)
277{ 277{
278 struct device_node *dp = op->dev.of_node; 278 struct device_node *dp = op->dev.of_node;
279 struct fb_info *info; 279 struct fb_info *info;
@@ -350,7 +350,7 @@ out_err:
350 return err; 350 return err;
351} 351}
352 352
353static int __devexit bw2_remove(struct of_device *op) 353static int __devexit bw2_remove(struct platform_device *op)
354{ 354{
355 struct fb_info *info = dev_get_drvdata(&op->dev); 355 struct fb_info *info = dev_get_drvdata(&op->dev);
356 struct bw2_par *par = info->par; 356 struct bw2_par *par = info->par;
@@ -390,12 +390,12 @@ static int __init bw2_init(void)
390 if (fb_get_options("bw2fb", NULL)) 390 if (fb_get_options("bw2fb", NULL))
391 return -ENODEV; 391 return -ENODEV;
392 392
393 return of_register_driver(&bw2_driver, &of_bus_type); 393 return of_register_platform_driver(&bw2_driver);
394} 394}
395 395
396static void __exit bw2_exit(void) 396static void __exit bw2_exit(void)
397{ 397{
398 of_unregister_driver(&bw2_driver); 398 of_unregister_platform_driver(&bw2_driver);
399} 399}
400 400
401module_init(bw2_init); 401module_init(bw2_init);
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
index d8345fcc4fe3..6b19136aa181 100644
--- a/drivers/video/carminefb.c
+++ b/drivers/video/carminefb.c
@@ -432,7 +432,7 @@ static int init_hardware(struct carmine_hw *hw)
432 u32 loops; 432 u32 loops;
433 u32 ret; 433 u32 ret;
434 434
435 /* Initalize Carmine */ 435 /* Initialize Carmine */
436 /* Sets internal clock */ 436 /* Sets internal clock */
437 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 437 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
438 CARMINE_DFLT_IP_CLOCK_ENABLE); 438 CARMINE_DFLT_IP_CLOCK_ENABLE);
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index e5dc2241194f..24249535ac86 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -446,7 +446,7 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = {
446 { .size = 0 } 446 { .size = 0 }
447}; 447};
448 448
449static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, 449static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
450 struct cg14_par *par) 450 struct cg14_par *par)
451{ 451{
452 if (par->regs) 452 if (par->regs)
@@ -463,7 +463,7 @@ static void cg14_unmap_regs(struct of_device *op, struct fb_info *info,
463 info->screen_base, info->fix.smem_len); 463 info->screen_base, info->fix.smem_len);
464} 464}
465 465
466static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match) 466static int __devinit cg14_probe(struct platform_device *op, const struct of_device_id *match)
467{ 467{
468 struct device_node *dp = op->dev.of_node; 468 struct device_node *dp = op->dev.of_node;
469 struct fb_info *info; 469 struct fb_info *info;
@@ -570,7 +570,7 @@ out_err:
570 return err; 570 return err;
571} 571}
572 572
573static int __devexit cg14_remove(struct of_device *op) 573static int __devexit cg14_remove(struct platform_device *op)
574{ 574{
575 struct fb_info *info = dev_get_drvdata(&op->dev); 575 struct fb_info *info = dev_get_drvdata(&op->dev);
576 struct cg14_par *par = info->par; 576 struct cg14_par *par = info->par;
@@ -610,12 +610,12 @@ static int __init cg14_init(void)
610 if (fb_get_options("cg14fb", NULL)) 610 if (fb_get_options("cg14fb", NULL))
611 return -ENODEV; 611 return -ENODEV;
612 612
613 return of_register_driver(&cg14_driver, &of_bus_type); 613 return of_register_platform_driver(&cg14_driver);
614} 614}
615 615
616static void __exit cg14_exit(void) 616static void __exit cg14_exit(void)
617{ 617{
618 of_unregister_driver(&cg14_driver); 618 of_unregister_platform_driver(&cg14_driver);
619} 619}
620 620
621module_init(cg14_init); 621module_init(cg14_init);
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 558d73a948a0..09c0c3c42482 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -346,7 +346,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par)
346 return 0; 346 return 0;
347} 347}
348 348
349static int __devinit cg3_probe(struct of_device *op, 349static int __devinit cg3_probe(struct platform_device *op,
350 const struct of_device_id *match) 350 const struct of_device_id *match)
351{ 351{
352 struct device_node *dp = op->dev.of_node; 352 struct device_node *dp = op->dev.of_node;
@@ -433,7 +433,7 @@ out_err:
433 return err; 433 return err;
434} 434}
435 435
436static int __devexit cg3_remove(struct of_device *op) 436static int __devexit cg3_remove(struct platform_device *op)
437{ 437{
438 struct fb_info *info = dev_get_drvdata(&op->dev); 438 struct fb_info *info = dev_get_drvdata(&op->dev);
439 struct cg3_par *par = info->par; 439 struct cg3_par *par = info->par;
@@ -477,12 +477,12 @@ static int __init cg3_init(void)
477 if (fb_get_options("cg3fb", NULL)) 477 if (fb_get_options("cg3fb", NULL))
478 return -ENODEV; 478 return -ENODEV;
479 479
480 return of_register_driver(&cg3_driver, &of_bus_type); 480 return of_register_platform_driver(&cg3_driver);
481} 481}
482 482
483static void __exit cg3_exit(void) 483static void __exit cg3_exit(void)
484{ 484{
485 of_unregister_driver(&cg3_driver); 485 of_unregister_platform_driver(&cg3_driver);
486} 486}
487 487
488module_init(cg3_init); 488module_init(cg3_init);
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 480d761a27a8..2b5a97058b08 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -718,7 +718,7 @@ static void __devinit cg6_chip_init(struct fb_info *info)
718 sbus_writel(info->var.yres - 1, &fbc->clipmaxy); 718 sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
719} 719}
720 720
721static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, 721static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info,
722 struct cg6_par *par) 722 struct cg6_par *par)
723{ 723{
724 if (par->fbc) 724 if (par->fbc)
@@ -737,7 +737,7 @@ static void cg6_unmap_regs(struct of_device *op, struct fb_info *info,
737 info->fix.smem_len); 737 info->fix.smem_len);
738} 738}
739 739
740static int __devinit cg6_probe(struct of_device *op, 740static int __devinit cg6_probe(struct platform_device *op,
741 const struct of_device_id *match) 741 const struct of_device_id *match)
742{ 742{
743 struct device_node *dp = op->dev.of_node; 743 struct device_node *dp = op->dev.of_node;
@@ -827,7 +827,7 @@ out_err:
827 return err; 827 return err;
828} 828}
829 829
830static int __devexit cg6_remove(struct of_device *op) 830static int __devexit cg6_remove(struct platform_device *op)
831{ 831{
832 struct fb_info *info = dev_get_drvdata(&op->dev); 832 struct fb_info *info = dev_get_drvdata(&op->dev);
833 struct cg6_par *par = info->par; 833 struct cg6_par *par = info->par;
@@ -870,12 +870,12 @@ static int __init cg6_init(void)
870 if (fb_get_options("cg6fb", NULL)) 870 if (fb_get_options("cg6fb", NULL))
871 return -ENODEV; 871 return -ENODEV;
872 872
873 return of_register_driver(&cg6_driver, &of_bus_type); 873 return of_register_platform_driver(&cg6_driver);
874} 874}
875 875
876static void __exit cg6_exit(void) 876static void __exit cg6_exit(void)
877{ 877{
878 of_unregister_driver(&cg6_driver); 878 of_unregister_platform_driver(&cg6_driver);
879} 879}
880 880
881module_init(cg6_init); 881module_init(cg6_init);
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 8e8f18d29d7a..5a35f22372b9 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -6,7 +6,7 @@ menu "Console display driver support"
6 6
7config VGA_CONSOLE 7config VGA_CONSOLE
8 bool "VGA text console" if EMBEDDED || !X86 8 bool "VGA text console" if EMBEDDED || !X86
9 depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 9 depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER)
10 default y 10 default y
11 help 11 help
12 Saying Y here will allow you to use Linux in text mode through a 12 Saying Y here will allow you to use Linux in text mode through a
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index af88651b0735..28b1a834906b 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -22,7 +22,7 @@
22/* 22/*
23 * Accelerated handlers. 23 * Accelerated handlers.
24 */ 24 */
25static inline void update_attr(u8 *dst, u8 *src, int attribute, 25static void update_attr(u8 *dst, u8 *src, int attribute,
26 struct vc_data *vc) 26 struct vc_data *vc)
27{ 27{
28 int i, offset = (vc->vc_font.height < 10) ? 1 : 2; 28 int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index b0a3fa00706d..7ccc967831f0 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -283,10 +283,11 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
283 struct fbcon_ops *ops = info->fbcon_par; 283 struct fbcon_ops *ops = info->fbcon_par;
284 284
285 return (info->state != FBINFO_STATE_RUNNING || 285 return (info->state != FBINFO_STATE_RUNNING ||
286 vc->vc_mode != KD_TEXT || ops->graphics); 286 vc->vc_mode != KD_TEXT || ops->graphics) &&
287 !vt_force_oops_output(vc);
287} 288}
288 289
289static inline int get_color(struct vc_data *vc, struct fb_info *info, 290static int get_color(struct vc_data *vc, struct fb_info *info,
290 u16 c, int is_fg) 291 u16 c, int is_fg)
291{ 292{
292 int depth = fb_get_color_depth(&info->var, &info->fix); 293 int depth = fb_get_color_depth(&info->var, &info->fix);
@@ -1073,6 +1074,7 @@ static void fbcon_init(struct vc_data *vc, int init)
1073 if (p->userfont) 1074 if (p->userfont)
1074 charcnt = FNTCHARCNT(p->fontdata); 1075 charcnt = FNTCHARCNT(p->fontdata);
1075 1076
1077 vc->vc_panic_force_write = !!(info->flags & FBINFO_CAN_FORCE_OUTPUT);
1076 vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); 1078 vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
1077 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; 1079 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
1078 if (charcnt == 256) { 1080 if (charcnt == 256) {
@@ -2342,6 +2344,30 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
2342 return 0; 2344 return 0;
2343} 2345}
2344 2346
2347static int fbcon_debug_enter(struct vc_data *vc)
2348{
2349 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
2350 struct fbcon_ops *ops = info->fbcon_par;
2351
2352 ops->save_graphics = ops->graphics;
2353 ops->graphics = 0;
2354 if (info->fbops->fb_debug_enter)
2355 info->fbops->fb_debug_enter(info);
2356 fbcon_set_palette(vc, color_table);
2357 return 0;
2358}
2359
2360static int fbcon_debug_leave(struct vc_data *vc)
2361{
2362 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
2363 struct fbcon_ops *ops = info->fbcon_par;
2364
2365 ops->graphics = ops->save_graphics;
2366 if (info->fbops->fb_debug_leave)
2367 info->fbops->fb_debug_leave(info);
2368 return 0;
2369}
2370
2345static int fbcon_get_font(struct vc_data *vc, struct console_font *font) 2371static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
2346{ 2372{
2347 u8 *fontdata = vc->vc_font.data; 2373 u8 *fontdata = vc->vc_font.data;
@@ -3276,6 +3302,8 @@ static const struct consw fb_con = {
3276 .con_screen_pos = fbcon_screen_pos, 3302 .con_screen_pos = fbcon_screen_pos,
3277 .con_getxy = fbcon_getxy, 3303 .con_getxy = fbcon_getxy,
3278 .con_resize = fbcon_resize, 3304 .con_resize = fbcon_resize,
3305 .con_debug_enter = fbcon_debug_enter,
3306 .con_debug_leave = fbcon_debug_leave,
3279}; 3307};
3280 3308
3281static struct notifier_block fbcon_event_notifier = { 3309static struct notifier_block fbcon_event_notifier = {
@@ -3480,7 +3508,7 @@ static void fbcon_exit(void)
3480 softback_buf = 0UL; 3508 softback_buf = 0UL;
3481 3509
3482 for (i = 0; i < FB_MAX; i++) { 3510 for (i = 0; i < FB_MAX; i++) {
3483 int pending; 3511 int pending = 0;
3484 3512
3485 mapped = 0; 3513 mapped = 0;
3486 info = registered_fb[i]; 3514 info = registered_fb[i];
@@ -3488,7 +3516,8 @@ static void fbcon_exit(void)
3488 if (info == NULL) 3516 if (info == NULL)
3489 continue; 3517 continue;
3490 3518
3491 pending = cancel_work_sync(&info->queue); 3519 if (info->queue.func)
3520 pending = cancel_work_sync(&info->queue);
3492 DPRINTK("fbcon: %s pending work\n", (pending ? "canceled" : 3521 DPRINTK("fbcon: %s pending work\n", (pending ? "canceled" :
3493 "no")); 3522 "no"));
3494 3523
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 89a346880ec0..6bd2e0c7f209 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -74,6 +74,7 @@ struct fbcon_ops {
74 int cursor_reset; 74 int cursor_reset;
75 int blank_state; 75 int blank_state;
76 int graphics; 76 int graphics;
77 int save_graphics; /* for debug enter/leave */
77 int flags; 78 int flags;
78 int rotate; 79 int rotate;
79 int cur_rotate; 80 int cur_rotate;
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
index d135671d9961..41b32ae23dac 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -22,7 +22,7 @@
22 * Rotation 270 degrees 22 * Rotation 270 degrees
23 */ 23 */
24 24
25static inline void ccw_update_attr(u8 *dst, u8 *src, int attribute, 25static void ccw_update_attr(u8 *dst, u8 *src, int attribute,
26 struct vc_data *vc) 26 struct vc_data *vc)
27{ 27{
28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; 28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index 126110f8454f..6a737827beb1 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -22,7 +22,7 @@
22 * Rotation 90 degrees 22 * Rotation 90 degrees
23 */ 23 */
24 24
25static inline void cw_update_attr(u8 *dst, u8 *src, int attribute, 25static void cw_update_attr(u8 *dst, u8 *src, int attribute,
26 struct vc_data *vc) 26 struct vc_data *vc)
27{ 27{
28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; 28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
index 93a3e7381b50..ff0872c0498b 100644
--- a/drivers/video/console/fbcon_ud.c
+++ b/drivers/video/console/fbcon_ud.c
@@ -22,7 +22,7 @@
22 * Rotation 180 degrees 22 * Rotation 180 degrees
23 */ 23 */
24 24
25static inline void ud_update_attr(u8 *dst, u8 *src, int attribute, 25static void ud_update_attr(u8 *dst, u8 *src, int attribute,
26 struct vc_data *vc) 26 struct vc_data *vc)
27{ 27{
28 int i, offset = (vc->vc_font.height < 10) ? 1 : 2; 28 int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 182dd6f8aadd..54e32c513610 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -1108,7 +1108,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
1108 charmap += 4 * cmapsz; 1108 charmap += 4 * cmapsz;
1109#endif 1109#endif
1110 1110
1111 unlock_kernel();
1112 spin_lock_irq(&vga_lock); 1111 spin_lock_irq(&vga_lock);
1113 /* First, the Sequencer */ 1112 /* First, the Sequencer */
1114 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); 1113 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
@@ -1192,7 +1191,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
1192 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); 1191 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
1193 } 1192 }
1194 spin_unlock_irq(&vga_lock); 1193 spin_unlock_irq(&vga_lock);
1195 lock_kernel();
1196 return 0; 1194 return 0;
1197} 1195}
1198 1196
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 49fcbe8f18ac..c225dcce89e7 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -40,6 +40,8 @@
40#include <linux/vmalloc.h> 40#include <linux/vmalloc.h>
41#include <linux/delay.h> 41#include <linux/delay.h>
42#include <linux/interrupt.h> 42#include <linux/interrupt.h>
43#include <linux/of.h>
44#include <linux/of_address.h>
43#include <linux/fb.h> 45#include <linux/fb.h>
44#include <linux/init.h> 46#include <linux/init.h>
45#include <linux/pci.h> 47#include <linux/pci.h>
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 3a561df2e8a2..0c1afd13ddd3 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -388,6 +388,7 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
388 pseudo_val |= convert_bitfield(red, &var->red); 388 pseudo_val |= convert_bitfield(red, &var->red);
389 pseudo_val |= convert_bitfield(green, &var->green); 389 pseudo_val |= convert_bitfield(green, &var->green);
390 pseudo_val |= convert_bitfield(blue, &var->blue); 390 pseudo_val |= convert_bitfield(blue, &var->blue);
391 ret = 0;
391 break; 392 break;
392 } 393 }
393 394
@@ -436,6 +437,8 @@ static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
436 cyber2000fb_writeb(i | 4, 0x3cf, cfb); 437 cyber2000fb_writeb(i | 4, 0x3cf, cfb);
437 cyber2000fb_writeb(val, 0x3c6, cfb); 438 cyber2000fb_writeb(val, 0x3c6, cfb);
438 cyber2000fb_writeb(i, 0x3cf, cfb); 439 cyber2000fb_writeb(i, 0x3cf, cfb);
440 /* prevent card lock-up observed on x86 with CyberPro 2000 */
441 cyber2000fb_readb(0x3cf, cfb);
439} 442}
440 443
441static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw) 444static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index 4a56f46af40a..70477c2e4b61 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -13,10 +13,10 @@
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/screen_info.h> 14#include <linux/screen_info.h>
15#include <linux/dmi.h> 15#include <linux/dmi.h>
16 16#include <linux/pci.h>
17#include <video/vga.h> 17#include <video/vga.h>
18 18
19static struct fb_var_screeninfo efifb_defined __initdata = { 19static struct fb_var_screeninfo efifb_defined __devinitdata = {
20 .activate = FB_ACTIVATE_NOW, 20 .activate = FB_ACTIVATE_NOW,
21 .height = -1, 21 .height = -1,
22 .width = -1, 22 .width = -1,
@@ -27,7 +27,7 @@ static struct fb_var_screeninfo efifb_defined __initdata = {
27 .vmode = FB_VMODE_NONINTERLACED, 27 .vmode = FB_VMODE_NONINTERLACED,
28}; 28};
29 29
30static struct fb_fix_screeninfo efifb_fix __initdata = { 30static struct fb_fix_screeninfo efifb_fix __devinitdata = {
31 .id = "EFI VGA", 31 .id = "EFI VGA",
32 .type = FB_TYPE_PACKED_PIXELS, 32 .type = FB_TYPE_PACKED_PIXELS,
33 .accel = FB_ACCEL_NONE, 33 .accel = FB_ACCEL_NONE,
@@ -39,17 +39,31 @@ enum {
39 M_I20, /* 20-Inch iMac */ 39 M_I20, /* 20-Inch iMac */
40 M_I20_SR, /* 20-Inch iMac (Santa Rosa) */ 40 M_I20_SR, /* 20-Inch iMac (Santa Rosa) */
41 M_I24, /* 24-Inch iMac */ 41 M_I24, /* 24-Inch iMac */
42 M_I24_8_1, /* 24-Inch iMac, 8,1th gen */
43 M_I24_10_1, /* 24-Inch iMac, 10,1th gen */
44 M_I27_11_1, /* 27-Inch iMac, 11,1th gen */
42 M_MINI, /* Mac Mini */ 45 M_MINI, /* Mac Mini */
46 M_MINI_3_1, /* Mac Mini, 3,1th gen */
47 M_MINI_4_1, /* Mac Mini, 4,1th gen */
43 M_MB, /* MacBook */ 48 M_MB, /* MacBook */
44 M_MB_2, /* MacBook, 2nd rev. */ 49 M_MB_2, /* MacBook, 2nd rev. */
45 M_MB_3, /* MacBook, 3rd rev. */ 50 M_MB_3, /* MacBook, 3rd rev. */
51 M_MB_5_1, /* MacBook, 5th rev. */
52 M_MB_6_1, /* MacBook, 6th rev. */
53 M_MB_7_1, /* MacBook, 7th rev. */
46 M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ 54 M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
47 M_MBA, /* MacBook Air */ 55 M_MBA, /* MacBook Air */
48 M_MBP, /* MacBook Pro */ 56 M_MBP, /* MacBook Pro */
49 M_MBP_2, /* MacBook Pro 2nd gen */ 57 M_MBP_2, /* MacBook Pro 2nd gen */
58 M_MBP_2_2, /* MacBook Pro 2,2nd gen */
50 M_MBP_SR, /* MacBook Pro (Santa Rosa) */ 59 M_MBP_SR, /* MacBook Pro (Santa Rosa) */
51 M_MBP_4, /* MacBook Pro, 4th gen */ 60 M_MBP_4, /* MacBook Pro, 4th gen */
52 M_MBP_5_1, /* MacBook Pro, 5,1th gen */ 61 M_MBP_5_1, /* MacBook Pro, 5,1th gen */
62 M_MBP_5_2, /* MacBook Pro, 5,2th gen */
63 M_MBP_5_3, /* MacBook Pro, 5,3rd gen */
64 M_MBP_6_1, /* MacBook Pro, 6,1th gen */
65 M_MBP_6_2, /* MacBook Pro, 6,2th gen */
66 M_MBP_7_1, /* MacBook Pro, 7,1th gen */
53 M_UNKNOWN /* placeholder */ 67 M_UNKNOWN /* placeholder */
54}; 68};
55 69
@@ -59,19 +73,33 @@ static struct efifb_dmi_info {
59 int stride; 73 int stride;
60 int width; 74 int width;
61 int height; 75 int height;
62} dmi_list[] = { 76} dmi_list[] __initdata = {
63 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, 77 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 },
64 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ 78 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
65 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, 79 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
66 [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ 80 [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */
81 [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 },
82 [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 },
83 [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 },
67 [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, 84 [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 },
85 [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 },
86 [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 },
68 [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, 87 [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 },
88 [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 },
89 [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 },
90 [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 },
69 [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, 91 [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 },
70 [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, 92 [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 },
71 [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ 93 [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
94 [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 },
72 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, 95 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
73 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, 96 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
74 [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, 97 [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 },
98 [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 },
99 [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 },
100 [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 },
101 [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 },
102 [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 },
75 [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } 103 [M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
76}; 104};
77 105
@@ -83,7 +111,7 @@ static int set_system(const struct dmi_system_id *id);
83 DMI_MATCH(DMI_PRODUCT_NAME, name) }, \ 111 DMI_MATCH(DMI_PRODUCT_NAME, name) }, \
84 &dmi_list[enumid] } 112 &dmi_list[enumid] }
85 113
86static struct dmi_system_id __initdata dmi_system_table[] = { 114static const struct dmi_system_id dmi_system_table[] __initconst = {
87 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17), 115 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17),
88 /* At least one of these two will be right; maybe both? */ 116 /* At least one of these two will be right; maybe both? */
89 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20), 117 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20),
@@ -92,7 +120,12 @@ static struct dmi_system_id __initdata dmi_system_table[] = {
92 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24), 120 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
93 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24), 121 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
94 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR), 122 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
123 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac8,1", M_I24_8_1),
124 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac10,1", M_I24_10_1),
125 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac11,1", M_I27_11_1),
95 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI), 126 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
127 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini3,1", M_MINI_3_1),
128 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini4,1", M_MINI_4_1),
96 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB), 129 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
97 /* At least one of these two will be right; maybe both? */ 130 /* At least one of these two will be right; maybe both? */
98 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB), 131 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
@@ -101,14 +134,23 @@ static struct dmi_system_id __initdata dmi_system_table[] = {
101 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB), 134 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
102 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB), 135 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
103 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB), 136 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
137 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook5,1", M_MB_5_1),
138 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
139 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
104 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), 140 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
105 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), 141 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
106 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), 142 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
143 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
107 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2), 144 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
108 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR), 145 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
109 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR), 146 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
110 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4), 147 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
111 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1), 148 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1),
149 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,2", M_MBP_5_2),
150 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,3", M_MBP_5_3),
151 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
152 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
153 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
112 {}, 154 {},
113}; 155};
114 156
@@ -116,7 +158,7 @@ static int set_system(const struct dmi_system_id *id)
116{ 158{
117 struct efifb_dmi_info *info = id->driver_data; 159 struct efifb_dmi_info *info = id->driver_data;
118 if (info->base == 0) 160 if (info->base == 0)
119 return -ENODEV; 161 return 0;
120 162
121 printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " 163 printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
122 "(%dx%d, stride %d)\n", id->ident, 164 "(%dx%d, stride %d)\n", id->ident,
@@ -124,18 +166,55 @@ static int set_system(const struct dmi_system_id *id)
124 info->stride); 166 info->stride);
125 167
126 /* Trust the bootloader over the DMI tables */ 168 /* Trust the bootloader over the DMI tables */
127 if (screen_info.lfb_base == 0) 169 if (screen_info.lfb_base == 0) {
170#if defined(CONFIG_PCI)
171 struct pci_dev *dev = NULL;
172 int found_bar = 0;
173#endif
128 screen_info.lfb_base = info->base; 174 screen_info.lfb_base = info->base;
129 if (screen_info.lfb_linelength == 0)
130 screen_info.lfb_linelength = info->stride;
131 if (screen_info.lfb_width == 0)
132 screen_info.lfb_width = info->width;
133 if (screen_info.lfb_height == 0)
134 screen_info.lfb_height = info->height;
135 if (screen_info.orig_video_isVGA == 0)
136 screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
137 175
138 return 0; 176#if defined(CONFIG_PCI)
177 /* make sure that the address in the table is actually on a
178 * VGA device's PCI BAR */
179
180 for_each_pci_dev(dev) {
181 int i;
182 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
183 continue;
184 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
185 resource_size_t start, end;
186
187 start = pci_resource_start(dev, i);
188 if (start == 0)
189 break;
190 end = pci_resource_end(dev, i);
191 if (screen_info.lfb_base >= start &&
192 screen_info.lfb_base < end) {
193 found_bar = 1;
194 }
195 }
196 }
197 if (!found_bar)
198 screen_info.lfb_base = 0;
199#endif
200 }
201 if (screen_info.lfb_base) {
202 if (screen_info.lfb_linelength == 0)
203 screen_info.lfb_linelength = info->stride;
204 if (screen_info.lfb_width == 0)
205 screen_info.lfb_width = info->width;
206 if (screen_info.lfb_height == 0)
207 screen_info.lfb_height = info->height;
208 if (screen_info.orig_video_isVGA == 0)
209 screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
210 } else {
211 screen_info.lfb_linelength = 0;
212 screen_info.lfb_width = 0;
213 screen_info.lfb_height = 0;
214 screen_info.orig_video_isVGA = 0;
215 return 0;
216 }
217 return 1;
139} 218}
140 219
141static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, 220static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index db9713b49ce9..a268cbf1cbea 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -4,7 +4,7 @@
4 * Epson Research S1D13505 Embedded RAMDAC LCD/CRT Controller 4 * Epson Research S1D13505 Embedded RAMDAC LCD/CRT Controller
5 * (previously known as SED1355) 5 * (previously known as SED1355)
6 * 6 *
7 * Cf. http://www.erd.epson.com/vdc/html/S1D13505.html 7 * Cf. http://vdc.epson.com/
8 * 8 *
9 * 9 *
10 * Copyright (C) Hewlett-Packard Company. All rights reserved. 10 * Copyright (C) Hewlett-Packard Company. All rights reserved.
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
index 7293eaccd81b..7cb715dfc0e1 100644
--- a/drivers/video/fbcvt.c
+++ b/drivers/video/fbcvt.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * Based from the VESA(TM) Coordinated Video Timing Generator by 6 * Based from the VESA(TM) Coordinated Video Timing Generator by
7 * Graham Loveridge April 9, 2003 available at 7 * Graham Loveridge April 9, 2003 available at
8 * http://www.vesa.org/public/CVT/CVTd6r1.xls 8 * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
9 * 9 *
10 * This file is subject to the terms and conditions of the GNU General Public 10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive 11 * License. See the file COPYING in the main directory of this archive
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 731fce64df9d..0e6aa3d96a42 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -697,9 +697,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
697 struct inode *inode = file->f_path.dentry->d_inode; 697 struct inode *inode = file->f_path.dentry->d_inode;
698 int fbidx = iminor(inode); 698 int fbidx = iminor(inode);
699 struct fb_info *info = registered_fb[fbidx]; 699 struct fb_info *info = registered_fb[fbidx];
700 u32 *buffer, *dst; 700 u8 *buffer, *dst;
701 u32 __iomem *src; 701 u8 __iomem *src;
702 int c, i, cnt = 0, err = 0; 702 int c, cnt = 0, err = 0;
703 unsigned long total_size; 703 unsigned long total_size;
704 704
705 if (!info || ! info->screen_base) 705 if (!info || ! info->screen_base)
@@ -730,7 +730,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
730 if (!buffer) 730 if (!buffer)
731 return -ENOMEM; 731 return -ENOMEM;
732 732
733 src = (u32 __iomem *) (info->screen_base + p); 733 src = (u8 __iomem *) (info->screen_base + p);
734 734
735 if (info->fbops->fb_sync) 735 if (info->fbops->fb_sync)
736 info->fbops->fb_sync(info); 736 info->fbops->fb_sync(info);
@@ -738,17 +738,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
738 while (count) { 738 while (count) {
739 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 739 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
740 dst = buffer; 740 dst = buffer;
741 for (i = c >> 2; i--; ) 741 fb_memcpy_fromfb(dst, src, c);
742 *dst++ = fb_readl(src++); 742 dst += c;
743 if (c & 3) { 743 src += c;
744 u8 *dst8 = (u8 *) dst;
745 u8 __iomem *src8 = (u8 __iomem *) src;
746
747 for (i = c & 3; i--;)
748 *dst8++ = fb_readb(src8++);
749
750 src = (u32 __iomem *) src8;
751 }
752 744
753 if (copy_to_user(buf, buffer, c)) { 745 if (copy_to_user(buf, buffer, c)) {
754 err = -EFAULT; 746 err = -EFAULT;
@@ -772,9 +764,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
772 struct inode *inode = file->f_path.dentry->d_inode; 764 struct inode *inode = file->f_path.dentry->d_inode;
773 int fbidx = iminor(inode); 765 int fbidx = iminor(inode);
774 struct fb_info *info = registered_fb[fbidx]; 766 struct fb_info *info = registered_fb[fbidx];
775 u32 *buffer, *src; 767 u8 *buffer, *src;
776 u32 __iomem *dst; 768 u8 __iomem *dst;
777 int c, i, cnt = 0, err = 0; 769 int c, cnt = 0, err = 0;
778 unsigned long total_size; 770 unsigned long total_size;
779 771
780 if (!info || !info->screen_base) 772 if (!info || !info->screen_base)
@@ -811,7 +803,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
811 if (!buffer) 803 if (!buffer)
812 return -ENOMEM; 804 return -ENOMEM;
813 805
814 dst = (u32 __iomem *) (info->screen_base + p); 806 dst = (u8 __iomem *) (info->screen_base + p);
815 807
816 if (info->fbops->fb_sync) 808 if (info->fbops->fb_sync)
817 info->fbops->fb_sync(info); 809 info->fbops->fb_sync(info);
@@ -825,19 +817,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
825 break; 817 break;
826 } 818 }
827 819
828 for (i = c >> 2; i--; ) 820 fb_memcpy_tofb(dst, src, c);
829 fb_writel(*src++, dst++); 821 dst += c;
830 822 src += c;
831 if (c & 3) {
832 u8 *src8 = (u8 *) src;
833 u8 __iomem *dst8 = (u8 __iomem *) dst;
834
835 for (i = c & 3; i--; )
836 fb_writeb(*src8++, dst8++);
837
838 dst = (u32 __iomem *) dst8;
839 }
840
841 *ppos += c; 823 *ppos += c;
842 buf += c; 824 buf += c;
843 cnt += c; 825 cnt += c;
@@ -877,13 +859,13 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
877 859
878 if ((err = info->fbops->fb_pan_display(var, info))) 860 if ((err = info->fbops->fb_pan_display(var, info)))
879 return err; 861 return err;
880 info->var.xoffset = var->xoffset; 862 info->var.xoffset = var->xoffset;
881 info->var.yoffset = var->yoffset; 863 info->var.yoffset = var->yoffset;
882 if (var->vmode & FB_VMODE_YWRAP) 864 if (var->vmode & FB_VMODE_YWRAP)
883 info->var.vmode |= FB_VMODE_YWRAP; 865 info->var.vmode |= FB_VMODE_YWRAP;
884 else 866 else
885 info->var.vmode &= ~FB_VMODE_YWRAP; 867 info->var.vmode &= ~FB_VMODE_YWRAP;
886 return 0; 868 return 0;
887} 869}
888 870
889static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, 871static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
@@ -1362,6 +1344,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
1362 vma->vm_pgoff = off >> PAGE_SHIFT; 1344 vma->vm_pgoff = off >> PAGE_SHIFT;
1363 /* This is an IO map - tell maydump to skip this VMA */ 1345 /* This is an IO map - tell maydump to skip this VMA */
1364 vma->vm_flags |= VM_IO | VM_RESERVED; 1346 vma->vm_flags |= VM_IO | VM_RESERVED;
1347 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
1365 fb_pgprotect(file, vma, off); 1348 fb_pgprotect(file, vma, off);
1366 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, 1349 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1367 vma->vm_end - vma->vm_start, vma->vm_page_prot)) 1350 vma->vm_end - vma->vm_start, vma->vm_page_prot))
@@ -1438,6 +1421,7 @@ static const struct file_operations fb_fops = {
1438#ifdef CONFIG_FB_DEFERRED_IO 1421#ifdef CONFIG_FB_DEFERRED_IO
1439 .fsync = fb_deferred_io_fsync, 1422 .fsync = fb_deferred_io_fsync,
1440#endif 1423#endif
1424 .llseek = default_llseek,
1441}; 1425};
1442 1426
1443struct class *fb_class; 1427struct class *fb_class;
@@ -1786,7 +1770,7 @@ static int ofonly __read_mostly;
1786int fb_get_options(char *name, char **option) 1770int fb_get_options(char *name, char **option)
1787{ 1771{
1788 char *opt, *options = NULL; 1772 char *opt, *options = NULL;
1789 int opt_len, retval = 0; 1773 int retval = 0;
1790 int name_len = strlen(name), i; 1774 int name_len = strlen(name), i;
1791 1775
1792 if (name_len && ofonly && strncmp(name, "offb", 4)) 1776 if (name_len && ofonly && strncmp(name, "offb", 4))
@@ -1796,8 +1780,7 @@ int fb_get_options(char *name, char **option)
1796 for (i = 0; i < FB_MAX; i++) { 1780 for (i = 0; i < FB_MAX; i++) {
1797 if (video_options[i] == NULL) 1781 if (video_options[i] == NULL)
1798 continue; 1782 continue;
1799 opt_len = strlen(video_options[i]); 1783 if (!video_options[i][0])
1800 if (!opt_len)
1801 continue; 1784 continue;
1802 opt = video_options[i]; 1785 opt = video_options[i];
1803 if (!strncmp(name, opt, name_len) && 1786 if (!strncmp(name, opt, name_len) &&
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 95c0227f47fc..6739b2af3bc0 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -893,7 +893,7 @@ static void ffb_init_fix(struct fb_info *info)
893 info->fix.accel = FB_ACCEL_SUN_CREATOR; 893 info->fix.accel = FB_ACCEL_SUN_CREATOR;
894} 894}
895 895
896static int __devinit ffb_probe(struct of_device *op, 896static int __devinit ffb_probe(struct platform_device *op,
897 const struct of_device_id *match) 897 const struct of_device_id *match)
898{ 898{
899 struct device_node *dp = op->dev.of_node; 899 struct device_node *dp = op->dev.of_node;
@@ -1023,7 +1023,7 @@ out_err:
1023 return err; 1023 return err;
1024} 1024}
1025 1025
1026static int __devexit ffb_remove(struct of_device *op) 1026static int __devexit ffb_remove(struct platform_device *op)
1027{ 1027{
1028 struct fb_info *info = dev_get_drvdata(&op->dev); 1028 struct fb_info *info = dev_get_drvdata(&op->dev);
1029 struct ffb_par *par = info->par; 1029 struct ffb_par *par = info->par;
@@ -1067,12 +1067,12 @@ static int __init ffb_init(void)
1067 if (fb_get_options("ffb", NULL)) 1067 if (fb_get_options("ffb", NULL))
1068 return -ENODEV; 1068 return -ENODEV;
1069 1069
1070 return of_register_driver(&ffb_driver, &of_bus_type); 1070 return of_register_platform_driver(&ffb_driver);
1071} 1071}
1072 1072
1073static void __exit ffb_exit(void) 1073static void __exit ffb_exit(void)
1074{ 1074{
1075 of_unregister_driver(&ffb_driver); 1075 of_unregister_platform_driver(&ffb_driver);
1076} 1076}
1077 1077
1078module_init(ffb_init); 1078module_init(ffb_init);
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 27455ce298b7..8bbbf08fa3ce 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -34,7 +34,8 @@
34#include <linux/of_platform.h> 34#include <linux/of_platform.h>
35 35
36#include <sysdev/fsl_soc.h> 36#include <sysdev/fsl_soc.h>
37#include "fsl-diu-fb.h" 37#include <linux/fsl-diu-fb.h>
38#include "edid.h"
38 39
39/* 40/*
40 * These parameters give default parameters 41 * These parameters give default parameters
@@ -217,6 +218,7 @@ struct mfb_info {
217 int x_aoi_d; /* aoi display x offset to physical screen */ 218 int x_aoi_d; /* aoi display x offset to physical screen */
218 int y_aoi_d; /* aoi display y offset to physical screen */ 219 int y_aoi_d; /* aoi display y offset to physical screen */
219 struct fsl_diu_data *parent; 220 struct fsl_diu_data *parent;
221 u8 *edid_data;
220}; 222};
221 223
222 224
@@ -317,6 +319,17 @@ static void fsl_diu_free(void *virt, size_t size)
317 free_pages_exact(virt, size); 319 free_pages_exact(virt, size);
318} 320}
319 321
322/*
323 * Workaround for failed writing desc register of planes.
324 * Needed with MPC5121 DIU rev 2.0 silicon.
325 */
326void wr_reg_wa(u32 *reg, u32 val)
327{
328 do {
329 out_be32(reg, val);
330 } while (in_be32(reg) != val);
331}
332
320static int fsl_diu_enable_panel(struct fb_info *info) 333static int fsl_diu_enable_panel(struct fb_info *info)
321{ 334{
322 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; 335 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
@@ -330,7 +343,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
330 switch (mfbi->index) { 343 switch (mfbi->index) {
331 case 0: /* plane 0 */ 344 case 0: /* plane 0 */
332 if (hw->desc[0] != ad->paddr) 345 if (hw->desc[0] != ad->paddr)
333 out_be32(&hw->desc[0], ad->paddr); 346 wr_reg_wa(&hw->desc[0], ad->paddr);
334 break; 347 break;
335 case 1: /* plane 1 AOI 0 */ 348 case 1: /* plane 1 AOI 0 */
336 cmfbi = machine_data->fsl_diu_info[2]->par; 349 cmfbi = machine_data->fsl_diu_info[2]->par;
@@ -340,7 +353,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
340 cpu_to_le32(cmfbi->ad->paddr); 353 cpu_to_le32(cmfbi->ad->paddr);
341 else 354 else
342 ad->next_ad = 0; 355 ad->next_ad = 0;
343 out_be32(&hw->desc[1], ad->paddr); 356 wr_reg_wa(&hw->desc[1], ad->paddr);
344 } 357 }
345 break; 358 break;
346 case 3: /* plane 2 AOI 0 */ 359 case 3: /* plane 2 AOI 0 */
@@ -351,14 +364,14 @@ static int fsl_diu_enable_panel(struct fb_info *info)
351 cpu_to_le32(cmfbi->ad->paddr); 364 cpu_to_le32(cmfbi->ad->paddr);
352 else 365 else
353 ad->next_ad = 0; 366 ad->next_ad = 0;
354 out_be32(&hw->desc[2], ad->paddr); 367 wr_reg_wa(&hw->desc[2], ad->paddr);
355 } 368 }
356 break; 369 break;
357 case 2: /* plane 1 AOI 1 */ 370 case 2: /* plane 1 AOI 1 */
358 pmfbi = machine_data->fsl_diu_info[1]->par; 371 pmfbi = machine_data->fsl_diu_info[1]->par;
359 ad->next_ad = 0; 372 ad->next_ad = 0;
360 if (hw->desc[1] == machine_data->dummy_ad->paddr) 373 if (hw->desc[1] == machine_data->dummy_ad->paddr)
361 out_be32(&hw->desc[1], ad->paddr); 374 wr_reg_wa(&hw->desc[1], ad->paddr);
362 else /* AOI0 open */ 375 else /* AOI0 open */
363 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); 376 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
364 break; 377 break;
@@ -366,7 +379,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
366 pmfbi = machine_data->fsl_diu_info[3]->par; 379 pmfbi = machine_data->fsl_diu_info[3]->par;
367 ad->next_ad = 0; 380 ad->next_ad = 0;
368 if (hw->desc[2] == machine_data->dummy_ad->paddr) 381 if (hw->desc[2] == machine_data->dummy_ad->paddr)
369 out_be32(&hw->desc[2], ad->paddr); 382 wr_reg_wa(&hw->desc[2], ad->paddr);
370 else /* AOI0 was open */ 383 else /* AOI0 was open */
371 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); 384 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
372 break; 385 break;
@@ -390,27 +403,24 @@ static int fsl_diu_disable_panel(struct fb_info *info)
390 switch (mfbi->index) { 403 switch (mfbi->index) {
391 case 0: /* plane 0 */ 404 case 0: /* plane 0 */
392 if (hw->desc[0] != machine_data->dummy_ad->paddr) 405 if (hw->desc[0] != machine_data->dummy_ad->paddr)
393 out_be32(&hw->desc[0], 406 wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr);
394 machine_data->dummy_ad->paddr);
395 break; 407 break;
396 case 1: /* plane 1 AOI 0 */ 408 case 1: /* plane 1 AOI 0 */
397 cmfbi = machine_data->fsl_diu_info[2]->par; 409 cmfbi = machine_data->fsl_diu_info[2]->par;
398 if (cmfbi->count > 0) /* AOI1 is open */ 410 if (cmfbi->count > 0) /* AOI1 is open */
399 out_be32(&hw->desc[1], cmfbi->ad->paddr); 411 wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
400 /* move AOI1 to the first */ 412 /* move AOI1 to the first */
401 else /* AOI1 was closed */ 413 else /* AOI1 was closed */
402 out_be32(&hw->desc[1], 414 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
403 machine_data->dummy_ad->paddr);
404 /* close AOI 0 */ 415 /* close AOI 0 */
405 break; 416 break;
406 case 3: /* plane 2 AOI 0 */ 417 case 3: /* plane 2 AOI 0 */
407 cmfbi = machine_data->fsl_diu_info[4]->par; 418 cmfbi = machine_data->fsl_diu_info[4]->par;
408 if (cmfbi->count > 0) /* AOI1 is open */ 419 if (cmfbi->count > 0) /* AOI1 is open */
409 out_be32(&hw->desc[2], cmfbi->ad->paddr); 420 wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
410 /* move AOI1 to the first */ 421 /* move AOI1 to the first */
411 else /* AOI1 was closed */ 422 else /* AOI1 was closed */
412 out_be32(&hw->desc[2], 423 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
413 machine_data->dummy_ad->paddr);
414 /* close AOI 0 */ 424 /* close AOI 0 */
415 break; 425 break;
416 case 2: /* plane 1 AOI 1 */ 426 case 2: /* plane 1 AOI 1 */
@@ -421,7 +431,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
421 /* AOI0 is open, must be the first */ 431 /* AOI0 is open, must be the first */
422 pmfbi->ad->next_ad = 0; 432 pmfbi->ad->next_ad = 0;
423 } else /* AOI1 is the first in the chain */ 433 } else /* AOI1 is the first in the chain */
424 out_be32(&hw->desc[1], machine_data->dummy_ad->paddr); 434 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
425 /* close AOI 1 */ 435 /* close AOI 1 */
426 break; 436 break;
427 case 4: /* plane 2 AOI 1 */ 437 case 4: /* plane 2 AOI 1 */
@@ -432,7 +442,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
432 /* AOI0 is open, must be the first */ 442 /* AOI0 is open, must be the first */
433 pmfbi->ad->next_ad = 0; 443 pmfbi->ad->next_ad = 0;
434 } else /* AOI1 is the first in the chain */ 444 } else /* AOI1 is the first in the chain */
435 out_be32(&hw->desc[2], machine_data->dummy_ad->paddr); 445 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
436 /* close AOI 1 */ 446 /* close AOI 1 */
437 break; 447 break;
438 default: 448 default:
@@ -1100,6 +1110,10 @@ static int fsl_diu_open(struct fb_info *info, int user)
1100 struct mfb_info *mfbi = info->par; 1110 struct mfb_info *mfbi = info->par;
1101 int res = 0; 1111 int res = 0;
1102 1112
1113 /* free boot splash memory on first /dev/fb0 open */
1114 if (!mfbi->index && diu_ops.release_bootmem)
1115 diu_ops.release_bootmem();
1116
1103 spin_lock(&diu_lock); 1117 spin_lock(&diu_lock);
1104 mfbi->count++; 1118 mfbi->count++;
1105 if (mfbi->count == 1) { 1119 if (mfbi->count == 1) {
@@ -1173,18 +1187,30 @@ static int __devinit install_fb(struct fb_info *info)
1173 int rc; 1187 int rc;
1174 struct mfb_info *mfbi = info->par; 1188 struct mfb_info *mfbi = info->par;
1175 const char *aoi_mode, *init_aoi_mode = "320x240"; 1189 const char *aoi_mode, *init_aoi_mode = "320x240";
1190 struct fb_videomode *db = fsl_diu_mode_db;
1191 unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
1192 int has_default_mode = 1;
1176 1193
1177 if (init_fbinfo(info)) 1194 if (init_fbinfo(info))
1178 return -EINVAL; 1195 return -EINVAL;
1179 1196
1180 if (mfbi->index == 0) /* plane 0 */ 1197 if (mfbi->index == 0) { /* plane 0 */
1198 if (mfbi->edid_data) {
1199 /* Now build modedb from EDID */
1200 fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs);
1201 fb_videomode_to_modelist(info->monspecs.modedb,
1202 info->monspecs.modedb_len,
1203 &info->modelist);
1204 db = info->monspecs.modedb;
1205 dbsize = info->monspecs.modedb_len;
1206 }
1181 aoi_mode = fb_mode; 1207 aoi_mode = fb_mode;
1182 else 1208 } else {
1183 aoi_mode = init_aoi_mode; 1209 aoi_mode = init_aoi_mode;
1210 }
1184 pr_debug("mode used = %s\n", aoi_mode); 1211 pr_debug("mode used = %s\n", aoi_mode);
1185 rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, 1212 rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize,
1186 ARRAY_SIZE(fsl_diu_mode_db), &fsl_diu_default_mode, default_bpp); 1213 &fsl_diu_default_mode, default_bpp);
1187
1188 switch (rc) { 1214 switch (rc) {
1189 case 1: 1215 case 1:
1190 pr_debug("using mode specified in @mode\n"); 1216 pr_debug("using mode specified in @mode\n");
@@ -1202,10 +1228,50 @@ static int __devinit install_fb(struct fb_info *info)
1202 default: 1228 default:
1203 pr_debug("rc = %d\n", rc); 1229 pr_debug("rc = %d\n", rc);
1204 pr_debug("failed to find mode\n"); 1230 pr_debug("failed to find mode\n");
1205 return -EINVAL; 1231 /*
1232 * For plane 0 we continue and look into
1233 * driver's internal modedb.
1234 */
1235 if (mfbi->index == 0 && mfbi->edid_data)
1236 has_default_mode = 0;
1237 else
1238 return -EINVAL;
1206 break; 1239 break;
1207 } 1240 }
1208 1241
1242 if (!has_default_mode) {
1243 rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
1244 ARRAY_SIZE(fsl_diu_mode_db),
1245 &fsl_diu_default_mode,
1246 default_bpp);
1247 if (rc > 0 && rc < 5)
1248 has_default_mode = 1;
1249 }
1250
1251 /* Still not found, use preferred mode from database if any */
1252 if (!has_default_mode && info->monspecs.modedb) {
1253 struct fb_monspecs *specs = &info->monspecs;
1254 struct fb_videomode *modedb = &specs->modedb[0];
1255
1256 /*
1257 * Get preferred timing. If not found,
1258 * first mode in database will be used.
1259 */
1260 if (specs->misc & FB_MISC_1ST_DETAIL) {
1261 int i;
1262
1263 for (i = 0; i < specs->modedb_len; i++) {
1264 if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
1265 modedb = &specs->modedb[i];
1266 break;
1267 }
1268 }
1269 }
1270
1271 info->var.bits_per_pixel = default_bpp;
1272 fb_videomode_to_var(&info->var, modedb);
1273 }
1274
1209 pr_debug("xres_virtual %d\n", info->var.xres_virtual); 1275 pr_debug("xres_virtual %d\n", info->var.xres_virtual);
1210 pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel); 1276 pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel);
1211 1277
@@ -1244,6 +1310,9 @@ static void uninstall_fb(struct fb_info *info)
1244 if (!mfbi->registered) 1310 if (!mfbi->registered)
1245 return; 1311 return;
1246 1312
1313 if (mfbi->index == 0)
1314 kfree(mfbi->edid_data);
1315
1247 unregister_framebuffer(info); 1316 unregister_framebuffer(info);
1248 unmap_video_memory(info); 1317 unmap_video_memory(info);
1249 if (&info->cmap) 1318 if (&info->cmap)
@@ -1324,7 +1393,7 @@ static void free_irq_local(int irq)
1324 * Power management hooks. Note that we won't be called from IRQ context, 1393 * Power management hooks. Note that we won't be called from IRQ context,
1325 * unlike the blank functions above, so we may sleep. 1394 * unlike the blank functions above, so we may sleep.
1326 */ 1395 */
1327static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) 1396static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
1328{ 1397{
1329 struct fsl_diu_data *machine_data; 1398 struct fsl_diu_data *machine_data;
1330 1399
@@ -1334,7 +1403,7 @@ static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state)
1334 return 0; 1403 return 0;
1335} 1404}
1336 1405
1337static int fsl_diu_resume(struct of_device *ofdev) 1406static int fsl_diu_resume(struct platform_device *ofdev)
1338{ 1407{
1339 struct fsl_diu_data *machine_data; 1408 struct fsl_diu_data *machine_data;
1340 1409
@@ -1418,7 +1487,7 @@ static ssize_t show_monitor(struct device *device,
1418 return diu_ops.show_monitor_port(machine_data->monitor_port, buf); 1487 return diu_ops.show_monitor_port(machine_data->monitor_port, buf);
1419} 1488}
1420 1489
1421static int __devinit fsl_diu_probe(struct of_device *ofdev, 1490static int __devinit fsl_diu_probe(struct platform_device *ofdev,
1422 const struct of_device_id *match) 1491 const struct of_device_id *match)
1423{ 1492{
1424 struct device_node *np = ofdev->dev.of_node; 1493 struct device_node *np = ofdev->dev.of_node;
@@ -1427,6 +1496,7 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
1427 int ret, i, error = 0; 1496 int ret, i, error = 0;
1428 struct resource res; 1497 struct resource res;
1429 struct fsl_diu_data *machine_data; 1498 struct fsl_diu_data *machine_data;
1499 int diu_mode;
1430 1500
1431 machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL); 1501 machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL);
1432 if (!machine_data) 1502 if (!machine_data)
@@ -1443,6 +1513,17 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
1443 mfbi = machine_data->fsl_diu_info[i]->par; 1513 mfbi = machine_data->fsl_diu_info[i]->par;
1444 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); 1514 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
1445 mfbi->parent = machine_data; 1515 mfbi->parent = machine_data;
1516
1517 if (mfbi->index == 0) {
1518 const u8 *prop;
1519 int len;
1520
1521 /* Get EDID */
1522 prop = of_get_property(np, "edid", &len);
1523 if (prop && len == EDID_LENGTH)
1524 mfbi->edid_data = kmemdup(prop, EDID_LENGTH,
1525 GFP_KERNEL);
1526 }
1446 } 1527 }
1447 1528
1448 ret = of_address_to_resource(np, 0, &res); 1529 ret = of_address_to_resource(np, 0, &res);
@@ -1463,7 +1544,9 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
1463 goto error2; 1544 goto error2;
1464 } 1545 }
1465 1546
1466 out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU anyway*/ 1547 diu_mode = in_be32(&dr.diu_reg->diu_mode);
1548 if (diu_mode != MFB_MODE1)
1549 out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU */
1467 1550
1468 /* Get the IRQ of the DIU */ 1551 /* Get the IRQ of the DIU */
1469 machine_data->irq = irq_of_parse_and_map(np, 0); 1552 machine_data->irq = irq_of_parse_and_map(np, 0);
@@ -1511,7 +1594,13 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
1511 machine_data->dummy_ad->offset_xyd = 0; 1594 machine_data->dummy_ad->offset_xyd = 0;
1512 machine_data->dummy_ad->next_ad = 0; 1595 machine_data->dummy_ad->next_ad = 0;
1513 1596
1514 out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr); 1597 /*
1598 * Let DIU display splash screen if it was pre-initialized
1599 * by the bootloader, set dummy area descriptor otherwise.
1600 */
1601 if (diu_mode != MFB_MODE1)
1602 out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr);
1603
1515 out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr); 1604 out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr);
1516 out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr); 1605 out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr);
1517 1606
@@ -1578,7 +1667,7 @@ error2:
1578} 1667}
1579 1668
1580 1669
1581static int fsl_diu_remove(struct of_device *ofdev) 1670static int fsl_diu_remove(struct platform_device *ofdev)
1582{ 1671{
1583 struct fsl_diu_data *machine_data; 1672 struct fsl_diu_data *machine_data;
1584 int i; 1673 int i;
diff --git a/drivers/video/fsl-diu-fb.h b/drivers/video/fsl-diu-fb.h
deleted file mode 100644
index fc295d7ea463..000000000000
--- a/drivers/video/fsl-diu-fb.h
+++ /dev/null
@@ -1,223 +0,0 @@
1/*
2 * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
3 *
4 * Freescale DIU Frame Buffer device driver
5 *
6 * Authors: Hongjun Chen <hong-jun.chen@freescale.com>
7 * Paul Widmer <paul.widmer@freescale.com>
8 * Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
9 * York Sun <yorksun@freescale.com>
10 *
11 * Based on imxfb.c Copyright (C) 2004 S.Hauer, Pengutronix
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 */
19
20#ifndef __FSL_DIU_FB_H__
21#define __FSL_DIU_FB_H__
22
23/* Arbitrary threshold to determine the allocation method
24 * See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory()
25 */
26#define MEM_ALLOC_THRESHOLD (1024*768*4+32)
27/* Minimum value that the pixel clock can be set to in pico seconds
28 * This is determined by platform clock/3 where the minimum platform
29 * clock is 533MHz. This gives 5629 pico seconds.
30 */
31#define MIN_PIX_CLK 5629
32#define MAX_PIX_CLK 96096
33
34#include <linux/types.h>
35
36struct mfb_alpha {
37 int enable;
38 int alpha;
39};
40
41struct mfb_chroma_key {
42 int enable;
43 __u8 red_max;
44 __u8 green_max;
45 __u8 blue_max;
46 __u8 red_min;
47 __u8 green_min;
48 __u8 blue_min;
49};
50
51struct aoi_display_offset {
52 int x_aoi_d;
53 int y_aoi_d;
54};
55
56#define MFB_SET_CHROMA_KEY _IOW('M', 1, struct mfb_chroma_key)
57#define MFB_WAIT_FOR_VSYNC _IOW('F', 0x20, u_int32_t)
58#define MFB_SET_BRIGHTNESS _IOW('M', 3, __u8)
59
60#define MFB_SET_ALPHA 0x80014d00
61#define MFB_GET_ALPHA 0x40014d00
62#define MFB_SET_AOID 0x80084d04
63#define MFB_GET_AOID 0x40084d04
64#define MFB_SET_PIXFMT 0x80014d08
65#define MFB_GET_PIXFMT 0x40014d08
66
67#define FBIOGET_GWINFO 0x46E0
68#define FBIOPUT_GWINFO 0x46E1
69
70#ifdef __KERNEL__
71#include <linux/spinlock.h>
72
73/*
74 * These are the fields of area descriptor(in DDR memory) for every plane
75 */
76struct diu_ad {
77 /* Word 0(32-bit) in DDR memory */
78/* __u16 comp; */
79/* __u16 pixel_s:2; */
80/* __u16 pallete:1; */
81/* __u16 red_c:2; */
82/* __u16 green_c:2; */
83/* __u16 blue_c:2; */
84/* __u16 alpha_c:3; */
85/* __u16 byte_f:1; */
86/* __u16 res0:3; */
87
88 __be32 pix_fmt; /* hard coding pixel format */
89
90 /* Word 1(32-bit) in DDR memory */
91 __le32 addr;
92
93 /* Word 2(32-bit) in DDR memory */
94/* __u32 delta_xs:11; */
95/* __u32 res1:1; */
96/* __u32 delta_ys:11; */
97/* __u32 res2:1; */
98/* __u32 g_alpha:8; */
99 __le32 src_size_g_alpha;
100
101 /* Word 3(32-bit) in DDR memory */
102/* __u32 delta_xi:11; */
103/* __u32 res3:5; */
104/* __u32 delta_yi:11; */
105/* __u32 res4:3; */
106/* __u32 flip:2; */
107 __le32 aoi_size;
108
109 /* Word 4(32-bit) in DDR memory */
110 /*__u32 offset_xi:11;
111 __u32 res5:5;
112 __u32 offset_yi:11;
113 __u32 res6:5;
114 */
115 __le32 offset_xyi;
116
117 /* Word 5(32-bit) in DDR memory */
118 /*__u32 offset_xd:11;
119 __u32 res7:5;
120 __u32 offset_yd:11;
121 __u32 res8:5; */
122 __le32 offset_xyd;
123
124
125 /* Word 6(32-bit) in DDR memory */
126 __u8 ckmax_r;
127 __u8 ckmax_g;
128 __u8 ckmax_b;
129 __u8 res9;
130
131 /* Word 7(32-bit) in DDR memory */
132 __u8 ckmin_r;
133 __u8 ckmin_g;
134 __u8 ckmin_b;
135 __u8 res10;
136/* __u32 res10:8; */
137
138 /* Word 8(32-bit) in DDR memory */
139 __le32 next_ad;
140
141 /* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
142 __u32 paddr;
143} __attribute__ ((packed));
144
145/* DIU register map */
146struct diu {
147 __be32 desc[3];
148 __be32 gamma;
149 __be32 pallete;
150 __be32 cursor;
151 __be32 curs_pos;
152 __be32 diu_mode;
153 __be32 bgnd;
154 __be32 bgnd_wb;
155 __be32 disp_size;
156 __be32 wb_size;
157 __be32 wb_mem_addr;
158 __be32 hsyn_para;
159 __be32 vsyn_para;
160 __be32 syn_pol;
161 __be32 thresholds;
162 __be32 int_status;
163 __be32 int_mask;
164 __be32 colorbar[8];
165 __be32 filling;
166 __be32 plut;
167} __attribute__ ((packed));
168
169struct diu_hw {
170 struct diu *diu_reg;
171 spinlock_t reg_lock;
172
173 __u32 mode; /* DIU operation mode */
174};
175
176struct diu_addr {
177 __u8 __iomem *vaddr; /* Virtual address */
178 dma_addr_t paddr; /* Physical address */
179 __u32 offset;
180};
181
182struct diu_pool {
183 struct diu_addr ad;
184 struct diu_addr gamma;
185 struct diu_addr pallete;
186 struct diu_addr cursor;
187};
188
189#define FSL_DIU_BASE_OFFSET 0x2C000 /* Offset of DIU */
190#define INT_LCDC 64 /* DIU interrupt number */
191
192#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */
193 /* 1 for plane 0, 2 for plane 1&2 each */
194
195/* Minimum X and Y resolutions */
196#define MIN_XRES 64
197#define MIN_YRES 64
198
199/* HW cursor parameters */
200#define MAX_CURS 32
201
202/* Modes of operation of DIU */
203#define MFB_MODE0 0 /* DIU off */
204#define MFB_MODE1 1 /* All three planes output to display */
205#define MFB_MODE2 2 /* Plane 1 to display, planes 2+3 written back*/
206#define MFB_MODE3 3 /* All three planes written back to memory */
207#define MFB_MODE4 4 /* Color bar generation */
208
209/* INT_STATUS/INT_MASK field descriptions */
210#define INT_VSYNC 0x01 /* Vsync interrupt */
211#define INT_VSYNC_WB 0x02 /* Vsync interrupt for write back operation */
212#define INT_UNDRUN 0x04 /* Under run exception interrupt */
213#define INT_PARERR 0x08 /* Display parameters error interrupt */
214#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */
215
216/* Panels'operation modes */
217#define MFB_TYPE_OUTPUT 0 /* Panel output to display */
218#define MFB_TYPE_OFF 1 /* Panel off */
219#define MFB_TYPE_WB 2 /* Panel written back to memory */
220#define MFB_TYPE_TEST 3 /* Panel generate color bar */
221
222#endif /* __KERNEL__ */
223#endif /* __FSL_DIU_FB_H__ */
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 7d8c55d7fd28..933899dca33a 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -91,10 +91,10 @@ static uint32_t pseudo_palette[16];
91static uint32_t gbe_cmap[256]; 91static uint32_t gbe_cmap[256];
92static int gbe_turned_on; /* 0 turned off, 1 turned on */ 92static int gbe_turned_on; /* 0 turned off, 1 turned on */
93 93
94static char *mode_option __initdata = NULL; 94static char *mode_option __devinitdata = NULL;
95 95
96/* default CRT mode */ 96/* default CRT mode */
97static struct fb_var_screeninfo default_var_CRT __initdata = { 97static struct fb_var_screeninfo default_var_CRT __devinitdata = {
98 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 98 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
99 .xres = 640, 99 .xres = 640,
100 .yres = 480, 100 .yres = 480,
@@ -125,7 +125,7 @@ static struct fb_var_screeninfo default_var_CRT __initdata = {
125}; 125};
126 126
127/* default LCD mode */ 127/* default LCD mode */
128static struct fb_var_screeninfo default_var_LCD __initdata = { 128static struct fb_var_screeninfo default_var_LCD __devinitdata = {
129 /* 1600x1024, 8 bpp */ 129 /* 1600x1024, 8 bpp */
130 .xres = 1600, 130 .xres = 1600,
131 .yres = 1024, 131 .yres = 1024,
@@ -157,7 +157,7 @@ static struct fb_var_screeninfo default_var_LCD __initdata = {
157 157
158/* default modedb mode */ 158/* default modedb mode */
159/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */ 159/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
160static struct fb_videomode default_mode_CRT __initdata = { 160static struct fb_videomode default_mode_CRT __devinitdata = {
161 .refresh = 60, 161 .refresh = 60,
162 .xres = 640, 162 .xres = 640,
163 .yres = 480, 163 .yres = 480,
@@ -172,7 +172,7 @@ static struct fb_videomode default_mode_CRT __initdata = {
172 .vmode = FB_VMODE_NONINTERLACED, 172 .vmode = FB_VMODE_NONINTERLACED,
173}; 173};
174/* 1600x1024 SGI flatpanel 1600sw */ 174/* 1600x1024 SGI flatpanel 1600sw */
175static struct fb_videomode default_mode_LCD __initdata = { 175static struct fb_videomode default_mode_LCD __devinitdata = {
176 /* 1600x1024, 8 bpp */ 176 /* 1600x1024, 8 bpp */
177 .xres = 1600, 177 .xres = 1600,
178 .yres = 1024, 178 .yres = 1024,
@@ -186,8 +186,8 @@ static struct fb_videomode default_mode_LCD __initdata = {
186 .vmode = FB_VMODE_NONINTERLACED, 186 .vmode = FB_VMODE_NONINTERLACED,
187}; 187};
188 188
189static struct fb_videomode *default_mode __initdata = &default_mode_CRT; 189static struct fb_videomode *default_mode __devinitdata = &default_mode_CRT;
190static struct fb_var_screeninfo *default_var __initdata = &default_var_CRT; 190static struct fb_var_screeninfo *default_var __devinitdata = &default_var_CRT;
191 191
192static int flat_panel_enabled = 0; 192static int flat_panel_enabled = 0;
193 193
@@ -1098,7 +1098,7 @@ static void gbefb_create_sysfs(struct device *dev)
1098 * Initialization 1098 * Initialization
1099 */ 1099 */
1100 1100
1101static int __init gbefb_setup(char *options) 1101static int __devinit gbefb_setup(char *options)
1102{ 1102{
1103 char *this_opt; 1103 char *this_opt;
1104 1104
@@ -1143,8 +1143,10 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
1143 return -ENOMEM; 1143 return -ENOMEM;
1144 1144
1145#ifndef MODULE 1145#ifndef MODULE
1146 if (fb_get_options("gbefb", &options)) 1146 if (fb_get_options("gbefb", &options)) {
1147 return -ENODEV; 1147 ret = -ENODEV;
1148 goto out_release_framebuffer;
1149 }
1148 gbefb_setup(options); 1150 gbefb_setup(options);
1149#endif 1151#endif
1150 1152
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index 328ae6c673ec..f37de60ecc59 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -17,7 +17,6 @@
17#include <linux/agp_backend.h> 17#include <linux/agp_backend.h>
18#include <linux/fb.h> 18#include <linux/fb.h>
19#include <linux/i2c.h> 19#include <linux/i2c.h>
20#include <linux/i2c-id.h>
21#include <linux/i2c-algo-bit.h> 20#include <linux/i2c-algo-bit.h>
22#include <video/vga.h> 21#include <video/vga.h>
23 22
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 15d200109446..d885c770eb84 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -368,7 +368,7 @@ static int __init iga_init(struct fb_info *info, struct iga_par *par)
368 return 1; 368 return 1;
369} 369}
370 370
371int __init igafb_init(void) 371static int __init igafb_init(void)
372{ 372{
373 struct fb_info *info; 373 struct fb_info *info;
374 struct pci_dev *pdev; 374 struct pci_dev *pdev;
@@ -531,6 +531,7 @@ int __init igafb_init(void)
531 iounmap(info->screen_base); 531 iounmap(info->screen_base);
532 kfree(par->mmap_map); 532 kfree(par->mmap_map);
533 kfree(info); 533 kfree(info);
534 return -ENODEV;
534 } 535 }
535 536
536#ifdef CONFIG_SPARC 537#ifdef CONFIG_SPARC
@@ -556,7 +557,7 @@ int __init igafb_init(void)
556 return 0; 557 return 0;
557} 558}
558 559
559int __init igafb_setup(char *options) 560static int __init igafb_setup(char *options)
560{ 561{
561 char *this_opt; 562 char *this_opt;
562 563
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index b4b6deceed15..5c363d026f64 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -40,6 +40,12 @@
40 */ 40 */
41#define DEBUG_VAR 1 41#define DEBUG_VAR 1
42 42
43#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
44 (defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) && \
45 defined(CONFIG_FB_IMX_MODULE))
46#define PWMR_BACKLIGHT_AVAILABLE
47#endif
48
43#define DRIVER_NAME "imx-fb" 49#define DRIVER_NAME "imx-fb"
44 50
45#define LCDC_SSA 0x00 51#define LCDC_SSA 0x00
@@ -175,6 +181,9 @@ struct imxfb_info {
175 181
176 struct imx_fb_videomode *mode; 182 struct imx_fb_videomode *mode;
177 int num_modes; 183 int num_modes;
184#ifdef PWMR_BACKLIGHT_AVAILABLE
185 struct backlight_device *bl;
186#endif
178 187
179 void (*lcd_power)(int); 188 void (*lcd_power)(int);
180 void (*backlight_power)(int); 189 void (*backlight_power)(int);
@@ -449,6 +458,73 @@ static int imxfb_set_par(struct fb_info *info)
449 return 0; 458 return 0;
450} 459}
451 460
461#ifdef PWMR_BACKLIGHT_AVAILABLE
462static int imxfb_bl_get_brightness(struct backlight_device *bl)
463{
464 struct imxfb_info *fbi = bl_get_data(bl);
465
466 return readl(fbi->regs + LCDC_PWMR) & 0xFF;
467}
468
469static int imxfb_bl_update_status(struct backlight_device *bl)
470{
471 struct imxfb_info *fbi = bl_get_data(bl);
472 int brightness = bl->props.brightness;
473
474 if (bl->props.power != FB_BLANK_UNBLANK)
475 brightness = 0;
476 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
477 brightness = 0;
478
479 fbi->pwmr = (fbi->pwmr & ~0xFF) | brightness;
480
481 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
482 clk_enable(fbi->clk);
483 writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
484 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
485 clk_disable(fbi->clk);
486
487 return 0;
488}
489
490static const struct backlight_ops imxfb_lcdc_bl_ops = {
491 .update_status = imxfb_bl_update_status,
492 .get_brightness = imxfb_bl_get_brightness,
493};
494
495static void imxfb_init_backlight(struct imxfb_info *fbi)
496{
497 struct backlight_properties props;
498 struct backlight_device *bl;
499
500 if (fbi->bl)
501 return;
502
503 memset(&props, 0, sizeof(struct backlight_properties));
504 props.max_brightness = 0xff;
505 writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
506
507 bl = backlight_device_register("imxfb-bl", &fbi->pdev->dev, fbi,
508 &imxfb_lcdc_bl_ops, &props);
509 if (IS_ERR(bl)) {
510 dev_err(&fbi->pdev->dev, "error %ld on backlight register\n",
511 PTR_ERR(bl));
512 return;
513 }
514
515 fbi->bl = bl;
516 bl->props.power = FB_BLANK_UNBLANK;
517 bl->props.fb_blank = FB_BLANK_UNBLANK;
518 bl->props.brightness = imxfb_bl_get_brightness(bl);
519}
520
521static void imxfb_exit_backlight(struct imxfb_info *fbi)
522{
523 if (fbi->bl)
524 backlight_device_unregister(fbi->bl);
525}
526#endif
527
452static void imxfb_enable_controller(struct imxfb_info *fbi) 528static void imxfb_enable_controller(struct imxfb_info *fbi)
453{ 529{
454 pr_debug("Enabling LCD controller\n"); 530 pr_debug("Enabling LCD controller\n");
@@ -579,7 +655,9 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
579 fbi->regs + LCDC_SIZE); 655 fbi->regs + LCDC_SIZE);
580 656
581 writel(fbi->pcr, fbi->regs + LCDC_PCR); 657 writel(fbi->pcr, fbi->regs + LCDC_PCR);
658#ifndef PWMR_BACKLIGHT_AVAILABLE
582 writel(fbi->pwmr, fbi->regs + LCDC_PWMR); 659 writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
660#endif
583 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); 661 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
584 writel(fbi->dmacr, fbi->regs + LCDC_DMACR); 662 writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
585 663
@@ -779,6 +857,10 @@ static int __init imxfb_probe(struct platform_device *pdev)
779 } 857 }
780 858
781 imxfb_enable_controller(fbi); 859 imxfb_enable_controller(fbi);
860 fbi->pdev = pdev;
861#ifdef PWMR_BACKLIGHT_AVAILABLE
862 imxfb_init_backlight(fbi);
863#endif
782 864
783 return 0; 865 return 0;
784 866
@@ -816,6 +898,9 @@ static int __devexit imxfb_remove(struct platform_device *pdev)
816 898
817 imxfb_disable_controller(fbi); 899 imxfb_disable_controller(fbi);
818 900
901#ifdef PWMR_BACKLIGHT_AVAILABLE
902 imxfb_exit_backlight(fbi);
903#endif
819 unregister_framebuffer(info); 904 unregister_framebuffer(info);
820 905
821 pdata = pdev->dev.platform_data; 906 pdata = pdev->dev.platform_data;
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index 487f2be47460..3300bd31d9d7 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -32,7 +32,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
32#include <linux/fb.h> 32#include <linux/fb.h>
33 33
34#include <linux/i2c.h> 34#include <linux/i2c.h>
35#include <linux/i2c-id.h>
36#include <linux/i2c-algo-bit.h> 35#include <linux/i2c-algo-bit.h>
37 36
38#include <asm/io.h> 37#include <asm/io.h>
diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c
new file mode 100644
index 000000000000..670ecaa0385a
--- /dev/null
+++ b/drivers/video/jz4740_fb.c
@@ -0,0 +1,847 @@
1/*
2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 SoC LCD framebuffer driver
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/mutex.h>
19#include <linux/platform_device.h>
20
21#include <linux/clk.h>
22#include <linux/delay.h>
23
24#include <linux/console.h>
25#include <linux/fb.h>
26
27#include <linux/dma-mapping.h>
28
29#include <asm/mach-jz4740/jz4740_fb.h>
30#include <asm/mach-jz4740/gpio.h>
31
32#define JZ_REG_LCD_CFG 0x00
33#define JZ_REG_LCD_VSYNC 0x04
34#define JZ_REG_LCD_HSYNC 0x08
35#define JZ_REG_LCD_VAT 0x0C
36#define JZ_REG_LCD_DAH 0x10
37#define JZ_REG_LCD_DAV 0x14
38#define JZ_REG_LCD_PS 0x18
39#define JZ_REG_LCD_CLS 0x1C
40#define JZ_REG_LCD_SPL 0x20
41#define JZ_REG_LCD_REV 0x24
42#define JZ_REG_LCD_CTRL 0x30
43#define JZ_REG_LCD_STATE 0x34
44#define JZ_REG_LCD_IID 0x38
45#define JZ_REG_LCD_DA0 0x40
46#define JZ_REG_LCD_SA0 0x44
47#define JZ_REG_LCD_FID0 0x48
48#define JZ_REG_LCD_CMD0 0x4C
49#define JZ_REG_LCD_DA1 0x50
50#define JZ_REG_LCD_SA1 0x54
51#define JZ_REG_LCD_FID1 0x58
52#define JZ_REG_LCD_CMD1 0x5C
53
54#define JZ_LCD_CFG_SLCD BIT(31)
55#define JZ_LCD_CFG_PS_DISABLE BIT(23)
56#define JZ_LCD_CFG_CLS_DISABLE BIT(22)
57#define JZ_LCD_CFG_SPL_DISABLE BIT(21)
58#define JZ_LCD_CFG_REV_DISABLE BIT(20)
59#define JZ_LCD_CFG_HSYNCM BIT(19)
60#define JZ_LCD_CFG_PCLKM BIT(18)
61#define JZ_LCD_CFG_INV BIT(17)
62#define JZ_LCD_CFG_SYNC_DIR BIT(16)
63#define JZ_LCD_CFG_PS_POLARITY BIT(15)
64#define JZ_LCD_CFG_CLS_POLARITY BIT(14)
65#define JZ_LCD_CFG_SPL_POLARITY BIT(13)
66#define JZ_LCD_CFG_REV_POLARITY BIT(12)
67#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11)
68#define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10)
69#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9)
70#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8)
71#define JZ_LCD_CFG_18_BIT BIT(7)
72#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4))
73#define JZ_LCD_CFG_MODE_MASK 0xf
74
75#define JZ_LCD_CTRL_BURST_4 (0x0 << 28)
76#define JZ_LCD_CTRL_BURST_8 (0x1 << 28)
77#define JZ_LCD_CTRL_BURST_16 (0x2 << 28)
78#define JZ_LCD_CTRL_RGB555 BIT(27)
79#define JZ_LCD_CTRL_OFUP BIT(26)
80#define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24)
81#define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24)
82#define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24)
83#define JZ_LCD_CTRL_PDD_MASK (0xff << 16)
84#define JZ_LCD_CTRL_EOF_IRQ BIT(13)
85#define JZ_LCD_CTRL_SOF_IRQ BIT(12)
86#define JZ_LCD_CTRL_OFU_IRQ BIT(11)
87#define JZ_LCD_CTRL_IFU0_IRQ BIT(10)
88#define JZ_LCD_CTRL_IFU1_IRQ BIT(9)
89#define JZ_LCD_CTRL_DD_IRQ BIT(8)
90#define JZ_LCD_CTRL_QDD_IRQ BIT(7)
91#define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6)
92#define JZ_LCD_CTRL_LSB_FISRT BIT(5)
93#define JZ_LCD_CTRL_DISABLE BIT(4)
94#define JZ_LCD_CTRL_ENABLE BIT(3)
95#define JZ_LCD_CTRL_BPP_1 0x0
96#define JZ_LCD_CTRL_BPP_2 0x1
97#define JZ_LCD_CTRL_BPP_4 0x2
98#define JZ_LCD_CTRL_BPP_8 0x3
99#define JZ_LCD_CTRL_BPP_15_16 0x4
100#define JZ_LCD_CTRL_BPP_18_24 0x5
101
102#define JZ_LCD_CMD_SOF_IRQ BIT(15)
103#define JZ_LCD_CMD_EOF_IRQ BIT(16)
104#define JZ_LCD_CMD_ENABLE_PAL BIT(12)
105
106#define JZ_LCD_SYNC_MASK 0x3ff
107
108#define JZ_LCD_STATE_DISABLED BIT(0)
109
110struct jzfb_framedesc {
111 uint32_t next;
112 uint32_t addr;
113 uint32_t id;
114 uint32_t cmd;
115} __packed;
116
117struct jzfb {
118 struct fb_info *fb;
119 struct platform_device *pdev;
120 void __iomem *base;
121 struct resource *mem;
122 struct jz4740_fb_platform_data *pdata;
123
124 size_t vidmem_size;
125 void *vidmem;
126 dma_addr_t vidmem_phys;
127 struct jzfb_framedesc *framedesc;
128 dma_addr_t framedesc_phys;
129
130 struct clk *ldclk;
131 struct clk *lpclk;
132
133 unsigned is_enabled:1;
134 struct mutex lock;
135
136 uint32_t pseudo_palette[16];
137};
138
139static const struct fb_fix_screeninfo jzfb_fix __devinitdata = {
140 .id = "JZ4740 FB",
141 .type = FB_TYPE_PACKED_PIXELS,
142 .visual = FB_VISUAL_TRUECOLOR,
143 .xpanstep = 0,
144 .ypanstep = 0,
145 .ywrapstep = 0,
146 .accel = FB_ACCEL_NONE,
147};
148
149static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = {
150 JZ_GPIO_BULK_PIN(LCD_PCLK),
151 JZ_GPIO_BULK_PIN(LCD_HSYNC),
152 JZ_GPIO_BULK_PIN(LCD_VSYNC),
153 JZ_GPIO_BULK_PIN(LCD_DE),
154 JZ_GPIO_BULK_PIN(LCD_PS),
155 JZ_GPIO_BULK_PIN(LCD_REV),
156 JZ_GPIO_BULK_PIN(LCD_CLS),
157 JZ_GPIO_BULK_PIN(LCD_SPL),
158};
159
160static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = {
161 JZ_GPIO_BULK_PIN(LCD_DATA0),
162 JZ_GPIO_BULK_PIN(LCD_DATA1),
163 JZ_GPIO_BULK_PIN(LCD_DATA2),
164 JZ_GPIO_BULK_PIN(LCD_DATA3),
165 JZ_GPIO_BULK_PIN(LCD_DATA4),
166 JZ_GPIO_BULK_PIN(LCD_DATA5),
167 JZ_GPIO_BULK_PIN(LCD_DATA6),
168 JZ_GPIO_BULK_PIN(LCD_DATA7),
169 JZ_GPIO_BULK_PIN(LCD_DATA8),
170 JZ_GPIO_BULK_PIN(LCD_DATA9),
171 JZ_GPIO_BULK_PIN(LCD_DATA10),
172 JZ_GPIO_BULK_PIN(LCD_DATA11),
173 JZ_GPIO_BULK_PIN(LCD_DATA12),
174 JZ_GPIO_BULK_PIN(LCD_DATA13),
175 JZ_GPIO_BULK_PIN(LCD_DATA14),
176 JZ_GPIO_BULK_PIN(LCD_DATA15),
177 JZ_GPIO_BULK_PIN(LCD_DATA16),
178 JZ_GPIO_BULK_PIN(LCD_DATA17),
179};
180
181static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
182{
183 unsigned int num;
184
185 switch (jzfb->pdata->lcd_type) {
186 case JZ_LCD_TYPE_GENERIC_16_BIT:
187 num = 4;
188 break;
189 case JZ_LCD_TYPE_GENERIC_18_BIT:
190 num = 4;
191 break;
192 case JZ_LCD_TYPE_8BIT_SERIAL:
193 num = 3;
194 break;
195 case JZ_LCD_TYPE_SPECIAL_TFT_1:
196 case JZ_LCD_TYPE_SPECIAL_TFT_2:
197 case JZ_LCD_TYPE_SPECIAL_TFT_3:
198 num = 8;
199 break;
200 default:
201 num = 0;
202 break;
203 }
204 return num;
205}
206
207static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
208{
209 unsigned int num;
210
211 switch (jzfb->pdata->lcd_type) {
212 case JZ_LCD_TYPE_GENERIC_16_BIT:
213 num = 16;
214 break;
215 case JZ_LCD_TYPE_GENERIC_18_BIT:
216 num = 18;
217 break;
218 case JZ_LCD_TYPE_8BIT_SERIAL:
219 num = 8;
220 break;
221 case JZ_LCD_TYPE_SPECIAL_TFT_1:
222 case JZ_LCD_TYPE_SPECIAL_TFT_2:
223 case JZ_LCD_TYPE_SPECIAL_TFT_3:
224 if (jzfb->pdata->bpp == 18)
225 num = 18;
226 else
227 num = 16;
228 break;
229 default:
230 num = 0;
231 break;
232 }
233 return num;
234}
235
236/* Based on CNVT_TOHW macro from skeletonfb.c */
237static inline uint32_t jzfb_convert_color_to_hw(unsigned val,
238 struct fb_bitfield *bf)
239{
240 return (((val << bf->length) + 0x7FFF - val) >> 16) << bf->offset;
241}
242
243static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
244 unsigned blue, unsigned transp, struct fb_info *fb)
245{
246 uint32_t color;
247
248 if (regno >= 16)
249 return -EINVAL;
250
251 color = jzfb_convert_color_to_hw(red, &fb->var.red);
252 color |= jzfb_convert_color_to_hw(green, &fb->var.green);
253 color |= jzfb_convert_color_to_hw(blue, &fb->var.blue);
254 color |= jzfb_convert_color_to_hw(transp, &fb->var.transp);
255
256 ((uint32_t *)(fb->pseudo_palette))[regno] = color;
257
258 return 0;
259}
260
261static int jzfb_get_controller_bpp(struct jzfb *jzfb)
262{
263 switch (jzfb->pdata->bpp) {
264 case 18:
265 case 24:
266 return 32;
267 case 15:
268 return 16;
269 default:
270 return jzfb->pdata->bpp;
271 }
272}
273
274static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb,
275 struct fb_var_screeninfo *var)
276{
277 size_t i;
278 struct fb_videomode *mode = jzfb->pdata->modes;
279
280 for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
281 if (mode->xres == var->xres && mode->yres == var->yres)
282 return mode;
283 }
284
285 return NULL;
286}
287
288static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
289{
290 struct jzfb *jzfb = fb->par;
291 struct fb_videomode *mode;
292
293 if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
294 var->bits_per_pixel != jzfb->pdata->bpp)
295 return -EINVAL;
296
297 mode = jzfb_get_mode(jzfb, var);
298 if (mode == NULL)
299 return -EINVAL;
300
301 fb_videomode_to_var(var, mode);
302
303 switch (jzfb->pdata->bpp) {
304 case 8:
305 break;
306 case 15:
307 var->red.offset = 10;
308 var->red.length = 5;
309 var->green.offset = 6;
310 var->green.length = 5;
311 var->blue.offset = 0;
312 var->blue.length = 5;
313 break;
314 case 16:
315 var->red.offset = 11;
316 var->red.length = 5;
317 var->green.offset = 5;
318 var->green.length = 6;
319 var->blue.offset = 0;
320 var->blue.length = 5;
321 break;
322 case 18:
323 var->red.offset = 16;
324 var->red.length = 6;
325 var->green.offset = 8;
326 var->green.length = 6;
327 var->blue.offset = 0;
328 var->blue.length = 6;
329 var->bits_per_pixel = 32;
330 break;
331 case 32:
332 case 24:
333 var->transp.offset = 24;
334 var->transp.length = 8;
335 var->red.offset = 16;
336 var->red.length = 8;
337 var->green.offset = 8;
338 var->green.length = 8;
339 var->blue.offset = 0;
340 var->blue.length = 8;
341 var->bits_per_pixel = 32;
342 break;
343 default:
344 break;
345 }
346
347 return 0;
348}
349
350static int jzfb_set_par(struct fb_info *info)
351{
352 struct jzfb *jzfb = info->par;
353 struct jz4740_fb_platform_data *pdata = jzfb->pdata;
354 struct fb_var_screeninfo *var = &info->var;
355 struct fb_videomode *mode;
356 uint16_t hds, vds;
357 uint16_t hde, vde;
358 uint16_t ht, vt;
359 uint32_t ctrl;
360 uint32_t cfg;
361 unsigned long rate;
362
363 mode = jzfb_get_mode(jzfb, var);
364 if (mode == NULL)
365 return -EINVAL;
366
367 if (mode == info->mode)
368 return 0;
369
370 info->mode = mode;
371
372 hds = mode->hsync_len + mode->left_margin;
373 hde = hds + mode->xres;
374 ht = hde + mode->right_margin;
375
376 vds = mode->vsync_len + mode->upper_margin;
377 vde = vds + mode->yres;
378 vt = vde + mode->lower_margin;
379
380 ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16;
381
382 switch (pdata->bpp) {
383 case 1:
384 ctrl |= JZ_LCD_CTRL_BPP_1;
385 break;
386 case 2:
387 ctrl |= JZ_LCD_CTRL_BPP_2;
388 break;
389 case 4:
390 ctrl |= JZ_LCD_CTRL_BPP_4;
391 break;
392 case 8:
393 ctrl |= JZ_LCD_CTRL_BPP_8;
394 break;
395 case 15:
396 ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */
397 case 16:
398 ctrl |= JZ_LCD_CTRL_BPP_15_16;
399 break;
400 case 18:
401 case 24:
402 case 32:
403 ctrl |= JZ_LCD_CTRL_BPP_18_24;
404 break;
405 default:
406 break;
407 }
408
409 cfg = pdata->lcd_type & 0xf;
410
411 if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
412 cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
413
414 if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
415 cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
416
417 if (pdata->pixclk_falling_edge)
418 cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
419
420 if (pdata->date_enable_active_low)
421 cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
422
423 if (pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT)
424 cfg |= JZ_LCD_CFG_18_BIT;
425
426 if (mode->pixclock) {
427 rate = PICOS2KHZ(mode->pixclock) * 1000;
428 mode->refresh = rate / vt / ht;
429 } else {
430 if (pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
431 rate = mode->refresh * (vt + 2 * mode->xres) * ht;
432 else
433 rate = mode->refresh * vt * ht;
434
435 mode->pixclock = KHZ2PICOS(rate / 1000);
436 }
437
438 mutex_lock(&jzfb->lock);
439 if (!jzfb->is_enabled)
440 clk_enable(jzfb->ldclk);
441 else
442 ctrl |= JZ_LCD_CTRL_ENABLE;
443
444 switch (pdata->lcd_type) {
445 case JZ_LCD_TYPE_SPECIAL_TFT_1:
446 case JZ_LCD_TYPE_SPECIAL_TFT_2:
447 case JZ_LCD_TYPE_SPECIAL_TFT_3:
448 writel(pdata->special_tft_config.spl, jzfb->base + JZ_REG_LCD_SPL);
449 writel(pdata->special_tft_config.cls, jzfb->base + JZ_REG_LCD_CLS);
450 writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_PS);
451 writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_REV);
452 break;
453 default:
454 cfg |= JZ_LCD_CFG_PS_DISABLE;
455 cfg |= JZ_LCD_CFG_CLS_DISABLE;
456 cfg |= JZ_LCD_CFG_SPL_DISABLE;
457 cfg |= JZ_LCD_CFG_REV_DISABLE;
458 break;
459 }
460
461 writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC);
462 writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC);
463
464 writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT);
465
466 writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH);
467 writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV);
468
469 writel(cfg, jzfb->base + JZ_REG_LCD_CFG);
470
471 writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
472
473 if (!jzfb->is_enabled)
474 clk_disable(jzfb->ldclk);
475
476 mutex_unlock(&jzfb->lock);
477
478 clk_set_rate(jzfb->lpclk, rate);
479 clk_set_rate(jzfb->ldclk, rate * 3);
480
481 return 0;
482}
483
484static void jzfb_enable(struct jzfb *jzfb)
485{
486 uint32_t ctrl;
487
488 clk_enable(jzfb->ldclk);
489
490 jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
491 jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
492
493 writel(0, jzfb->base + JZ_REG_LCD_STATE);
494
495 writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
496
497 ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
498 ctrl |= JZ_LCD_CTRL_ENABLE;
499 ctrl &= ~JZ_LCD_CTRL_DISABLE;
500 writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
501}
502
503static void jzfb_disable(struct jzfb *jzfb)
504{
505 uint32_t ctrl;
506
507 ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
508 ctrl |= JZ_LCD_CTRL_DISABLE;
509 writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
510 do {
511 ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
512 } while (!(ctrl & JZ_LCD_STATE_DISABLED));
513
514 jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
515 jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
516
517 clk_disable(jzfb->ldclk);
518}
519
520static int jzfb_blank(int blank_mode, struct fb_info *info)
521{
522 struct jzfb *jzfb = info->par;
523
524 switch (blank_mode) {
525 case FB_BLANK_UNBLANK:
526 mutex_lock(&jzfb->lock);
527 if (jzfb->is_enabled) {
528 mutex_unlock(&jzfb->lock);
529 return 0;
530 }
531
532 jzfb_enable(jzfb);
533 jzfb->is_enabled = 1;
534
535 mutex_unlock(&jzfb->lock);
536 break;
537 default:
538 mutex_lock(&jzfb->lock);
539 if (!jzfb->is_enabled) {
540 mutex_unlock(&jzfb->lock);
541 return 0;
542 }
543
544 jzfb_disable(jzfb);
545 jzfb->is_enabled = 0;
546
547 mutex_unlock(&jzfb->lock);
548 break;
549 }
550
551 return 0;
552}
553
554static int jzfb_alloc_devmem(struct jzfb *jzfb)
555{
556 int max_videosize = 0;
557 struct fb_videomode *mode = jzfb->pdata->modes;
558 void *page;
559 int i;
560
561 for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
562 if (max_videosize < mode->xres * mode->yres)
563 max_videosize = mode->xres * mode->yres;
564 }
565
566 max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3;
567
568 jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
569 sizeof(*jzfb->framedesc),
570 &jzfb->framedesc_phys, GFP_KERNEL);
571
572 if (!jzfb->framedesc)
573 return -ENOMEM;
574
575 jzfb->vidmem_size = PAGE_ALIGN(max_videosize);
576 jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
577 jzfb->vidmem_size,
578 &jzfb->vidmem_phys, GFP_KERNEL);
579
580 if (!jzfb->vidmem)
581 goto err_free_framedesc;
582
583 for (page = jzfb->vidmem;
584 page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
585 page += PAGE_SIZE) {
586 SetPageReserved(virt_to_page(page));
587 }
588
589 jzfb->framedesc->next = jzfb->framedesc_phys;
590 jzfb->framedesc->addr = jzfb->vidmem_phys;
591 jzfb->framedesc->id = 0xdeafbead;
592 jzfb->framedesc->cmd = 0;
593 jzfb->framedesc->cmd |= max_videosize / 4;
594
595 return 0;
596
597err_free_framedesc:
598 dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
599 jzfb->framedesc, jzfb->framedesc_phys);
600 return -ENOMEM;
601}
602
603static void jzfb_free_devmem(struct jzfb *jzfb)
604{
605 dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
606 jzfb->vidmem, jzfb->vidmem_phys);
607 dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
608 jzfb->framedesc, jzfb->framedesc_phys);
609}
610
611static struct fb_ops jzfb_ops = {
612 .owner = THIS_MODULE,
613 .fb_check_var = jzfb_check_var,
614 .fb_set_par = jzfb_set_par,
615 .fb_blank = jzfb_blank,
616 .fb_fillrect = sys_fillrect,
617 .fb_copyarea = sys_copyarea,
618 .fb_imageblit = sys_imageblit,
619 .fb_setcolreg = jzfb_setcolreg,
620};
621
622static int __devinit jzfb_probe(struct platform_device *pdev)
623{
624 int ret;
625 struct jzfb *jzfb;
626 struct fb_info *fb;
627 struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
628 struct resource *mem;
629
630 if (!pdata) {
631 dev_err(&pdev->dev, "Missing platform data\n");
632 return -ENXIO;
633 }
634
635 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
636 if (!mem) {
637 dev_err(&pdev->dev, "Failed to get register memory resource\n");
638 return -ENXIO;
639 }
640
641 mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
642 if (!mem) {
643 dev_err(&pdev->dev, "Failed to request register memory region\n");
644 return -EBUSY;
645 }
646
647 fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
648 if (!fb) {
649 dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
650 ret = -ENOMEM;
651 goto err_release_mem_region;
652 }
653
654 fb->fbops = &jzfb_ops;
655 fb->flags = FBINFO_DEFAULT;
656
657 jzfb = fb->par;
658 jzfb->pdev = pdev;
659 jzfb->pdata = pdata;
660 jzfb->mem = mem;
661
662 jzfb->ldclk = clk_get(&pdev->dev, "lcd");
663 if (IS_ERR(jzfb->ldclk)) {
664 ret = PTR_ERR(jzfb->ldclk);
665 dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
666 goto err_framebuffer_release;
667 }
668
669 jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
670 if (IS_ERR(jzfb->lpclk)) {
671 ret = PTR_ERR(jzfb->lpclk);
672 dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
673 goto err_put_ldclk;
674 }
675
676 jzfb->base = ioremap(mem->start, resource_size(mem));
677 if (!jzfb->base) {
678 dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
679 ret = -EBUSY;
680 goto err_put_lpclk;
681 }
682
683 platform_set_drvdata(pdev, jzfb);
684
685 mutex_init(&jzfb->lock);
686
687 fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
688 &fb->modelist);
689 fb_videomode_to_var(&fb->var, pdata->modes);
690 fb->var.bits_per_pixel = pdata->bpp;
691 jzfb_check_var(&fb->var, fb);
692
693 ret = jzfb_alloc_devmem(jzfb);
694 if (ret) {
695 dev_err(&pdev->dev, "Failed to allocate video memory\n");
696 goto err_iounmap;
697 }
698
699 fb->fix = jzfb_fix;
700 fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
701 fb->fix.mmio_start = mem->start;
702 fb->fix.mmio_len = resource_size(mem);
703 fb->fix.smem_start = jzfb->vidmem_phys;
704 fb->fix.smem_len = fb->fix.line_length * fb->var.yres;
705 fb->screen_base = jzfb->vidmem;
706 fb->pseudo_palette = jzfb->pseudo_palette;
707
708 fb_alloc_cmap(&fb->cmap, 256, 0);
709
710 clk_enable(jzfb->ldclk);
711 jzfb->is_enabled = 1;
712
713 writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
714
715 fb->mode = NULL;
716 jzfb_set_par(fb);
717
718 jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
719 jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
720
721 ret = register_framebuffer(fb);
722 if (ret) {
723 dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
724 goto err_free_devmem;
725 }
726
727 jzfb->fb = fb;
728
729 return 0;
730
731err_free_devmem:
732 jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
733 jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
734
735 fb_dealloc_cmap(&fb->cmap);
736 jzfb_free_devmem(jzfb);
737err_iounmap:
738 iounmap(jzfb->base);
739err_put_lpclk:
740 clk_put(jzfb->lpclk);
741err_put_ldclk:
742 clk_put(jzfb->ldclk);
743err_framebuffer_release:
744 framebuffer_release(fb);
745err_release_mem_region:
746 release_mem_region(mem->start, resource_size(mem));
747 return ret;
748}
749
750static int __devexit jzfb_remove(struct platform_device *pdev)
751{
752 struct jzfb *jzfb = platform_get_drvdata(pdev);
753
754 jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
755
756 jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
757 jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
758
759 iounmap(jzfb->base);
760 release_mem_region(jzfb->mem->start, resource_size(jzfb->mem));
761
762 fb_dealloc_cmap(&jzfb->fb->cmap);
763 jzfb_free_devmem(jzfb);
764
765 platform_set_drvdata(pdev, NULL);
766
767 clk_put(jzfb->lpclk);
768 clk_put(jzfb->ldclk);
769
770 framebuffer_release(jzfb->fb);
771
772 return 0;
773}
774
775#ifdef CONFIG_PM
776
777static int jzfb_suspend(struct device *dev)
778{
779 struct jzfb *jzfb = dev_get_drvdata(dev);
780
781 acquire_console_sem();
782 fb_set_suspend(jzfb->fb, 1);
783 release_console_sem();
784
785 mutex_lock(&jzfb->lock);
786 if (jzfb->is_enabled)
787 jzfb_disable(jzfb);
788 mutex_unlock(&jzfb->lock);
789
790 return 0;
791}
792
793static int jzfb_resume(struct device *dev)
794{
795 struct jzfb *jzfb = dev_get_drvdata(dev);
796 clk_enable(jzfb->ldclk);
797
798 mutex_lock(&jzfb->lock);
799 if (jzfb->is_enabled)
800 jzfb_enable(jzfb);
801 mutex_unlock(&jzfb->lock);
802
803 acquire_console_sem();
804 fb_set_suspend(jzfb->fb, 0);
805 release_console_sem();
806
807 return 0;
808}
809
810static const struct dev_pm_ops jzfb_pm_ops = {
811 .suspend = jzfb_suspend,
812 .resume = jzfb_resume,
813 .poweroff = jzfb_suspend,
814 .restore = jzfb_resume,
815};
816
817#define JZFB_PM_OPS (&jzfb_pm_ops)
818
819#else
820#define JZFB_PM_OPS NULL
821#endif
822
823static struct platform_driver jzfb_driver = {
824 .probe = jzfb_probe,
825 .remove = __devexit_p(jzfb_remove),
826 .driver = {
827 .name = "jz4740-fb",
828 .pm = JZFB_PM_OPS,
829 },
830};
831
832static int __init jzfb_init(void)
833{
834 return platform_driver_register(&jzfb_driver);
835}
836module_init(jzfb_init);
837
838static void __exit jzfb_exit(void)
839{
840 platform_driver_unregister(&jzfb_driver);
841}
842module_exit(jzfb_exit);
843
844MODULE_LICENSE("GPL");
845MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
846MODULE_DESCRIPTION("JZ4740 SoC LCD framebuffer driver");
847MODULE_ALIAS("platform:jz4740-fb");
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index 9e8bf7d5e249..b599e5e36ced 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -529,7 +529,7 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
529 var->transp.length = 0; 529 var->transp.length = 0;
530} 530}
531 531
532static void leo_unmap_regs(struct of_device *op, struct fb_info *info, 532static void leo_unmap_regs(struct platform_device *op, struct fb_info *info,
533 struct leo_par *par) 533 struct leo_par *par)
534{ 534{
535 if (par->lc_ss0_usr) 535 if (par->lc_ss0_usr)
@@ -547,7 +547,7 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
547 of_iounmap(&op->resource[0], info->screen_base, 0x800000); 547 of_iounmap(&op->resource[0], info->screen_base, 0x800000);
548} 548}
549 549
550static int __devinit leo_probe(struct of_device *op, 550static int __devinit leo_probe(struct platform_device *op,
551 const struct of_device_id *match) 551 const struct of_device_id *match)
552{ 552{
553 struct device_node *dp = op->dev.of_node; 553 struct device_node *dp = op->dev.of_node;
@@ -637,7 +637,7 @@ out_err:
637 return err; 637 return err;
638} 638}
639 639
640static int __devexit leo_remove(struct of_device *op) 640static int __devexit leo_remove(struct platform_device *op)
641{ 641{
642 struct fb_info *info = dev_get_drvdata(&op->dev); 642 struct fb_info *info = dev_get_drvdata(&op->dev);
643 struct leo_par *par = info->par; 643 struct leo_par *par = info->par;
@@ -677,12 +677,12 @@ static int __init leo_init(void)
677 if (fb_get_options("leofb", NULL)) 677 if (fb_get_options("leofb", NULL))
678 return -ENODEV; 678 return -ENODEV;
679 679
680 return of_register_driver(&leo_driver, &of_bus_type); 680 return of_register_platform_driver(&leo_driver);
681} 681}
682 682
683static void __exit leo_exit(void) 683static void __exit leo_exit(void)
684{ 684{
685 of_unregister_driver(&leo_driver); 685 of_unregister_platform_driver(&leo_driver);
686} 686}
687 687
688module_init(leo_init); 688module_init(leo_init);
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index 403b14445a78..0fb280ead3dc 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -191,7 +191,7 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
191 }; 191 };
192 192
193 i2c_new_probed_device(&m2info->maven.adapter, 193 i2c_new_probed_device(&m2info->maven.adapter,
194 &maven_info, addr_list); 194 &maven_info, addr_list, NULL);
195 } 195 }
196 } 196 }
197 return m2info; 197 return m2info;
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c
index f9fa0fd00292..1717623aabc0 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.c
+++ b/drivers/video/matrox/matroxfb_DAC1064.c
@@ -869,12 +869,9 @@ static int MGAG100_preinit(struct matrox_fb_info *minfo)
869 minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100 869 minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100
870 ? minfo->devflags.sgram : 1; 870 ? minfo->devflags.sgram : 1;
871 871
872#ifdef CONFIG_FB_MATROX_G
873 if (minfo->devflags.g450dac) { 872 if (minfo->devflags.g450dac) {
874 minfo->outputs[0].output = &g450out; 873 minfo->outputs[0].output = &g450out;
875 } else 874 } else {
876#endif
877 {
878 minfo->outputs[0].output = &m1064; 875 minfo->outputs[0].output = &m1064;
879 } 876 }
880 minfo->outputs[0].src = minfo->outputs[0].default_src; 877 minfo->outputs[0].src = minfo->outputs[0].default_src;
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index f3a4e15672d9..f96a471cb1a8 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -151,13 +151,13 @@ static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
151static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) { 151static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) {
152#if defined(__alpha__) || defined(__i386__) || defined(__x86_64__) 152#if defined(__alpha__) || defined(__i386__) || defined(__x86_64__)
153 /* 153 /*
154 * memcpy_toio works for us if: 154 * iowrite32_rep works for us if:
155 * (1) Copies data as 32bit quantities, not byte after byte, 155 * (1) Copies data as 32bit quantities, not byte after byte,
156 * (2) Performs LE ordered stores, and 156 * (2) Performs LE ordered stores, and
157 * (3) It copes with unaligned source (destination is guaranteed to be page 157 * (3) It copes with unaligned source (destination is guaranteed to be page
158 * aligned and length is guaranteed to be multiple of 4). 158 * aligned and length is guaranteed to be multiple of 4).
159 */ 159 */
160 memcpy_toio(va.vaddr, src, len); 160 iowrite32_rep(va.vaddr, src, len >> 2);
161#else 161#else
162 u_int32_t __iomem* addr = va.vaddr; 162 u_int32_t __iomem* addr = va.vaddr;
163 163
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 1e3e8f19783e..31b8f67477b7 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -280,7 +280,7 @@ static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
280 return fxtal * (*feed) / (*in) * ctl->den; 280 return fxtal * (*feed) / (*in) * ctl->den;
281} 281}
282 282
283static unsigned int matroxfb_mavenclock(const struct matrox_pll_ctl* ctl, 283static int matroxfb_mavenclock(const struct matrox_pll_ctl *ctl,
284 unsigned int htotal, unsigned int vtotal, 284 unsigned int htotal, unsigned int vtotal,
285 unsigned int* in, unsigned int* feed, unsigned int* post, 285 unsigned int* in, unsigned int* feed, unsigned int* post,
286 unsigned int* htotal2) { 286 unsigned int* htotal2) {
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
index 4e2b8cc3d460..b1c4374cf940 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfb.c
@@ -550,7 +550,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par)
550 return 0; 550 return 0;
551} 551}
552 552
553static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, 553static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev,
554 const struct of_device_id *id) 554 const struct of_device_id *id)
555{ 555{
556 struct device_node *np = ofdev->dev.of_node; 556 struct device_node *np = ofdev->dev.of_node;
@@ -669,7 +669,7 @@ fbrel:
669 return ret; 669 return ret;
670} 670}
671 671
672static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev) 672static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev)
673{ 673{
674 struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); 674 struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
675 struct mb862xxfb_par *par = fbi->par; 675 struct mb862xxfb_par *par = fbi->par;
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c
index ecad96524570..12dec7634c55 100644
--- a/drivers/video/mbx/mbxdebugfs.c
+++ b/drivers/video/mbx/mbxdebugfs.c
@@ -175,36 +175,42 @@ static const struct file_operations sysconf_fops = {
175 .read = sysconf_read_file, 175 .read = sysconf_read_file,
176 .write = write_file_dummy, 176 .write = write_file_dummy,
177 .open = open_file_generic, 177 .open = open_file_generic,
178 .llseek = default_llseek,
178}; 179};
179 180
180static const struct file_operations clock_fops = { 181static const struct file_operations clock_fops = {
181 .read = clock_read_file, 182 .read = clock_read_file,
182 .write = write_file_dummy, 183 .write = write_file_dummy,
183 .open = open_file_generic, 184 .open = open_file_generic,
185 .llseek = default_llseek,
184}; 186};
185 187
186static const struct file_operations display_fops = { 188static const struct file_operations display_fops = {
187 .read = display_read_file, 189 .read = display_read_file,
188 .write = write_file_dummy, 190 .write = write_file_dummy,
189 .open = open_file_generic, 191 .open = open_file_generic,
192 .llseek = default_llseek,
190}; 193};
191 194
192static const struct file_operations gsctl_fops = { 195static const struct file_operations gsctl_fops = {
193 .read = gsctl_read_file, 196 .read = gsctl_read_file,
194 .write = write_file_dummy, 197 .write = write_file_dummy,
195 .open = open_file_generic, 198 .open = open_file_generic,
199 .llseek = default_llseek,
196}; 200};
197 201
198static const struct file_operations sdram_fops = { 202static const struct file_operations sdram_fops = {
199 .read = sdram_read_file, 203 .read = sdram_read_file,
200 .write = write_file_dummy, 204 .write = write_file_dummy,
201 .open = open_file_generic, 205 .open = open_file_generic,
206 .llseek = default_llseek,
202}; 207};
203 208
204static const struct file_operations misc_fops = { 209static const struct file_operations misc_fops = {
205 .read = misc_read_file, 210 .read = misc_read_file,
206 .write = write_file_dummy, 211 .write = write_file_dummy,
207 .open = open_file_generic, 212 .open = open_file_generic,
213 .llseek = default_llseek,
208}; 214};
209 215
210static void __devinit mbxfb_debugfs_init(struct fb_info *fbi) 216static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index 9b3d6e4584cc..63ed3b72b01c 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/metronomefb.c
@@ -10,7 +10,7 @@
10 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. 10 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
11 * 11 *
12 * This work was made possible by help and equipment support from E-Ink 12 * This work was made possible by help and equipment support from E-Ink
13 * Corporation. http://support.eink.com/community 13 * Corporation. http://www.eink.com/
14 * 14 *
15 * This driver is written to be used with the Metronome display controller. 15 * This driver is written to be used with the Metronome display controller.
16 * It is intended to be architecture independent. A board specific driver 16 * It is intended to be architecture independent. A board specific driver
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index c1ff271017a9..7c316c34dfca 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -187,10 +187,8 @@ static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
187 187
188static void mddi_handle_rev_data_avail(struct mddi_info *mddi) 188static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
189{ 189{
190 union mddi_rev *rev = mddi->rev_data;
191 uint32_t rev_data_count; 190 uint32_t rev_data_count;
192 uint32_t rev_crc_err_count; 191 uint32_t rev_crc_err_count;
193 int i;
194 struct reg_read_info *ri; 192 struct reg_read_info *ri;
195 size_t prev_offset; 193 size_t prev_offset;
196 uint16_t length; 194 uint16_t length;
@@ -670,7 +668,7 @@ static int __init mddi_rev_data_setup(struct mddi_info *mddi)
670 return 0; 668 return 0;
671} 669}
672 670
673static int __init mddi_probe(struct platform_device *pdev) 671static int __devinit mddi_probe(struct platform_device *pdev)
674{ 672{
675 struct msm_mddi_platform_data *pdata = pdev->dev.platform_data; 673 struct msm_mddi_platform_data *pdata = pdev->dev.platform_data;
676 struct mddi_info *mddi = &mddi_info[pdev->id]; 674 struct mddi_info *mddi = &mddi_info[pdev->id];
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 19c01c6208e8..3c28db03ad39 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -258,7 +258,6 @@ int get_img(struct mdp_img *img, struct fb_info *info,
258{ 258{
259 int put_needed, ret = 0; 259 int put_needed, ret = 0;
260 struct file *file; 260 struct file *file;
261 unsigned long vstart;
262 261
263 file = fget_light(img->memory_id, &put_needed); 262 file = fget_light(img->memory_id, &put_needed);
264 if (file == NULL) 263 if (file == NULL)
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 46dda7d8aaee..cb163a5397be 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -19,13 +19,14 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
22#include <linux/interrupt.h> 24#include <linux/interrupt.h>
23#include <linux/fb.h> 25#include <linux/fb.h>
24#include <linux/init.h> 26#include <linux/init.h>
25#include <linux/ioport.h> 27#include <linux/ioport.h>
26#include <linux/pci.h> 28#include <linux/pci.h>
27#include <asm/io.h> 29#include <asm/io.h>
28#include <asm/prom.h>
29 30
30#ifdef CONFIG_PPC64 31#ifdef CONFIG_PPC64
31#include <asm/pci-bridge.h> 32#include <asm/pci-bridge.h>
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
index 2ffb34af4c59..87785c215a52 100644
--- a/drivers/video/omap/blizzard.c
+++ b/drivers/video/omap/blizzard.c
@@ -1590,7 +1590,7 @@ static int blizzard_init(struct omapfb_device *fbdev, int ext_mode,
1590 blizzard.auto_update_window.width = fbdev->panel->x_res; 1590 blizzard.auto_update_window.width = fbdev->panel->x_res;
1591 blizzard.auto_update_window.height = fbdev->panel->y_res; 1591 blizzard.auto_update_window.height = fbdev->panel->y_res;
1592 blizzard.auto_update_window.out_x = 0; 1592 blizzard.auto_update_window.out_x = 0;
1593 blizzard.auto_update_window.out_x = 0; 1593 blizzard.auto_update_window.out_y = 0;
1594 blizzard.auto_update_window.out_width = fbdev->panel->x_res; 1594 blizzard.auto_update_window.out_width = fbdev->panel->x_res;
1595 blizzard.auto_update_window.out_height = fbdev->panel->y_res; 1595 blizzard.auto_update_window.out_height = fbdev->panel->y_res;
1596 blizzard.auto_update_window.format = 0; 1596 blizzard.auto_update_window.format = 0;
diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c
index 2be94eb3bbf5..10459d8bd9a0 100644
--- a/drivers/video/omap/lcd_apollon.c
+++ b/drivers/video/omap/lcd_apollon.c
@@ -25,7 +25,6 @@
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26 26
27#include <mach/gpio.h> 27#include <mach/gpio.h>
28#include <plat/mux.h>
29 28
30#include "omapfb.h" 29#include "omapfb.h"
31 30
@@ -34,8 +33,6 @@
34static int apollon_panel_init(struct lcd_panel *panel, 33static int apollon_panel_init(struct lcd_panel *panel,
35 struct omapfb_device *fbdev) 34 struct omapfb_device *fbdev)
36{ 35{
37 /* configure LCD PWR_EN */
38 omap_cfg_reg(M21_242X_GPIO11);
39 return 0; 36 return 0;
40} 37}
41 38
diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c
index ca75cc2a87a5..d7c6c3e0afc6 100644
--- a/drivers/video/omap/lcd_omap3beagle.c
+++ b/drivers/video/omap/lcd_omap3beagle.c
@@ -25,8 +25,6 @@
25#include <linux/gpio.h> 25#include <linux/gpio.h>
26#include <linux/i2c/twl.h> 26#include <linux/i2c/twl.h>
27 27
28#include <plat/mux.h>
29#include <plat/mux.h>
30#include <asm/mach-types.h> 28#include <asm/mach-types.h>
31 29
32#include "omapfb.h" 30#include "omapfb.h"
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 881c9f77c75a..12327bbfdbbb 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -40,7 +40,7 @@ config PANEL_TPO_TD043MTEA1
40 40
41config PANEL_ACX565AKM 41config PANEL_ACX565AKM
42 tristate "ACX565AKM Panel" 42 tristate "ACX565AKM Panel"
43 depends on OMAP2_DSS_SDI 43 depends on OMAP2_DSS_SDI && SPI
44 select BACKLIGHT_CLASS_DEVICE 44 select BACKLIGHT_CLASS_DEVICE
45 help 45 help
46 This is the LCD panel used on Nokia N900 46 This is the LCD panel used on Nokia N900
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index 1f8eb70e2937..e77310653207 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -587,12 +587,15 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
587 587
588 dev_dbg(&dssdev->dev, "%s\n", __func__); 588 dev_dbg(&dssdev->dev, "%s\n", __func__);
589 589
590 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
591 return 0;
592
590 mutex_lock(&md->mutex); 593 mutex_lock(&md->mutex);
591 594
592 r = omapdss_sdi_display_enable(dssdev); 595 r = omapdss_sdi_display_enable(dssdev);
593 if (r) { 596 if (r) {
594 pr_err("%s sdi enable failed\n", __func__); 597 pr_err("%s sdi enable failed\n", __func__);
595 return r; 598 goto fail_unlock;
596 } 599 }
597 600
598 /*FIXME tweak me */ 601 /*FIXME tweak me */
@@ -633,6 +636,8 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
633 return acx565akm_bl_update_status(md->bl_dev); 636 return acx565akm_bl_update_status(md->bl_dev);
634fail: 637fail:
635 omapdss_sdi_display_disable(dssdev); 638 omapdss_sdi_display_disable(dssdev);
639fail_unlock:
640 mutex_unlock(&md->mutex);
636 return r; 641 return r;
637} 642}
638 643
@@ -642,6 +647,9 @@ static void acx_panel_power_off(struct omap_dss_device *dssdev)
642 647
643 dev_dbg(&dssdev->dev, "%s\n", __func__); 648 dev_dbg(&dssdev->dev, "%s\n", __func__);
644 649
650 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
651 return;
652
645 mutex_lock(&md->mutex); 653 mutex_lock(&md->mutex);
646 654
647 if (!md->enabled) { 655 if (!md->enabled) {
diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c
index 300eff5de1b4..395a68de3990 100644
--- a/drivers/video/omap2/displays/panel-generic.c
+++ b/drivers/video/omap2/displays/panel-generic.c
@@ -39,6 +39,9 @@ static int generic_panel_power_on(struct omap_dss_device *dssdev)
39{ 39{
40 int r; 40 int r;
41 41
42 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
43 return 0;
44
42 r = omapdss_dpi_display_enable(dssdev); 45 r = omapdss_dpi_display_enable(dssdev);
43 if (r) 46 if (r)
44 goto err0; 47 goto err0;
@@ -58,6 +61,9 @@ err0:
58 61
59static void generic_panel_power_off(struct omap_dss_device *dssdev) 62static void generic_panel_power_off(struct omap_dss_device *dssdev)
60{ 63{
64 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
65 return;
66
61 if (dssdev->platform_disable) 67 if (dssdev->platform_disable)
62 dssdev->platform_disable(dssdev); 68 dssdev->platform_disable(dssdev);
63 69
diff --git a/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c b/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
index 10267461991c..0c6896cea2d0 100644
--- a/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
+++ b/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
@@ -43,6 +43,9 @@ static int sharp_lq_panel_power_on(struct omap_dss_device *dssdev)
43{ 43{
44 int r; 44 int r;
45 45
46 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
47 return 0;
48
46 r = omapdss_dpi_display_enable(dssdev); 49 r = omapdss_dpi_display_enable(dssdev);
47 if (r) 50 if (r)
48 goto err0; 51 goto err0;
@@ -65,6 +68,9 @@ err0:
65 68
66static void sharp_lq_panel_power_off(struct omap_dss_device *dssdev) 69static void sharp_lq_panel_power_off(struct omap_dss_device *dssdev)
67{ 70{
71 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
72 return;
73
68 if (dssdev->platform_disable) 74 if (dssdev->platform_disable)
69 dssdev->platform_disable(dssdev); 75 dssdev->platform_disable(dssdev);
70 76
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index 7d9eb2b1f5af..9a138f650e05 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -135,6 +135,9 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
135{ 135{
136 int r = 0; 136 int r = 0;
137 137
138 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
139 return 0;
140
138 r = omapdss_dpi_display_enable(dssdev); 141 r = omapdss_dpi_display_enable(dssdev);
139 if (r) 142 if (r)
140 goto err0; 143 goto err0;
@@ -157,6 +160,9 @@ err0:
157 160
158static void sharp_ls_power_off(struct omap_dss_device *dssdev) 161static void sharp_ls_power_off(struct omap_dss_device *dssdev)
159{ 162{
163 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
164 return;
165
160 if (dssdev->platform_disable) 166 if (dssdev->platform_disable)
161 dssdev->platform_disable(dssdev); 167 dssdev->platform_disable(dssdev);
162 168
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index aaf5d308a046..e1c765d11419 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -28,12 +28,13 @@
28#include <linux/fb.h> 28#include <linux/fb.h>
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/gpio.h> 30#include <linux/gpio.h>
31#include <linux/completion.h>
32#include <linux/workqueue.h> 31#include <linux/workqueue.h>
33#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/regulator/consumer.h>
34#include <linux/mutex.h> 34#include <linux/mutex.h>
35 35
36#include <plat/display.h> 36#include <plat/display.h>
37#include <plat/nokia-dsi-panel.h>
37 38
38/* DSI Virtual channel. Hardcoded for now. */ 39/* DSI Virtual channel. Hardcoded for now. */
39#define TCH 0 40#define TCH 0
@@ -62,11 +63,136 @@
62#define DCS_GET_ID2 0xdb 63#define DCS_GET_ID2 0xdb
63#define DCS_GET_ID3 0xdc 64#define DCS_GET_ID3 0xdc
64 65
65/* #define TAAL_USE_ESD_CHECK */
66#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000) 66#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
67 67
68static irqreturn_t taal_te_isr(int irq, void *data);
69static void taal_te_timeout_work_callback(struct work_struct *work);
68static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); 70static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
69 71
72struct panel_regulator {
73 struct regulator *regulator;
74 const char *name;
75 int min_uV;
76 int max_uV;
77};
78
79static void free_regulators(struct panel_regulator *regulators, int n)
80{
81 int i;
82
83 for (i = 0; i < n; i++) {
84 /* disable/put in reverse order */
85 regulator_disable(regulators[n - i - 1].regulator);
86 regulator_put(regulators[n - i - 1].regulator);
87 }
88}
89
90static int init_regulators(struct omap_dss_device *dssdev,
91 struct panel_regulator *regulators, int n)
92{
93 int r, i, v;
94
95 for (i = 0; i < n; i++) {
96 struct regulator *reg;
97
98 reg = regulator_get(&dssdev->dev, regulators[i].name);
99 if (IS_ERR(reg)) {
100 dev_err(&dssdev->dev, "failed to get regulator %s\n",
101 regulators[i].name);
102 r = PTR_ERR(reg);
103 goto err;
104 }
105
106 /* FIXME: better handling of fixed vs. variable regulators */
107 v = regulator_get_voltage(reg);
108 if (v < regulators[i].min_uV || v > regulators[i].max_uV) {
109 r = regulator_set_voltage(reg, regulators[i].min_uV,
110 regulators[i].max_uV);
111 if (r) {
112 dev_err(&dssdev->dev,
113 "failed to set regulator %s voltage\n",
114 regulators[i].name);
115 regulator_put(reg);
116 goto err;
117 }
118 }
119
120 r = regulator_enable(reg);
121 if (r) {
122 dev_err(&dssdev->dev, "failed to enable regulator %s\n",
123 regulators[i].name);
124 regulator_put(reg);
125 goto err;
126 }
127
128 regulators[i].regulator = reg;
129 }
130
131 return 0;
132
133err:
134 free_regulators(regulators, i);
135
136 return r;
137}
138
139/**
140 * struct panel_config - panel configuration
141 * @name: panel name
142 * @type: panel type
143 * @timings: panel resolution
144 * @sleep: various panel specific delays, passed to msleep() if non-zero
145 * @reset_sequence: reset sequence timings, passed to udelay() if non-zero
146 * @regulators: array of panel regulators
147 * @num_regulators: number of regulators in the array
148 */
149struct panel_config {
150 const char *name;
151 int type;
152
153 struct omap_video_timings timings;
154
155 struct {
156 unsigned int sleep_in;
157 unsigned int sleep_out;
158 unsigned int hw_reset;
159 unsigned int enable_te;
160 } sleep;
161
162 struct {
163 unsigned int high;
164 unsigned int low;
165 } reset_sequence;
166
167 struct panel_regulator *regulators;
168 int num_regulators;
169};
170
171enum {
172 PANEL_TAAL,
173};
174
175static struct panel_config panel_configs[] = {
176 {
177 .name = "taal",
178 .type = PANEL_TAAL,
179 .timings = {
180 .x_res = 864,
181 .y_res = 480,
182 },
183 .sleep = {
184 .sleep_in = 5,
185 .sleep_out = 5,
186 .hw_reset = 5,
187 .enable_te = 100, /* possible panel bug */
188 },
189 .reset_sequence = {
190 .high = 10,
191 .low = 10,
192 },
193 },
194};
195
70struct taal_data { 196struct taal_data {
71 struct mutex lock; 197 struct mutex lock;
72 198
@@ -84,8 +210,15 @@ struct taal_data {
84 bool mirror; 210 bool mirror;
85 211
86 bool te_enabled; 212 bool te_enabled;
87 bool use_ext_te; 213
88 struct completion te_completion; 214 atomic_t do_update;
215 struct {
216 u16 x;
217 u16 y;
218 u16 w;
219 u16 h;
220 } update_region;
221 struct delayed_work te_timeout_work;
89 222
90 bool use_dsi_bl; 223 bool use_dsi_bl;
91 224
@@ -96,8 +229,16 @@ struct taal_data {
96 229
97 struct workqueue_struct *esd_wq; 230 struct workqueue_struct *esd_wq;
98 struct delayed_work esd_work; 231 struct delayed_work esd_work;
232
233 struct panel_config *panel_config;
99}; 234};
100 235
236static inline struct nokia_dsi_panel_data
237*get_panel_data(const struct omap_dss_device *dssdev)
238{
239 return (struct nokia_dsi_panel_data *) dssdev->data;
240}
241
101static void taal_esd_work(struct work_struct *work); 242static void taal_esd_work(struct work_struct *work);
102 243
103static void hw_guard_start(struct taal_data *td, int guard_msec) 244static void hw_guard_start(struct taal_data *td, int guard_msec)
@@ -159,7 +300,8 @@ static int taal_sleep_in(struct taal_data *td)
159 300
160 hw_guard_start(td, 120); 301 hw_guard_start(td, 120);
161 302
162 msleep(5); 303 if (td->panel_config->sleep.sleep_in)
304 msleep(td->panel_config->sleep.sleep_in);
163 305
164 return 0; 306 return 0;
165} 307}
@@ -176,7 +318,8 @@ static int taal_sleep_out(struct taal_data *td)
176 318
177 hw_guard_start(td, 120); 319 hw_guard_start(td, 120);
178 320
179 msleep(5); 321 if (td->panel_config->sleep.sleep_out)
322 msleep(td->panel_config->sleep.sleep_out);
180 323
181 return 0; 324 return 0;
182} 325}
@@ -279,6 +422,7 @@ static int taal_bl_update_status(struct backlight_device *dev)
279{ 422{
280 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); 423 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
281 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 424 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
425 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
282 int r; 426 int r;
283 int level; 427 int level;
284 428
@@ -290,24 +434,26 @@ static int taal_bl_update_status(struct backlight_device *dev)
290 434
291 dev_dbg(&dssdev->dev, "update brightness to %d\n", level); 435 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
292 436
437 mutex_lock(&td->lock);
438
293 if (td->use_dsi_bl) { 439 if (td->use_dsi_bl) {
294 if (td->enabled) { 440 if (td->enabled) {
295 dsi_bus_lock(); 441 dsi_bus_lock();
296 r = taal_dcs_write_1(DCS_BRIGHTNESS, level); 442 r = taal_dcs_write_1(DCS_BRIGHTNESS, level);
297 dsi_bus_unlock(); 443 dsi_bus_unlock();
298 if (r) 444 } else {
299 return r; 445 r = 0;
300 } 446 }
301 } else { 447 } else {
302 if (!dssdev->set_backlight) 448 if (!panel_data->set_backlight)
303 return -EINVAL; 449 r = -EINVAL;
304 450 else
305 r = dssdev->set_backlight(dssdev, level); 451 r = panel_data->set_backlight(dssdev, level);
306 if (r)
307 return r;
308 } 452 }
309 453
310 return 0; 454 mutex_unlock(&td->lock);
455
456 return r;
311} 457}
312 458
313static int taal_bl_get_intensity(struct backlight_device *dev) 459static int taal_bl_get_intensity(struct backlight_device *dev)
@@ -344,16 +490,6 @@ static void taal_get_resolution(struct omap_dss_device *dssdev,
344 } 490 }
345} 491}
346 492
347static irqreturn_t taal_te_isr(int irq, void *data)
348{
349 struct omap_dss_device *dssdev = data;
350 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
351
352 complete_all(&td->te_completion);
353
354 return IRQ_HANDLED;
355}
356
357static ssize_t taal_num_errors_show(struct device *dev, 493static ssize_t taal_num_errors_show(struct device *dev,
358 struct device_attribute *attr, char *buf) 494 struct device_attribute *attr, char *buf)
359{ 495{
@@ -362,6 +498,8 @@ static ssize_t taal_num_errors_show(struct device *dev,
362 u8 errors; 498 u8 errors;
363 int r; 499 int r;
364 500
501 mutex_lock(&td->lock);
502
365 if (td->enabled) { 503 if (td->enabled) {
366 dsi_bus_lock(); 504 dsi_bus_lock();
367 r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); 505 r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors);
@@ -370,6 +508,8 @@ static ssize_t taal_num_errors_show(struct device *dev,
370 r = -ENODEV; 508 r = -ENODEV;
371 } 509 }
372 510
511 mutex_unlock(&td->lock);
512
373 if (r) 513 if (r)
374 return r; 514 return r;
375 515
@@ -384,6 +524,8 @@ static ssize_t taal_hw_revision_show(struct device *dev,
384 u8 id1, id2, id3; 524 u8 id1, id2, id3;
385 int r; 525 int r;
386 526
527 mutex_lock(&td->lock);
528
387 if (td->enabled) { 529 if (td->enabled) {
388 dsi_bus_lock(); 530 dsi_bus_lock();
389 r = taal_get_id(&id1, &id2, &id3); 531 r = taal_get_id(&id1, &id2, &id3);
@@ -392,6 +534,8 @@ static ssize_t taal_hw_revision_show(struct device *dev,
392 r = -ENODEV; 534 r = -ENODEV;
393 } 535 }
394 536
537 mutex_unlock(&td->lock);
538
395 if (r) 539 if (r)
396 return r; 540 return r;
397 541
@@ -441,6 +585,8 @@ static ssize_t store_cabc_mode(struct device *dev,
441 if (i == ARRAY_SIZE(cabc_modes)) 585 if (i == ARRAY_SIZE(cabc_modes))
442 return -EINVAL; 586 return -EINVAL;
443 587
588 mutex_lock(&td->lock);
589
444 if (td->enabled) { 590 if (td->enabled) {
445 dsi_bus_lock(); 591 dsi_bus_lock();
446 if (!td->cabc_broken) 592 if (!td->cabc_broken)
@@ -450,6 +596,8 @@ static ssize_t store_cabc_mode(struct device *dev,
450 596
451 td->cabc_mode = i; 597 td->cabc_mode = i;
452 598
599 mutex_unlock(&td->lock);
600
453 return count; 601 return count;
454} 602}
455 603
@@ -488,47 +636,93 @@ static struct attribute_group taal_attr_group = {
488 .attrs = taal_attrs, 636 .attrs = taal_attrs,
489}; 637};
490 638
639static void taal_hw_reset(struct omap_dss_device *dssdev)
640{
641 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
642 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
643
644 if (panel_data->reset_gpio == -1)
645 return;
646
647 gpio_set_value(panel_data->reset_gpio, 1);
648 if (td->panel_config->reset_sequence.high)
649 udelay(td->panel_config->reset_sequence.high);
650 /* reset the panel */
651 gpio_set_value(panel_data->reset_gpio, 0);
652 /* assert reset */
653 if (td->panel_config->reset_sequence.low)
654 udelay(td->panel_config->reset_sequence.low);
655 gpio_set_value(panel_data->reset_gpio, 1);
656 /* wait after releasing reset */
657 if (td->panel_config->sleep.hw_reset)
658 msleep(td->panel_config->sleep.hw_reset);
659}
660
491static int taal_probe(struct omap_dss_device *dssdev) 661static int taal_probe(struct omap_dss_device *dssdev)
492{ 662{
493 struct backlight_properties props; 663 struct backlight_properties props;
494 struct taal_data *td; 664 struct taal_data *td;
495 struct backlight_device *bldev; 665 struct backlight_device *bldev;
496 int r; 666 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
497 667 struct panel_config *panel_config = NULL;
498 const struct omap_video_timings taal_panel_timings = { 668 int r, i;
499 .x_res = 864,
500 .y_res = 480,
501 };
502 669
503 dev_dbg(&dssdev->dev, "probe\n"); 670 dev_dbg(&dssdev->dev, "probe\n");
504 671
672 if (!panel_data || !panel_data->name) {
673 r = -EINVAL;
674 goto err;
675 }
676
677 for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
678 if (strcmp(panel_data->name, panel_configs[i].name) == 0) {
679 panel_config = &panel_configs[i];
680 break;
681 }
682 }
683
684 if (!panel_config) {
685 r = -EINVAL;
686 goto err;
687 }
688
505 dssdev->panel.config = OMAP_DSS_LCD_TFT; 689 dssdev->panel.config = OMAP_DSS_LCD_TFT;
506 dssdev->panel.timings = taal_panel_timings; 690 dssdev->panel.timings = panel_config->timings;
507 dssdev->ctrl.pixel_size = 24; 691 dssdev->ctrl.pixel_size = 24;
508 692
509 td = kzalloc(sizeof(*td), GFP_KERNEL); 693 td = kzalloc(sizeof(*td), GFP_KERNEL);
510 if (!td) { 694 if (!td) {
511 r = -ENOMEM; 695 r = -ENOMEM;
512 goto err0; 696 goto err;
513 } 697 }
514 td->dssdev = dssdev; 698 td->dssdev = dssdev;
699 td->panel_config = panel_config;
515 700
516 mutex_init(&td->lock); 701 mutex_init(&td->lock);
517 702
703 atomic_set(&td->do_update, 0);
704
705 r = init_regulators(dssdev, panel_config->regulators,
706 panel_config->num_regulators);
707 if (r)
708 goto err_reg;
709
518 td->esd_wq = create_singlethread_workqueue("taal_esd"); 710 td->esd_wq = create_singlethread_workqueue("taal_esd");
519 if (td->esd_wq == NULL) { 711 if (td->esd_wq == NULL) {
520 dev_err(&dssdev->dev, "can't create ESD workqueue\n"); 712 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
521 r = -ENOMEM; 713 r = -ENOMEM;
522 goto err1; 714 goto err_wq;
523 } 715 }
524 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); 716 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
525 717
526 dev_set_drvdata(&dssdev->dev, td); 718 dev_set_drvdata(&dssdev->dev, td);
527 719
720 taal_hw_reset(dssdev);
721
528 /* if no platform set_backlight() defined, presume DSI backlight 722 /* if no platform set_backlight() defined, presume DSI backlight
529 * control */ 723 * control */
530 memset(&props, 0, sizeof(struct backlight_properties)); 724 memset(&props, 0, sizeof(struct backlight_properties));
531 if (!dssdev->set_backlight) 725 if (!panel_data->set_backlight)
532 td->use_dsi_bl = true; 726 td->use_dsi_bl = true;
533 727
534 if (td->use_dsi_bl) 728 if (td->use_dsi_bl)
@@ -539,7 +733,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
539 &taal_bl_ops, &props); 733 &taal_bl_ops, &props);
540 if (IS_ERR(bldev)) { 734 if (IS_ERR(bldev)) {
541 r = PTR_ERR(bldev); 735 r = PTR_ERR(bldev);
542 goto err2; 736 goto err_bl;
543 } 737 }
544 738
545 td->bldev = bldev; 739 td->bldev = bldev;
@@ -553,13 +747,13 @@ static int taal_probe(struct omap_dss_device *dssdev)
553 747
554 taal_bl_update_status(bldev); 748 taal_bl_update_status(bldev);
555 749
556 if (dssdev->phy.dsi.ext_te) { 750 if (panel_data->use_ext_te) {
557 int gpio = dssdev->phy.dsi.ext_te_gpio; 751 int gpio = panel_data->ext_te_gpio;
558 752
559 r = gpio_request(gpio, "taal irq"); 753 r = gpio_request(gpio, "taal irq");
560 if (r) { 754 if (r) {
561 dev_err(&dssdev->dev, "GPIO request failed\n"); 755 dev_err(&dssdev->dev, "GPIO request failed\n");
562 goto err3; 756 goto err_gpio;
563 } 757 }
564 758
565 gpio_direction_input(gpio); 759 gpio_direction_input(gpio);
@@ -571,49 +765,52 @@ static int taal_probe(struct omap_dss_device *dssdev)
571 if (r) { 765 if (r) {
572 dev_err(&dssdev->dev, "IRQ request failed\n"); 766 dev_err(&dssdev->dev, "IRQ request failed\n");
573 gpio_free(gpio); 767 gpio_free(gpio);
574 goto err3; 768 goto err_irq;
575 } 769 }
576 770
577 init_completion(&td->te_completion); 771 INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work,
772 taal_te_timeout_work_callback);
578 773
579 td->use_ext_te = true; 774 dev_dbg(&dssdev->dev, "Using GPIO TE\n");
580 } 775 }
581 776
582 r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); 777 r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
583 if (r) { 778 if (r) {
584 dev_err(&dssdev->dev, "failed to create sysfs files\n"); 779 dev_err(&dssdev->dev, "failed to create sysfs files\n");
585 goto err4; 780 goto err_sysfs;
586 } 781 }
587 782
588 return 0; 783 return 0;
589err4: 784err_sysfs:
590 if (td->use_ext_te) { 785 if (panel_data->use_ext_te)
591 int gpio = dssdev->phy.dsi.ext_te_gpio; 786 free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev);
592 free_irq(gpio_to_irq(gpio), dssdev); 787err_irq:
593 gpio_free(gpio); 788 if (panel_data->use_ext_te)
594 } 789 gpio_free(panel_data->ext_te_gpio);
595err3: 790err_gpio:
596 backlight_device_unregister(bldev); 791 backlight_device_unregister(bldev);
597err2: 792err_bl:
598 cancel_delayed_work_sync(&td->esd_work);
599 destroy_workqueue(td->esd_wq); 793 destroy_workqueue(td->esd_wq);
600err1: 794err_wq:
795 free_regulators(panel_config->regulators, panel_config->num_regulators);
796err_reg:
601 kfree(td); 797 kfree(td);
602err0: 798err:
603 return r; 799 return r;
604} 800}
605 801
606static void taal_remove(struct omap_dss_device *dssdev) 802static void taal_remove(struct omap_dss_device *dssdev)
607{ 803{
608 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 804 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
805 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
609 struct backlight_device *bldev; 806 struct backlight_device *bldev;
610 807
611 dev_dbg(&dssdev->dev, "remove\n"); 808 dev_dbg(&dssdev->dev, "remove\n");
612 809
613 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); 810 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
614 811
615 if (td->use_ext_te) { 812 if (panel_data->use_ext_te) {
616 int gpio = dssdev->phy.dsi.ext_te_gpio; 813 int gpio = panel_data->ext_te_gpio;
617 free_irq(gpio_to_irq(gpio), dssdev); 814 free_irq(gpio_to_irq(gpio), dssdev);
618 gpio_free(gpio); 815 gpio_free(gpio);
619 } 816 }
@@ -623,9 +820,15 @@ static void taal_remove(struct omap_dss_device *dssdev)
623 taal_bl_update_status(bldev); 820 taal_bl_update_status(bldev);
624 backlight_device_unregister(bldev); 821 backlight_device_unregister(bldev);
625 822
626 cancel_delayed_work_sync(&td->esd_work); 823 cancel_delayed_work(&td->esd_work);
627 destroy_workqueue(td->esd_wq); 824 destroy_workqueue(td->esd_wq);
628 825
826 /* reset, to be sure that the panel is in a valid state */
827 taal_hw_reset(dssdev);
828
829 free_regulators(td->panel_config->regulators,
830 td->panel_config->num_regulators);
831
629 kfree(td); 832 kfree(td);
630} 833}
631 834
@@ -635,23 +838,14 @@ static int taal_power_on(struct omap_dss_device *dssdev)
635 u8 id1, id2, id3; 838 u8 id1, id2, id3;
636 int r; 839 int r;
637 840
638 if (dssdev->platform_enable) {
639 r = dssdev->platform_enable(dssdev);
640 if (r)
641 return r;
642 }
643
644 /* it seems we have to wait a bit until taal is ready */
645 msleep(5);
646
647 dsi_bus_lock();
648
649 r = omapdss_dsi_display_enable(dssdev); 841 r = omapdss_dsi_display_enable(dssdev);
650 if (r) { 842 if (r) {
651 dev_err(&dssdev->dev, "failed to enable DSI\n"); 843 dev_err(&dssdev->dev, "failed to enable DSI\n");
652 goto err0; 844 goto err0;
653 } 845 }
654 846
847 taal_hw_reset(dssdev);
848
655 omapdss_dsi_vc_enable_hs(TCH, false); 849 omapdss_dsi_vc_enable_hs(TCH, false);
656 850
657 r = taal_sleep_out(td); 851 r = taal_sleep_out(td);
@@ -662,34 +856,47 @@ static int taal_power_on(struct omap_dss_device *dssdev)
662 if (r) 856 if (r)
663 goto err; 857 goto err;
664 858
665 /* on early revisions CABC is broken */ 859 /* on early Taal revisions CABC is broken */
666 if (id2 == 0x00 || id2 == 0xff || id2 == 0x81) 860 if (td->panel_config->type == PANEL_TAAL &&
861 (id2 == 0x00 || id2 == 0xff || id2 == 0x81))
667 td->cabc_broken = true; 862 td->cabc_broken = true;
668 863
669 taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); 864 r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
670 taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */ 865 if (r)
866 goto err;
867
868 r = taal_dcs_write_1(DCS_CTRL_DISPLAY,
869 (1<<2) | (1<<5)); /* BL | BCTRL */
870 if (r)
871 goto err;
872
873 r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
874 if (r)
875 goto err;
671 876
672 taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ 877 r = taal_set_addr_mode(td->rotate, td->mirror);
878 if (r)
879 goto err;
673 880
674 taal_set_addr_mode(td->rotate, td->mirror); 881 if (!td->cabc_broken) {
675 if (!td->cabc_broken) 882 r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
676 taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); 883 if (r)
884 goto err;
885 }
677 886
678 taal_dcs_write_0(DCS_DISPLAY_ON); 887 r = taal_dcs_write_0(DCS_DISPLAY_ON);
888 if (r)
889 goto err;
679 890
680 r = _taal_enable_te(dssdev, td->te_enabled); 891 r = _taal_enable_te(dssdev, td->te_enabled);
681 if (r) 892 if (r)
682 goto err; 893 goto err;
683 894
684#ifdef TAAL_USE_ESD_CHECK
685 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
686#endif
687
688 td->enabled = 1; 895 td->enabled = 1;
689 896
690 if (!td->intro_printed) { 897 if (!td->intro_printed) {
691 dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n", 898 dev_info(&dssdev->dev, "%s panel revision %02x.%02x.%02x\n",
692 id1, id2, id3); 899 td->panel_config->name, id1, id2, id3);
693 if (td->cabc_broken) 900 if (td->cabc_broken)
694 dev_info(&dssdev->dev, 901 dev_info(&dssdev->dev,
695 "old Taal version, CABC disabled\n"); 902 "old Taal version, CABC disabled\n");
@@ -698,46 +905,44 @@ static int taal_power_on(struct omap_dss_device *dssdev)
698 905
699 omapdss_dsi_vc_enable_hs(TCH, true); 906 omapdss_dsi_vc_enable_hs(TCH, true);
700 907
701 dsi_bus_unlock();
702
703 return 0; 908 return 0;
704err: 909err:
910 dev_err(&dssdev->dev, "error while enabling panel, issuing HW reset\n");
911
912 taal_hw_reset(dssdev);
913
705 omapdss_dsi_display_disable(dssdev); 914 omapdss_dsi_display_disable(dssdev);
706err0: 915err0:
707 dsi_bus_unlock();
708 if (dssdev->platform_disable)
709 dssdev->platform_disable(dssdev);
710
711 return r; 916 return r;
712} 917}
713 918
714static void taal_power_off(struct omap_dss_device *dssdev) 919static void taal_power_off(struct omap_dss_device *dssdev)
715{ 920{
716 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 921 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
922 int r;
717 923
718 dsi_bus_lock(); 924 r = taal_dcs_write_0(DCS_DISPLAY_OFF);
719 925 if (!r) {
720 cancel_delayed_work(&td->esd_work); 926 r = taal_sleep_in(td);
721 927 /* HACK: wait a bit so that the message goes through */
722 taal_dcs_write_0(DCS_DISPLAY_OFF); 928 msleep(10);
723 taal_sleep_in(td); 929 }
724 930
725 /* wait a bit so that the message goes through */ 931 if (r) {
726 msleep(10); 932 dev_err(&dssdev->dev,
933 "error disabling panel, issuing HW reset\n");
934 taal_hw_reset(dssdev);
935 }
727 936
728 omapdss_dsi_display_disable(dssdev); 937 omapdss_dsi_display_disable(dssdev);
729 938
730 if (dssdev->platform_disable)
731 dssdev->platform_disable(dssdev);
732
733 td->enabled = 0; 939 td->enabled = 0;
734
735 dsi_bus_unlock();
736} 940}
737 941
738static int taal_enable(struct omap_dss_device *dssdev) 942static int taal_enable(struct omap_dss_device *dssdev)
739{ 943{
740 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 944 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
945 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
741 int r; 946 int r;
742 947
743 dev_dbg(&dssdev->dev, "enable\n"); 948 dev_dbg(&dssdev->dev, "enable\n");
@@ -749,10 +954,19 @@ static int taal_enable(struct omap_dss_device *dssdev)
749 goto err; 954 goto err;
750 } 955 }
751 956
957 dsi_bus_lock();
958
752 r = taal_power_on(dssdev); 959 r = taal_power_on(dssdev);
960
961 dsi_bus_unlock();
962
753 if (r) 963 if (r)
754 goto err; 964 goto err;
755 965
966 if (panel_data->use_esd_check)
967 queue_delayed_work(td->esd_wq, &td->esd_work,
968 TAAL_ESD_CHECK_PERIOD);
969
756 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 970 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
757 971
758 mutex_unlock(&td->lock); 972 mutex_unlock(&td->lock);
@@ -772,9 +986,15 @@ static void taal_disable(struct omap_dss_device *dssdev)
772 986
773 mutex_lock(&td->lock); 987 mutex_lock(&td->lock);
774 988
989 cancel_delayed_work(&td->esd_work);
990
991 dsi_bus_lock();
992
775 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 993 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
776 taal_power_off(dssdev); 994 taal_power_off(dssdev);
777 995
996 dsi_bus_unlock();
997
778 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 998 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
779 999
780 mutex_unlock(&td->lock); 1000 mutex_unlock(&td->lock);
@@ -794,7 +1014,14 @@ static int taal_suspend(struct omap_dss_device *dssdev)
794 goto err; 1014 goto err;
795 } 1015 }
796 1016
1017 cancel_delayed_work(&td->esd_work);
1018
1019 dsi_bus_lock();
1020
797 taal_power_off(dssdev); 1021 taal_power_off(dssdev);
1022
1023 dsi_bus_unlock();
1024
798 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 1025 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
799 1026
800 mutex_unlock(&td->lock); 1027 mutex_unlock(&td->lock);
@@ -808,6 +1035,7 @@ err:
808static int taal_resume(struct omap_dss_device *dssdev) 1035static int taal_resume(struct omap_dss_device *dssdev)
809{ 1036{
810 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1037 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1038 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
811 int r; 1039 int r;
812 1040
813 dev_dbg(&dssdev->dev, "resume\n"); 1041 dev_dbg(&dssdev->dev, "resume\n");
@@ -819,8 +1047,20 @@ static int taal_resume(struct omap_dss_device *dssdev)
819 goto err; 1047 goto err;
820 } 1048 }
821 1049
1050 dsi_bus_lock();
1051
822 r = taal_power_on(dssdev); 1052 r = taal_power_on(dssdev);
823 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 1053
1054 dsi_bus_unlock();
1055
1056 if (r) {
1057 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
1058 } else {
1059 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
1060 if (panel_data->use_esd_check)
1061 queue_delayed_work(td->esd_wq, &td->esd_work,
1062 TAAL_ESD_CHECK_PERIOD);
1063 }
824 1064
825 mutex_unlock(&td->lock); 1065 mutex_unlock(&td->lock);
826 1066
@@ -837,10 +1077,52 @@ static void taal_framedone_cb(int err, void *data)
837 dsi_bus_unlock(); 1077 dsi_bus_unlock();
838} 1078}
839 1079
1080static irqreturn_t taal_te_isr(int irq, void *data)
1081{
1082 struct omap_dss_device *dssdev = data;
1083 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1084 int old;
1085 int r;
1086
1087 old = atomic_cmpxchg(&td->do_update, 1, 0);
1088
1089 if (old) {
1090 cancel_delayed_work(&td->te_timeout_work);
1091
1092 r = omap_dsi_update(dssdev, TCH,
1093 td->update_region.x,
1094 td->update_region.y,
1095 td->update_region.w,
1096 td->update_region.h,
1097 taal_framedone_cb, dssdev);
1098 if (r)
1099 goto err;
1100 }
1101
1102 return IRQ_HANDLED;
1103err:
1104 dev_err(&dssdev->dev, "start update failed\n");
1105 dsi_bus_unlock();
1106 return IRQ_HANDLED;
1107}
1108
1109static void taal_te_timeout_work_callback(struct work_struct *work)
1110{
1111 struct taal_data *td = container_of(work, struct taal_data,
1112 te_timeout_work.work);
1113 struct omap_dss_device *dssdev = td->dssdev;
1114
1115 dev_err(&dssdev->dev, "TE not received for 250ms!\n");
1116
1117 atomic_set(&td->do_update, 0);
1118 dsi_bus_unlock();
1119}
1120
840static int taal_update(struct omap_dss_device *dssdev, 1121static int taal_update(struct omap_dss_device *dssdev,
841 u16 x, u16 y, u16 w, u16 h) 1122 u16 x, u16 y, u16 w, u16 h)
842{ 1123{
843 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1124 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1125 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
844 int r; 1126 int r;
845 1127
846 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); 1128 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
@@ -853,7 +1135,7 @@ static int taal_update(struct omap_dss_device *dssdev,
853 goto err; 1135 goto err;
854 } 1136 }
855 1137
856 r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h); 1138 r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true);
857 if (r) 1139 if (r)
858 goto err; 1140 goto err;
859 1141
@@ -861,10 +1143,21 @@ static int taal_update(struct omap_dss_device *dssdev,
861 if (r) 1143 if (r)
862 goto err; 1144 goto err;
863 1145
864 r = omap_dsi_update(dssdev, TCH, x, y, w, h, 1146 if (td->te_enabled && panel_data->use_ext_te) {
865 taal_framedone_cb, dssdev); 1147 td->update_region.x = x;
866 if (r) 1148 td->update_region.y = y;
867 goto err; 1149 td->update_region.w = w;
1150 td->update_region.h = h;
1151 barrier();
1152 schedule_delayed_work(&td->te_timeout_work,
1153 msecs_to_jiffies(250));
1154 atomic_set(&td->do_update, 1);
1155 } else {
1156 r = omap_dsi_update(dssdev, TCH, x, y, w, h,
1157 taal_framedone_cb, dssdev);
1158 if (r)
1159 goto err;
1160 }
868 1161
869 /* note: no bus_unlock here. unlock is in framedone_cb */ 1162 /* note: no bus_unlock here. unlock is in framedone_cb */
870 mutex_unlock(&td->lock); 1163 mutex_unlock(&td->lock);
@@ -894,20 +1187,19 @@ static int taal_sync(struct omap_dss_device *dssdev)
894static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) 1187static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
895{ 1188{
896 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1189 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1190 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
897 int r; 1191 int r;
898 1192
899 td->te_enabled = enable;
900
901 if (enable) 1193 if (enable)
902 r = taal_dcs_write_1(DCS_TEAR_ON, 0); 1194 r = taal_dcs_write_1(DCS_TEAR_ON, 0);
903 else 1195 else
904 r = taal_dcs_write_0(DCS_TEAR_OFF); 1196 r = taal_dcs_write_0(DCS_TEAR_OFF);
905 1197
906 omapdss_dsi_enable_te(dssdev, enable); 1198 if (!panel_data->use_ext_te)
1199 omapdss_dsi_enable_te(dssdev, enable);
907 1200
908 /* XXX for some reason, DSI TE breaks if we don't wait here. 1201 if (td->panel_config->sleep.enable_te)
909 * Panel bug? Needs more studying */ 1202 msleep(td->panel_config->sleep.enable_te);
910 msleep(100);
911 1203
912 return r; 1204 return r;
913} 1205}
@@ -918,10 +1210,26 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
918 int r; 1210 int r;
919 1211
920 mutex_lock(&td->lock); 1212 mutex_lock(&td->lock);
1213
1214 if (td->te_enabled == enable)
1215 goto end;
1216
921 dsi_bus_lock(); 1217 dsi_bus_lock();
922 1218
923 r = _taal_enable_te(dssdev, enable); 1219 if (td->enabled) {
1220 r = _taal_enable_te(dssdev, enable);
1221 if (r)
1222 goto err;
1223 }
1224
1225 td->te_enabled = enable;
1226
1227 dsi_bus_unlock();
1228end:
1229 mutex_unlock(&td->lock);
924 1230
1231 return 0;
1232err:
925 dsi_bus_unlock(); 1233 dsi_bus_unlock();
926 mutex_unlock(&td->lock); 1234 mutex_unlock(&td->lock);
927 1235
@@ -948,6 +1256,10 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
948 dev_dbg(&dssdev->dev, "rotate %d\n", rotate); 1256 dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
949 1257
950 mutex_lock(&td->lock); 1258 mutex_lock(&td->lock);
1259
1260 if (td->rotate == rotate)
1261 goto end;
1262
951 dsi_bus_lock(); 1263 dsi_bus_lock();
952 1264
953 if (td->enabled) { 1265 if (td->enabled) {
@@ -959,6 +1271,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
959 td->rotate = rotate; 1271 td->rotate = rotate;
960 1272
961 dsi_bus_unlock(); 1273 dsi_bus_unlock();
1274end:
962 mutex_unlock(&td->lock); 1275 mutex_unlock(&td->lock);
963 return 0; 1276 return 0;
964err: 1277err:
@@ -987,6 +1300,10 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
987 dev_dbg(&dssdev->dev, "mirror %d\n", enable); 1300 dev_dbg(&dssdev->dev, "mirror %d\n", enable);
988 1301
989 mutex_lock(&td->lock); 1302 mutex_lock(&td->lock);
1303
1304 if (td->mirror == enable)
1305 goto end;
1306
990 dsi_bus_lock(); 1307 dsi_bus_lock();
991 if (td->enabled) { 1308 if (td->enabled) {
992 r = taal_set_addr_mode(td->rotate, enable); 1309 r = taal_set_addr_mode(td->rotate, enable);
@@ -997,6 +1314,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
997 td->mirror = enable; 1314 td->mirror = enable;
998 1315
999 dsi_bus_unlock(); 1316 dsi_bus_unlock();
1317end:
1000 mutex_unlock(&td->lock); 1318 mutex_unlock(&td->lock);
1001 return 0; 1319 return 0;
1002err: 1320err:
@@ -1024,23 +1342,30 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
1024 int r; 1342 int r;
1025 1343
1026 mutex_lock(&td->lock); 1344 mutex_lock(&td->lock);
1345
1346 if (!td->enabled) {
1347 r = -ENODEV;
1348 goto err1;
1349 }
1350
1027 dsi_bus_lock(); 1351 dsi_bus_lock();
1028 1352
1029 r = taal_dcs_read_1(DCS_GET_ID1, &id1); 1353 r = taal_dcs_read_1(DCS_GET_ID1, &id1);
1030 if (r) 1354 if (r)
1031 goto err; 1355 goto err2;
1032 r = taal_dcs_read_1(DCS_GET_ID2, &id2); 1356 r = taal_dcs_read_1(DCS_GET_ID2, &id2);
1033 if (r) 1357 if (r)
1034 goto err; 1358 goto err2;
1035 r = taal_dcs_read_1(DCS_GET_ID3, &id3); 1359 r = taal_dcs_read_1(DCS_GET_ID3, &id3);
1036 if (r) 1360 if (r)
1037 goto err; 1361 goto err2;
1038 1362
1039 dsi_bus_unlock(); 1363 dsi_bus_unlock();
1040 mutex_unlock(&td->lock); 1364 mutex_unlock(&td->lock);
1041 return 0; 1365 return 0;
1042err: 1366err2:
1043 dsi_bus_unlock(); 1367 dsi_bus_unlock();
1368err1:
1044 mutex_unlock(&td->lock); 1369 mutex_unlock(&td->lock);
1045 return r; 1370 return r;
1046} 1371}
@@ -1128,6 +1453,7 @@ static void taal_esd_work(struct work_struct *work)
1128 struct taal_data *td = container_of(work, struct taal_data, 1453 struct taal_data *td = container_of(work, struct taal_data,
1129 esd_work.work); 1454 esd_work.work);
1130 struct omap_dss_device *dssdev = td->dssdev; 1455 struct omap_dss_device *dssdev = td->dssdev;
1456 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1131 u8 state1, state2; 1457 u8 state1, state2;
1132 int r; 1458 int r;
1133 1459
@@ -1168,7 +1494,7 @@ static void taal_esd_work(struct work_struct *work)
1168 } 1494 }
1169 /* Self-diagnostics result is also shown on TE GPIO line. We need 1495 /* Self-diagnostics result is also shown on TE GPIO line. We need
1170 * to re-enable TE after self diagnostics */ 1496 * to re-enable TE after self diagnostics */
1171 if (td->use_ext_te && td->te_enabled) { 1497 if (td->te_enabled && panel_data->use_ext_te) {
1172 r = taal_dcs_write_1(DCS_TEAR_ON, 0); 1498 r = taal_dcs_write_1(DCS_TEAR_ON, 0);
1173 if (r) 1499 if (r)
1174 goto err; 1500 goto err;
@@ -1184,6 +1510,7 @@ err:
1184 dev_err(&dssdev->dev, "performing LCD reset\n"); 1510 dev_err(&dssdev->dev, "performing LCD reset\n");
1185 1511
1186 taal_power_off(dssdev); 1512 taal_power_off(dssdev);
1513 taal_hw_reset(dssdev);
1187 taal_power_on(dssdev); 1514 taal_power_on(dssdev);
1188 1515
1189 dsi_bus_unlock(); 1516 dsi_bus_unlock();
diff --git a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
index fa434ca6e4b7..526e906c8a6c 100644
--- a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
+++ b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
@@ -46,6 +46,9 @@ static int toppoly_tdo_panel_power_on(struct omap_dss_device *dssdev)
46{ 46{
47 int r; 47 int r;
48 48
49 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
50 return 0;
51
49 r = omapdss_dpi_display_enable(dssdev); 52 r = omapdss_dpi_display_enable(dssdev);
50 if (r) 53 if (r)
51 goto err0; 54 goto err0;
@@ -65,6 +68,9 @@ err0:
65 68
66static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev) 69static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev)
67{ 70{
71 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
72 return;
73
68 if (dssdev->platform_disable) 74 if (dssdev->platform_disable)
69 dssdev->platform_disable(dssdev); 75 dssdev->platform_disable(dssdev);
70 76
@@ -73,8 +79,12 @@ static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev)
73 79
74static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev) 80static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev)
75{ 81{
76 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | 82 dssdev->panel.config = OMAP_DSS_LCD_TFT |
77 OMAP_DSS_LCD_IHS; 83 OMAP_DSS_LCD_IVS |
84 OMAP_DSS_LCD_IHS |
85 OMAP_DSS_LCD_IPC |
86 OMAP_DSS_LCD_ONOFF;
87
78 dssdev->panel.timings = toppoly_tdo_panel_timings; 88 dssdev->panel.timings = toppoly_tdo_panel_timings;
79 89
80 return 0; 90 return 0;
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index e866e76b13d0..dbe9d43b4850 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -269,6 +269,9 @@ static int tpo_td043_power_on(struct omap_dss_device *dssdev)
269 int nreset_gpio = dssdev->reset_gpio; 269 int nreset_gpio = dssdev->reset_gpio;
270 int r; 270 int r;
271 271
272 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
273 return 0;
274
272 r = omapdss_dpi_display_enable(dssdev); 275 r = omapdss_dpi_display_enable(dssdev);
273 if (r) 276 if (r)
274 goto err0; 277 goto err0;
@@ -308,6 +311,9 @@ static void tpo_td043_power_off(struct omap_dss_device *dssdev)
308 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); 311 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
309 int nreset_gpio = dssdev->reset_gpio; 312 int nreset_gpio = dssdev->reset_gpio;
310 313
314 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
315 return;
316
311 tpo_td043_write(tpo_td043->spi, 3, 317 tpo_td043_write(tpo_td043->spi, 3,
312 TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM); 318 TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
313 319
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index d71b5d9d71b1..7db17b5e570c 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,5 +1,5 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2omapdss-y := core.o dss.o dispc.o display.o manager.o overlay.o 2omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o
3omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 3omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
4omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 4omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
5omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 5omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index b3a498f22d36..8e89f6049280 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -37,6 +37,7 @@
37#include <plat/clock.h> 37#include <plat/clock.h>
38 38
39#include "dss.h" 39#include "dss.h"
40#include "dss_features.h"
40 41
41static struct { 42static struct {
42 struct platform_device *pdev; 43 struct platform_device *pdev;
@@ -502,6 +503,8 @@ static int omap_dss_probe(struct platform_device *pdev)
502 503
503 core.pdev = pdev; 504 core.pdev = pdev;
504 505
506 dss_features_init();
507
505 dss_init_overlay_managers(pdev); 508 dss_init_overlay_managers(pdev);
506 dss_init_overlays(pdev); 509 dss_init_overlays(pdev);
507 510
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index e777e352dbcd..fa40fa59a9ac 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -31,6 +31,7 @@
31#include <linux/seq_file.h> 31#include <linux/seq_file.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/workqueue.h> 33#include <linux/workqueue.h>
34#include <linux/hardirq.h>
34 35
35#include <plat/sram.h> 36#include <plat/sram.h>
36#include <plat/clock.h> 37#include <plat/clock.h>
@@ -38,6 +39,7 @@
38#include <plat/display.h> 39#include <plat/display.h>
39 40
40#include "dss.h" 41#include "dss.h"
42#include "dss_features.h"
41 43
42/* DISPC */ 44/* DISPC */
43#define DISPC_BASE 0x48050400 45#define DISPC_BASE 0x48050400
@@ -138,6 +140,22 @@ struct omap_dispc_isr_data {
138 u32 mask; 140 u32 mask;
139}; 141};
140 142
143struct dispc_h_coef {
144 s8 hc4;
145 s8 hc3;
146 u8 hc2;
147 s8 hc1;
148 s8 hc0;
149};
150
151struct dispc_v_coef {
152 s8 vc22;
153 s8 vc2;
154 u8 vc1;
155 s8 vc0;
156 s8 vc00;
157};
158
141#define REG_GET(idx, start, end) \ 159#define REG_GET(idx, start, end) \
142 FLD_GET(dispc_read_reg(idx), start, end) 160 FLD_GET(dispc_read_reg(idx), start, end)
143 161
@@ -335,7 +353,7 @@ void dispc_save_context(void)
335void dispc_restore_context(void) 353void dispc_restore_context(void)
336{ 354{
337 RR(SYSCONFIG); 355 RR(SYSCONFIG);
338 RR(IRQENABLE); 356 /*RR(IRQENABLE);*/
339 /*RR(CONTROL);*/ 357 /*RR(CONTROL);*/
340 RR(CONFIG); 358 RR(CONFIG);
341 RR(DEFAULT_COLOR0); 359 RR(DEFAULT_COLOR0);
@@ -472,6 +490,15 @@ void dispc_restore_context(void)
472 490
473 /* enable last, because LCD & DIGIT enable are here */ 491 /* enable last, because LCD & DIGIT enable are here */
474 RR(CONTROL); 492 RR(CONTROL);
493
494 /* clear spurious SYNC_LOST_DIGIT interrupts */
495 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
496
497 /*
498 * enable last so IRQs won't trigger before
499 * the context is fully restored
500 */
501 RR(IRQENABLE);
475} 502}
476 503
477#undef SR 504#undef SR
@@ -554,106 +581,77 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
554 int vscaleup, int five_taps) 581 int vscaleup, int five_taps)
555{ 582{
556 /* Coefficients for horizontal up-sampling */ 583 /* Coefficients for horizontal up-sampling */
557 static const u32 coef_hup[8] = { 584 static const struct dispc_h_coef coef_hup[8] = {
558 0x00800000, 585 { 0, 0, 128, 0, 0 },
559 0x0D7CF800, 586 { -1, 13, 124, -8, 0 },
560 0x1E70F5FF, 587 { -2, 30, 112, -11, -1 },
561 0x335FF5FE, 588 { -5, 51, 95, -11, -2 },
562 0xF74949F7, 589 { 0, -9, 73, 73, -9 },
563 0xF55F33FB, 590 { -2, -11, 95, 51, -5 },
564 0xF5701EFE, 591 { -1, -11, 112, 30, -2 },
565 0xF87C0DFF, 592 { 0, -8, 124, 13, -1 },
566 }; 593 };
567 594
568 /* Coefficients for horizontal down-sampling */ 595 /* Coefficients for vertical up-sampling */
569 static const u32 coef_hdown[8] = { 596 static const struct dispc_v_coef coef_vup_3tap[8] = {
570 0x24382400, 597 { 0, 0, 128, 0, 0 },
571 0x28371FFE, 598 { 0, 3, 123, 2, 0 },
572 0x2C361BFB, 599 { 0, 12, 111, 5, 0 },
573 0x303516F9, 600 { 0, 32, 89, 7, 0 },
574 0x11343311, 601 { 0, 0, 64, 64, 0 },
575 0x1635300C, 602 { 0, 7, 89, 32, 0 },
576 0x1B362C08, 603 { 0, 5, 111, 12, 0 },
577 0x1F372804, 604 { 0, 2, 123, 3, 0 },
578 }; 605 };
579 606
580 /* Coefficients for horizontal and vertical up-sampling */ 607 static const struct dispc_v_coef coef_vup_5tap[8] = {
581 static const u32 coef_hvup[2][8] = { 608 { 0, 0, 128, 0, 0 },
582 { 609 { -1, 13, 124, -8, 0 },
583 0x00800000, 610 { -2, 30, 112, -11, -1 },
584 0x037B02FF, 611 { -5, 51, 95, -11, -2 },
585 0x0C6F05FE, 612 { 0, -9, 73, 73, -9 },
586 0x205907FB, 613 { -2, -11, 95, 51, -5 },
587 0x00404000, 614 { -1, -11, 112, 30, -2 },
588 0x075920FE, 615 { 0, -8, 124, 13, -1 },
589 0x056F0CFF,
590 0x027B0300,
591 },
592 {
593 0x00800000,
594 0x0D7CF8FF,
595 0x1E70F5FE,
596 0x335FF5FB,
597 0xF7404000,
598 0xF55F33FE,
599 0xF5701EFF,
600 0xF87C0D00,
601 },
602 }; 616 };
603 617
604 /* Coefficients for horizontal and vertical down-sampling */ 618 /* Coefficients for horizontal down-sampling */
605 static const u32 coef_hvdown[2][8] = { 619 static const struct dispc_h_coef coef_hdown[8] = {
606 { 620 { 0, 36, 56, 36, 0 },
607 0x24382400, 621 { 4, 40, 55, 31, -2 },
608 0x28391F04, 622 { 8, 44, 54, 27, -5 },
609 0x2D381B08, 623 { 12, 48, 53, 22, -7 },
610 0x3237170C, 624 { -9, 17, 52, 51, 17 },
611 0x123737F7, 625 { -7, 22, 53, 48, 12 },
612 0x173732F9, 626 { -5, 27, 54, 44, 8 },
613 0x1B382DFB, 627 { -2, 31, 55, 40, 4 },
614 0x1F3928FE,
615 },
616 {
617 0x24382400,
618 0x28371F04,
619 0x2C361B08,
620 0x3035160C,
621 0x113433F7,
622 0x163530F9,
623 0x1B362CFB,
624 0x1F3728FE,
625 },
626 }; 628 };
627 629
628 /* Coefficients for vertical up-sampling */ 630 /* Coefficients for vertical down-sampling */
629 static const u32 coef_vup[8] = { 631 static const struct dispc_v_coef coef_vdown_3tap[8] = {
630 0x00000000, 632 { 0, 36, 56, 36, 0 },
631 0x0000FF00, 633 { 0, 40, 57, 31, 0 },
632 0x0000FEFF, 634 { 0, 45, 56, 27, 0 },
633 0x0000FBFE, 635 { 0, 50, 55, 23, 0 },
634 0x000000F7, 636 { 0, 18, 55, 55, 0 },
635 0x0000FEFB, 637 { 0, 23, 55, 50, 0 },
636 0x0000FFFE, 638 { 0, 27, 56, 45, 0 },
637 0x000000FF, 639 { 0, 31, 57, 40, 0 },
638 }; 640 };
639 641
640 642 static const struct dispc_v_coef coef_vdown_5tap[8] = {
641 /* Coefficients for vertical down-sampling */ 643 { 0, 36, 56, 36, 0 },
642 static const u32 coef_vdown[8] = { 644 { 4, 40, 55, 31, -2 },
643 0x00000000, 645 { 8, 44, 54, 27, -5 },
644 0x000004FE, 646 { 12, 48, 53, 22, -7 },
645 0x000008FB, 647 { -9, 17, 52, 51, 17 },
646 0x00000CF9, 648 { -7, 22, 53, 48, 12 },
647 0x0000F711, 649 { -5, 27, 54, 44, 8 },
648 0x0000F90C, 650 { -2, 31, 55, 40, 4 },
649 0x0000FB08,
650 0x0000FE04,
651 }; 651 };
652 652
653 const u32 *h_coef; 653 const struct dispc_h_coef *h_coef;
654 const u32 *hv_coef; 654 const struct dispc_v_coef *v_coef;
655 const u32 *hv_coef_mod;
656 const u32 *v_coef;
657 int i; 655 int i;
658 656
659 if (hscaleup) 657 if (hscaleup)
@@ -661,47 +659,34 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
661 else 659 else
662 h_coef = coef_hdown; 660 h_coef = coef_hdown;
663 661
664 if (vscaleup) { 662 if (vscaleup)
665 hv_coef = coef_hvup[five_taps]; 663 v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
666 v_coef = coef_vup; 664 else
667 665 v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
668 if (hscaleup)
669 hv_coef_mod = NULL;
670 else
671 hv_coef_mod = coef_hvdown[five_taps];
672 } else {
673 hv_coef = coef_hvdown[five_taps];
674 v_coef = coef_vdown;
675
676 if (hscaleup)
677 hv_coef_mod = coef_hvup[five_taps];
678 else
679 hv_coef_mod = NULL;
680 }
681 666
682 for (i = 0; i < 8; i++) { 667 for (i = 0; i < 8; i++) {
683 u32 h, hv; 668 u32 h, hv;
684 669
685 h = h_coef[i]; 670 h = FLD_VAL(h_coef[i].hc0, 7, 0)
686 671 | FLD_VAL(h_coef[i].hc1, 15, 8)
687 hv = hv_coef[i]; 672 | FLD_VAL(h_coef[i].hc2, 23, 16)
688 673 | FLD_VAL(h_coef[i].hc3, 31, 24);
689 if (hv_coef_mod) { 674 hv = FLD_VAL(h_coef[i].hc4, 7, 0)
690 hv &= 0xffffff00; 675 | FLD_VAL(v_coef[i].vc0, 15, 8)
691 hv |= (hv_coef_mod[i] & 0xff); 676 | FLD_VAL(v_coef[i].vc1, 23, 16)
692 } 677 | FLD_VAL(v_coef[i].vc2, 31, 24);
693 678
694 _dispc_write_firh_reg(plane, i, h); 679 _dispc_write_firh_reg(plane, i, h);
695 _dispc_write_firhv_reg(plane, i, hv); 680 _dispc_write_firhv_reg(plane, i, hv);
696 } 681 }
697 682
698 if (!five_taps) 683 if (five_taps) {
699 return; 684 for (i = 0; i < 8; i++) {
700 685 u32 v;
701 for (i = 0; i < 8; i++) { 686 v = FLD_VAL(v_coef[i].vc00, 7, 0)
702 u32 v; 687 | FLD_VAL(v_coef[i].vc22, 15, 8);
703 v = v_coef[i]; 688 _dispc_write_firv_reg(plane, i, v);
704 _dispc_write_firv_reg(plane, i, v); 689 }
705 } 690 }
706} 691}
707 692
@@ -790,12 +775,12 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
790 775
791static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) 776static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
792{ 777{
793 778 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
794 BUG_ON(plane == OMAP_DSS_VIDEO1);
795
796 if (cpu_is_omap24xx())
797 return; 779 return;
798 780
781 BUG_ON(!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
782 plane == OMAP_DSS_VIDEO1);
783
799 if (plane == OMAP_DSS_GFX) 784 if (plane == OMAP_DSS_GFX)
800 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); 785 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
801 else if (plane == OMAP_DSS_VIDEO2) 786 else if (plane == OMAP_DSS_VIDEO2)
@@ -965,17 +950,14 @@ static void dispc_read_plane_fifo_sizes(void)
965 DISPC_VID_FIFO_SIZE_STATUS(1) }; 950 DISPC_VID_FIFO_SIZE_STATUS(1) };
966 u32 size; 951 u32 size;
967 int plane; 952 int plane;
953 u8 start, end;
968 954
969 enable_clocks(1); 955 enable_clocks(1);
970 956
971 for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { 957 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
972 if (cpu_is_omap24xx())
973 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
974 else if (cpu_is_omap34xx())
975 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
976 else
977 BUG();
978 958
959 for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
960 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), start, end);
979 dispc.fifo_size[plane] = size; 961 dispc.fifo_size[plane] = size;
980 } 962 }
981 963
@@ -992,6 +974,8 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
992 const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, 974 const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
993 DISPC_VID_FIFO_THRESHOLD(0), 975 DISPC_VID_FIFO_THRESHOLD(0),
994 DISPC_VID_FIFO_THRESHOLD(1) }; 976 DISPC_VID_FIFO_THRESHOLD(1) };
977 u8 hi_start, hi_end, lo_start, lo_end;
978
995 enable_clocks(1); 979 enable_clocks(1);
996 980
997 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", 981 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
@@ -1000,12 +984,12 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
1000 REG_GET(ftrs_reg[plane], 27, 16), 984 REG_GET(ftrs_reg[plane], 27, 16),
1001 low, high); 985 low, high);
1002 986
1003 if (cpu_is_omap24xx()) 987 dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
1004 dispc_write_reg(ftrs_reg[plane], 988 dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
1005 FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0)); 989
1006 else 990 dispc_write_reg(ftrs_reg[plane],
1007 dispc_write_reg(ftrs_reg[plane], 991 FLD_VAL(high, hi_start, hi_end) |
1008 FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0)); 992 FLD_VAL(low, lo_start, lo_end));
1009 993
1010 enable_clocks(0); 994 enable_clocks(0);
1011} 995}
@@ -1025,13 +1009,16 @@ static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
1025 u32 val; 1009 u32 val;
1026 const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0), 1010 const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
1027 DISPC_VID_FIR(1) }; 1011 DISPC_VID_FIR(1) };
1012 u8 hinc_start, hinc_end, vinc_start, vinc_end;
1028 1013
1029 BUG_ON(plane == OMAP_DSS_GFX); 1014 BUG_ON(plane == OMAP_DSS_GFX);
1030 1015
1031 if (cpu_is_omap24xx()) 1016 dss_feat_get_reg_field(FEAT_REG_FIRHINC, &hinc_start, &hinc_end);
1032 val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0); 1017 dss_feat_get_reg_field(FEAT_REG_FIRVINC, &vinc_start, &vinc_end);
1033 else 1018
1034 val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0); 1019 val = FLD_VAL(vinc, vinc_start, vinc_end) |
1020 FLD_VAL(hinc, hinc_start, hinc_end);
1021
1035 dispc_write_reg(fir_reg[plane-1], val); 1022 dispc_write_reg(fir_reg[plane-1], val);
1036} 1023}
1037 1024
@@ -1557,6 +1544,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
1557 case OMAP_DSS_COLOR_ARGB16: 1544 case OMAP_DSS_COLOR_ARGB16:
1558 case OMAP_DSS_COLOR_ARGB32: 1545 case OMAP_DSS_COLOR_ARGB32:
1559 case OMAP_DSS_COLOR_RGBA32: 1546 case OMAP_DSS_COLOR_RGBA32:
1547 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
1548 return -EINVAL;
1560 case OMAP_DSS_COLOR_RGBX32: 1549 case OMAP_DSS_COLOR_RGBX32:
1561 if (cpu_is_omap24xx()) 1550 if (cpu_is_omap24xx())
1562 return -EINVAL; 1551 return -EINVAL;
@@ -1597,9 +1586,10 @@ static int _dispc_setup_plane(enum omap_plane plane,
1597 case OMAP_DSS_COLOR_ARGB16: 1586 case OMAP_DSS_COLOR_ARGB16:
1598 case OMAP_DSS_COLOR_ARGB32: 1587 case OMAP_DSS_COLOR_ARGB32:
1599 case OMAP_DSS_COLOR_RGBA32: 1588 case OMAP_DSS_COLOR_RGBA32:
1600 if (cpu_is_omap24xx()) 1589 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
1601 return -EINVAL; 1590 return -EINVAL;
1602 if (plane == OMAP_DSS_VIDEO1) 1591 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
1592 plane == OMAP_DSS_VIDEO1)
1603 return -EINVAL; 1593 return -EINVAL;
1604 break; 1594 break;
1605 1595
@@ -1992,7 +1982,7 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable)
1992} 1982}
1993void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) 1983void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
1994{ 1984{
1995 if (cpu_is_omap24xx()) 1985 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
1996 return; 1986 return;
1997 1987
1998 enable_clocks(1); 1988 enable_clocks(1);
@@ -2006,7 +1996,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
2006{ 1996{
2007 bool enabled; 1997 bool enabled;
2008 1998
2009 if (cpu_is_omap24xx()) 1999 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
2010 return false; 2000 return false;
2011 2001
2012 enable_clocks(1); 2002 enable_clocks(1);
@@ -3019,7 +3009,7 @@ void dispc_fake_vsync_irq(void)
3019 u32 irqstatus = DISPC_IRQ_VSYNC; 3009 u32 irqstatus = DISPC_IRQ_VSYNC;
3020 int i; 3010 int i;
3021 3011
3022 local_irq_disable(); 3012 WARN_ON(!in_interrupt());
3023 3013
3024 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 3014 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3025 struct omap_dispc_isr_data *isr_data; 3015 struct omap_dispc_isr_data *isr_data;
@@ -3031,8 +3021,6 @@ void dispc_fake_vsync_irq(void)
3031 if (isr_data->mask & irqstatus) 3021 if (isr_data->mask & irqstatus)
3032 isr_data->isr(isr_data->arg, irqstatus); 3022 isr_data->isr(isr_data->arg, irqstatus);
3033 } 3023 }
3034
3035 local_irq_enable();
3036} 3024}
3037#endif 3025#endif
3038 3026
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index ef8c8529dda2..22dd7a474f79 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -82,6 +82,9 @@ static ssize_t display_upd_mode_store(struct device *dev,
82 int val, r; 82 int val, r;
83 enum omap_dss_update_mode mode; 83 enum omap_dss_update_mode mode;
84 84
85 if (!dssdev->driver->set_update_mode)
86 return -EINVAL;
87
85 val = simple_strtoul(buf, NULL, 10); 88 val = simple_strtoul(buf, NULL, 10);
86 89
87 switch (val) { 90 switch (val) {
@@ -343,7 +346,6 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
343 case OMAP_DISPLAY_TYPE_VENC: 346 case OMAP_DISPLAY_TYPE_VENC:
344 case OMAP_DISPLAY_TYPE_SDI: 347 case OMAP_DISPLAY_TYPE_SDI:
345 return 24; 348 return 24;
346 return 24;
347 default: 349 default:
348 BUG(); 350 BUG();
349 } 351 }
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 3af207b2bde3..aa4f7a5fae29 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -165,6 +165,14 @@ struct dsi_reg { u16 idx; };
165#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) 165#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
166#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) 166#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
167#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) 167#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
168#define DSI_CIO_IRQ_ERROR_MASK \
169 (DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \
170 DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \
171 DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRCONTROL1 | \
172 DSI_CIO_IRQ_ERRCONTROL2 | DSI_CIO_IRQ_ERRCONTROL3 | \
173 DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \
174 DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \
175 DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3)
168 176
169#define DSI_DT_DCS_SHORT_WRITE_0 0x05 177#define DSI_DT_DCS_SHORT_WRITE_0 0x05
170#define DSI_DT_DCS_SHORT_WRITE_1 0x15 178#define DSI_DT_DCS_SHORT_WRITE_1 0x15
@@ -232,13 +240,15 @@ static struct
232 unsigned pll_locked; 240 unsigned pll_locked;
233 241
234 struct completion bta_completion; 242 struct completion bta_completion;
243 void (*bta_callback)(void);
235 244
236 int update_channel; 245 int update_channel;
237 struct dsi_update_region update_region; 246 struct dsi_update_region update_region;
238 247
239 bool te_enabled; 248 bool te_enabled;
240 249
241 struct work_struct framedone_work; 250 struct workqueue_struct *workqueue;
251
242 void (*framedone_callback)(int, void *); 252 void (*framedone_callback)(int, void *);
243 void *framedone_data; 253 void *framedone_data;
244 254
@@ -509,9 +519,13 @@ void dsi_irq_handler(void)
509 dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); 519 dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]);
510#endif 520#endif
511 521
512 if (vcstatus & DSI_VC_IRQ_BTA) 522 if (vcstatus & DSI_VC_IRQ_BTA) {
513 complete(&dsi.bta_completion); 523 complete(&dsi.bta_completion);
514 524
525 if (dsi.bta_callback)
526 dsi.bta_callback();
527 }
528
515 if (vcstatus & DSI_VC_IRQ_ERROR_MASK) { 529 if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
516 DSSERR("DSI VC(%d) error, vc irqstatus %x\n", 530 DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
517 i, vcstatus); 531 i, vcstatus);
@@ -536,8 +550,12 @@ void dsi_irq_handler(void)
536 /* flush posted write */ 550 /* flush posted write */
537 dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); 551 dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
538 552
539 DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); 553 if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
540 print_irq_status_cio(ciostatus); 554 DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
555 print_irq_status_cio(ciostatus);
556 } else if (debug_irq) {
557 print_irq_status_cio(ciostatus);
558 }
541 } 559 }
542 560
543 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); 561 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
@@ -584,11 +602,8 @@ static void _dsi_initialize_irq(void)
584 for (i = 0; i < 4; ++i) 602 for (i = 0; i < 4; ++i)
585 dsi_write_reg(DSI_VC_IRQENABLE(i), l); 603 dsi_write_reg(DSI_VC_IRQENABLE(i), l);
586 604
587 /* XXX zonda responds incorrectly, causing control error: 605 l = DSI_CIO_IRQ_ERROR_MASK;
588 Exit from LP-ESC mode to LP11 uses wrong transition states on the 606 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l);
589 data lines LP0 and LN0. */
590 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
591 -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
592} 607}
593 608
594static u32 dsi_get_errors(void) 609static u32 dsi_get_errors(void)
@@ -1098,6 +1113,7 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
1098 if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) { 1113 if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
1099 DSSERR("PLL not coming out of reset.\n"); 1114 DSSERR("PLL not coming out of reset.\n");
1100 r = -ENODEV; 1115 r = -ENODEV;
1116 dispc_pck_free_enable(0);
1101 goto err1; 1117 goto err1;
1102 } 1118 }
1103 1119
@@ -1740,42 +1756,52 @@ static void dsi_vc_initial_config(int channel)
1740 dsi.vc[channel].mode = DSI_VC_MODE_L4; 1756 dsi.vc[channel].mode = DSI_VC_MODE_L4;
1741} 1757}
1742 1758
1743static void dsi_vc_config_l4(int channel) 1759static int dsi_vc_config_l4(int channel)
1744{ 1760{
1745 if (dsi.vc[channel].mode == DSI_VC_MODE_L4) 1761 if (dsi.vc[channel].mode == DSI_VC_MODE_L4)
1746 return; 1762 return 0;
1747 1763
1748 DSSDBGF("%d", channel); 1764 DSSDBGF("%d", channel);
1749 1765
1750 dsi_vc_enable(channel, 0); 1766 dsi_vc_enable(channel, 0);
1751 1767
1752 if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ 1768 /* VC_BUSY */
1769 if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) {
1753 DSSERR("vc(%d) busy when trying to config for L4\n", channel); 1770 DSSERR("vc(%d) busy when trying to config for L4\n", channel);
1771 return -EIO;
1772 }
1754 1773
1755 REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ 1774 REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
1756 1775
1757 dsi_vc_enable(channel, 1); 1776 dsi_vc_enable(channel, 1);
1758 1777
1759 dsi.vc[channel].mode = DSI_VC_MODE_L4; 1778 dsi.vc[channel].mode = DSI_VC_MODE_L4;
1779
1780 return 0;
1760} 1781}
1761 1782
1762static void dsi_vc_config_vp(int channel) 1783static int dsi_vc_config_vp(int channel)
1763{ 1784{
1764 if (dsi.vc[channel].mode == DSI_VC_MODE_VP) 1785 if (dsi.vc[channel].mode == DSI_VC_MODE_VP)
1765 return; 1786 return 0;
1766 1787
1767 DSSDBGF("%d", channel); 1788 DSSDBGF("%d", channel);
1768 1789
1769 dsi_vc_enable(channel, 0); 1790 dsi_vc_enable(channel, 0);
1770 1791
1771 if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ 1792 /* VC_BUSY */
1793 if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) {
1772 DSSERR("vc(%d) busy when trying to config for VP\n", channel); 1794 DSSERR("vc(%d) busy when trying to config for VP\n", channel);
1795 return -EIO;
1796 }
1773 1797
1774 REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ 1798 REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
1775 1799
1776 dsi_vc_enable(channel, 1); 1800 dsi_vc_enable(channel, 1);
1777 1801
1778 dsi.vc[channel].mode = DSI_VC_MODE_VP; 1802 dsi.vc[channel].mode = DSI_VC_MODE_VP;
1803
1804 return 0;
1779} 1805}
1780 1806
1781 1807
@@ -1854,19 +1880,19 @@ static u16 dsi_vc_flush_receive_data(int channel)
1854 u32 val; 1880 u32 val;
1855 u8 dt; 1881 u8 dt;
1856 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); 1882 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
1857 DSSDBG("\trawval %#08x\n", val); 1883 DSSERR("\trawval %#08x\n", val);
1858 dt = FLD_GET(val, 5, 0); 1884 dt = FLD_GET(val, 5, 0);
1859 if (dt == DSI_DT_RX_ACK_WITH_ERR) { 1885 if (dt == DSI_DT_RX_ACK_WITH_ERR) {
1860 u16 err = FLD_GET(val, 23, 8); 1886 u16 err = FLD_GET(val, 23, 8);
1861 dsi_show_rx_ack_with_err(err); 1887 dsi_show_rx_ack_with_err(err);
1862 } else if (dt == DSI_DT_RX_SHORT_READ_1) { 1888 } else if (dt == DSI_DT_RX_SHORT_READ_1) {
1863 DSSDBG("\tDCS short response, 1 byte: %#x\n", 1889 DSSERR("\tDCS short response, 1 byte: %#x\n",
1864 FLD_GET(val, 23, 8)); 1890 FLD_GET(val, 23, 8));
1865 } else if (dt == DSI_DT_RX_SHORT_READ_2) { 1891 } else if (dt == DSI_DT_RX_SHORT_READ_2) {
1866 DSSDBG("\tDCS short response, 2 byte: %#x\n", 1892 DSSERR("\tDCS short response, 2 byte: %#x\n",
1867 FLD_GET(val, 23, 8)); 1893 FLD_GET(val, 23, 8));
1868 } else if (dt == DSI_DT_RX_DCS_LONG_READ) { 1894 } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
1869 DSSDBG("\tDCS long response, len %d\n", 1895 DSSERR("\tDCS long response, len %d\n",
1870 FLD_GET(val, 23, 8)); 1896 FLD_GET(val, 23, 8));
1871 dsi_vc_flush_long_data(channel); 1897 dsi_vc_flush_long_data(channel);
1872 } else { 1898 } else {
@@ -2087,6 +2113,13 @@ int dsi_vc_dcs_write(int channel, u8 *data, int len)
2087 if (r) 2113 if (r)
2088 goto err; 2114 goto err;
2089 2115
2116 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
2117 DSSERR("rx fifo not empty after write, dumping data:\n");
2118 dsi_vc_flush_receive_data(channel);
2119 r = -EIO;
2120 goto err;
2121 }
2122
2090 return 0; 2123 return 0;
2091err: 2124err:
2092 DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n", 2125 DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n",
@@ -2233,11 +2266,12 @@ int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data)
2233} 2266}
2234EXPORT_SYMBOL(dsi_vc_dcs_read_1); 2267EXPORT_SYMBOL(dsi_vc_dcs_read_1);
2235 2268
2236int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data) 2269int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2)
2237{ 2270{
2271 u8 buf[2];
2238 int r; 2272 int r;
2239 2273
2240 r = dsi_vc_dcs_read(channel, dcs_cmd, (u8 *)data, 2); 2274 r = dsi_vc_dcs_read(channel, dcs_cmd, buf, 2);
2241 2275
2242 if (r < 0) 2276 if (r < 0)
2243 return r; 2277 return r;
@@ -2245,231 +2279,122 @@ int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data)
2245 if (r != 2) 2279 if (r != 2)
2246 return -EIO; 2280 return -EIO;
2247 2281
2282 *data1 = buf[0];
2283 *data2 = buf[1];
2284
2248 return 0; 2285 return 0;
2249} 2286}
2250EXPORT_SYMBOL(dsi_vc_dcs_read_2); 2287EXPORT_SYMBOL(dsi_vc_dcs_read_2);
2251 2288
2252int dsi_vc_set_max_rx_packet_size(int channel, u16 len) 2289int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
2253{ 2290{
2254 int r; 2291 return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
2255 r = dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
2256 len, 0); 2292 len, 0);
2257
2258 if (r)
2259 return r;
2260
2261 r = dsi_vc_send_bta_sync(channel);
2262
2263 return r;
2264} 2293}
2265EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); 2294EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
2266 2295
2267static void dsi_set_lp_rx_timeout(unsigned long ns) 2296static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16)
2268{ 2297{
2269 u32 r;
2270 unsigned x4, x16;
2271 unsigned long fck; 2298 unsigned long fck;
2272 unsigned long ticks; 2299 unsigned long total_ticks;
2300 u32 r;
2273 2301
2274 /* ticks in DSI_FCK */ 2302 BUG_ON(ticks > 0x1fff);
2275 2303
2304 /* ticks in DSI_FCK */
2276 fck = dsi_fclk_rate(); 2305 fck = dsi_fclk_rate();
2277 ticks = (fck / 1000 / 1000) * ns / 1000;
2278 x4 = 0;
2279 x16 = 0;
2280
2281 if (ticks > 0x1fff) {
2282 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2283 x4 = 1;
2284 x16 = 0;
2285 }
2286
2287 if (ticks > 0x1fff) {
2288 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2289 x4 = 0;
2290 x16 = 1;
2291 }
2292
2293 if (ticks > 0x1fff) {
2294 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2295 x4 = 1;
2296 x16 = 1;
2297 }
2298
2299 if (ticks > 0x1fff) {
2300 DSSWARN("LP_TX_TO over limit, setting it to max\n");
2301 ticks = 0x1fff;
2302 x4 = 1;
2303 x16 = 1;
2304 }
2305 2306
2306 r = dsi_read_reg(DSI_TIMING2); 2307 r = dsi_read_reg(DSI_TIMING2);
2307 r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ 2308 r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
2308 r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */ 2309 r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */
2309 r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */ 2310 r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */
2310 r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ 2311 r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
2311 dsi_write_reg(DSI_TIMING2, r); 2312 dsi_write_reg(DSI_TIMING2, r);
2312 2313
2313 DSSDBG("LP_RX_TO %lu ns (%#lx ticks%s%s)\n", 2314 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
2314 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / 2315
2315 (fck / 1000 / 1000), 2316 DSSDBG("LP_RX_TO %lu ticks (%#x%s%s) = %lu ns\n",
2316 ticks, x4 ? " x4" : "", x16 ? " x16" : ""); 2317 total_ticks,
2318 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
2319 (total_ticks * 1000) / (fck / 1000 / 1000));
2317} 2320}
2318 2321
2319static void dsi_set_ta_timeout(unsigned long ns) 2322static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16)
2320{ 2323{
2321 u32 r;
2322 unsigned x8, x16;
2323 unsigned long fck; 2324 unsigned long fck;
2324 unsigned long ticks; 2325 unsigned long total_ticks;
2326 u32 r;
2327
2328 BUG_ON(ticks > 0x1fff);
2325 2329
2326 /* ticks in DSI_FCK */ 2330 /* ticks in DSI_FCK */
2327 fck = dsi_fclk_rate(); 2331 fck = dsi_fclk_rate();
2328 ticks = (fck / 1000 / 1000) * ns / 1000;
2329 x8 = 0;
2330 x16 = 0;
2331
2332 if (ticks > 0x1fff) {
2333 ticks = (fck / 1000 / 1000) * ns / 1000 / 8;
2334 x8 = 1;
2335 x16 = 0;
2336 }
2337
2338 if (ticks > 0x1fff) {
2339 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2340 x8 = 0;
2341 x16 = 1;
2342 }
2343
2344 if (ticks > 0x1fff) {
2345 ticks = (fck / 1000 / 1000) * ns / 1000 / (8 * 16);
2346 x8 = 1;
2347 x16 = 1;
2348 }
2349
2350 if (ticks > 0x1fff) {
2351 DSSWARN("TA_TO over limit, setting it to max\n");
2352 ticks = 0x1fff;
2353 x8 = 1;
2354 x16 = 1;
2355 }
2356 2332
2357 r = dsi_read_reg(DSI_TIMING1); 2333 r = dsi_read_reg(DSI_TIMING1);
2358 r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ 2334 r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
2359 r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */ 2335 r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */
2360 r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */ 2336 r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */
2361 r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ 2337 r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
2362 dsi_write_reg(DSI_TIMING1, r); 2338 dsi_write_reg(DSI_TIMING1, r);
2363 2339
2364 DSSDBG("TA_TO %lu ns (%#lx ticks%s%s)\n", 2340 total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1);
2365 (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) / 2341
2366 (fck / 1000 / 1000), 2342 DSSDBG("TA_TO %lu ticks (%#x%s%s) = %lu ns\n",
2367 ticks, x8 ? " x8" : "", x16 ? " x16" : ""); 2343 total_ticks,
2344 ticks, x8 ? " x8" : "", x16 ? " x16" : "",
2345 (total_ticks * 1000) / (fck / 1000 / 1000));
2368} 2346}
2369 2347
2370static void dsi_set_stop_state_counter(unsigned long ns) 2348static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16)
2371{ 2349{
2372 u32 r;
2373 unsigned x4, x16;
2374 unsigned long fck; 2350 unsigned long fck;
2375 unsigned long ticks; 2351 unsigned long total_ticks;
2352 u32 r;
2376 2353
2377 /* ticks in DSI_FCK */ 2354 BUG_ON(ticks > 0x1fff);
2378 2355
2356 /* ticks in DSI_FCK */
2379 fck = dsi_fclk_rate(); 2357 fck = dsi_fclk_rate();
2380 ticks = (fck / 1000 / 1000) * ns / 1000;
2381 x4 = 0;
2382 x16 = 0;
2383
2384 if (ticks > 0x1fff) {
2385 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2386 x4 = 1;
2387 x16 = 0;
2388 }
2389
2390 if (ticks > 0x1fff) {
2391 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2392 x4 = 0;
2393 x16 = 1;
2394 }
2395
2396 if (ticks > 0x1fff) {
2397 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2398 x4 = 1;
2399 x16 = 1;
2400 }
2401
2402 if (ticks > 0x1fff) {
2403 DSSWARN("STOP_STATE_COUNTER_IO over limit, "
2404 "setting it to max\n");
2405 ticks = 0x1fff;
2406 x4 = 1;
2407 x16 = 1;
2408 }
2409 2358
2410 r = dsi_read_reg(DSI_TIMING1); 2359 r = dsi_read_reg(DSI_TIMING1);
2411 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ 2360 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
2412 r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */ 2361 r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */
2413 r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */ 2362 r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */
2414 r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ 2363 r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
2415 dsi_write_reg(DSI_TIMING1, r); 2364 dsi_write_reg(DSI_TIMING1, r);
2416 2365
2417 DSSDBG("STOP_STATE_COUNTER %lu ns (%#lx ticks%s%s)\n", 2366 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
2418 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / 2367
2419 (fck / 1000 / 1000), 2368 DSSDBG("STOP_STATE_COUNTER %lu ticks (%#x%s%s) = %lu ns\n",
2420 ticks, x4 ? " x4" : "", x16 ? " x16" : ""); 2369 total_ticks,
2370 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
2371 (total_ticks * 1000) / (fck / 1000 / 1000));
2421} 2372}
2422 2373
2423static void dsi_set_hs_tx_timeout(unsigned long ns) 2374static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16)
2424{ 2375{
2425 u32 r;
2426 unsigned x4, x16;
2427 unsigned long fck; 2376 unsigned long fck;
2428 unsigned long ticks; 2377 unsigned long total_ticks;
2378 u32 r;
2429 2379
2430 /* ticks in TxByteClkHS */ 2380 BUG_ON(ticks > 0x1fff);
2431 2381
2382 /* ticks in TxByteClkHS */
2432 fck = dsi_get_txbyteclkhs(); 2383 fck = dsi_get_txbyteclkhs();
2433 ticks = (fck / 1000 / 1000) * ns / 1000;
2434 x4 = 0;
2435 x16 = 0;
2436
2437 if (ticks > 0x1fff) {
2438 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2439 x4 = 1;
2440 x16 = 0;
2441 }
2442
2443 if (ticks > 0x1fff) {
2444 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2445 x4 = 0;
2446 x16 = 1;
2447 }
2448
2449 if (ticks > 0x1fff) {
2450 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2451 x4 = 1;
2452 x16 = 1;
2453 }
2454
2455 if (ticks > 0x1fff) {
2456 DSSWARN("HS_TX_TO over limit, setting it to max\n");
2457 ticks = 0x1fff;
2458 x4 = 1;
2459 x16 = 1;
2460 }
2461 2384
2462 r = dsi_read_reg(DSI_TIMING2); 2385 r = dsi_read_reg(DSI_TIMING2);
2463 r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ 2386 r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
2464 r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */ 2387 r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */
2465 r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */ 2388 r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */
2466 r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ 2389 r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
2467 dsi_write_reg(DSI_TIMING2, r); 2390 dsi_write_reg(DSI_TIMING2, r);
2468 2391
2469 DSSDBG("HS_TX_TO %lu ns (%#lx ticks%s%s)\n", 2392 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
2470 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / 2393
2471 (fck / 1000 / 1000), 2394 DSSDBG("HS_TX_TO %lu ticks (%#x%s%s) = %lu ns\n",
2472 ticks, x4 ? " x4" : "", x16 ? " x16" : ""); 2395 total_ticks,
2396 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
2397 (total_ticks * 1000) / (fck / 1000 / 1000));
2473} 2398}
2474static int dsi_proto_config(struct omap_dss_device *dssdev) 2399static int dsi_proto_config(struct omap_dss_device *dssdev)
2475{ 2400{
@@ -2487,10 +2412,10 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
2487 DSI_FIFO_SIZE_32); 2412 DSI_FIFO_SIZE_32);
2488 2413
2489 /* XXX what values for the timeouts? */ 2414 /* XXX what values for the timeouts? */
2490 dsi_set_stop_state_counter(1000); 2415 dsi_set_stop_state_counter(0x1000, false, false);
2491 dsi_set_ta_timeout(6400000); 2416 dsi_set_ta_timeout(0x1fff, true, true);
2492 dsi_set_lp_rx_timeout(48000); 2417 dsi_set_lp_rx_timeout(0x1fff, true, true);
2493 dsi_set_hs_tx_timeout(1000000); 2418 dsi_set_hs_tx_timeout(0x1fff, true, true);
2494 2419
2495 switch (dssdev->ctrl.pixel_size) { 2420 switch (dssdev->ctrl.pixel_size) {
2496 case 16: 2421 case 16:
@@ -2759,6 +2684,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2759 unsigned packet_payload; 2684 unsigned packet_payload;
2760 unsigned packet_len; 2685 unsigned packet_len;
2761 u32 l; 2686 u32 l;
2687 int r;
2762 const unsigned channel = dsi.update_channel; 2688 const unsigned channel = dsi.update_channel;
2763 /* line buffer is 1024 x 24bits */ 2689 /* line buffer is 1024 x 24bits */
2764 /* XXX: for some reason using full buffer size causes considerable TX 2690 /* XXX: for some reason using full buffer size causes considerable TX
@@ -2809,8 +2735,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2809 2735
2810 dsi_perf_mark_start(); 2736 dsi_perf_mark_start();
2811 2737
2812 schedule_delayed_work(&dsi.framedone_timeout_work, 2738 r = queue_delayed_work(dsi.workqueue, &dsi.framedone_timeout_work,
2813 msecs_to_jiffies(250)); 2739 msecs_to_jiffies(250));
2740 BUG_ON(r == 0);
2814 2741
2815 dss_start_update(dssdev); 2742 dss_start_update(dssdev);
2816 2743
@@ -2834,62 +2761,70 @@ static void dsi_te_timeout(unsigned long arg)
2834} 2761}
2835#endif 2762#endif
2836 2763
2837static void dsi_framedone_timeout_work_callback(struct work_struct *work) 2764static void dsi_handle_framedone(int error)
2838{ 2765{
2839 int r;
2840 const int channel = dsi.update_channel; 2766 const int channel = dsi.update_channel;
2841 2767
2842 DSSERR("Framedone not received for 250ms!\n"); 2768 cancel_delayed_work(&dsi.framedone_timeout_work);
2769
2770 dsi_vc_disable_bta_irq(channel);
2843 2771
2844 /* SIDLEMODE back to smart-idle */ 2772 /* SIDLEMODE back to smart-idle */
2845 dispc_enable_sidle(); 2773 dispc_enable_sidle();
2846 2774
2775 dsi.bta_callback = NULL;
2776
2847 if (dsi.te_enabled) { 2777 if (dsi.te_enabled) {
2848 /* enable LP_RX_TO again after the TE */ 2778 /* enable LP_RX_TO again after the TE */
2849 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ 2779 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
2850 } 2780 }
2851 2781
2852 /* Send BTA after the frame. We need this for the TE to work, as TE
2853 * trigger is only sent for BTAs without preceding packet. Thus we need
2854 * to BTA after the pixel packets so that next BTA will cause TE
2855 * trigger.
2856 *
2857 * This is not needed when TE is not in use, but we do it anyway to
2858 * make sure that the transfer has been completed. It would be more
2859 * optimal, but more complex, to wait only just before starting next
2860 * transfer. */
2861 r = dsi_vc_send_bta_sync(channel);
2862 if (r)
2863 DSSERR("BTA after framedone failed\n");
2864
2865 /* RX_FIFO_NOT_EMPTY */ 2782 /* RX_FIFO_NOT_EMPTY */
2866 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { 2783 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
2867 DSSERR("Received error during frame transfer:\n"); 2784 DSSERR("Received error during frame transfer:\n");
2868 dsi_vc_flush_receive_data(channel); 2785 dsi_vc_flush_receive_data(channel);
2786 if (!error)
2787 error = -EIO;
2869 } 2788 }
2870 2789
2871 dsi.framedone_callback(-ETIMEDOUT, dsi.framedone_data); 2790 dsi.framedone_callback(error, dsi.framedone_data);
2791
2792 if (!error)
2793 dsi_perf_show("DISPC");
2872} 2794}
2873 2795
2874static void dsi_framedone_irq_callback(void *data, u32 mask) 2796static void dsi_framedone_timeout_work_callback(struct work_struct *work)
2875{ 2797{
2876 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and 2798 /* XXX While extremely unlikely, we could get FRAMEDONE interrupt after
2877 * turns itself off. However, DSI still has the pixels in its buffers, 2799 * 250ms which would conflict with this timeout work. What should be
2878 * and is sending the data. 2800 * done is first cancel the transfer on the HW, and then cancel the
2879 */ 2801 * possibly scheduled framedone work. However, cancelling the transfer
2802 * on the HW is buggy, and would probably require resetting the whole
2803 * DSI */
2880 2804
2881 /* SIDLEMODE back to smart-idle */ 2805 DSSERR("Framedone not received for 250ms!\n");
2882 dispc_enable_sidle();
2883 2806
2884 schedule_work(&dsi.framedone_work); 2807 dsi_handle_framedone(-ETIMEDOUT);
2885} 2808}
2886 2809
2887static void dsi_handle_framedone(void) 2810static void dsi_framedone_bta_callback(void)
2811{
2812 dsi_handle_framedone(0);
2813
2814#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
2815 dispc_fake_vsync_irq();
2816#endif
2817}
2818
2819static void dsi_framedone_irq_callback(void *data, u32 mask)
2888{ 2820{
2889 int r;
2890 const int channel = dsi.update_channel; 2821 const int channel = dsi.update_channel;
2822 int r;
2891 2823
2892 DSSDBG("FRAMEDONE\n"); 2824 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
2825 * turns itself off. However, DSI still has the pixels in its buffers,
2826 * and is sending the data.
2827 */
2893 2828
2894 if (dsi.te_enabled) { 2829 if (dsi.te_enabled) {
2895 /* enable LP_RX_TO again after the TE */ 2830 /* enable LP_RX_TO again after the TE */
@@ -2904,37 +2839,30 @@ static void dsi_handle_framedone(void)
2904 * This is not needed when TE is not in use, but we do it anyway to 2839 * This is not needed when TE is not in use, but we do it anyway to
2905 * make sure that the transfer has been completed. It would be more 2840 * make sure that the transfer has been completed. It would be more
2906 * optimal, but more complex, to wait only just before starting next 2841 * optimal, but more complex, to wait only just before starting next
2907 * transfer. */ 2842 * transfer.
2908 r = dsi_vc_send_bta_sync(channel); 2843 *
2909 if (r) 2844 * Also, as there's no interrupt telling when the transfer has been
2910 DSSERR("BTA after framedone failed\n"); 2845 * done and the channel could be reconfigured, the only way is to
2911 2846 * busyloop until TE_SIZE is zero. With BTA we can do this
2912 /* RX_FIFO_NOT_EMPTY */ 2847 * asynchronously.
2913 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { 2848 * */
2914 DSSERR("Received error during frame transfer:\n");
2915 dsi_vc_flush_receive_data(channel);
2916 }
2917
2918#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
2919 dispc_fake_vsync_irq();
2920#endif
2921}
2922
2923static void dsi_framedone_work_callback(struct work_struct *work)
2924{
2925 DSSDBGF();
2926 2849
2927 cancel_delayed_work_sync(&dsi.framedone_timeout_work); 2850 dsi.bta_callback = dsi_framedone_bta_callback;
2928 2851
2929 dsi_handle_framedone(); 2852 barrier();
2930 2853
2931 dsi_perf_show("DISPC"); 2854 dsi_vc_enable_bta_irq(channel);
2932 2855
2933 dsi.framedone_callback(0, dsi.framedone_data); 2856 r = dsi_vc_send_bta(channel);
2857 if (r) {
2858 DSSERR("BTA after framedone failed\n");
2859 dsi_handle_framedone(-EIO);
2860 }
2934} 2861}
2935 2862
2936int omap_dsi_prepare_update(struct omap_dss_device *dssdev, 2863int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
2937 u16 *x, u16 *y, u16 *w, u16 *h) 2864 u16 *x, u16 *y, u16 *w, u16 *h,
2865 bool enlarge_update_area)
2938{ 2866{
2939 u16 dw, dh; 2867 u16 dw, dh;
2940 2868
@@ -2958,7 +2886,8 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
2958 dsi_perf_mark_setup(); 2886 dsi_perf_mark_setup();
2959 2887
2960 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 2888 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2961 dss_setup_partial_planes(dssdev, x, y, w, h); 2889 dss_setup_partial_planes(dssdev, x, y, w, h,
2890 enlarge_update_area);
2962 dispc_set_lcd_size(*w, *h); 2891 dispc_set_lcd_size(*w, *h);
2963 } 2892 }
2964 2893
@@ -2973,6 +2902,12 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
2973{ 2902{
2974 dsi.update_channel = channel; 2903 dsi.update_channel = channel;
2975 2904
2905 /* OMAP DSS cannot send updates of odd widths.
2906 * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON
2907 * here to make sure we catch erroneous updates. Otherwise we'll only
2908 * see rather obscure HW error happening, as DSS halts. */
2909 BUG_ON(x % 2 == 1);
2910
2976 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 2911 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2977 dsi.framedone_callback = callback; 2912 dsi.framedone_callback = callback;
2978 dsi.framedone_data = data; 2913 dsi.framedone_data = data;
@@ -2985,7 +2920,12 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
2985 2920
2986 dsi_update_screen_dispc(dssdev, x, y, w, h); 2921 dsi_update_screen_dispc(dssdev, x, y, w, h);
2987 } else { 2922 } else {
2988 dsi_update_screen_l4(dssdev, x, y, w, h); 2923 int r;
2924
2925 r = dsi_update_screen_l4(dssdev, x, y, w, h);
2926 if (r)
2927 return r;
2928
2989 dsi_perf_show("L4"); 2929 dsi_perf_show("L4");
2990 callback(0, data); 2930 callback(0, data);
2991 } 2931 }
@@ -3048,8 +2988,10 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
3048 cinfo.regm3 = dssdev->phy.dsi.div.regm3; 2988 cinfo.regm3 = dssdev->phy.dsi.div.regm3;
3049 cinfo.regm4 = dssdev->phy.dsi.div.regm4; 2989 cinfo.regm4 = dssdev->phy.dsi.div.regm4;
3050 r = dsi_calc_clock_rates(&cinfo); 2990 r = dsi_calc_clock_rates(&cinfo);
3051 if (r) 2991 if (r) {
2992 DSSERR("Failed to calc dsi clocks\n");
3052 return r; 2993 return r;
2994 }
3053 2995
3054 r = dsi_pll_set_clock_div(&cinfo); 2996 r = dsi_pll_set_clock_div(&cinfo);
3055 if (r) { 2997 if (r) {
@@ -3147,6 +3089,13 @@ err0:
3147 3089
3148static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) 3090static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
3149{ 3091{
3092 /* disable interface */
3093 dsi_if_enable(0);
3094 dsi_vc_enable(0, 0);
3095 dsi_vc_enable(1, 0);
3096 dsi_vc_enable(2, 0);
3097 dsi_vc_enable(3, 0);
3098
3150 dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); 3099 dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
3151 dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); 3100 dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
3152 dsi_complexio_uninit(); 3101 dsi_complexio_uninit();
@@ -3257,7 +3206,7 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
3257 burst_size_bytes = 16 * 32 / 8; 3206 burst_size_bytes = 16 * 32 / 8;
3258 3207
3259 *fifo_high = fifo_size - burst_size_bytes; 3208 *fifo_high = fifo_size - burst_size_bytes;
3260 *fifo_low = fifo_size - burst_size_bytes * 8; 3209 *fifo_low = fifo_size - burst_size_bytes * 2;
3261} 3210}
3262 3211
3263int dsi_init_display(struct omap_dss_device *dssdev) 3212int dsi_init_display(struct omap_dss_device *dssdev)
@@ -3274,6 +3223,18 @@ int dsi_init_display(struct omap_dss_device *dssdev)
3274 return 0; 3223 return 0;
3275} 3224}
3276 3225
3226void dsi_wait_dsi1_pll_active(void)
3227{
3228 if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1)
3229 DSSERR("DSI1 PLL clock not active\n");
3230}
3231
3232void dsi_wait_dsi2_pll_active(void)
3233{
3234 if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1)
3235 DSSERR("DSI2 PLL clock not active\n");
3236}
3237
3277int dsi_init(struct platform_device *pdev) 3238int dsi_init(struct platform_device *pdev)
3278{ 3239{
3279 u32 rev; 3240 u32 rev;
@@ -3292,7 +3253,10 @@ int dsi_init(struct platform_device *pdev)
3292 mutex_init(&dsi.lock); 3253 mutex_init(&dsi.lock);
3293 sema_init(&dsi.bus_lock, 1); 3254 sema_init(&dsi.bus_lock, 1);
3294 3255
3295 INIT_WORK(&dsi.framedone_work, dsi_framedone_work_callback); 3256 dsi.workqueue = create_singlethread_workqueue("dsi");
3257 if (dsi.workqueue == NULL)
3258 return -ENOMEM;
3259
3296 INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work, 3260 INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work,
3297 dsi_framedone_timeout_work_callback); 3261 dsi_framedone_timeout_work_callback);
3298 3262
@@ -3310,7 +3274,6 @@ int dsi_init(struct platform_device *pdev)
3310 3274
3311 dsi.vdds_dsi_reg = dss_get_vdds_dsi(); 3275 dsi.vdds_dsi_reg = dss_get_vdds_dsi();
3312 if (IS_ERR(dsi.vdds_dsi_reg)) { 3276 if (IS_ERR(dsi.vdds_dsi_reg)) {
3313 iounmap(dsi.base);
3314 DSSERR("can't get VDDS_DSI regulator\n"); 3277 DSSERR("can't get VDDS_DSI regulator\n");
3315 r = PTR_ERR(dsi.vdds_dsi_reg); 3278 r = PTR_ERR(dsi.vdds_dsi_reg);
3316 goto err2; 3279 goto err2;
@@ -3328,6 +3291,7 @@ int dsi_init(struct platform_device *pdev)
3328err2: 3291err2:
3329 iounmap(dsi.base); 3292 iounmap(dsi.base);
3330err1: 3293err1:
3294 destroy_workqueue(dsi.workqueue);
3331 return r; 3295 return r;
3332} 3296}
3333 3297
@@ -3335,6 +3299,8 @@ void dsi_exit(void)
3335{ 3299{
3336 iounmap(dsi.base); 3300 iounmap(dsi.base);
3337 3301
3302 destroy_workqueue(dsi.workqueue);
3303
3338 DSSDBG("omap_dsi_exit\n"); 3304 DSSDBG("omap_dsi_exit\n");
3339} 3305}
3340 3306
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 24b18258654f..77c3621c9171 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -265,6 +265,9 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
265 265
266 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; 266 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
267 267
268 if (clk_src == DSS_SRC_DSI1_PLL_FCLK)
269 dsi_wait_dsi1_pll_active();
270
268 REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ 271 REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */
269 272
270 dss.dispc_clk_source = clk_src; 273 dss.dispc_clk_source = clk_src;
@@ -279,6 +282,9 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
279 282
280 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; 283 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
281 284
285 if (clk_src == DSS_SRC_DSI2_PLL_FCLK)
286 dsi_wait_dsi2_pll_active();
287
282 REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ 288 REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
283 289
284 dss.dsi_clk_source = clk_src; 290 dss.dsi_clk_source = clk_src;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 786f433fd571..5c7940d5f282 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -199,7 +199,8 @@ int dss_init_overlay_managers(struct platform_device *pdev);
199void dss_uninit_overlay_managers(struct platform_device *pdev); 199void dss_uninit_overlay_managers(struct platform_device *pdev);
200int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); 200int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
201void dss_setup_partial_planes(struct omap_dss_device *dssdev, 201void dss_setup_partial_planes(struct omap_dss_device *dssdev,
202 u16 *x, u16 *y, u16 *w, u16 *h); 202 u16 *x, u16 *y, u16 *w, u16 *h,
203 bool enlarge_update_area);
203void dss_start_update(struct omap_dss_device *dssdev); 204void dss_start_update(struct omap_dss_device *dssdev);
204 205
205/* overlay */ 206/* overlay */
@@ -281,6 +282,8 @@ void dsi_pll_uninit(void);
281void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, 282void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
282 u32 fifo_size, enum omap_burst_size *burst_size, 283 u32 fifo_size, enum omap_burst_size *burst_size,
283 u32 *fifo_low, u32 *fifo_high); 284 u32 *fifo_low, u32 *fifo_high);
285void dsi_wait_dsi1_pll_active(void);
286void dsi_wait_dsi2_pll_active(void);
284#else 287#else
285static inline int dsi_init(struct platform_device *pdev) 288static inline int dsi_init(struct platform_device *pdev)
286{ 289{
@@ -289,6 +292,12 @@ static inline int dsi_init(struct platform_device *pdev)
289static inline void dsi_exit(void) 292static inline void dsi_exit(void)
290{ 293{
291} 294}
295static inline void dsi_wait_dsi1_pll_active(void)
296{
297}
298static inline void dsi_wait_dsi2_pll_active(void)
299{
300}
292#endif 301#endif
293 302
294/* DPI */ 303/* DPI */
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
new file mode 100644
index 000000000000..867f68de125f
--- /dev/null
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -0,0 +1,191 @@
1/*
2 * linux/drivers/video/omap2/dss/dss_features.c
3 *
4 * Copyright (C) 2010 Texas Instruments
5 * Author: Archit Taneja <archit@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <linux/types.h>
22#include <linux/err.h>
23#include <linux/slab.h>
24
25#include <plat/display.h>
26#include <plat/cpu.h>
27
28#include "dss_features.h"
29
30/* Defines a generic omap register field */
31struct dss_reg_field {
32 enum dss_feat_reg_field id;
33 u8 start, end;
34};
35
36struct omap_dss_features {
37 const struct dss_reg_field *reg_fields;
38 const int num_reg_fields;
39
40 const u32 has_feature;
41
42 const int num_mgrs;
43 const int num_ovls;
44 const enum omap_display_type *supported_displays;
45 const enum omap_color_mode *supported_color_modes;
46};
47
48/* This struct is assigned to one of the below during initialization */
49static struct omap_dss_features *omap_current_dss_features;
50
51static const struct dss_reg_field omap2_dss_reg_fields[] = {
52 { FEAT_REG_FIRHINC, 11, 0 },
53 { FEAT_REG_FIRVINC, 27, 16 },
54 { FEAT_REG_FIFOLOWTHRESHOLD, 8, 0 },
55 { FEAT_REG_FIFOHIGHTHRESHOLD, 24, 16 },
56 { FEAT_REG_FIFOSIZE, 8, 0 },
57};
58
59static const struct dss_reg_field omap3_dss_reg_fields[] = {
60 { FEAT_REG_FIRHINC, 12, 0 },
61 { FEAT_REG_FIRVINC, 28, 16 },
62 { FEAT_REG_FIFOLOWTHRESHOLD, 11, 0 },
63 { FEAT_REG_FIFOHIGHTHRESHOLD, 27, 16 },
64 { FEAT_REG_FIFOSIZE, 10, 0 },
65};
66
67static const enum omap_display_type omap2_dss_supported_displays[] = {
68 /* OMAP_DSS_CHANNEL_LCD */
69 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
70 OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
71
72 /* OMAP_DSS_CHANNEL_DIGIT */
73 OMAP_DISPLAY_TYPE_VENC,
74};
75
76static const enum omap_display_type omap3_dss_supported_displays[] = {
77 /* OMAP_DSS_CHANNEL_LCD */
78 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
79 OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
80
81 /* OMAP_DSS_CHANNEL_DIGIT */
82 OMAP_DISPLAY_TYPE_VENC,
83};
84
85static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
86 /* OMAP_DSS_GFX */
87 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
88 OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
89 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
90 OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
91
92 /* OMAP_DSS_VIDEO1 */
93 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
94 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
95 OMAP_DSS_COLOR_UYVY,
96
97 /* OMAP_DSS_VIDEO2 */
98 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
99 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
100 OMAP_DSS_COLOR_UYVY,
101};
102
103static const enum omap_color_mode omap3_dss_supported_color_modes[] = {
104 /* OMAP_DSS_GFX */
105 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
106 OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
107 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
108 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
109 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
110 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
111
112 /* OMAP_DSS_VIDEO1 */
113 OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
114 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
115 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
116
117 /* OMAP_DSS_VIDEO2 */
118 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
119 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
120 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
121 OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
122 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
123};
124
125/* OMAP2 DSS Features */
126static struct omap_dss_features omap2_dss_features = {
127 .reg_fields = omap2_dss_reg_fields,
128 .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
129
130 .num_mgrs = 2,
131 .num_ovls = 3,
132 .supported_displays = omap2_dss_supported_displays,
133 .supported_color_modes = omap2_dss_supported_color_modes,
134};
135
136/* OMAP3 DSS Features */
137static struct omap_dss_features omap3_dss_features = {
138 .reg_fields = omap3_dss_reg_fields,
139 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
140
141 .has_feature = FEAT_GLOBAL_ALPHA,
142
143 .num_mgrs = 2,
144 .num_ovls = 3,
145 .supported_displays = omap3_dss_supported_displays,
146 .supported_color_modes = omap3_dss_supported_color_modes,
147};
148
149/* Functions returning values related to a DSS feature */
150int dss_feat_get_num_mgrs(void)
151{
152 return omap_current_dss_features->num_mgrs;
153}
154
155int dss_feat_get_num_ovls(void)
156{
157 return omap_current_dss_features->num_ovls;
158}
159
160enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel)
161{
162 return omap_current_dss_features->supported_displays[channel];
163}
164
165enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
166{
167 return omap_current_dss_features->supported_color_modes[plane];
168}
169
170/* DSS has_feature check */
171bool dss_has_feature(enum dss_feat_id id)
172{
173 return omap_current_dss_features->has_feature & id;
174}
175
176void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
177{
178 if (id >= omap_current_dss_features->num_reg_fields)
179 BUG();
180
181 *start = omap_current_dss_features->reg_fields[id].start;
182 *end = omap_current_dss_features->reg_fields[id].end;
183}
184
185void dss_features_init(void)
186{
187 if (cpu_is_omap24xx())
188 omap_current_dss_features = &omap2_dss_features;
189 else
190 omap_current_dss_features = &omap3_dss_features;
191}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
new file mode 100644
index 000000000000..cb231eaa9b31
--- /dev/null
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -0,0 +1,50 @@
1/*
2 * linux/drivers/video/omap2/dss/dss_features.h
3 *
4 * Copyright (C) 2010 Texas Instruments
5 * Author: Archit Taneja <archit@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef __OMAP2_DSS_FEATURES_H
21#define __OMAP2_DSS_FEATURES_H
22
23#define MAX_DSS_MANAGERS 2
24#define MAX_DSS_OVERLAYS 3
25
26/* DSS has feature id */
27enum dss_feat_id {
28 FEAT_GLOBAL_ALPHA = 1 << 0,
29 FEAT_GLOBAL_ALPHA_VID1 = 1 << 1,
30};
31
32/* DSS register field id */
33enum dss_feat_reg_field {
34 FEAT_REG_FIRHINC,
35 FEAT_REG_FIRVINC,
36 FEAT_REG_FIFOHIGHTHRESHOLD,
37 FEAT_REG_FIFOLOWTHRESHOLD,
38 FEAT_REG_FIFOSIZE,
39};
40
41/* DSS Feature Functions */
42int dss_feat_get_num_mgrs(void);
43int dss_feat_get_num_ovls(void);
44enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
45enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
46
47bool dss_has_feature(enum dss_feat_id id);
48void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
49void dss_features_init(void);
50#endif
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 9e1fbe531bf0..545e9b9a4d92 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -33,6 +33,7 @@
33#include <plat/cpu.h> 33#include <plat/cpu.h>
34 34
35#include "dss.h" 35#include "dss.h"
36#include "dss_features.h"
36 37
37static int num_managers; 38static int num_managers;
38static struct list_head manager_list; 39static struct list_head manager_list;
@@ -440,12 +441,16 @@ struct manager_cache_data {
440 441
441 /* manual update region */ 442 /* manual update region */
442 u16 x, y, w, h; 443 u16 x, y, w, h;
444
445 /* enlarge the update area if the update area contains scaled
446 * overlays */
447 bool enlarge_update_area;
443}; 448};
444 449
445static struct { 450static struct {
446 spinlock_t lock; 451 spinlock_t lock;
447 struct overlay_cache_data overlay_cache[3]; 452 struct overlay_cache_data overlay_cache[MAX_DSS_OVERLAYS];
448 struct manager_cache_data manager_cache[2]; 453 struct manager_cache_data manager_cache[MAX_DSS_MANAGERS];
449 454
450 bool irq_enabled; 455 bool irq_enabled;
451} dss_cache; 456} dss_cache;
@@ -525,7 +530,7 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
525 int i; 530 int i;
526 struct omap_dss_device *dssdev = mgr->device; 531 struct omap_dss_device *dssdev = mgr->device;
527 532
528 if (!dssdev) 533 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
529 return 0; 534 return 0;
530 535
531 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { 536 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
@@ -596,11 +601,14 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
596 int r; 601 int r;
597 int i; 602 int i;
598 603
599 if (!ovl->manager || !ovl->manager->device) 604 if (!ovl->manager)
600 return 0; 605 return 0;
601 606
602 dssdev = ovl->manager->device; 607 dssdev = ovl->manager->device;
603 608
609 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
610 return 0;
611
604 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { 612 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
605 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; 613 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
606 channel = OMAP_DSS_CHANNEL_DIGIT; 614 channel = OMAP_DSS_CHANNEL_DIGIT;
@@ -718,6 +726,7 @@ static int configure_overlay(enum omap_plane plane)
718 u16 x, y, w, h; 726 u16 x, y, w, h;
719 u32 paddr; 727 u32 paddr;
720 int r; 728 int r;
729 u16 orig_w, orig_h, orig_outw, orig_outh;
721 730
722 DSSDBGF("%d", plane); 731 DSSDBGF("%d", plane);
723 732
@@ -738,8 +747,16 @@ static int configure_overlay(enum omap_plane plane)
738 outh = c->out_height == 0 ? c->height : c->out_height; 747 outh = c->out_height == 0 ? c->height : c->out_height;
739 paddr = c->paddr; 748 paddr = c->paddr;
740 749
750 orig_w = w;
751 orig_h = h;
752 orig_outw = outw;
753 orig_outh = outh;
754
741 if (c->manual_update && mc->do_manual_update) { 755 if (c->manual_update && mc->do_manual_update) {
742 unsigned bpp; 756 unsigned bpp;
757 unsigned scale_x_m = w, scale_x_d = outw;
758 unsigned scale_y_m = h, scale_y_d = outh;
759
743 /* If the overlay is outside the update region, disable it */ 760 /* If the overlay is outside the update region, disable it */
744 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, 761 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
745 x, y, outw, outh)) { 762 x, y, outw, outh)) {
@@ -770,38 +787,47 @@ static int configure_overlay(enum omap_plane plane)
770 BUG(); 787 BUG();
771 } 788 }
772 789
773 if (dispc_is_overlay_scaled(c)) { 790 if (mc->x > c->pos_x) {
774 /* If the overlay is scaled, the update area has 791 x = 0;
775 * already been enlarged to cover the whole overlay. We 792 outw -= (mc->x - c->pos_x);
776 * only need to adjust x/y here */ 793 paddr += (mc->x - c->pos_x) *
777 x = c->pos_x - mc->x; 794 scale_x_m / scale_x_d * bpp / 8;
778 y = c->pos_y - mc->y;
779 } else { 795 } else {
780 if (mc->x > c->pos_x) { 796 x = c->pos_x - mc->x;
781 x = 0; 797 }
782 w -= (mc->x - c->pos_x);
783 paddr += (mc->x - c->pos_x) * bpp / 8;
784 } else {
785 x = c->pos_x - mc->x;
786 }
787
788 if (mc->y > c->pos_y) {
789 y = 0;
790 h -= (mc->y - c->pos_y);
791 paddr += (mc->y - c->pos_y) * c->screen_width *
792 bpp / 8;
793 } else {
794 y = c->pos_y - mc->y;
795 }
796
797 if (mc->w < (x+w))
798 w -= (x+w) - (mc->w);
799 798
800 if (mc->h < (y+h)) 799 if (mc->y > c->pos_y) {
801 h -= (y+h) - (mc->h); 800 y = 0;
801 outh -= (mc->y - c->pos_y);
802 paddr += (mc->y - c->pos_y) *
803 scale_y_m / scale_y_d *
804 c->screen_width * bpp / 8;
805 } else {
806 y = c->pos_y - mc->y;
807 }
802 808
803 outw = w; 809 if (mc->w < (x + outw))
804 outh = h; 810 outw -= (x + outw) - (mc->w);
811
812 if (mc->h < (y + outh))
813 outh -= (y + outh) - (mc->h);
814
815 w = w * outw / orig_outw;
816 h = h * outh / orig_outh;
817
818 /* YUV mode overlay's input width has to be even and the
819 * algorithm above may adjust the width to be odd.
820 *
821 * Here we adjust the width if needed, preferring to increase
822 * the width if the original width was bigger.
823 */
824 if ((w & 1) &&
825 (c->color_mode == OMAP_DSS_COLOR_YUV2 ||
826 c->color_mode == OMAP_DSS_COLOR_UYVY)) {
827 if (orig_w > w)
828 w += 1;
829 else
830 w -= 1;
805 } 831 }
806 } 832 }
807 833
@@ -857,12 +883,12 @@ static int configure_dispc(void)
857{ 883{
858 struct overlay_cache_data *oc; 884 struct overlay_cache_data *oc;
859 struct manager_cache_data *mc; 885 struct manager_cache_data *mc;
860 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); 886 const int num_ovls = dss_feat_get_num_ovls();
861 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); 887 const int num_mgrs = dss_feat_get_num_mgrs();
862 int i; 888 int i;
863 int r; 889 int r;
864 bool mgr_busy[2]; 890 bool mgr_busy[MAX_DSS_MANAGERS];
865 bool mgr_go[2]; 891 bool mgr_go[MAX_DSS_MANAGERS];
866 bool busy; 892 bool busy;
867 893
868 r = 0; 894 r = 0;
@@ -960,15 +986,16 @@ static void make_even(u16 *x, u16 *w)
960/* Configure dispc for partial update. Return possibly modified update 986/* Configure dispc for partial update. Return possibly modified update
961 * area */ 987 * area */
962void dss_setup_partial_planes(struct omap_dss_device *dssdev, 988void dss_setup_partial_planes(struct omap_dss_device *dssdev,
963 u16 *xi, u16 *yi, u16 *wi, u16 *hi) 989 u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area)
964{ 990{
965 struct overlay_cache_data *oc; 991 struct overlay_cache_data *oc;
966 struct manager_cache_data *mc; 992 struct manager_cache_data *mc;
967 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); 993 const int num_ovls = dss_feat_get_num_ovls();
968 struct omap_overlay_manager *mgr; 994 struct omap_overlay_manager *mgr;
969 int i; 995 int i;
970 u16 x, y, w, h; 996 u16 x, y, w, h;
971 unsigned long flags; 997 unsigned long flags;
998 bool area_changed;
972 999
973 x = *xi; 1000 x = *xi;
974 y = *yi; 1001 y = *yi;
@@ -989,73 +1016,91 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
989 1016
990 spin_lock_irqsave(&dss_cache.lock, flags); 1017 spin_lock_irqsave(&dss_cache.lock, flags);
991 1018
992 /* We need to show the whole overlay if it is scaled. So look for 1019 /*
993 * those, and make the update area larger if found. 1020 * Execute the outer loop until the inner loop has completed
994 * Also mark the overlay cache dirty */ 1021 * once without increasing the update area. This will ensure that
995 for (i = 0; i < num_ovls; ++i) { 1022 * all scaled overlays end up completely within the update area.
996 unsigned x1, y1, x2, y2; 1023 */
997 unsigned outw, outh; 1024 do {
1025 area_changed = false;
998 1026
999 oc = &dss_cache.overlay_cache[i]; 1027 /* We need to show the whole overlay if it is scaled. So look
1028 * for those, and make the update area larger if found.
1029 * Also mark the overlay cache dirty */
1030 for (i = 0; i < num_ovls; ++i) {
1031 unsigned x1, y1, x2, y2;
1032 unsigned outw, outh;
1000 1033
1001 if (oc->channel != mgr->id) 1034 oc = &dss_cache.overlay_cache[i];
1002 continue;
1003 1035
1004 oc->dirty = true; 1036 if (oc->channel != mgr->id)
1037 continue;
1005 1038
1006 if (!oc->enabled) 1039 oc->dirty = true;
1007 continue;
1008 1040
1009 if (!dispc_is_overlay_scaled(oc)) 1041 if (!enlarge_update_area)
1010 continue; 1042 continue;
1011 1043
1012 outw = oc->out_width == 0 ? oc->width : oc->out_width; 1044 if (!oc->enabled)
1013 outh = oc->out_height == 0 ? oc->height : oc->out_height; 1045 continue;
1014 1046
1015 /* is the overlay outside the update region? */ 1047 if (!dispc_is_overlay_scaled(oc))
1016 if (!rectangle_intersects(x, y, w, h, 1048 continue;
1017 oc->pos_x, oc->pos_y,
1018 outw, outh))
1019 continue;
1020 1049
1021 /* if the overlay totally inside the update region? */ 1050 outw = oc->out_width == 0 ?
1022 if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh, 1051 oc->width : oc->out_width;
1023 x, y, w, h)) 1052 outh = oc->out_height == 0 ?
1024 continue; 1053 oc->height : oc->out_height;
1054
1055 /* is the overlay outside the update region? */
1056 if (!rectangle_intersects(x, y, w, h,
1057 oc->pos_x, oc->pos_y,
1058 outw, outh))
1059 continue;
1060
1061 /* if the overlay totally inside the update region? */
1062 if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
1063 x, y, w, h))
1064 continue;
1025 1065
1026 if (x > oc->pos_x) 1066 if (x > oc->pos_x)
1027 x1 = oc->pos_x; 1067 x1 = oc->pos_x;
1028 else 1068 else
1029 x1 = x; 1069 x1 = x;
1030 1070
1031 if (y > oc->pos_y) 1071 if (y > oc->pos_y)
1032 y1 = oc->pos_y; 1072 y1 = oc->pos_y;
1033 else 1073 else
1034 y1 = y; 1074 y1 = y;
1035 1075
1036 if ((x + w) < (oc->pos_x + outw)) 1076 if ((x + w) < (oc->pos_x + outw))
1037 x2 = oc->pos_x + outw; 1077 x2 = oc->pos_x + outw;
1038 else 1078 else
1039 x2 = x + w; 1079 x2 = x + w;
1040 1080
1041 if ((y + h) < (oc->pos_y + outh)) 1081 if ((y + h) < (oc->pos_y + outh))
1042 y2 = oc->pos_y + outh; 1082 y2 = oc->pos_y + outh;
1043 else 1083 else
1044 y2 = y + h; 1084 y2 = y + h;
1045 1085
1046 x = x1; 1086 x = x1;
1047 y = y1; 1087 y = y1;
1048 w = x2 - x1; 1088 w = x2 - x1;
1049 h = y2 - y1; 1089 h = y2 - y1;
1050 1090
1051 make_even(&x, &w); 1091 make_even(&x, &w);
1052 1092
1053 DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", 1093 DSSDBG("changing upd area due to ovl(%d) "
1094 "scaling %d,%d %dx%d\n",
1054 i, x, y, w, h); 1095 i, x, y, w, h);
1055 } 1096
1097 area_changed = true;
1098 }
1099 } while (area_changed);
1056 1100
1057 mc = &dss_cache.manager_cache[mgr->id]; 1101 mc = &dss_cache.manager_cache[mgr->id];
1058 mc->do_manual_update = true; 1102 mc->do_manual_update = true;
1103 mc->enlarge_update_area = enlarge_update_area;
1059 mc->x = x; 1104 mc->x = x;
1060 mc->y = y; 1105 mc->y = y;
1061 mc->w = w; 1106 mc->w = w;
@@ -1077,8 +1122,8 @@ void dss_start_update(struct omap_dss_device *dssdev)
1077{ 1122{
1078 struct manager_cache_data *mc; 1123 struct manager_cache_data *mc;
1079 struct overlay_cache_data *oc; 1124 struct overlay_cache_data *oc;
1080 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); 1125 const int num_ovls = dss_feat_get_num_ovls();
1081 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); 1126 const int num_mgrs = dss_feat_get_num_mgrs();
1082 struct omap_overlay_manager *mgr; 1127 struct omap_overlay_manager *mgr;
1083 int i; 1128 int i;
1084 1129
@@ -1107,10 +1152,10 @@ static void dss_apply_irq_handler(void *data, u32 mask)
1107{ 1152{
1108 struct manager_cache_data *mc; 1153 struct manager_cache_data *mc;
1109 struct overlay_cache_data *oc; 1154 struct overlay_cache_data *oc;
1110 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); 1155 const int num_ovls = dss_feat_get_num_ovls();
1111 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); 1156 const int num_mgrs = dss_feat_get_num_mgrs();
1112 int i, r; 1157 int i, r;
1113 bool mgr_busy[2]; 1158 bool mgr_busy[MAX_DSS_MANAGERS];
1114 1159
1115 mgr_busy[0] = dispc_go_busy(0); 1160 mgr_busy[0] = dispc_go_busy(0);
1116 mgr_busy[1] = dispc_go_busy(1); 1161 mgr_busy[1] = dispc_go_busy(1);
@@ -1417,7 +1462,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
1417 1462
1418 num_managers = 0; 1463 num_managers = 0;
1419 1464
1420 for (i = 0; i < 2; ++i) { 1465 for (i = 0; i < dss_feat_get_num_mgrs(); ++i) {
1421 struct omap_overlay_manager *mgr; 1466 struct omap_overlay_manager *mgr;
1422 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); 1467 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1423 1468
@@ -1427,14 +1472,10 @@ int dss_init_overlay_managers(struct platform_device *pdev)
1427 case 0: 1472 case 0:
1428 mgr->name = "lcd"; 1473 mgr->name = "lcd";
1429 mgr->id = OMAP_DSS_CHANNEL_LCD; 1474 mgr->id = OMAP_DSS_CHANNEL_LCD;
1430 mgr->supported_displays =
1431 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
1432 OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
1433 break; 1475 break;
1434 case 1: 1476 case 1:
1435 mgr->name = "tv"; 1477 mgr->name = "tv";
1436 mgr->id = OMAP_DSS_CHANNEL_DIGIT; 1478 mgr->id = OMAP_DSS_CHANNEL_DIGIT;
1437 mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
1438 break; 1479 break;
1439 } 1480 }
1440 1481
@@ -1450,6 +1491,8 @@ int dss_init_overlay_managers(struct platform_device *pdev)
1450 mgr->disable = &dss_mgr_disable; 1491 mgr->disable = &dss_mgr_disable;
1451 1492
1452 mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; 1493 mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
1494 mgr->supported_displays =
1495 dss_feat_get_supported_displays(mgr->id);
1453 1496
1454 dss_overlay_setup_dispc_manager(mgr); 1497 dss_overlay_setup_dispc_manager(mgr);
1455 1498
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 82336583adef..75642c22cac7 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -35,6 +35,7 @@
35#include <plat/cpu.h> 35#include <plat/cpu.h>
36 36
37#include "dss.h" 37#include "dss.h"
38#include "dss_features.h"
38 39
39static int num_overlays; 40static int num_overlays;
40static struct list_head overlay_list; 41static struct list_head overlay_list;
@@ -65,7 +66,7 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
65 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 66 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
66 mgr = omap_dss_get_overlay_manager(i); 67 mgr = omap_dss_get_overlay_manager(i);
67 68
68 if (strncmp(buf, mgr->name, len) == 0) 69 if (sysfs_streq(buf, mgr->name))
69 break; 70 break;
70 71
71 mgr = NULL; 72 mgr = NULL;
@@ -237,7 +238,8 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
237 /* Video1 plane does not support global alpha 238 /* Video1 plane does not support global alpha
238 * to always make it 255 completely opaque 239 * to always make it 255 completely opaque
239 */ 240 */
240 if (ovl->id == OMAP_DSS_VIDEO1) 241 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
242 ovl->id == OMAP_DSS_VIDEO1)
241 info.global_alpha = 255; 243 info.global_alpha = 255;
242 else 244 else
243 info.global_alpha = simple_strtoul(buf, NULL, 10); 245 info.global_alpha = simple_strtoul(buf, NULL, 10);
@@ -510,11 +512,11 @@ static void omap_dss_add_overlay(struct omap_overlay *overlay)
510 list_add_tail(&overlay->list, &overlay_list); 512 list_add_tail(&overlay->list, &overlay_list);
511} 513}
512 514
513static struct omap_overlay *dispc_overlays[3]; 515static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS];
514 516
515void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr) 517void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
516{ 518{
517 mgr->num_overlays = 3; 519 mgr->num_overlays = dss_feat_get_num_ovls();
518 mgr->overlays = dispc_overlays; 520 mgr->overlays = dispc_overlays;
519} 521}
520 522
@@ -535,7 +537,7 @@ void dss_init_overlays(struct platform_device *pdev)
535 537
536 num_overlays = 0; 538 num_overlays = 0;
537 539
538 for (i = 0; i < 3; ++i) { 540 for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
539 struct omap_overlay *ovl; 541 struct omap_overlay *ovl;
540 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); 542 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
541 543
@@ -545,18 +547,12 @@ void dss_init_overlays(struct platform_device *pdev)
545 case 0: 547 case 0:
546 ovl->name = "gfx"; 548 ovl->name = "gfx";
547 ovl->id = OMAP_DSS_GFX; 549 ovl->id = OMAP_DSS_GFX;
548 ovl->supported_modes = cpu_is_omap34xx() ?
549 OMAP_DSS_COLOR_GFX_OMAP3 :
550 OMAP_DSS_COLOR_GFX_OMAP2;
551 ovl->caps = OMAP_DSS_OVL_CAP_DISPC; 550 ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
552 ovl->info.global_alpha = 255; 551 ovl->info.global_alpha = 255;
553 break; 552 break;
554 case 1: 553 case 1:
555 ovl->name = "vid1"; 554 ovl->name = "vid1";
556 ovl->id = OMAP_DSS_VIDEO1; 555 ovl->id = OMAP_DSS_VIDEO1;
557 ovl->supported_modes = cpu_is_omap34xx() ?
558 OMAP_DSS_COLOR_VID1_OMAP3 :
559 OMAP_DSS_COLOR_VID_OMAP2;
560 ovl->caps = OMAP_DSS_OVL_CAP_SCALE | 556 ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
561 OMAP_DSS_OVL_CAP_DISPC; 557 OMAP_DSS_OVL_CAP_DISPC;
562 ovl->info.global_alpha = 255; 558 ovl->info.global_alpha = 255;
@@ -564,9 +560,6 @@ void dss_init_overlays(struct platform_device *pdev)
564 case 2: 560 case 2:
565 ovl->name = "vid2"; 561 ovl->name = "vid2";
566 ovl->id = OMAP_DSS_VIDEO2; 562 ovl->id = OMAP_DSS_VIDEO2;
567 ovl->supported_modes = cpu_is_omap34xx() ?
568 OMAP_DSS_COLOR_VID2_OMAP3 :
569 OMAP_DSS_COLOR_VID_OMAP2;
570 ovl->caps = OMAP_DSS_OVL_CAP_SCALE | 563 ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
571 OMAP_DSS_OVL_CAP_DISPC; 564 OMAP_DSS_OVL_CAP_DISPC;
572 ovl->info.global_alpha = 255; 565 ovl->info.global_alpha = 255;
@@ -579,6 +572,9 @@ void dss_init_overlays(struct platform_device *pdev)
579 ovl->get_overlay_info = &dss_ovl_get_overlay_info; 572 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
580 ovl->wait_for_go = &dss_ovl_wait_for_go; 573 ovl->wait_for_go = &dss_ovl_wait_for_go;
581 574
575 ovl->supported_modes =
576 dss_feat_get_supported_color_modes(ovl->id);
577
582 omap_dss_add_overlay(ovl); 578 omap_dss_add_overlay(ovl);
583 579
584 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, 580 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
@@ -651,7 +647,7 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
651 } 647 }
652 648
653 if (mgr) { 649 if (mgr) {
654 for (i = 0; i < 3; i++) { 650 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
655 struct omap_overlay *ovl; 651 struct omap_overlay *ovl;
656 ovl = omap_dss_get_overlay(i); 652 ovl = omap_dss_get_overlay(i);
657 if (!ovl->manager || force) { 653 if (!ovl->manager || force) {
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index cc23f53cc62d..bbe62464e92d 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -886,7 +886,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
886 return -EINVAL; 886 return -EINVAL;
887 887
888 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 888 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
889 dss_setup_partial_planes(dssdev, x, y, w, h); 889 dss_setup_partial_planes(dssdev, x, y, w, h, true);
890 dispc_set_lcd_size(*w, *h); 890 dispc_set_lcd_size(*w, *h);
891 } 891 }
892 892
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index 43496d6c377f..65149b22cf37 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -3,7 +3,7 @@ menuconfig FB_OMAP2
3 depends on FB && OMAP2_DSS 3 depends on FB && OMAP2_DSS
4 4
5 select OMAP2_VRAM 5 select OMAP2_VRAM
6 select OMAP2_VRFB 6 select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
7 select FB_CFB_FILLRECT 7 select FB_CFB_FILLRECT
8 select FB_CFB_COPYAREA 8 select FB_CFB_COPYAREA
9 select FB_CFB_IMAGEBLIT 9 select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 9c7361871d78..6f435450987e 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -34,12 +34,37 @@
34 34
35#include "omapfb.h" 35#include "omapfb.h"
36 36
37static u8 get_mem_idx(struct omapfb_info *ofbi)
38{
39 if (ofbi->id == ofbi->region->id)
40 return 0;
41
42 return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
43}
44
45static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
46 u8 mem_idx)
47{
48 struct omapfb2_device *fbdev = ofbi->fbdev;
49
50 if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
51 mem_idx &= OMAPFB_MEM_IDX_MASK;
52 else
53 mem_idx = ofbi->id;
54
55 if (mem_idx >= fbdev->num_fbs)
56 return NULL;
57
58 return &fbdev->regions[mem_idx];
59}
60
37static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) 61static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
38{ 62{
39 struct omapfb_info *ofbi = FB2OFB(fbi); 63 struct omapfb_info *ofbi = FB2OFB(fbi);
40 struct omapfb2_device *fbdev = ofbi->fbdev; 64 struct omapfb2_device *fbdev = ofbi->fbdev;
41 struct omap_overlay *ovl; 65 struct omap_overlay *ovl;
42 struct omap_overlay_info info; 66 struct omap_overlay_info old_info;
67 struct omapfb2_mem_region *old_rg, *new_rg;
43 int r = 0; 68 int r = 0;
44 69
45 DBG("omapfb_setup_plane\n"); 70 DBG("omapfb_setup_plane\n");
@@ -52,36 +77,106 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
52 /* XXX uses only the first overlay */ 77 /* XXX uses only the first overlay */
53 ovl = ofbi->overlays[0]; 78 ovl = ofbi->overlays[0];
54 79
55 if (pi->enabled && !ofbi->region.size) { 80 old_rg = ofbi->region;
81 new_rg = get_mem_region(ofbi, pi->mem_idx);
82 if (!new_rg) {
83 r = -EINVAL;
84 goto out;
85 }
86
87 /* Take the locks in a specific order to keep lockdep happy */
88 if (old_rg->id < new_rg->id) {
89 omapfb_get_mem_region(old_rg);
90 omapfb_get_mem_region(new_rg);
91 } else if (new_rg->id < old_rg->id) {
92 omapfb_get_mem_region(new_rg);
93 omapfb_get_mem_region(old_rg);
94 } else
95 omapfb_get_mem_region(old_rg);
96
97 if (pi->enabled && !new_rg->size) {
56 /* 98 /*
57 * This plane's memory was freed, can't enable it 99 * This plane's memory was freed, can't enable it
58 * until it's reallocated. 100 * until it's reallocated.
59 */ 101 */
60 r = -EINVAL; 102 r = -EINVAL;
61 goto out; 103 goto put_mem;
62 } 104 }
63 105
64 ovl->get_overlay_info(ovl, &info); 106 ovl->get_overlay_info(ovl, &old_info);
65 107
66 info.pos_x = pi->pos_x; 108 if (old_rg != new_rg) {
67 info.pos_y = pi->pos_y; 109 ofbi->region = new_rg;
68 info.out_width = pi->out_width; 110 set_fb_fix(fbi);
69 info.out_height = pi->out_height; 111 }
70 info.enabled = pi->enabled;
71 112
72 r = ovl->set_overlay_info(ovl, &info); 113 if (pi->enabled) {
73 if (r) 114 struct omap_overlay_info info;
74 goto out;
75 115
76 if (ovl->manager) { 116 r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
77 r = ovl->manager->apply(ovl->manager); 117 pi->out_width, pi->out_height);
78 if (r) 118 if (r)
79 goto out; 119 goto undo;
120
121 ovl->get_overlay_info(ovl, &info);
122
123 if (!info.enabled) {
124 info.enabled = pi->enabled;
125 r = ovl->set_overlay_info(ovl, &info);
126 if (r)
127 goto undo;
128 }
129 } else {
130 struct omap_overlay_info info;
131
132 ovl->get_overlay_info(ovl, &info);
133
134 info.enabled = pi->enabled;
135 info.pos_x = pi->pos_x;
136 info.pos_y = pi->pos_y;
137 info.out_width = pi->out_width;
138 info.out_height = pi->out_height;
139
140 r = ovl->set_overlay_info(ovl, &info);
141 if (r)
142 goto undo;
80 } 143 }
81 144
82out: 145 if (ovl->manager)
83 if (r) 146 ovl->manager->apply(ovl->manager);
84 dev_err(fbdev->dev, "setup_plane failed\n"); 147
148 /* Release the locks in a specific order to keep lockdep happy */
149 if (old_rg->id > new_rg->id) {
150 omapfb_put_mem_region(old_rg);
151 omapfb_put_mem_region(new_rg);
152 } else if (new_rg->id > old_rg->id) {
153 omapfb_put_mem_region(new_rg);
154 omapfb_put_mem_region(old_rg);
155 } else
156 omapfb_put_mem_region(old_rg);
157
158 return 0;
159
160 undo:
161 if (old_rg != new_rg) {
162 ofbi->region = old_rg;
163 set_fb_fix(fbi);
164 }
165
166 ovl->set_overlay_info(ovl, &old_info);
167 put_mem:
168 /* Release the locks in a specific order to keep lockdep happy */
169 if (old_rg->id > new_rg->id) {
170 omapfb_put_mem_region(old_rg);
171 omapfb_put_mem_region(new_rg);
172 } else if (new_rg->id > old_rg->id) {
173 omapfb_put_mem_region(new_rg);
174 omapfb_put_mem_region(old_rg);
175 } else
176 omapfb_put_mem_region(old_rg);
177 out:
178 dev_err(fbdev->dev, "setup_plane failed\n");
179
85 return r; 180 return r;
86} 181}
87 182
@@ -92,8 +187,8 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
92 if (ofbi->num_overlays != 1) { 187 if (ofbi->num_overlays != 1) {
93 memset(pi, 0, sizeof(*pi)); 188 memset(pi, 0, sizeof(*pi));
94 } else { 189 } else {
95 struct omap_overlay_info *ovli;
96 struct omap_overlay *ovl; 190 struct omap_overlay *ovl;
191 struct omap_overlay_info *ovli;
97 192
98 ovl = ofbi->overlays[0]; 193 ovl = ofbi->overlays[0];
99 ovli = &ovl->info; 194 ovli = &ovl->info;
@@ -103,6 +198,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
103 pi->enabled = ovli->enabled; 198 pi->enabled = ovli->enabled;
104 pi->channel_out = 0; /* xxx */ 199 pi->channel_out = 0; /* xxx */
105 pi->mirror = 0; 200 pi->mirror = 0;
201 pi->mem_idx = get_mem_idx(ofbi);
106 pi->out_width = ovli->out_width; 202 pi->out_width = ovli->out_width;
107 pi->out_height = ovli->out_height; 203 pi->out_height = ovli->out_height;
108 } 204 }
@@ -115,7 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
115 struct omapfb_info *ofbi = FB2OFB(fbi); 211 struct omapfb_info *ofbi = FB2OFB(fbi);
116 struct omapfb2_device *fbdev = ofbi->fbdev; 212 struct omapfb2_device *fbdev = ofbi->fbdev;
117 struct omapfb2_mem_region *rg; 213 struct omapfb2_mem_region *rg;
118 int r, i; 214 int r = 0, i;
119 size_t size; 215 size_t size;
120 216
121 if (mi->type > OMAPFB_MEMTYPE_MAX) 217 if (mi->type > OMAPFB_MEMTYPE_MAX)
@@ -123,22 +219,44 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
123 219
124 size = PAGE_ALIGN(mi->size); 220 size = PAGE_ALIGN(mi->size);
125 221
126 rg = &ofbi->region; 222 rg = ofbi->region;
127 223
128 for (i = 0; i < ofbi->num_overlays; i++) { 224 down_write_nested(&rg->lock, rg->id);
129 if (ofbi->overlays[i]->info.enabled) 225 atomic_inc(&rg->lock_count);
130 return -EBUSY; 226
227 if (atomic_read(&rg->map_count)) {
228 r = -EBUSY;
229 goto out;
230 }
231
232 for (i = 0; i < fbdev->num_fbs; i++) {
233 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
234 int j;
235
236 if (ofbi2->region != rg)
237 continue;
238
239 for (j = 0; j < ofbi2->num_overlays; j++) {
240 if (ofbi2->overlays[j]->info.enabled) {
241 r = -EBUSY;
242 goto out;
243 }
244 }
131 } 245 }
132 246
133 if (rg->size != size || rg->type != mi->type) { 247 if (rg->size != size || rg->type != mi->type) {
134 r = omapfb_realloc_fbmem(fbi, size, mi->type); 248 r = omapfb_realloc_fbmem(fbi, size, mi->type);
135 if (r) { 249 if (r) {
136 dev_err(fbdev->dev, "realloc fbmem failed\n"); 250 dev_err(fbdev->dev, "realloc fbmem failed\n");
137 return r; 251 goto out;
138 } 252 }
139 } 253 }
140 254
141 return 0; 255 out:
256 atomic_dec(&rg->lock_count);
257 up_write(&rg->lock);
258
259 return r;
142} 260}
143 261
144static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) 262static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
@@ -146,12 +264,14 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
146 struct omapfb_info *ofbi = FB2OFB(fbi); 264 struct omapfb_info *ofbi = FB2OFB(fbi);
147 struct omapfb2_mem_region *rg; 265 struct omapfb2_mem_region *rg;
148 266
149 rg = &ofbi->region; 267 rg = omapfb_get_mem_region(ofbi->region);
150 memset(mi, 0, sizeof(*mi)); 268 memset(mi, 0, sizeof(*mi));
151 269
152 mi->size = rg->size; 270 mi->size = rg->size;
153 mi->type = rg->type; 271 mi->type = rg->type;
154 272
273 omapfb_put_mem_region(rg);
274
155 return 0; 275 return 0;
156} 276}
157 277
@@ -490,6 +610,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
490 struct omapfb_vram_info vram_info; 610 struct omapfb_vram_info vram_info;
491 struct omapfb_tearsync_info tearsync_info; 611 struct omapfb_tearsync_info tearsync_info;
492 struct omapfb_display_info display_info; 612 struct omapfb_display_info display_info;
613 u32 crt;
493 } p; 614 } p;
494 615
495 int r = 0; 616 int r = 0;
@@ -648,6 +769,17 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
648 r = -EFAULT; 769 r = -EFAULT;
649 break; 770 break;
650 771
772 case FBIO_WAITFORVSYNC:
773 if (get_user(p.crt, (__u32 __user *)arg)) {
774 r = -EFAULT;
775 break;
776 }
777 if (p.crt != 0) {
778 r = -ENODEV;
779 break;
780 }
781 /* FALLTHROUGH */
782
651 case OMAPFB_WAITFORVSYNC: 783 case OMAPFB_WAITFORVSYNC:
652 DBG("ioctl WAITFORVSYNC\n"); 784 DBG("ioctl WAITFORVSYNC\n");
653 if (!display) { 785 if (!display) {
@@ -738,7 +870,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
738 break; 870 break;
739 } 871 }
740 872
741 if (!display->driver->enable_te) { 873 if (!display || !display->driver->enable_te) {
742 r = -ENODEV; 874 r = -ENODEV;
743 break; 875 break;
744 } 876 }
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 4b4506da96da..6a704f176c22 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -157,7 +157,7 @@ static void fill_fb(struct fb_info *fbi)
157 157
158static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) 158static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
159{ 159{
160 const struct vrfb *vrfb = &ofbi->region.vrfb; 160 const struct vrfb *vrfb = &ofbi->region->vrfb;
161 unsigned offset; 161 unsigned offset;
162 162
163 switch (rot) { 163 switch (rot) {
@@ -185,27 +185,27 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
185static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot) 185static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
186{ 186{
187 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 187 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
188 return ofbi->region.vrfb.paddr[rot] 188 return ofbi->region->vrfb.paddr[rot]
189 + omapfb_get_vrfb_offset(ofbi, rot); 189 + omapfb_get_vrfb_offset(ofbi, rot);
190 } else { 190 } else {
191 return ofbi->region.paddr; 191 return ofbi->region->paddr;
192 } 192 }
193} 193}
194 194
195static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi) 195static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
196{ 196{
197 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 197 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
198 return ofbi->region.vrfb.paddr[0]; 198 return ofbi->region->vrfb.paddr[0];
199 else 199 else
200 return ofbi->region.paddr; 200 return ofbi->region->paddr;
201} 201}
202 202
203static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi) 203static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
204{ 204{
205 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 205 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
206 return ofbi->region.vrfb.vaddr[0]; 206 return ofbi->region->vrfb.vaddr[0];
207 else 207 else
208 return ofbi->region.vaddr; 208 return ofbi->region->vaddr;
209} 209}
210 210
211static struct omapfb_colormode omapfb_colormodes[] = { 211static struct omapfb_colormode omapfb_colormodes[] = {
@@ -450,7 +450,7 @@ static int check_vrfb_fb_size(unsigned long region_size,
450static int check_fb_size(const struct omapfb_info *ofbi, 450static int check_fb_size(const struct omapfb_info *ofbi,
451 struct fb_var_screeninfo *var) 451 struct fb_var_screeninfo *var)
452{ 452{
453 unsigned long max_frame_size = ofbi->region.size; 453 unsigned long max_frame_size = ofbi->region->size;
454 int bytespp = var->bits_per_pixel >> 3; 454 int bytespp = var->bits_per_pixel >> 3;
455 unsigned long line_size = var->xres_virtual * bytespp; 455 unsigned long line_size = var->xres_virtual * bytespp;
456 456
@@ -497,7 +497,7 @@ static int check_fb_size(const struct omapfb_info *ofbi,
497static int setup_vrfb_rotation(struct fb_info *fbi) 497static int setup_vrfb_rotation(struct fb_info *fbi)
498{ 498{
499 struct omapfb_info *ofbi = FB2OFB(fbi); 499 struct omapfb_info *ofbi = FB2OFB(fbi);
500 struct omapfb2_mem_region *rg = &ofbi->region; 500 struct omapfb2_mem_region *rg = ofbi->region;
501 struct vrfb *vrfb = &rg->vrfb; 501 struct vrfb *vrfb = &rg->vrfb;
502 struct fb_var_screeninfo *var = &fbi->var; 502 struct fb_var_screeninfo *var = &fbi->var;
503 struct fb_fix_screeninfo *fix = &fbi->fix; 503 struct fb_fix_screeninfo *fix = &fbi->fix;
@@ -558,9 +558,9 @@ static int setup_vrfb_rotation(struct fb_info *fbi)
558 return r; 558 return r;
559 559
560 /* used by open/write in fbmem.c */ 560 /* used by open/write in fbmem.c */
561 fbi->screen_base = ofbi->region.vrfb.vaddr[0]; 561 fbi->screen_base = ofbi->region->vrfb.vaddr[0];
562 562
563 fix->smem_start = ofbi->region.vrfb.paddr[0]; 563 fix->smem_start = ofbi->region->vrfb.paddr[0];
564 564
565 switch (var->nonstd) { 565 switch (var->nonstd) {
566 case OMAPFB_COLOR_YUV422: 566 case OMAPFB_COLOR_YUV422:
@@ -599,7 +599,7 @@ void set_fb_fix(struct fb_info *fbi)
599 struct fb_fix_screeninfo *fix = &fbi->fix; 599 struct fb_fix_screeninfo *fix = &fbi->fix;
600 struct fb_var_screeninfo *var = &fbi->var; 600 struct fb_var_screeninfo *var = &fbi->var;
601 struct omapfb_info *ofbi = FB2OFB(fbi); 601 struct omapfb_info *ofbi = FB2OFB(fbi);
602 struct omapfb2_mem_region *rg = &ofbi->region; 602 struct omapfb2_mem_region *rg = ofbi->region;
603 603
604 DBG("set_fb_fix\n"); 604 DBG("set_fb_fix\n");
605 605
@@ -668,8 +668,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
668 668
669 DBG("check_fb_var %d\n", ofbi->id); 669 DBG("check_fb_var %d\n", ofbi->id);
670 670
671 if (ofbi->region.size == 0) 671 WARN_ON(!atomic_read(&ofbi->region->lock_count));
672 return 0;
673 672
674 r = fb_mode_to_dss_mode(var, &mode); 673 r = fb_mode_to_dss_mode(var, &mode);
675 if (r) { 674 if (r) {
@@ -684,13 +683,14 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
684 } 683 }
685 } 684 }
686 685
687 if (var->rotate < 0 || var->rotate > 3) 686 if (var->rotate > 3)
688 return -EINVAL; 687 return -EINVAL;
689 688
690 if (check_fb_res_bounds(var)) 689 if (check_fb_res_bounds(var))
691 return -EINVAL; 690 return -EINVAL;
692 691
693 if (check_fb_size(ofbi, var)) 692 /* When no memory is allocated ignore the size check */
693 if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
694 return -EINVAL; 694 return -EINVAL;
695 695
696 if (var->xres + var->xoffset > var->xres_virtual) 696 if (var->xres + var->xoffset > var->xres_virtual)
@@ -714,10 +714,10 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
714 var->pixclock = timings.pixel_clock != 0 ? 714 var->pixclock = timings.pixel_clock != 0 ?
715 KHZ2PICOS(timings.pixel_clock) : 715 KHZ2PICOS(timings.pixel_clock) :
716 0; 716 0;
717 var->left_margin = timings.hfp; 717 var->left_margin = timings.hbp;
718 var->right_margin = timings.hbp; 718 var->right_margin = timings.hfp;
719 var->upper_margin = timings.vfp; 719 var->upper_margin = timings.vbp;
720 var->lower_margin = timings.vbp; 720 var->lower_margin = timings.vfp;
721 var->hsync_len = timings.hsw; 721 var->hsync_len = timings.hsw;
722 var->vsync_len = timings.vsw; 722 var->vsync_len = timings.vsw;
723 } else { 723 } else {
@@ -822,9 +822,43 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
822 return offset; 822 return offset;
823} 823}
824 824
825static void omapfb_calc_addr(const struct omapfb_info *ofbi,
826 const struct fb_var_screeninfo *var,
827 const struct fb_fix_screeninfo *fix,
828 int rotation, u32 *paddr, void __iomem **vaddr)
829{
830 u32 data_start_p;
831 void __iomem *data_start_v;
832 int offset;
833
834 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
835 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
836 data_start_v = NULL;
837 } else {
838 data_start_p = omapfb_get_region_paddr(ofbi);
839 data_start_v = omapfb_get_region_vaddr(ofbi);
840 }
841
842 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
843 offset = calc_rotation_offset_vrfb(var, fix, rotation);
844 else
845 offset = calc_rotation_offset_dma(var, fix, rotation);
846
847 data_start_p += offset;
848 data_start_v += offset;
849
850 if (offset)
851 DBG("offset %d, %d = %d\n",
852 var->xoffset, var->yoffset, offset);
853
854 DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
855
856 *paddr = data_start_p;
857 *vaddr = data_start_v;
858}
825 859
826/* setup overlay according to the fb */ 860/* setup overlay according to the fb */
827static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, 861int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
828 u16 posx, u16 posy, u16 outw, u16 outh) 862 u16 posx, u16 posy, u16 outw, u16 outh)
829{ 863{
830 int r = 0; 864 int r = 0;
@@ -832,9 +866,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
832 struct fb_var_screeninfo *var = &fbi->var; 866 struct fb_var_screeninfo *var = &fbi->var;
833 struct fb_fix_screeninfo *fix = &fbi->fix; 867 struct fb_fix_screeninfo *fix = &fbi->fix;
834 enum omap_color_mode mode = 0; 868 enum omap_color_mode mode = 0;
835 int offset; 869 u32 data_start_p = 0;
836 u32 data_start_p; 870 void __iomem *data_start_v = NULL;
837 void __iomem *data_start_v;
838 struct omap_overlay_info info; 871 struct omap_overlay_info info;
839 int xres, yres; 872 int xres, yres;
840 int screen_width; 873 int screen_width;
@@ -842,6 +875,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
842 int rotation = var->rotate; 875 int rotation = var->rotate;
843 int i; 876 int i;
844 877
878 WARN_ON(!atomic_read(&ofbi->region->lock_count));
879
845 for (i = 0; i < ofbi->num_overlays; i++) { 880 for (i = 0; i < ofbi->num_overlays; i++) {
846 if (ovl != ofbi->overlays[i]) 881 if (ovl != ofbi->overlays[i])
847 continue; 882 continue;
@@ -861,28 +896,9 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
861 yres = var->yres; 896 yres = var->yres;
862 } 897 }
863 898
864 899 if (ofbi->region->size)
865 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 900 omapfb_calc_addr(ofbi, var, fix, rotation,
866 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); 901 &data_start_p, &data_start_v);
867 data_start_v = NULL;
868 } else {
869 data_start_p = omapfb_get_region_paddr(ofbi);
870 data_start_v = omapfb_get_region_vaddr(ofbi);
871 }
872
873 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
874 offset = calc_rotation_offset_vrfb(var, fix, rotation);
875 else
876 offset = calc_rotation_offset_dma(var, fix, rotation);
877
878 data_start_p += offset;
879 data_start_v += offset;
880
881 if (offset)
882 DBG("offset %d, %d = %d\n",
883 var->xoffset, var->yoffset, offset);
884
885 DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
886 902
887 r = fb_mode_to_dss_mode(var, &mode); 903 r = fb_mode_to_dss_mode(var, &mode);
888 if (r) { 904 if (r) {
@@ -954,12 +970,14 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
954 fill_fb(fbi); 970 fill_fb(fbi);
955#endif 971#endif
956 972
973 WARN_ON(!atomic_read(&ofbi->region->lock_count));
974
957 for (i = 0; i < ofbi->num_overlays; i++) { 975 for (i = 0; i < ofbi->num_overlays; i++) {
958 ovl = ofbi->overlays[i]; 976 ovl = ofbi->overlays[i];
959 977
960 DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); 978 DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
961 979
962 if (ofbi->region.size == 0) { 980 if (ofbi->region->size == 0) {
963 /* the fb is not available. disable the overlay */ 981 /* the fb is not available. disable the overlay */
964 omapfb_overlay_enable(ovl, 0); 982 omapfb_overlay_enable(ovl, 0);
965 if (!init && ovl->manager) 983 if (!init && ovl->manager)
@@ -1007,36 +1025,48 @@ err:
1007 * DO NOT MODIFY PAR */ 1025 * DO NOT MODIFY PAR */
1008static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) 1026static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
1009{ 1027{
1028 struct omapfb_info *ofbi = FB2OFB(fbi);
1010 int r; 1029 int r;
1011 1030
1012 DBG("check_var(%d)\n", FB2OFB(fbi)->id); 1031 DBG("check_var(%d)\n", FB2OFB(fbi)->id);
1013 1032
1033 omapfb_get_mem_region(ofbi->region);
1034
1014 r = check_fb_var(fbi, var); 1035 r = check_fb_var(fbi, var);
1015 1036
1037 omapfb_put_mem_region(ofbi->region);
1038
1016 return r; 1039 return r;
1017} 1040}
1018 1041
1019/* set the video mode according to info->var */ 1042/* set the video mode according to info->var */
1020static int omapfb_set_par(struct fb_info *fbi) 1043static int omapfb_set_par(struct fb_info *fbi)
1021{ 1044{
1045 struct omapfb_info *ofbi = FB2OFB(fbi);
1022 int r; 1046 int r;
1023 1047
1024 DBG("set_par(%d)\n", FB2OFB(fbi)->id); 1048 DBG("set_par(%d)\n", FB2OFB(fbi)->id);
1025 1049
1050 omapfb_get_mem_region(ofbi->region);
1051
1026 set_fb_fix(fbi); 1052 set_fb_fix(fbi);
1027 1053
1028 r = setup_vrfb_rotation(fbi); 1054 r = setup_vrfb_rotation(fbi);
1029 if (r) 1055 if (r)
1030 return r; 1056 goto out;
1031 1057
1032 r = omapfb_apply_changes(fbi, 0); 1058 r = omapfb_apply_changes(fbi, 0);
1033 1059
1060 out:
1061 omapfb_put_mem_region(ofbi->region);
1062
1034 return r; 1063 return r;
1035} 1064}
1036 1065
1037static int omapfb_pan_display(struct fb_var_screeninfo *var, 1066static int omapfb_pan_display(struct fb_var_screeninfo *var,
1038 struct fb_info *fbi) 1067 struct fb_info *fbi)
1039{ 1068{
1069 struct omapfb_info *ofbi = FB2OFB(fbi);
1040 struct fb_var_screeninfo new_var; 1070 struct fb_var_screeninfo new_var;
1041 int r; 1071 int r;
1042 1072
@@ -1052,23 +1082,31 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var,
1052 1082
1053 fbi->var = new_var; 1083 fbi->var = new_var;
1054 1084
1085 omapfb_get_mem_region(ofbi->region);
1086
1055 r = omapfb_apply_changes(fbi, 0); 1087 r = omapfb_apply_changes(fbi, 0);
1056 1088
1089 omapfb_put_mem_region(ofbi->region);
1090
1057 return r; 1091 return r;
1058} 1092}
1059 1093
1060static void mmap_user_open(struct vm_area_struct *vma) 1094static void mmap_user_open(struct vm_area_struct *vma)
1061{ 1095{
1062 struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; 1096 struct omapfb2_mem_region *rg = vma->vm_private_data;
1063 1097
1064 atomic_inc(&ofbi->map_count); 1098 omapfb_get_mem_region(rg);
1099 atomic_inc(&rg->map_count);
1100 omapfb_put_mem_region(rg);
1065} 1101}
1066 1102
1067static void mmap_user_close(struct vm_area_struct *vma) 1103static void mmap_user_close(struct vm_area_struct *vma)
1068{ 1104{
1069 struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; 1105 struct omapfb2_mem_region *rg = vma->vm_private_data;
1070 1106
1071 atomic_dec(&ofbi->map_count); 1107 omapfb_get_mem_region(rg);
1108 atomic_dec(&rg->map_count);
1109 omapfb_put_mem_region(rg);
1072} 1110}
1073 1111
1074static struct vm_operations_struct mmap_user_ops = { 1112static struct vm_operations_struct mmap_user_ops = {
@@ -1080,9 +1118,11 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1080{ 1118{
1081 struct omapfb_info *ofbi = FB2OFB(fbi); 1119 struct omapfb_info *ofbi = FB2OFB(fbi);
1082 struct fb_fix_screeninfo *fix = &fbi->fix; 1120 struct fb_fix_screeninfo *fix = &fbi->fix;
1121 struct omapfb2_mem_region *rg;
1083 unsigned long off; 1122 unsigned long off;
1084 unsigned long start; 1123 unsigned long start;
1085 u32 len; 1124 u32 len;
1125 int r = -EINVAL;
1086 1126
1087 if (vma->vm_end - vma->vm_start == 0) 1127 if (vma->vm_end - vma->vm_start == 0)
1088 return 0; 1128 return 0;
@@ -1090,12 +1130,14 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1090 return -EINVAL; 1130 return -EINVAL;
1091 off = vma->vm_pgoff << PAGE_SHIFT; 1131 off = vma->vm_pgoff << PAGE_SHIFT;
1092 1132
1133 rg = omapfb_get_mem_region(ofbi->region);
1134
1093 start = omapfb_get_region_paddr(ofbi); 1135 start = omapfb_get_region_paddr(ofbi);
1094 len = fix->smem_len; 1136 len = fix->smem_len;
1095 if (off >= len) 1137 if (off >= len)
1096 return -EINVAL; 1138 goto error;
1097 if ((vma->vm_end - vma->vm_start + off) > len) 1139 if ((vma->vm_end - vma->vm_start + off) > len)
1098 return -EINVAL; 1140 goto error;
1099 1141
1100 off += start; 1142 off += start;
1101 1143
@@ -1105,13 +1147,25 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1105 vma->vm_flags |= VM_IO | VM_RESERVED; 1147 vma->vm_flags |= VM_IO | VM_RESERVED;
1106 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); 1148 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1107 vma->vm_ops = &mmap_user_ops; 1149 vma->vm_ops = &mmap_user_ops;
1108 vma->vm_private_data = ofbi; 1150 vma->vm_private_data = rg;
1109 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, 1151 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1110 vma->vm_end - vma->vm_start, vma->vm_page_prot)) 1152 vma->vm_end - vma->vm_start,
1111 return -EAGAIN; 1153 vma->vm_page_prot)) {
1154 r = -EAGAIN;
1155 goto error;
1156 }
1157
1112 /* vm_ops.open won't be called for mmap itself. */ 1158 /* vm_ops.open won't be called for mmap itself. */
1113 atomic_inc(&ofbi->map_count); 1159 atomic_inc(&rg->map_count);
1160
1161 omapfb_put_mem_region(rg);
1162
1114 return 0; 1163 return 0;
1164
1165 error:
1166 omapfb_put_mem_region(ofbi->region);
1167
1168 return r;
1115} 1169}
1116 1170
1117/* Store a single color palette entry into a pseudo palette or the hardware 1171/* Store a single color palette entry into a pseudo palette or the hardware
@@ -1154,11 +1208,6 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
1154 if (r != 0) 1208 if (r != 0)
1155 break; 1209 break;
1156 1210
1157 if (regno < 0) {
1158 r = -EINVAL;
1159 break;
1160 }
1161
1162 if (regno < 16) { 1211 if (regno < 16) {
1163 u16 pal; 1212 u16 pal;
1164 pal = ((red >> (16 - var->red.length)) << 1213 pal = ((red >> (16 - var->red.length)) <<
@@ -1217,6 +1266,9 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
1217 int do_update = 0; 1266 int do_update = 0;
1218 int r = 0; 1267 int r = 0;
1219 1268
1269 if (!display)
1270 return -EINVAL;
1271
1220 omapfb_lock(fbdev); 1272 omapfb_lock(fbdev);
1221 1273
1222 switch (blank) { 1274 switch (blank) {
@@ -1300,7 +1352,9 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
1300 struct omapfb2_device *fbdev = ofbi->fbdev; 1352 struct omapfb2_device *fbdev = ofbi->fbdev;
1301 struct omapfb2_mem_region *rg; 1353 struct omapfb2_mem_region *rg;
1302 1354
1303 rg = &ofbi->region; 1355 rg = ofbi->region;
1356
1357 WARN_ON(atomic_read(&rg->map_count));
1304 1358
1305 if (rg->paddr) 1359 if (rg->paddr)
1306 if (omap_vram_free(rg->paddr, rg->size)) 1360 if (omap_vram_free(rg->paddr, rg->size))
@@ -1355,8 +1409,15 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1355 void __iomem *vaddr; 1409 void __iomem *vaddr;
1356 int r; 1410 int r;
1357 1411
1358 rg = &ofbi->region; 1412 rg = ofbi->region;
1359 memset(rg, 0, sizeof(*rg)); 1413
1414 rg->paddr = 0;
1415 rg->vaddr = NULL;
1416 memset(&rg->vrfb, 0, sizeof rg->vrfb);
1417 rg->size = 0;
1418 rg->type = 0;
1419 rg->alloc = false;
1420 rg->map = false;
1360 1421
1361 size = PAGE_ALIGN(size); 1422 size = PAGE_ALIGN(size);
1362 1423
@@ -1609,7 +1670,7 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1609 for (i = 0; i < fbdev->num_fbs; i++) { 1670 for (i = 0; i < fbdev->num_fbs; i++) {
1610 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); 1671 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1611 struct omapfb2_mem_region *rg; 1672 struct omapfb2_mem_region *rg;
1612 rg = &ofbi->region; 1673 rg = ofbi->region;
1613 1674
1614 DBG("region%d phys %08x virt %p size=%lu\n", 1675 DBG("region%d phys %08x virt %p size=%lu\n",
1615 i, 1676 i,
@@ -1626,7 +1687,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1626 struct omapfb_info *ofbi = FB2OFB(fbi); 1687 struct omapfb_info *ofbi = FB2OFB(fbi);
1627 struct omapfb2_device *fbdev = ofbi->fbdev; 1688 struct omapfb2_device *fbdev = ofbi->fbdev;
1628 struct omap_dss_device *display = fb2display(fbi); 1689 struct omap_dss_device *display = fb2display(fbi);
1629 struct omapfb2_mem_region *rg = &ofbi->region; 1690 struct omapfb2_mem_region *rg = ofbi->region;
1630 unsigned long old_size = rg->size; 1691 unsigned long old_size = rg->size;
1631 unsigned long old_paddr = rg->paddr; 1692 unsigned long old_paddr = rg->paddr;
1632 int old_type = rg->type; 1693 int old_type = rg->type;
@@ -1709,7 +1770,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1709 fbi->flags = FBINFO_FLAG_DEFAULT; 1770 fbi->flags = FBINFO_FLAG_DEFAULT;
1710 fbi->pseudo_palette = fbdev->pseudo_palette; 1771 fbi->pseudo_palette = fbdev->pseudo_palette;
1711 1772
1712 if (ofbi->region.size == 0) { 1773 if (ofbi->region->size == 0) {
1713 clear_fb_info(fbi); 1774 clear_fb_info(fbi);
1714 return 0; 1775 return 0;
1715 } 1776 }
@@ -1871,6 +1932,10 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1871 ofbi->fbdev = fbdev; 1932 ofbi->fbdev = fbdev;
1872 ofbi->id = i; 1933 ofbi->id = i;
1873 1934
1935 ofbi->region = &fbdev->regions[i];
1936 ofbi->region->id = i;
1937 init_rwsem(&ofbi->region->lock);
1938
1874 /* assign these early, so that fb alloc can use them */ 1939 /* assign these early, so that fb alloc can use them */
1875 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : 1940 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1876 OMAP_DSS_ROT_DMA; 1941 OMAP_DSS_ROT_DMA;
@@ -1900,7 +1965,13 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1900 1965
1901 /* setup fb_infos */ 1966 /* setup fb_infos */
1902 for (i = 0; i < fbdev->num_fbs; i++) { 1967 for (i = 0; i < fbdev->num_fbs; i++) {
1903 r = omapfb_fb_init(fbdev, fbdev->fbs[i]); 1968 struct fb_info *fbi = fbdev->fbs[i];
1969 struct omapfb_info *ofbi = FB2OFB(fbi);
1970
1971 omapfb_get_mem_region(ofbi->region);
1972 r = omapfb_fb_init(fbdev, fbi);
1973 omapfb_put_mem_region(ofbi->region);
1974
1904 if (r) { 1975 if (r) {
1905 dev_err(fbdev->dev, "failed to setup fb_info\n"); 1976 dev_err(fbdev->dev, "failed to setup fb_info\n");
1906 return r; 1977 return r;
@@ -1921,20 +1992,19 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1921 DBG("framebuffers registered\n"); 1992 DBG("framebuffers registered\n");
1922 1993
1923 for (i = 0; i < fbdev->num_fbs; i++) { 1994 for (i = 0; i < fbdev->num_fbs; i++) {
1924 r = omapfb_apply_changes(fbdev->fbs[i], 1); 1995 struct fb_info *fbi = fbdev->fbs[i];
1996 struct omapfb_info *ofbi = FB2OFB(fbi);
1997
1998 omapfb_get_mem_region(ofbi->region);
1999 r = omapfb_apply_changes(fbi, 1);
2000 omapfb_put_mem_region(ofbi->region);
2001
1925 if (r) { 2002 if (r) {
1926 dev_err(fbdev->dev, "failed to change mode\n"); 2003 dev_err(fbdev->dev, "failed to change mode\n");
1927 return r; 2004 return r;
1928 } 2005 }
1929 } 2006 }
1930 2007
1931 DBG("create sysfs for fbs\n");
1932 r = omapfb_create_sysfs(fbdev);
1933 if (r) {
1934 dev_err(fbdev->dev, "failed to create sysfs entries\n");
1935 return r;
1936 }
1937
1938 /* Enable fb0 */ 2008 /* Enable fb0 */
1939 if (fbdev->num_fbs > 0) { 2009 if (fbdev->num_fbs > 0) {
1940 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); 2010 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
@@ -1968,11 +2038,11 @@ static int omapfb_mode_to_timings(const char *mode_str,
1968#ifdef CONFIG_OMAP2_DSS_VENC 2038#ifdef CONFIG_OMAP2_DSS_VENC
1969 if (strcmp(mode_str, "pal") == 0) { 2039 if (strcmp(mode_str, "pal") == 0) {
1970 *timings = omap_dss_pal_timings; 2040 *timings = omap_dss_pal_timings;
1971 *bpp = 0; 2041 *bpp = 24;
1972 return 0; 2042 return 0;
1973 } else if (strcmp(mode_str, "ntsc") == 0) { 2043 } else if (strcmp(mode_str, "ntsc") == 0) {
1974 *timings = omap_dss_ntsc_timings; 2044 *timings = omap_dss_ntsc_timings;
1975 *bpp = 0; 2045 *bpp = 24;
1976 return 0; 2046 return 0;
1977 } 2047 }
1978#endif 2048#endif
@@ -1989,10 +2059,10 @@ static int omapfb_mode_to_timings(const char *mode_str,
1989 2059
1990 if (r != 0) { 2060 if (r != 0) {
1991 timings->pixel_clock = PICOS2KHZ(var.pixclock); 2061 timings->pixel_clock = PICOS2KHZ(var.pixclock);
1992 timings->hfp = var.left_margin; 2062 timings->hbp = var.left_margin;
1993 timings->hbp = var.right_margin; 2063 timings->hfp = var.right_margin;
1994 timings->vfp = var.upper_margin; 2064 timings->vbp = var.upper_margin;
1995 timings->vbp = var.lower_margin; 2065 timings->vfp = var.lower_margin;
1996 timings->hsw = var.hsync_len; 2066 timings->hsw = var.hsync_len;
1997 timings->vsw = var.vsync_len; 2067 timings->vsw = var.vsync_len;
1998 timings->x_res = var.xres; 2068 timings->x_res = var.xres;
@@ -2128,6 +2198,16 @@ static int omapfb_probe(struct platform_device *pdev)
2128 goto err0; 2198 goto err0;
2129 } 2199 }
2130 2200
2201 /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
2202 * available for OMAP2 and OMAP3
2203 */
2204 if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
2205 def_vrfb = 0;
2206 dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
2207 "ignoring the module parameter vrfb=y\n");
2208 }
2209
2210
2131 mutex_init(&fbdev->mtx); 2211 mutex_init(&fbdev->mtx);
2132 2212
2133 fbdev->dev = &pdev->dev; 2213 fbdev->dev = &pdev->dev;
@@ -2220,6 +2300,13 @@ static int omapfb_probe(struct platform_device *pdev)
2220 } 2300 }
2221 } 2301 }
2222 2302
2303 DBG("create sysfs for fbs\n");
2304 r = omapfb_create_sysfs(fbdev);
2305 if (r) {
2306 dev_err(fbdev->dev, "failed to create sysfs entries\n");
2307 goto cleanup;
2308 }
2309
2223 return 0; 2310 return 0;
2224 2311
2225cleanup: 2312cleanup:
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 5179219128bd..6f9c72cd6bb0 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -49,6 +49,7 @@ static ssize_t store_rotate_type(struct device *dev,
49{ 49{
50 struct fb_info *fbi = dev_get_drvdata(dev); 50 struct fb_info *fbi = dev_get_drvdata(dev);
51 struct omapfb_info *ofbi = FB2OFB(fbi); 51 struct omapfb_info *ofbi = FB2OFB(fbi);
52 struct omapfb2_mem_region *rg;
52 enum omap_dss_rotation_type rot_type; 53 enum omap_dss_rotation_type rot_type;
53 int r; 54 int r;
54 55
@@ -64,9 +65,11 @@ static ssize_t store_rotate_type(struct device *dev,
64 if (rot_type == ofbi->rotation_type) 65 if (rot_type == ofbi->rotation_type)
65 goto out; 66 goto out;
66 67
67 if (ofbi->region.size) { 68 rg = omapfb_get_mem_region(ofbi->region);
69
70 if (rg->size) {
68 r = -EBUSY; 71 r = -EBUSY;
69 goto out; 72 goto put_region;
70 } 73 }
71 74
72 ofbi->rotation_type = rot_type; 75 ofbi->rotation_type = rot_type;
@@ -75,6 +78,8 @@ static ssize_t store_rotate_type(struct device *dev,
75 * Since the VRAM for this FB is not allocated at the moment we don't 78 * Since the VRAM for this FB is not allocated at the moment we don't
76 * need to do any further parameter checking at this point. 79 * need to do any further parameter checking at this point.
77 */ 80 */
81put_region:
82 omapfb_put_mem_region(rg);
78out: 83out:
79 unlock_fb_info(fbi); 84 unlock_fb_info(fbi);
80 85
@@ -97,7 +102,7 @@ static ssize_t store_mirror(struct device *dev,
97{ 102{
98 struct fb_info *fbi = dev_get_drvdata(dev); 103 struct fb_info *fbi = dev_get_drvdata(dev);
99 struct omapfb_info *ofbi = FB2OFB(fbi); 104 struct omapfb_info *ofbi = FB2OFB(fbi);
100 bool mirror; 105 unsigned long mirror;
101 int r; 106 int r;
102 struct fb_var_screeninfo new_var; 107 struct fb_var_screeninfo new_var;
103 108
@@ -111,6 +116,8 @@ static ssize_t store_mirror(struct device *dev,
111 116
112 ofbi->mirror = mirror; 117 ofbi->mirror = mirror;
113 118
119 omapfb_get_mem_region(ofbi->region);
120
114 memcpy(&new_var, &fbi->var, sizeof(new_var)); 121 memcpy(&new_var, &fbi->var, sizeof(new_var));
115 r = check_fb_var(fbi, &new_var); 122 r = check_fb_var(fbi, &new_var);
116 if (r) 123 if (r)
@@ -125,6 +132,8 @@ static ssize_t store_mirror(struct device *dev,
125 132
126 r = count; 133 r = count;
127out: 134out:
135 omapfb_put_mem_region(ofbi->region);
136
128 unlock_fb_info(fbi); 137 unlock_fb_info(fbi);
129 138
130 return r; 139 return r;
@@ -263,11 +272,15 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
263 272
264 DBG("detaching %d\n", ofbi->overlays[i]->id); 273 DBG("detaching %d\n", ofbi->overlays[i]->id);
265 274
275 omapfb_get_mem_region(ofbi->region);
276
266 omapfb_overlay_enable(ovl, 0); 277 omapfb_overlay_enable(ovl, 0);
267 278
268 if (ovl->manager) 279 if (ovl->manager)
269 ovl->manager->apply(ovl->manager); 280 ovl->manager->apply(ovl->manager);
270 281
282 omapfb_put_mem_region(ofbi->region);
283
271 for (t = i + 1; t < ofbi->num_overlays; t++) { 284 for (t = i + 1; t < ofbi->num_overlays; t++) {
272 ofbi->rotation[t-1] = ofbi->rotation[t]; 285 ofbi->rotation[t-1] = ofbi->rotation[t];
273 ofbi->overlays[t-1] = ofbi->overlays[t]; 286 ofbi->overlays[t-1] = ofbi->overlays[t];
@@ -300,7 +313,12 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
300 } 313 }
301 314
302 if (added) { 315 if (added) {
316 omapfb_get_mem_region(ofbi->region);
317
303 r = omapfb_apply_changes(fbi, 0); 318 r = omapfb_apply_changes(fbi, 0);
319
320 omapfb_put_mem_region(ofbi->region);
321
304 if (r) 322 if (r)
305 goto out; 323 goto out;
306 } 324 }
@@ -388,7 +406,12 @@ static ssize_t store_overlays_rotate(struct device *dev,
388 for (i = 0; i < num_ovls; ++i) 406 for (i = 0; i < num_ovls; ++i)
389 ofbi->rotation[i] = rotation[i]; 407 ofbi->rotation[i] = rotation[i];
390 408
409 omapfb_get_mem_region(ofbi->region);
410
391 r = omapfb_apply_changes(fbi, 0); 411 r = omapfb_apply_changes(fbi, 0);
412
413 omapfb_put_mem_region(ofbi->region);
414
392 if (r) 415 if (r)
393 goto out; 416 goto out;
394 417
@@ -408,7 +431,7 @@ static ssize_t show_size(struct device *dev,
408 struct fb_info *fbi = dev_get_drvdata(dev); 431 struct fb_info *fbi = dev_get_drvdata(dev);
409 struct omapfb_info *ofbi = FB2OFB(fbi); 432 struct omapfb_info *ofbi = FB2OFB(fbi);
410 433
411 return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size); 434 return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
412} 435}
413 436
414static ssize_t store_size(struct device *dev, struct device_attribute *attr, 437static ssize_t store_size(struct device *dev, struct device_attribute *attr,
@@ -416,6 +439,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
416{ 439{
417 struct fb_info *fbi = dev_get_drvdata(dev); 440 struct fb_info *fbi = dev_get_drvdata(dev);
418 struct omapfb_info *ofbi = FB2OFB(fbi); 441 struct omapfb_info *ofbi = FB2OFB(fbi);
442 struct omapfb2_device *fbdev = ofbi->fbdev;
443 struct omapfb2_mem_region *rg;
419 unsigned long size; 444 unsigned long size;
420 int r; 445 int r;
421 int i; 446 int i;
@@ -425,15 +450,33 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
425 if (!lock_fb_info(fbi)) 450 if (!lock_fb_info(fbi))
426 return -ENODEV; 451 return -ENODEV;
427 452
428 for (i = 0; i < ofbi->num_overlays; i++) { 453 rg = ofbi->region;
429 if (ofbi->overlays[i]->info.enabled) { 454
430 r = -EBUSY; 455 down_write_nested(&rg->lock, rg->id);
431 goto out; 456 atomic_inc(&rg->lock_count);
457
458 if (atomic_read(&rg->map_count)) {
459 r = -EBUSY;
460 goto out;
461 }
462
463 for (i = 0; i < fbdev->num_fbs; i++) {
464 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
465 int j;
466
467 if (ofbi2->region != rg)
468 continue;
469
470 for (j = 0; j < ofbi2->num_overlays; j++) {
471 if (ofbi2->overlays[j]->info.enabled) {
472 r = -EBUSY;
473 goto out;
474 }
432 } 475 }
433 } 476 }
434 477
435 if (size != ofbi->region.size) { 478 if (size != ofbi->region->size) {
436 r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type); 479 r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
437 if (r) { 480 if (r) {
438 dev_err(dev, "realloc fbmem failed\n"); 481 dev_err(dev, "realloc fbmem failed\n");
439 goto out; 482 goto out;
@@ -442,6 +485,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
442 485
443 r = count; 486 r = count;
444out: 487out:
488 atomic_dec(&rg->lock_count);
489 up_write(&rg->lock);
490
445 unlock_fb_info(fbi); 491 unlock_fb_info(fbi);
446 492
447 return r; 493 return r;
@@ -453,7 +499,7 @@ static ssize_t show_phys(struct device *dev,
453 struct fb_info *fbi = dev_get_drvdata(dev); 499 struct fb_info *fbi = dev_get_drvdata(dev);
454 struct omapfb_info *ofbi = FB2OFB(fbi); 500 struct omapfb_info *ofbi = FB2OFB(fbi);
455 501
456 return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr); 502 return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
457} 503}
458 504
459static ssize_t show_virt(struct device *dev, 505static ssize_t show_virt(struct device *dev,
@@ -462,7 +508,7 @@ static ssize_t show_virt(struct device *dev,
462 struct fb_info *fbi = dev_get_drvdata(dev); 508 struct fb_info *fbi = dev_get_drvdata(dev);
463 struct omapfb_info *ofbi = FB2OFB(fbi); 509 struct omapfb_info *ofbi = FB2OFB(fbi);
464 510
465 return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr); 511 return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
466} 512}
467 513
468static struct device_attribute omapfb_attrs[] = { 514static struct device_attribute omapfb_attrs[] = {
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index cd54fdbfd8bb..1305fc9880ba 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -27,6 +27,8 @@
27#define DEBUG 27#define DEBUG
28#endif 28#endif
29 29
30#include <linux/rwsem.h>
31
30#include <plat/display.h> 32#include <plat/display.h>
31 33
32#ifdef DEBUG 34#ifdef DEBUG
@@ -44,6 +46,7 @@ extern unsigned int omapfb_debug;
44#define OMAPFB_MAX_OVL_PER_FB 3 46#define OMAPFB_MAX_OVL_PER_FB 3
45 47
46struct omapfb2_mem_region { 48struct omapfb2_mem_region {
49 int id;
47 u32 paddr; 50 u32 paddr;
48 void __iomem *vaddr; 51 void __iomem *vaddr;
49 struct vrfb vrfb; 52 struct vrfb vrfb;
@@ -51,13 +54,15 @@ struct omapfb2_mem_region {
51 u8 type; /* OMAPFB_PLANE_MEM_* */ 54 u8 type; /* OMAPFB_PLANE_MEM_* */
52 bool alloc; /* allocated by the driver */ 55 bool alloc; /* allocated by the driver */
53 bool map; /* kernel mapped by the driver */ 56 bool map; /* kernel mapped by the driver */
57 atomic_t map_count;
58 struct rw_semaphore lock;
59 atomic_t lock_count;
54}; 60};
55 61
56/* appended to fb_info */ 62/* appended to fb_info */
57struct omapfb_info { 63struct omapfb_info {
58 int id; 64 int id;
59 struct omapfb2_mem_region region; 65 struct omapfb2_mem_region *region;
60 atomic_t map_count;
61 int num_overlays; 66 int num_overlays;
62 struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB]; 67 struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
63 struct omapfb2_device *fbdev; 68 struct omapfb2_device *fbdev;
@@ -76,6 +81,7 @@ struct omapfb2_device {
76 81
77 unsigned num_fbs; 82 unsigned num_fbs;
78 struct fb_info *fbs[10]; 83 struct fb_info *fbs[10];
84 struct omapfb2_mem_region regions[10];
79 85
80 unsigned num_displays; 86 unsigned num_displays;
81 struct omap_dss_device *displays[10]; 87 struct omap_dss_device *displays[10];
@@ -117,6 +123,9 @@ int omapfb_update_window(struct fb_info *fbi,
117int dss_mode_to_fb_mode(enum omap_color_mode dssmode, 123int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
118 struct fb_var_screeninfo *var); 124 struct fb_var_screeninfo *var);
119 125
126int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
127 u16 posx, u16 posy, u16 outw, u16 outh);
128
120/* find the display connected to this fb, if any */ 129/* find the display connected to this fb, if any */
121static inline struct omap_dss_device *fb2display(struct fb_info *fbi) 130static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
122{ 131{
@@ -148,8 +157,24 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
148 struct omap_overlay_info info; 157 struct omap_overlay_info info;
149 158
150 ovl->get_overlay_info(ovl, &info); 159 ovl->get_overlay_info(ovl, &info);
160 if (info.enabled == enable)
161 return 0;
151 info.enabled = enable; 162 info.enabled = enable;
152 return ovl->set_overlay_info(ovl, &info); 163 return ovl->set_overlay_info(ovl, &info);
153} 164}
154 165
166static inline struct omapfb2_mem_region *
167omapfb_get_mem_region(struct omapfb2_mem_region *rg)
168{
169 down_read_nested(&rg->lock, rg->id);
170 atomic_inc(&rg->lock_count);
171 return rg;
172}
173
174static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg)
175{
176 atomic_dec(&rg->lock_count);
177 up_read(&rg->lock);
178}
179
155#endif 180#endif
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
index 3b1237ad85ed..fed2a72bc6b6 100644
--- a/drivers/video/omap2/vram.c
+++ b/drivers/video/omap2/vram.c
@@ -25,7 +25,7 @@
25#include <linux/list.h> 25#include <linux/list.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/seq_file.h> 27#include <linux/seq_file.h>
28#include <linux/bootmem.h> 28#include <linux/memblock.h>
29#include <linux/completion.h> 29#include <linux/completion.h>
30#include <linux/debugfs.h> 30#include <linux/debugfs.h>
31#include <linux/jiffies.h> 31#include <linux/jiffies.h>
@@ -525,10 +525,8 @@ early_param("vram", omap_vram_early_vram);
525 * Called from map_io. We need to call to this early enough so that we 525 * Called from map_io. We need to call to this early enough so that we
526 * can reserve the fixed SDRAM regions before VM could get hold of them. 526 * can reserve the fixed SDRAM regions before VM could get hold of them.
527 */ 527 */
528void __init omap_vram_reserve_sdram(void) 528void __init omap_vram_reserve_sdram_memblock(void)
529{ 529{
530 struct bootmem_data *bdata;
531 unsigned long sdram_start, sdram_size;
532 u32 paddr; 530 u32 paddr;
533 u32 size = 0; 531 u32 size = 0;
534 532
@@ -555,29 +553,24 @@ void __init omap_vram_reserve_sdram(void)
555 553
556 size = PAGE_ALIGN(size); 554 size = PAGE_ALIGN(size);
557 555
558 bdata = NODE_DATA(0)->bdata;
559 sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
560 sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
561
562 if (paddr) { 556 if (paddr) {
563 if ((paddr & ~PAGE_MASK) || paddr < sdram_start || 557 if ((paddr & ~PAGE_MASK) ||
564 paddr + size > sdram_start + sdram_size) { 558 !memblock_is_region_memory(paddr, size)) {
565 pr_err("Illegal SDRAM region for VRAM\n"); 559 pr_err("Illegal SDRAM region for VRAM\n");
566 return; 560 return;
567 } 561 }
568 562
569 if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) { 563 if (memblock_is_region_reserved(paddr, size)) {
570 pr_err("FB: failed to reserve VRAM\n"); 564 pr_err("FB: failed to reserve VRAM - busy\n");
571 return; 565 return;
572 } 566 }
573 } else { 567
574 if (size > sdram_size) { 568 if (memblock_reserve(paddr, size) < 0) {
575 pr_err("Illegal SDRAM size for VRAM\n"); 569 pr_err("FB: failed to reserve VRAM - no memory\n");
576 return; 570 return;
577 } 571 }
578 572 } else {
579 paddr = virt_to_phys(alloc_bootmem_pages(size)); 573 paddr = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_REAL_LIMIT);
580 BUG_ON(paddr & ~PAGE_MASK);
581 } 574 }
582 575
583 omap_vram_add_region(paddr, size); 576 omap_vram_add_region(paddr, size);
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 6552751e81aa..b6c3fc2db632 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -249,7 +249,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
249 info->fix.accel = FB_ACCEL_SUN_CGTHREE; 249 info->fix.accel = FB_ACCEL_SUN_CGTHREE;
250} 250}
251 251
252static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match) 252static int __devinit p9100_probe(struct platform_device *op, const struct of_device_id *match)
253{ 253{
254 struct device_node *dp = op->dev.of_node; 254 struct device_node *dp = op->dev.of_node;
255 struct fb_info *info; 255 struct fb_info *info;
@@ -326,7 +326,7 @@ out_err:
326 return err; 326 return err;
327} 327}
328 328
329static int __devexit p9100_remove(struct of_device *op) 329static int __devexit p9100_remove(struct platform_device *op)
330{ 330{
331 struct fb_info *info = dev_get_drvdata(&op->dev); 331 struct fb_info *info = dev_get_drvdata(&op->dev);
332 struct p9100_par *par = info->par; 332 struct p9100_par *par = info->par;
@@ -367,12 +367,12 @@ static int __init p9100_init(void)
367 if (fb_get_options("p9100fb", NULL)) 367 if (fb_get_options("p9100fb", NULL))
368 return -ENODEV; 368 return -ENODEV;
369 369
370 return of_register_driver(&p9100_driver, &of_bus_type); 370 return of_register_platform_driver(&p9100_driver);
371} 371}
372 372
373static void __exit p9100_exit(void) 373static void __exit p9100_exit(void)
374{ 374{
375 of_unregister_driver(&p9100_driver); 375 of_unregister_platform_driver(&p9100_driver);
376} 376}
377 377
378module_init(p9100_init); 378module_init(p9100_init);
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 72a1f4c04732..a50e1977b316 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -533,7 +533,7 @@ static int __init platinumfb_setup(char *options)
533#define invalidate_cache(addr) 533#define invalidate_cache(addr)
534#endif 534#endif
535 535
536static int __devinit platinumfb_probe(struct of_device* odev, 536static int __devinit platinumfb_probe(struct platform_device* odev,
537 const struct of_device_id *match) 537 const struct of_device_id *match)
538{ 538{
539 struct device_node *dp = odev->dev.of_node; 539 struct device_node *dp = odev->dev.of_node;
@@ -646,7 +646,7 @@ static int __devinit platinumfb_probe(struct of_device* odev,
646 return rc; 646 return rc;
647} 647}
648 648
649static int __devexit platinumfb_remove(struct of_device* odev) 649static int __devexit platinumfb_remove(struct platform_device* odev)
650{ 650{
651 struct fb_info *info = dev_get_drvdata(&odev->dev); 651 struct fb_info *info = dev_get_drvdata(&odev->dev);
652 struct fb_info_platinum *pinfo = info->par; 652 struct fb_info_platinum *pinfo = info->par;
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index 0f361b6100d2..0c69fa20251b 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -44,7 +44,7 @@ struct pmagbafb_par {
44}; 44};
45 45
46 46
47static struct fb_var_screeninfo pmagbafb_defined __initdata = { 47static struct fb_var_screeninfo pmagbafb_defined __devinitdata = {
48 .xres = 1024, 48 .xres = 1024,
49 .yres = 864, 49 .yres = 864,
50 .xres_virtual = 1024, 50 .xres_virtual = 1024,
@@ -68,7 +68,7 @@ static struct fb_var_screeninfo pmagbafb_defined __initdata = {
68 .vmode = FB_VMODE_NONINTERLACED, 68 .vmode = FB_VMODE_NONINTERLACED,
69}; 69};
70 70
71static struct fb_fix_screeninfo pmagbafb_fix __initdata = { 71static struct fb_fix_screeninfo pmagbafb_fix __devinitdata = {
72 .id = "PMAG-BA", 72 .id = "PMAG-BA",
73 .smem_len = (1024 * 1024), 73 .smem_len = (1024 * 1024),
74 .type = FB_TYPE_PACKED_PIXELS, 74 .type = FB_TYPE_PACKED_PIXELS,
@@ -142,7 +142,7 @@ static void __init pmagbafb_erase_cursor(struct fb_info *info)
142} 142}
143 143
144 144
145static int __init pmagbafb_probe(struct device *dev) 145static int __devinit pmagbafb_probe(struct device *dev)
146{ 146{
147 struct tc_dev *tdev = to_tc_dev(dev); 147 struct tc_dev *tdev = to_tc_dev(dev);
148 resource_size_t start, len; 148 resource_size_t start, len;
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 2de0806421b4..22fcb9a3d5c0 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -45,7 +45,7 @@ struct pmagbbfb_par {
45}; 45};
46 46
47 47
48static struct fb_var_screeninfo pmagbbfb_defined __initdata = { 48static struct fb_var_screeninfo pmagbbfb_defined __devinitdata = {
49 .bits_per_pixel = 8, 49 .bits_per_pixel = 8,
50 .red.length = 8, 50 .red.length = 8,
51 .green.length = 8, 51 .green.length = 8,
@@ -58,7 +58,7 @@ static struct fb_var_screeninfo pmagbbfb_defined __initdata = {
58 .vmode = FB_VMODE_NONINTERLACED, 58 .vmode = FB_VMODE_NONINTERLACED,
59}; 59};
60 60
61static struct fb_fix_screeninfo pmagbbfb_fix __initdata = { 61static struct fb_fix_screeninfo pmagbbfb_fix __devinitdata = {
62 .id = "PMAGB-BA", 62 .id = "PMAGB-BA",
63 .smem_len = (2048 * 1024), 63 .smem_len = (2048 * 1024),
64 .type = FB_TYPE_PACKED_PIXELS, 64 .type = FB_TYPE_PACKED_PIXELS,
@@ -148,7 +148,7 @@ static void __init pmagbbfb_erase_cursor(struct fb_info *info)
148/* 148/*
149 * Set up screen parameters. 149 * Set up screen parameters.
150 */ 150 */
151static void __init pmagbbfb_screen_setup(struct fb_info *info) 151static void __devinit pmagbbfb_screen_setup(struct fb_info *info)
152{ 152{
153 struct pmagbbfb_par *par = info->par; 153 struct pmagbbfb_par *par = info->par;
154 154
@@ -180,9 +180,9 @@ static void __init pmagbbfb_screen_setup(struct fb_info *info)
180/* 180/*
181 * Determine oscillator configuration. 181 * Determine oscillator configuration.
182 */ 182 */
183static void __init pmagbbfb_osc_setup(struct fb_info *info) 183static void __devinit pmagbbfb_osc_setup(struct fb_info *info)
184{ 184{
185 static unsigned int pmagbbfb_freqs[] __initdata = { 185 static unsigned int pmagbbfb_freqs[] __devinitdata = {
186 130808, 119843, 104000, 92980, 74370, 72800, 186 130808, 119843, 104000, 92980, 74370, 72800,
187 69197, 66000, 65000, 50350, 36000, 32000, 25175 187 69197, 66000, 65000, 50350, 36000, 32000, 25175
188 }; 188 };
@@ -247,7 +247,7 @@ static void __init pmagbbfb_osc_setup(struct fb_info *info)
247}; 247};
248 248
249 249
250static int __init pmagbbfb_probe(struct device *dev) 250static int __devinit pmagbbfb_probe(struct device *dev)
251{ 251{
252 struct tc_dev *tdev = to_tc_dev(dev); 252 struct tc_dev *tdev = to_tc_dev(dev);
253 resource_size_t start, len; 253 resource_size_t start, len;
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index c91a7f70f7b0..cea6403ae71c 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -298,8 +298,8 @@ static void set_dma_control0(struct pxa168fb_info *fbi)
298 * Set bit to enable graphics DMA. 298 * Set bit to enable graphics DMA.
299 */ 299 */
300 x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0); 300 x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
301 x |= fbi->active ? 0x00000100 : 0; 301 x &= ~CFG_GRA_ENA_MASK;
302 fbi->active = 0; 302 x |= fbi->active ? CFG_GRA_ENA(1) : CFG_GRA_ENA(0);
303 303
304 /* 304 /*
305 * If we are in a pseudo-color mode, we need to enable 305 * If we are in a pseudo-color mode, we need to enable
@@ -559,7 +559,7 @@ static struct fb_ops pxa168fb_ops = {
559 .fb_imageblit = cfb_imageblit, 559 .fb_imageblit = cfb_imageblit,
560}; 560};
561 561
562static int __init pxa168fb_init_mode(struct fb_info *info, 562static int __devinit pxa168fb_init_mode(struct fb_info *info,
563 struct pxa168fb_mach_info *mi) 563 struct pxa168fb_mach_info *mi)
564{ 564{
565 struct pxa168fb_info *fbi = info->par; 565 struct pxa168fb_info *fbi = info->par;
@@ -599,7 +599,7 @@ static int __init pxa168fb_init_mode(struct fb_info *info,
599 return ret; 599 return ret;
600} 600}
601 601
602static int __init pxa168fb_probe(struct platform_device *pdev) 602static int __devinit pxa168fb_probe(struct platform_device *pdev)
603{ 603{
604 struct pxa168fb_mach_info *mi; 604 struct pxa168fb_mach_info *mi;
605 struct fb_info *info = 0; 605 struct fb_info *info = 0;
@@ -784,20 +784,67 @@ failed:
784 return ret; 784 return ret;
785} 785}
786 786
787static int __devexit pxa168fb_remove(struct platform_device *pdev)
788{
789 struct pxa168fb_info *fbi = platform_get_drvdata(pdev);
790 struct fb_info *info;
791 int irq;
792 unsigned int data;
793
794 if (!fbi)
795 return 0;
796
797 /* disable DMA transfer */
798 data = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
799 data &= ~CFG_GRA_ENA_MASK;
800 writel(data, fbi->reg_base + LCD_SPU_DMA_CTRL0);
801
802 info = fbi->info;
803
804 unregister_framebuffer(info);
805
806 writel(GRA_FRAME_IRQ0_ENA(0x0), fbi->reg_base + SPU_IRQ_ENA);
807
808 if (info->cmap.len)
809 fb_dealloc_cmap(&info->cmap);
810
811 irq = platform_get_irq(pdev, 0);
812 free_irq(irq, fbi);
813
814 dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
815 info->screen_base, info->fix.smem_start);
816
817 iounmap(fbi->reg_base);
818
819 clk_disable(fbi->clk);
820 clk_put(fbi->clk);
821
822 framebuffer_release(info);
823
824 return 0;
825}
826
787static struct platform_driver pxa168fb_driver = { 827static struct platform_driver pxa168fb_driver = {
788 .driver = { 828 .driver = {
789 .name = "pxa168-fb", 829 .name = "pxa168-fb",
790 .owner = THIS_MODULE, 830 .owner = THIS_MODULE,
791 }, 831 },
792 .probe = pxa168fb_probe, 832 .probe = pxa168fb_probe,
833 .remove = __devexit_p(pxa168fb_remove),
793}; 834};
794 835
795static int __devinit pxa168fb_init(void) 836static int __init pxa168fb_init(void)
796{ 837{
797 return platform_driver_register(&pxa168fb_driver); 838 return platform_driver_register(&pxa168fb_driver);
798} 839}
799module_init(pxa168fb_init); 840module_init(pxa168fb_init);
800 841
842static void __exit pxa168fb_exit(void)
843{
844 platform_driver_unregister(&pxa168fb_driver);
845}
846module_exit(pxa168fb_exit);
847
801MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> " 848MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
802 "Green Wan <gwan@marvell.com>"); 849 "Green Wan <gwan@marvell.com>");
803MODULE_DESCRIPTION("Framebuffer driver for PXA168/910"); 850MODULE_DESCRIPTION("Framebuffer driver for PXA168/910");
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index fc32c323a381..f5a39f5aa900 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -28,7 +28,7 @@
28 28
29#define Q40_PHYS_SCREEN_ADDR 0xFE800000 29#define Q40_PHYS_SCREEN_ADDR 0xFE800000
30 30
31static struct fb_fix_screeninfo q40fb_fix __initdata = { 31static struct fb_fix_screeninfo q40fb_fix __devinitdata = {
32 .id = "Q40", 32 .id = "Q40",
33 .smem_len = 1024*1024, 33 .smem_len = 1024*1024,
34 .type = FB_TYPE_PACKED_PIXELS, 34 .type = FB_TYPE_PACKED_PIXELS,
@@ -37,7 +37,7 @@ static struct fb_fix_screeninfo q40fb_fix __initdata = {
37 .accel = FB_ACCEL_NONE, 37 .accel = FB_ACCEL_NONE,
38}; 38};
39 39
40static struct fb_var_screeninfo q40fb_var __initdata = { 40static struct fb_var_screeninfo q40fb_var __devinitdata = {
41 .xres = 1024, 41 .xres = 1024,
42 .yres = 512, 42 .yres = 512,
43 .xres_virtual = 1024, 43 .xres_virtual = 1024,
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 9682ecc60e12..f9aca9d13d1b 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1,7 +1,7 @@
1/* linux/drivers/video/s3c-fb.c 1/* linux/drivers/video/s3c-fb.c
2 * 2 *
3 * Copyright 2008 Openmoko Inc. 3 * Copyright 2008 Openmoko Inc.
4 * Copyright 2008 Simtec Electronics 4 * Copyright 2008-2010 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk> 5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/ 6 * http://armlinux.simtec.co.uk/
7 * 7 *
@@ -9,7 +9,7 @@
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software FoundatIon.
13*/ 13*/
14 14
15#include <linux/kernel.h> 15#include <linux/kernel.h>
@@ -21,9 +21,11 @@
21#include <linux/clk.h> 21#include <linux/clk.h>
22#include <linux/fb.h> 22#include <linux/fb.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/uaccess.h>
25#include <linux/interrupt.h>
24 26
25#include <mach/map.h> 27#include <mach/map.h>
26#include <mach/regs-fb.h> 28#include <plat/regs-fb-v4.h>
27#include <plat/fb.h> 29#include <plat/fb.h>
28 30
29/* This driver will export a number of framebuffer interfaces depending 31/* This driver will export a number of framebuffer interfaces depending
@@ -36,9 +38,9 @@
36 * output timings and as the control for the output power-down state. 38 * output timings and as the control for the output power-down state.
37*/ 39*/
38 40
39/* note, some of the functions that get called are derived from including 41/* note, the previous use of <mach/regs-fb.h> to get platform specific data
40 * <mach/regs-fb.h> as they are specific to the architecture that the code 42 * has been replaced by using the platform device name to pick the correct
41 * is being built for. 43 * configuration data for the system.
42*/ 44*/
43 45
44#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE 46#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE
@@ -48,13 +50,108 @@
48 __raw_writel(v, r); } while(0) 50 __raw_writel(v, r); } while(0)
49#endif /* FB_S3C_DEBUG_REGWRITE */ 51#endif /* FB_S3C_DEBUG_REGWRITE */
50 52
53/* irq_flags bits */
54#define S3C_FB_VSYNC_IRQ_EN 0
55
56#define VSYNC_TIMEOUT_MSEC 50
57
51struct s3c_fb; 58struct s3c_fb;
52 59
60#define VALID_BPP(x) (1 << ((x) - 1))
61
62#define OSD_BASE(win, variant) ((variant).osd + ((win) * (variant).osd_stride))
63#define VIDOSD_A(win, variant) (OSD_BASE(win, variant) + 0x00)
64#define VIDOSD_B(win, variant) (OSD_BASE(win, variant) + 0x04)
65#define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08)
66#define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C)
67
68/**
69 * struct s3c_fb_variant - fb variant information
70 * @is_2443: Set if S3C2443/S3C2416 style hardware.
71 * @nr_windows: The number of windows.
72 * @vidtcon: The base for the VIDTCONx registers
73 * @wincon: The base for the WINxCON registers.
74 * @winmap: The base for the WINxMAP registers.
75 * @keycon: The abse for the WxKEYCON registers.
76 * @buf_start: Offset of buffer start registers.
77 * @buf_size: Offset of buffer size registers.
78 * @buf_end: Offset of buffer end registers.
79 * @osd: The base for the OSD registers.
80 * @palette: Address of palette memory, or 0 if none.
81 * @has_prtcon: Set if has PRTCON register.
82 * @has_shadowcon: Set if has SHADOWCON register.
83 */
84struct s3c_fb_variant {
85 unsigned int is_2443:1;
86 unsigned short nr_windows;
87 unsigned short vidtcon;
88 unsigned short wincon;
89 unsigned short winmap;
90 unsigned short keycon;
91 unsigned short buf_start;
92 unsigned short buf_end;
93 unsigned short buf_size;
94 unsigned short osd;
95 unsigned short osd_stride;
96 unsigned short palette[S3C_FB_MAX_WIN];
97
98 unsigned int has_prtcon:1;
99 unsigned int has_shadowcon:1;
100};
101
102/**
103 * struct s3c_fb_win_variant
104 * @has_osd_c: Set if has OSD C register.
105 * @has_osd_d: Set if has OSD D register.
106 * @has_osd_alpha: Set if can change alpha transparency for a window.
107 * @palette_sz: Size of palette in entries.
108 * @palette_16bpp: Set if palette is 16bits wide.
109 * @osd_size_off: If != 0, supports setting up OSD for a window; the appropriate
110 * register is located at the given offset from OSD_BASE.
111 * @valid_bpp: 1 bit per BPP setting to show valid bits-per-pixel.
112 *
113 * valid_bpp bit x is set if (x+1)BPP is supported.
114 */
115struct s3c_fb_win_variant {
116 unsigned int has_osd_c:1;
117 unsigned int has_osd_d:1;
118 unsigned int has_osd_alpha:1;
119 unsigned int palette_16bpp:1;
120 unsigned short osd_size_off;
121 unsigned short palette_sz;
122 u32 valid_bpp;
123};
124
125/**
126 * struct s3c_fb_driverdata - per-device type driver data for init time.
127 * @variant: The variant information for this driver.
128 * @win: The window information for each window.
129 */
130struct s3c_fb_driverdata {
131 struct s3c_fb_variant variant;
132 struct s3c_fb_win_variant *win[S3C_FB_MAX_WIN];
133};
134
135/**
136 * struct s3c_fb_palette - palette information
137 * @r: Red bitfield.
138 * @g: Green bitfield.
139 * @b: Blue bitfield.
140 * @a: Alpha bitfield.
141 */
142struct s3c_fb_palette {
143 struct fb_bitfield r;
144 struct fb_bitfield g;
145 struct fb_bitfield b;
146 struct fb_bitfield a;
147};
148
53/** 149/**
54 * struct s3c_fb_win - per window private data for each framebuffer. 150 * struct s3c_fb_win - per window private data for each framebuffer.
55 * @windata: The platform data supplied for the window configuration. 151 * @windata: The platform data supplied for the window configuration.
56 * @parent: The hardware that this window is part of. 152 * @parent: The hardware that this window is part of.
57 * @fbinfo: Pointer pack to the framebuffer info for this window. 153 * @fbinfo: Pointer pack to the framebuffer info for this window.
154 * @varint: The variant information for this window.
58 * @palette_buffer: Buffer/cache to hold palette entries. 155 * @palette_buffer: Buffer/cache to hold palette entries.
59 * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/ 156 * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/
60 * @index: The window number of this window. 157 * @index: The window number of this window.
@@ -65,6 +162,7 @@ struct s3c_fb_win {
65 struct s3c_fb *parent; 162 struct s3c_fb *parent;
66 struct fb_info *fbinfo; 163 struct fb_info *fbinfo;
67 struct s3c_fb_palette palette; 164 struct s3c_fb_palette palette;
165 struct s3c_fb_win_variant variant;
68 166
69 u32 *palette_buffer; 167 u32 *palette_buffer;
70 u32 pseudo_palette[16]; 168 u32 pseudo_palette[16];
@@ -72,37 +170,54 @@ struct s3c_fb_win {
72}; 170};
73 171
74/** 172/**
173 * struct s3c_fb_vsync - vsync information
174 * @wait: a queue for processes waiting for vsync
175 * @count: vsync interrupt count
176 */
177struct s3c_fb_vsync {
178 wait_queue_head_t wait;
179 unsigned int count;
180};
181
182/**
75 * struct s3c_fb - overall hardware state of the hardware 183 * struct s3c_fb - overall hardware state of the hardware
76 * @dev: The device that we bound to, for printing, etc. 184 * @dev: The device that we bound to, for printing, etc.
77 * @regs_res: The resource we claimed for the IO registers. 185 * @regs_res: The resource we claimed for the IO registers.
78 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. 186 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
79 * @regs: The mapped hardware registers. 187 * @regs: The mapped hardware registers.
188 * @variant: Variant information for this hardware.
80 * @enabled: A bitmask of enabled hardware windows. 189 * @enabled: A bitmask of enabled hardware windows.
81 * @pdata: The platform configuration data passed with the device. 190 * @pdata: The platform configuration data passed with the device.
82 * @windows: The hardware windows that have been claimed. 191 * @windows: The hardware windows that have been claimed.
192 * @irq_no: IRQ line number
193 * @irq_flags: irq flags
194 * @vsync_info: VSYNC-related information (count, queues...)
83 */ 195 */
84struct s3c_fb { 196struct s3c_fb {
85 struct device *dev; 197 struct device *dev;
86 struct resource *regs_res; 198 struct resource *regs_res;
87 struct clk *bus_clk; 199 struct clk *bus_clk;
88 void __iomem *regs; 200 void __iomem *regs;
201 struct s3c_fb_variant variant;
89 202
90 unsigned char enabled; 203 unsigned char enabled;
91 204
92 struct s3c_fb_platdata *pdata; 205 struct s3c_fb_platdata *pdata;
93 struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; 206 struct s3c_fb_win *windows[S3C_FB_MAX_WIN];
207
208 int irq_no;
209 unsigned long irq_flags;
210 struct s3c_fb_vsync vsync_info;
94}; 211};
95 212
96/** 213/**
97 * s3c_fb_win_has_palette() - determine if a mode has a palette 214 * s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode.
98 * @win: The window number being queried. 215 * @win: The device window.
99 * @bpp: The number of bits per pixel to test. 216 * @bpp: The bit depth.
100 *
101 * Work out if the given window supports palletised data at the specified bpp.
102 */ 217 */
103static int s3c_fb_win_has_palette(unsigned int win, unsigned int bpp) 218static bool s3c_fb_validate_win_bpp(struct s3c_fb_win *win, unsigned int bpp)
104{ 219{
105 return s3c_fb_win_pal_size(win) <= (1 << bpp); 220 return win->variant.valid_bpp & VALID_BPP(bpp);
106} 221}
107 222
108/** 223/**
@@ -125,7 +240,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
125 var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres); 240 var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres);
126 var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres); 241 var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres);
127 242
128 if (!s3c_fb_validate_win_bpp(win->index, var->bits_per_pixel)) { 243 if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) {
129 dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", 244 dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n",
130 win->index, var->bits_per_pixel); 245 win->index, var->bits_per_pixel);
131 return -EINVAL; 246 return -EINVAL;
@@ -140,7 +255,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
140 case 2: 255 case 2:
141 case 4: 256 case 4:
142 case 8: 257 case 8:
143 if (!s3c_fb_win_has_palette(win->index, var->bits_per_pixel)) { 258 if (sfb->variant.palette[win->index] != 0) {
144 /* non palletised, A:1,R:2,G:3,B:2 mode */ 259 /* non palletised, A:1,R:2,G:3,B:2 mode */
145 var->red.offset = 4; 260 var->red.offset = 4;
146 var->green.offset = 2; 261 var->green.offset = 2;
@@ -255,6 +370,66 @@ static int s3c_fb_align_word(unsigned int bpp, unsigned int pix)
255} 370}
256 371
257/** 372/**
373 * vidosd_set_size() - set OSD size for a window
374 *
375 * @win: the window to set OSD size for
376 * @size: OSD size register value
377 */
378static void vidosd_set_size(struct s3c_fb_win *win, u32 size)
379{
380 struct s3c_fb *sfb = win->parent;
381
382 /* OSD can be set up if osd_size_off != 0 for this window */
383 if (win->variant.osd_size_off)
384 writel(size, sfb->regs + OSD_BASE(win->index, sfb->variant)
385 + win->variant.osd_size_off);
386}
387
388/**
389 * vidosd_set_alpha() - set alpha transparency for a window
390 *
391 * @win: the window to set OSD size for
392 * @alpha: alpha register value
393 */
394static void vidosd_set_alpha(struct s3c_fb_win *win, u32 alpha)
395{
396 struct s3c_fb *sfb = win->parent;
397
398 if (win->variant.has_osd_alpha)
399 writel(alpha, sfb->regs + VIDOSD_C(win->index, sfb->variant));
400}
401
402/**
403 * shadow_protect_win() - disable updating values from shadow registers at vsync
404 *
405 * @win: window to protect registers for
406 * @protect: 1 to protect (disable updates)
407 */
408static void shadow_protect_win(struct s3c_fb_win *win, bool protect)
409{
410 struct s3c_fb *sfb = win->parent;
411 u32 reg;
412
413 if (protect) {
414 if (sfb->variant.has_prtcon) {
415 writel(PRTCON_PROTECT, sfb->regs + PRTCON);
416 } else if (sfb->variant.has_shadowcon) {
417 reg = readl(sfb->regs + SHADOWCON);
418 writel(reg | SHADOWCON_WINx_PROTECT(win->index),
419 sfb->regs + SHADOWCON);
420 }
421 } else {
422 if (sfb->variant.has_prtcon) {
423 writel(0, sfb->regs + PRTCON);
424 } else if (sfb->variant.has_shadowcon) {
425 reg = readl(sfb->regs + SHADOWCON);
426 writel(reg & ~SHADOWCON_WINx_PROTECT(win->index),
427 sfb->regs + SHADOWCON);
428 }
429 }
430}
431
432/**
258 * s3c_fb_set_par() - framebuffer request to set new framebuffer state. 433 * s3c_fb_set_par() - framebuffer request to set new framebuffer state.
259 * @info: The framebuffer to change. 434 * @info: The framebuffer to change.
260 * 435 *
@@ -266,14 +441,17 @@ static int s3c_fb_set_par(struct fb_info *info)
266 struct s3c_fb_win *win = info->par; 441 struct s3c_fb_win *win = info->par;
267 struct s3c_fb *sfb = win->parent; 442 struct s3c_fb *sfb = win->parent;
268 void __iomem *regs = sfb->regs; 443 void __iomem *regs = sfb->regs;
444 void __iomem *buf = regs;
269 int win_no = win->index; 445 int win_no = win->index;
270 u32 osdc_data = 0; 446 u32 alpha = 0;
271 u32 data; 447 u32 data;
272 u32 pagewidth; 448 u32 pagewidth;
273 int clkdiv; 449 int clkdiv;
274 450
275 dev_dbg(sfb->dev, "setting framebuffer parameters\n"); 451 dev_dbg(sfb->dev, "setting framebuffer parameters\n");
276 452
453 shadow_protect_win(win, 1);
454
277 switch (var->bits_per_pixel) { 455 switch (var->bits_per_pixel) {
278 case 32: 456 case 32:
279 case 24: 457 case 24:
@@ -282,7 +460,7 @@ static int s3c_fb_set_par(struct fb_info *info)
282 info->fix.visual = FB_VISUAL_TRUECOLOR; 460 info->fix.visual = FB_VISUAL_TRUECOLOR;
283 break; 461 break;
284 case 8: 462 case 8:
285 if (s3c_fb_win_has_palette(win_no, 8)) 463 if (win->variant.palette_sz >= 256)
286 info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 464 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
287 else 465 else
288 info->fix.visual = FB_VISUAL_TRUECOLOR; 466 info->fix.visual = FB_VISUAL_TRUECOLOR;
@@ -297,12 +475,15 @@ static int s3c_fb_set_par(struct fb_info *info)
297 475
298 info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; 476 info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
299 477
478 info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
479 info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
480
300 /* disable the window whilst we update it */ 481 /* disable the window whilst we update it */
301 writel(0, regs + WINCON(win_no)); 482 writel(0, regs + WINCON(win_no));
302 483
303 /* use window 0 as the basis for the lcd output timings */ 484 /* use platform specified window as the basis for the lcd timings */
304 485
305 if (win_no == 0) { 486 if (win_no == sfb->pdata->default_win) {
306 clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); 487 clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
307 488
308 data = sfb->pdata->vidcon0; 489 data = sfb->pdata->vidcon0;
@@ -315,6 +496,9 @@ static int s3c_fb_set_par(struct fb_info *info)
315 496
316 /* write the timing data to the panel */ 497 /* write the timing data to the panel */
317 498
499 if (sfb->variant.is_2443)
500 data |= (1 << 5);
501
318 data |= VIDCON0_ENVID | VIDCON0_ENVID_F; 502 data |= VIDCON0_ENVID | VIDCON0_ENVID_F;
319 writel(data, regs + VIDCON0); 503 writel(data, regs + VIDCON0);
320 504
@@ -322,53 +506,54 @@ static int s3c_fb_set_par(struct fb_info *info)
322 VIDTCON0_VFPD(var->lower_margin - 1) | 506 VIDTCON0_VFPD(var->lower_margin - 1) |
323 VIDTCON0_VSPW(var->vsync_len - 1); 507 VIDTCON0_VSPW(var->vsync_len - 1);
324 508
325 writel(data, regs + VIDTCON0); 509 writel(data, regs + sfb->variant.vidtcon);
326 510
327 data = VIDTCON1_HBPD(var->left_margin - 1) | 511 data = VIDTCON1_HBPD(var->left_margin - 1) |
328 VIDTCON1_HFPD(var->right_margin - 1) | 512 VIDTCON1_HFPD(var->right_margin - 1) |
329 VIDTCON1_HSPW(var->hsync_len - 1); 513 VIDTCON1_HSPW(var->hsync_len - 1);
330 514
331 writel(data, regs + VIDTCON1); 515 /* VIDTCON1 */
516 writel(data, regs + sfb->variant.vidtcon + 4);
332 517
333 data = VIDTCON2_LINEVAL(var->yres - 1) | 518 data = VIDTCON2_LINEVAL(var->yres - 1) |
334 VIDTCON2_HOZVAL(var->xres - 1); 519 VIDTCON2_HOZVAL(var->xres - 1);
335 writel(data, regs + VIDTCON2); 520 writel(data, regs +sfb->variant.vidtcon + 8 );
336 } 521 }
337 522
338 /* write the buffer address */ 523 /* write the buffer address */
339 524
340 writel(info->fix.smem_start, regs + VIDW_BUF_START(win_no)); 525 /* start and end registers stride is 8 */
526 buf = regs + win_no * 8;
527
528 writel(info->fix.smem_start, buf + sfb->variant.buf_start);
341 529
342 data = info->fix.smem_start + info->fix.line_length * var->yres; 530 data = info->fix.smem_start + info->fix.line_length * var->yres;
343 writel(data, regs + VIDW_BUF_END(win_no)); 531 writel(data, buf + sfb->variant.buf_end);
344 532
345 pagewidth = (var->xres * var->bits_per_pixel) >> 3; 533 pagewidth = (var->xres * var->bits_per_pixel) >> 3;
346 data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) | 534 data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) |
347 VIDW_BUF_SIZE_PAGEWIDTH(pagewidth); 535 VIDW_BUF_SIZE_PAGEWIDTH(pagewidth);
348 writel(data, regs + VIDW_BUF_SIZE(win_no)); 536 writel(data, regs + sfb->variant.buf_size + (win_no * 4));
349 537
350 /* write 'OSD' registers to control position of framebuffer */ 538 /* write 'OSD' registers to control position of framebuffer */
351 539
352 data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0); 540 data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0);
353 writel(data, regs + VIDOSD_A(win_no)); 541 writel(data, regs + VIDOSD_A(win_no, sfb->variant));
354 542
355 data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel, 543 data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
356 var->xres - 1)) | 544 var->xres - 1)) |
357 VIDOSDxB_BOTRIGHT_Y(var->yres - 1); 545 VIDOSDxB_BOTRIGHT_Y(var->yres - 1);
358 546
359 writel(data, regs + VIDOSD_B(win_no)); 547 writel(data, regs + VIDOSD_B(win_no, sfb->variant));
360 548
361 data = var->xres * var->yres; 549 data = var->xres * var->yres;
362 550
363 osdc_data = VIDISD14C_ALPHA1_R(0xf) | 551 alpha = VIDISD14C_ALPHA1_R(0xf) |
364 VIDISD14C_ALPHA1_G(0xf) | 552 VIDISD14C_ALPHA1_G(0xf) |
365 VIDISD14C_ALPHA1_B(0xf); 553 VIDISD14C_ALPHA1_B(0xf);
366 554
367 if (s3c_fb_has_osd_d(win_no)) { 555 vidosd_set_alpha(win, alpha);
368 writel(data, regs + VIDOSD_D(win_no)); 556 vidosd_set_size(win, data);
369 writel(osdc_data, regs + VIDOSD_C(win_no));
370 } else
371 writel(data, regs + VIDOSD_C(win_no));
372 557
373 data = WINCONx_ENWIN; 558 data = WINCONx_ENWIN;
374 559
@@ -424,13 +609,15 @@ static int s3c_fb_set_par(struct fb_info *info)
424 else 609 else
425 data |= WINCON0_BPPMODE_24BPP_888; 610 data |= WINCON0_BPPMODE_24BPP_888;
426 611
612 data |= WINCONx_WSWP;
427 data |= WINCONx_BURSTLEN_16WORD; 613 data |= WINCONx_BURSTLEN_16WORD;
428 break; 614 break;
429 } 615 }
430 616
431 /* It has no color key control register for window0 */ 617 /* Enable the colour keying for the window below this one */
432 if (win_no > 0) { 618 if (win_no > 0) {
433 u32 keycon0_data = 0, keycon1_data = 0; 619 u32 keycon0_data = 0, keycon1_data = 0;
620 void __iomem *keycon = regs + sfb->variant.keycon;
434 621
435 keycon0_data = ~(WxKEYCON0_KEYBL_EN | 622 keycon0_data = ~(WxKEYCON0_KEYBL_EN |
436 WxKEYCON0_KEYEN_F | 623 WxKEYCON0_KEYEN_F |
@@ -438,12 +625,23 @@ static int s3c_fb_set_par(struct fb_info *info)
438 625
439 keycon1_data = WxKEYCON1_COLVAL(0xffffff); 626 keycon1_data = WxKEYCON1_COLVAL(0xffffff);
440 627
441 writel(keycon0_data, regs + WxKEYCONy(win_no-1, 0)); 628 keycon += (win_no - 1) * 8;
442 writel(keycon1_data, regs + WxKEYCONy(win_no-1, 1)); 629
630 writel(keycon0_data, keycon + WKEYCON0);
631 writel(keycon1_data, keycon + WKEYCON1);
632 }
633
634 writel(data, regs + sfb->variant.wincon + (win_no * 4));
635 writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
636
637 /* Enable DMA channel for this window */
638 if (sfb->variant.has_shadowcon) {
639 data = readl(sfb->regs + SHADOWCON);
640 data |= SHADOWCON_CHx_ENABLE(win_no);
641 writel(data, sfb->regs + SHADOWCON);
443 } 642 }
444 643
445 writel(data, regs + WINCON(win_no)); 644 shadow_protect_win(win, 0);
446 writel(0x0, regs + WINxMAP(win_no));
447 645
448 return 0; 646 return 0;
449} 647}
@@ -470,7 +668,7 @@ static void s3c_fb_update_palette(struct s3c_fb *sfb,
470 void __iomem *palreg; 668 void __iomem *palreg;
471 u32 palcon; 669 u32 palcon;
472 670
473 palreg = sfb->regs + s3c_fb_pal_reg(win->index, reg); 671 palreg = sfb->regs + sfb->variant.palette[win->index];
474 672
475 dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n", 673 dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n",
476 __func__, win->index, reg, palreg, value); 674 __func__, win->index, reg, palreg, value);
@@ -480,10 +678,10 @@ static void s3c_fb_update_palette(struct s3c_fb *sfb,
480 palcon = readl(sfb->regs + WPALCON); 678 palcon = readl(sfb->regs + WPALCON);
481 writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON); 679 writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON);
482 680
483 if (s3c_fb_pal_is16(win->index)) 681 if (win->variant.palette_16bpp)
484 writew(value, palreg); 682 writew(value, palreg + (reg * 2));
485 else 683 else
486 writel(value, palreg); 684 writel(value, palreg + (reg * 4));
487 685
488 writel(palcon, sfb->regs + WPALCON); 686 writel(palcon, sfb->regs + WPALCON);
489} 687}
@@ -532,7 +730,7 @@ static int s3c_fb_setcolreg(unsigned regno,
532 break; 730 break;
533 731
534 case FB_VISUAL_PSEUDOCOLOR: 732 case FB_VISUAL_PSEUDOCOLOR:
535 if (regno < s3c_fb_win_pal_size(win->index)) { 733 if (regno < win->variant.palette_sz) {
536 val = chan_to_field(red, &win->palette.r); 734 val = chan_to_field(red, &win->palette.r);
537 val |= chan_to_field(green, &win->palette.g); 735 val |= chan_to_field(green, &win->palette.g);
538 val |= chan_to_field(blue, &win->palette.b); 736 val |= chan_to_field(blue, &win->palette.b);
@@ -591,7 +789,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
591 789
592 dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); 790 dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
593 791
594 wincon = readl(sfb->regs + WINCON(index)); 792 wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
595 793
596 switch (blank_mode) { 794 switch (blank_mode) {
597 case FB_BLANK_POWERDOWN: 795 case FB_BLANK_POWERDOWN:
@@ -602,11 +800,11 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
602 case FB_BLANK_NORMAL: 800 case FB_BLANK_NORMAL:
603 /* disable the DMA and display 0x0 (black) */ 801 /* disable the DMA and display 0x0 (black) */
604 writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), 802 writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0),
605 sfb->regs + WINxMAP(index)); 803 sfb->regs + sfb->variant.winmap + (index * 4));
606 break; 804 break;
607 805
608 case FB_BLANK_UNBLANK: 806 case FB_BLANK_UNBLANK:
609 writel(0x0, sfb->regs + WINxMAP(index)); 807 writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4));
610 wincon |= WINCONx_ENWIN; 808 wincon |= WINCONx_ENWIN;
611 sfb->enabled |= (1 << index); 809 sfb->enabled |= (1 << index);
612 break; 810 break;
@@ -617,7 +815,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
617 return 1; 815 return 1;
618 } 816 }
619 817
620 writel(wincon, sfb->regs + WINCON(index)); 818 writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4));
621 819
622 /* Check the enabled state to see if we need to be running the 820 /* Check the enabled state to see if we need to be running the
623 * main LCD interface, as if there are no active windows then 821 * main LCD interface, as if there are no active windows then
@@ -636,12 +834,185 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
636 /* we're stuck with this until we can do something about overriding 834 /* we're stuck with this until we can do something about overriding
637 * the power control using the blanking event for a single fb. 835 * the power control using the blanking event for a single fb.
638 */ 836 */
639 if (index == 0) 837 if (index == sfb->pdata->default_win)
640 s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); 838 s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0);
641 839
642 return 0; 840 return 0;
643} 841}
644 842
843/**
844 * s3c_fb_pan_display() - Pan the display.
845 *
846 * Note that the offsets can be written to the device at any time, as their
847 * values are latched at each vsync automatically. This also means that only
848 * the last call to this function will have any effect on next vsync, but
849 * there is no need to sleep waiting for it to prevent tearing.
850 *
851 * @var: The screen information to verify.
852 * @info: The framebuffer device.
853 */
854static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
855 struct fb_info *info)
856{
857 struct s3c_fb_win *win = info->par;
858 struct s3c_fb *sfb = win->parent;
859 void __iomem *buf = sfb->regs + win->index * 8;
860 unsigned int start_boff, end_boff;
861
862 /* Offset in bytes to the start of the displayed area */
863 start_boff = var->yoffset * info->fix.line_length;
864 /* X offset depends on the current bpp */
865 if (info->var.bits_per_pixel >= 8) {
866 start_boff += var->xoffset * (info->var.bits_per_pixel >> 3);
867 } else {
868 switch (info->var.bits_per_pixel) {
869 case 4:
870 start_boff += var->xoffset >> 1;
871 break;
872 case 2:
873 start_boff += var->xoffset >> 2;
874 break;
875 case 1:
876 start_boff += var->xoffset >> 3;
877 break;
878 default:
879 dev_err(sfb->dev, "invalid bpp\n");
880 return -EINVAL;
881 }
882 }
883 /* Offset in bytes to the end of the displayed area */
884 end_boff = start_boff + var->yres * info->fix.line_length;
885
886 /* Temporarily turn off per-vsync update from shadow registers until
887 * both start and end addresses are updated to prevent corruption */
888 shadow_protect_win(win, 1);
889
890 writel(info->fix.smem_start + start_boff, buf + sfb->variant.buf_start);
891 writel(info->fix.smem_start + end_boff, buf + sfb->variant.buf_end);
892
893 shadow_protect_win(win, 0);
894
895 return 0;
896}
897
898/**
899 * s3c_fb_enable_irq() - enable framebuffer interrupts
900 * @sfb: main hardware state
901 */
902static void s3c_fb_enable_irq(struct s3c_fb *sfb)
903{
904 void __iomem *regs = sfb->regs;
905 u32 irq_ctrl_reg;
906
907 if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
908 /* IRQ disabled, enable it */
909 irq_ctrl_reg = readl(regs + VIDINTCON0);
910
911 irq_ctrl_reg |= VIDINTCON0_INT_ENABLE;
912 irq_ctrl_reg |= VIDINTCON0_INT_FRAME;
913
914 irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK;
915 irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC;
916 irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK;
917 irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE;
918
919 writel(irq_ctrl_reg, regs + VIDINTCON0);
920 }
921}
922
923/**
924 * s3c_fb_disable_irq() - disable framebuffer interrupts
925 * @sfb: main hardware state
926 */
927static void s3c_fb_disable_irq(struct s3c_fb *sfb)
928{
929 void __iomem *regs = sfb->regs;
930 u32 irq_ctrl_reg;
931
932 if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
933 /* IRQ enabled, disable it */
934 irq_ctrl_reg = readl(regs + VIDINTCON0);
935
936 irq_ctrl_reg &= ~VIDINTCON0_INT_FRAME;
937 irq_ctrl_reg &= ~VIDINTCON0_INT_ENABLE;
938
939 writel(irq_ctrl_reg, regs + VIDINTCON0);
940 }
941}
942
943static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
944{
945 struct s3c_fb *sfb = dev_id;
946 void __iomem *regs = sfb->regs;
947 u32 irq_sts_reg;
948
949 irq_sts_reg = readl(regs + VIDINTCON1);
950
951 if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
952
953 /* VSYNC interrupt, accept it */
954 writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1);
955
956 sfb->vsync_info.count++;
957 wake_up_interruptible(&sfb->vsync_info.wait);
958 }
959
960 /* We only support waiting for VSYNC for now, so it's safe
961 * to always disable irqs here.
962 */
963 s3c_fb_disable_irq(sfb);
964
965 return IRQ_HANDLED;
966}
967
968/**
969 * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout
970 * @sfb: main hardware state
971 * @crtc: head index.
972 */
973static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
974{
975 unsigned long count;
976 int ret;
977
978 if (crtc != 0)
979 return -ENODEV;
980
981 count = sfb->vsync_info.count;
982 s3c_fb_enable_irq(sfb);
983 ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
984 count != sfb->vsync_info.count,
985 msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
986 if (ret == 0)
987 return -ETIMEDOUT;
988
989 return 0;
990}
991
992static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
993 unsigned long arg)
994{
995 struct s3c_fb_win *win = info->par;
996 struct s3c_fb *sfb = win->parent;
997 int ret;
998 u32 crtc;
999
1000 switch (cmd) {
1001 case FBIO_WAITFORVSYNC:
1002 if (get_user(crtc, (u32 __user *)arg)) {
1003 ret = -EFAULT;
1004 break;
1005 }
1006
1007 ret = s3c_fb_wait_for_vsync(sfb, crtc);
1008 break;
1009 default:
1010 ret = -ENOTTY;
1011 }
1012
1013 return ret;
1014}
1015
645static struct fb_ops s3c_fb_ops = { 1016static struct fb_ops s3c_fb_ops = {
646 .owner = THIS_MODULE, 1017 .owner = THIS_MODULE,
647 .fb_check_var = s3c_fb_check_var, 1018 .fb_check_var = s3c_fb_check_var,
@@ -651,9 +1022,33 @@ static struct fb_ops s3c_fb_ops = {
651 .fb_fillrect = cfb_fillrect, 1022 .fb_fillrect = cfb_fillrect,
652 .fb_copyarea = cfb_copyarea, 1023 .fb_copyarea = cfb_copyarea,
653 .fb_imageblit = cfb_imageblit, 1024 .fb_imageblit = cfb_imageblit,
1025 .fb_pan_display = s3c_fb_pan_display,
1026 .fb_ioctl = s3c_fb_ioctl,
654}; 1027};
655 1028
656/** 1029/**
1030 * s3c_fb_missing_pixclock() - calculates pixel clock
1031 * @mode: The video mode to change.
1032 *
1033 * Calculate the pixel clock when none has been given through platform data.
1034 */
1035static void __devinit s3c_fb_missing_pixclock(struct fb_videomode *mode)
1036{
1037 u64 pixclk = 1000000000000ULL;
1038 u32 div;
1039
1040 div = mode->left_margin + mode->hsync_len + mode->right_margin +
1041 mode->xres;
1042 div *= mode->upper_margin + mode->vsync_len + mode->lower_margin +
1043 mode->yres;
1044 div *= mode->refresh ? : 60;
1045
1046 do_div(pixclk, div);
1047
1048 mode->pixclock = pixclk;
1049}
1050
1051/**
657 * s3c_fb_alloc_memory() - allocate display memory for framebuffer window 1052 * s3c_fb_alloc_memory() - allocate display memory for framebuffer window
658 * @sfb: The base resources for the hardware. 1053 * @sfb: The base resources for the hardware.
659 * @win: The window to initialise memory for. 1054 * @win: The window to initialise memory for.
@@ -711,7 +1106,8 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
711{ 1106{
712 struct fb_info *fbi = win->fbinfo; 1107 struct fb_info *fbi = win->fbinfo;
713 1108
714 dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len), 1109 if (fbi->screen_base)
1110 dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
715 fbi->screen_base, fbi->fix.smem_start); 1111 fbi->screen_base, fbi->fix.smem_start);
716} 1112}
717 1113
@@ -724,9 +1120,18 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
724 */ 1120 */
725static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win) 1121static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
726{ 1122{
1123 u32 data;
1124
727 if (win->fbinfo) { 1125 if (win->fbinfo) {
1126 if (sfb->variant.has_shadowcon) {
1127 data = readl(sfb->regs + SHADOWCON);
1128 data &= ~SHADOWCON_CHx_ENABLE(win->index);
1129 data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index);
1130 writel(data, sfb->regs + SHADOWCON);
1131 }
728 unregister_framebuffer(win->fbinfo); 1132 unregister_framebuffer(win->fbinfo);
729 fb_dealloc_cmap(&win->fbinfo->cmap); 1133 if (win->fbinfo->cmap.len)
1134 fb_dealloc_cmap(&win->fbinfo->cmap);
730 s3c_fb_free_memory(sfb, win); 1135 s3c_fb_free_memory(sfb, win);
731 framebuffer_release(win->fbinfo); 1136 framebuffer_release(win->fbinfo);
732 } 1137 }
@@ -735,12 +1140,14 @@ static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
735/** 1140/**
736 * s3c_fb_probe_win() - register an hardware window 1141 * s3c_fb_probe_win() - register an hardware window
737 * @sfb: The base resources for the hardware 1142 * @sfb: The base resources for the hardware
1143 * @variant: The variant information for this window.
738 * @res: Pointer to where to place the resultant window. 1144 * @res: Pointer to where to place the resultant window.
739 * 1145 *
740 * Allocate and do the basic initialisation for one of the hardware's graphics 1146 * Allocate and do the basic initialisation for one of the hardware's graphics
741 * windows. 1147 * windows.
742 */ 1148 */
743static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, 1149static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
1150 struct s3c_fb_win_variant *variant,
744 struct s3c_fb_win **res) 1151 struct s3c_fb_win **res)
745{ 1152{
746 struct fb_var_screeninfo *var; 1153 struct fb_var_screeninfo *var;
@@ -751,9 +1158,11 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
751 int palette_size; 1158 int palette_size;
752 int ret; 1159 int ret;
753 1160
754 dev_dbg(sfb->dev, "probing window %d\n", win_no); 1161 dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant);
1162
1163 init_waitqueue_head(&sfb->vsync_info.wait);
755 1164
756 palette_size = s3c_fb_win_pal_size(win_no); 1165 palette_size = variant->palette_sz * 4;
757 1166
758 fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) + 1167 fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
759 palette_size * sizeof(u32), sfb->dev); 1168 palette_size * sizeof(u32), sfb->dev);
@@ -770,7 +1179,9 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
770 WARN_ON(windata->win_mode.yres == 0); 1179 WARN_ON(windata->win_mode.yres == 0);
771 1180
772 win = fbinfo->par; 1181 win = fbinfo->par;
1182 *res = win;
773 var = &fbinfo->var; 1183 var = &fbinfo->var;
1184 win->variant = *variant;
774 win->fbinfo = fbinfo; 1185 win->fbinfo = fbinfo;
775 win->parent = sfb; 1186 win->parent = sfb;
776 win->windata = windata; 1187 win->windata = windata;
@@ -784,7 +1195,24 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
784 } 1195 }
785 1196
786 /* setup the r/b/g positions for the window's palette */ 1197 /* setup the r/b/g positions for the window's palette */
787 s3c_fb_init_palette(win_no, &win->palette); 1198 if (win->variant.palette_16bpp) {
1199 /* Set RGB 5:6:5 as default */
1200 win->palette.r.offset = 11;
1201 win->palette.r.length = 5;
1202 win->palette.g.offset = 5;
1203 win->palette.g.length = 6;
1204 win->palette.b.offset = 0;
1205 win->palette.b.length = 5;
1206
1207 } else {
1208 /* Set 8bpp or 8bpp and 1bit alpha */
1209 win->palette.r.offset = 16;
1210 win->palette.r.length = 8;
1211 win->palette.g.offset = 8;
1212 win->palette.g.length = 8;
1213 win->palette.b.offset = 0;
1214 win->palette.b.length = 8;
1215 }
788 1216
789 /* setup the initial video mode from the window */ 1217 /* setup the initial video mode from the window */
790 fb_videomode_to_var(&fbinfo->var, initmode); 1218 fb_videomode_to_var(&fbinfo->var, initmode);
@@ -808,7 +1236,7 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
808 1236
809 /* create initial colour map */ 1237 /* create initial colour map */
810 1238
811 ret = fb_alloc_cmap(&fbinfo->cmap, s3c_fb_win_pal_size(win_no), 1); 1239 ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1);
812 if (ret == 0) 1240 if (ret == 0)
813 fb_set_cmap(&fbinfo->cmap, fbinfo); 1241 fb_set_cmap(&fbinfo->cmap, fbinfo);
814 else 1242 else
@@ -826,7 +1254,6 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
826 return ret; 1254 return ret;
827 } 1255 }
828 1256
829 *res = win;
830 dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id); 1257 dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id);
831 1258
832 return 0; 1259 return 0;
@@ -842,18 +1269,19 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
842static void s3c_fb_clear_win(struct s3c_fb *sfb, int win) 1269static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
843{ 1270{
844 void __iomem *regs = sfb->regs; 1271 void __iomem *regs = sfb->regs;
845 1272 u32 reg;
846 writel(0, regs + WINCON(win)); 1273
847 writel(0xffffff, regs + WxKEYCONy(win, 0)); 1274 writel(0, regs + sfb->variant.wincon + (win * 4));
848 writel(0xffffff, regs + WxKEYCONy(win, 1)); 1275 writel(0, regs + VIDOSD_A(win, sfb->variant));
849 1276 writel(0, regs + VIDOSD_B(win, sfb->variant));
850 writel(0, regs + VIDOSD_A(win)); 1277 writel(0, regs + VIDOSD_C(win, sfb->variant));
851 writel(0, regs + VIDOSD_B(win)); 1278 reg = readl(regs + SHADOWCON);
852 writel(0, regs + VIDOSD_C(win)); 1279 writel(reg & ~SHADOWCON_WINx_PROTECT(win), regs + SHADOWCON);
853} 1280}
854 1281
855static int __devinit s3c_fb_probe(struct platform_device *pdev) 1282static int __devinit s3c_fb_probe(struct platform_device *pdev)
856{ 1283{
1284 struct s3c_fb_driverdata *fbdrv;
857 struct device *dev = &pdev->dev; 1285 struct device *dev = &pdev->dev;
858 struct s3c_fb_platdata *pd; 1286 struct s3c_fb_platdata *pd;
859 struct s3c_fb *sfb; 1287 struct s3c_fb *sfb;
@@ -861,6 +1289,13 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
861 int win; 1289 int win;
862 int ret = 0; 1290 int ret = 0;
863 1291
1292 fbdrv = (struct s3c_fb_driverdata *)platform_get_device_id(pdev)->driver_data;
1293
1294 if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
1295 dev_err(dev, "too many windows, cannot attach\n");
1296 return -EINVAL;
1297 }
1298
864 pd = pdev->dev.platform_data; 1299 pd = pdev->dev.platform_data;
865 if (!pd) { 1300 if (!pd) {
866 dev_err(dev, "no platform data specified\n"); 1301 dev_err(dev, "no platform data specified\n");
@@ -873,8 +1308,11 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
873 return -ENOMEM; 1308 return -ENOMEM;
874 } 1309 }
875 1310
1311 dev_dbg(dev, "allocate new framebuffer %p\n", sfb);
1312
876 sfb->dev = dev; 1313 sfb->dev = dev;
877 sfb->pdata = pd; 1314 sfb->pdata = pd;
1315 sfb->variant = fbdrv->variant;
878 1316
879 sfb->bus_clk = clk_get(dev, "lcd"); 1317 sfb->bus_clk = clk_get(dev, "lcd");
880 if (IS_ERR(sfb->bus_clk)) { 1318 if (IS_ERR(sfb->bus_clk)) {
@@ -906,6 +1344,20 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
906 goto err_req_region; 1344 goto err_req_region;
907 } 1345 }
908 1346
1347 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1348 if (!res) {
1349 dev_err(dev, "failed to acquire irq resource\n");
1350 ret = -ENOENT;
1351 goto err_ioremap;
1352 }
1353 sfb->irq_no = res->start;
1354 ret = request_irq(sfb->irq_no, s3c_fb_irq,
1355 0, "s3c_fb", sfb);
1356 if (ret) {
1357 dev_err(dev, "irq request failed\n");
1358 goto err_ioremap;
1359 }
1360
909 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); 1361 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
910 1362
911 /* setup gpio and output polarity controls */ 1363 /* setup gpio and output polarity controls */
@@ -916,21 +1368,34 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
916 1368
917 /* zero all windows before we do anything */ 1369 /* zero all windows before we do anything */
918 1370
919 for (win = 0; win < S3C_FB_MAX_WIN; win++) 1371 for (win = 0; win < fbdrv->variant.nr_windows; win++)
920 s3c_fb_clear_win(sfb, win); 1372 s3c_fb_clear_win(sfb, win);
921 1373
1374 /* initialise colour key controls */
1375 for (win = 0; win < (fbdrv->variant.nr_windows - 1); win++) {
1376 void __iomem *regs = sfb->regs + sfb->variant.keycon;
1377
1378 regs += (win * 8);
1379 writel(0xffffff, regs + WKEYCON0);
1380 writel(0xffffff, regs + WKEYCON1);
1381 }
1382
922 /* we have the register setup, start allocating framebuffers */ 1383 /* we have the register setup, start allocating framebuffers */
923 1384
924 for (win = 0; win < S3C_FB_MAX_WIN; win++) { 1385 for (win = 0; win < fbdrv->variant.nr_windows; win++) {
925 if (!pd->win[win]) 1386 if (!pd->win[win])
926 continue; 1387 continue;
927 1388
928 ret = s3c_fb_probe_win(sfb, win, &sfb->windows[win]); 1389 if (!pd->win[win]->win_mode.pixclock)
1390 s3c_fb_missing_pixclock(&pd->win[win]->win_mode);
1391
1392 ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
1393 &sfb->windows[win]);
929 if (ret < 0) { 1394 if (ret < 0) {
930 dev_err(dev, "failed to create window %d\n", win); 1395 dev_err(dev, "failed to create window %d\n", win);
931 for (; win >= 0; win--) 1396 for (; win >= 0; win--)
932 s3c_fb_release_win(sfb, sfb->windows[win]); 1397 s3c_fb_release_win(sfb, sfb->windows[win]);
933 goto err_ioremap; 1398 goto err_irq;
934 } 1399 }
935 } 1400 }
936 1401
@@ -938,6 +1403,9 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
938 1403
939 return 0; 1404 return 0;
940 1405
1406err_irq:
1407 free_irq(sfb->irq_no, sfb);
1408
941err_ioremap: 1409err_ioremap:
942 iounmap(sfb->regs); 1410 iounmap(sfb->regs);
943 1411
@@ -970,6 +1438,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
970 if (sfb->windows[win]) 1438 if (sfb->windows[win])
971 s3c_fb_release_win(sfb, sfb->windows[win]); 1439 s3c_fb_release_win(sfb, sfb->windows[win]);
972 1440
1441 free_irq(sfb->irq_no, sfb);
1442
973 iounmap(sfb->regs); 1443 iounmap(sfb->regs);
974 1444
975 clk_disable(sfb->bus_clk); 1445 clk_disable(sfb->bus_clk);
@@ -1016,9 +1486,17 @@ static int s3c_fb_resume(struct platform_device *pdev)
1016 writel(pd->vidcon1, sfb->regs + VIDCON1); 1486 writel(pd->vidcon1, sfb->regs + VIDCON1);
1017 1487
1018 /* zero all windows before we do anything */ 1488 /* zero all windows before we do anything */
1019 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) 1489 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
1020 s3c_fb_clear_win(sfb, win_no); 1490 s3c_fb_clear_win(sfb, win_no);
1021 1491
1492 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
1493 void __iomem *regs = sfb->regs + sfb->variant.keycon;
1494
1495 regs += (win_no * 8);
1496 writel(0xffffff, regs + WKEYCON0);
1497 writel(0xffffff, regs + WKEYCON1);
1498 }
1499
1022 /* restore framebuffers */ 1500 /* restore framebuffers */
1023 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { 1501 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
1024 win = sfb->windows[win_no]; 1502 win = sfb->windows[win_no];
@@ -1036,11 +1514,208 @@ static int s3c_fb_resume(struct platform_device *pdev)
1036#define s3c_fb_resume NULL 1514#define s3c_fb_resume NULL
1037#endif 1515#endif
1038 1516
1517
1518#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
1519#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
1520
1521static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = {
1522 [0] = {
1523 .has_osd_c = 1,
1524 .osd_size_off = 0x8,
1525 .palette_sz = 256,
1526 .valid_bpp = VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24),
1527 },
1528 [1] = {
1529 .has_osd_c = 1,
1530 .has_osd_d = 1,
1531 .osd_size_off = 0x12,
1532 .has_osd_alpha = 1,
1533 .palette_sz = 256,
1534 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) |
1535 VALID_BPP(18) | VALID_BPP(19) |
1536 VALID_BPP(24) | VALID_BPP(25)),
1537 },
1538 [2] = {
1539 .has_osd_c = 1,
1540 .has_osd_d = 1,
1541 .osd_size_off = 0x12,
1542 .has_osd_alpha = 1,
1543 .palette_sz = 16,
1544 .palette_16bpp = 1,
1545 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) |
1546 VALID_BPP(18) | VALID_BPP(19) |
1547 VALID_BPP(24) | VALID_BPP(25)),
1548 },
1549 [3] = {
1550 .has_osd_c = 1,
1551 .has_osd_alpha = 1,
1552 .palette_sz = 16,
1553 .palette_16bpp = 1,
1554 .valid_bpp = (VALID_BPP124 | VALID_BPP(16) |
1555 VALID_BPP(18) | VALID_BPP(19) |
1556 VALID_BPP(24) | VALID_BPP(25)),
1557 },
1558 [4] = {
1559 .has_osd_c = 1,
1560 .has_osd_alpha = 1,
1561 .palette_sz = 4,
1562 .palette_16bpp = 1,
1563 .valid_bpp = (VALID_BPP(1) | VALID_BPP(2) |
1564 VALID_BPP(16) | VALID_BPP(18) |
1565 VALID_BPP(24) | VALID_BPP(25)),
1566 },
1567};
1568
1569static struct s3c_fb_driverdata s3c_fb_data_64xx = {
1570 .variant = {
1571 .nr_windows = 5,
1572 .vidtcon = VIDTCON0,
1573 .wincon = WINCON(0),
1574 .winmap = WINxMAP(0),
1575 .keycon = WKEYCON,
1576 .osd = VIDOSD_BASE,
1577 .osd_stride = 16,
1578 .buf_start = VIDW_BUF_START(0),
1579 .buf_size = VIDW_BUF_SIZE(0),
1580 .buf_end = VIDW_BUF_END(0),
1581
1582 .palette = {
1583 [0] = 0x400,
1584 [1] = 0x800,
1585 [2] = 0x300,
1586 [3] = 0x320,
1587 [4] = 0x340,
1588 },
1589
1590 .has_prtcon = 1,
1591 },
1592 .win[0] = &s3c_fb_data_64xx_wins[0],
1593 .win[1] = &s3c_fb_data_64xx_wins[1],
1594 .win[2] = &s3c_fb_data_64xx_wins[2],
1595 .win[3] = &s3c_fb_data_64xx_wins[3],
1596 .win[4] = &s3c_fb_data_64xx_wins[4],
1597};
1598
1599static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
1600 .variant = {
1601 .nr_windows = 5,
1602 .vidtcon = VIDTCON0,
1603 .wincon = WINCON(0),
1604 .winmap = WINxMAP(0),
1605 .keycon = WKEYCON,
1606 .osd = VIDOSD_BASE,
1607 .osd_stride = 16,
1608 .buf_start = VIDW_BUF_START(0),
1609 .buf_size = VIDW_BUF_SIZE(0),
1610 .buf_end = VIDW_BUF_END(0),
1611
1612 .palette = {
1613 [0] = 0x2400,
1614 [1] = 0x2800,
1615 [2] = 0x2c00,
1616 [3] = 0x3000,
1617 [4] = 0x3400,
1618 },
1619
1620 .has_prtcon = 1,
1621 },
1622 .win[0] = &s3c_fb_data_64xx_wins[0],
1623 .win[1] = &s3c_fb_data_64xx_wins[1],
1624 .win[2] = &s3c_fb_data_64xx_wins[2],
1625 .win[3] = &s3c_fb_data_64xx_wins[3],
1626 .win[4] = &s3c_fb_data_64xx_wins[4],
1627};
1628
1629static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
1630 .variant = {
1631 .nr_windows = 5,
1632 .vidtcon = VIDTCON0,
1633 .wincon = WINCON(0),
1634 .winmap = WINxMAP(0),
1635 .keycon = WKEYCON,
1636 .osd = VIDOSD_BASE,
1637 .osd_stride = 16,
1638 .buf_start = VIDW_BUF_START(0),
1639 .buf_size = VIDW_BUF_SIZE(0),
1640 .buf_end = VIDW_BUF_END(0),
1641
1642 .palette = {
1643 [0] = 0x2400,
1644 [1] = 0x2800,
1645 [2] = 0x2c00,
1646 [3] = 0x3000,
1647 [4] = 0x3400,
1648 },
1649
1650 .has_shadowcon = 1,
1651 },
1652 .win[0] = &s3c_fb_data_64xx_wins[0],
1653 .win[1] = &s3c_fb_data_64xx_wins[1],
1654 .win[2] = &s3c_fb_data_64xx_wins[2],
1655 .win[3] = &s3c_fb_data_64xx_wins[3],
1656 .win[4] = &s3c_fb_data_64xx_wins[4],
1657};
1658
1659/* S3C2443/S3C2416 style hardware */
1660static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
1661 .variant = {
1662 .nr_windows = 2,
1663 .is_2443 = 1,
1664
1665 .vidtcon = 0x08,
1666 .wincon = 0x14,
1667 .winmap = 0xd0,
1668 .keycon = 0xb0,
1669 .osd = 0x28,
1670 .osd_stride = 12,
1671 .buf_start = 0x64,
1672 .buf_size = 0x94,
1673 .buf_end = 0x7c,
1674
1675 .palette = {
1676 [0] = 0x400,
1677 [1] = 0x800,
1678 },
1679 },
1680 .win[0] = &(struct s3c_fb_win_variant) {
1681 .palette_sz = 256,
1682 .valid_bpp = VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24),
1683 },
1684 .win[1] = &(struct s3c_fb_win_variant) {
1685 .has_osd_c = 1,
1686 .has_osd_alpha = 1,
1687 .palette_sz = 256,
1688 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) |
1689 VALID_BPP(18) | VALID_BPP(19) |
1690 VALID_BPP(24) | VALID_BPP(25) |
1691 VALID_BPP(28)),
1692 },
1693};
1694
1695static struct platform_device_id s3c_fb_driver_ids[] = {
1696 {
1697 .name = "s3c-fb",
1698 .driver_data = (unsigned long)&s3c_fb_data_64xx,
1699 }, {
1700 .name = "s5pc100-fb",
1701 .driver_data = (unsigned long)&s3c_fb_data_s5pc100,
1702 }, {
1703 .name = "s5pv210-fb",
1704 .driver_data = (unsigned long)&s3c_fb_data_s5pv210,
1705 }, {
1706 .name = "s3c2443-fb",
1707 .driver_data = (unsigned long)&s3c_fb_data_s3c2443,
1708 },
1709 {},
1710};
1711MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
1712
1039static struct platform_driver s3c_fb_driver = { 1713static struct platform_driver s3c_fb_driver = {
1040 .probe = s3c_fb_probe, 1714 .probe = s3c_fb_probe,
1041 .remove = __devexit_p(s3c_fb_remove), 1715 .remove = __devexit_p(s3c_fb_remove),
1042 .suspend = s3c_fb_suspend, 1716 .suspend = s3c_fb_suspend,
1043 .resume = s3c_fb_resume, 1717 .resume = s3c_fb_resume,
1718 .id_table = s3c_fb_driver_ids,
1044 .driver = { 1719 .driver = {
1045 .name = "s3c-fb", 1720 .name = "s3c-fb",
1046 .owner = THIS_MODULE, 1721 .owner = THIS_MODULE,
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index ed371c868b3a..b16e6138fdd4 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -181,6 +181,15 @@ void savagefb_create_i2c_busses(struct fb_info *info)
181 par->chan.algo.getscl = prosavage_gpio_getscl; 181 par->chan.algo.getscl = prosavage_gpio_getscl;
182 break; 182 break;
183 case FB_ACCEL_SAVAGE4: 183 case FB_ACCEL_SAVAGE4:
184 par->chan.reg = CR_SERIAL1;
185 if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40))
186 par->chan.reg = CR_SERIAL2;
187 par->chan.ioaddr = par->mmio.vbase;
188 par->chan.algo.setsda = prosavage_gpio_setsda;
189 par->chan.algo.setscl = prosavage_gpio_setscl;
190 par->chan.algo.getsda = prosavage_gpio_getsda;
191 par->chan.algo.getscl = prosavage_gpio_getscl;
192 break;
184 case FB_ACCEL_SAVAGE2000: 193 case FB_ACCEL_SAVAGE2000:
185 par->chan.reg = 0xff20; 194 par->chan.reg = 0xff20;
186 par->chan.ioaddr = par->mmio.vbase; 195 par->chan.ioaddr = par->mmio.vbase;
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
index 8bfdfc3c5234..e4c3f214eb8e 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -13,7 +13,6 @@
13#define __SAVAGEFB_H__ 13#define __SAVAGEFB_H__
14 14
15#include <linux/i2c.h> 15#include <linux/i2c.h>
16#include <linux/i2c-id.h>
17#include <linux/i2c-algo-bit.h> 16#include <linux/i2c-algo-bit.h>
18#include <linux/mutex.h> 17#include <linux/mutex.h>
19#include <video/vga.h> 18#include <video/vga.h>
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
new file mode 100644
index 000000000000..5699ce0c1780
--- /dev/null
+++ b/drivers/video/sh_mipi_dsi.c
@@ -0,0 +1,505 @@
1/*
2 * Renesas SH-mobile MIPI DSI support
3 *
4 * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 *
6 * This is free software; you can redistribute it and/or modify
7 * it under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/clk.h>
12#include <linux/delay.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <linux/string.h>
18#include <linux/types.h>
19
20#include <video/mipi_display.h>
21#include <video/sh_mipi_dsi.h>
22#include <video/sh_mobile_lcdc.h>
23
24#define CMTSRTCTR 0x80d0
25#define CMTSRTREQ 0x8070
26
27#define DSIINTE 0x0060
28
29/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */
30#define MAX_SH_MIPI_DSI 2
31
32struct sh_mipi {
33 void __iomem *base;
34 struct clk *dsit_clk;
35 struct clk *dsip_clk;
36};
37
38static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
39
40/* Protect the above array */
41static DEFINE_MUTEX(array_lock);
42
43static struct sh_mipi *sh_mipi_by_handle(int handle)
44{
45 if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0)
46 return NULL;
47
48 return mipi_dsi[handle];
49}
50
51static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd,
52 u8 cmd, u8 param)
53{
54 u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8);
55 int cnt = 100;
56
57 /* transmit a short packet to LCD panel */
58 iowrite32(1 | data, mipi->base + 0x80d0); /* CMTSRTCTR */
59 iowrite32(1, mipi->base + 0x8070); /* CMTSRTREQ */
60
61 while ((ioread32(mipi->base + 0x8070) & 1) && --cnt)
62 udelay(1);
63
64 return cnt ? 0 : -ETIMEDOUT;
65}
66
67#define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \
68 -EINVAL : (c) - 1)
69
70static int sh_mipi_dcs(int handle, u8 cmd)
71{
72 struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
73 if (!mipi)
74 return -ENODEV;
75 return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0);
76}
77
78static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param)
79{
80 struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
81 if (!mipi)
82 return -ENODEV;
83 return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd,
84 param);
85}
86
87static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
88{
89 /*
90 * enable LCDC data tx, transition to LPS after completion of each HS
91 * packet
92 */
93 iowrite32(0x00000002 | enable, mipi->base + 0x8000); /* DTCTR */
94}
95
96static void sh_mipi_shutdown(struct platform_device *pdev)
97{
98 struct sh_mipi *mipi = platform_get_drvdata(pdev);
99
100 sh_mipi_dsi_enable(mipi, false);
101}
102
103static void mipi_display_on(void *arg, struct fb_info *info)
104{
105 struct sh_mipi *mipi = arg;
106
107 sh_mipi_dsi_enable(mipi, true);
108}
109
110static void mipi_display_off(void *arg)
111{
112 struct sh_mipi *mipi = arg;
113
114 sh_mipi_dsi_enable(mipi, false);
115}
116
117static int __init sh_mipi_setup(struct sh_mipi *mipi,
118 struct sh_mipi_dsi_info *pdata)
119{
120 void __iomem *base = mipi->base;
121 struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
122 u32 pctype, datatype, pixfmt;
123 u32 linelength;
124 bool yuv;
125
126 /* Select data format */
127 switch (pdata->data_format) {
128 case MIPI_RGB888:
129 pctype = 0;
130 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
131 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
132 linelength = ch->lcd_cfg.xres * 3;
133 yuv = false;
134 break;
135 case MIPI_RGB565:
136 pctype = 1;
137 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
138 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
139 linelength = ch->lcd_cfg.xres * 2;
140 yuv = false;
141 break;
142 case MIPI_RGB666_LP:
143 pctype = 2;
144 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
145 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
146 linelength = ch->lcd_cfg.xres * 3;
147 yuv = false;
148 break;
149 case MIPI_RGB666:
150 pctype = 3;
151 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
152 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
153 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8;
154 yuv = false;
155 break;
156 case MIPI_BGR888:
157 pctype = 8;
158 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
159 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
160 linelength = ch->lcd_cfg.xres * 3;
161 yuv = false;
162 break;
163 case MIPI_BGR565:
164 pctype = 9;
165 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
166 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
167 linelength = ch->lcd_cfg.xres * 2;
168 yuv = false;
169 break;
170 case MIPI_BGR666_LP:
171 pctype = 0xa;
172 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
173 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
174 linelength = ch->lcd_cfg.xres * 3;
175 yuv = false;
176 break;
177 case MIPI_BGR666:
178 pctype = 0xb;
179 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
180 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
181 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8;
182 yuv = false;
183 break;
184 case MIPI_YUYV:
185 pctype = 4;
186 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
187 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
188 linelength = ch->lcd_cfg.xres * 2;
189 yuv = true;
190 break;
191 case MIPI_UYVY:
192 pctype = 5;
193 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
194 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
195 linelength = ch->lcd_cfg.xres * 2;
196 yuv = true;
197 break;
198 case MIPI_YUV420_L:
199 pctype = 6;
200 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
201 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
202 linelength = (ch->lcd_cfg.xres * 12 + 7) / 8;
203 yuv = true;
204 break;
205 case MIPI_YUV420:
206 pctype = 7;
207 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
208 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
209 /* Length of U/V line */
210 linelength = (ch->lcd_cfg.xres + 1) / 2;
211 yuv = true;
212 break;
213 default:
214 return -EINVAL;
215 }
216
217 if ((yuv && ch->interface_type != YUV422) ||
218 (!yuv && ch->interface_type != RGB24))
219 return -EINVAL;
220
221 /* reset DSI link */
222 iowrite32(0x00000001, base); /* SYSCTRL */
223 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
224 udelay(50);
225 iowrite32(0x00000000, base); /* SYSCTRL */
226
227 /* setup DSI link */
228
229 /*
230 * Default = ULPS enable |
231 * Contention detection enabled |
232 * EoT packet transmission enable |
233 * CRC check enable |
234 * ECC check enable
235 * additionally enable first two lanes
236 */
237 iowrite32(0x00003703, base + 0x04); /* SYSCONF */
238 /*
239 * T_wakeup = 0x7000
240 * T_hs-trail = 3
241 * T_hs-prepare = 3
242 * T_clk-trail = 3
243 * T_clk-prepare = 2
244 */
245 iowrite32(0x70003332, base + 0x08); /* TIMSET */
246 /* no responses requested */
247 iowrite32(0x00000000, base + 0x18); /* RESREQSET0 */
248 /* request response to packets of type 0x28 */
249 iowrite32(0x00000100, base + 0x1c); /* RESREQSET1 */
250 /* High-speed transmission timeout, default 0xffffffff */
251 iowrite32(0x0fffffff, base + 0x20); /* HSTTOVSET */
252 /* LP reception timeout, default 0xffffffff */
253 iowrite32(0x0fffffff, base + 0x24); /* LPRTOVSET */
254 /* Turn-around timeout, default 0xffffffff */
255 iowrite32(0x0fffffff, base + 0x28); /* TATOVSET */
256 /* Peripheral reset timeout, default 0xffffffff */
257 iowrite32(0x0fffffff, base + 0x2c); /* PRTOVSET */
258 /* Enable timeout counters */
259 iowrite32(0x00000f00, base + 0x30); /* DSICTRL */
260 /* Interrupts not used, disable all */
261 iowrite32(0, base + DSIINTE);
262 /* DSI-Tx bias on */
263 iowrite32(0x00000001, base + 0x70); /* PHYCTRL */
264 udelay(200);
265 /* Deassert resets, power on, set multiplier */
266 iowrite32(0x03070b01, base + 0x70); /* PHYCTRL */
267
268 /* setup l-bridge */
269
270 /*
271 * Enable transmission of all packets,
272 * transmit LPS after each HS packet completion
273 */
274 iowrite32(0x00000006, base + 0x8000); /* DTCTR */
275 /* VSYNC width = 2 (<< 17) */
276 iowrite32(0x00040000 | (pctype << 12) | datatype, base + 0x8020); /* VMCTR1 */
277 /*
278 * Non-burst mode with sync pulses: VSE and HSE are output,
279 * HSA period allowed, no commands in LP
280 */
281 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */
282 /*
283 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
284 * sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default
285 * (unused, since VMCTR2[HSABM] = 0)
286 */
287 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */
288
289 msleep(5);
290
291 /* setup LCD panel */
292
293 /* cf. drivers/video/omap/lcd_mipid.c */
294 sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE);
295 msleep(120);
296 /*
297 * [7] - Page Address Mode
298 * [6] - Column Address Mode
299 * [5] - Page / Column Address Mode
300 * [4] - Display Device Line Refresh Order
301 * [3] - RGB/BGR Order
302 * [2] - Display Data Latch Data Order
303 * [1] - Flip Horizontal
304 * [0] - Flip Vertical
305 */
306 sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
307 /* cf. set_data_lines() */
308 sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT,
309 pixfmt << 4);
310 sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
311
312 return 0;
313}
314
315static int __init sh_mipi_probe(struct platform_device *pdev)
316{
317 struct sh_mipi *mipi;
318 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
319 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
320 unsigned long rate, f_current;
321 int idx = pdev->id, ret;
322 char dsip_clk[] = "dsi.p_clk";
323
324 if (!res || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
325 return -ENODEV;
326
327 mutex_lock(&array_lock);
328 if (idx < 0)
329 for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
330 ;
331
332 if (idx == ARRAY_SIZE(mipi_dsi)) {
333 ret = -EBUSY;
334 goto efindslot;
335 }
336
337 mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
338 if (!mipi) {
339 ret = -ENOMEM;
340 goto ealloc;
341 }
342
343 if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
344 dev_err(&pdev->dev, "MIPI register region already claimed\n");
345 ret = -EBUSY;
346 goto ereqreg;
347 }
348
349 mipi->base = ioremap(res->start, resource_size(res));
350 if (!mipi->base) {
351 ret = -ENOMEM;
352 goto emap;
353 }
354
355 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
356 if (IS_ERR(mipi->dsit_clk)) {
357 ret = PTR_ERR(mipi->dsit_clk);
358 goto eclktget;
359 }
360
361 f_current = clk_get_rate(mipi->dsit_clk);
362 /* 80MHz required by the datasheet */
363 rate = clk_round_rate(mipi->dsit_clk, 80000000);
364 if (rate > 0 && rate != f_current)
365 ret = clk_set_rate(mipi->dsit_clk, rate);
366 else
367 ret = rate;
368 if (ret < 0)
369 goto esettrate;
370
371 dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
372
373 sprintf(dsip_clk, "dsi%1.1dp_clk", idx);
374 mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk);
375 if (IS_ERR(mipi->dsip_clk)) {
376 ret = PTR_ERR(mipi->dsip_clk);
377 goto eclkpget;
378 }
379
380 f_current = clk_get_rate(mipi->dsip_clk);
381 /* Between 10 and 50MHz */
382 rate = clk_round_rate(mipi->dsip_clk, 24000000);
383 if (rate > 0 && rate != f_current)
384 ret = clk_set_rate(mipi->dsip_clk, rate);
385 else
386 ret = rate;
387 if (ret < 0)
388 goto esetprate;
389
390 dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate);
391
392 msleep(10);
393
394 ret = clk_enable(mipi->dsit_clk);
395 if (ret < 0)
396 goto eclkton;
397
398 ret = clk_enable(mipi->dsip_clk);
399 if (ret < 0)
400 goto eclkpon;
401
402 mipi_dsi[idx] = mipi;
403
404 ret = sh_mipi_setup(mipi, pdata);
405 if (ret < 0)
406 goto emipisetup;
407
408 mutex_unlock(&array_lock);
409 platform_set_drvdata(pdev, mipi);
410
411 /* Set up LCDC callbacks */
412 pdata->lcd_chan->board_cfg.board_data = mipi;
413 pdata->lcd_chan->board_cfg.display_on = mipi_display_on;
414 pdata->lcd_chan->board_cfg.display_off = mipi_display_off;
415
416 return 0;
417
418emipisetup:
419 mipi_dsi[idx] = NULL;
420 clk_disable(mipi->dsip_clk);
421eclkpon:
422 clk_disable(mipi->dsit_clk);
423eclkton:
424esetprate:
425 clk_put(mipi->dsip_clk);
426eclkpget:
427esettrate:
428 clk_put(mipi->dsit_clk);
429eclktget:
430 iounmap(mipi->base);
431emap:
432 release_mem_region(res->start, resource_size(res));
433ereqreg:
434 kfree(mipi);
435ealloc:
436efindslot:
437 mutex_unlock(&array_lock);
438
439 return ret;
440}
441
442static int __exit sh_mipi_remove(struct platform_device *pdev)
443{
444 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
445 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
446 struct sh_mipi *mipi = platform_get_drvdata(pdev);
447 int i, ret;
448
449 mutex_lock(&array_lock);
450
451 for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++)
452 ;
453
454 if (i == ARRAY_SIZE(mipi_dsi)) {
455 ret = -EINVAL;
456 } else {
457 ret = 0;
458 mipi_dsi[i] = NULL;
459 }
460
461 mutex_unlock(&array_lock);
462
463 if (ret < 0)
464 return ret;
465
466 pdata->lcd_chan->board_cfg.display_on = NULL;
467 pdata->lcd_chan->board_cfg.display_off = NULL;
468 pdata->lcd_chan->board_cfg.board_data = NULL;
469
470 clk_disable(mipi->dsip_clk);
471 clk_disable(mipi->dsit_clk);
472 clk_put(mipi->dsit_clk);
473 clk_put(mipi->dsip_clk);
474 iounmap(mipi->base);
475 if (res)
476 release_mem_region(res->start, resource_size(res));
477 platform_set_drvdata(pdev, NULL);
478 kfree(mipi);
479
480 return 0;
481}
482
483static struct platform_driver sh_mipi_driver = {
484 .remove = __exit_p(sh_mipi_remove),
485 .shutdown = sh_mipi_shutdown,
486 .driver = {
487 .name = "sh-mipi-dsi",
488 },
489};
490
491static int __init sh_mipi_init(void)
492{
493 return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe);
494}
495module_init(sh_mipi_init);
496
497static void __exit sh_mipi_exit(void)
498{
499 platform_driver_unregister(&sh_mipi_driver);
500}
501module_exit(sh_mipi_exit);
502
503MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
504MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
505MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
new file mode 100644
index 000000000000..ef989d94511c
--- /dev/null
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -0,0 +1,1110 @@
1/*
2 * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
3 * for SLISHDMI13T and SLIPHDMIT IP cores
4 *
5 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/clk.h>
13#include <linux/console.h>
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/init.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/pm_runtime.h>
22#include <linux/slab.h>
23#include <linux/types.h>
24#include <linux/workqueue.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
27
28#include <video/sh_mobile_hdmi.h>
29#include <video/sh_mobile_lcdc.h>
30
31#define HDMI_SYSTEM_CTRL 0x00 /* System control */
32#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control,
33 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
34#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8 0x02 /* bits 15..8 of 20-bit N for Audio Clock Regeneration packet */
35#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0 0x03 /* bits 7..0 of 20-bit N for Audio Clock Regeneration packet */
36#define HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS 0x04 /* SPDIF audio sampling frequency,
37 bits 19..16 of Internal CTS */
38#define HDMI_INTERNAL_CTS_15_8 0x05 /* bits 15..8 of Internal CTS */
39#define HDMI_INTERNAL_CTS_7_0 0x06 /* bits 7..0 of Internal CTS */
40#define HDMI_EXTERNAL_CTS_19_16 0x07 /* External CTS */
41#define HDMI_EXTERNAL_CTS_15_8 0x08 /* External CTS */
42#define HDMI_EXTERNAL_CTS_7_0 0x09 /* External CTS */
43#define HDMI_AUDIO_SETTING_1 0x0A /* Audio setting.1 */
44#define HDMI_AUDIO_SETTING_2 0x0B /* Audio setting.2 */
45#define HDMI_I2S_AUDIO_SET 0x0C /* I2S audio setting */
46#define HDMI_DSD_AUDIO_SET 0x0D /* DSD audio setting */
47#define HDMI_DEBUG_MONITOR_1 0x0E /* Debug monitor.1 */
48#define HDMI_DEBUG_MONITOR_2 0x0F /* Debug monitor.2 */
49#define HDMI_I2S_INPUT_PIN_SWAP 0x10 /* I2S input pin swap */
50#define HDMI_AUDIO_STATUS_BITS_SETTING_1 0x11 /* Audio status bits setting.1 */
51#define HDMI_AUDIO_STATUS_BITS_SETTING_2 0x12 /* Audio status bits setting.2 */
52#define HDMI_CATEGORY_CODE 0x13 /* Category code */
53#define HDMI_SOURCE_NUM_AUDIO_WORD_LEN 0x14 /* Source number/Audio word length */
54#define HDMI_AUDIO_VIDEO_SETTING_1 0x15 /* Audio/Video setting.1 */
55#define HDMI_VIDEO_SETTING_1 0x16 /* Video setting.1 */
56#define HDMI_DEEP_COLOR_MODES 0x17 /* Deep Color Modes */
57
58/* 12 16- and 10-bit Color space conversion parameters: 0x18..0x2f */
59#define HDMI_COLOR_SPACE_CONVERSION_PARAMETERS 0x18
60
61#define HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS 0x30 /* External video parameter settings */
62#define HDMI_EXTERNAL_H_TOTAL_7_0 0x31 /* External horizontal total (LSB) */
63#define HDMI_EXTERNAL_H_TOTAL_11_8 0x32 /* External horizontal total (MSB) */
64#define HDMI_EXTERNAL_H_BLANK_7_0 0x33 /* External horizontal blank (LSB) */
65#define HDMI_EXTERNAL_H_BLANK_9_8 0x34 /* External horizontal blank (MSB) */
66#define HDMI_EXTERNAL_H_DELAY_7_0 0x35 /* External horizontal delay (LSB) */
67#define HDMI_EXTERNAL_H_DELAY_9_8 0x36 /* External horizontal delay (MSB) */
68#define HDMI_EXTERNAL_H_DURATION_7_0 0x37 /* External horizontal duration (LSB) */
69#define HDMI_EXTERNAL_H_DURATION_9_8 0x38 /* External horizontal duration (MSB) */
70#define HDMI_EXTERNAL_V_TOTAL_7_0 0x39 /* External vertical total (LSB) */
71#define HDMI_EXTERNAL_V_TOTAL_9_8 0x3A /* External vertical total (MSB) */
72#define HDMI_AUDIO_VIDEO_SETTING_2 0x3B /* Audio/Video setting.2 */
73#define HDMI_EXTERNAL_V_BLANK 0x3D /* External vertical blank */
74#define HDMI_EXTERNAL_V_DELAY 0x3E /* External vertical delay */
75#define HDMI_EXTERNAL_V_DURATION 0x3F /* External vertical duration */
76#define HDMI_CTRL_PKT_MANUAL_SEND_CONTROL 0x40 /* Control packet manual send control */
77#define HDMI_CTRL_PKT_AUTO_SEND 0x41 /* Control packet auto send with VSYNC control */
78#define HDMI_AUTO_CHECKSUM_OPTION 0x42 /* Auto checksum option */
79#define HDMI_VIDEO_SETTING_2 0x45 /* Video setting.2 */
80#define HDMI_OUTPUT_OPTION 0x46 /* Output option */
81#define HDMI_SLIPHDMIT_PARAM_OPTION 0x51 /* SLIPHDMIT parameter option */
82#define HDMI_HSYNC_PMENT_AT_EMB_7_0 0x52 /* HSYNC placement at embedded sync (LSB) */
83#define HDMI_HSYNC_PMENT_AT_EMB_15_8 0x53 /* HSYNC placement at embedded sync (MSB) */
84#define HDMI_VSYNC_PMENT_AT_EMB_7_0 0x54 /* VSYNC placement at embedded sync (LSB) */
85#define HDMI_VSYNC_PMENT_AT_EMB_14_8 0x55 /* VSYNC placement at embedded sync (MSB) */
86#define HDMI_SLIPHDMIT_PARAM_SETTINGS_1 0x56 /* SLIPHDMIT parameter settings.1 */
87#define HDMI_SLIPHDMIT_PARAM_SETTINGS_2 0x57 /* SLIPHDMIT parameter settings.2 */
88#define HDMI_SLIPHDMIT_PARAM_SETTINGS_3 0x58 /* SLIPHDMIT parameter settings.3 */
89#define HDMI_SLIPHDMIT_PARAM_SETTINGS_5 0x59 /* SLIPHDMIT parameter settings.5 */
90#define HDMI_SLIPHDMIT_PARAM_SETTINGS_6 0x5A /* SLIPHDMIT parameter settings.6 */
91#define HDMI_SLIPHDMIT_PARAM_SETTINGS_7 0x5B /* SLIPHDMIT parameter settings.7 */
92#define HDMI_SLIPHDMIT_PARAM_SETTINGS_8 0x5C /* SLIPHDMIT parameter settings.8 */
93#define HDMI_SLIPHDMIT_PARAM_SETTINGS_9 0x5D /* SLIPHDMIT parameter settings.9 */
94#define HDMI_SLIPHDMIT_PARAM_SETTINGS_10 0x5E /* SLIPHDMIT parameter settings.10 */
95#define HDMI_CTRL_PKT_BUF_INDEX 0x5F /* Control packet buffer index */
96#define HDMI_CTRL_PKT_BUF_ACCESS_HB0 0x60 /* Control packet data buffer access window - HB0 */
97#define HDMI_CTRL_PKT_BUF_ACCESS_HB1 0x61 /* Control packet data buffer access window - HB1 */
98#define HDMI_CTRL_PKT_BUF_ACCESS_HB2 0x62 /* Control packet data buffer access window - HB2 */
99#define HDMI_CTRL_PKT_BUF_ACCESS_PB0 0x63 /* Control packet data buffer access window - PB0 */
100#define HDMI_CTRL_PKT_BUF_ACCESS_PB1 0x64 /* Control packet data buffer access window - PB1 */
101#define HDMI_CTRL_PKT_BUF_ACCESS_PB2 0x65 /* Control packet data buffer access window - PB2 */
102#define HDMI_CTRL_PKT_BUF_ACCESS_PB3 0x66 /* Control packet data buffer access window - PB3 */
103#define HDMI_CTRL_PKT_BUF_ACCESS_PB4 0x67 /* Control packet data buffer access window - PB4 */
104#define HDMI_CTRL_PKT_BUF_ACCESS_PB5 0x68 /* Control packet data buffer access window - PB5 */
105#define HDMI_CTRL_PKT_BUF_ACCESS_PB6 0x69 /* Control packet data buffer access window - PB6 */
106#define HDMI_CTRL_PKT_BUF_ACCESS_PB7 0x6A /* Control packet data buffer access window - PB7 */
107#define HDMI_CTRL_PKT_BUF_ACCESS_PB8 0x6B /* Control packet data buffer access window - PB8 */
108#define HDMI_CTRL_PKT_BUF_ACCESS_PB9 0x6C /* Control packet data buffer access window - PB9 */
109#define HDMI_CTRL_PKT_BUF_ACCESS_PB10 0x6D /* Control packet data buffer access window - PB10 */
110#define HDMI_CTRL_PKT_BUF_ACCESS_PB11 0x6E /* Control packet data buffer access window - PB11 */
111#define HDMI_CTRL_PKT_BUF_ACCESS_PB12 0x6F /* Control packet data buffer access window - PB12 */
112#define HDMI_CTRL_PKT_BUF_ACCESS_PB13 0x70 /* Control packet data buffer access window - PB13 */
113#define HDMI_CTRL_PKT_BUF_ACCESS_PB14 0x71 /* Control packet data buffer access window - PB14 */
114#define HDMI_CTRL_PKT_BUF_ACCESS_PB15 0x72 /* Control packet data buffer access window - PB15 */
115#define HDMI_CTRL_PKT_BUF_ACCESS_PB16 0x73 /* Control packet data buffer access window - PB16 */
116#define HDMI_CTRL_PKT_BUF_ACCESS_PB17 0x74 /* Control packet data buffer access window - PB17 */
117#define HDMI_CTRL_PKT_BUF_ACCESS_PB18 0x75 /* Control packet data buffer access window - PB18 */
118#define HDMI_CTRL_PKT_BUF_ACCESS_PB19 0x76 /* Control packet data buffer access window - PB19 */
119#define HDMI_CTRL_PKT_BUF_ACCESS_PB20 0x77 /* Control packet data buffer access window - PB20 */
120#define HDMI_CTRL_PKT_BUF_ACCESS_PB21 0x78 /* Control packet data buffer access window - PB21 */
121#define HDMI_CTRL_PKT_BUF_ACCESS_PB22 0x79 /* Control packet data buffer access window - PB22 */
122#define HDMI_CTRL_PKT_BUF_ACCESS_PB23 0x7A /* Control packet data buffer access window - PB23 */
123#define HDMI_CTRL_PKT_BUF_ACCESS_PB24 0x7B /* Control packet data buffer access window - PB24 */
124#define HDMI_CTRL_PKT_BUF_ACCESS_PB25 0x7C /* Control packet data buffer access window - PB25 */
125#define HDMI_CTRL_PKT_BUF_ACCESS_PB26 0x7D /* Control packet data buffer access window - PB26 */
126#define HDMI_CTRL_PKT_BUF_ACCESS_PB27 0x7E /* Control packet data buffer access window - PB27 */
127#define HDMI_EDID_KSV_FIFO_ACCESS_WINDOW 0x80 /* EDID/KSV FIFO access window */
128#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_7_0 0x81 /* DDC bus access frequency control (LSB) */
129#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_15_8 0x82 /* DDC bus access frequency control (MSB) */
130#define HDMI_INTERRUPT_MASK_1 0x92 /* Interrupt mask.1 */
131#define HDMI_INTERRUPT_MASK_2 0x93 /* Interrupt mask.2 */
132#define HDMI_INTERRUPT_STATUS_1 0x94 /* Interrupt status.1 */
133#define HDMI_INTERRUPT_STATUS_2 0x95 /* Interrupt status.2 */
134#define HDMI_INTERRUPT_MASK_3 0x96 /* Interrupt mask.3 */
135#define HDMI_INTERRUPT_MASK_4 0x97 /* Interrupt mask.4 */
136#define HDMI_INTERRUPT_STATUS_3 0x98 /* Interrupt status.3 */
137#define HDMI_INTERRUPT_STATUS_4 0x99 /* Interrupt status.4 */
138#define HDMI_SOFTWARE_HDCP_CONTROL_1 0x9A /* Software HDCP control.1 */
139#define HDMI_FRAME_COUNTER 0x9C /* Frame counter */
140#define HDMI_FRAME_COUNTER_FOR_RI_CHECK 0x9D /* Frame counter for Ri check */
141#define HDMI_HDCP_CONTROL 0xAF /* HDCP control */
142#define HDMI_RI_FRAME_COUNT_REGISTER 0xB2 /* Ri frame count register */
143#define HDMI_DDC_BUS_CONTROL 0xB7 /* DDC bus control */
144#define HDMI_HDCP_STATUS 0xB8 /* HDCP status */
145#define HDMI_SHA0 0xB9 /* sha0 */
146#define HDMI_SHA1 0xBA /* sha1 */
147#define HDMI_SHA2 0xBB /* sha2 */
148#define HDMI_SHA3 0xBC /* sha3 */
149#define HDMI_SHA4 0xBD /* sha4 */
150#define HDMI_BCAPS_READ 0xBE /* BCAPS read / debug */
151#define HDMI_AKSV_BKSV_7_0_MONITOR 0xBF /* AKSV/BKSV[7:0] monitor */
152#define HDMI_AKSV_BKSV_15_8_MONITOR 0xC0 /* AKSV/BKSV[15:8] monitor */
153#define HDMI_AKSV_BKSV_23_16_MONITOR 0xC1 /* AKSV/BKSV[23:16] monitor */
154#define HDMI_AKSV_BKSV_31_24_MONITOR 0xC2 /* AKSV/BKSV[31:24] monitor */
155#define HDMI_AKSV_BKSV_39_32_MONITOR 0xC3 /* AKSV/BKSV[39:32] monitor */
156#define HDMI_EDID_SEGMENT_POINTER 0xC4 /* EDID segment pointer */
157#define HDMI_EDID_WORD_ADDRESS 0xC5 /* EDID word address */
158#define HDMI_EDID_DATA_FIFO_ADDRESS 0xC6 /* EDID data FIFO address */
159#define HDMI_NUM_OF_HDMI_DEVICES 0xC7 /* Number of HDMI devices */
160#define HDMI_HDCP_ERROR_CODE 0xC8 /* HDCP error code */
161#define HDMI_100MS_TIMER_SET 0xC9 /* 100ms timer setting */
162#define HDMI_5SEC_TIMER_SET 0xCA /* 5sec timer setting */
163#define HDMI_RI_READ_COUNT 0xCB /* Ri read count */
164#define HDMI_AN_SEED 0xCC /* An seed */
165#define HDMI_MAX_NUM_OF_RCIVRS_ALLOWED 0xCD /* Maximum number of receivers allowed */
166#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_1 0xCE /* HDCP memory access control.1 */
167#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_2 0xCF /* HDCP memory access control.2 */
168#define HDMI_HDCP_CONTROL_2 0xD0 /* HDCP Control 2 */
169#define HDMI_HDCP_KEY_MEMORY_CONTROL 0xD2 /* HDCP Key Memory Control */
170#define HDMI_COLOR_SPACE_CONV_CONFIG_1 0xD3 /* Color space conversion configuration.1 */
171#define HDMI_VIDEO_SETTING_3 0xD4 /* Video setting.3 */
172#define HDMI_RI_7_0 0xD5 /* Ri[7:0] */
173#define HDMI_RI_15_8 0xD6 /* Ri[15:8] */
174#define HDMI_PJ 0xD7 /* Pj */
175#define HDMI_SHA_RD 0xD8 /* sha_rd */
176#define HDMI_RI_7_0_SAVED 0xD9 /* Ri[7:0] saved */
177#define HDMI_RI_15_8_SAVED 0xDA /* Ri[15:8] saved */
178#define HDMI_PJ_SAVED 0xDB /* Pj saved */
179#define HDMI_NUM_OF_DEVICES 0xDC /* Number of devices */
180#define HDMI_HOT_PLUG_MSENS_STATUS 0xDF /* Hot plug/MSENS status */
181#define HDMI_BCAPS_WRITE 0xE0 /* bcaps */
182#define HDMI_BSTAT_7_0 0xE1 /* bstat[7:0] */
183#define HDMI_BSTAT_15_8 0xE2 /* bstat[15:8] */
184#define HDMI_BKSV_7_0 0xE3 /* bksv[7:0] */
185#define HDMI_BKSV_15_8 0xE4 /* bksv[15:8] */
186#define HDMI_BKSV_23_16 0xE5 /* bksv[23:16] */
187#define HDMI_BKSV_31_24 0xE6 /* bksv[31:24] */
188#define HDMI_BKSV_39_32 0xE7 /* bksv[39:32] */
189#define HDMI_AN_7_0 0xE8 /* An[7:0] */
190#define HDMI_AN_15_8 0xE9 /* An [15:8] */
191#define HDMI_AN_23_16 0xEA /* An [23:16] */
192#define HDMI_AN_31_24 0xEB /* An [31:24] */
193#define HDMI_AN_39_32 0xEC /* An [39:32] */
194#define HDMI_AN_47_40 0xED /* An [47:40] */
195#define HDMI_AN_55_48 0xEE /* An [55:48] */
196#define HDMI_AN_63_56 0xEF /* An [63:56] */
197#define HDMI_PRODUCT_ID 0xF0 /* Product ID */
198#define HDMI_REVISION_ID 0xF1 /* Revision ID */
199#define HDMI_TEST_MODE 0xFE /* Test mode */
200
201enum hotplug_state {
202 HDMI_HOTPLUG_DISCONNECTED,
203 HDMI_HOTPLUG_CONNECTED,
204 HDMI_HOTPLUG_EDID_DONE,
205};
206
207struct sh_hdmi {
208 void __iomem *base;
209 enum hotplug_state hp_state;
210 struct clk *hdmi_clk;
211 struct device *dev;
212 struct fb_info *info;
213 struct delayed_work edid_work;
214 struct fb_var_screeninfo var;
215};
216
217static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
218{
219 iowrite8(data, hdmi->base + reg);
220}
221
222static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
223{
224 return ioread8(hdmi->base + reg);
225}
226
227/*
228 * HDMI sound
229 */
230static unsigned int sh_hdmi_snd_read(struct snd_soc_codec *codec,
231 unsigned int reg)
232{
233 struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
234
235 return hdmi_read(hdmi, reg);
236}
237
238static int sh_hdmi_snd_write(struct snd_soc_codec *codec,
239 unsigned int reg,
240 unsigned int value)
241{
242 struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
243
244 hdmi_write(hdmi, value, reg);
245 return 0;
246}
247
248static struct snd_soc_dai_driver sh_hdmi_dai = {
249 .name = "sh_mobile_hdmi-hifi",
250 .playback = {
251 .stream_name = "Playback",
252 .channels_min = 2,
253 .channels_max = 8,
254 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
255 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
256 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
257 SNDRV_PCM_RATE_192000,
258 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
259 },
260};
261
262static int sh_hdmi_snd_probe(struct snd_soc_codec *codec)
263{
264 dev_info(codec->dev, "SH Mobile HDMI Audio Codec");
265
266 return 0;
267}
268
269static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
270 .probe = sh_hdmi_snd_probe,
271 .read = sh_hdmi_snd_read,
272 .write = sh_hdmi_snd_write,
273};
274
275/*
276 * HDMI video
277 */
278
279/* External video parameter settings */
280static void hdmi_external_video_param(struct sh_hdmi *hdmi)
281{
282 struct fb_var_screeninfo *var = &hdmi->var;
283 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
284 u8 sync = 0;
285
286 htotal = var->xres + var->right_margin + var->left_margin + var->hsync_len;
287
288 hdelay = var->hsync_len + var->left_margin;
289 hblank = var->right_margin + hdelay;
290
291 /*
292 * Vertical timing looks a bit different in Figure 18,
293 * but let's try the same first by setting offset = 0
294 */
295 vtotal = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
296
297 vdelay = var->vsync_len + var->upper_margin;
298 vblank = var->lower_margin + vdelay;
299 voffset = min(var->upper_margin / 2, 6U);
300
301 /*
302 * [3]: VSYNC polarity: Positive
303 * [2]: HSYNC polarity: Positive
304 * [1]: Interlace/Progressive: Progressive
305 * [0]: External video settings enable: used.
306 */
307 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
308 sync |= 4;
309 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
310 sync |= 8;
311
312 pr_debug("H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
313 htotal, hblank, hdelay, var->hsync_len,
314 vtotal, vblank, vdelay, var->vsync_len, sync);
315
316 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
317
318 hdmi_write(hdmi, htotal, HDMI_EXTERNAL_H_TOTAL_7_0);
319 hdmi_write(hdmi, htotal >> 8, HDMI_EXTERNAL_H_TOTAL_11_8);
320
321 hdmi_write(hdmi, hblank, HDMI_EXTERNAL_H_BLANK_7_0);
322 hdmi_write(hdmi, hblank >> 8, HDMI_EXTERNAL_H_BLANK_9_8);
323
324 hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0);
325 hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8);
326
327 hdmi_write(hdmi, var->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0);
328 hdmi_write(hdmi, var->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8);
329
330 hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0);
331 hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8);
332
333 hdmi_write(hdmi, vblank, HDMI_EXTERNAL_V_BLANK);
334
335 hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY);
336
337 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
338
339 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for manual mode */
340}
341
342/**
343 * sh_hdmi_video_config()
344 */
345static void sh_hdmi_video_config(struct sh_hdmi *hdmi)
346{
347 /*
348 * [7:4]: Audio sampling frequency: 48kHz
349 * [3:1]: Input video format: RGB and YCbCr 4:4:4 (Y on Green)
350 * [0]: Internal/External DE select: internal
351 */
352 hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1);
353
354 /*
355 * [7:6]: Video output format: RGB 4:4:4
356 * [5:4]: Input video data width: 8 bit
357 * [3:1]: EAV/SAV location: channel 1
358 * [0]: Video input color space: RGB
359 */
360 hdmi_write(hdmi, 0x34, HDMI_VIDEO_SETTING_1);
361
362 /*
363 * [7:6]: Together with bit [6] of HDMI_AUDIO_VIDEO_SETTING_2, which is
364 * left at 0 by default, this configures 24bpp and sets the Color Depth
365 * (CD) field in the General Control Packet
366 */
367 hdmi_write(hdmi, 0x20, HDMI_DEEP_COLOR_MODES);
368}
369
370/**
371 * sh_hdmi_audio_config()
372 */
373static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
374{
375 u8 data;
376 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
377
378 /*
379 * [7:4] L/R data swap control
380 * [3:0] appropriate N[19:16]
381 */
382 hdmi_write(hdmi, 0x00, HDMI_L_R_DATA_SWAP_CTRL_RPKT);
383 /* appropriate N[15:8] */
384 hdmi_write(hdmi, 0x18, HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8);
385 /* appropriate N[7:0] */
386 hdmi_write(hdmi, 0x00, HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0);
387
388 /* [7:4] 48 kHz SPDIF not used */
389 hdmi_write(hdmi, 0x20, HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS);
390
391 /*
392 * [6:5] set required down sampling rate if required
393 * [4:3] set required audio source
394 */
395 switch (pdata->flags & HDMI_SND_SRC_MASK) {
396 default:
397 /* fall through */
398 case HDMI_SND_SRC_I2S:
399 data = 0x0 << 3;
400 break;
401 case HDMI_SND_SRC_SPDIF:
402 data = 0x1 << 3;
403 break;
404 case HDMI_SND_SRC_DSD:
405 data = 0x2 << 3;
406 break;
407 case HDMI_SND_SRC_HBR:
408 data = 0x3 << 3;
409 break;
410 }
411 hdmi_write(hdmi, data, HDMI_AUDIO_SETTING_1);
412
413 /* [3:0] set sending channel number for channel status */
414 hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2);
415
416 /*
417 * [5:2] set valid I2S source input pin
418 * [1:0] set input I2S source mode
419 */
420 hdmi_write(hdmi, 0x04, HDMI_I2S_AUDIO_SET);
421
422 /* [7:4] set valid DSD source input pin */
423 hdmi_write(hdmi, 0x00, HDMI_DSD_AUDIO_SET);
424
425 /* [7:0] set appropriate I2S input pin swap settings if required */
426 hdmi_write(hdmi, 0x00, HDMI_I2S_INPUT_PIN_SWAP);
427
428 /*
429 * [7] set validity bit for channel status
430 * [3:0] set original sample frequency for channel status
431 */
432 hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_1);
433
434 /*
435 * [7] set value for channel status
436 * [6] set value for channel status
437 * [5] set copyright bit for channel status
438 * [4:2] set additional information for channel status
439 * [1:0] set clock accuracy for channel status
440 */
441 hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_2);
442
443 /* [7:0] set category code for channel status */
444 hdmi_write(hdmi, 0x00, HDMI_CATEGORY_CODE);
445
446 /*
447 * [7:4] set source number for channel status
448 * [3:0] set word length for channel status
449 */
450 hdmi_write(hdmi, 0x00, HDMI_SOURCE_NUM_AUDIO_WORD_LEN);
451
452 /* [7:4] set sample frequency for channel status */
453 hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1);
454}
455
456/**
457 * sh_hdmi_phy_config()
458 */
459static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
460{
461 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
462 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
463 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
464 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
465 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */
466 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
467 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
468 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
469 hdmi_write(hdmi, 0x0E, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
470 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
471 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
472}
473
474/**
475 * sh_hdmi_avi_infoframe_setup() - Auxiliary Video Information InfoFrame CONTROL PACKET
476 */
477static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
478{
479 /* AVI InfoFrame */
480 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX);
481
482 /* Packet Type = 0x82 */
483 hdmi_write(hdmi, 0x82, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
484
485 /* Version = 0x02 */
486 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
487
488 /* Length = 13 (0x0D) */
489 hdmi_write(hdmi, 0x0D, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
490
491 /* N. A. Checksum */
492 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0);
493
494 /*
495 * Y = RGB
496 * A0 = No Data
497 * B = Bar Data not valid
498 * S = No Data
499 */
500 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
501
502 /*
503 * C = No Data
504 * M = 16:9 Picture Aspect Ratio
505 * R = Same as picture aspect ratio
506 */
507 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
508
509 /*
510 * ITC = No Data
511 * EC = xvYCC601
512 * Q = Default (depends on video format)
513 * SC = No Known non_uniform Scaling
514 */
515 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
516
517 /*
518 * VIC = 1280 x 720p: ignored if external config is used
519 * Send 2 for 720 x 480p, 16 for 1080p
520 */
521 hdmi_write(hdmi, 4, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
522
523 /* PR = No Repetition */
524 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
525
526 /* Line Number of End of Top Bar (lower 8 bits) */
527 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6);
528
529 /* Line Number of End of Top Bar (upper 8 bits) */
530 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7);
531
532 /* Line Number of Start of Bottom Bar (lower 8 bits) */
533 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8);
534
535 /* Line Number of Start of Bottom Bar (upper 8 bits) */
536 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9);
537
538 /* Pixel Number of End of Left Bar (lower 8 bits) */
539 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10);
540
541 /* Pixel Number of End of Left Bar (upper 8 bits) */
542 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB11);
543
544 /* Pixel Number of Start of Right Bar (lower 8 bits) */
545 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB12);
546
547 /* Pixel Number of Start of Right Bar (upper 8 bits) */
548 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB13);
549}
550
551/**
552 * sh_hdmi_audio_infoframe_setup() - Audio InfoFrame of CONTROL PACKET
553 */
554static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi)
555{
556 /* Audio InfoFrame */
557 hdmi_write(hdmi, 0x08, HDMI_CTRL_PKT_BUF_INDEX);
558
559 /* Packet Type = 0x84 */
560 hdmi_write(hdmi, 0x84, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
561
562 /* Version Number = 0x01 */
563 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
564
565 /* 0 Length = 10 (0x0A) */
566 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
567
568 /* n. a. Checksum */
569 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0);
570
571 /* Audio Channel Count = Refer to Stream Header */
572 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
573
574 /* Refer to Stream Header */
575 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
576
577 /* Format depends on coding type (i.e. CT0...CT3) */
578 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
579
580 /* Speaker Channel Allocation = Front Right + Front Left */
581 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
582
583 /* Level Shift Value = 0 dB, Down - mix is permitted or no information */
584 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
585
586 /* Reserved (0) */
587 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6);
588 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7);
589 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8);
590 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9);
591 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10);
592}
593
594/**
595 * sh_hdmi_gamut_metadata_setup() - Gamut Metadata Packet of CONTROL PACKET
596 */
597static void sh_hdmi_gamut_metadata_setup(struct sh_hdmi *hdmi)
598{
599 int i;
600
601 /* Gamut Metadata Packet */
602 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_INDEX);
603
604 /* Packet Type = 0x0A */
605 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
606 /* Gamut Packet is not used, so default value */
607 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
608 /* Gamut Packet is not used, so default value */
609 hdmi_write(hdmi, 0x10, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
610
611 /* GBD bytes 0 through 27 */
612 for (i = 0; i <= 27; i++)
613 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0_63H - PB27_7EH */
614 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
615}
616
617/**
618 * sh_hdmi_acp_setup() - Audio Content Protection Packet (ACP)
619 */
620static void sh_hdmi_acp_setup(struct sh_hdmi *hdmi)
621{
622 int i;
623
624 /* Audio Content Protection Packet (ACP) */
625 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_INDEX);
626
627 /* Packet Type = 0x04 */
628 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
629 /* ACP_Type */
630 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
631 /* Reserved (0) */
632 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
633
634 /* GBD bytes 0 through 27 */
635 for (i = 0; i <= 27; i++)
636 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
637 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
638}
639
640/**
641 * sh_hdmi_isrc1_setup() - ISRC1 Packet
642 */
643static void sh_hdmi_isrc1_setup(struct sh_hdmi *hdmi)
644{
645 int i;
646
647 /* ISRC1 Packet */
648 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_INDEX);
649
650 /* Packet Type = 0x05 */
651 hdmi_write(hdmi, 0x05, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
652 /* ISRC_Cont, ISRC_Valid, Reserved (0), ISRC_Status */
653 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
654 /* Reserved (0) */
655 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
656
657 /* PB0 UPC_EAN_ISRC_0-15 */
658 /* Bytes PB16-PB27 shall be set to a value of 0. */
659 for (i = 0; i <= 27; i++)
660 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
661 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
662}
663
664/**
665 * sh_hdmi_isrc2_setup() - ISRC2 Packet
666 */
667static void sh_hdmi_isrc2_setup(struct sh_hdmi *hdmi)
668{
669 int i;
670
671 /* ISRC2 Packet */
672 hdmi_write(hdmi, 0x03, HDMI_CTRL_PKT_BUF_INDEX);
673
674 /* HB0 Packet Type = 0x06 */
675 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
676 /* Reserved (0) */
677 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
678 /* Reserved (0) */
679 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
680
681 /* PB0 UPC_EAN_ISRC_16-31 */
682 /* Bytes PB16-PB27 shall be set to a value of 0. */
683 for (i = 0; i <= 27; i++)
684 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
685 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
686}
687
688/**
689 * sh_hdmi_configure() - Initialise HDMI for output
690 */
691static void sh_hdmi_configure(struct sh_hdmi *hdmi)
692{
693 /* Configure video format */
694 sh_hdmi_video_config(hdmi);
695
696 /* Configure audio format */
697 sh_hdmi_audio_config(hdmi);
698
699 /* Configure PHY */
700 sh_hdmi_phy_config(hdmi);
701
702 /* Auxiliary Video Information (AVI) InfoFrame */
703 sh_hdmi_avi_infoframe_setup(hdmi);
704
705 /* Audio InfoFrame */
706 sh_hdmi_audio_infoframe_setup(hdmi);
707
708 /* Gamut Metadata packet */
709 sh_hdmi_gamut_metadata_setup(hdmi);
710
711 /* Audio Content Protection (ACP) Packet */
712 sh_hdmi_acp_setup(hdmi);
713
714 /* ISRC1 Packet */
715 sh_hdmi_isrc1_setup(hdmi);
716
717 /* ISRC2 Packet */
718 sh_hdmi_isrc2_setup(hdmi);
719
720 /*
721 * Control packet auto send with VSYNC control: auto send
722 * General control, Gamut metadata, ISRC, and ACP packets
723 */
724 hdmi_write(hdmi, 0x8E, HDMI_CTRL_PKT_AUTO_SEND);
725
726 /* FIXME */
727 msleep(10);
728
729 /* PS mode b->d, reset PLLA and PLLB */
730 hdmi_write(hdmi, 0x4C, HDMI_SYSTEM_CTRL);
731
732 udelay(10);
733
734 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
735}
736
737static void sh_hdmi_read_edid(struct sh_hdmi *hdmi)
738{
739 struct fb_var_screeninfo *var = &hdmi->var;
740 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
741 struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg;
742 unsigned long height = var->height, width = var->width;
743 int i;
744 u8 edid[128];
745
746 /* Read EDID */
747 pr_debug("Read back EDID code:");
748 for (i = 0; i < 128; i++) {
749 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
750#ifdef DEBUG
751 if ((i % 16) == 0) {
752 printk(KERN_CONT "\n");
753 printk(KERN_DEBUG "%02X | %02X", i, edid[i]);
754 } else {
755 printk(KERN_CONT " %02X", edid[i]);
756 }
757#endif
758 }
759#ifdef DEBUG
760 printk(KERN_CONT "\n");
761#endif
762 fb_parse_edid(edid, var);
763 pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n",
764 var->left_margin, var->xres, var->right_margin, var->hsync_len,
765 var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
766 PICOS2KHZ(var->pixclock));
767
768 /* FIXME: Use user-provided configuration instead of EDID */
769 var->width = width;
770 var->xres = lcd_cfg->xres;
771 var->xres_virtual = lcd_cfg->xres;
772 var->left_margin = lcd_cfg->left_margin;
773 var->right_margin = lcd_cfg->right_margin;
774 var->hsync_len = lcd_cfg->hsync_len;
775 var->height = height;
776 var->yres = lcd_cfg->yres;
777 var->yres_virtual = lcd_cfg->yres * 2;
778 var->upper_margin = lcd_cfg->upper_margin;
779 var->lower_margin = lcd_cfg->lower_margin;
780 var->vsync_len = lcd_cfg->vsync_len;
781 var->sync = lcd_cfg->sync;
782 var->pixclock = lcd_cfg->pixclock;
783
784 hdmi_external_video_param(hdmi);
785}
786
787static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
788{
789 struct sh_hdmi *hdmi = dev_id;
790 u8 status1, status2, mask1, mask2;
791
792 /* mode_b and PLLA and PLLB reset */
793 hdmi_write(hdmi, 0x2C, HDMI_SYSTEM_CTRL);
794
795 /* How long shall reset be held? */
796 udelay(10);
797
798 /* mode_b and PLLA and PLLB reset release */
799 hdmi_write(hdmi, 0x20, HDMI_SYSTEM_CTRL);
800
801 status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1);
802 status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2);
803
804 mask1 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_1);
805 mask2 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_2);
806
807 /* Correct would be to ack only set bits, but the datasheet requires 0xff */
808 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_1);
809 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2);
810
811 if (printk_ratelimit())
812 pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n",
813 irq, status1, mask1, status2, mask2);
814
815 if (!((status1 & mask1) | (status2 & mask2))) {
816 return IRQ_NONE;
817 } else if (status1 & 0xc0) {
818 u8 msens;
819
820 /* Datasheet specifies 10ms... */
821 udelay(500);
822
823 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS);
824 pr_debug("MSENS 0x%x\n", msens);
825 /* Check, if hot plug & MSENS pin status are both high */
826 if ((msens & 0xC0) == 0xC0) {
827 /* Display plug in */
828 hdmi->hp_state = HDMI_HOTPLUG_CONNECTED;
829
830 /* Set EDID word address */
831 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
832 /* Set EDID segment pointer */
833 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
834 /* Enable EDID interrupt */
835 hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
836 } else if (!(status1 & 0x80)) {
837 /* Display unplug, beware multiple interrupts */
838 if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED)
839 schedule_delayed_work(&hdmi->edid_work, 0);
840
841 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
842 /* display_off will switch back to mode_a */
843 }
844 } else if (status1 & 2) {
845 /* EDID error interrupt: retry */
846 /* Set EDID word address */
847 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
848 /* Set EDID segment pointer */
849 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
850 } else if (status1 & 4) {
851 /* Disable EDID interrupt */
852 hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1);
853 hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
854 schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10));
855 }
856
857 return IRQ_HANDLED;
858}
859
860static void hdmi_display_on(void *arg, struct fb_info *info)
861{
862 struct sh_hdmi *hdmi = arg;
863 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
864
865 if (info->var.xres != 1280 || info->var.yres != 720) {
866 dev_warn(info->device, "Unsupported framebuffer geometry %ux%u\n",
867 info->var.xres, info->var.yres);
868 return;
869 }
870
871 pr_debug("%s(%p): state %x\n", __func__, pdata->lcd_dev, info->state);
872 /*
873 * FIXME: not a good place to store fb_info. And we cannot nullify it
874 * even on monitor disconnect. What should the lifecycle be?
875 */
876 hdmi->info = info;
877 switch (hdmi->hp_state) {
878 case HDMI_HOTPLUG_EDID_DONE:
879 /* PS mode d->e. All functions are active */
880 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
881 pr_debug("HDMI running\n");
882 break;
883 case HDMI_HOTPLUG_DISCONNECTED:
884 info->state = FBINFO_STATE_SUSPENDED;
885 default:
886 hdmi->var = info->var;
887 }
888}
889
890static void hdmi_display_off(void *arg)
891{
892 struct sh_hdmi *hdmi = arg;
893 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
894
895 pr_debug("%s(%p)\n", __func__, pdata->lcd_dev);
896 /* PS mode e->a */
897 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
898}
899
900/* Hotplug interrupt occurred, read EDID */
901static void edid_work_fn(struct work_struct *work)
902{
903 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
904 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
905
906 pr_debug("%s(%p): begin, hotplug status %d\n", __func__,
907 pdata->lcd_dev, hdmi->hp_state);
908
909 if (!pdata->lcd_dev)
910 return;
911
912 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
913 pm_runtime_get_sync(hdmi->dev);
914 /* A device has been plugged in */
915 sh_hdmi_read_edid(hdmi);
916 msleep(10);
917 sh_hdmi_configure(hdmi);
918 /* Switched to another (d) power-save mode */
919 msleep(10);
920
921 if (!hdmi->info)
922 return;
923
924 acquire_console_sem();
925
926 /* HDMI plug in */
927 hdmi->info->var = hdmi->var;
928 if (hdmi->info->state != FBINFO_STATE_RUNNING)
929 fb_set_suspend(hdmi->info, 0);
930 else
931 hdmi_display_on(hdmi, hdmi->info);
932
933 release_console_sem();
934 } else {
935 if (!hdmi->info)
936 return;
937
938 acquire_console_sem();
939
940 /* HDMI disconnect */
941 fb_set_suspend(hdmi->info, 1);
942
943 release_console_sem();
944 pm_runtime_put(hdmi->dev);
945 }
946
947 pr_debug("%s(%p): end\n", __func__, pdata->lcd_dev);
948}
949
950static int __init sh_hdmi_probe(struct platform_device *pdev)
951{
952 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
953 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
954 int irq = platform_get_irq(pdev, 0), ret;
955 struct sh_hdmi *hdmi;
956 long rate;
957
958 if (!res || !pdata || irq < 0)
959 return -ENODEV;
960
961 hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
962 if (!hdmi) {
963 dev_err(&pdev->dev, "Cannot allocate device data\n");
964 return -ENOMEM;
965 }
966
967 ret = snd_soc_register_codec(&pdev->dev,
968 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
969 if (ret < 0)
970 goto esndreg;
971
972 hdmi->dev = &pdev->dev;
973
974 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
975 if (IS_ERR(hdmi->hdmi_clk)) {
976 ret = PTR_ERR(hdmi->hdmi_clk);
977 dev_err(&pdev->dev, "Unable to get clock: %d\n", ret);
978 goto egetclk;
979 }
980
981 rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000;
982
983 rate = clk_round_rate(hdmi->hdmi_clk, rate);
984 if (rate < 0) {
985 ret = rate;
986 dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate);
987 goto erate;
988 }
989
990 ret = clk_set_rate(hdmi->hdmi_clk, rate);
991 if (ret < 0) {
992 dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret);
993 goto erate;
994 }
995
996 pr_debug("HDMI set frequency %lu\n", rate);
997
998 ret = clk_enable(hdmi->hdmi_clk);
999 if (ret < 0) {
1000 dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret);
1001 goto eclkenable;
1002 }
1003
1004 dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
1005
1006 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
1007 dev_err(&pdev->dev, "HDMI register region already claimed\n");
1008 ret = -EBUSY;
1009 goto ereqreg;
1010 }
1011
1012 hdmi->base = ioremap(res->start, resource_size(res));
1013 if (!hdmi->base) {
1014 dev_err(&pdev->dev, "HDMI register region already claimed\n");
1015 ret = -ENOMEM;
1016 goto emap;
1017 }
1018
1019 platform_set_drvdata(pdev, hdmi);
1020
1021#if 1
1022 /* Product and revision IDs are 0 in sh-mobile version */
1023 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
1024 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
1025#endif
1026
1027 /* Set up LCDC callbacks */
1028 pdata->lcd_chan->board_cfg.board_data = hdmi;
1029 pdata->lcd_chan->board_cfg.display_on = hdmi_display_on;
1030 pdata->lcd_chan->board_cfg.display_off = hdmi_display_off;
1031
1032 INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn);
1033
1034 pm_runtime_enable(&pdev->dev);
1035 pm_runtime_resume(&pdev->dev);
1036
1037 ret = request_irq(irq, sh_hdmi_hotplug, 0,
1038 dev_name(&pdev->dev), hdmi);
1039 if (ret < 0) {
1040 dev_err(&pdev->dev, "Unable to request irq: %d\n", ret);
1041 goto ereqirq;
1042 }
1043
1044 return 0;
1045
1046ereqirq:
1047 pm_runtime_disable(&pdev->dev);
1048 iounmap(hdmi->base);
1049emap:
1050 release_mem_region(res->start, resource_size(res));
1051ereqreg:
1052 clk_disable(hdmi->hdmi_clk);
1053eclkenable:
1054erate:
1055 clk_put(hdmi->hdmi_clk);
1056egetclk:
1057 snd_soc_unregister_codec(&pdev->dev);
1058esndreg:
1059 kfree(hdmi);
1060
1061 return ret;
1062}
1063
1064static int __exit sh_hdmi_remove(struct platform_device *pdev)
1065{
1066 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
1067 struct sh_hdmi *hdmi = platform_get_drvdata(pdev);
1068 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1069 int irq = platform_get_irq(pdev, 0);
1070
1071 snd_soc_unregister_codec(&pdev->dev);
1072
1073 pdata->lcd_chan->board_cfg.display_on = NULL;
1074 pdata->lcd_chan->board_cfg.display_off = NULL;
1075 pdata->lcd_chan->board_cfg.board_data = NULL;
1076
1077 free_irq(irq, hdmi);
1078 pm_runtime_disable(&pdev->dev);
1079 cancel_delayed_work_sync(&hdmi->edid_work);
1080 clk_disable(hdmi->hdmi_clk);
1081 clk_put(hdmi->hdmi_clk);
1082 iounmap(hdmi->base);
1083 release_mem_region(res->start, resource_size(res));
1084 kfree(hdmi);
1085
1086 return 0;
1087}
1088
1089static struct platform_driver sh_hdmi_driver = {
1090 .remove = __exit_p(sh_hdmi_remove),
1091 .driver = {
1092 .name = "sh-mobile-hdmi",
1093 },
1094};
1095
1096static int __init sh_hdmi_init(void)
1097{
1098 return platform_driver_probe(&sh_hdmi_driver, sh_hdmi_probe);
1099}
1100module_init(sh_hdmi_init);
1101
1102static void __exit sh_hdmi_exit(void)
1103{
1104 platform_driver_unregister(&sh_hdmi_driver);
1105}
1106module_exit(sh_hdmi_exit);
1107
1108MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
1109MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver");
1110MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 12c451a711e9..7a1419279c8f 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -56,6 +56,7 @@ static int lcdc_shared_regs[] = {
56/* per-channel registers */ 56/* per-channel registers */
57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, 57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR, 58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
59 LDHAJR,
59 NR_CH_REGS }; 60 NR_CH_REGS };
60 61
61static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 62static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
@@ -74,6 +75,7 @@ static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
74 [LDVLNR] = 0x450, 75 [LDVLNR] = 0x450,
75 [LDVSYNR] = 0x454, 76 [LDVSYNR] = 0x454,
76 [LDPMR] = 0x460, 77 [LDPMR] = 0x460,
78 [LDHAJR] = 0x4a0,
77}; 79};
78 80
79static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { 81static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
@@ -137,6 +139,7 @@ struct sh_mobile_lcdc_priv {
137 struct clk *dot_clk; 139 struct clk *dot_clk;
138 unsigned long lddckr; 140 unsigned long lddckr;
139 struct sh_mobile_lcdc_chan ch[2]; 141 struct sh_mobile_lcdc_chan ch[2];
142 struct notifier_block notifier;
140 unsigned long saved_shared_regs[NR_SHARED_REGS]; 143 unsigned long saved_shared_regs[NR_SHARED_REGS];
141 int started; 144 int started;
142}; 145};
@@ -404,6 +407,56 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
404 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */ 407 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
405} 408}
406 409
410static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
411{
412 struct fb_var_screeninfo *var = &ch->info->var;
413 unsigned long h_total, hsync_pos;
414 u32 tmp;
415
416 tmp = ch->ldmt1r_value;
417 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
418 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
419 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
420 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
421 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
422 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
423 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
424 lcdc_write_chan(ch, LDMT1R, tmp);
425
426 /* setup SYS bus */
427 lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
428 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
429
430 /* horizontal configuration */
431 h_total = var->xres + var->hsync_len +
432 var->left_margin + var->right_margin;
433 tmp = h_total / 8; /* HTCN */
434 tmp |= (var->xres / 8) << 16; /* HDCN */
435 lcdc_write_chan(ch, LDHCNR, tmp);
436
437 hsync_pos = var->xres + var->right_margin;
438 tmp = hsync_pos / 8; /* HSYNP */
439 tmp |= (var->hsync_len / 8) << 16; /* HSYNW */
440 lcdc_write_chan(ch, LDHSYNR, tmp);
441
442 /* vertical configuration */
443 tmp = var->yres + var->vsync_len +
444 var->upper_margin + var->lower_margin; /* VTLN */
445 tmp |= var->yres << 16; /* VDLN */
446 lcdc_write_chan(ch, LDVLNR, tmp);
447
448 tmp = var->yres + var->lower_margin; /* VSYNP */
449 tmp |= var->vsync_len << 16; /* VSYNW */
450 lcdc_write_chan(ch, LDVSYNR, tmp);
451
452 /* Adjust horizontal synchronisation for HDMI */
453 tmp = ((var->xres & 7) << 24) |
454 ((h_total & 7) << 16) |
455 ((var->hsync_len & 7) << 8) |
456 hsync_pos;
457 lcdc_write_chan(ch, LDHAJR, tmp);
458}
459
407static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 460static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
408{ 461{
409 struct sh_mobile_lcdc_chan *ch; 462 struct sh_mobile_lcdc_chan *ch;
@@ -470,49 +523,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
470 if (!ch->enabled) 523 if (!ch->enabled)
471 continue; 524 continue;
472 525
473 tmp = ch->ldmt1r_value; 526 sh_mobile_lcdc_geometry(ch);
474 tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
475 tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
476 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
477 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
478 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
479 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
480 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
481 lcdc_write_chan(ch, LDMT1R, tmp);
482
483 /* setup SYS bus */
484 lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
485 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
486
487 /* horizontal configuration */
488 tmp = lcd_cfg->xres + lcd_cfg->hsync_len;
489 tmp += lcd_cfg->left_margin;
490 tmp += lcd_cfg->right_margin;
491 tmp /= 8; /* HTCN */
492 tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */
493 lcdc_write_chan(ch, LDHCNR, tmp);
494
495 tmp = lcd_cfg->xres;
496 tmp += lcd_cfg->right_margin;
497 tmp /= 8; /* HSYNP */
498 tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */
499 lcdc_write_chan(ch, LDHSYNR, tmp);
500 527
501 /* power supply */ 528 /* power supply */
502 lcdc_write_chan(ch, LDPMR, 0); 529 lcdc_write_chan(ch, LDPMR, 0);
503 530
504 /* vertical configuration */
505 tmp = lcd_cfg->yres + lcd_cfg->vsync_len;
506 tmp += lcd_cfg->upper_margin;
507 tmp += lcd_cfg->lower_margin; /* VTLN */
508 tmp |= lcd_cfg->yres << 16; /* VDLN */
509 lcdc_write_chan(ch, LDVLNR, tmp);
510
511 tmp = lcd_cfg->yres;
512 tmp += lcd_cfg->lower_margin; /* VSYNP */
513 tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */
514 lcdc_write_chan(ch, LDVSYNR, tmp);
515
516 board_cfg = &ch->cfg.board_cfg; 531 board_cfg = &ch->cfg.board_cfg;
517 if (board_cfg->setup_sys) 532 if (board_cfg->setup_sys)
518 ret = board_cfg->setup_sys(board_cfg->board_data, ch, 533 ret = board_cfg->setup_sys(board_cfg->board_data, ch,
@@ -577,7 +592,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
577 592
578 board_cfg = &ch->cfg.board_cfg; 593 board_cfg = &ch->cfg.board_cfg;
579 if (board_cfg->display_on) 594 if (board_cfg->display_on)
580 board_cfg->display_on(board_cfg->board_data); 595 board_cfg->display_on(board_cfg->board_data, ch->info);
581 } 596 }
582 597
583 return 0; 598 return 0;
@@ -943,6 +958,62 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
943 .runtime_resume = sh_mobile_lcdc_runtime_resume, 958 .runtime_resume = sh_mobile_lcdc_runtime_resume,
944}; 959};
945 960
961static int sh_mobile_lcdc_notify(struct notifier_block *nb,
962 unsigned long action, void *data)
963{
964 struct fb_event *event = data;
965 struct fb_info *info = event->info;
966 struct sh_mobile_lcdc_chan *ch = info->par;
967 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
968 struct fb_var_screeninfo *var;
969
970 if (&ch->lcdc->notifier != nb)
971 return 0;
972
973 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
974 __func__, action, event->data);
975
976 switch(action) {
977 case FB_EVENT_SUSPEND:
978 if (board_cfg->display_off)
979 board_cfg->display_off(board_cfg->board_data);
980 pm_runtime_put(info->device);
981 break;
982 case FB_EVENT_RESUME:
983 var = &info->var;
984
985 /* HDMI must be enabled before LCDC configuration */
986 if (board_cfg->display_on)
987 board_cfg->display_on(board_cfg->board_data, ch->info);
988
989 /* Check if the new display is not in our modelist */
990 if (ch->info->modelist.next &&
991 !fb_match_mode(var, &ch->info->modelist)) {
992 struct fb_videomode mode;
993 int ret;
994
995 /* Can we handle this display? */
996 if (var->xres > ch->cfg.lcd_cfg.xres ||
997 var->yres > ch->cfg.lcd_cfg.yres)
998 return -ENOMEM;
999
1000 /* Add to the modelist */
1001 fb_var_to_videomode(&mode, var);
1002 ret = fb_add_videomode(&mode, &ch->info->modelist);
1003 if (ret < 0)
1004 return ret;
1005 }
1006
1007 pm_runtime_get_sync(info->device);
1008
1009 sh_mobile_lcdc_geometry(ch);
1010
1011 break;
1012 }
1013
1014 return 0;
1015}
1016
946static int sh_mobile_lcdc_remove(struct platform_device *pdev); 1017static int sh_mobile_lcdc_remove(struct platform_device *pdev);
947 1018
948static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) 1019static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
@@ -1020,15 +1091,19 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1020 goto err1; 1091 goto err1;
1021 } 1092 }
1022 1093
1094 priv->base = ioremap_nocache(res->start, resource_size(res));
1095 if (!priv->base)
1096 goto err1;
1097
1023 error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv); 1098 error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv);
1024 if (error) { 1099 if (error) {
1025 dev_err(&pdev->dev, "unable to setup clocks\n"); 1100 dev_err(&pdev->dev, "unable to setup clocks\n");
1026 goto err1; 1101 goto err1;
1027 } 1102 }
1028 1103
1029 priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
1030
1031 for (i = 0; i < j; i++) { 1104 for (i = 0; i < j; i++) {
1105 struct fb_var_screeninfo *var;
1106 struct fb_videomode *lcd_cfg;
1032 cfg = &priv->ch[i].cfg; 1107 cfg = &priv->ch[i].cfg;
1033 1108
1034 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); 1109 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev);
@@ -1039,22 +1114,33 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1039 } 1114 }
1040 1115
1041 info = priv->ch[i].info; 1116 info = priv->ch[i].info;
1117 var = &info->var;
1118 lcd_cfg = &cfg->lcd_cfg;
1042 info->fbops = &sh_mobile_lcdc_ops; 1119 info->fbops = &sh_mobile_lcdc_ops;
1043 info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; 1120 var->xres = var->xres_virtual = lcd_cfg->xres;
1044 info->var.yres = cfg->lcd_cfg.yres; 1121 var->yres = lcd_cfg->yres;
1045 /* Default Y virtual resolution is 2x panel size */ 1122 /* Default Y virtual resolution is 2x panel size */
1046 info->var.yres_virtual = info->var.yres * 2; 1123 var->yres_virtual = var->yres * 2;
1047 info->var.width = cfg->lcd_size_cfg.width; 1124 var->width = cfg->lcd_size_cfg.width;
1048 info->var.height = cfg->lcd_size_cfg.height; 1125 var->height = cfg->lcd_size_cfg.height;
1049 info->var.activate = FB_ACTIVATE_NOW; 1126 var->activate = FB_ACTIVATE_NOW;
1050 error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp); 1127 var->left_margin = lcd_cfg->left_margin;
1128 var->right_margin = lcd_cfg->right_margin;
1129 var->upper_margin = lcd_cfg->upper_margin;
1130 var->lower_margin = lcd_cfg->lower_margin;
1131 var->hsync_len = lcd_cfg->hsync_len;
1132 var->vsync_len = lcd_cfg->vsync_len;
1133 var->sync = lcd_cfg->sync;
1134 var->pixclock = lcd_cfg->pixclock;
1135
1136 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp);
1051 if (error) 1137 if (error)
1052 break; 1138 break;
1053 1139
1054 info->fix = sh_mobile_lcdc_fix; 1140 info->fix = sh_mobile_lcdc_fix;
1055 info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8); 1141 info->fix.line_length = lcd_cfg->xres * (cfg->bpp / 8);
1056 info->fix.smem_len = info->fix.line_length * 1142 info->fix.smem_len = info->fix.line_length *
1057 info->var.yres_virtual; 1143 var->yres_virtual;
1058 1144
1059 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, 1145 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
1060 &priv->ch[i].dma_handle, GFP_KERNEL); 1146 &priv->ch[i].dma_handle, GFP_KERNEL);
@@ -1119,10 +1205,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1119 ch->cfg.bpp); 1205 ch->cfg.bpp);
1120 1206
1121 /* deferred io mode: disable clock to save power */ 1207 /* deferred io mode: disable clock to save power */
1122 if (info->fbdefio) 1208 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
1123 sh_mobile_lcdc_clk_off(priv); 1209 sh_mobile_lcdc_clk_off(priv);
1124 } 1210 }
1125 1211
1212 /* Failure ignored */
1213 priv->notifier.notifier_call = sh_mobile_lcdc_notify;
1214 fb_register_client(&priv->notifier);
1215
1126 return 0; 1216 return 0;
1127err1: 1217err1:
1128 sh_mobile_lcdc_remove(pdev); 1218 sh_mobile_lcdc_remove(pdev);
@@ -1136,6 +1226,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1136 struct fb_info *info; 1226 struct fb_info *info;
1137 int i; 1227 int i;
1138 1228
1229 fb_unregister_client(&priv->notifier);
1230
1139 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 1231 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1140 if (priv->ch[i].info && priv->ch[i].info->dev) 1232 if (priv->ch[i].info && priv->ch[i].info->dev)
1141 unregister_framebuffer(priv->ch[i].info); 1233 unregister_framebuffer(priv->ch[i].info);
@@ -1151,8 +1243,10 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1151 if (priv->ch[i].sglist) 1243 if (priv->ch[i].sglist)
1152 vfree(priv->ch[i].sglist); 1244 vfree(priv->ch[i].sglist);
1153 1245
1154 dma_free_coherent(&pdev->dev, info->fix.smem_len, 1246 if (info->screen_base)
1155 info->screen_base, priv->ch[i].dma_handle); 1247 dma_free_coherent(&pdev->dev, info->fix.smem_len,
1248 info->screen_base,
1249 priv->ch[i].dma_handle);
1156 fb_dealloc_cmap(&info->cmap); 1250 fb_dealloc_cmap(&info->cmap);
1157 framebuffer_release(info); 1251 framebuffer_release(info);
1158 } 1252 }
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 559bf1727a2b..b52f8e4ef1fd 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1701,6 +1701,9 @@ static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1701 break; 1701 break;
1702 1702
1703 case FBIOGET_VBLANK: 1703 case FBIOGET_VBLANK:
1704
1705 memset(&sisvbblank, 0, sizeof(struct fb_vblank));
1706
1704 sisvbblank.count = 0; 1707 sisvbblank.count = 0;
1705 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount); 1708 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1706 1709
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c
index 489b44e8db81..5dbe06af2226 100644
--- a/drivers/video/sunxvr1000.c
+++ b/drivers/video/sunxvr1000.c
@@ -111,7 +111,7 @@ static int __devinit gfb_set_fbinfo(struct gfb_info *gp)
111 return 0; 111 return 0;
112} 112}
113 113
114static int __devinit gfb_probe(struct of_device *op, 114static int __devinit gfb_probe(struct platform_device *op,
115 const struct of_device_id *match) 115 const struct of_device_id *match)
116{ 116{
117 struct device_node *dp = op->dev.of_node; 117 struct device_node *dp = op->dev.of_node;
@@ -172,7 +172,7 @@ err_out:
172 return err; 172 return err;
173} 173}
174 174
175static int __devexit gfb_remove(struct of_device *op) 175static int __devexit gfb_remove(struct platform_device *op)
176{ 176{
177 struct fb_info *info = dev_get_drvdata(&op->dev); 177 struct fb_info *info = dev_get_drvdata(&op->dev);
178 struct gfb_info *gp = info->par; 178 struct gfb_info *gp = info->par;
@@ -213,12 +213,12 @@ static int __init gfb_init(void)
213 if (fb_get_options("gfb", NULL)) 213 if (fb_get_options("gfb", NULL))
214 return -ENODEV; 214 return -ENODEV;
215 215
216 return of_register_driver(&gfb_driver, &of_bus_type); 216 return of_register_platform_driver(&gfb_driver);
217} 217}
218 218
219static void __exit gfb_exit(void) 219static void __exit gfb_exit(void)
220{ 220{
221 of_unregister_driver(&gfb_driver); 221 of_unregister_platform_driver(&gfb_driver);
222} 222}
223 223
224module_init(gfb_init); 224module_init(gfb_init);
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index cc039b33d2d8..77ad27955cf0 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -342,7 +342,7 @@ tcx_init_fix(struct fb_info *info, int linebytes)
342 info->fix.accel = FB_ACCEL_SUN_TCX; 342 info->fix.accel = FB_ACCEL_SUN_TCX;
343} 343}
344 344
345static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, 345static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info,
346 struct tcx_par *par) 346 struct tcx_par *par)
347{ 347{
348 if (par->tec) 348 if (par->tec)
@@ -362,7 +362,7 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info,
362 info->screen_base, info->fix.smem_len); 362 info->screen_base, info->fix.smem_len);
363} 363}
364 364
365static int __devinit tcx_probe(struct of_device *op, 365static int __devinit tcx_probe(struct platform_device *op,
366 const struct of_device_id *match) 366 const struct of_device_id *match)
367{ 367{
368 struct device_node *dp = op->dev.of_node; 368 struct device_node *dp = op->dev.of_node;
@@ -486,7 +486,7 @@ out_err:
486 return err; 486 return err;
487} 487}
488 488
489static int __devexit tcx_remove(struct of_device *op) 489static int __devexit tcx_remove(struct platform_device *op)
490{ 490{
491 struct fb_info *info = dev_get_drvdata(&op->dev); 491 struct fb_info *info = dev_get_drvdata(&op->dev);
492 struct tcx_par *par = info->par; 492 struct tcx_par *par = info->par;
@@ -526,12 +526,12 @@ static int __init tcx_init(void)
526 if (fb_get_options("tcxfb", NULL)) 526 if (fb_get_options("tcxfb", NULL))
527 return -ENODEV; 527 return -ENODEV;
528 528
529 return of_register_driver(&tcx_driver, &of_bus_type); 529 return of_register_platform_driver(&tcx_driver);
530} 530}
531 531
532static void __exit tcx_exit(void) 532static void __exit tcx_exit(void)
533{ 533{
534 of_unregister_driver(&tcx_driver); 534 of_unregister_platform_driver(&tcx_driver);
535} 535}
536 536
537module_init(tcx_init); 537module_init(tcx_init);
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 980548390048..3ee5e63cfa4f 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -1571,8 +1571,8 @@ out_err_iobase:
1571 if (default_par->mtrr_handle >= 0) 1571 if (default_par->mtrr_handle >= 0)
1572 mtrr_del(default_par->mtrr_handle, info->fix.smem_start, 1572 mtrr_del(default_par->mtrr_handle, info->fix.smem_start,
1573 info->fix.smem_len); 1573 info->fix.smem_len);
1574 release_mem_region(pci_resource_start(pdev, 2), 1574 release_region(pci_resource_start(pdev, 2),
1575 pci_resource_len(pdev, 2)); 1575 pci_resource_len(pdev, 2));
1576out_err_screenbase: 1576out_err_screenbase:
1577 if (info->screen_base) 1577 if (info->screen_base)
1578 iounmap(info->screen_base); 1578 iounmap(info->screen_base);
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 1b3b1c718e80..aba7686b1a32 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -305,7 +305,7 @@ tgafb_set_par(struct fb_info *info)
305 TGA_WRITE_REG(par, htimings, TGA_HORIZ_REG); 305 TGA_WRITE_REG(par, htimings, TGA_HORIZ_REG);
306 TGA_WRITE_REG(par, vtimings, TGA_VERT_REG); 306 TGA_WRITE_REG(par, vtimings, TGA_VERT_REG);
307 307
308 /* Initalise RAMDAC. */ 308 /* Initialise RAMDAC. */
309 if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) { 309 if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
310 310
311 /* Init BT485 RAMDAC registers. */ 311 /* Init BT485 RAMDAC registers. */
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 7b8839ebf3c4..52ec0959d462 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -1977,8 +1977,7 @@ static void __devexit uvesafb_exit(void)
1977 1977
1978module_exit(uvesafb_exit); 1978module_exit(uvesafb_exit);
1979 1979
1980#define param_get_scroll NULL 1980static int param_set_scroll(const char *val, const struct kernel_param *kp)
1981static int param_set_scroll(const char *val, struct kernel_param *kp)
1982{ 1981{
1983 ypan = 0; 1982 ypan = 0;
1984 1983
@@ -1993,7 +1992,9 @@ static int param_set_scroll(const char *val, struct kernel_param *kp)
1993 1992
1994 return 0; 1993 return 0;
1995} 1994}
1996 1995static struct kernel_param_ops param_ops_scroll = {
1996 .set = param_set_scroll,
1997};
1997#define param_check_scroll(name, p) __param_check(name, p, void) 1998#define param_check_scroll(name, p) __param_check(name, p, void)
1998 1999
1999module_param_named(scroll, ypan, scroll, 0); 2000module_param_named(scroll, ypan, scroll, 0);
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 090aa1a9be6e..6a069d047914 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -253,7 +253,7 @@ static int __init vesafb_probe(struct platform_device *dev)
253 size_vmode = vesafb_defined.yres * vesafb_fix.line_length; 253 size_vmode = vesafb_defined.yres * vesafb_fix.line_length;
254 254
255 /* size_total -- all video memory we have. Used for mtrr 255 /* size_total -- all video memory we have. Used for mtrr
256 * entries, ressource allocation and bounds 256 * entries, resource allocation and bounds
257 * checking. */ 257 * checking. */
258 size_total = screen_info.lfb_size * 65536; 258 size_total = screen_info.lfb_size * 65536;
259 if (vram_total) 259 if (vram_total)
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index d31dc96f838a..85d76ec4c63e 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -726,7 +726,9 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
726 726
727 /* Prepare startup mode */ 727 /* Prepare startup mode */
728 728
729 kparam_block_sysfs_write(mode_option);
729 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); 730 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
731 kparam_unblock_sysfs_write(mode_option);
730 if (! ((rc == 1) || (rc == 2))) { 732 if (! ((rc == 1) || (rc == 2))) {
731 rc = -EINVAL; 733 rc = -EINVAL;
732 dev_err(info->device, "mode %s not found\n", mode_option); 734 dev_err(info->device, "mode %s not found\n", mode_option);
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index e66b8b19ce5d..d8b12c32e3ef 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -858,9 +858,9 @@ unsigned long w100fb_gpio_read(int port)
858void w100fb_gpio_write(int port, unsigned long value) 858void w100fb_gpio_write(int port, unsigned long value)
859{ 859{
860 if (port==W100_GPIO_PORT_A) 860 if (port==W100_GPIO_PORT_A)
861 value = writel(value, remapped_regs + mmGPIO_DATA); 861 writel(value, remapped_regs + mmGPIO_DATA);
862 else 862 else
863 value = writel(value, remapped_regs + mmGPIO_DATA2); 863 writel(value, remapped_regs + mmGPIO_DATA2);
864} 864}
865EXPORT_SYMBOL(w100fb_gpio_read); 865EXPORT_SYMBOL(w100fb_gpio_read);
866EXPORT_SYMBOL(w100fb_gpio_write); 866EXPORT_SYMBOL(w100fb_gpio_write);
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index fa97d3e7c21a..7c7f42a12796 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -684,7 +684,7 @@ static struct xenbus_driver xenfb_driver = {
684 684
685static int __init xenfb_init(void) 685static int __init xenfb_init(void)
686{ 686{
687 if (!xen_domain()) 687 if (!xen_pv_domain())
688 return -ENODEV; 688 return -ENODEV;
689 689
690 /* Nothing to do if running in dom0. */ 690 /* Nothing to do if running in dom0. */
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 574dc54e12d4..68bd23476c64 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -32,10 +32,14 @@
32#include <linux/dma-mapping.h> 32#include <linux/dma-mapping.h>
33#include <linux/of_device.h> 33#include <linux/of_device.h>
34#include <linux/of_platform.h> 34#include <linux/of_platform.h>
35#include <linux/of_address.h>
35#include <linux/io.h> 36#include <linux/io.h>
36#include <linux/xilinxfb.h> 37#include <linux/xilinxfb.h>
37#include <linux/slab.h> 38#include <linux/slab.h>
39
40#ifdef CONFIG_PPC_DCR
38#include <asm/dcr.h> 41#include <asm/dcr.h>
42#endif
39 43
40#define DRIVER_NAME "xilinxfb" 44#define DRIVER_NAME "xilinxfb"
41 45
@@ -123,10 +127,10 @@ struct xilinxfb_drvdata {
123 registers */ 127 registers */
124 void __iomem *regs; /* virt. address of the control 128 void __iomem *regs; /* virt. address of the control
125 registers */ 129 registers */
126 130#ifdef CONFIG_PPC_DCR
127 dcr_host_t dcr_host; 131 dcr_host_t dcr_host;
128 unsigned int dcr_len; 132 unsigned int dcr_len;
129 133#endif
130 void *fb_virt; /* virt. address of the frame buffer */ 134 void *fb_virt; /* virt. address of the frame buffer */
131 dma_addr_t fb_phys; /* phys. address of the frame buffer */ 135 dma_addr_t fb_phys; /* phys. address of the frame buffer */
132 int fb_alloced; /* Flag, was the fb memory alloced? */ 136 int fb_alloced; /* Flag, was the fb memory alloced? */
@@ -152,9 +156,10 @@ static void xilinx_fb_out_be32(struct xilinxfb_drvdata *drvdata, u32 offset,
152{ 156{
153 if (drvdata->flags & PLB_ACCESS_FLAG) 157 if (drvdata->flags & PLB_ACCESS_FLAG)
154 out_be32(drvdata->regs + (offset << 2), val); 158 out_be32(drvdata->regs + (offset << 2), val);
159#ifdef CONFIG_PPC_DCR
155 else 160 else
156 dcr_write(drvdata->dcr_host, offset, val); 161 dcr_write(drvdata->dcr_host, offset, val);
157 162#endif
158} 163}
159 164
160static int 165static int
@@ -383,8 +388,11 @@ static int xilinxfb_release(struct device *dev)
383 if (drvdata->flags & PLB_ACCESS_FLAG) { 388 if (drvdata->flags & PLB_ACCESS_FLAG) {
384 iounmap(drvdata->regs); 389 iounmap(drvdata->regs);
385 release_mem_region(drvdata->regs_phys, 8); 390 release_mem_region(drvdata->regs_phys, 8);
386 } else 391 }
392#ifdef CONFIG_PPC_DCR
393 else
387 dcr_unmap(drvdata->dcr_host, drvdata->dcr_len); 394 dcr_unmap(drvdata->dcr_host, drvdata->dcr_len);
395#endif
388 396
389 kfree(drvdata); 397 kfree(drvdata);
390 dev_set_drvdata(dev, NULL); 398 dev_set_drvdata(dev, NULL);
@@ -397,14 +405,14 @@ static int xilinxfb_release(struct device *dev)
397 */ 405 */
398 406
399static int __devinit 407static int __devinit
400xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) 408xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
401{ 409{
402 const u32 *prop; 410 const u32 *prop;
403 u32 *p; 411 u32 *p;
404 u32 tft_access; 412 u32 tft_access;
405 struct xilinxfb_platform_data pdata; 413 struct xilinxfb_platform_data pdata;
406 struct resource res; 414 struct resource res;
407 int size, rc, start; 415 int size, rc;
408 struct xilinxfb_drvdata *drvdata; 416 struct xilinxfb_drvdata *drvdata;
409 417
410 /* Copy with the default pdata (not a ptr reference!) */ 418 /* Copy with the default pdata (not a ptr reference!) */
@@ -437,7 +445,10 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
437 dev_err(&op->dev, "invalid address\n"); 445 dev_err(&op->dev, "invalid address\n");
438 goto err; 446 goto err;
439 } 447 }
440 } else { 448 }
449#ifdef CONFIG_PPC_DCR
450 else {
451 int start;
441 res.start = 0; 452 res.start = 0;
442 start = dcr_resource_start(op->dev.of_node, 0); 453 start = dcr_resource_start(op->dev.of_node, 0);
443 drvdata->dcr_len = dcr_resource_len(op->dev.of_node, 0); 454 drvdata->dcr_len = dcr_resource_len(op->dev.of_node, 0);
@@ -447,6 +458,7 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
447 goto err; 458 goto err;
448 } 459 }
449 } 460 }
461#endif
450 462
451 prop = of_get_property(op->dev.of_node, "phys-size", &size); 463 prop = of_get_property(op->dev.of_node, "phys-size", &size);
452 if ((prop) && (size >= sizeof(u32)*2)) { 464 if ((prop) && (size >= sizeof(u32)*2)) {
@@ -477,7 +489,7 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
477 return -ENODEV; 489 return -ENODEV;
478} 490}
479 491
480static int __devexit xilinxfb_of_remove(struct of_device *op) 492static int __devexit xilinxfb_of_remove(struct platform_device *op)
481{ 493{
482 return xilinxfb_release(&op->dev); 494 return xilinxfb_release(&op->dev);
483} 495}
@@ -485,6 +497,8 @@ static int __devexit xilinxfb_of_remove(struct of_device *op)
485/* Match table for of_platform binding */ 497/* Match table for of_platform binding */
486static struct of_device_id xilinxfb_of_match[] __devinitdata = { 498static struct of_device_id xilinxfb_of_match[] __devinitdata = {
487 { .compatible = "xlnx,xps-tft-1.00.a", }, 499 { .compatible = "xlnx,xps-tft-1.00.a", },
500 { .compatible = "xlnx,xps-tft-2.00.a", },
501 { .compatible = "xlnx,xps-tft-2.01.a", },
488 { .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", }, 502 { .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", },
489 { .compatible = "xlnx,plb-dvi-cntlr-ref-1.00.c", }, 503 { .compatible = "xlnx,plb-dvi-cntlr-ref-1.00.c", },
490 {}, 504 {},