aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-30 18:30:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-30 18:30:01 -0400
commitacff987d94cbdb4049f3706bed1f1792f8ef6837 (patch)
tree36bded977aab5d80cf9aeb5467f83dd554a25d01 /drivers/video
parentce949717b559709423c1ef716a9db16d1dcadaed (diff)
parentb57287ba497b63a0d87a058631bbddfed9392e9f (diff)
Merge branch 'fbdev-next' of git://github.com/schandinat/linux-2.6
* 'fbdev-next' of git://github.com/schandinat/linux-2.6: (270 commits) video: platinumfb: Add __devexit_p at necessary place drivers/video: fsl-diu-fb: merge diu_pool into fsl_diu_data drivers/video: fsl-diu-fb: merge diu_hw into fsl_diu_data drivers/video: fsl-diu-fb: only DIU modes 0 and 1 are supported drivers/video: fsl-diu-fb: remove unused panel operating mode support drivers/video: fsl-diu-fb: use an enum for the AOI index drivers/video: fsl-diu-fb: add several new video modes drivers/video: fsl-diu-fb: remove broken screen blanking support drivers/video: fsl-diu-fb: move some definitions out of the header file drivers/video: fsl-diu-fb: fix some ioctls video: da8xx-fb: Increased resolution configuration of revised LCDC IP OMAPDSS: picodlp: add missing #include <linux/module.h> fb: fix au1100fb bitrot. mx3fb: fix NULL pointer dereference in screen blanking. video: irq: Remove IRQF_DISABLED smscufx: change edid data to u8 instead of char OMAPDSS: DISPC: zorder support for DSS overlays OMAPDSS: DISPC: VIDEO3 pipeline support OMAPDSS/OMAP_VOUT: Fix incorrect OMAP3-alpha compatibility setting video/omap: fix build dependencies ... Fix up conflicts in: - drivers/staging/xgifb/XGI_main_26.c Changes to XGIfb_pan_var() - drivers/video/omap/{lcd_apollon.c,lcd_ldp.c,lcd_overo.c} Removed (or in the case of apollon.c, merged into the generic DSS panel in drivers/video/omap2/displays/panel-generic-dpi.c)
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/68328fb.c4
-rw-r--r--drivers/video/Kconfig34
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/acornfb.c5
-rw-r--r--drivers/video/arkfb.c9
-rw-r--r--drivers/video/atmel_lcdfb.c15
-rw-r--r--drivers/video/aty/radeon_base.c10
-rw-r--r--drivers/video/au1100fb.c181
-rw-r--r--drivers/video/au1100fb.h6
-rw-r--r--drivers/video/au1200fb.c299
-rw-r--r--drivers/video/backlight/adp8860_bl.c1
-rw-r--r--drivers/video/backlight/adp8870_bl.c1
-rw-r--r--drivers/video/bf54x-lq043fb.c2
-rw-r--r--drivers/video/bfin-lq035q1-fb.c2
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c2
-rw-r--r--drivers/video/bfin_adv7393fb.c2
-rw-r--r--drivers/video/carminefb.c6
-rw-r--r--drivers/video/controlfb.c2
-rw-r--r--drivers/video/da8xx-fb.c186
-rw-r--r--drivers/video/fb-puv3.c4
-rw-r--r--drivers/video/fb_defio.c3
-rw-r--r--drivers/video/fbmem.c3
-rw-r--r--drivers/video/fbmon.c21
-rw-r--r--drivers/video/fbsysfs.c3
-rw-r--r--drivers/video/fsl-diu-fb.c992
-rw-r--r--drivers/video/g364fb.c5
-rw-r--r--drivers/video/grvga.c579
-rw-r--r--drivers/video/gxt4500.c4
-rw-r--r--drivers/video/hgafb.c4
-rw-r--r--drivers/video/imsttfb.c2
-rw-r--r--drivers/video/intelfb/intelfbhw.c6
-rw-r--r--drivers/video/mb862xx/mb862xx-i2c.c2
-rw-r--r--drivers/video/mb862xx/mb862xxfbdrv.c6
-rw-r--r--drivers/video/modedb.c444
-rw-r--r--drivers/video/msm/mddi.c2
-rw-r--r--drivers/video/msm/mdp.c6
-rw-r--r--drivers/video/mx3fb.c19
-rw-r--r--drivers/video/mxsfb.c1
-rw-r--r--drivers/video/neofb.c4
-rw-r--r--drivers/video/nuc900fb.c3
-rw-r--r--drivers/video/omap/Kconfig29
-rw-r--r--drivers/video/omap/Makefile8
-rw-r--r--drivers/video/omap/lcd_2430sdp.c203
-rw-r--r--drivers/video/omap/lcd_apollon.c136
-rw-r--r--drivers/video/omap/lcd_h4.c117
-rw-r--r--drivers/video/omap/lcd_ldp.c201
-rw-r--r--drivers/video/omap/lcd_omap3beagle.c130
-rw-r--r--drivers/video/omap/lcd_omap3evm.c193
-rw-r--r--drivers/video/omap/lcd_overo.c180
-rw-r--r--drivers/video/omap2/displays/Kconfig28
-rw-r--r--drivers/video/omap2/displays/Makefile3
-rw-r--r--drivers/video/omap2/displays/panel-dvi.c363
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c113
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c747
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c594
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.h288
-rw-r--r--drivers/video/omap2/displays/panel-taal.c125
-rw-r--r--drivers/video/omap2/dss/Kconfig2
-rw-r--r--drivers/video/omap2/dss/Makefile2
-rw-r--r--drivers/video/omap2/dss/core.c4
-rw-r--r--drivers/video/omap2/dss/dispc.c1700
-rw-r--r--drivers/video/omap2/dss/dispc.h57
-rw-r--r--drivers/video/omap2/dss/display.c31
-rw-r--r--drivers/video/omap2/dss/dpi.c28
-rw-r--r--drivers/video/omap2/dss/dsi.c929
-rw-r--r--drivers/video/omap2/dss/dss.c18
-rw-r--r--drivers/video/omap2/dss/dss.h156
-rw-r--r--drivers/video/omap2/dss/dss_features.c130
-rw-r--r--drivers/video/omap2/dss/dss_features.h17
-rw-r--r--drivers/video/omap2/dss/hdmi.c1260
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c (renamed from drivers/video/omap2/dss/hdmi_omap4_panel.c)68
-rw-r--r--drivers/video/omap2/dss/manager.c191
-rw-r--r--drivers/video/omap2/dss/overlay.c122
-rw-r--r--drivers/video/omap2/dss/rfbi.c45
-rw-r--r--drivers/video/omap2/dss/sdi.c19
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h138
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c1239
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h (renamed from drivers/video/omap2/dss/hdmi.h)400
-rw-r--r--drivers/video/omap2/dss/venc.c27
-rw-r--r--drivers/video/omap2/omapfb/Kconfig2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c134
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c6
-rw-r--r--drivers/video/platinumfb.c4
-rw-r--r--drivers/video/pm2fb.c6
-rw-r--r--drivers/video/pm3fb.c6
-rw-r--r--drivers/video/ps3fb.c2
-rw-r--r--drivers/video/pxa3xx-gcu.c4
-rw-r--r--drivers/video/pxafb.c2
-rw-r--r--drivers/video/s3c-fb.c117
-rw-r--r--drivers/video/s3c2410fb.c3
-rw-r--r--drivers/video/s3fb.c9
-rw-r--r--drivers/video/sa1100fb.c3
-rw-r--r--drivers/video/savage/savagefb_driver.c16
-rw-r--r--drivers/video/sh_mobile_hdmi.c47
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c1162
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h12
-rw-r--r--drivers/video/sh_mobile_meram.c208
-rw-r--r--drivers/video/sh_mobile_meram.h41
-rw-r--r--drivers/video/sis/sis_main.c30
-rw-r--r--drivers/video/skeletonfb.c2
-rw-r--r--drivers/video/sm501fb.c6
-rw-r--r--drivers/video/smscufx.c1994
-rw-r--r--drivers/video/tmiofb.c2
-rw-r--r--drivers/video/tridentfb.c4
-rw-r--r--drivers/video/udlfb.c187
-rw-r--r--drivers/video/valkyriefb.c2
-rw-r--r--drivers/video/vfb.c4
-rw-r--r--drivers/video/vga16fb.c2
-rw-r--r--drivers/video/via/dvi.c34
-rw-r--r--drivers/video/via/dvi.h3
-rw-r--r--drivers/video/via/global.c2
-rw-r--r--drivers/video/via/global.h2
-rw-r--r--drivers/video/via/hw.c544
-rw-r--r--drivers/video/via/hw.h285
-rw-r--r--drivers/video/via/lcd.c53
-rw-r--r--drivers/video/via/lcd.h7
-rw-r--r--drivers/video/via/share.h23
-rw-r--r--drivers/video/via/via-core.c2
-rw-r--r--drivers/video/via/via_modesetting.c104
-rw-r--r--drivers/video/via/via_modesetting.h23
-rw-r--r--drivers/video/via/viafbdev.c182
-rw-r--r--drivers/video/via/viamode.c60
-rw-r--r--drivers/video/via/viamode.h4
-rw-r--r--drivers/video/vt8500lcdfb.c6
-rw-r--r--drivers/video/vt8623fb.c9
-rw-r--r--drivers/video/xilinxfb.c1
126 files changed, 11087 insertions, 7197 deletions
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 75a39eab70c..a425d65d5ba 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -378,8 +378,8 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
378 || var->xoffset) 378 || var->xoffset)
379 return -EINVAL; 379 return -EINVAL;
380 } else { 380 } else {
381 if (var->xoffset + var->xres > info->var.xres_virtual || 381 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
382 var->yoffset + var->yres > info->var.yres_virtual) 382 var->yoffset + info->var.yres > info->var.yres_virtual)
383 return -EINVAL; 383 return -EINVAL;
384 } 384 }
385 info->var.xoffset = var->xoffset; 385 info->var.xoffset = var->xoffset;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 549b960667c..8165c5577d7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -259,6 +259,15 @@ config FB_TILEBLITTING
259comment "Frame buffer hardware drivers" 259comment "Frame buffer hardware drivers"
260 depends on FB 260 depends on FB
261 261
262config FB_GRVGA
263 tristate "Aeroflex Gaisler framebuffer support"
264 depends on FB && SPARC
265 select FB_CFB_FILLRECT
266 select FB_CFB_COPYAREA
267 select FB_CFB_IMAGEBLIT
268 ---help---
269 This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler.
270
262config FB_CIRRUS 271config FB_CIRRUS
263 tristate "Cirrus Logic support" 272 tristate "Cirrus Logic support"
264 depends on FB && (ZORRO || PCI) 273 depends on FB && (ZORRO || PCI)
@@ -1756,9 +1765,10 @@ config FB_AU1100
1756config FB_AU1200 1765config FB_AU1200
1757 bool "Au1200 LCD Driver" 1766 bool "Au1200 LCD Driver"
1758 depends on (FB = y) && MIPS && SOC_AU1200 1767 depends on (FB = y) && MIPS && SOC_AU1200
1759 select FB_CFB_FILLRECT 1768 select FB_SYS_FILLRECT
1760 select FB_CFB_COPYAREA 1769 select FB_SYS_COPYAREA
1761 select FB_CFB_IMAGEBLIT 1770 select FB_SYS_IMAGEBLIT
1771 select FB_SYS_FOPS
1762 help 1772 help
1763 This is the framebuffer driver for the AMD Au1200 SOC. It can drive 1773 This is the framebuffer driver for the AMD Au1200 SOC. It can drive
1764 various panels and CRTs by passing in kernel cmd line option 1774 various panels and CRTs by passing in kernel cmd line option
@@ -2027,7 +2037,7 @@ config FB_TMIO_ACCELL
2027 2037
2028config FB_S3C 2038config FB_S3C
2029 tristate "Samsung S3C framebuffer support" 2039 tristate "Samsung S3C framebuffer support"
2030 depends on FB && S3C_DEV_FB 2040 depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0)
2031 select FB_CFB_FILLRECT 2041 select FB_CFB_FILLRECT
2032 select FB_CFB_COPYAREA 2042 select FB_CFB_COPYAREA
2033 select FB_CFB_IMAGEBLIT 2043 select FB_CFB_IMAGEBLIT
@@ -2110,6 +2120,22 @@ config FB_SM501
2110 2120
2111 If unsure, say N. 2121 If unsure, say N.
2112 2122
2123config FB_SMSCUFX
2124 tristate "SMSC UFX6000/7000 USB Framebuffer support"
2125 depends on FB && USB
2126 select FB_MODE_HELPERS
2127 select FB_SYS_FILLRECT
2128 select FB_SYS_COPYAREA
2129 select FB_SYS_IMAGEBLIT
2130 select FB_SYS_FOPS
2131 select FB_DEFERRED_IO
2132 ---help---
2133 This is a kernel framebuffer driver for SMSC UFX USB devices.
2134 Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
2135 mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000
2136 (USB 3.0) devices.
2137 To compile as a module, choose M here: the module name is smscufx.
2138
2113config FB_UDL 2139config FB_UDL
2114 tristate "Displaylink USB Framebuffer support" 2140 tristate "Displaylink USB Framebuffer support"
2115 depends on FB && USB 2141 depends on FB && USB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 8b83129e209..9b9d8fff773 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
33obj-$(CONFIG_FB_ARC) += arcfb.o 33obj-$(CONFIG_FB_ARC) += arcfb.o
34obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o 34obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
35obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o 35obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
36obj-$(CONFIG_FB_GRVGA) += grvga.o
36obj-$(CONFIG_FB_PM2) += pm2fb.o 37obj-$(CONFIG_FB_PM2) += pm2fb.o
37obj-$(CONFIG_FB_PM3) += pm3fb.o 38obj-$(CONFIG_FB_PM3) += pm3fb.o
38 39
@@ -127,6 +128,7 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
127obj-$(CONFIG_FB_PS3) += ps3fb.o 128obj-$(CONFIG_FB_PS3) += ps3fb.o
128obj-$(CONFIG_FB_SM501) += sm501fb.o 129obj-$(CONFIG_FB_SM501) += sm501fb.o
129obj-$(CONFIG_FB_UDL) += udlfb.o 130obj-$(CONFIG_FB_UDL) += udlfb.o
131obj-$(CONFIG_FB_SMSCUFX) += smscufx.o
130obj-$(CONFIG_FB_XILINX) += xilinxfb.o 132obj-$(CONFIG_FB_XILINX) += xilinxfb.o
131obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o 133obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
132obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o 134obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 6183a57eb69..b303f171506 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -850,9 +850,10 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
850 u_int y_bottom = var->yoffset; 850 u_int y_bottom = var->yoffset;
851 851
852 if (!(var->vmode & FB_VMODE_YWRAP)) 852 if (!(var->vmode & FB_VMODE_YWRAP))
853 y_bottom += var->yres; 853 y_bottom += info->var.yres;
854 854
855 BUG_ON(y_bottom > var->yres_virtual); 855 if (y_bottom > info->var.yres_virtual)
856 return -EINVAL;
856 857
857 acornfb_update_dma(info, var); 858 acornfb_update_dma(info, var);
858 859
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
index 8686429cbdf..555dd4c64f5 100644
--- a/drivers/video/arkfb.c
+++ b/drivers/video/arkfb.c
@@ -908,13 +908,14 @@ static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info
908 unsigned int offset; 908 unsigned int offset;
909 909
910 /* Calculate the offset */ 910 /* Calculate the offset */
911 if (var->bits_per_pixel == 0) { 911 if (info->var.bits_per_pixel == 0) {
912 offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); 912 offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
913 + (var->xoffset / 2);
913 offset = offset >> 2; 914 offset = offset >> 2;
914 } else { 915 } else {
915 offset = (var->yoffset * info->fix.line_length) + 916 offset = (var->yoffset * info->fix.line_length) +
916 (var->xoffset * var->bits_per_pixel / 8); 917 (var->xoffset * info->var.bits_per_pixel / 8);
917 offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 3); 918 offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 3);
918 } 919 }
919 920
920 /* Set the offset */ 921 /* Set the offset */
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index dda920623c6..4ac48d9ee66 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -39,7 +39,8 @@
39 | FBINFO_HWACCEL_YPAN) 39 | FBINFO_HWACCEL_YPAN)
40 40
41static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, 41static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
42 struct fb_var_screeninfo *var) 42 struct fb_var_screeninfo *var,
43 struct fb_info *info)
43{ 44{
44 45
45} 46}
@@ -50,14 +51,16 @@ static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
50 | FBINFO_HWACCEL_YPAN) 51 | FBINFO_HWACCEL_YPAN)
51 52
52static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, 53static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
53 struct fb_var_screeninfo *var) 54 struct fb_var_screeninfo *var,
55 struct fb_info *info)
54{ 56{
55 u32 dma2dcfg; 57 u32 dma2dcfg;
56 u32 pixeloff; 58 u32 pixeloff;
57 59
58 pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f; 60 pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f;
59 61
60 dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8; 62 dma2dcfg = (info->var.xres_virtual - info->var.xres)
63 * info->var.bits_per_pixel / 8;
61 dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET; 64 dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
62 lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); 65 lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
63 66
@@ -249,14 +252,14 @@ static void atmel_lcdfb_update_dma(struct fb_info *info,
249 unsigned long dma_addr; 252 unsigned long dma_addr;
250 253
251 dma_addr = (fix->smem_start + var->yoffset * fix->line_length 254 dma_addr = (fix->smem_start + var->yoffset * fix->line_length
252 + var->xoffset * var->bits_per_pixel / 8); 255 + var->xoffset * info->var.bits_per_pixel / 8);
253 256
254 dma_addr &= ~3UL; 257 dma_addr &= ~3UL;
255 258
256 /* Set framebuffer DMA base address and pixel offset */ 259 /* Set framebuffer DMA base address and pixel offset */
257 lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); 260 lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
258 261
259 atmel_lcdfb_update_dma2d(sinfo, var); 262 atmel_lcdfb_update_dma2d(sinfo, var, info);
260} 263}
261 264
262static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) 265static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 32f8cf6200a..150684882ef 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -845,16 +845,16 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
845{ 845{
846 struct radeonfb_info *rinfo = info->par; 846 struct radeonfb_info *rinfo = info->par;
847 847
848 if ((var->xoffset + var->xres > var->xres_virtual) 848 if ((var->xoffset + info->var.xres > info->var.xres_virtual)
849 || (var->yoffset + var->yres > var->yres_virtual)) 849 || (var->yoffset + info->var.yres > info->var.yres_virtual))
850 return -EINVAL; 850 return -EINVAL;
851 851
852 if (rinfo->asleep) 852 if (rinfo->asleep)
853 return 0; 853 return 0;
854 854
855 radeon_fifo_wait(2); 855 radeon_fifo_wait(2);
856 OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) 856 OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length +
857 * var->bits_per_pixel / 8) & ~7); 857 var->xoffset * info->var.bits_per_pixel / 8) & ~7);
858 return 0; 858 return 0;
859} 859}
860 860
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 01a8fde67f2..649cb35de4e 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -110,12 +110,6 @@ static struct fb_var_screeninfo au1100fb_var __devinitdata = {
110 .vmode = FB_VMODE_NONINTERLACED, 110 .vmode = FB_VMODE_NONINTERLACED,
111}; 111};
112 112
113static struct au1100fb_drv_info drv_info;
114
115static int nocursor = 0;
116module_param(nocursor, int, 0644);
117MODULE_PARM_DESC(nocursor, "cursor enable/disable");
118
119/* fb_blank 113/* fb_blank
120 * Blank the screen. Depending on the mode, the screen will be 114 * Blank the screen. Depending on the mode, the screen will be
121 * activated with the backlight color, or desactivated 115 * activated with the backlight color, or desactivated
@@ -132,7 +126,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
132 /* Turn on panel */ 126 /* Turn on panel */
133 fbdev->regs->lcd_control |= LCD_CONTROL_GO; 127 fbdev->regs->lcd_control |= LCD_CONTROL_GO;
134#ifdef CONFIG_MIPS_PB1100 128#ifdef CONFIG_MIPS_PB1100
135 if (drv_info.panel_idx == 1) { 129 if (fbdev->panel_idx == 1) {
136 au_writew(au_readw(PB1100_G_CONTROL) 130 au_writew(au_readw(PB1100_G_CONTROL)
137 | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), 131 | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD),
138 PB1100_G_CONTROL); 132 PB1100_G_CONTROL);
@@ -147,7 +141,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
147 /* Turn off panel */ 141 /* Turn off panel */
148 fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; 142 fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
149#ifdef CONFIG_MIPS_PB1100 143#ifdef CONFIG_MIPS_PB1100
150 if (drv_info.panel_idx == 1) { 144 if (fbdev->panel_idx == 1) {
151 au_writew(au_readw(PB1100_G_CONTROL) 145 au_writew(au_readw(PB1100_G_CONTROL)
152 & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), 146 & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD),
153 PB1100_G_CONTROL); 147 PB1100_G_CONTROL);
@@ -428,17 +422,6 @@ int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
428 return 0; 422 return 0;
429} 423}
430 424
431/* fb_cursor
432 * Used to disable cursor drawing...
433 */
434int au1100fb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
435{
436 if (nocursor)
437 return 0;
438 else
439 return -EINVAL; /* just to force soft_cursor() call */
440}
441
442static struct fb_ops au1100fb_ops = 425static struct fb_ops au1100fb_ops =
443{ 426{
444 .owner = THIS_MODULE, 427 .owner = THIS_MODULE,
@@ -450,13 +433,53 @@ static struct fb_ops au1100fb_ops =
450 .fb_imageblit = cfb_imageblit, 433 .fb_imageblit = cfb_imageblit,
451 .fb_rotate = au1100fb_fb_rotate, 434 .fb_rotate = au1100fb_fb_rotate,
452 .fb_mmap = au1100fb_fb_mmap, 435 .fb_mmap = au1100fb_fb_mmap,
453 .fb_cursor = au1100fb_fb_cursor,
454}; 436};
455 437
456 438
457/*-------------------------------------------------------------------------*/ 439/*-------------------------------------------------------------------------*/
458 440
459/* AU1100 LCD controller device driver */ 441static int au1100fb_setup(struct au1100fb_device *fbdev)
442{
443 char *this_opt, *options;
444 int num_panels = ARRAY_SIZE(known_lcd_panels);
445
446 if (num_panels <= 0) {
447 print_err("No LCD panels supported by driver!");
448 return -ENODEV;
449 }
450
451 if (fb_get_options(DRIVER_NAME, &options))
452 return -ENODEV;
453 if (!options)
454 return -ENODEV;
455
456 while ((this_opt = strsep(&options, ",")) != NULL) {
457 /* Panel option */
458 if (!strncmp(this_opt, "panel:", 6)) {
459 int i;
460 this_opt += 6;
461 for (i = 0; i < num_panels; i++) {
462 if (!strncmp(this_opt, known_lcd_panels[i].name,
463 strlen(this_opt))) {
464 fbdev->panel = &known_lcd_panels[i];
465 fbdev->panel_idx = i;
466 break;
467 }
468 }
469 if (i >= num_panels) {
470 print_warn("Panel '%s' not supported!", this_opt);
471 return -ENODEV;
472 }
473 }
474 /* Unsupported option */
475 else
476 print_warn("Unsupported option \"%s\"", this_opt);
477 }
478
479 print_info("Panel=%s", fbdev->panel->name);
480
481 return 0;
482}
460 483
461static int __devinit au1100fb_drv_probe(struct platform_device *dev) 484static int __devinit au1100fb_drv_probe(struct platform_device *dev)
462{ 485{
@@ -465,22 +488,21 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
465 unsigned long page; 488 unsigned long page;
466 u32 sys_clksrc; 489 u32 sys_clksrc;
467 490
468 if (!dev)
469 return -EINVAL;
470
471 /* Allocate new device private */ 491 /* Allocate new device private */
472 if (!(fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) { 492 fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL);
493 if (!fbdev) {
473 print_err("fail to allocate device private record"); 494 print_err("fail to allocate device private record");
474 return -ENOMEM; 495 return -ENOMEM;
475 } 496 }
476 497
477 fbdev->panel = &known_lcd_panels[drv_info.panel_idx]; 498 if (au1100fb_setup(fbdev))
499 goto failed;
478 500
479 platform_set_drvdata(dev, (void *)fbdev); 501 platform_set_drvdata(dev, (void *)fbdev);
480 502
481 /* Allocate region for our registers and map them */ 503 /* Allocate region for our registers and map them */
482 if (!(regs_res = platform_get_resource(to_platform_device(dev), 504 regs_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
483 IORESOURCE_MEM, 0))) { 505 if (!regs_res) {
484 print_err("fail to retrieve registers resource"); 506 print_err("fail to retrieve registers resource");
485 return -EFAULT; 507 return -EFAULT;
486 } 508 }
@@ -500,13 +522,11 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
500 print_dbg("Register memory map at %p", fbdev->regs); 522 print_dbg("Register memory map at %p", fbdev->regs);
501 print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); 523 print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len);
502 524
503
504
505 /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ 525 /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */
506 fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * 526 fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
507 (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; 527 (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
508 528
509 fbdev->fb_mem = dma_alloc_coherent(dev, PAGE_ALIGN(fbdev->fb_len), 529 fbdev->fb_mem = dma_alloc_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len),
510 &fbdev->fb_phys, GFP_KERNEL); 530 &fbdev->fb_phys, GFP_KERNEL);
511 if (!fbdev->fb_mem) { 531 if (!fbdev->fb_mem) {
512 print_err("fail to allocate frambuffer (size: %dK))", 532 print_err("fail to allocate frambuffer (size: %dK))",
@@ -525,7 +545,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
525 page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len); 545 page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
526 page += PAGE_SIZE) { 546 page += PAGE_SIZE) {
527#if CONFIG_DMA_NONCOHERENT 547#if CONFIG_DMA_NONCOHERENT
528 SetPageReserved(virt_to_page(CAC_ADDR(page))); 548 SetPageReserved(virt_to_page(CAC_ADDR((void *)page)));
529#else 549#else
530 SetPageReserved(virt_to_page(page)); 550 SetPageReserved(virt_to_page(page));
531#endif 551#endif
@@ -578,7 +598,8 @@ failed:
578 release_mem_region(fbdev->regs_phys, fbdev->regs_len); 598 release_mem_region(fbdev->regs_phys, fbdev->regs_len);
579 } 599 }
580 if (fbdev->fb_mem) { 600 if (fbdev->fb_mem) {
581 dma_free_noncoherent(dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys); 601 dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem,
602 fbdev->fb_phys);
582 } 603 }
583 if (fbdev->info.cmap.len != 0) { 604 if (fbdev->info.cmap.len != 0) {
584 fb_dealloc_cmap(&fbdev->info.cmap); 605 fb_dealloc_cmap(&fbdev->info.cmap);
@@ -608,7 +629,8 @@ int au1100fb_drv_remove(struct platform_device *dev)
608 629
609 release_mem_region(fbdev->regs_phys, fbdev->regs_len); 630 release_mem_region(fbdev->regs_phys, fbdev->regs_len);
610 631
611 dma_free_coherent(dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys); 632 dma_free_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem,
633 fbdev->fb_phys);
612 634
613 fb_dealloc_cmap(&fbdev->info.cmap); 635 fb_dealloc_cmap(&fbdev->info.cmap);
614 kfree(fbdev->info.pseudo_palette); 636 kfree(fbdev->info.pseudo_palette);
@@ -675,101 +697,18 @@ static struct platform_driver au1100fb_driver = {
675 .resume = au1100fb_drv_resume, 697 .resume = au1100fb_drv_resume,
676}; 698};
677 699
678/*-------------------------------------------------------------------------*/ 700static int __init au1100fb_load(void)
679
680/* Kernel driver */
681
682int au1100fb_setup(char *options)
683{
684 char* this_opt;
685 int num_panels = ARRAY_SIZE(known_lcd_panels);
686 char* mode = NULL;
687 int panel_idx = 0;
688
689 if (num_panels <= 0) {
690 print_err("No LCD panels supported by driver!");
691 return -EFAULT;
692 }
693
694 if (options) {
695 while ((this_opt = strsep(&options,",")) != NULL) {
696 /* Panel option */
697 if (!strncmp(this_opt, "panel:", 6)) {
698 int i;
699 this_opt += 6;
700 for (i = 0; i < num_panels; i++) {
701 if (!strncmp(this_opt,
702 known_lcd_panels[i].name,
703 strlen(this_opt))) {
704 panel_idx = i;
705 break;
706 }
707 }
708 if (i >= num_panels) {
709 print_warn("Panel %s not supported!", this_opt);
710 }
711 }
712 if (!strncmp(this_opt, "nocursor", 8)) {
713 this_opt += 8;
714 nocursor = 1;
715 print_info("Cursor disabled");
716 }
717 /* Mode option (only option that start with digit) */
718 else if (isdigit(this_opt[0])) {
719 mode = kstrdup(this_opt, GFP_KERNEL);
720 if (!mode) {
721 print_err("memory allocation failed");
722 return -ENOMEM;
723 }
724 }
725 /* Unsupported option */
726 else {
727 print_warn("Unsupported option \"%s\"", this_opt);
728 }
729 }
730 }
731
732 drv_info.panel_idx = panel_idx;
733 drv_info.opt_mode = mode;
734
735 print_info("Panel=%s Mode=%s",
736 known_lcd_panels[drv_info.panel_idx].name,
737 drv_info.opt_mode ? drv_info.opt_mode : "default");
738
739 return 0;
740}
741
742int __init au1100fb_init(void)
743{ 701{
744 char* options;
745 int ret;
746
747 print_info("" DRIVER_DESC "");
748
749 memset(&drv_info, 0, sizeof(drv_info));
750
751 if (fb_get_options(DRIVER_NAME, &options))
752 return -ENODEV;
753
754 /* Setup driver with options */
755 ret = au1100fb_setup(options);
756 if (ret < 0) {
757 print_err("Fail to setup driver");
758 return ret;
759 }
760
761 return platform_driver_register(&au1100fb_driver); 702 return platform_driver_register(&au1100fb_driver);
762} 703}
763 704
764void __exit au1100fb_cleanup(void) 705static void __exit au1100fb_unload(void)
765{ 706{
766 platform_driver_unregister(&au1100fb_driver); 707 platform_driver_unregister(&au1100fb_driver);
767
768 kfree(drv_info.opt_mode);
769} 708}
770 709
771module_init(au1100fb_init); 710module_init(au1100fb_load);
772module_exit(au1100fb_cleanup); 711module_exit(au1100fb_unload);
773 712
774MODULE_DESCRIPTION(DRIVER_DESC); 713MODULE_DESCRIPTION(DRIVER_DESC);
775MODULE_LICENSE("GPL"); 714MODULE_LICENSE("GPL");
diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h
index 164fe2f231e..12d9642d546 100644
--- a/drivers/video/au1100fb.h
+++ b/drivers/video/au1100fb.h
@@ -108,6 +108,7 @@ struct au1100fb_device {
108 unsigned char* fb_mem; /* FrameBuffer memory map */ 108 unsigned char* fb_mem; /* FrameBuffer memory map */
109 size_t fb_len; 109 size_t fb_len;
110 dma_addr_t fb_phys; 110 dma_addr_t fb_phys;
111 int panel_idx;
111}; 112};
112 113
113/********************************************************************/ 114/********************************************************************/
@@ -364,11 +365,6 @@ static struct au1100fb_panel known_lcd_panels[] =
364 }, 365 },
365}; 366};
366 367
367struct au1100fb_drv_info {
368 int panel_idx;
369 char *opt_mode;
370};
371
372/********************************************************************/ 368/********************************************************************/
373 369
374/* Inline helpers */ 370/* Inline helpers */
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 5dff32ac804..72005598040 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -46,18 +46,10 @@
46#include <asm/mach-au1x00/au1000.h> 46#include <asm/mach-au1x00/au1000.h>
47#include "au1200fb.h" 47#include "au1200fb.h"
48 48
49#ifdef CONFIG_PM
50#include <asm/mach-au1x00/au1xxx_pm.h>
51#endif
52
53#ifndef CONFIG_FB_AU1200_DEVS
54#define CONFIG_FB_AU1200_DEVS 4
55#endif
56
57#define DRIVER_NAME "au1200fb" 49#define DRIVER_NAME "au1200fb"
58#define DRIVER_DESC "LCD controller driver for AU1200 processors" 50#define DRIVER_DESC "LCD controller driver for AU1200 processors"
59 51
60#define DEBUG 1 52#define DEBUG 0
61 53
62#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) 54#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
63#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) 55#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
@@ -150,7 +142,7 @@ struct au1200_lcd_iodata_t {
150 142
151/* Private, per-framebuffer management information (independent of the panel itself) */ 143/* Private, per-framebuffer management information (independent of the panel itself) */
152struct au1200fb_device { 144struct au1200fb_device {
153 struct fb_info fb_info; /* FB driver info record */ 145 struct fb_info *fb_info; /* FB driver info record */
154 146
155 int plane; 147 int plane;
156 unsigned char* fb_mem; /* FrameBuffer memory map */ 148 unsigned char* fb_mem; /* FrameBuffer memory map */
@@ -158,7 +150,6 @@ struct au1200fb_device {
158 dma_addr_t fb_phys; 150 dma_addr_t fb_phys;
159}; 151};
160 152
161static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
162/********************************************************************/ 153/********************************************************************/
163 154
164/* LCD controller restrictions */ 155/* LCD controller restrictions */
@@ -171,10 +162,18 @@ static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
171/* Default number of visible screen buffer to allocate */ 162/* Default number of visible screen buffer to allocate */
172#define AU1200FB_NBR_VIDEO_BUFFERS 1 163#define AU1200FB_NBR_VIDEO_BUFFERS 1
173 164
165/* Default maximum number of fb devices to create */
166#define MAX_DEVICE_COUNT 4
167
168/* Default window configuration entry to use (see windows[]) */
169#define DEFAULT_WINDOW_INDEX 2
170
174/********************************************************************/ 171/********************************************************************/
175 172
173static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT];
176static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; 174static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
177static int window_index = 2; /* default is zero */ 175static int device_count = MAX_DEVICE_COUNT;
176static int window_index = DEFAULT_WINDOW_INDEX; /* default is zero */
178static int panel_index = 2; /* default is zero */ 177static int panel_index = 2; /* default is zero */
179static struct window_settings *win; 178static struct window_settings *win;
180static struct panel_settings *panel; 179static struct panel_settings *panel;
@@ -205,12 +204,6 @@ struct window_settings {
205extern int board_au1200fb_panel_init (void); 204extern int board_au1200fb_panel_init (void);
206extern int board_au1200fb_panel_shutdown (void); 205extern int board_au1200fb_panel_shutdown (void);
207 206
208#ifdef CONFIG_PM
209int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
210 au1xxx_request_t request, void *data);
211au1xxx_power_dev_t *LCD_pm_dev;
212#endif
213
214/* 207/*
215 * Default window configurations 208 * Default window configurations
216 */ 209 */
@@ -652,25 +645,6 @@ static struct panel_settings known_lcd_panels[] =
652 645
653/********************************************************************/ 646/********************************************************************/
654 647
655#ifdef CONFIG_PM
656static int set_brightness(unsigned int brightness)
657{
658 unsigned int hi1, divider;
659
660 /* limit brightness pwm duty to >= 30/1600 */
661 if (brightness < 30) {
662 brightness = 30;
663 }
664 divider = (lcd->pwmdiv & 0x3FFFF) + 1;
665 hi1 = (lcd->pwmhi >> 16) + 1;
666 hi1 = (((brightness & 0xFF) + 1) * divider >> 8);
667 lcd->pwmhi &= 0xFFFF;
668 lcd->pwmhi |= (hi1 << 16);
669
670 return brightness;
671}
672#endif /* CONFIG_PM */
673
674static int winbpp (unsigned int winctrl1) 648static int winbpp (unsigned int winctrl1)
675{ 649{
676 int bits = 0; 650 int bits = 0;
@@ -712,8 +686,8 @@ static int fbinfo2index (struct fb_info *fb_info)
712{ 686{
713 int i; 687 int i;
714 688
715 for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { 689 for (i = 0; i < device_count; ++i) {
716 if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) 690 if (fb_info == _au1200fb_infos[i])
717 return i; 691 return i;
718 } 692 }
719 printk("au1200fb: ERROR: fbinfo2index failed!\n"); 693 printk("au1200fb: ERROR: fbinfo2index failed!\n");
@@ -962,7 +936,7 @@ static void au1200_setmode(struct au1200fb_device *fbdev)
962 lcd->window[plane].winctrl2 = ( 0 936 lcd->window[plane].winctrl2 = ( 0
963 | LCD_WINCTRL2_CKMODE_00 937 | LCD_WINCTRL2_CKMODE_00
964 | LCD_WINCTRL2_DBM 938 | LCD_WINCTRL2_DBM
965 | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) 939 | LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length)
966 | LCD_WINCTRL2_SCX_1 940 | LCD_WINCTRL2_SCX_1
967 | LCD_WINCTRL2_SCY_1 941 | LCD_WINCTRL2_SCY_1
968 ) ; 942 ) ;
@@ -1050,7 +1024,7 @@ static void au1200fb_update_fbinfo(struct fb_info *fbi)
1050static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, 1024static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
1051 struct fb_info *fbi) 1025 struct fb_info *fbi)
1052{ 1026{
1053 struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; 1027 struct au1200fb_device *fbdev = fbi->par;
1054 u32 pixclock; 1028 u32 pixclock;
1055 int screen_size, plane; 1029 int screen_size, plane;
1056 1030
@@ -1142,7 +1116,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
1142 */ 1116 */
1143static int au1200fb_fb_set_par(struct fb_info *fbi) 1117static int au1200fb_fb_set_par(struct fb_info *fbi)
1144{ 1118{
1145 struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; 1119 struct au1200fb_device *fbdev = fbi->par;
1146 1120
1147 au1200fb_update_fbinfo(fbi); 1121 au1200fb_update_fbinfo(fbi);
1148 au1200_setmode(fbdev); 1122 au1200_setmode(fbdev);
@@ -1246,11 +1220,7 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
1246{ 1220{
1247 unsigned int len; 1221 unsigned int len;
1248 unsigned long start=0, off; 1222 unsigned long start=0, off;
1249 struct au1200fb_device *fbdev = (struct au1200fb_device *) info; 1223 struct au1200fb_device *fbdev = info->par;
1250
1251#ifdef CONFIG_PM
1252 au1xxx_pm_access(LCD_pm_dev);
1253#endif
1254 1224
1255 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { 1225 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
1256 return -EINVAL; 1226 return -EINVAL;
@@ -1461,10 +1431,6 @@ static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
1461 int plane; 1431 int plane;
1462 int val; 1432 int val;
1463 1433
1464#ifdef CONFIG_PM
1465 au1xxx_pm_access(LCD_pm_dev);
1466#endif
1467
1468 plane = fbinfo2index(info); 1434 plane = fbinfo2index(info);
1469 print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); 1435 print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
1470 1436
@@ -1536,9 +1502,11 @@ static struct fb_ops au1200fb_fb_ops = {
1536 .fb_set_par = au1200fb_fb_set_par, 1502 .fb_set_par = au1200fb_fb_set_par,
1537 .fb_setcolreg = au1200fb_fb_setcolreg, 1503 .fb_setcolreg = au1200fb_fb_setcolreg,
1538 .fb_blank = au1200fb_fb_blank, 1504 .fb_blank = au1200fb_fb_blank,
1539 .fb_fillrect = cfb_fillrect, 1505 .fb_fillrect = sys_fillrect,
1540 .fb_copyarea = cfb_copyarea, 1506 .fb_copyarea = sys_copyarea,
1541 .fb_imageblit = cfb_imageblit, 1507 .fb_imageblit = sys_imageblit,
1508 .fb_read = fb_sys_read,
1509 .fb_write = fb_sys_write,
1542 .fb_sync = NULL, 1510 .fb_sync = NULL,
1543 .fb_ioctl = au1200fb_ioctl, 1511 .fb_ioctl = au1200fb_ioctl,
1544 .fb_mmap = au1200fb_fb_mmap, 1512 .fb_mmap = au1200fb_fb_mmap,
@@ -1561,10 +1529,9 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
1561 1529
1562static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) 1530static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
1563{ 1531{
1564 struct fb_info *fbi = &fbdev->fb_info; 1532 struct fb_info *fbi = fbdev->fb_info;
1565 int bpp; 1533 int bpp;
1566 1534
1567 memset(fbi, 0, sizeof(struct fb_info));
1568 fbi->fbops = &au1200fb_fb_ops; 1535 fbi->fbops = &au1200fb_fb_ops;
1569 1536
1570 bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); 1537 bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
@@ -1623,24 +1590,36 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
1623 1590
1624/* AU1200 LCD controller device driver */ 1591/* AU1200 LCD controller device driver */
1625 1592
1626static int au1200fb_drv_probe(struct platform_device *dev) 1593static int __devinit au1200fb_drv_probe(struct platform_device *dev)
1627{ 1594{
1628 struct au1200fb_device *fbdev; 1595 struct au1200fb_device *fbdev;
1596 struct fb_info *fbi = NULL;
1629 unsigned long page; 1597 unsigned long page;
1630 int bpp, plane, ret; 1598 int bpp, plane, ret, irq;
1631 1599
1632 if (!dev) 1600 /* shut gcc up */
1633 return -EINVAL; 1601 ret = 0;
1602 fbdev = NULL;
1603
1604 /* Kickstart the panel */
1605 au1200_setpanel(panel);
1634 1606
1635 for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { 1607 for (plane = 0; plane < device_count; ++plane) {
1636 bpp = winbpp(win->w[plane].mode_winctrl1); 1608 bpp = winbpp(win->w[plane].mode_winctrl1);
1637 if (win->w[plane].xres == 0) 1609 if (win->w[plane].xres == 0)
1638 win->w[plane].xres = panel->Xres; 1610 win->w[plane].xres = panel->Xres;
1639 if (win->w[plane].yres == 0) 1611 if (win->w[plane].yres == 0)
1640 win->w[plane].yres = panel->Yres; 1612 win->w[plane].yres = panel->Yres;
1641 1613
1642 fbdev = &_au1200fb_devices[plane]; 1614 fbi = framebuffer_alloc(sizeof(struct au1200fb_device),
1643 memset(fbdev, 0, sizeof(struct au1200fb_device)); 1615 &dev->dev);
1616 if (!fbi)
1617 goto failed;
1618
1619 _au1200fb_infos[plane] = fbi;
1620 fbdev = fbi->par;
1621 fbdev->fb_info = fbi;
1622
1644 fbdev->plane = plane; 1623 fbdev->plane = plane;
1645 1624
1646 /* Allocate the framebuffer to the maximum screen size */ 1625 /* Allocate the framebuffer to the maximum screen size */
@@ -1673,30 +1652,31 @@ static int au1200fb_drv_probe(struct platform_device *dev)
1673 goto failed; 1652 goto failed;
1674 1653
1675 /* Register new framebuffer */ 1654 /* Register new framebuffer */
1676 if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { 1655 ret = register_framebuffer(fbi);
1656 if (ret < 0) {
1677 print_err("cannot register new framebuffer"); 1657 print_err("cannot register new framebuffer");
1678 goto failed; 1658 goto failed;
1679 } 1659 }
1680 1660
1681 au1200fb_fb_set_par(&fbdev->fb_info); 1661 au1200fb_fb_set_par(fbi);
1682 1662
1683#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) 1663#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
1684 if (plane == 0) 1664 if (plane == 0)
1685 if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { 1665 if (fb_prepare_logo(fbi, FB_ROTATE_UR)) {
1686 /* Start display and show logo on boot */ 1666 /* Start display and show logo on boot */
1687 fb_set_cmap(&fbdev->fb_info.cmap, 1667 fb_set_cmap(&fbi->cmap, fbi);
1688 &fbdev->fb_info); 1668 fb_show_logo(fbi, FB_ROTATE_UR);
1689
1690 fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR);
1691 } 1669 }
1692#endif 1670#endif
1693 } 1671 }
1694 1672
1695 /* Now hook interrupt too */ 1673 /* Now hook interrupt too */
1696 if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, 1674 irq = platform_get_irq(dev, 0);
1697 IRQF_DISABLED | IRQF_SHARED, "lcd", (void *)dev)) < 0) { 1675 ret = request_irq(irq, au1200fb_handle_irq,
1676 IRQF_SHARED, "lcd", (void *)dev);
1677 if (ret) {
1698 print_err("fail to request interrupt line %d (err: %d)", 1678 print_err("fail to request interrupt line %d (err: %d)",
1699 AU1200_LCD_INT, ret); 1679 irq, ret);
1700 goto failed; 1680 goto failed;
1701 } 1681 }
1702 1682
@@ -1705,84 +1685,108 @@ static int au1200fb_drv_probe(struct platform_device *dev)
1705failed: 1685failed:
1706 /* NOTE: This only does the current plane/window that failed; others are still active */ 1686 /* NOTE: This only does the current plane/window that failed; others are still active */
1707 if (fbdev->fb_mem) 1687 if (fbdev->fb_mem)
1708 dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), 1688 dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len),
1709 fbdev->fb_mem, fbdev->fb_phys); 1689 fbdev->fb_mem, fbdev->fb_phys);
1710 if (fbdev->fb_info.cmap.len != 0) 1690 if (fbi) {
1711 fb_dealloc_cmap(&fbdev->fb_info.cmap); 1691 if (fbi->cmap.len != 0)
1712 if (fbdev->fb_info.pseudo_palette) 1692 fb_dealloc_cmap(&fbi->cmap);
1713 kfree(fbdev->fb_info.pseudo_palette); 1693 kfree(fbi->pseudo_palette);
1694 }
1714 if (plane == 0) 1695 if (plane == 0)
1715 free_irq(AU1200_LCD_INT, (void*)dev); 1696 free_irq(AU1200_LCD_INT, (void*)dev);
1716 return ret; 1697 return ret;
1717} 1698}
1718 1699
1719static int au1200fb_drv_remove(struct platform_device *dev) 1700static int __devexit au1200fb_drv_remove(struct platform_device *dev)
1720{ 1701{
1721 struct au1200fb_device *fbdev; 1702 struct au1200fb_device *fbdev;
1703 struct fb_info *fbi;
1722 int plane; 1704 int plane;
1723 1705
1724 if (!dev)
1725 return -ENODEV;
1726
1727 /* Turn off the panel */ 1706 /* Turn off the panel */
1728 au1200_setpanel(NULL); 1707 au1200_setpanel(NULL);
1729 1708
1730 for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) 1709 for (plane = 0; plane < device_count; ++plane) {
1731 { 1710 fbi = _au1200fb_infos[plane];
1732 fbdev = &_au1200fb_devices[plane]; 1711 fbdev = fbi->par;
1733 1712
1734 /* Clean up all probe data */ 1713 /* Clean up all probe data */
1735 unregister_framebuffer(&fbdev->fb_info); 1714 unregister_framebuffer(fbi);
1736 if (fbdev->fb_mem) 1715 if (fbdev->fb_mem)
1737 dma_free_noncoherent(&dev->dev, 1716 dma_free_noncoherent(&dev->dev,
1738 PAGE_ALIGN(fbdev->fb_len), 1717 PAGE_ALIGN(fbdev->fb_len),
1739 fbdev->fb_mem, fbdev->fb_phys); 1718 fbdev->fb_mem, fbdev->fb_phys);
1740 if (fbdev->fb_info.cmap.len != 0) 1719 if (fbi->cmap.len != 0)
1741 fb_dealloc_cmap(&fbdev->fb_info.cmap); 1720 fb_dealloc_cmap(&fbi->cmap);
1742 if (fbdev->fb_info.pseudo_palette) 1721 kfree(fbi->pseudo_palette);
1743 kfree(fbdev->fb_info.pseudo_palette); 1722
1723 framebuffer_release(fbi);
1724 _au1200fb_infos[plane] = NULL;
1744 } 1725 }
1745 1726
1746 free_irq(AU1200_LCD_INT, (void *)dev); 1727 free_irq(platform_get_irq(dev, 0), (void *)dev);
1747 1728
1748 return 0; 1729 return 0;
1749} 1730}
1750 1731
1751#ifdef CONFIG_PM 1732#ifdef CONFIG_PM
1752static int au1200fb_drv_suspend(struct platform_device *dev, u32 state) 1733static int au1200fb_drv_suspend(struct device *dev)
1753{ 1734{
1754 /* TODO */ 1735 au1200_setpanel(NULL);
1736
1737 lcd->outmask = 0;
1738 au_sync();
1739
1755 return 0; 1740 return 0;
1756} 1741}
1757 1742
1758static int au1200fb_drv_resume(struct platform_device *dev) 1743static int au1200fb_drv_resume(struct device *dev)
1759{ 1744{
1760 /* TODO */ 1745 struct fb_info *fbi;
1746 int i;
1747
1748 /* Kickstart the panel */
1749 au1200_setpanel(panel);
1750
1751 for (i = 0; i < device_count; i++) {
1752 fbi = _au1200fb_infos[i];
1753 au1200fb_fb_set_par(fbi);
1754 }
1755
1761 return 0; 1756 return 0;
1762} 1757}
1758
1759static const struct dev_pm_ops au1200fb_pmops = {
1760 .suspend = au1200fb_drv_suspend,
1761 .resume = au1200fb_drv_resume,
1762 .freeze = au1200fb_drv_suspend,
1763 .thaw = au1200fb_drv_resume,
1764};
1765
1766#define AU1200FB_PMOPS (&au1200fb_pmops)
1767
1768#else
1769#define AU1200FB_PMOPS NULL
1763#endif /* CONFIG_PM */ 1770#endif /* CONFIG_PM */
1764 1771
1765static struct platform_driver au1200fb_driver = { 1772static struct platform_driver au1200fb_driver = {
1766 .driver = { 1773 .driver = {
1767 .name = "au1200-lcd", 1774 .name = "au1200-lcd",
1768 .owner = THIS_MODULE, 1775 .owner = THIS_MODULE,
1776 .pm = AU1200FB_PMOPS,
1769 }, 1777 },
1770 .probe = au1200fb_drv_probe, 1778 .probe = au1200fb_drv_probe,
1771 .remove = au1200fb_drv_remove, 1779 .remove = __devexit_p(au1200fb_drv_remove),
1772#ifdef CONFIG_PM
1773 .suspend = au1200fb_drv_suspend,
1774 .resume = au1200fb_drv_resume,
1775#endif
1776}; 1780};
1777 1781
1778/*-------------------------------------------------------------------------*/ 1782/*-------------------------------------------------------------------------*/
1779 1783
1780/* Kernel driver */ 1784/* Kernel driver */
1781 1785
1782static void au1200fb_setup(void) 1786static int au1200fb_setup(void)
1783{ 1787{
1784 char* options = NULL; 1788 char *options = NULL;
1785 char* this_opt; 1789 char *this_opt, *endptr;
1786 int num_panels = ARRAY_SIZE(known_lcd_panels); 1790 int num_panels = ARRAY_SIZE(known_lcd_panels);
1787 int panel_idx = -1; 1791 int panel_idx = -1;
1788 1792
@@ -1827,70 +1831,42 @@ static void au1200fb_setup(void)
1827 nohwcursor = 1; 1831 nohwcursor = 1;
1828 } 1832 }
1829 1833
1830 /* Unsupported option */ 1834 else if (strncmp(this_opt, "devices:", 8) == 0) {
1831 else { 1835 this_opt += 8;
1832 print_warn("Unsupported option \"%s\"", this_opt); 1836 device_count = simple_strtol(this_opt,
1837 &endptr, 0);
1838 if ((device_count < 0) ||
1839 (device_count > MAX_DEVICE_COUNT))
1840 device_count = MAX_DEVICE_COUNT;
1833 } 1841 }
1834 }
1835 }
1836}
1837 1842
1838#ifdef CONFIG_PM 1843 else if (strncmp(this_opt, "wincfg:", 7) == 0) {
1839static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, 1844 this_opt += 7;
1840 au1xxx_request_t request, void *data) { 1845 window_index = simple_strtol(this_opt,
1841 int retval = -1; 1846 &endptr, 0);
1842 unsigned int d = 0; 1847 if ((window_index < 0) ||
1843 unsigned int brightness = 0; 1848 (window_index >= ARRAY_SIZE(windows)))
1844 1849 window_index = DEFAULT_WINDOW_INDEX;
1845 if (request == AU1XXX_PM_SLEEP) {
1846 board_au1200fb_panel_shutdown();
1847 }
1848 else if (request == AU1XXX_PM_WAKEUP) {
1849 if(dev->prev_state == SLEEP_STATE)
1850 {
1851 int plane;
1852 au1200_setpanel(panel);
1853 for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
1854 struct au1200fb_device *fbdev;
1855 fbdev = &_au1200fb_devices[plane];
1856 au1200fb_fb_set_par(&fbdev->fb_info);
1857 } 1850 }
1858 }
1859 1851
1860 d = *((unsigned int*)data); 1852 else if (strncmp(this_opt, "off", 3) == 0)
1861 if(d <=10) brightness = 26; 1853 return 1;
1862 else if(d<=20) brightness = 51; 1854 /* Unsupported option */
1863 else if(d<=30) brightness = 77; 1855 else {
1864 else if(d<=40) brightness = 102; 1856 print_warn("Unsupported option \"%s\"", this_opt);
1865 else if(d<=50) brightness = 128; 1857 }
1866 else if(d<=60) brightness = 153;
1867 else if(d<=70) brightness = 179;
1868 else if(d<=80) brightness = 204;
1869 else if(d<=90) brightness = 230;
1870 else brightness = 255;
1871 set_brightness(brightness);
1872 } else if (request == AU1XXX_PM_GETSTATUS) {
1873 return dev->cur_state;
1874 } else if (request == AU1XXX_PM_ACCESS) {
1875 if (dev->cur_state != SLEEP_STATE)
1876 return retval;
1877 else {
1878 au1200_setpanel(panel);
1879 } 1858 }
1880 } else if (request == AU1XXX_PM_IDLE) {
1881 } else if (request == AU1XXX_PM_CLEANUP) {
1882 } 1859 }
1883 1860 return 0;
1884 return retval;
1885} 1861}
1886#endif
1887 1862
1888static int __init au1200fb_init(void) 1863static int __init au1200fb_init(void)
1889{ 1864{
1890 print_info("" DRIVER_DESC ""); 1865 print_info("" DRIVER_DESC "");
1891 1866
1892 /* Setup driver with options */ 1867 /* Setup driver with options */
1893 au1200fb_setup(); 1868 if (au1200fb_setup())
1869 return -ENODEV;
1894 1870
1895 /* Point to the panel selected */ 1871 /* Point to the panel selected */
1896 panel = &known_lcd_panels[panel_index]; 1872 panel = &known_lcd_panels[panel_index];
@@ -1899,17 +1875,6 @@ static int __init au1200fb_init(void)
1899 printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); 1875 printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
1900 printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); 1876 printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
1901 1877
1902 /* Kickstart the panel, the framebuffers/windows come soon enough */
1903 au1200_setpanel(panel);
1904
1905 #ifdef CONFIG_PM
1906 LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL);
1907 if ( LCD_pm_dev == NULL)
1908 printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n");
1909 else
1910 printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n");
1911 #endif
1912
1913 return platform_driver_register(&au1200fb_driver); 1878 return platform_driver_register(&au1200fb_driver);
1914} 1879}
1915 1880
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 183b6f63985..66bc74d9ce2 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -7,7 +7,6 @@
7 */ 7 */
8 8
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/version.h>
11#include <linux/init.h> 10#include <linux/init.h>
12#include <linux/errno.h> 11#include <linux/errno.h>
13#include <linux/pm.h> 12#include <linux/pm.h>
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index d06886a2bfb..98e0304deea 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -7,7 +7,6 @@
7 */ 7 */
8 8
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/version.h>
11#include <linux/init.h> 10#include <linux/init.h>
12#include <linux/errno.h> 11#include <linux/errno.h>
13#include <linux/pm.h> 12#include <linux/pm.h>
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index 2464b910b59..56720fb476b 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -633,7 +633,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
633 goto out7; 633 goto out7;
634 } 634 }
635 635
636 if (request_irq(info->irq, bfin_bf54x_irq_error, IRQF_DISABLED, 636 if (request_irq(info->irq, bfin_bf54x_irq_error, 0,
637 "PPI ERROR", info) < 0) { 637 "PPI ERROR", info) < 0) {
638 printk(KERN_ERR DRIVER_NAME 638 printk(KERN_ERR DRIVER_NAME
639 ": unable to request PPI ERROR IRQ\n"); 639 ": unable to request PPI ERROR IRQ\n");
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
index 23b6c4b62c7..c633068372c 100644
--- a/drivers/video/bfin-lq035q1-fb.c
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -695,7 +695,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
695 goto out7; 695 goto out7;
696 } 696 }
697 697
698 ret = request_irq(info->irq, bfin_lq035q1_irq_error, IRQF_DISABLED, 698 ret = request_irq(info->irq, bfin_lq035q1_irq_error, 0,
699 DRIVER_NAME" PPI ERROR", info); 699 DRIVER_NAME" PPI ERROR", info);
700 if (ret < 0) { 700 if (ret < 0) {
701 dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n"); 701 dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n");
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index d8de29f0dd8..d5e12675961 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -529,7 +529,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
529 goto out7; 529 goto out7;
530 } 530 }
531 531
532 ret = request_irq(info->irq, bfin_t350mcqb_irq_error, IRQF_DISABLED, 532 ret = request_irq(info->irq, bfin_t350mcqb_irq_error, 0,
533 "PPI ERROR", info); 533 "PPI ERROR", info);
534 if (ret < 0) { 534 if (ret < 0) {
535 printk(KERN_ERR DRIVER_NAME 535 printk(KERN_ERR DRIVER_NAME
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
index 8486f541156..811dd7f6aa4 100644
--- a/drivers/video/bfin_adv7393fb.c
+++ b/drivers/video/bfin_adv7393fb.c
@@ -481,7 +481,7 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
481 goto out_4; 481 goto out_4;
482 } 482 }
483 483
484 if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, IRQF_DISABLED, 484 if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0,
485 "PPI ERROR", fbdev) < 0) { 485 "PPI ERROR", fbdev) < 0) {
486 dev_err(&client->dev, "unable to request PPI ERROR IRQ\n"); 486 dev_err(&client->dev, "unable to request PPI ERROR IRQ\n");
487 ret = -EFAULT; 487 ret = -EFAULT;
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
index caaa27d4a46..cb09aa1fa13 100644
--- a/drivers/video/carminefb.c
+++ b/drivers/video/carminefb.c
@@ -32,11 +32,11 @@
32#define CARMINEFB_DEFAULT_VIDEO_MODE 1 32#define CARMINEFB_DEFAULT_VIDEO_MODE 1
33 33
34static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; 34static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
35module_param(fb_mode, uint, 444); 35module_param(fb_mode, uint, 0444);
36MODULE_PARM_DESC(fb_mode, "Initial video mode as integer."); 36MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
37 37
38static char *fb_mode_str; 38static char *fb_mode_str;
39module_param(fb_mode_str, charp, 444); 39module_param(fb_mode_str, charp, 0444);
40MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); 40MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
41 41
42/* 42/*
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
46 * 0b010 Display 1 46 * 0b010 Display 1
47 */ 47 */
48static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1; 48static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
49module_param(fb_displays, int, 444); 49module_param(fb_displays, int, 0444);
50MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used"); 50MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
51 51
52struct carmine_hw { 52struct carmine_hw {
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 9075bea5587..7b2c40abae1 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -550,7 +550,7 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
550 550
551 551
552/* 552/*
553 * Parse user speficied options (`video=controlfb:') 553 * Parse user specified options (`video=controlfb:')
554 */ 554 */
555static void __init control_setup(char *options) 555static void __init control_setup(char *options)
556{ 556{
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index fcdac872522..55f91d9ab00 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -35,6 +35,9 @@
35 35
36#define DRIVER_NAME "da8xx_lcdc" 36#define DRIVER_NAME "da8xx_lcdc"
37 37
38#define LCD_VERSION_1 1
39#define LCD_VERSION_2 2
40
38/* LCD Status Register */ 41/* LCD Status Register */
39#define LCD_END_OF_FRAME1 BIT(9) 42#define LCD_END_OF_FRAME1 BIT(9)
40#define LCD_END_OF_FRAME0 BIT(8) 43#define LCD_END_OF_FRAME0 BIT(8)
@@ -49,7 +52,9 @@
49#define LCD_DMA_BURST_4 0x2 52#define LCD_DMA_BURST_4 0x2
50#define LCD_DMA_BURST_8 0x3 53#define LCD_DMA_BURST_8 0x3
51#define LCD_DMA_BURST_16 0x4 54#define LCD_DMA_BURST_16 0x4
52#define LCD_END_OF_FRAME_INT_ENA BIT(2) 55#define LCD_V1_END_OF_FRAME_INT_ENA BIT(2)
56#define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8)
57#define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9)
53#define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) 58#define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0)
54 59
55/* LCD Control Register */ 60/* LCD Control Register */
@@ -65,12 +70,18 @@
65#define LCD_MONO_8BIT_MODE BIT(9) 70#define LCD_MONO_8BIT_MODE BIT(9)
66#define LCD_RASTER_ORDER BIT(8) 71#define LCD_RASTER_ORDER BIT(8)
67#define LCD_TFT_MODE BIT(7) 72#define LCD_TFT_MODE BIT(7)
68#define LCD_UNDERFLOW_INT_ENA BIT(6) 73#define LCD_V1_UNDERFLOW_INT_ENA BIT(6)
69#define LCD_PL_ENABLE BIT(4) 74#define LCD_V2_UNDERFLOW_INT_ENA BIT(5)
75#define LCD_V1_PL_INT_ENA BIT(4)
76#define LCD_V2_PL_INT_ENA BIT(6)
70#define LCD_MONOCHROME_MODE BIT(1) 77#define LCD_MONOCHROME_MODE BIT(1)
71#define LCD_RASTER_ENABLE BIT(0) 78#define LCD_RASTER_ENABLE BIT(0)
72#define LCD_TFT_ALT_ENABLE BIT(23) 79#define LCD_TFT_ALT_ENABLE BIT(23)
73#define LCD_STN_565_ENABLE BIT(24) 80#define LCD_STN_565_ENABLE BIT(24)
81#define LCD_V2_DMA_CLK_EN BIT(2)
82#define LCD_V2_LIDD_CLK_EN BIT(1)
83#define LCD_V2_CORE_CLK_EN BIT(0)
84#define LCD_V2_LPP_B10 26
74 85
75/* LCD Raster Timing 2 Register */ 86/* LCD Raster Timing 2 Register */
76#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) 87#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
@@ -82,6 +93,7 @@
82#define LCD_INVERT_FRAME_CLOCK BIT(20) 93#define LCD_INVERT_FRAME_CLOCK BIT(20)
83 94
84/* LCD Block */ 95/* LCD Block */
96#define LCD_PID_REG 0x0
85#define LCD_CTRL_REG 0x4 97#define LCD_CTRL_REG 0x4
86#define LCD_STAT_REG 0x8 98#define LCD_STAT_REG 0x8
87#define LCD_RASTER_CTRL_REG 0x28 99#define LCD_RASTER_CTRL_REG 0x28
@@ -94,6 +106,17 @@
94#define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C 106#define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C
95#define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 107#define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50
96 108
109/* Interrupt Registers available only in Version 2 */
110#define LCD_RAW_STAT_REG 0x58
111#define LCD_MASKED_STAT_REG 0x5c
112#define LCD_INT_ENABLE_SET_REG 0x60
113#define LCD_INT_ENABLE_CLR_REG 0x64
114#define LCD_END_OF_INT_IND_REG 0x68
115
116/* Clock registers available only on Version 2 */
117#define LCD_CLK_ENABLE_REG 0x6c
118#define LCD_CLK_RESET_REG 0x70
119
97#define LCD_NUM_BUFFERS 2 120#define LCD_NUM_BUFFERS 2
98 121
99#define WSI_TIMEOUT 50 122#define WSI_TIMEOUT 50
@@ -105,6 +128,8 @@
105 128
106static resource_size_t da8xx_fb_reg_base; 129static resource_size_t da8xx_fb_reg_base;
107static struct resource *lcdc_regs; 130static struct resource *lcdc_regs;
131static unsigned int lcd_revision;
132static irq_handler_t lcdc_irq_handler;
108 133
109static inline unsigned int lcdc_read(unsigned int addr) 134static inline unsigned int lcdc_read(unsigned int addr)
110{ 135{
@@ -240,6 +265,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
240 u32 end; 265 u32 end;
241 u32 reg_ras; 266 u32 reg_ras;
242 u32 reg_dma; 267 u32 reg_dma;
268 u32 reg_int;
243 269
244 /* init reg to clear PLM (loading mode) fields */ 270 /* init reg to clear PLM (loading mode) fields */
245 reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); 271 reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
@@ -252,7 +278,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
252 end = par->dma_end; 278 end = par->dma_end;
253 279
254 reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); 280 reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY);
255 reg_dma |= LCD_END_OF_FRAME_INT_ENA; 281 if (lcd_revision == LCD_VERSION_1) {
282 reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA;
283 } else {
284 reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
285 LCD_V2_END_OF_FRAME0_INT_ENA |
286 LCD_V2_END_OF_FRAME1_INT_ENA;
287 lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
288 }
256 reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; 289 reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
257 290
258 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); 291 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
@@ -264,7 +297,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
264 end = start + par->palette_sz - 1; 297 end = start + par->palette_sz - 1;
265 298
266 reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); 299 reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
267 reg_ras |= LCD_PL_ENABLE; 300
301 if (lcd_revision == LCD_VERSION_1) {
302 reg_ras |= LCD_V1_PL_INT_ENA;
303 } else {
304 reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
305 LCD_V2_PL_INT_ENA;
306 lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
307 }
268 308
269 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); 309 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
270 lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); 310 lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
@@ -348,6 +388,7 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
348static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) 388static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
349{ 389{
350 u32 reg; 390 u32 reg;
391 u32 reg_int;
351 392
352 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | 393 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
353 LCD_MONO_8BIT_MODE | 394 LCD_MONO_8BIT_MODE |
@@ -375,7 +416,13 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
375 } 416 }
376 417
377 /* enable additional interrupts here */ 418 /* enable additional interrupts here */
378 reg |= LCD_UNDERFLOW_INT_ENA; 419 if (lcd_revision == LCD_VERSION_1) {
420 reg |= LCD_V1_UNDERFLOW_INT_ENA;
421 } else {
422 reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
423 LCD_V2_UNDERFLOW_INT_ENA;
424 lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
425 }
379 426
380 lcdc_write(reg, LCD_RASTER_CTRL_REG); 427 lcdc_write(reg, LCD_RASTER_CTRL_REG);
381 428
@@ -413,18 +460,43 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
413 460
414 /* Set the Panel Width */ 461 /* Set the Panel Width */
415 /* Pixels per line = (PPL + 1)*16 */ 462 /* Pixels per line = (PPL + 1)*16 */
416 /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ 463 if (lcd_revision == LCD_VERSION_1) {
417 width &= 0x3f0; 464 /*
465 * 0x3F in bits 4..9 gives max horizontal resolution = 1024
466 * pixels.
467 */
468 width &= 0x3f0;
469 } else {
470 /*
471 * 0x7F in bits 4..10 gives max horizontal resolution = 2048
472 * pixels.
473 */
474 width &= 0x7f0;
475 }
476
418 reg = lcdc_read(LCD_RASTER_TIMING_0_REG); 477 reg = lcdc_read(LCD_RASTER_TIMING_0_REG);
419 reg &= 0xfffffc00; 478 reg &= 0xfffffc00;
420 reg |= ((width >> 4) - 1) << 4; 479 if (lcd_revision == LCD_VERSION_1) {
480 reg |= ((width >> 4) - 1) << 4;
481 } else {
482 width = (width >> 4) - 1;
483 reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3);
484 }
421 lcdc_write(reg, LCD_RASTER_TIMING_0_REG); 485 lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
422 486
423 /* Set the Panel Height */ 487 /* Set the Panel Height */
488 /* Set bits 9:0 of Lines Per Pixel */
424 reg = lcdc_read(LCD_RASTER_TIMING_1_REG); 489 reg = lcdc_read(LCD_RASTER_TIMING_1_REG);
425 reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); 490 reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);
426 lcdc_write(reg, LCD_RASTER_TIMING_1_REG); 491 lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
427 492
493 /* Set bit 10 of Lines Per Pixel */
494 if (lcd_revision == LCD_VERSION_2) {
495 reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
496 reg |= ((height - 1) & 0x400) << 16;
497 lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
498 }
499
428 /* Set the Raster Order of the Frame Buffer */ 500 /* Set the Raster Order of the Frame Buffer */
429 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); 501 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
430 if (raster_order) 502 if (raster_order)
@@ -511,6 +583,9 @@ static void lcd_reset(struct da8xx_fb_par *par)
511 /* DMA has to be disabled */ 583 /* DMA has to be disabled */
512 lcdc_write(0, LCD_DMA_CTRL_REG); 584 lcdc_write(0, LCD_DMA_CTRL_REG);
513 lcdc_write(0, LCD_RASTER_CTRL_REG); 585 lcdc_write(0, LCD_RASTER_CTRL_REG);
586
587 if (lcd_revision == LCD_VERSION_2)
588 lcdc_write(0, LCD_INT_ENABLE_SET_REG);
514} 589}
515 590
516static void lcd_calc_clk_divider(struct da8xx_fb_par *par) 591static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
@@ -523,6 +598,11 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
523 /* Configure the LCD clock divisor. */ 598 /* Configure the LCD clock divisor. */
524 lcdc_write(LCD_CLK_DIVISOR(div) | 599 lcdc_write(LCD_CLK_DIVISOR(div) |
525 (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); 600 (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
601
602 if (lcd_revision == LCD_VERSION_2)
603 lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
604 LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
605
526} 606}
527 607
528static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, 608static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
@@ -583,7 +663,63 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
583 return 0; 663 return 0;
584} 664}
585 665
586static irqreturn_t lcdc_irq_handler(int irq, void *arg) 666/* IRQ handler for version 2 of LCDC */
667static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
668{
669 struct da8xx_fb_par *par = arg;
670 u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
671 u32 reg_int;
672
673 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
674 lcd_disable_raster();
675 lcdc_write(stat, LCD_MASKED_STAT_REG);
676 lcd_enable_raster();
677 } else if (stat & LCD_PL_LOAD_DONE) {
678 /*
679 * Must disable raster before changing state of any control bit.
680 * And also must be disabled before clearing the PL loading
681 * interrupt via the following write to the status register. If
682 * this is done after then one gets multiple PL done interrupts.
683 */
684 lcd_disable_raster();
685
686 lcdc_write(stat, LCD_MASKED_STAT_REG);
687
688 /* Disable PL completion inerrupt */
689 reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) |
690 (LCD_V2_PL_INT_ENA);
691 lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG);
692
693 /* Setup and start data loading mode */
694 lcd_blit(LOAD_DATA, par);
695 } else {
696 lcdc_write(stat, LCD_MASKED_STAT_REG);
697
698 if (stat & LCD_END_OF_FRAME0) {
699 lcdc_write(par->dma_start,
700 LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
701 lcdc_write(par->dma_end,
702 LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
703 par->vsync_flag = 1;
704 wake_up_interruptible(&par->vsync_wait);
705 }
706
707 if (stat & LCD_END_OF_FRAME1) {
708 lcdc_write(par->dma_start,
709 LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
710 lcdc_write(par->dma_end,
711 LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
712 par->vsync_flag = 1;
713 wake_up_interruptible(&par->vsync_wait);
714 }
715 }
716
717 lcdc_write(0, LCD_END_OF_INT_IND_REG);
718 return IRQ_HANDLED;
719}
720
721/* IRQ handler for version 1 LCDC */
722static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
587{ 723{
588 struct da8xx_fb_par *par = arg; 724 struct da8xx_fb_par *par = arg;
589 u32 stat = lcdc_read(LCD_STAT_REG); 725 u32 stat = lcdc_read(LCD_STAT_REG);
@@ -606,7 +742,7 @@ static irqreturn_t lcdc_irq_handler(int irq, void *arg)
606 742
607 /* Disable PL completion inerrupt */ 743 /* Disable PL completion inerrupt */
608 reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); 744 reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
609 reg_ras &= ~LCD_PL_ENABLE; 745 reg_ras &= ~LCD_V1_PL_INT_ENA;
610 lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); 746 lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
611 747
612 /* Setup and start data loading mode */ 748 /* Setup and start data loading mode */
@@ -877,8 +1013,8 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
877 1013
878 start = fix->smem_start + 1014 start = fix->smem_start +
879 new_var.yoffset * fix->line_length + 1015 new_var.yoffset * fix->line_length +
880 new_var.xoffset * var->bits_per_pixel / 8; 1016 new_var.xoffset * fbi->var.bits_per_pixel / 8;
881 end = start + var->yres * fix->line_length - 1; 1017 end = start + fbi->var.yres * fix->line_length - 1;
882 par->dma_start = start; 1018 par->dma_start = start;
883 par->dma_end = end; 1019 par->dma_end = end;
884 } 1020 }
@@ -945,6 +1081,22 @@ static int __devinit fb_probe(struct platform_device *device)
945 if (ret) 1081 if (ret)
946 goto err_clk_put; 1082 goto err_clk_put;
947 1083
1084 /* Determine LCD IP Version */
1085 switch (lcdc_read(LCD_PID_REG)) {
1086 case 0x4C100102:
1087 lcd_revision = LCD_VERSION_1;
1088 break;
1089 case 0x4F200800:
1090 lcd_revision = LCD_VERSION_2;
1091 break;
1092 default:
1093 dev_warn(&device->dev, "Unknown PID Reg value 0x%x, "
1094 "defaulting to LCD revision 1\n",
1095 lcdc_read(LCD_PID_REG));
1096 lcd_revision = LCD_VERSION_1;
1097 break;
1098 }
1099
948 for (i = 0, lcdc_info = known_lcd_panels; 1100 for (i = 0, lcdc_info = known_lcd_panels;
949 i < ARRAY_SIZE(known_lcd_panels); 1101 i < ARRAY_SIZE(known_lcd_panels);
950 i++, lcdc_info++) { 1102 i++, lcdc_info++) {
@@ -1085,7 +1237,13 @@ static int __devinit fb_probe(struct platform_device *device)
1085 } 1237 }
1086#endif 1238#endif
1087 1239
1088 ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); 1240 if (lcd_revision == LCD_VERSION_1)
1241 lcdc_irq_handler = lcdc_irq_handler_rev01;
1242 else
1243 lcdc_irq_handler = lcdc_irq_handler_rev02;
1244
1245 ret = request_irq(par->irq, lcdc_irq_handler, 0,
1246 DRIVER_NAME, par);
1089 if (ret) 1247 if (ret)
1090 goto irq_freq; 1248 goto irq_freq;
1091 return 0; 1249 return 0;
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
index 27f2c57e06e..60a787fa32c 100644
--- a/drivers/video/fb-puv3.c
+++ b/drivers/video/fb-puv3.c
@@ -624,8 +624,8 @@ static int unifb_pan_display(struct fb_var_screeninfo *var,
624 || var->xoffset) 624 || var->xoffset)
625 return -EINVAL; 625 return -EINVAL;
626 } else { 626 } else {
627 if (var->xoffset + var->xres > info->var.xres_virtual || 627 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
628 var->yoffset + var->yres > info->var.yres_virtual) 628 var->yoffset + info->var.yres > info->var.yres_virtual)
629 return -EINVAL; 629 return -EINVAL;
630 } 630 }
631 info->var.xoffset = var->xoffset; 631 info->var.xoffset = var->xoffset;
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 32814e8800e..c27e153d888 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -223,8 +223,7 @@ void fb_deferred_io_cleanup(struct fb_info *info)
223 int i; 223 int i;
224 224
225 BUG_ON(!fbdefio); 225 BUG_ON(!fbdefio);
226 cancel_delayed_work(&info->deferred_work); 226 cancel_delayed_work_sync(&info->deferred_work);
227 flush_scheduled_work();
228 227
229 /* clear out the mapping that we setup */ 228 /* clear out the mapping that we setup */
230 for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { 229 for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 5aac00eb183..ad936295d8f 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state)
1738{ 1738{
1739 struct fb_event event; 1739 struct fb_event event;
1740 1740
1741 if (!lock_fb_info(info))
1742 return;
1743 event.info = info; 1741 event.info = info;
1744 if (state) { 1742 if (state) {
1745 fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); 1743 fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
@@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state)
1748 info->state = FBINFO_STATE_RUNNING; 1746 info->state = FBINFO_STATE_RUNNING;
1749 fb_notifier_call_chain(FB_EVENT_RESUME, &event); 1747 fb_notifier_call_chain(FB_EVENT_RESUME, &event);
1750 } 1748 }
1751 unlock_fb_info(info);
1752} 1749}
1753 1750
1754/** 1751/**
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 4f57485f8c5..cef65574db6 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -493,7 +493,8 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
493 return num; 493 return num;
494} 494}
495 495
496static int get_std_timing(unsigned char *block, struct fb_videomode *mode) 496static int get_std_timing(unsigned char *block, struct fb_videomode *mode,
497 int ver, int rev)
497{ 498{
498 int xres, yres = 0, refresh, ratio, i; 499 int xres, yres = 0, refresh, ratio, i;
499 500
@@ -504,7 +505,11 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
504 ratio = (block[1] & 0xc0) >> 6; 505 ratio = (block[1] & 0xc0) >> 6;
505 switch (ratio) { 506 switch (ratio) {
506 case 0: 507 case 0:
507 yres = xres; 508 /* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */
509 if (ver < 1 || (ver == 1 && rev < 3))
510 yres = xres;
511 else
512 yres = (xres * 10)/16;
508 break; 513 break;
509 case 1: 514 case 1:
510 yres = (xres * 3)/4; 515 yres = (xres * 3)/4;
@@ -533,12 +538,12 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
533} 538}
534 539
535static int get_dst_timing(unsigned char *block, 540static int get_dst_timing(unsigned char *block,
536 struct fb_videomode *mode) 541 struct fb_videomode *mode, int ver, int rev)
537{ 542{
538 int j, num = 0; 543 int j, num = 0;
539 544
540 for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) 545 for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
541 num += get_std_timing(block, &mode[num]); 546 num += get_std_timing(block, &mode[num], ver, rev);
542 547
543 return num; 548 return num;
544} 549}
@@ -599,6 +604,10 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
599 struct fb_videomode *mode, *m; 604 struct fb_videomode *mode, *m;
600 unsigned char *block; 605 unsigned char *block;
601 int num = 0, i, first = 1; 606 int num = 0, i, first = 1;
607 int ver, rev;
608
609 ver = edid[EDID_STRUCT_VERSION];
610 rev = edid[EDID_STRUCT_REVISION];
602 611
603 mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL); 612 mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
604 if (mode == NULL) 613 if (mode == NULL)
@@ -632,12 +641,12 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
632 DPRINTK(" Standard Timings\n"); 641 DPRINTK(" Standard Timings\n");
633 block = edid + STD_TIMING_DESCRIPTIONS_START; 642 block = edid + STD_TIMING_DESCRIPTIONS_START;
634 for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) 643 for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
635 num += get_std_timing(block, &mode[num]); 644 num += get_std_timing(block, &mode[num], ver, rev);
636 645
637 block = edid + DETAILED_TIMING_DESCRIPTIONS_START; 646 block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
638 for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { 647 for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
639 if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) 648 if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
640 num += get_dst_timing(block + 5, &mode[num]); 649 num += get_dst_timing(block + 5, &mode[num], ver, rev);
641 } 650 }
642 651
643 /* Yikes, EDID data is totally useless */ 652 /* Yikes, EDID data is totally useless */
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 04251ce8918..67afa9c2289 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device,
399 399
400 state = simple_strtoul(buf, &last, 0); 400 state = simple_strtoul(buf, &last, 0);
401 401
402 if (!lock_fb_info(fb_info))
403 return -ENODEV;
402 console_lock(); 404 console_lock();
403 fb_set_suspend(fb_info, (int)state); 405 fb_set_suspend(fb_info, (int)state);
404 console_unlock(); 406 console_unlock();
407 unlock_fb_info(fb_info);
405 408
406 return count; 409 return count;
407} 410}
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 0acc7d65aea..a16beeb5f54 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -30,37 +30,40 @@
30#include <linux/clk.h> 30#include <linux/clk.h>
31#include <linux/uaccess.h> 31#include <linux/uaccess.h>
32#include <linux/vmalloc.h> 32#include <linux/vmalloc.h>
33 33#include <linux/spinlock.h>
34#include <linux/of_platform.h>
35 34
36#include <sysdev/fsl_soc.h> 35#include <sysdev/fsl_soc.h>
37#include <linux/fsl-diu-fb.h> 36#include <linux/fsl-diu-fb.h>
38#include "edid.h" 37#include "edid.h"
39 38
40/* 39#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */
41 * These parameters give default parameters 40 /* 1 for plane 0, 2 for plane 1&2 each */
42 * for video output 1024x768, 41
43 * FIXME - change timing to proper amounts 42/* HW cursor parameters */
44 * hsync 31.5kHz, vsync 60Hz 43#define MAX_CURS 32
45 */ 44
46static struct fb_videomode __devinitdata fsl_diu_default_mode = { 45/* INT_STATUS/INT_MASK field descriptions */
47 .refresh = 60, 46#define INT_VSYNC 0x01 /* Vsync interrupt */
48 .xres = 1024, 47#define INT_VSYNC_WB 0x02 /* Vsync interrupt for write back operation */
49 .yres = 768, 48#define INT_UNDRUN 0x04 /* Under run exception interrupt */
50 .pixclock = 15385, 49#define INT_PARERR 0x08 /* Display parameters error interrupt */
51 .left_margin = 160, 50#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */
52 .right_margin = 24, 51
53 .upper_margin = 29, 52struct diu_addr {
54 .lower_margin = 3, 53 void *vaddr; /* Virtual address */
55 .hsync_len = 136, 54 dma_addr_t paddr; /* Physical address */
56 .vsync_len = 6, 55 __u32 offset;
57 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
58 .vmode = FB_VMODE_NONINTERLACED
59}; 56};
60 57
58/*
59 * List of supported video modes
60 *
61 * The first entry is the default video mode. The remain entries are in
62 * order if increasing resolution and frequency. The 320x240-60 mode is
63 * the initial AOI for the second and third planes.
64 */
61static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { 65static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
62 { 66 {
63 .name = "1024x768-60",
64 .refresh = 60, 67 .refresh = 60,
65 .xres = 1024, 68 .xres = 1024,
66 .yres = 768, 69 .yres = 768,
@@ -75,7 +78,132 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
75 .vmode = FB_VMODE_NONINTERLACED 78 .vmode = FB_VMODE_NONINTERLACED
76 }, 79 },
77 { 80 {
78 .name = "1024x768-70", 81 .refresh = 60,
82 .xres = 320,
83 .yres = 240,
84 .pixclock = 79440,
85 .left_margin = 16,
86 .right_margin = 16,
87 .upper_margin = 16,
88 .lower_margin = 5,
89 .hsync_len = 48,
90 .vsync_len = 1,
91 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
92 .vmode = FB_VMODE_NONINTERLACED
93 },
94 {
95 .refresh = 60,
96 .xres = 640,
97 .yres = 480,
98 .pixclock = 39722,
99 .left_margin = 48,
100 .right_margin = 16,
101 .upper_margin = 33,
102 .lower_margin = 10,
103 .hsync_len = 96,
104 .vsync_len = 2,
105 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
106 .vmode = FB_VMODE_NONINTERLACED
107 },
108 {
109 .refresh = 72,
110 .xres = 640,
111 .yres = 480,
112 .pixclock = 32052,
113 .left_margin = 128,
114 .right_margin = 24,
115 .upper_margin = 28,
116 .lower_margin = 9,
117 .hsync_len = 40,
118 .vsync_len = 3,
119 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
120 .vmode = FB_VMODE_NONINTERLACED
121 },
122 {
123 .refresh = 75,
124 .xres = 640,
125 .yres = 480,
126 .pixclock = 31747,
127 .left_margin = 120,
128 .right_margin = 16,
129 .upper_margin = 16,
130 .lower_margin = 1,
131 .hsync_len = 64,
132 .vsync_len = 3,
133 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
134 .vmode = FB_VMODE_NONINTERLACED
135 },
136 {
137 .refresh = 90,
138 .xres = 640,
139 .yres = 480,
140 .pixclock = 25057,
141 .left_margin = 120,
142 .right_margin = 32,
143 .upper_margin = 14,
144 .lower_margin = 25,
145 .hsync_len = 40,
146 .vsync_len = 14,
147 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
148 .vmode = FB_VMODE_NONINTERLACED
149 },
150 {
151 .refresh = 100,
152 .xres = 640,
153 .yres = 480,
154 .pixclock = 22272,
155 .left_margin = 48,
156 .right_margin = 32,
157 .upper_margin = 17,
158 .lower_margin = 22,
159 .hsync_len = 128,
160 .vsync_len = 12,
161 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
162 .vmode = FB_VMODE_NONINTERLACED
163 },
164 {
165 .refresh = 60,
166 .xres = 800,
167 .yres = 480,
168 .pixclock = 33805,
169 .left_margin = 96,
170 .right_margin = 24,
171 .upper_margin = 10,
172 .lower_margin = 3,
173 .hsync_len = 72,
174 .vsync_len = 7,
175 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
176 .vmode = FB_VMODE_NONINTERLACED
177 },
178 {
179 .refresh = 60,
180 .xres = 800,
181 .yres = 600,
182 .pixclock = 25000,
183 .left_margin = 88,
184 .right_margin = 40,
185 .upper_margin = 23,
186 .lower_margin = 1,
187 .hsync_len = 128,
188 .vsync_len = 4,
189 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
190 .vmode = FB_VMODE_NONINTERLACED
191 },
192 {
193 .refresh = 60,
194 .xres = 854,
195 .yres = 480,
196 .pixclock = 31518,
197 .left_margin = 104,
198 .right_margin = 16,
199 .upper_margin = 13,
200 .lower_margin = 1,
201 .hsync_len = 88,
202 .vsync_len = 3,
203 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
204 .vmode = FB_VMODE_NONINTERLACED
205 },
206 {
79 .refresh = 70, 207 .refresh = 70,
80 .xres = 1024, 208 .xres = 1024,
81 .yres = 768, 209 .yres = 768,
@@ -90,7 +218,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
90 .vmode = FB_VMODE_NONINTERLACED 218 .vmode = FB_VMODE_NONINTERLACED
91 }, 219 },
92 { 220 {
93 .name = "1024x768-75",
94 .refresh = 75, 221 .refresh = 75,
95 .xres = 1024, 222 .xres = 1024,
96 .yres = 768, 223 .yres = 768,
@@ -105,7 +232,34 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
105 .vmode = FB_VMODE_NONINTERLACED 232 .vmode = FB_VMODE_NONINTERLACED
106 }, 233 },
107 { 234 {
108 .name = "1280x1024-60", 235 .refresh = 60,
236 .xres = 1280,
237 .yres = 480,
238 .pixclock = 18939,
239 .left_margin = 353,
240 .right_margin = 47,
241 .upper_margin = 39,
242 .lower_margin = 4,
243 .hsync_len = 8,
244 .vsync_len = 2,
245 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
246 .vmode = FB_VMODE_NONINTERLACED
247 },
248 {
249 .refresh = 60,
250 .xres = 1280,
251 .yres = 720,
252 .pixclock = 13426,
253 .left_margin = 192,
254 .right_margin = 64,
255 .upper_margin = 22,
256 .lower_margin = 1,
257 .hsync_len = 136,
258 .vsync_len = 3,
259 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
260 .vmode = FB_VMODE_NONINTERLACED
261 },
262 {
109 .refresh = 60, 263 .refresh = 60,
110 .xres = 1280, 264 .xres = 1280,
111 .yres = 1024, 265 .yres = 1024,
@@ -120,7 +274,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
120 .vmode = FB_VMODE_NONINTERLACED 274 .vmode = FB_VMODE_NONINTERLACED
121 }, 275 },
122 { 276 {
123 .name = "1280x1024-70",
124 .refresh = 70, 277 .refresh = 70,
125 .xres = 1280, 278 .xres = 1280,
126 .yres = 1024, 279 .yres = 1024,
@@ -135,7 +288,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
135 .vmode = FB_VMODE_NONINTERLACED 288 .vmode = FB_VMODE_NONINTERLACED
136 }, 289 },
137 { 290 {
138 .name = "1280x1024-75",
139 .refresh = 75, 291 .refresh = 75,
140 .xres = 1280, 292 .xres = 1280,
141 .yres = 1024, 293 .yres = 1024,
@@ -150,40 +302,25 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
150 .vmode = FB_VMODE_NONINTERLACED 302 .vmode = FB_VMODE_NONINTERLACED
151 }, 303 },
152 { 304 {
153 .name = "320x240", /* for AOI only */
154 .refresh = 60, 305 .refresh = 60,
155 .xres = 320, 306 .xres = 1920,
156 .yres = 240, 307 .yres = 1080,
157 .pixclock = 15385, 308 .pixclock = 5787,
158 .left_margin = 0, 309 .left_margin = 328,
159 .right_margin = 0, 310 .right_margin = 120,
160 .upper_margin = 0, 311 .upper_margin = 34,
161 .lower_margin = 0, 312 .lower_margin = 1,
162 .hsync_len = 0, 313 .hsync_len = 208,
163 .vsync_len = 0, 314 .vsync_len = 3,
164 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
165 .vmode = FB_VMODE_NONINTERLACED
166 },
167 {
168 .name = "1280x480-60",
169 .refresh = 60,
170 .xres = 1280,
171 .yres = 480,
172 .pixclock = 18939,
173 .left_margin = 353,
174 .right_margin = 47,
175 .upper_margin = 39,
176 .lower_margin = 4,
177 .hsync_len = 8,
178 .vsync_len = 2,
179 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 315 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
180 .vmode = FB_VMODE_NONINTERLACED 316 .vmode = FB_VMODE_NONINTERLACED
181 }, 317 },
182}; 318};
183 319
184static char *fb_mode = "1024x768-32@60"; 320static char *fb_mode;
185static unsigned long default_bpp = 32; 321static unsigned long default_bpp = 32;
186static int monitor_port; 322static enum fsl_diu_monitor_port monitor_port;
323static char *monitor_string;
187 324
188#if defined(CONFIG_NOT_COHERENT_CACHE) 325#if defined(CONFIG_NOT_COHERENT_CACHE)
189static u8 *coherence_data; 326static u8 *coherence_data;
@@ -201,15 +338,27 @@ struct fsl_diu_data {
201 void *dummy_aoi_virt; 338 void *dummy_aoi_virt;
202 unsigned int irq; 339 unsigned int irq;
203 int fb_enabled; 340 int fb_enabled;
204 int monitor_port; 341 enum fsl_diu_monitor_port monitor_port;
342 struct diu __iomem *diu_reg;
343 spinlock_t reg_lock;
344 struct diu_addr ad;
345 struct diu_addr gamma;
346 struct diu_addr pallete;
347 struct diu_addr cursor;
348};
349
350enum mfb_index {
351 PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */
352 PLANE1_AOI0, /* Plane 1, first AOI */
353 PLANE1_AOI1, /* Plane 1, second AOI */
354 PLANE2_AOI0, /* Plane 2, first AOI */
355 PLANE2_AOI1, /* Plane 2, second AOI */
205}; 356};
206 357
207struct mfb_info { 358struct mfb_info {
208 int index; 359 enum mfb_index index;
209 int type;
210 char *id; 360 char *id;
211 int registered; 361 int registered;
212 int blank;
213 unsigned long pseudo_palette[16]; 362 unsigned long pseudo_palette[16];
214 struct diu_ad *ad; 363 struct diu_ad *ad;
215 int cursor_reset; 364 int cursor_reset;
@@ -223,63 +372,82 @@ struct mfb_info {
223 372
224 373
225static struct mfb_info mfb_template[] = { 374static struct mfb_info mfb_template[] = {
226 { /* AOI 0 for plane 0 */ 375 {
227 .index = 0, 376 .index = PLANE0,
228 .type = MFB_TYPE_OUTPUT, 377 .id = "Panel0",
229 .id = "Panel0", 378 .registered = 0,
230 .registered = 0, 379 .count = 0,
231 .count = 0, 380 .x_aoi_d = 0,
232 .x_aoi_d = 0, 381 .y_aoi_d = 0,
233 .y_aoi_d = 0,
234 }, 382 },
235 { /* AOI 0 for plane 1 */ 383 {
236 .index = 1, 384 .index = PLANE1_AOI0,
237 .type = MFB_TYPE_OUTPUT, 385 .id = "Panel1 AOI0",
238 .id = "Panel1 AOI0", 386 .registered = 0,
239 .registered = 0, 387 .g_alpha = 0xff,
240 .g_alpha = 0xff, 388 .count = 0,
241 .count = 0, 389 .x_aoi_d = 0,
242 .x_aoi_d = 0, 390 .y_aoi_d = 0,
243 .y_aoi_d = 0,
244 }, 391 },
245 { /* AOI 1 for plane 1 */ 392 {
246 .index = 2, 393 .index = PLANE1_AOI1,
247 .type = MFB_TYPE_OUTPUT, 394 .id = "Panel1 AOI1",
248 .id = "Panel1 AOI1", 395 .registered = 0,
249 .registered = 0, 396 .g_alpha = 0xff,
250 .g_alpha = 0xff, 397 .count = 0,
251 .count = 0, 398 .x_aoi_d = 0,
252 .x_aoi_d = 0, 399 .y_aoi_d = 480,
253 .y_aoi_d = 480,
254 }, 400 },
255 { /* AOI 0 for plane 2 */ 401 {
256 .index = 3, 402 .index = PLANE2_AOI0,
257 .type = MFB_TYPE_OUTPUT, 403 .id = "Panel2 AOI0",
258 .id = "Panel2 AOI0", 404 .registered = 0,
259 .registered = 0, 405 .g_alpha = 0xff,
260 .g_alpha = 0xff, 406 .count = 0,
261 .count = 0, 407 .x_aoi_d = 640,
262 .x_aoi_d = 640, 408 .y_aoi_d = 0,
263 .y_aoi_d = 0,
264 }, 409 },
265 { /* AOI 1 for plane 2 */ 410 {
266 .index = 4, 411 .index = PLANE2_AOI1,
267 .type = MFB_TYPE_OUTPUT, 412 .id = "Panel2 AOI1",
268 .id = "Panel2 AOI1", 413 .registered = 0,
269 .registered = 0, 414 .g_alpha = 0xff,
270 .g_alpha = 0xff, 415 .count = 0,
271 .count = 0, 416 .x_aoi_d = 640,
272 .x_aoi_d = 640, 417 .y_aoi_d = 480,
273 .y_aoi_d = 480,
274 }, 418 },
275}; 419};
276 420
277static struct diu_hw dr = { 421/**
278 .mode = MFB_MODE1, 422 * fsl_diu_name_to_port - convert a port name to a monitor port enum
279 .reg_lock = __SPIN_LOCK_UNLOCKED(diu_hw.reg_lock), 423 *
280}; 424 * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns
425 * the enum fsl_diu_monitor_port that corresponds to that string.
426 *
427 * For compatibility with older versions, a number ("0", "1", or "2") is also
428 * supported.
429 *
430 * If the string is unknown, DVI is assumed.
431 *
432 * If the particular port is not supported by the platform, another port
433 * (platform-specific) is chosen instead.
434 */
435static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
436{
437 enum fsl_diu_monitor_port port = FSL_DIU_PORT_DVI;
438 unsigned long val;
281 439
282static struct diu_pool pool; 440 if (s) {
441 if (!strict_strtoul(s, 10, &val) && (val <= 2))
442 port = (enum fsl_diu_monitor_port) val;
443 else if (strncmp(s, "lvds", 4) == 0)
444 port = FSL_DIU_PORT_LVDS;
445 else if (strncmp(s, "dlvds", 5) == 0)
446 port = FSL_DIU_PORT_DLVDS;
447 }
448
449 return diu_ops.valid_monitor_port(port);
450}
283 451
284/** 452/**
285 * fsl_diu_alloc - allocate memory for the DIU 453 * fsl_diu_alloc - allocate memory for the DIU
@@ -292,14 +460,9 @@ static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
292{ 460{
293 void *virt; 461 void *virt;
294 462
295 pr_debug("size=%zu\n", size);
296
297 virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO); 463 virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
298 if (virt) { 464 if (virt)
299 *phys = virt_to_phys(virt); 465 *phys = virt_to_phys(virt);
300 pr_debug("virt=%p phys=%llx\n", virt,
301 (unsigned long long)*phys);
302 }
303 466
304 return virt; 467 return virt;
305} 468}
@@ -313,8 +476,6 @@ static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
313 */ 476 */
314static void fsl_diu_free(void *virt, size_t size) 477static void fsl_diu_free(void *virt, size_t size)
315{ 478{
316 pr_debug("virt=%p size=%zu\n", virt, size);
317
318 if (virt && size) 479 if (virt && size)
319 free_pages_exact(virt, size); 480 free_pages_exact(virt, size);
320} 481}
@@ -330,82 +491,72 @@ void wr_reg_wa(u32 *reg, u32 val)
330 } while (in_be32(reg) != val); 491 } while (in_be32(reg) != val);
331} 492}
332 493
333static int fsl_diu_enable_panel(struct fb_info *info) 494static void fsl_diu_enable_panel(struct fb_info *info)
334{ 495{
335 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; 496 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
336 struct diu *hw = dr.diu_reg;
337 struct diu_ad *ad = mfbi->ad; 497 struct diu_ad *ad = mfbi->ad;
338 struct fsl_diu_data *machine_data = mfbi->parent; 498 struct fsl_diu_data *machine_data = mfbi->parent;
339 int res = 0; 499 struct diu __iomem *hw = machine_data->diu_reg;
340 500
341 pr_debug("enable_panel index %d\n", mfbi->index); 501 switch (mfbi->index) {
342 if (mfbi->type != MFB_TYPE_OFF) { 502 case PLANE0:
343 switch (mfbi->index) { 503 if (hw->desc[0] != ad->paddr)
344 case 0: /* plane 0 */ 504 wr_reg_wa(&hw->desc[0], ad->paddr);
345 if (hw->desc[0] != ad->paddr) 505 break;
346 wr_reg_wa(&hw->desc[0], ad->paddr); 506 case PLANE1_AOI0:
347 break; 507 cmfbi = machine_data->fsl_diu_info[2]->par;
348 case 1: /* plane 1 AOI 0 */ 508 if (hw->desc[1] != ad->paddr) { /* AOI0 closed */
349 cmfbi = machine_data->fsl_diu_info[2]->par; 509 if (cmfbi->count > 0) /* AOI1 open */
350 if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ 510 ad->next_ad =
351 if (cmfbi->count > 0) /* AOI1 open */ 511 cpu_to_le32(cmfbi->ad->paddr);
352 ad->next_ad = 512 else
353 cpu_to_le32(cmfbi->ad->paddr); 513 ad->next_ad = 0;
354 else 514 wr_reg_wa(&hw->desc[1], ad->paddr);
355 ad->next_ad = 0;
356 wr_reg_wa(&hw->desc[1], ad->paddr);
357 }
358 break;
359 case 3: /* plane 2 AOI 0 */
360 cmfbi = machine_data->fsl_diu_info[4]->par;
361 if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
362 if (cmfbi->count > 0) /* AOI1 open */
363 ad->next_ad =
364 cpu_to_le32(cmfbi->ad->paddr);
365 else
366 ad->next_ad = 0;
367 wr_reg_wa(&hw->desc[2], ad->paddr);
368 }
369 break;
370 case 2: /* plane 1 AOI 1 */
371 pmfbi = machine_data->fsl_diu_info[1]->par;
372 ad->next_ad = 0;
373 if (hw->desc[1] == machine_data->dummy_ad->paddr)
374 wr_reg_wa(&hw->desc[1], ad->paddr);
375 else /* AOI0 open */
376 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
377 break;
378 case 4: /* plane 2 AOI 1 */
379 pmfbi = machine_data->fsl_diu_info[3]->par;
380 ad->next_ad = 0;
381 if (hw->desc[2] == machine_data->dummy_ad->paddr)
382 wr_reg_wa(&hw->desc[2], ad->paddr);
383 else /* AOI0 was open */
384 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
385 break;
386 default:
387 res = -EINVAL;
388 break;
389 } 515 }
390 } else 516 break;
391 res = -EINVAL; 517 case PLANE2_AOI0:
392 return res; 518 cmfbi = machine_data->fsl_diu_info[4]->par;
519 if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
520 if (cmfbi->count > 0) /* AOI1 open */
521 ad->next_ad =
522 cpu_to_le32(cmfbi->ad->paddr);
523 else
524 ad->next_ad = 0;
525 wr_reg_wa(&hw->desc[2], ad->paddr);
526 }
527 break;
528 case PLANE1_AOI1:
529 pmfbi = machine_data->fsl_diu_info[1]->par;
530 ad->next_ad = 0;
531 if (hw->desc[1] == machine_data->dummy_ad->paddr)
532 wr_reg_wa(&hw->desc[1], ad->paddr);
533 else /* AOI0 open */
534 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
535 break;
536 case PLANE2_AOI1:
537 pmfbi = machine_data->fsl_diu_info[3]->par;
538 ad->next_ad = 0;
539 if (hw->desc[2] == machine_data->dummy_ad->paddr)
540 wr_reg_wa(&hw->desc[2], ad->paddr);
541 else /* AOI0 was open */
542 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
543 break;
544 }
393} 545}
394 546
395static int fsl_diu_disable_panel(struct fb_info *info) 547static void fsl_diu_disable_panel(struct fb_info *info)
396{ 548{
397 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; 549 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
398 struct diu *hw = dr.diu_reg;
399 struct diu_ad *ad = mfbi->ad; 550 struct diu_ad *ad = mfbi->ad;
400 struct fsl_diu_data *machine_data = mfbi->parent; 551 struct fsl_diu_data *machine_data = mfbi->parent;
401 int res = 0; 552 struct diu __iomem *hw = machine_data->diu_reg;
402 553
403 switch (mfbi->index) { 554 switch (mfbi->index) {
404 case 0: /* plane 0 */ 555 case PLANE0:
405 if (hw->desc[0] != machine_data->dummy_ad->paddr) 556 if (hw->desc[0] != machine_data->dummy_ad->paddr)
406 wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr); 557 wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr);
407 break; 558 break;
408 case 1: /* plane 1 AOI 0 */ 559 case PLANE1_AOI0:
409 cmfbi = machine_data->fsl_diu_info[2]->par; 560 cmfbi = machine_data->fsl_diu_info[2]->par;
410 if (cmfbi->count > 0) /* AOI1 is open */ 561 if (cmfbi->count > 0) /* AOI1 is open */
411 wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr); 562 wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
@@ -414,7 +565,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
414 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); 565 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
415 /* close AOI 0 */ 566 /* close AOI 0 */
416 break; 567 break;
417 case 3: /* plane 2 AOI 0 */ 568 case PLANE2_AOI0:
418 cmfbi = machine_data->fsl_diu_info[4]->par; 569 cmfbi = machine_data->fsl_diu_info[4]->par;
419 if (cmfbi->count > 0) /* AOI1 is open */ 570 if (cmfbi->count > 0) /* AOI1 is open */
420 wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr); 571 wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
@@ -423,7 +574,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
423 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); 574 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
424 /* close AOI 0 */ 575 /* close AOI 0 */
425 break; 576 break;
426 case 2: /* plane 1 AOI 1 */ 577 case PLANE1_AOI1:
427 pmfbi = machine_data->fsl_diu_info[1]->par; 578 pmfbi = machine_data->fsl_diu_info[1]->par;
428 if (hw->desc[1] != ad->paddr) { 579 if (hw->desc[1] != ad->paddr) {
429 /* AOI1 is not the first in the chain */ 580 /* AOI1 is not the first in the chain */
@@ -434,7 +585,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
434 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); 585 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
435 /* close AOI 1 */ 586 /* close AOI 1 */
436 break; 587 break;
437 case 4: /* plane 2 AOI 1 */ 588 case PLANE2_AOI1:
438 pmfbi = machine_data->fsl_diu_info[3]->par; 589 pmfbi = machine_data->fsl_diu_info[3]->par;
439 if (hw->desc[2] != ad->paddr) { 590 if (hw->desc[2] != ad->paddr) {
440 /* AOI1 is not the first in the chain */ 591 /* AOI1 is not the first in the chain */
@@ -445,31 +596,26 @@ static int fsl_diu_disable_panel(struct fb_info *info)
445 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); 596 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
446 /* close AOI 1 */ 597 /* close AOI 1 */
447 break; 598 break;
448 default:
449 res = -EINVAL;
450 break;
451 } 599 }
452
453 return res;
454} 600}
455 601
456static void enable_lcdc(struct fb_info *info) 602static void enable_lcdc(struct fb_info *info)
457{ 603{
458 struct diu *hw = dr.diu_reg;
459 struct mfb_info *mfbi = info->par; 604 struct mfb_info *mfbi = info->par;
460 struct fsl_diu_data *machine_data = mfbi->parent; 605 struct fsl_diu_data *machine_data = mfbi->parent;
606 struct diu __iomem *hw = machine_data->diu_reg;
461 607
462 if (!machine_data->fb_enabled) { 608 if (!machine_data->fb_enabled) {
463 out_be32(&hw->diu_mode, dr.mode); 609 out_be32(&hw->diu_mode, MFB_MODE1);
464 machine_data->fb_enabled++; 610 machine_data->fb_enabled++;
465 } 611 }
466} 612}
467 613
468static void disable_lcdc(struct fb_info *info) 614static void disable_lcdc(struct fb_info *info)
469{ 615{
470 struct diu *hw = dr.diu_reg;
471 struct mfb_info *mfbi = info->par; 616 struct mfb_info *mfbi = info->par;
472 struct fsl_diu_data *machine_data = mfbi->parent; 617 struct fsl_diu_data *machine_data = mfbi->parent;
618 struct diu __iomem *hw = machine_data->diu_reg;
473 619
474 if (machine_data->fb_enabled) { 620 if (machine_data->fb_enabled) {
475 out_be32(&hw->diu_mode, 0); 621 out_be32(&hw->diu_mode, 0);
@@ -482,7 +628,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
482{ 628{
483 struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par; 629 struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par;
484 struct fsl_diu_data *machine_data = mfbi->parent; 630 struct fsl_diu_data *machine_data = mfbi->parent;
485 int available_height, upper_aoi_bottom, index = mfbi->index; 631 int available_height, upper_aoi_bottom;
632 enum mfb_index index = mfbi->index;
486 int lower_aoi_is_open, upper_aoi_is_open; 633 int lower_aoi_is_open, upper_aoi_is_open;
487 __u32 base_plane_width, base_plane_height, upper_aoi_height; 634 __u32 base_plane_width, base_plane_height, upper_aoi_height;
488 635
@@ -494,14 +641,14 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
494 if (mfbi->y_aoi_d < 0) 641 if (mfbi->y_aoi_d < 0)
495 mfbi->y_aoi_d = 0; 642 mfbi->y_aoi_d = 0;
496 switch (index) { 643 switch (index) {
497 case 0: 644 case PLANE0:
498 if (mfbi->x_aoi_d != 0) 645 if (mfbi->x_aoi_d != 0)
499 mfbi->x_aoi_d = 0; 646 mfbi->x_aoi_d = 0;
500 if (mfbi->y_aoi_d != 0) 647 if (mfbi->y_aoi_d != 0)
501 mfbi->y_aoi_d = 0; 648 mfbi->y_aoi_d = 0;
502 break; 649 break;
503 case 1: /* AOI 0 */ 650 case PLANE1_AOI0:
504 case 3: 651 case PLANE2_AOI0:
505 lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; 652 lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par;
506 lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; 653 lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
507 if (var->xres > base_plane_width) 654 if (var->xres > base_plane_width)
@@ -518,8 +665,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
518 if ((mfbi->y_aoi_d + var->yres) > available_height) 665 if ((mfbi->y_aoi_d + var->yres) > available_height)
519 mfbi->y_aoi_d = available_height - var->yres; 666 mfbi->y_aoi_d = available_height - var->yres;
520 break; 667 break;
521 case 2: /* AOI 1 */ 668 case PLANE1_AOI1:
522 case 4: 669 case PLANE2_AOI1:
523 upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; 670 upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par;
524 upper_aoi_height = 671 upper_aoi_height =
525 machine_data->fsl_diu_info[index-1]->var.yres; 672 machine_data->fsl_diu_info[index-1]->var.yres;
@@ -555,9 +702,6 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
555static int fsl_diu_check_var(struct fb_var_screeninfo *var, 702static int fsl_diu_check_var(struct fb_var_screeninfo *var,
556 struct fb_info *info) 703 struct fb_info *info)
557{ 704{
558 pr_debug("check_var xres: %d\n", var->xres);
559 pr_debug("check_var yres: %d\n", var->yres);
560
561 if (var->xres_virtual < var->xres) 705 if (var->xres_virtual < var->xres)
562 var->xres_virtual = var->xres; 706 var->xres_virtual = var->xres;
563 if (var->yres_virtual < var->yres) 707 if (var->yres_virtual < var->yres)
@@ -652,7 +796,7 @@ static void set_fix(struct fb_info *info)
652 struct fb_var_screeninfo *var = &info->var; 796 struct fb_var_screeninfo *var = &info->var;
653 struct mfb_info *mfbi = info->par; 797 struct mfb_info *mfbi = info->par;
654 798
655 strncpy(fix->id, mfbi->id, strlen(mfbi->id)); 799 strncpy(fix->id, mfbi->id, sizeof(fix->id));
656 fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; 800 fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
657 fix->type = FB_TYPE_PACKED_PIXELS; 801 fix->type = FB_TYPE_PACKED_PIXELS;
658 fix->accel = FB_ACCEL_NONE; 802 fix->accel = FB_ACCEL_NONE;
@@ -666,45 +810,37 @@ static void update_lcdc(struct fb_info *info)
666 struct fb_var_screeninfo *var = &info->var; 810 struct fb_var_screeninfo *var = &info->var;
667 struct mfb_info *mfbi = info->par; 811 struct mfb_info *mfbi = info->par;
668 struct fsl_diu_data *machine_data = mfbi->parent; 812 struct fsl_diu_data *machine_data = mfbi->parent;
669 struct diu *hw; 813 struct diu __iomem *hw;
670 int i, j; 814 int i, j;
671 char __iomem *cursor_base, *gamma_table_base; 815 char __iomem *cursor_base, *gamma_table_base;
672 816
673 u32 temp; 817 u32 temp;
674 818
675 hw = dr.diu_reg; 819 hw = machine_data->diu_reg;
676
677 if (mfbi->type == MFB_TYPE_OFF) {
678 fsl_diu_disable_panel(info);
679 return;
680 }
681 820
682 diu_ops.set_monitor_port(machine_data->monitor_port); 821 diu_ops.set_monitor_port(machine_data->monitor_port);
683 gamma_table_base = pool.gamma.vaddr; 822 gamma_table_base = machine_data->gamma.vaddr;
684 cursor_base = pool.cursor.vaddr; 823 cursor_base = machine_data->cursor.vaddr;
685 /* Prep for DIU init - gamma table, cursor table */ 824 /* Prep for DIU init - gamma table, cursor table */
686 825
687 for (i = 0; i <= 2; i++) 826 for (i = 0; i <= 2; i++)
688 for (j = 0; j <= 255; j++) 827 for (j = 0; j <= 255; j++)
689 *gamma_table_base++ = j; 828 *gamma_table_base++ = j;
690 829
691 diu_ops.set_gamma_table(machine_data->monitor_port, pool.gamma.vaddr); 830 diu_ops.set_gamma_table(machine_data->monitor_port,
831 machine_data->gamma.vaddr);
692 832
693 pr_debug("update-lcdc: HW - %p\n Disabling DIU\n", hw);
694 disable_lcdc(info); 833 disable_lcdc(info);
695 834
696 /* Program DIU registers */ 835 /* Program DIU registers */
697 836
698 out_be32(&hw->gamma, pool.gamma.paddr); 837 out_be32(&hw->gamma, machine_data->gamma.paddr);
699 out_be32(&hw->cursor, pool.cursor.paddr); 838 out_be32(&hw->cursor, machine_data->cursor.paddr);
700 839
701 out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ 840 out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
702 out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ 841 out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
703 out_be32(&hw->disp_size, (var->yres << 16 | var->xres)); 842 out_be32(&hw->disp_size, (var->yres << 16 | var->xres));
704 /* DISP SIZE */ 843 /* DISP SIZE */
705 pr_debug("DIU xres: %d\n", var->xres);
706 pr_debug("DIU yres: %d\n", var->yres);
707
708 out_be32(&hw->wb_size, 0); /* WB SIZE */ 844 out_be32(&hw->wb_size, 0); /* WB SIZE */
709 out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ 845 out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */
710 846
@@ -721,15 +857,6 @@ static void update_lcdc(struct fb_info *info)
721 857
722 out_be32(&hw->vsyn_para, temp); 858 out_be32(&hw->vsyn_para, temp);
723 859
724 pr_debug("DIU right_margin - %d\n", var->right_margin);
725 pr_debug("DIU left_margin - %d\n", var->left_margin);
726 pr_debug("DIU hsync_len - %d\n", var->hsync_len);
727 pr_debug("DIU upper_margin - %d\n", var->upper_margin);
728 pr_debug("DIU lower_margin - %d\n", var->lower_margin);
729 pr_debug("DIU vsync_len - %d\n", var->vsync_len);
730 pr_debug("DIU HSYNC - 0x%08x\n", hw->hsyn_para);
731 pr_debug("DIU VSYNC - 0x%08x\n", hw->vsyn_para);
732
733 diu_ops.set_pixel_clock(var->pixclock); 860 diu_ops.set_pixel_clock(var->pixclock);
734 861
735 out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ 862 out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */
@@ -746,14 +873,9 @@ static int map_video_memory(struct fb_info *info)
746 phys_addr_t phys; 873 phys_addr_t phys;
747 u32 smem_len = info->fix.line_length * info->var.yres_virtual; 874 u32 smem_len = info->fix.line_length * info->var.yres_virtual;
748 875
749 pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual);
750 pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual);
751 pr_debug("info->fix.line_length = %d\n", info->fix.line_length);
752 pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len);
753
754 info->screen_base = fsl_diu_alloc(smem_len, &phys); 876 info->screen_base = fsl_diu_alloc(smem_len, &phys);
755 if (info->screen_base == NULL) { 877 if (info->screen_base == NULL) {
756 printk(KERN_ERR "Unable to allocate fb memory\n"); 878 dev_err(info->dev, "unable to allocate fb memory\n");
757 return -ENOMEM; 879 return -ENOMEM;
758 } 880 }
759 mutex_lock(&info->mm_lock); 881 mutex_lock(&info->mm_lock);
@@ -762,10 +884,6 @@ static int map_video_memory(struct fb_info *info)
762 mutex_unlock(&info->mm_lock); 884 mutex_unlock(&info->mm_lock);
763 info->screen_size = info->fix.smem_len; 885 info->screen_size = info->fix.smem_len;
764 886
765 pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n",
766 info->fix.smem_start, info->fix.smem_len);
767 pr_debug("screen base %p\n", info->screen_base);
768
769 return 0; 887 return 0;
770} 888}
771 889
@@ -810,9 +928,9 @@ static int fsl_diu_set_par(struct fb_info *info)
810 struct mfb_info *mfbi = info->par; 928 struct mfb_info *mfbi = info->par;
811 struct fsl_diu_data *machine_data = mfbi->parent; 929 struct fsl_diu_data *machine_data = mfbi->parent;
812 struct diu_ad *ad = mfbi->ad; 930 struct diu_ad *ad = mfbi->ad;
813 struct diu *hw; 931 struct diu __iomem *hw;
814 932
815 hw = dr.diu_reg; 933 hw = machine_data->diu_reg;
816 934
817 set_fix(info); 935 set_fix(info);
818 mfbi->cursor_reset = 1; 936 mfbi->cursor_reset = 1;
@@ -822,18 +940,16 @@ static int fsl_diu_set_par(struct fb_info *info)
822 if (len != info->fix.smem_len) { 940 if (len != info->fix.smem_len) {
823 if (info->fix.smem_start) 941 if (info->fix.smem_start)
824 unmap_video_memory(info); 942 unmap_video_memory(info);
825 pr_debug("SET PAR: smem_len = %d\n", info->fix.smem_len);
826 943
827 /* Memory allocation for framebuffer */ 944 /* Memory allocation for framebuffer */
828 if (map_video_memory(info)) { 945 if (map_video_memory(info)) {
829 printk(KERN_ERR "Unable to allocate fb memory 1\n"); 946 dev_err(info->dev, "unable to allocate fb memory 1\n");
830 return -ENOMEM; 947 return -ENOMEM;
831 } 948 }
832 } 949 }
833 950
834 ad->pix_fmt = 951 ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port,
835 diu_ops.get_pixel_format(var->bits_per_pixel, 952 var->bits_per_pixel);
836 machine_data->monitor_port);
837 ad->addr = cpu_to_le32(info->fix.smem_start); 953 ad->addr = cpu_to_le32(info->fix.smem_start);
838 ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | 954 ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
839 var->xres_virtual) | mfbi->g_alpha; 955 var->xres_virtual) | mfbi->g_alpha;
@@ -851,14 +967,14 @@ static int fsl_diu_set_par(struct fb_info *info)
851 ad->ckmin_g = 255; 967 ad->ckmin_g = 255;
852 ad->ckmin_b = 255; 968 ad->ckmin_b = 255;
853 969
854 if (mfbi->index == 0) 970 if (mfbi->index == PLANE0)
855 update_lcdc(info); 971 update_lcdc(info);
856 return 0; 972 return 0;
857} 973}
858 974
859static inline __u32 CNVT_TOHW(__u32 val, __u32 width) 975static inline __u32 CNVT_TOHW(__u32 val, __u32 width)
860{ 976{
861 return ((val<<width) + 0x7FFF - val)>>16; 977 return ((val << width) + 0x7FFF - val) >> 16;
862} 978}
863 979
864/* 980/*
@@ -870,8 +986,9 @@ static inline __u32 CNVT_TOHW(__u32 val, __u32 width)
870 * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited 986 * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited
871 * color palette. 987 * color palette.
872 */ 988 */
873static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green, 989static int fsl_diu_setcolreg(unsigned int regno, unsigned int red,
874 unsigned blue, unsigned transp, struct fb_info *info) 990 unsigned int green, unsigned int blue,
991 unsigned int transp, struct fb_info *info)
875{ 992{
876 int ret = 1; 993 int ret = 1;
877 994
@@ -906,9 +1023,6 @@ static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green,
906 ret = 0; 1023 ret = 0;
907 } 1024 }
908 break; 1025 break;
909 case FB_VISUAL_STATIC_PSEUDOCOLOR:
910 case FB_VISUAL_PSEUDOCOLOR:
911 break;
912 } 1026 }
913 1027
914 return ret; 1028 return ret;
@@ -944,37 +1058,6 @@ static int fsl_diu_pan_display(struct fb_var_screeninfo *var,
944 return 0; 1058 return 0;
945} 1059}
946 1060
947/*
948 * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking
949 * succeeded, != 0 if un-/blanking failed.
950 * blank_mode == 2: suspend vsync
951 * blank_mode == 3: suspend hsync
952 * blank_mode == 4: powerdown
953 */
954static int fsl_diu_blank(int blank_mode, struct fb_info *info)
955{
956 struct mfb_info *mfbi = info->par;
957
958 mfbi->blank = blank_mode;
959
960 switch (blank_mode) {
961 case FB_BLANK_VSYNC_SUSPEND:
962 case FB_BLANK_HSYNC_SUSPEND:
963 /* FIXME: fixes to enable_panel and enable lcdc needed */
964 case FB_BLANK_NORMAL:
965 /* fsl_diu_disable_panel(info);*/
966 break;
967 case FB_BLANK_POWERDOWN:
968 /* disable_lcdc(info); */
969 break;
970 case FB_BLANK_UNBLANK:
971 /* fsl_diu_enable_panel(info);*/
972 break;
973 }
974
975 return 0;
976}
977
978static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, 1061static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
979 unsigned long arg) 1062 unsigned long arg)
980{ 1063{
@@ -989,25 +1072,29 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
989 if (!arg) 1072 if (!arg)
990 return -EINVAL; 1073 return -EINVAL;
991 switch (cmd) { 1074 switch (cmd) {
1075 case MFB_SET_PIXFMT_OLD:
1076 dev_warn(info->dev,
1077 "MFB_SET_PIXFMT value of 0x%08x is deprecated.\n",
1078 MFB_SET_PIXFMT_OLD);
992 case MFB_SET_PIXFMT: 1079 case MFB_SET_PIXFMT:
993 if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt))) 1080 if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt)))
994 return -EFAULT; 1081 return -EFAULT;
995 ad->pix_fmt = pix_fmt; 1082 ad->pix_fmt = pix_fmt;
996 pr_debug("Set pixel format to 0x%08x\n", ad->pix_fmt);
997 break; 1083 break;
1084 case MFB_GET_PIXFMT_OLD:
1085 dev_warn(info->dev,
1086 "MFB_GET_PIXFMT value of 0x%08x is deprecated.\n",
1087 MFB_GET_PIXFMT_OLD);
998 case MFB_GET_PIXFMT: 1088 case MFB_GET_PIXFMT:
999 pix_fmt = ad->pix_fmt; 1089 pix_fmt = ad->pix_fmt;
1000 if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt))) 1090 if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt)))
1001 return -EFAULT; 1091 return -EFAULT;
1002 pr_debug("get pixel format 0x%08x\n", ad->pix_fmt);
1003 break; 1092 break;
1004 case MFB_SET_AOID: 1093 case MFB_SET_AOID:
1005 if (copy_from_user(&aoi_d, buf, sizeof(aoi_d))) 1094 if (copy_from_user(&aoi_d, buf, sizeof(aoi_d)))
1006 return -EFAULT; 1095 return -EFAULT;
1007 mfbi->x_aoi_d = aoi_d.x_aoi_d; 1096 mfbi->x_aoi_d = aoi_d.x_aoi_d;
1008 mfbi->y_aoi_d = aoi_d.y_aoi_d; 1097 mfbi->y_aoi_d = aoi_d.y_aoi_d;
1009 pr_debug("set AOI display offset of index %d to (%d,%d)\n",
1010 mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d);
1011 fsl_diu_check_var(&info->var, info); 1098 fsl_diu_check_var(&info->var, info);
1012 fsl_diu_set_aoi(info); 1099 fsl_diu_set_aoi(info);
1013 break; 1100 break;
@@ -1016,14 +1103,11 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
1016 aoi_d.y_aoi_d = mfbi->y_aoi_d; 1103 aoi_d.y_aoi_d = mfbi->y_aoi_d;
1017 if (copy_to_user(buf, &aoi_d, sizeof(aoi_d))) 1104 if (copy_to_user(buf, &aoi_d, sizeof(aoi_d)))
1018 return -EFAULT; 1105 return -EFAULT;
1019 pr_debug("get AOI display offset of index %d (%d,%d)\n",
1020 mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d);
1021 break; 1106 break;
1022 case MFB_GET_ALPHA: 1107 case MFB_GET_ALPHA:
1023 global_alpha = mfbi->g_alpha; 1108 global_alpha = mfbi->g_alpha;
1024 if (copy_to_user(buf, &global_alpha, sizeof(global_alpha))) 1109 if (copy_to_user(buf, &global_alpha, sizeof(global_alpha)))
1025 return -EFAULT; 1110 return -EFAULT;
1026 pr_debug("get global alpha of index %d\n", mfbi->index);
1027 break; 1111 break;
1028 case MFB_SET_ALPHA: 1112 case MFB_SET_ALPHA:
1029 /* set panel information */ 1113 /* set panel information */
@@ -1032,7 +1116,6 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
1032 ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) | 1116 ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) |
1033 (global_alpha & 0xff); 1117 (global_alpha & 0xff);
1034 mfbi->g_alpha = global_alpha; 1118 mfbi->g_alpha = global_alpha;
1035 pr_debug("set global alpha for index %d\n", mfbi->index);
1036 break; 1119 break;
1037 case MFB_SET_CHROMA_KEY: 1120 case MFB_SET_CHROMA_KEY:
1038 /* set panel winformation */ 1121 /* set panel winformation */
@@ -1060,27 +1143,9 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
1060 ad->ckmin_g = ck.green_min; 1143 ad->ckmin_g = ck.green_min;
1061 ad->ckmin_b = ck.blue_min; 1144 ad->ckmin_b = ck.blue_min;
1062 } 1145 }
1063 pr_debug("set chroma key\n");
1064 break; 1146 break;
1065 case FBIOGET_GWINFO:
1066 if (mfbi->type == MFB_TYPE_OFF)
1067 return -ENODEV;
1068 /* get graphic window information */
1069 if (copy_to_user(buf, ad, sizeof(*ad)))
1070 return -EFAULT;
1071 break;
1072 case FBIOGET_HWCINFO:
1073 pr_debug("FBIOGET_HWCINFO:0x%08x\n", FBIOGET_HWCINFO);
1074 break;
1075 case FBIOPUT_MODEINFO:
1076 pr_debug("FBIOPUT_MODEINFO:0x%08x\n", FBIOPUT_MODEINFO);
1077 break;
1078 case FBIOGET_DISPINFO:
1079 pr_debug("FBIOGET_DISPINFO:0x%08x\n", FBIOGET_DISPINFO);
1080 break;
1081
1082 default: 1147 default:
1083 printk(KERN_ERR "Unknown ioctl command (0x%08X)\n", cmd); 1148 dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd);
1084 return -ENOIOCTLCMD; 1149 return -ENOIOCTLCMD;
1085 } 1150 }
1086 1151
@@ -1095,22 +1160,18 @@ static int fsl_diu_open(struct fb_info *info, int user)
1095 int res = 0; 1160 int res = 0;
1096 1161
1097 /* free boot splash memory on first /dev/fb0 open */ 1162 /* free boot splash memory on first /dev/fb0 open */
1098 if (!mfbi->index && diu_ops.release_bootmem) 1163 if ((mfbi->index == PLANE0) && diu_ops.release_bootmem)
1099 diu_ops.release_bootmem(); 1164 diu_ops.release_bootmem();
1100 1165
1101 spin_lock(&diu_lock); 1166 spin_lock(&diu_lock);
1102 mfbi->count++; 1167 mfbi->count++;
1103 if (mfbi->count == 1) { 1168 if (mfbi->count == 1) {
1104 pr_debug("open plane index %d\n", mfbi->index);
1105 fsl_diu_check_var(&info->var, info); 1169 fsl_diu_check_var(&info->var, info);
1106 res = fsl_diu_set_par(info); 1170 res = fsl_diu_set_par(info);
1107 if (res < 0) 1171 if (res < 0)
1108 mfbi->count--; 1172 mfbi->count--;
1109 else { 1173 else
1110 res = fsl_diu_enable_panel(info); 1174 fsl_diu_enable_panel(info);
1111 if (res < 0)
1112 mfbi->count--;
1113 }
1114 } 1175 }
1115 1176
1116 spin_unlock(&diu_lock); 1177 spin_unlock(&diu_lock);
@@ -1126,12 +1187,9 @@ static int fsl_diu_release(struct fb_info *info, int user)
1126 1187
1127 spin_lock(&diu_lock); 1188 spin_lock(&diu_lock);
1128 mfbi->count--; 1189 mfbi->count--;
1129 if (mfbi->count == 0) { 1190 if (mfbi->count == 0)
1130 pr_debug("release plane index %d\n", mfbi->index); 1191 fsl_diu_disable_panel(info);
1131 res = fsl_diu_disable_panel(info); 1192
1132 if (res < 0)
1133 mfbi->count++;
1134 }
1135 spin_unlock(&diu_lock); 1193 spin_unlock(&diu_lock);
1136 return res; 1194 return res;
1137} 1195}
@@ -1141,7 +1199,6 @@ static struct fb_ops fsl_diu_ops = {
1141 .fb_check_var = fsl_diu_check_var, 1199 .fb_check_var = fsl_diu_check_var,
1142 .fb_set_par = fsl_diu_set_par, 1200 .fb_set_par = fsl_diu_set_par,
1143 .fb_setcolreg = fsl_diu_setcolreg, 1201 .fb_setcolreg = fsl_diu_setcolreg,
1144 .fb_blank = fsl_diu_blank,
1145 .fb_pan_display = fsl_diu_pan_display, 1202 .fb_pan_display = fsl_diu_pan_display,
1146 .fb_fillrect = cfb_fillrect, 1203 .fb_fillrect = cfb_fillrect,
1147 .fb_copyarea = cfb_copyarea, 1204 .fb_copyarea = cfb_copyarea,
@@ -1178,7 +1235,7 @@ static int __devinit install_fb(struct fb_info *info)
1178 if (init_fbinfo(info)) 1235 if (init_fbinfo(info))
1179 return -EINVAL; 1236 return -EINVAL;
1180 1237
1181 if (mfbi->index == 0) { /* plane 0 */ 1238 if (mfbi->index == PLANE0) {
1182 if (mfbi->edid_data) { 1239 if (mfbi->edid_data) {
1183 /* Now build modedb from EDID */ 1240 /* Now build modedb from EDID */
1184 fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs); 1241 fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs);
@@ -1192,43 +1249,23 @@ static int __devinit install_fb(struct fb_info *info)
1192 } else { 1249 } else {
1193 aoi_mode = init_aoi_mode; 1250 aoi_mode = init_aoi_mode;
1194 } 1251 }
1195 pr_debug("mode used = %s\n", aoi_mode); 1252 rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, NULL,
1196 rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, 1253 default_bpp);
1197 &fsl_diu_default_mode, default_bpp); 1254 if (!rc) {
1198 switch (rc) {
1199 case 1:
1200 pr_debug("using mode specified in @mode\n");
1201 break;
1202 case 2:
1203 pr_debug("using mode specified in @mode "
1204 "with ignored refresh rate\n");
1205 break;
1206 case 3:
1207 pr_debug("using mode default mode\n");
1208 break;
1209 case 4:
1210 pr_debug("using mode from list\n");
1211 break;
1212 default:
1213 pr_debug("rc = %d\n", rc);
1214 pr_debug("failed to find mode\n");
1215 /* 1255 /*
1216 * For plane 0 we continue and look into 1256 * For plane 0 we continue and look into
1217 * driver's internal modedb. 1257 * driver's internal modedb.
1218 */ 1258 */
1219 if (mfbi->index == 0 && mfbi->edid_data) 1259 if ((mfbi->index == PLANE0) && mfbi->edid_data)
1220 has_default_mode = 0; 1260 has_default_mode = 0;
1221 else 1261 else
1222 return -EINVAL; 1262 return -EINVAL;
1223 break;
1224 } 1263 }
1225 1264
1226 if (!has_default_mode) { 1265 if (!has_default_mode) {
1227 rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, 1266 rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
1228 ARRAY_SIZE(fsl_diu_mode_db), 1267 ARRAY_SIZE(fsl_diu_mode_db), NULL, default_bpp);
1229 &fsl_diu_default_mode, 1268 if (rc)
1230 default_bpp);
1231 if (rc > 0 && rc < 5)
1232 has_default_mode = 1; 1269 has_default_mode = 1;
1233 } 1270 }
1234 1271
@@ -1256,33 +1293,22 @@ static int __devinit install_fb(struct fb_info *info)
1256 fb_videomode_to_var(&info->var, modedb); 1293 fb_videomode_to_var(&info->var, modedb);
1257 } 1294 }
1258 1295
1259 pr_debug("xres_virtual %d\n", info->var.xres_virtual);
1260 pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel);
1261
1262 pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual);
1263 pr_debug("info->fix.line_length = %d\n", info->fix.line_length);
1264
1265 if (mfbi->type == MFB_TYPE_OFF)
1266 mfbi->blank = FB_BLANK_NORMAL;
1267 else
1268 mfbi->blank = FB_BLANK_UNBLANK;
1269
1270 if (fsl_diu_check_var(&info->var, info)) { 1296 if (fsl_diu_check_var(&info->var, info)) {
1271 printk(KERN_ERR "fb_check_var failed"); 1297 dev_err(info->dev, "fsl_diu_check_var failed\n");
1298 unmap_video_memory(info);
1272 fb_dealloc_cmap(&info->cmap); 1299 fb_dealloc_cmap(&info->cmap);
1273 return -EINVAL; 1300 return -EINVAL;
1274 } 1301 }
1275 1302
1276 if (register_framebuffer(info) < 0) { 1303 if (register_framebuffer(info) < 0) {
1277 printk(KERN_ERR "register_framebuffer failed"); 1304 dev_err(info->dev, "register_framebuffer failed\n");
1278 unmap_video_memory(info); 1305 unmap_video_memory(info);
1279 fb_dealloc_cmap(&info->cmap); 1306 fb_dealloc_cmap(&info->cmap);
1280 return -EINVAL; 1307 return -EINVAL;
1281 } 1308 }
1282 1309
1283 mfbi->registered = 1; 1310 mfbi->registered = 1;
1284 printk(KERN_INFO "fb%d: %s fb device registered successfully.\n", 1311 dev_info(info->dev, "%s registered successfully\n", mfbi->id);
1285 info->node, info->fix.id);
1286 1312
1287 return 0; 1313 return 0;
1288} 1314}
@@ -1294,7 +1320,7 @@ static void uninstall_fb(struct fb_info *info)
1294 if (!mfbi->registered) 1320 if (!mfbi->registered)
1295 return; 1321 return;
1296 1322
1297 if (mfbi->index == 0) 1323 if (mfbi->index == PLANE0)
1298 kfree(mfbi->edid_data); 1324 kfree(mfbi->edid_data);
1299 1325
1300 unregister_framebuffer(info); 1326 unregister_framebuffer(info);
@@ -1307,20 +1333,20 @@ static void uninstall_fb(struct fb_info *info)
1307 1333
1308static irqreturn_t fsl_diu_isr(int irq, void *dev_id) 1334static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
1309{ 1335{
1310 struct diu *hw = dr.diu_reg; 1336 struct diu __iomem *hw = dev_id;
1311 unsigned int status = in_be32(&hw->int_status); 1337 unsigned int status = in_be32(&hw->int_status);
1312 1338
1313 if (status) { 1339 if (status) {
1314 /* This is the workaround for underrun */ 1340 /* This is the workaround for underrun */
1315 if (status & INT_UNDRUN) { 1341 if (status & INT_UNDRUN) {
1316 out_be32(&hw->diu_mode, 0); 1342 out_be32(&hw->diu_mode, 0);
1317 pr_debug("Err: DIU occurs underrun!\n");
1318 udelay(1); 1343 udelay(1);
1319 out_be32(&hw->diu_mode, 1); 1344 out_be32(&hw->diu_mode, 1);
1320 } 1345 }
1321#if defined(CONFIG_NOT_COHERENT_CACHE) 1346#if defined(CONFIG_NOT_COHERENT_CACHE)
1322 else if (status & INT_VSYNC) { 1347 else if (status & INT_VSYNC) {
1323 unsigned int i; 1348 unsigned int i;
1349
1324 for (i = 0; i < coherence_data_size; 1350 for (i = 0; i < coherence_data_size;
1325 i += d_cache_line_size) 1351 i += d_cache_line_size)
1326 __asm__ __volatile__ ( 1352 __asm__ __volatile__ (
@@ -1333,43 +1359,38 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
1333 return IRQ_NONE; 1359 return IRQ_NONE;
1334} 1360}
1335 1361
1336static int request_irq_local(int irq) 1362static int request_irq_local(struct fsl_diu_data *machine_data)
1337{ 1363{
1338 unsigned long status, ints; 1364 struct diu __iomem *hw = machine_data->diu_reg;
1339 struct diu *hw; 1365 u32 ints;
1340 int ret; 1366 int ret;
1341 1367
1342 hw = dr.diu_reg;
1343
1344 /* Read to clear the status */ 1368 /* Read to clear the status */
1345 status = in_be32(&hw->int_status); 1369 in_be32(&hw->int_status);
1346 1370
1347 ret = request_irq(irq, fsl_diu_isr, 0, "diu", NULL); 1371 ret = request_irq(machine_data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
1348 if (ret) 1372 if (!ret) {
1349 pr_info("Request diu IRQ failed.\n");
1350 else {
1351 ints = INT_PARERR | INT_LS_BF_VS; 1373 ints = INT_PARERR | INT_LS_BF_VS;
1352#if !defined(CONFIG_NOT_COHERENT_CACHE) 1374#if !defined(CONFIG_NOT_COHERENT_CACHE)
1353 ints |= INT_VSYNC; 1375 ints |= INT_VSYNC;
1354#endif 1376#endif
1355 if (dr.mode == MFB_MODE2 || dr.mode == MFB_MODE3)
1356 ints |= INT_VSYNC_WB;
1357 1377
1358 /* Read to clear the status */ 1378 /* Read to clear the status */
1359 status = in_be32(&hw->int_status); 1379 in_be32(&hw->int_status);
1360 out_be32(&hw->int_mask, ints); 1380 out_be32(&hw->int_mask, ints);
1361 } 1381 }
1382
1362 return ret; 1383 return ret;
1363} 1384}
1364 1385
1365static void free_irq_local(int irq) 1386static void free_irq_local(struct fsl_diu_data *machine_data)
1366{ 1387{
1367 struct diu *hw = dr.diu_reg; 1388 struct diu __iomem *hw = machine_data->diu_reg;
1368 1389
1369 /* Disable all LCDC interrupt */ 1390 /* Disable all LCDC interrupt */
1370 out_be32(&hw->int_mask, 0x1f); 1391 out_be32(&hw->int_mask, 0x1f);
1371 1392
1372 free_irq(irq, NULL); 1393 free_irq(machine_data->irq, NULL);
1373} 1394}
1374 1395
1375#ifdef CONFIG_PM 1396#ifdef CONFIG_PM
@@ -1406,49 +1427,42 @@ static int fsl_diu_resume(struct platform_device *ofdev)
1406static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size, 1427static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size,
1407 u32 bytes_align) 1428 u32 bytes_align)
1408{ 1429{
1409 u32 offset, ssize; 1430 u32 offset;
1410 u32 mask; 1431 dma_addr_t mask;
1411 dma_addr_t paddr = 0;
1412 1432
1413 ssize = size + bytes_align; 1433 buf->vaddr =
1414 buf->vaddr = dma_alloc_coherent(dev, ssize, &paddr, GFP_DMA | 1434 dma_alloc_coherent(dev, size + bytes_align, &buf->paddr,
1415 __GFP_ZERO); 1435 GFP_DMA | __GFP_ZERO);
1416 if (!buf->vaddr) 1436 if (!buf->vaddr)
1417 return -ENOMEM; 1437 return -ENOMEM;
1418 1438
1419 buf->paddr = (__u32) paddr;
1420
1421 mask = bytes_align - 1; 1439 mask = bytes_align - 1;
1422 offset = (u32)buf->paddr & mask; 1440 offset = buf->paddr & mask;
1423 if (offset) { 1441 if (offset) {
1424 buf->offset = bytes_align - offset; 1442 buf->offset = bytes_align - offset;
1425 buf->paddr = (u32)buf->paddr + offset; 1443 buf->paddr = buf->paddr + offset;
1426 } else 1444 } else
1427 buf->offset = 0; 1445 buf->offset = 0;
1446
1428 return 0; 1447 return 0;
1429} 1448}
1430 1449
1431static void free_buf(struct device *dev, struct diu_addr *buf, u32 size, 1450static void free_buf(struct device *dev, struct diu_addr *buf, u32 size,
1432 u32 bytes_align) 1451 u32 bytes_align)
1433{ 1452{
1434 dma_free_coherent(dev, size + bytes_align, 1453 dma_free_coherent(dev, size + bytes_align, buf->vaddr,
1435 buf->vaddr, (buf->paddr - buf->offset)); 1454 buf->paddr - buf->offset);
1436 return;
1437} 1455}
1438 1456
1439static ssize_t store_monitor(struct device *device, 1457static ssize_t store_monitor(struct device *device,
1440 struct device_attribute *attr, const char *buf, size_t count) 1458 struct device_attribute *attr, const char *buf, size_t count)
1441{ 1459{
1442 int old_monitor_port; 1460 enum fsl_diu_monitor_port old_monitor_port;
1443 unsigned long val;
1444 struct fsl_diu_data *machine_data = 1461 struct fsl_diu_data *machine_data =
1445 container_of(attr, struct fsl_diu_data, dev_attr); 1462 container_of(attr, struct fsl_diu_data, dev_attr);
1446 1463
1447 if (strict_strtoul(buf, 10, &val))
1448 return 0;
1449
1450 old_monitor_port = machine_data->monitor_port; 1464 old_monitor_port = machine_data->monitor_port;
1451 machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val); 1465 machine_data->monitor_port = fsl_diu_name_to_port(buf);
1452 1466
1453 if (old_monitor_port != machine_data->monitor_port) { 1467 if (old_monitor_port != machine_data->monitor_port) {
1454 /* All AOIs need adjust pixel format 1468 /* All AOIs need adjust pixel format
@@ -1468,16 +1482,25 @@ static ssize_t show_monitor(struct device *device,
1468{ 1482{
1469 struct fsl_diu_data *machine_data = 1483 struct fsl_diu_data *machine_data =
1470 container_of(attr, struct fsl_diu_data, dev_attr); 1484 container_of(attr, struct fsl_diu_data, dev_attr);
1471 return diu_ops.show_monitor_port(machine_data->monitor_port, buf); 1485
1486 switch (machine_data->monitor_port) {
1487 case FSL_DIU_PORT_DVI:
1488 return sprintf(buf, "DVI\n");
1489 case FSL_DIU_PORT_LVDS:
1490 return sprintf(buf, "Single-link LVDS\n");
1491 case FSL_DIU_PORT_DLVDS:
1492 return sprintf(buf, "Dual-link LVDS\n");
1493 }
1494
1495 return 0;
1472} 1496}
1473 1497
1474static int __devinit fsl_diu_probe(struct platform_device *ofdev) 1498static int __devinit fsl_diu_probe(struct platform_device *pdev)
1475{ 1499{
1476 struct device_node *np = ofdev->dev.of_node; 1500 struct device_node *np = pdev->dev.of_node;
1477 struct mfb_info *mfbi; 1501 struct mfb_info *mfbi;
1478 phys_addr_t dummy_ad_addr; 1502 phys_addr_t dummy_ad_addr = 0;
1479 int ret, i, error = 0; 1503 int ret, i, error = 0;
1480 struct resource res;
1481 struct fsl_diu_data *machine_data; 1504 struct fsl_diu_data *machine_data;
1482 int diu_mode; 1505 int diu_mode;
1483 1506
@@ -1485,11 +1508,13 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev)
1485 if (!machine_data) 1508 if (!machine_data)
1486 return -ENOMEM; 1509 return -ENOMEM;
1487 1510
1511 spin_lock_init(&machine_data->reg_lock);
1512
1488 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { 1513 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
1489 machine_data->fsl_diu_info[i] = 1514 machine_data->fsl_diu_info[i] =
1490 framebuffer_alloc(sizeof(struct mfb_info), &ofdev->dev); 1515 framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev);
1491 if (!machine_data->fsl_diu_info[i]) { 1516 if (!machine_data->fsl_diu_info[i]) {
1492 dev_err(&ofdev->dev, "cannot allocate memory\n"); 1517 dev_err(&pdev->dev, "cannot allocate memory\n");
1493 ret = -ENOMEM; 1518 ret = -ENOMEM;
1494 goto error2; 1519 goto error2;
1495 } 1520 }
@@ -1497,7 +1522,7 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev)
1497 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); 1522 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
1498 mfbi->parent = machine_data; 1523 mfbi->parent = machine_data;
1499 1524
1500 if (mfbi->index == 0) { 1525 if (mfbi->index == PLANE0) {
1501 const u8 *prop; 1526 const u8 *prop;
1502 int len; 1527 int len;
1503 1528
@@ -1509,60 +1534,49 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev)
1509 } 1534 }
1510 } 1535 }
1511 1536
1512 ret = of_address_to_resource(np, 0, &res); 1537 machine_data->diu_reg = of_iomap(np, 0);
1513 if (ret) { 1538 if (!machine_data->diu_reg) {
1514 dev_err(&ofdev->dev, "could not obtain DIU address\n"); 1539 dev_err(&pdev->dev, "cannot map DIU registers\n");
1515 goto error;
1516 }
1517 if (!res.start) {
1518 dev_err(&ofdev->dev, "invalid DIU address\n");
1519 goto error;
1520 }
1521 dev_dbg(&ofdev->dev, "%s, res.start: 0x%08x\n", __func__, res.start);
1522
1523 dr.diu_reg = ioremap(res.start, sizeof(struct diu));
1524 if (!dr.diu_reg) {
1525 dev_err(&ofdev->dev, "Err: can't map DIU registers!\n");
1526 ret = -EFAULT; 1540 ret = -EFAULT;
1527 goto error2; 1541 goto error2;
1528 } 1542 }
1529 1543
1530 diu_mode = in_be32(&dr.diu_reg->diu_mode); 1544 diu_mode = in_be32(&machine_data->diu_reg->diu_mode);
1531 if (diu_mode != MFB_MODE1) 1545 if (diu_mode == MFB_MODE0)
1532 out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU */ 1546 out_be32(&machine_data->diu_reg->diu_mode, 0); /* disable DIU */
1533 1547
1534 /* Get the IRQ of the DIU */ 1548 /* Get the IRQ of the DIU */
1535 machine_data->irq = irq_of_parse_and_map(np, 0); 1549 machine_data->irq = irq_of_parse_and_map(np, 0);
1536 1550
1537 if (!machine_data->irq) { 1551 if (!machine_data->irq) {
1538 dev_err(&ofdev->dev, "could not get DIU IRQ\n"); 1552 dev_err(&pdev->dev, "could not get DIU IRQ\n");
1539 ret = -EINVAL; 1553 ret = -EINVAL;
1540 goto error; 1554 goto error;
1541 } 1555 }
1542 machine_data->monitor_port = monitor_port; 1556 machine_data->monitor_port = monitor_port;
1543 1557
1544 /* Area descriptor memory pool aligns to 64-bit boundary */ 1558 /* Area descriptor memory pool aligns to 64-bit boundary */
1545 if (allocate_buf(&ofdev->dev, &pool.ad, 1559 if (allocate_buf(&pdev->dev, &machine_data->ad,
1546 sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) 1560 sizeof(struct diu_ad) * FSL_AOI_NUM, 8))
1547 return -ENOMEM; 1561 return -ENOMEM;
1548 1562
1549 /* Get memory for Gamma Table - 32-byte aligned memory */ 1563 /* Get memory for Gamma Table - 32-byte aligned memory */
1550 if (allocate_buf(&ofdev->dev, &pool.gamma, 768, 32)) { 1564 if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) {
1551 ret = -ENOMEM; 1565 ret = -ENOMEM;
1552 goto error; 1566 goto error;
1553 } 1567 }
1554 1568
1555 /* For performance, cursor bitmap buffer aligns to 32-byte boundary */ 1569 /* For performance, cursor bitmap buffer aligns to 32-byte boundary */
1556 if (allocate_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2, 1570 if (allocate_buf(&pdev->dev, &machine_data->cursor,
1557 32)) { 1571 MAX_CURS * MAX_CURS * 2, 32)) {
1558 ret = -ENOMEM; 1572 ret = -ENOMEM;
1559 goto error; 1573 goto error;
1560 } 1574 }
1561 1575
1562 i = ARRAY_SIZE(machine_data->fsl_diu_info); 1576 i = ARRAY_SIZE(machine_data->fsl_diu_info);
1563 machine_data->dummy_ad = (struct diu_ad *) 1577 machine_data->dummy_ad = (struct diu_ad *)((u32)machine_data->ad.vaddr +
1564 ((u32)pool.ad.vaddr + pool.ad.offset) + i; 1578 machine_data->ad.offset) + i;
1565 machine_data->dummy_ad->paddr = pool.ad.paddr + 1579 machine_data->dummy_ad->paddr = machine_data->ad.paddr +
1566 i * sizeof(struct diu_ad); 1580 i * sizeof(struct diu_ad);
1567 machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr); 1581 machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr);
1568 if (!machine_data->dummy_aoi_virt) { 1582 if (!machine_data->dummy_aoi_virt) {
@@ -1581,30 +1595,29 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev)
1581 * Let DIU display splash screen if it was pre-initialized 1595 * Let DIU display splash screen if it was pre-initialized
1582 * by the bootloader, set dummy area descriptor otherwise. 1596 * by the bootloader, set dummy area descriptor otherwise.
1583 */ 1597 */
1584 if (diu_mode != MFB_MODE1) 1598 if (diu_mode == MFB_MODE0)
1585 out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr); 1599 out_be32(&machine_data->diu_reg->desc[0],
1600 machine_data->dummy_ad->paddr);
1586 1601
1587 out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr); 1602 out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad->paddr);
1588 out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr); 1603 out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad->paddr);
1589 1604
1590 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { 1605 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
1591 machine_data->fsl_diu_info[i]->fix.smem_start = 0; 1606 machine_data->fsl_diu_info[i]->fix.smem_start = 0;
1592 mfbi = machine_data->fsl_diu_info[i]->par; 1607 mfbi = machine_data->fsl_diu_info[i]->par;
1593 mfbi->ad = (struct diu_ad *)((u32)pool.ad.vaddr 1608 mfbi->ad = (struct diu_ad *)((u32)machine_data->ad.vaddr
1594 + pool.ad.offset) + i; 1609 + machine_data->ad.offset) + i;
1595 mfbi->ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad); 1610 mfbi->ad->paddr =
1611 machine_data->ad.paddr + i * sizeof(struct diu_ad);
1596 ret = install_fb(machine_data->fsl_diu_info[i]); 1612 ret = install_fb(machine_data->fsl_diu_info[i]);
1597 if (ret) { 1613 if (ret) {
1598 dev_err(&ofdev->dev, 1614 dev_err(&pdev->dev, "could not register fb %d\n", i);
1599 "Failed to register framebuffer %d\n",
1600 i);
1601 goto error; 1615 goto error;
1602 } 1616 }
1603 } 1617 }
1604 1618
1605 if (request_irq_local(machine_data->irq)) { 1619 if (request_irq_local(machine_data)) {
1606 dev_err(machine_data->fsl_diu_info[0]->dev, 1620 dev_err(&pdev->dev, "could not claim irq\n");
1607 "could not request irq for diu.");
1608 goto error; 1621 goto error;
1609 } 1622 }
1610 1623
@@ -1616,29 +1629,28 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev)
1616 error = device_create_file(machine_data->fsl_diu_info[0]->dev, 1629 error = device_create_file(machine_data->fsl_diu_info[0]->dev,
1617 &machine_data->dev_attr); 1630 &machine_data->dev_attr);
1618 if (error) { 1631 if (error) {
1619 dev_err(machine_data->fsl_diu_info[0]->dev, 1632 dev_err(&pdev->dev, "could not create sysfs file %s\n",
1620 "could not create sysfs %s file\n",
1621 machine_data->dev_attr.attr.name); 1633 machine_data->dev_attr.attr.name);
1622 } 1634 }
1623 1635
1624 dev_set_drvdata(&ofdev->dev, machine_data); 1636 dev_set_drvdata(&pdev->dev, machine_data);
1625 return 0; 1637 return 0;
1626 1638
1627error: 1639error:
1628 for (i = ARRAY_SIZE(machine_data->fsl_diu_info); 1640 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
1629 i > 0; i--) 1641 uninstall_fb(machine_data->fsl_diu_info[i]);
1630 uninstall_fb(machine_data->fsl_diu_info[i - 1]); 1642
1631 if (pool.ad.vaddr) 1643 if (machine_data->ad.vaddr)
1632 free_buf(&ofdev->dev, &pool.ad, 1644 free_buf(&pdev->dev, &machine_data->ad,
1633 sizeof(struct diu_ad) * FSL_AOI_NUM, 8); 1645 sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
1634 if (pool.gamma.vaddr) 1646 if (machine_data->gamma.vaddr)
1635 free_buf(&ofdev->dev, &pool.gamma, 768, 32); 1647 free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
1636 if (pool.cursor.vaddr) 1648 if (machine_data->cursor.vaddr)
1637 free_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2, 1649 free_buf(&pdev->dev, &machine_data->cursor,
1638 32); 1650 MAX_CURS * MAX_CURS * 2, 32);
1639 if (machine_data->dummy_aoi_virt) 1651 if (machine_data->dummy_aoi_virt)
1640 fsl_diu_free(machine_data->dummy_aoi_virt, 64); 1652 fsl_diu_free(machine_data->dummy_aoi_virt, 64);
1641 iounmap(dr.diu_reg); 1653 iounmap(machine_data->diu_reg);
1642 1654
1643error2: 1655error2:
1644 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1656 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
@@ -1649,28 +1661,27 @@ error2:
1649 return ret; 1661 return ret;
1650} 1662}
1651 1663
1652 1664static int fsl_diu_remove(struct platform_device *pdev)
1653static int fsl_diu_remove(struct platform_device *ofdev)
1654{ 1665{
1655 struct fsl_diu_data *machine_data; 1666 struct fsl_diu_data *machine_data;
1656 int i; 1667 int i;
1657 1668
1658 machine_data = dev_get_drvdata(&ofdev->dev); 1669 machine_data = dev_get_drvdata(&pdev->dev);
1659 disable_lcdc(machine_data->fsl_diu_info[0]); 1670 disable_lcdc(machine_data->fsl_diu_info[0]);
1660 free_irq_local(machine_data->irq); 1671 free_irq_local(machine_data);
1661 for (i = ARRAY_SIZE(machine_data->fsl_diu_info); i > 0; i--) 1672 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
1662 uninstall_fb(machine_data->fsl_diu_info[i - 1]); 1673 uninstall_fb(machine_data->fsl_diu_info[i]);
1663 if (pool.ad.vaddr) 1674 if (machine_data->ad.vaddr)
1664 free_buf(&ofdev->dev, &pool.ad, 1675 free_buf(&pdev->dev, &machine_data->ad,
1665 sizeof(struct diu_ad) * FSL_AOI_NUM, 8); 1676 sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
1666 if (pool.gamma.vaddr) 1677 if (machine_data->gamma.vaddr)
1667 free_buf(&ofdev->dev, &pool.gamma, 768, 32); 1678 free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
1668 if (pool.cursor.vaddr) 1679 if (machine_data->cursor.vaddr)
1669 free_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2, 1680 free_buf(&pdev->dev, &machine_data->cursor,
1670 32); 1681 MAX_CURS * MAX_CURS * 2, 32);
1671 if (machine_data->dummy_aoi_virt) 1682 if (machine_data->dummy_aoi_virt)
1672 fsl_diu_free(machine_data->dummy_aoi_virt, 64); 1683 fsl_diu_free(machine_data->dummy_aoi_virt, 64);
1673 iounmap(dr.diu_reg); 1684 iounmap(machine_data->diu_reg);
1674 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1685 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
1675 if (machine_data->fsl_diu_info[i]) 1686 if (machine_data->fsl_diu_info[i])
1676 framebuffer_release(machine_data->fsl_diu_info[i]); 1687 framebuffer_release(machine_data->fsl_diu_info[i]);
@@ -1692,8 +1703,7 @@ static int __init fsl_diu_setup(char *options)
1692 if (!*opt) 1703 if (!*opt)
1693 continue; 1704 continue;
1694 if (!strncmp(opt, "monitor=", 8)) { 1705 if (!strncmp(opt, "monitor=", 8)) {
1695 if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2)) 1706 monitor_port = fsl_diu_name_to_port(opt + 8);
1696 monitor_port = val;
1697 } else if (!strncmp(opt, "bpp=", 4)) { 1707 } else if (!strncmp(opt, "bpp=", 4)) {
1698 if (!strict_strtoul(opt + 4, 10, &val)) 1708 if (!strict_strtoul(opt + 4, 10, &val))
1699 default_bpp = val; 1709 default_bpp = val;
@@ -1720,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, fsl_diu_match);
1720 1730
1721static struct platform_driver fsl_diu_driver = { 1731static struct platform_driver fsl_diu_driver = {
1722 .driver = { 1732 .driver = {
1723 .name = "fsl_diu", 1733 .name = "fsl-diu-fb",
1724 .owner = THIS_MODULE, 1734 .owner = THIS_MODULE,
1725 .of_match_table = fsl_diu_match, 1735 .of_match_table = fsl_diu_match,
1726 }, 1736 },
@@ -1746,48 +1756,54 @@ static int __init fsl_diu_init(void)
1746 if (fb_get_options("fslfb", &option)) 1756 if (fb_get_options("fslfb", &option))
1747 return -ENODEV; 1757 return -ENODEV;
1748 fsl_diu_setup(option); 1758 fsl_diu_setup(option);
1759#else
1760 monitor_port = fsl_diu_name_to_port(monitor_string);
1749#endif 1761#endif
1750 printk(KERN_INFO "Freescale DIU driver\n"); 1762 pr_info("Freescale Display Interface Unit (DIU) framebuffer driver\n");
1751 1763
1752#ifdef CONFIG_NOT_COHERENT_CACHE 1764#ifdef CONFIG_NOT_COHERENT_CACHE
1753 np = of_find_node_by_type(NULL, "cpu"); 1765 np = of_find_node_by_type(NULL, "cpu");
1754 if (!np) { 1766 if (!np) {
1755 printk(KERN_ERR "Err: can't find device node 'cpu'\n"); 1767 pr_err("fsl-diu-fb: can't find 'cpu' device node\n");
1756 return -ENODEV; 1768 return -ENODEV;
1757 } 1769 }
1758 1770
1759 prop = of_get_property(np, "d-cache-size", NULL); 1771 prop = of_get_property(np, "d-cache-size", NULL);
1760 if (prop == NULL) { 1772 if (prop == NULL) {
1773 pr_err("fsl-diu-fb: missing 'd-cache-size' property' "
1774 "in 'cpu' node\n");
1761 of_node_put(np); 1775 of_node_put(np);
1762 return -ENODEV; 1776 return -ENODEV;
1763 } 1777 }
1764 1778
1765 /* Freescale PLRU requires 13/8 times the cache size to do a proper 1779 /*
1766 displacement flush 1780 * Freescale PLRU requires 13/8 times the cache size to do a proper
1781 * displacement flush
1767 */ 1782 */
1768 coherence_data_size = *prop * 13; 1783 coherence_data_size = be32_to_cpup(prop) * 13;
1769 coherence_data_size /= 8; 1784 coherence_data_size /= 8;
1770 1785
1771 prop = of_get_property(np, "d-cache-line-size", NULL); 1786 prop = of_get_property(np, "d-cache-line-size", NULL);
1772 if (prop == NULL) { 1787 if (prop == NULL) {
1788 pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
1789 "in 'cpu' node\n");
1773 of_node_put(np); 1790 of_node_put(np);
1774 return -ENODEV; 1791 return -ENODEV;
1775 } 1792 }
1776 d_cache_line_size = *prop; 1793 d_cache_line_size = be32_to_cpup(prop);
1777 1794
1778 of_node_put(np); 1795 of_node_put(np);
1779 coherence_data = vmalloc(coherence_data_size); 1796 coherence_data = vmalloc(coherence_data_size);
1780 if (!coherence_data) 1797 if (!coherence_data)
1781 return -ENOMEM; 1798 return -ENOMEM;
1782#endif 1799#endif
1800
1783 ret = platform_driver_register(&fsl_diu_driver); 1801 ret = platform_driver_register(&fsl_diu_driver);
1784 if (ret) { 1802 if (ret) {
1785 printk(KERN_ERR 1803 pr_err("fsl-diu-fb: failed to register platform driver\n");
1786 "fsl-diu: failed to register platform driver\n");
1787#if defined(CONFIG_NOT_COHERENT_CACHE) 1804#if defined(CONFIG_NOT_COHERENT_CACHE)
1788 vfree(coherence_data); 1805 vfree(coherence_data);
1789#endif 1806#endif
1790 iounmap(dr.diu_reg);
1791 } 1807 }
1792 return ret; 1808 return ret;
1793} 1809}
@@ -1811,8 +1827,8 @@ module_param_named(mode, fb_mode, charp, 0);
1811MODULE_PARM_DESC(mode, 1827MODULE_PARM_DESC(mode,
1812 "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); 1828 "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
1813module_param_named(bpp, default_bpp, ulong, 0); 1829module_param_named(bpp, default_bpp, ulong, 0);
1814MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode"); 1830MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified in 'mode'");
1815module_param_named(monitor, monitor_port, int, 0); 1831module_param_named(monitor, monitor_string, charp, 0);
1816MODULE_PARM_DESC(monitor, 1832MODULE_PARM_DESC(monitor, "Specify the monitor port "
1817 "Specify the monitor port (0, 1 or 2) if supported by the platform"); 1833 "(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform");
1818 1834
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c
index d662317d85e..223896cc5f7 100644
--- a/drivers/video/g364fb.c
+++ b/drivers/video/g364fb.c
@@ -149,10 +149,11 @@ int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
149static int g364fb_pan_display(struct fb_var_screeninfo *var, 149static int g364fb_pan_display(struct fb_var_screeninfo *var,
150 struct fb_info *info) 150 struct fb_info *info)
151{ 151{
152 if (var->xoffset || var->yoffset + var->yres > var->yres_virtual) 152 if (var->xoffset ||
153 var->yoffset + info->var.yres > info->var.yres_virtual)
153 return -EINVAL; 154 return -EINVAL;
154 155
155 *(unsigned int *) TOP_REG = var->yoffset * var->xres; 156 *(unsigned int *) TOP_REG = var->yoffset * info->var.xres;
156 return 0; 157 return 0;
157} 158}
158 159
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c
new file mode 100644
index 00000000000..f37e0253820
--- /dev/null
+++ b/drivers/video/grvga.c
@@ -0,0 +1,579 @@
1/*
2 * Driver for Aeroflex Gaisler SVGACTRL framebuffer device.
3 *
4 * 2011 (c) Aeroflex Gaisler AB
5 *
6 * Full documentation of the core can be found here:
7 * http://www.gaisler.com/products/grlib/grip.pdf
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * Contributors: Kristoffer Glembo <kristoffer@gaisler.com>
15 *
16 */
17
18#include <linux/platform_device.h>
19#include <linux/dma-mapping.h>
20#include <linux/of_platform.h>
21#include <linux/of_device.h>
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/string.h>
25#include <linux/delay.h>
26#include <linux/errno.h>
27#include <linux/init.h>
28#include <linux/slab.h>
29#include <linux/tty.h>
30#include <linux/mm.h>
31#include <linux/fb.h>
32#include <linux/io.h>
33
34struct grvga_regs {
35 u32 status; /* 0x00 */
36 u32 video_length; /* 0x04 */
37 u32 front_porch; /* 0x08 */
38 u32 sync_length; /* 0x0C */
39 u32 line_length; /* 0x10 */
40 u32 fb_pos; /* 0x14 */
41 u32 clk_vector[4]; /* 0x18 */
42 u32 clut; /* 0x20 */
43};
44
45struct grvga_par {
46 struct grvga_regs *regs;
47 u32 color_palette[16]; /* 16 entry pseudo palette used by fbcon in true color mode */
48 int clk_sel;
49 int fb_alloced; /* = 1 if framebuffer is allocated in main memory */
50};
51
52
53static const struct fb_videomode grvga_modedb[] = {
54 {
55 /* 640x480 @ 60 Hz */
56 NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2,
57 0, FB_VMODE_NONINTERLACED
58 }, {
59 /* 800x600 @ 60 Hz */
60 NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
61 0, FB_VMODE_NONINTERLACED
62 }, {
63 /* 800x600 @ 72 Hz */
64 NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
65 0, FB_VMODE_NONINTERLACED
66 }, {
67 /* 1024x768 @ 60 Hz */
68 NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
69 0, FB_VMODE_NONINTERLACED
70 }
71 };
72
73static struct fb_fix_screeninfo grvga_fix __initdata = {
74 .id = "AG SVGACTRL",
75 .type = FB_TYPE_PACKED_PIXELS,
76 .visual = FB_VISUAL_PSEUDOCOLOR,
77 .xpanstep = 0,
78 .ypanstep = 1,
79 .ywrapstep = 0,
80 .accel = FB_ACCEL_NONE,
81};
82
83static int grvga_check_var(struct fb_var_screeninfo *var,
84 struct fb_info *info)
85{
86 struct grvga_par *par = info->par;
87 int i;
88
89 if (!var->xres)
90 var->xres = 1;
91 if (!var->yres)
92 var->yres = 1;
93 if (var->bits_per_pixel <= 8)
94 var->bits_per_pixel = 8;
95 else if (var->bits_per_pixel <= 16)
96 var->bits_per_pixel = 16;
97 else if (var->bits_per_pixel <= 24)
98 var->bits_per_pixel = 24;
99 else if (var->bits_per_pixel <= 32)
100 var->bits_per_pixel = 32;
101 else
102 return -EINVAL;
103
104 var->xres_virtual = var->xres;
105 var->yres_virtual = 2*var->yres;
106
107 if (info->fix.smem_len) {
108 if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len)
109 return -ENOMEM;
110 }
111
112 /* Which clocks that are available can be read out in these registers */
113 for (i = 0; i <= 3 ; i++) {
114 if (var->pixclock == par->regs->clk_vector[i])
115 break;
116 }
117 if (i <= 3)
118 par->clk_sel = i;
119 else
120 return -EINVAL;
121
122 switch (info->var.bits_per_pixel) {
123 case 8:
124 var->red = (struct fb_bitfield) {0, 8, 0}; /* offset, length, msb-right */
125 var->green = (struct fb_bitfield) {0, 8, 0};
126 var->blue = (struct fb_bitfield) {0, 8, 0};
127 var->transp = (struct fb_bitfield) {0, 0, 0};
128 break;
129 case 16:
130 var->red = (struct fb_bitfield) {11, 5, 0};
131 var->green = (struct fb_bitfield) {5, 6, 0};
132 var->blue = (struct fb_bitfield) {0, 5, 0};
133 var->transp = (struct fb_bitfield) {0, 0, 0};
134 break;
135 case 24:
136 case 32:
137 var->red = (struct fb_bitfield) {16, 8, 0};
138 var->green = (struct fb_bitfield) {8, 8, 0};
139 var->blue = (struct fb_bitfield) {0, 8, 0};
140 var->transp = (struct fb_bitfield) {24, 8, 0};
141 break;
142 default:
143 return -EINVAL;
144 }
145
146 return 0;
147}
148
149static int grvga_set_par(struct fb_info *info)
150{
151
152 u32 func = 0;
153 struct grvga_par *par = info->par;
154
155 __raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1),
156 &par->regs->video_length);
157
158 __raw_writel((info->var.lower_margin << 16) | (info->var.right_margin),
159 &par->regs->front_porch);
160
161 __raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len),
162 &par->regs->sync_length);
163
164 __raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) |
165 (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1),
166 &par->regs->line_length);
167
168 switch (info->var.bits_per_pixel) {
169 case 8:
170 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
171 func = 1;
172 break;
173 case 16:
174 info->fix.visual = FB_VISUAL_TRUECOLOR;
175 func = 2;
176 break;
177 case 24:
178 case 32:
179 info->fix.visual = FB_VISUAL_TRUECOLOR;
180 func = 3;
181 break;
182 default:
183 return -EINVAL;
184 }
185
186 __raw_writel((par->clk_sel << 6) | (func << 4) | 1,
187 &par->regs->status);
188
189 info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8;
190 return 0;
191}
192
193static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info)
194{
195 struct grvga_par *par;
196 par = info->par;
197
198 if (regno >= 256) /* Size of CLUT */
199 return -EINVAL;
200
201 if (info->var.grayscale) {
202 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
203 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
204 }
205
206
207
208#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
209
210 red = CNVT_TOHW(red, info->var.red.length);
211 green = CNVT_TOHW(green, info->var.green.length);
212 blue = CNVT_TOHW(blue, info->var.blue.length);
213 transp = CNVT_TOHW(transp, info->var.transp.length);
214
215#undef CNVT_TOHW
216
217 /* In PSEUDOCOLOR we use the hardware CLUT */
218 if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
219 __raw_writel((regno << 24) | (red << 16) | (green << 8) | blue,
220 &par->regs->clut);
221
222 /* Truecolor uses the pseudo palette */
223 else if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
224 u32 v;
225 if (regno >= 16)
226 return -EINVAL;
227
228
229 v = (red << info->var.red.offset) |
230 (green << info->var.green.offset) |
231 (blue << info->var.blue.offset) |
232 (transp << info->var.transp.offset);
233
234 ((u32 *) (info->pseudo_palette))[regno] = v;
235 }
236 return 0;
237}
238
239static int grvga_pan_display(struct fb_var_screeninfo *var,
240 struct fb_info *info)
241{
242 struct grvga_par *par = info->par;
243 struct fb_fix_screeninfo *fix = &info->fix;
244 u32 base_addr;
245
246 if (var->xoffset != 0)
247 return -EINVAL;
248
249 base_addr = fix->smem_start + (var->yoffset * fix->line_length);
250 base_addr &= ~3UL;
251
252 /* Set framebuffer base address */
253 __raw_writel(base_addr,
254 &par->regs->fb_pos);
255
256 return 0;
257}
258
259static struct fb_ops grvga_ops = {
260 .owner = THIS_MODULE,
261 .fb_check_var = grvga_check_var,
262 .fb_set_par = grvga_set_par,
263 .fb_setcolreg = grvga_setcolreg,
264 .fb_pan_display = grvga_pan_display,
265 .fb_fillrect = cfb_fillrect,
266 .fb_copyarea = cfb_copyarea,
267 .fb_imageblit = cfb_imageblit
268};
269
270static int __init grvga_parse_custom(char *options,
271 struct fb_var_screeninfo *screendata)
272{
273 char *this_opt;
274 int count = 0;
275 if (!options || !*options)
276 return -1;
277
278 while ((this_opt = strsep(&options, " ")) != NULL) {
279 if (!*this_opt)
280 continue;
281
282 switch (count) {
283 case 0:
284 screendata->pixclock = simple_strtoul(this_opt, NULL, 0);
285 count++;
286 break;
287 case 1:
288 screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0);
289 count++;
290 break;
291 case 2:
292 screendata->right_margin = simple_strtoul(this_opt, NULL, 0);
293 count++;
294 break;
295 case 3:
296 screendata->hsync_len = simple_strtoul(this_opt, NULL, 0);
297 count++;
298 break;
299 case 4:
300 screendata->left_margin = simple_strtoul(this_opt, NULL, 0);
301 count++;
302 break;
303 case 5:
304 screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0);
305 count++;
306 break;
307 case 6:
308 screendata->lower_margin = simple_strtoul(this_opt, NULL, 0);
309 count++;
310 break;
311 case 7:
312 screendata->vsync_len = simple_strtoul(this_opt, NULL, 0);
313 count++;
314 break;
315 case 8:
316 screendata->upper_margin = simple_strtoul(this_opt, NULL, 0);
317 count++;
318 break;
319 case 9:
320 screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0);
321 count++;
322 break;
323 default:
324 return -1;
325 }
326 }
327 screendata->activate = FB_ACTIVATE_NOW;
328 screendata->vmode = FB_VMODE_NONINTERLACED;
329 return 0;
330}
331
332static int __devinit grvga_probe(struct platform_device *dev)
333{
334 struct fb_info *info;
335 int retval = -ENOMEM;
336 unsigned long virtual_start;
337 unsigned long grvga_fix_addr = 0;
338 unsigned long physical_start = 0;
339 unsigned long grvga_mem_size = 0;
340 struct grvga_par *par = NULL;
341 char *options = NULL, *mode_opt = NULL;
342
343 info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev);
344 if (!info) {
345 dev_err(&dev->dev, "framebuffer_alloc failed\n");
346 return -ENOMEM;
347 }
348
349 /* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>]
350 *
351 * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters
352 * If address is left out, we allocate memory,
353 * if size is left out we only allocate enough to support the given mode.
354 */
355 if (fb_get_options("grvga", &options)) {
356 retval = -ENODEV;
357 goto err;
358 }
359
360 if (!options || !*options)
361 options = "640x480-8@60";
362
363 while (1) {
364 char *this_opt = strsep(&options, ",");
365
366 if (!this_opt)
367 break;
368
369 if (!strncmp(this_opt, "custom", 6)) {
370 if (grvga_parse_custom(this_opt, &info->var) < 0) {
371 dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt);
372 retval = -EINVAL;
373 goto err1;
374 }
375 } else if (!strncmp(this_opt, "addr", 4))
376 grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16);
377 else if (!strncmp(this_opt, "size", 4))
378 grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0);
379 else
380 mode_opt = this_opt;
381 }
382
383 par = info->par;
384 info->fbops = &grvga_ops;
385 info->fix = grvga_fix;
386 info->pseudo_palette = par->color_palette;
387 info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
388 info->fix.smem_len = grvga_mem_size;
389
390 if (!request_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]), "grlib-svgactrl regs")) {
391 dev_err(&dev->dev, "registers already mapped\n");
392 retval = -EBUSY;
393 goto err;
394 }
395
396 par->regs = of_ioremap(&dev->resource[0], 0,
397 resource_size(&dev->resource[0]),
398 "grlib-svgactrl regs");
399
400 if (!par->regs) {
401 dev_err(&dev->dev, "failed to map registers\n");
402 retval = -ENOMEM;
403 goto err1;
404 }
405
406 retval = fb_alloc_cmap(&info->cmap, 256, 0);
407 if (retval < 0) {
408 dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n");
409 retval = -ENOMEM;
410 goto err2;
411 }
412
413 if (mode_opt) {
414 retval = fb_find_mode(&info->var, info, mode_opt,
415 grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8);
416 if (!retval || retval == 4) {
417 retval = -EINVAL;
418 goto err3;
419 }
420 }
421
422 if (!grvga_mem_size)
423 grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8;
424
425 if (grvga_fix_addr) {
426 /* Got framebuffer base address from argument list */
427
428 physical_start = grvga_fix_addr;
429
430 if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) {
431 dev_err(&dev->dev, "failed to request memory region\n");
432 retval = -ENOMEM;
433 goto err3;
434 }
435
436 virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size);
437
438 if (!virtual_start) {
439 dev_err(&dev->dev, "error mapping framebuffer memory\n");
440 retval = -ENOMEM;
441 goto err4;
442 }
443 } else { /* Allocate frambuffer memory */
444
445 unsigned long page;
446
447 virtual_start = (unsigned long) __get_free_pages(GFP_DMA,
448 get_order(grvga_mem_size));
449 if (!virtual_start) {
450 dev_err(&dev->dev,
451 "unable to allocate framebuffer memory (%lu bytes)\n",
452 grvga_mem_size);
453 retval = -ENOMEM;
454 goto err3;
455 }
456
457 physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE);
458
459 /* Set page reserved so that mmap will work. This is necessary
460 * since we'll be remapping normal memory.
461 */
462 for (page = virtual_start;
463 page < PAGE_ALIGN(virtual_start + grvga_mem_size);
464 page += PAGE_SIZE) {
465 SetPageReserved(virt_to_page(page));
466 }
467
468 par->fb_alloced = 1;
469 }
470
471 memset((unsigned long *) virtual_start, 0, grvga_mem_size);
472
473 info->screen_base = (char __iomem *) virtual_start;
474 info->fix.smem_start = physical_start;
475 info->fix.smem_len = grvga_mem_size;
476
477 dev_set_drvdata(&dev->dev, info);
478
479 dev_info(&dev->dev,
480 "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n",
481 info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel,
482 grvga_mem_size >> 10, info->screen_base);
483
484 retval = register_framebuffer(info);
485 if (retval < 0) {
486 dev_err(&dev->dev, "failed to register framebuffer\n");
487 goto err4;
488 }
489
490 __raw_writel(physical_start, &par->regs->fb_pos);
491 __raw_writel(__raw_readl(&par->regs->status) | 1, /* Enable framebuffer */
492 &par->regs->status);
493
494 return 0;
495
496err4:
497 dev_set_drvdata(&dev->dev, NULL);
498 if (grvga_fix_addr) {
499 release_mem_region(physical_start, grvga_mem_size);
500 iounmap((void *)virtual_start);
501 } else
502 kfree((void *)virtual_start);
503err3:
504 fb_dealloc_cmap(&info->cmap);
505err2:
506 of_iounmap(&dev->resource[0], par->regs,
507 resource_size(&dev->resource[0]));
508err1:
509 release_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]));
510err:
511 framebuffer_release(info);
512
513 return retval;
514}
515
516static int __devexit grvga_remove(struct platform_device *device)
517{
518 struct fb_info *info = dev_get_drvdata(&device->dev);
519 struct grvga_par *par = info->par;
520
521 if (info) {
522 unregister_framebuffer(info);
523 fb_dealloc_cmap(&info->cmap);
524
525 of_iounmap(&device->resource[0], par->regs,
526 resource_size(&device->resource[0]));
527 release_mem_region(device->resource[0].start, resource_size(&device->resource[0]));
528
529 if (!par->fb_alloced) {
530 release_mem_region(info->fix.smem_start, info->fix.smem_len);
531 iounmap(info->screen_base);
532 } else
533 kfree((void *)info->screen_base);
534
535 framebuffer_release(info);
536 dev_set_drvdata(&device->dev, NULL);
537 }
538
539 return 0;
540}
541
542static struct of_device_id svgactrl_of_match[] = {
543 {
544 .name = "GAISLER_SVGACTRL",
545 },
546 {
547 .name = "01_063",
548 },
549 {},
550};
551MODULE_DEVICE_TABLE(of, svgactrl_of_match);
552
553static struct platform_driver grvga_driver = {
554 .driver = {
555 .name = "grlib-svgactrl",
556 .owner = THIS_MODULE,
557 .of_match_table = svgactrl_of_match,
558 },
559 .probe = grvga_probe,
560 .remove = __devexit_p(grvga_remove),
561};
562
563
564static int __init grvga_init(void)
565{
566 return platform_driver_register(&grvga_driver);
567}
568
569static void __exit grvga_exit(void)
570{
571 platform_driver_unregister(&grvga_driver);
572}
573
574module_init(grvga_init);
575module_exit(grvga_exit);
576
577MODULE_LICENSE("GPL");
578MODULE_AUTHOR("Aeroflex Gaisler");
579MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver");
diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c
index 896e53dea90..0fad23f810a 100644
--- a/drivers/video/gxt4500.c
+++ b/drivers/video/gxt4500.c
@@ -543,8 +543,8 @@ static int gxt4500_pan_display(struct fb_var_screeninfo *var,
543 543
544 if (var->xoffset & 7) 544 if (var->xoffset & 7)
545 return -EINVAL; 545 return -EINVAL;
546 if (var->xoffset + var->xres > var->xres_virtual || 546 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
547 var->yoffset + var->yres > var->yres_virtual) 547 var->yoffset + info->var.yres > info->var.yres_virtual)
548 return -EINVAL; 548 return -EINVAL;
549 549
550 writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); 550 writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index 4052718eefa..4394389caf6 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -422,8 +422,8 @@ static int hgafb_pan_display(struct fb_var_screeninfo *var,
422 var->xoffset) 422 var->xoffset)
423 return -EINVAL; 423 return -EINVAL;
424 } else { 424 } else {
425 if (var->xoffset + var->xres > info->var.xres_virtual 425 if (var->xoffset + info->var.xres > info->var.xres_virtual
426 || var->yoffset + var->yres > info->var.yres_virtual 426 || var->yoffset + info->var.yres > info->var.yres_virtual
427 || var->yoffset % 8) 427 || var->yoffset % 8)
428 return -EINVAL; 428 return -EINVAL;
429 } 429 }
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index efb2c10656b..8149356471e 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -749,7 +749,7 @@ set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
749{ 749{
750 struct imstt_par *par = info->par; 750 struct imstt_par *par = info->par;
751 __u32 off = var->yoffset * (info->fix.line_length >> 3) 751 __u32 off = var->yoffset * (info->fix.line_length >> 3)
752 + ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3); 752 + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3);
753 write_reg_le32(par->dc_regs, SSR, off); 753 write_reg_le32(par->dc_regs, SSR, off);
754} 754}
755 755
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 38065cf94ac..fbad61da359 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -390,12 +390,12 @@ int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
390 xoffset = ROUND_DOWN_TO(var->xoffset, 8); 390 xoffset = ROUND_DOWN_TO(var->xoffset, 8);
391 yoffset = var->yoffset; 391 yoffset = var->yoffset;
392 392
393 if ((xoffset + var->xres > var->xres_virtual) || 393 if ((xoffset + info->var.xres > info->var.xres_virtual) ||
394 (yoffset + var->yres > var->yres_virtual)) 394 (yoffset + info->var.yres > info->var.yres_virtual))
395 return -EINVAL; 395 return -EINVAL;
396 396
397 offset = (yoffset * dinfo->pitch) + 397 offset = (yoffset * dinfo->pitch) +
398 (xoffset * var->bits_per_pixel) / 8; 398 (xoffset * info->var.bits_per_pixel) / 8;
399 399
400 offset += dinfo->fb.offset << 12; 400 offset += dinfo->fb.offset << 12;
401 401
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c
index b953099edd8..934081d2b7a 100644
--- a/drivers/video/mb862xx/mb862xx-i2c.c
+++ b/drivers/video/mb862xx/mb862xx-i2c.c
@@ -23,7 +23,7 @@ static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
23 u32 reg; 23 u32 reg;
24 24
25 do { 25 do {
26 udelay(1); 26 udelay(10);
27 reg = inreg(i2c, GC_I2C_BCR); 27 reg = inreg(i2c, GC_I2C_BCR);
28 if (reg & (I2C_INT | I2C_BER)) 28 if (reg & (I2C_INT | I2C_BER))
29 break; 29 break;
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
index ee1de3e26de..c16ff1d62e9 100644
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/mb862xx/mb862xxfbdrv.c
@@ -278,7 +278,7 @@ static int mb862xxfb_pan(struct fb_var_screeninfo *var,
278 reg = pack(var->yoffset, var->xoffset); 278 reg = pack(var->yoffset, var->xoffset);
279 outreg(disp, GC_L0WY_L0WX, reg); 279 outreg(disp, GC_L0WY_L0WX, reg);
280 280
281 reg = pack(var->yres_virtual, var->xres_virtual); 281 reg = pack(info->var.yres_virtual, info->var.xres_virtual);
282 outreg(disp, GC_L0WH_L0WW, reg); 282 outreg(disp, GC_L0WH_L0WW, reg);
283 return 0; 283 return 0;
284} 284}
@@ -737,7 +737,7 @@ static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
737 if (mb862xx_gdc_init(par)) 737 if (mb862xx_gdc_init(par))
738 goto io_unmap; 738 goto io_unmap;
739 739
740 if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED, 740 if (request_irq(par->irq, mb862xx_intr, 0,
741 DRV_NAME, (void *)par)) { 741 DRV_NAME, (void *)par)) {
742 dev_err(dev, "Cannot request irq\n"); 742 dev_err(dev, "Cannot request irq\n");
743 goto io_unmap; 743 goto io_unmap;
@@ -1073,7 +1073,7 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
1073 if (mb862xx_pci_gdc_init(par)) 1073 if (mb862xx_pci_gdc_init(par))
1074 goto io_unmap; 1074 goto io_unmap;
1075 1075
1076 if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED, 1076 if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
1077 DRV_NAME, (void *)par)) { 1077 DRV_NAME, (void *)par)) {
1078 dev_err(dev, "Cannot request irq\n"); 1078 dev_err(dev, "Cannot request irq\n");
1079 goto io_unmap; 1079 goto io_unmap;
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index cb175fe7abc..a9a907c440d 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -491,55 +491,56 @@ EXPORT_SYMBOL(vesa_modes);
491static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, 491static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
492 const struct fb_videomode *mode, unsigned int bpp) 492 const struct fb_videomode *mode, unsigned int bpp)
493{ 493{
494 int err = 0; 494 int err = 0;
495 495
496 DPRINTK("Trying mode %s %dx%d-%d@%d\n", mode->name ? mode->name : "noname", 496 DPRINTK("Trying mode %s %dx%d-%d@%d\n",
497 mode->xres, mode->yres, bpp, mode->refresh); 497 mode->name ? mode->name : "noname",
498 var->xres = mode->xres; 498 mode->xres, mode->yres, bpp, mode->refresh);
499 var->yres = mode->yres; 499 var->xres = mode->xres;
500 var->xres_virtual = mode->xres; 500 var->yres = mode->yres;
501 var->yres_virtual = mode->yres; 501 var->xres_virtual = mode->xres;
502 var->xoffset = 0; 502 var->yres_virtual = mode->yres;
503 var->yoffset = 0; 503 var->xoffset = 0;
504 var->bits_per_pixel = bpp; 504 var->yoffset = 0;
505 var->activate |= FB_ACTIVATE_TEST; 505 var->bits_per_pixel = bpp;
506 var->pixclock = mode->pixclock; 506 var->activate |= FB_ACTIVATE_TEST;
507 var->left_margin = mode->left_margin; 507 var->pixclock = mode->pixclock;
508 var->right_margin = mode->right_margin; 508 var->left_margin = mode->left_margin;
509 var->upper_margin = mode->upper_margin; 509 var->right_margin = mode->right_margin;
510 var->lower_margin = mode->lower_margin; 510 var->upper_margin = mode->upper_margin;
511 var->hsync_len = mode->hsync_len; 511 var->lower_margin = mode->lower_margin;
512 var->vsync_len = mode->vsync_len; 512 var->hsync_len = mode->hsync_len;
513 var->sync = mode->sync; 513 var->vsync_len = mode->vsync_len;
514 var->vmode = mode->vmode; 514 var->sync = mode->sync;
515 if (info->fbops->fb_check_var) 515 var->vmode = mode->vmode;
516 err = info->fbops->fb_check_var(var, info); 516 if (info->fbops->fb_check_var)
517 var->activate &= ~FB_ACTIVATE_TEST; 517 err = info->fbops->fb_check_var(var, info);
518 return err; 518 var->activate &= ~FB_ACTIVATE_TEST;
519 return err;
519} 520}
520 521
521/** 522/**
522 * fb_find_mode - finds a valid video mode 523 * fb_find_mode - finds a valid video mode
523 * @var: frame buffer user defined part of display 524 * @var: frame buffer user defined part of display
524 * @info: frame buffer info structure 525 * @info: frame buffer info structure
525 * @mode_option: string video mode to find 526 * @mode_option: string video mode to find
526 * @db: video mode database 527 * @db: video mode database
527 * @dbsize: size of @db 528 * @dbsize: size of @db
528 * @default_mode: default video mode to fall back to 529 * @default_mode: default video mode to fall back to
529 * @default_bpp: default color depth in bits per pixel 530 * @default_bpp: default color depth in bits per pixel
530 * 531 *
531 * Finds a suitable video mode, starting with the specified mode 532 * Finds a suitable video mode, starting with the specified mode
532 * in @mode_option with fallback to @default_mode. If 533 * in @mode_option with fallback to @default_mode. If
533 * @default_mode fails, all modes in the video mode database will 534 * @default_mode fails, all modes in the video mode database will
534 * be tried. 535 * be tried.
535 * 536 *
536 * Valid mode specifiers for @mode_option: 537 * Valid mode specifiers for @mode_option:
537 * 538 *
538 * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or 539 * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
539 * <name>[-<bpp>][@<refresh>] 540 * <name>[-<bpp>][@<refresh>]
540 * 541 *
541 * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and 542 * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
542 * <name> a string. 543 * <name> a string.
543 * 544 *
544 * If 'M' is present after yres (and before refresh/bpp if present), 545 * If 'M' is present after yres (and before refresh/bpp if present),
545 * the function will compute the timings using VESA(tm) Coordinated 546 * the function will compute the timings using VESA(tm) Coordinated
@@ -551,12 +552,12 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
551 * 552 *
552 * 1024x768MR-8@60m - Reduced blank with margins at 60Hz. 553 * 1024x768MR-8@60m - Reduced blank with margins at 60Hz.
553 * 554 *
554 * NOTE: The passed struct @var is _not_ cleared! This allows you 555 * NOTE: The passed struct @var is _not_ cleared! This allows you
555 * to supply values for e.g. the grayscale and accel_flags fields. 556 * to supply values for e.g. the grayscale and accel_flags fields.
556 * 557 *
557 * Returns zero for failure, 1 if using specified @mode_option, 558 * Returns zero for failure, 1 if using specified @mode_option,
558 * 2 if using specified @mode_option with an ignored refresh rate, 559 * 2 if using specified @mode_option with an ignored refresh rate,
559 * 3 if default mode is used, 4 if fall back to any valid mode. 560 * 3 if default mode is used, 4 if fall back to any valid mode.
560 * 561 *
561 */ 562 */
562 563
@@ -566,198 +567,203 @@ int fb_find_mode(struct fb_var_screeninfo *var,
566 const struct fb_videomode *default_mode, 567 const struct fb_videomode *default_mode,
567 unsigned int default_bpp) 568 unsigned int default_bpp)
568{ 569{
569 int i; 570 int i;
570
571 /* Set up defaults */
572 if (!db) {
573 db = modedb;
574 dbsize = ARRAY_SIZE(modedb);
575 }
576
577 if (!default_mode)
578 default_mode = &db[0];
579
580 if (!default_bpp)
581 default_bpp = 8;
582
583 /* Did the user specify a video mode? */
584 if (!mode_option)
585 mode_option = fb_mode_option;
586 if (mode_option) {
587 const char *name = mode_option;
588 unsigned int namelen = strlen(name);
589 int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
590 unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
591 int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
592 u32 best, diff, tdiff;
593
594 for (i = namelen-1; i >= 0; i--) {
595 switch (name[i]) {
596 case '@':
597 namelen = i;
598 if (!refresh_specified && !bpp_specified &&
599 !yres_specified) {
600 refresh = simple_strtol(&name[i+1], NULL, 10);
601 refresh_specified = 1;
602 if (cvt || rb)
603 cvt = 0;
604 } else
605 goto done;
606 break;
607 case '-':
608 namelen = i;
609 if (!bpp_specified && !yres_specified) {
610 bpp = simple_strtol(&name[i+1], NULL, 10);
611 bpp_specified = 1;
612 if (cvt || rb)
613 cvt = 0;
614 } else
615 goto done;
616 break;
617 case 'x':
618 if (!yres_specified) {
619 yres = simple_strtol(&name[i+1], NULL, 10);
620 yres_specified = 1;
621 } else
622 goto done;
623 break;
624 case '0' ... '9':
625 break;
626 case 'M':
627 if (!yres_specified)
628 cvt = 1;
629 break;
630 case 'R':
631 if (!cvt)
632 rb = 1;
633 break;
634 case 'm':
635 if (!cvt)
636 margins = 1;
637 break;
638 case 'i':
639 if (!cvt)
640 interlace = 1;
641 break;
642 default:
643 goto done;
644 }
645 }
646 if (i < 0 && yres_specified) {
647 xres = simple_strtol(name, NULL, 10);
648 res_specified = 1;
649 }
650done:
651 if (cvt) {
652 struct fb_videomode cvt_mode;
653 int ret;
654
655 DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
656 (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
657 "", (margins) ? " with margins" : "", (interlace) ?
658 " interlaced" : "");
659
660 memset(&cvt_mode, 0, sizeof(cvt_mode));
661 cvt_mode.xres = xres;
662 cvt_mode.yres = yres;
663 cvt_mode.refresh = (refresh) ? refresh : 60;
664 571
665 if (interlace) 572 /* Set up defaults */
666 cvt_mode.vmode |= FB_VMODE_INTERLACED; 573 if (!db) {
667 else 574 db = modedb;
668 cvt_mode.vmode &= ~FB_VMODE_INTERLACED; 575 dbsize = ARRAY_SIZE(modedb);
576 }
669 577
670 ret = fb_find_mode_cvt(&cvt_mode, margins, rb); 578 if (!default_mode)
579 default_mode = &db[0];
580
581 if (!default_bpp)
582 default_bpp = 8;
583
584 /* Did the user specify a video mode? */
585 if (!mode_option)
586 mode_option = fb_mode_option;
587 if (mode_option) {
588 const char *name = mode_option;
589 unsigned int namelen = strlen(name);
590 int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
591 unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
592 int yres_specified = 0, cvt = 0, rb = 0, interlace = 0;
593 int margins = 0;
594 u32 best, diff, tdiff;
595
596 for (i = namelen-1; i >= 0; i--) {
597 switch (name[i]) {
598 case '@':
599 namelen = i;
600 if (!refresh_specified && !bpp_specified &&
601 !yres_specified) {
602 refresh = simple_strtol(&name[i+1], NULL,
603 10);
604 refresh_specified = 1;
605 if (cvt || rb)
606 cvt = 0;
607 } else
608 goto done;
609 break;
610 case '-':
611 namelen = i;
612 if (!bpp_specified && !yres_specified) {
613 bpp = simple_strtol(&name[i+1], NULL,
614 10);
615 bpp_specified = 1;
616 if (cvt || rb)
617 cvt = 0;
618 } else
619 goto done;
620 break;
621 case 'x':
622 if (!yres_specified) {
623 yres = simple_strtol(&name[i+1], NULL,
624 10);
625 yres_specified = 1;
626 } else
627 goto done;
628 break;
629 case '0' ... '9':
630 break;
631 case 'M':
632 if (!yres_specified)
633 cvt = 1;
634 break;
635 case 'R':
636 if (!cvt)
637 rb = 1;
638 break;
639 case 'm':
640 if (!cvt)
641 margins = 1;
642 break;
643 case 'i':
644 if (!cvt)
645 interlace = 1;
646 break;
647 default:
648 goto done;
649 }
650 }
651 if (i < 0 && yres_specified) {
652 xres = simple_strtol(name, NULL, 10);
653 res_specified = 1;
654 }
655done:
656 if (cvt) {
657 struct fb_videomode cvt_mode;
658 int ret;
659
660 DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
661 (refresh) ? refresh : 60,
662 (rb) ? " reduced blanking" : "",
663 (margins) ? " with margins" : "",
664 (interlace) ? " interlaced" : "");
665
666 memset(&cvt_mode, 0, sizeof(cvt_mode));
667 cvt_mode.xres = xres;
668 cvt_mode.yres = yres;
669 cvt_mode.refresh = (refresh) ? refresh : 60;
670
671 if (interlace)
672 cvt_mode.vmode |= FB_VMODE_INTERLACED;
673 else
674 cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
675
676 ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
677
678 if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
679 DPRINTK("modedb CVT: CVT mode ok\n");
680 return 1;
681 }
671 682
672 if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) { 683 DPRINTK("CVT mode invalid, getting mode from database\n");
673 DPRINTK("modedb CVT: CVT mode ok\n"); 684 }
674 return 1;
675 }
676 685
677 DPRINTK("CVT mode invalid, getting mode from database\n"); 686 DPRINTK("Trying specified video mode%s %ix%i\n",
678 } 687 refresh_specified ? "" : " (ignoring refresh rate)",
688 xres, yres);
679 689
680 DPRINTK("Trying specified video mode%s %ix%i\n", 690 if (!refresh_specified) {
681 refresh_specified ? "" : " (ignoring refresh rate)", xres, yres); 691 /*
682 692 * If the caller has provided a custom mode database and
683 if (!refresh_specified) { 693 * a valid monspecs structure, we look for the mode with
684 /* 694 * the highest refresh rate. Otherwise we play it safe
685 * If the caller has provided a custom mode database and a 695 * it and try to find a mode with a refresh rate closest
686 * valid monspecs structure, we look for the mode with the 696 * to the standard 60 Hz.
687 * highest refresh rate. Otherwise we play it safe it and 697 */
688 * try to find a mode with a refresh rate closest to the 698 if (db != modedb &&
689 * standard 60 Hz. 699 info->monspecs.vfmin && info->monspecs.vfmax &&
690 */ 700 info->monspecs.hfmin && info->monspecs.hfmax &&
691 if (db != modedb && 701 info->monspecs.dclkmax) {
692 info->monspecs.vfmin && info->monspecs.vfmax && 702 refresh = 1000;
693 info->monspecs.hfmin && info->monspecs.hfmax && 703 } else {
694 info->monspecs.dclkmax) { 704 refresh = 60;
695 refresh = 1000; 705 }
696 } else {
697 refresh = 60;
698 } 706 }
699 }
700 707
701 diff = -1; 708 diff = -1;
702 best = -1; 709 best = -1;
703 for (i = 0; i < dbsize; i++) { 710 for (i = 0; i < dbsize; i++) {
704 if ((name_matches(db[i], name, namelen) || 711 if ((name_matches(db[i], name, namelen) ||
705 (res_specified && res_matches(db[i], xres, yres))) && 712 (res_specified && res_matches(db[i], xres, yres))) &&
706 !fb_try_mode(var, info, &db[i], bpp)) { 713 !fb_try_mode(var, info, &db[i], bpp)) {
707 if (refresh_specified && db[i].refresh == refresh) { 714 if (refresh_specified && db[i].refresh == refresh)
708 return 1; 715 return 1;
709 } else { 716
710 if (abs(db[i].refresh - refresh) < diff) { 717 if (abs(db[i].refresh - refresh) < diff) {
711 diff = abs(db[i].refresh - refresh); 718 diff = abs(db[i].refresh - refresh);
712 best = i; 719 best = i;
713 } 720 }
714 } 721 }
715 } 722 }
716 } 723 if (best != -1) {
717 if (best != -1) { 724 fb_try_mode(var, info, &db[best], bpp);
718 fb_try_mode(var, info, &db[best], bpp); 725 return (refresh_specified) ? 2 : 1;
719 return (refresh_specified) ? 2 : 1; 726 }
720 }
721
722 diff = 2 * (xres + yres);
723 best = -1;
724 DPRINTK("Trying best-fit modes\n");
725 for (i = 0; i < dbsize; i++) {
726 DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
727 if (!fb_try_mode(var, info, &db[i], bpp)) {
728 tdiff = abs(db[i].xres - xres) +
729 abs(db[i].yres - yres);
730
731 /*
732 * Penalize modes with resolutions smaller
733 * than requested.
734 */
735 if (xres > db[i].xres || yres > db[i].yres)
736 tdiff += xres + yres;
737 727
738 if (diff > tdiff) { 728 diff = 2 * (xres + yres);
739 diff = tdiff; 729 best = -1;
740 best = i; 730 DPRINTK("Trying best-fit modes\n");
731 for (i = 0; i < dbsize; i++) {
732 DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
733 if (!fb_try_mode(var, info, &db[i], bpp)) {
734 tdiff = abs(db[i].xres - xres) +
735 abs(db[i].yres - yres);
736
737 /*
738 * Penalize modes with resolutions smaller
739 * than requested.
740 */
741 if (xres > db[i].xres || yres > db[i].yres)
742 tdiff += xres + yres;
743
744 if (diff > tdiff) {
745 diff = tdiff;
746 best = i;
747 }
741 } 748 }
742 } 749 }
750 if (best != -1) {
751 fb_try_mode(var, info, &db[best], bpp);
752 return 5;
753 }
743 } 754 }
744 if (best != -1) {
745 fb_try_mode(var, info, &db[best], bpp);
746 return 5;
747 }
748 }
749 755
750 DPRINTK("Trying default video mode\n"); 756 DPRINTK("Trying default video mode\n");
751 if (!fb_try_mode(var, info, default_mode, default_bpp)) 757 if (!fb_try_mode(var, info, default_mode, default_bpp))
752 return 3; 758 return 3;
753 759
754 DPRINTK("Trying all modes\n"); 760 DPRINTK("Trying all modes\n");
755 for (i = 0; i < dbsize; i++) 761 for (i = 0; i < dbsize; i++)
756 if (!fb_try_mode(var, info, &db[i], default_bpp)) 762 if (!fb_try_mode(var, info, &db[i], default_bpp))
757 return 4; 763 return 4;
758 764
759 DPRINTK("No valid mode found\n"); 765 DPRINTK("No valid mode found\n");
760 return 0; 766 return 0;
761} 767}
762 768
763/** 769/**
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index 178b0720bd7..4527cbf0a4e 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -715,7 +715,7 @@ static int __devinit mddi_probe(struct platform_device *pdev)
715 715
716 mddi->int_enable = 0; 716 mddi->int_enable = 0;
717 mddi_writel(mddi->int_enable, INTEN); 717 mddi_writel(mddi->int_enable, INTEN);
718 ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi", 718 ret = request_irq(mddi->irq, mddi_isr, 0, "mddi",
719 &mddi->client_data); 719 &mddi->client_data);
720 if (ret) { 720 if (ret) {
721 printk(KERN_ERR "mddi: failed to request enable irq!\n"); 721 printk(KERN_ERR "mddi: failed to request enable irq!\n");
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 243d16f09b8..b9344772bac 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -421,10 +421,11 @@ int mdp_probe(struct platform_device *pdev)
421 clk = clk_get(&pdev->dev, "mdp_clk"); 421 clk = clk_get(&pdev->dev, "mdp_clk");
422 if (IS_ERR(clk)) { 422 if (IS_ERR(clk)) {
423 printk(KERN_INFO "mdp: failed to get mdp clk"); 423 printk(KERN_INFO "mdp: failed to get mdp clk");
424 return PTR_ERR(clk); 424 ret = PTR_ERR(clk);
425 goto error_get_clk;
425 } 426 }
426 427
427 ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp); 428 ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp);
428 if (ret) 429 if (ret)
429 goto error_request_irq; 430 goto error_request_irq;
430 disable_irq(mdp->irq); 431 disable_irq(mdp->irq);
@@ -495,6 +496,7 @@ int mdp_probe(struct platform_device *pdev)
495error_device_register: 496error_device_register:
496 free_irq(mdp->irq, mdp); 497 free_irq(mdp->irq, mdp);
497error_request_irq: 498error_request_irq:
499error_get_clk:
498 iounmap(mdp->base); 500 iounmap(mdp->base);
499error_get_irq: 501error_get_irq:
500error_ioremap: 502error_ioremap:
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index 7e3a490e8d7..e3406ab3130 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -382,6 +382,9 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi)
382 uint32_t enabled; 382 uint32_t enabled;
383 unsigned long flags; 383 unsigned long flags;
384 384
385 if (mx3_fbi->txd == NULL)
386 return;
387
385 spin_lock_irqsave(&mx3fb->lock, flags); 388 spin_lock_irqsave(&mx3fb->lock, flags);
386 389
387 enabled = sdc_fb_uninit(mx3_fbi); 390 enabled = sdc_fb_uninit(mx3_fbi);
@@ -986,9 +989,19 @@ static void __blank(int blank, struct fb_info *fbi)
986{ 989{
987 struct mx3fb_info *mx3_fbi = fbi->par; 990 struct mx3fb_info *mx3_fbi = fbi->par;
988 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; 991 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
992 int was_blank = mx3_fbi->blank;
989 993
990 mx3_fbi->blank = blank; 994 mx3_fbi->blank = blank;
991 995
996 /* Attention!
997 * Do not call sdc_disable_channel() for a channel that is disabled
998 * already! This will result in a kernel NULL pointer dereference
999 * (mx3_fbi->txd is NULL). Hide the fact, that all blank modes are
1000 * handled equally by this driver.
1001 */
1002 if (blank > FB_BLANK_UNBLANK && was_blank > FB_BLANK_UNBLANK)
1003 return;
1004
992 switch (blank) { 1005 switch (blank) {
993 case FB_BLANK_POWERDOWN: 1006 case FB_BLANK_POWERDOWN:
994 case FB_BLANK_VSYNC_SUSPEND: 1007 case FB_BLANK_VSYNC_SUSPEND:
@@ -1062,15 +1075,15 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
1062 y_bottom = var->yoffset; 1075 y_bottom = var->yoffset;
1063 1076
1064 if (!(var->vmode & FB_VMODE_YWRAP)) 1077 if (!(var->vmode & FB_VMODE_YWRAP))
1065 y_bottom += var->yres; 1078 y_bottom += fbi->var.yres;
1066 1079
1067 if (y_bottom > fbi->var.yres_virtual) 1080 if (y_bottom > fbi->var.yres_virtual)
1068 return -EINVAL; 1081 return -EINVAL;
1069 1082
1070 mutex_lock(&mx3_fbi->mutex); 1083 mutex_lock(&mx3_fbi->mutex);
1071 1084
1072 offset = (var->yoffset * var->xres_virtual + var->xoffset) * 1085 offset = var->yoffset * fbi->fix.line_length
1073 (var->bits_per_pixel / 8); 1086 + var->xoffset * (fbi->var.bits_per_pixel / 8);
1074 base = fbi->fix.smem_start + offset; 1087 base = fbi->fix.smem_start + offset;
1075 1088
1076 dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n", 1089 dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n",
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 0b2f2dd4141..d837d63c456 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -39,6 +39,7 @@
39 * the required value in the imx_fb_videomode structure. 39 * the required value in the imx_fb_videomode structure.
40 */ 40 */
41 41
42#include <linux/module.h>
42#include <linux/kernel.h> 43#include <linux/kernel.h>
43#include <linux/platform_device.h> 44#include <linux/platform_device.h>
44#include <linux/clk.h> 45#include <linux/clk.h>
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 588527a254c..feea7b1dc38 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -1185,8 +1185,8 @@ static int neofb_pan_display(struct fb_var_screeninfo *var,
1185 1185
1186 DBG("neofb_update_start"); 1186 DBG("neofb_update_start");
1187 1187
1188 Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2; 1188 Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2;
1189 Base *= (var->bits_per_pixel + 7) / 8; 1189 Base *= (info->var.bits_per_pixel + 7) / 8;
1190 1190
1191 neoUnlock(); 1191 neoUnlock();
1192 1192
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index 0fff59782e4..d1fbbd888cf 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -39,7 +39,6 @@
39#include <mach/regs-clock.h> 39#include <mach/regs-clock.h>
40#include <mach/regs-ldm.h> 40#include <mach/regs-ldm.h>
41#include <mach/fb.h> 41#include <mach/fb.h>
42#include <mach/clkdev.h>
43 42
44#include "nuc900fb.h" 43#include "nuc900fb.h"
45 44
@@ -588,7 +587,7 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev)
588 fbinfo->flags = FBINFO_FLAG_DEFAULT; 587 fbinfo->flags = FBINFO_FLAG_DEFAULT;
589 fbinfo->pseudo_palette = &fbi->pseudo_pal; 588 fbinfo->pseudo_palette = &fbi->pseudo_pal;
590 589
591 ret = request_irq(irq, nuc900fb_irqhandler, IRQF_DISABLED, 590 ret = request_irq(irq, nuc900fb_irqhandler, 0,
592 pdev->name, fbinfo); 591 pdev->name, fbinfo);
593 if (ret) { 592 if (ret) {
594 dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n", 593 dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n",
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 196fa2e7f43..84ff23208c2 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -9,35 +9,6 @@ config FB_OMAP
9 help 9 help
10 Frame buffer driver for OMAP based boards. 10 Frame buffer driver for OMAP based boards.
11 11
12config FB_OMAP_LCD_VGA
13 bool "Use LCD in VGA mode"
14 depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP
15 help
16 Set LCD resolution as VGA (640 X 480).
17 Default resolution without this option is QVGA(320 X 240).
18 Please take a look at drivers/video/omap/lcd_ldp.c file
19 for lcd driver code.
20choice
21 depends on FB_OMAP && MACH_OVERO
22 prompt "Screen resolution"
23 default FB_OMAP_079M3R
24 help
25 Selected desired screen resolution
26
27config FB_OMAP_031M3R
28 boolean "640 x 480 @ 60 Hz Reduced blanking"
29
30config FB_OMAP_048M3R
31 boolean "800 x 600 @ 60 Hz Reduced blanking"
32
33config FB_OMAP_079M3R
34 boolean "1024 x 768 @ 60 Hz Reduced blanking"
35
36config FB_OMAP_092M9R
37 boolean "1280 x 720 @ 60 Hz Reduced blanking"
38
39endchoice
40
41config FB_OMAP_LCDC_EXTERNAL 12config FB_OMAP_LCDC_EXTERNAL
42 bool "External LCD controller support" 13 bool "External LCD controller support"
43 depends on FB_OMAP 14 depends on FB_OMAP
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
index 25db55696e1..ef78550917f 100644
--- a/drivers/video/omap/Makefile
+++ b/drivers/video/omap/Makefile
@@ -17,7 +17,6 @@ objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
17objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o 17objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o
18 18
19objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o 19objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o
20objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o
21objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o 20objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
22objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o 21objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
23objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o 22objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o
@@ -26,14 +25,7 @@ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
26objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o 25objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
27objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o 26objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
28 27
29objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o
30objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o
31objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o
32objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o
33objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o
34objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o
35objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o 28objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
36objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o
37objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o 29objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o
38 30
39omapfb-objs := $(objs-yy) 31omapfb-objs := $(objs-yy)
diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c
deleted file mode 100644
index e3eccc9af78..00000000000
--- a/drivers/video/omap/lcd_2430sdp.c
+++ /dev/null
@@ -1,203 +0,0 @@
1/*
2 * LCD panel support for the TI 2430SDP board
3 *
4 * Copyright (C) 2007 MontaVista
5 * Author: Hunyue Yau <hyau@mvista.com>
6 *
7 * Derived from drivers/video/omap/lcd-apollon.c
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/delay.h>
27#include <linux/gpio.h>
28#include <linux/i2c/twl.h>
29
30#include <plat/mux.h>
31#include <asm/mach-types.h>
32
33#include "omapfb.h"
34
35#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91
36#define SDP2430_LCD_PANEL_ENABLE_GPIO 154
37#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24
38#define SDP3430_LCD_PANEL_ENABLE_GPIO 28
39
40static unsigned backlight_gpio;
41static unsigned enable_gpio;
42
43#define LCD_PIXCLOCK_MAX 5400 /* freq 5.4 MHz */
44#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
45#define ENABLE_VAUX2_DEDICATED 0x09
46#define ENABLE_VAUX2_DEV_GRP 0x20
47#define ENABLE_VAUX3_DEDICATED 0x03
48#define ENABLE_VAUX3_DEV_GRP 0x20
49
50#define ENABLE_VPLL2_DEDICATED 0x05
51#define ENABLE_VPLL2_DEV_GRP 0xE0
52#define TWL4030_VPLL2_DEV_GRP 0x33
53#define TWL4030_VPLL2_DEDICATED 0x36
54
55#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v)
56
57
58static int sdp2430_panel_init(struct lcd_panel *panel,
59 struct omapfb_device *fbdev)
60{
61 if (machine_is_omap_3430sdp()) {
62 enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO;
63 backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
64 } else {
65 enable_gpio = SDP2430_LCD_PANEL_ENABLE_GPIO;
66 backlight_gpio = SDP2430_LCD_PANEL_BACKLIGHT_GPIO;
67 }
68
69 gpio_request(enable_gpio, "LCD enable"); /* LCD panel */
70 gpio_request(backlight_gpio, "LCD bl"); /* LCD backlight */
71 gpio_direction_output(enable_gpio, 0);
72 gpio_direction_output(backlight_gpio, 0);
73
74 return 0;
75}
76
77static void sdp2430_panel_cleanup(struct lcd_panel *panel)
78{
79 gpio_free(backlight_gpio);
80 gpio_free(enable_gpio);
81}
82
83static int sdp2430_panel_enable(struct lcd_panel *panel)
84{
85 u8 ded_val, ded_reg;
86 u8 grp_val, grp_reg;
87
88 if (machine_is_omap_3430sdp()) {
89 ded_reg = TWL4030_VAUX3_DEDICATED;
90 ded_val = ENABLE_VAUX3_DEDICATED;
91 grp_reg = TWL4030_VAUX3_DEV_GRP;
92 grp_val = ENABLE_VAUX3_DEV_GRP;
93
94 if (omap_rev() > OMAP3430_REV_ES1_0) {
95 t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED,
96 TWL4030_VPLL2_DEDICATED);
97 t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP,
98 TWL4030_VPLL2_DEV_GRP);
99 }
100 } else {
101 ded_reg = TWL4030_VAUX2_DEDICATED;
102 ded_val = ENABLE_VAUX2_DEDICATED;
103 grp_reg = TWL4030_VAUX2_DEV_GRP;
104 grp_val = ENABLE_VAUX2_DEV_GRP;
105 }
106
107 gpio_set_value(enable_gpio, 1);
108 gpio_set_value(backlight_gpio, 1);
109
110 if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg))
111 return -EIO;
112 if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg))
113 return -EIO;
114
115 return 0;
116}
117
118static void sdp2430_panel_disable(struct lcd_panel *panel)
119{
120 gpio_set_value(enable_gpio, 0);
121 gpio_set_value(backlight_gpio, 0);
122 if (omap_rev() > OMAP3430_REV_ES1_0) {
123 t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED);
124 t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP);
125 msleep(4);
126 }
127}
128
129static unsigned long sdp2430_panel_get_caps(struct lcd_panel *panel)
130{
131 return 0;
132}
133
134struct lcd_panel sdp2430_panel = {
135 .name = "sdp2430",
136 .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
137 OMAP_LCDC_INV_HSYNC,
138
139 .bpp = 16,
140 .data_lines = 16,
141 .x_res = 240,
142 .y_res = 320,
143 .hsw = 3, /* hsync_len (4) - 1 */
144 .hfp = 3, /* right_margin (4) - 1 */
145 .hbp = 39, /* left_margin (40) - 1 */
146 .vsw = 1, /* vsync_len (2) - 1 */
147 .vfp = 2, /* lower_margin */
148 .vbp = 7, /* upper_margin (8) - 1 */
149
150 .pixel_clock = LCD_PIXCLOCK_MAX,
151
152 .init = sdp2430_panel_init,
153 .cleanup = sdp2430_panel_cleanup,
154 .enable = sdp2430_panel_enable,
155 .disable = sdp2430_panel_disable,
156 .get_caps = sdp2430_panel_get_caps,
157};
158
159static int sdp2430_panel_probe(struct platform_device *pdev)
160{
161 omapfb_register_panel(&sdp2430_panel);
162 return 0;
163}
164
165static int sdp2430_panel_remove(struct platform_device *pdev)
166{
167 return 0;
168}
169
170static int sdp2430_panel_suspend(struct platform_device *pdev,
171 pm_message_t mesg)
172{
173 return 0;
174}
175
176static int sdp2430_panel_resume(struct platform_device *pdev)
177{
178 return 0;
179}
180
181struct platform_driver sdp2430_panel_driver = {
182 .probe = sdp2430_panel_probe,
183 .remove = sdp2430_panel_remove,
184 .suspend = sdp2430_panel_suspend,
185 .resume = sdp2430_panel_resume,
186 .driver = {
187 .name = "sdp2430_lcd",
188 .owner = THIS_MODULE,
189 },
190};
191
192static int __init sdp2430_panel_drv_init(void)
193{
194 return platform_driver_register(&sdp2430_panel_driver);
195}
196
197static void __exit sdp2430_panel_drv_exit(void)
198{
199 platform_driver_unregister(&sdp2430_panel_driver);
200}
201
202module_init(sdp2430_panel_drv_init);
203module_exit(sdp2430_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c
deleted file mode 100644
index 4b24f549f9b..00000000000
--- a/drivers/video/omap/lcd_apollon.c
+++ /dev/null
@@ -1,136 +0,0 @@
1/*
2 * LCD panel support for the Samsung OMAP2 Apollon board
3 *
4 * Copyright (C) 2005,2006 Samsung Electronics
5 * Author: Kyungmin Park <kyungmin.park@samsung.com>
6 *
7 * Derived from drivers/video/omap/lcd-h4.c
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26
27#include <asm/gpio.h>
28
29#include "omapfb.h"
30
31/* #define USE_35INCH_LCD 1 */
32
33static int apollon_panel_init(struct lcd_panel *panel,
34 struct omapfb_device *fbdev)
35{
36 return 0;
37}
38
39static void apollon_panel_cleanup(struct lcd_panel *panel)
40{
41}
42
43static int apollon_panel_enable(struct lcd_panel *panel)
44{
45 return 0;
46}
47
48static void apollon_panel_disable(struct lcd_panel *panel)
49{
50}
51
52static unsigned long apollon_panel_get_caps(struct lcd_panel *panel)
53{
54 return 0;
55}
56
57struct lcd_panel apollon_panel = {
58 .name = "apollon",
59 .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
60 OMAP_LCDC_INV_HSYNC,
61
62 .bpp = 16,
63 .data_lines = 18,
64#ifdef USE_35INCH_LCD
65 .x_res = 240,
66 .y_res = 320,
67 .hsw = 2,
68 .hfp = 3,
69 .hbp = 9,
70 .vsw = 4,
71 .vfp = 3,
72 .vbp = 5,
73#else
74 .x_res = 480,
75 .y_res = 272,
76 .hsw = 41,
77 .hfp = 2,
78 .hbp = 2,
79 .vsw = 10,
80 .vfp = 2,
81 .vbp = 2,
82#endif
83 .pixel_clock = 6250,
84
85 .init = apollon_panel_init,
86 .cleanup = apollon_panel_cleanup,
87 .enable = apollon_panel_enable,
88 .disable = apollon_panel_disable,
89 .get_caps = apollon_panel_get_caps,
90};
91
92static int apollon_panel_probe(struct platform_device *pdev)
93{
94 omapfb_register_panel(&apollon_panel);
95 return 0;
96}
97
98static int apollon_panel_remove(struct platform_device *pdev)
99{
100 return 0;
101}
102
103static int apollon_panel_suspend(struct platform_device *pdev,
104 pm_message_t mesg)
105{
106 return 0;
107}
108
109static int apollon_panel_resume(struct platform_device *pdev)
110{
111 return 0;
112}
113
114struct platform_driver apollon_panel_driver = {
115 .probe = apollon_panel_probe,
116 .remove = apollon_panel_remove,
117 .suspend = apollon_panel_suspend,
118 .resume = apollon_panel_resume,
119 .driver = {
120 .name = "apollon_lcd",
121 .owner = THIS_MODULE,
122 },
123};
124
125static int __init apollon_panel_drv_init(void)
126{
127 return platform_driver_register(&apollon_panel_driver);
128}
129
130static void __exit apollon_panel_drv_exit(void)
131{
132 platform_driver_unregister(&apollon_panel_driver);
133}
134
135module_init(apollon_panel_drv_init);
136module_exit(apollon_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
deleted file mode 100644
index 03a06a98275..00000000000
--- a/drivers/video/omap/lcd_h4.c
+++ /dev/null
@@ -1,117 +0,0 @@
1/*
2 * LCD panel support for the TI OMAP H4 board
3 *
4 * Copyright (C) 2004 Nokia Corporation
5 * Author: Imre Deak <imre.deak@nokia.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 as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/module.h>
23#include <linux/platform_device.h>
24
25#include "omapfb.h"
26
27static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
28{
29 return 0;
30}
31
32static void h4_panel_cleanup(struct lcd_panel *panel)
33{
34}
35
36static int h4_panel_enable(struct lcd_panel *panel)
37{
38 return 0;
39}
40
41static void h4_panel_disable(struct lcd_panel *panel)
42{
43}
44
45static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
46{
47 return 0;
48}
49
50static struct lcd_panel h4_panel = {
51 .name = "h4",
52 .config = OMAP_LCDC_PANEL_TFT,
53
54 .bpp = 16,
55 .data_lines = 16,
56 .x_res = 240,
57 .y_res = 320,
58 .pixel_clock = 6250,
59 .hsw = 15,
60 .hfp = 15,
61 .hbp = 60,
62 .vsw = 1,
63 .vfp = 1,
64 .vbp = 1,
65
66 .init = h4_panel_init,
67 .cleanup = h4_panel_cleanup,
68 .enable = h4_panel_enable,
69 .disable = h4_panel_disable,
70 .get_caps = h4_panel_get_caps,
71};
72
73static int h4_panel_probe(struct platform_device *pdev)
74{
75 omapfb_register_panel(&h4_panel);
76 return 0;
77}
78
79static int h4_panel_remove(struct platform_device *pdev)
80{
81 return 0;
82}
83
84static int h4_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
85{
86 return 0;
87}
88
89static int h4_panel_resume(struct platform_device *pdev)
90{
91 return 0;
92}
93
94static struct platform_driver h4_panel_driver = {
95 .probe = h4_panel_probe,
96 .remove = h4_panel_remove,
97 .suspend = h4_panel_suspend,
98 .resume = h4_panel_resume,
99 .driver = {
100 .name = "lcd_h4",
101 .owner = THIS_MODULE,
102 },
103};
104
105static int __init h4_panel_drv_init(void)
106{
107 return platform_driver_register(&h4_panel_driver);
108}
109
110static void __exit h4_panel_drv_cleanup(void)
111{
112 platform_driver_unregister(&h4_panel_driver);
113}
114
115module_init(h4_panel_drv_init);
116module_exit(h4_panel_drv_cleanup);
117
diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c
deleted file mode 100644
index 062466402c0..00000000000
--- a/drivers/video/omap/lcd_ldp.c
+++ /dev/null
@@ -1,201 +0,0 @@
1/*
2 * LCD panel support for the TI LDP board
3 *
4 * Copyright (C) 2007 WindRiver
5 * Author: Stanley Miao <stanley.miao@windriver.com>
6 *
7 * Derived from drivers/video/omap/lcd-2430sdp.c
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/delay.h>
27#include <linux/i2c/twl.h>
28
29#include <asm/gpio.h>
30#include <plat/mux.h>
31#include <asm/mach-types.h>
32
33#include "omapfb.h"
34
35#define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES)
36#define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES)
37
38#define LCD_PANEL_RESET_GPIO 55
39#define LCD_PANEL_QVGA_GPIO 56
40
41#ifdef CONFIG_FB_OMAP_LCD_VGA
42#define LCD_XRES 480
43#define LCD_YRES 640
44#define LCD_PIXCLOCK_MAX 41700
45#else
46#define LCD_XRES 240
47#define LCD_YRES 320
48#define LCD_PIXCLOCK_MAX 185186
49#endif
50
51#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
52#define ENABLE_VAUX2_DEDICATED 0x09
53#define ENABLE_VAUX2_DEV_GRP 0x20
54#define ENABLE_VAUX3_DEDICATED 0x03
55#define ENABLE_VAUX3_DEV_GRP 0x20
56
57#define ENABLE_VPLL2_DEDICATED 0x05
58#define ENABLE_VPLL2_DEV_GRP 0xE0
59#define TWL4030_VPLL2_DEV_GRP 0x33
60#define TWL4030_VPLL2_DEDICATED 0x36
61
62#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v)
63
64
65static int ldp_panel_init(struct lcd_panel *panel,
66 struct omapfb_device *fbdev)
67{
68 gpio_request(LCD_PANEL_RESET_GPIO, "lcd reset");
69 gpio_request(LCD_PANEL_QVGA_GPIO, "lcd qvga");
70 gpio_request(LCD_PANEL_ENABLE_GPIO, "lcd panel");
71 gpio_request(LCD_PANEL_BACKLIGHT_GPIO, "lcd backlight");
72
73 gpio_direction_output(LCD_PANEL_QVGA_GPIO, 0);
74 gpio_direction_output(LCD_PANEL_RESET_GPIO, 0);
75 gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
76 gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0);
77
78#ifdef CONFIG_FB_OMAP_LCD_VGA
79 gpio_set_value(LCD_PANEL_QVGA_GPIO, 0);
80#else
81 gpio_set_value(LCD_PANEL_QVGA_GPIO, 1);
82#endif
83 gpio_set_value(LCD_PANEL_RESET_GPIO, 1);
84
85 return 0;
86}
87
88static void ldp_panel_cleanup(struct lcd_panel *panel)
89{
90 gpio_free(LCD_PANEL_BACKLIGHT_GPIO);
91 gpio_free(LCD_PANEL_ENABLE_GPIO);
92 gpio_free(LCD_PANEL_QVGA_GPIO);
93 gpio_free(LCD_PANEL_RESET_GPIO);
94}
95
96static int ldp_panel_enable(struct lcd_panel *panel)
97{
98 if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED,
99 TWL4030_VPLL2_DEDICATED))
100 return -EIO;
101 if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP,
102 TWL4030_VPLL2_DEV_GRP))
103 return -EIO;
104
105 gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1);
106 gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 1);
107
108 if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEDICATED,
109 TWL4030_VAUX3_DEDICATED))
110 return -EIO;
111 if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEV_GRP,
112 TWL4030_VAUX3_DEV_GRP))
113 return -EIO;
114
115 return 0;
116}
117
118static void ldp_panel_disable(struct lcd_panel *panel)
119{
120 gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
121 gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0);
122
123 t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED);
124 t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP);
125 msleep(4);
126}
127
128static unsigned long ldp_panel_get_caps(struct lcd_panel *panel)
129{
130 return 0;
131}
132
133struct lcd_panel ldp_panel = {
134 .name = "ldp",
135 .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
136 OMAP_LCDC_INV_HSYNC,
137
138 .bpp = 16,
139 .data_lines = 18,
140 .x_res = LCD_XRES,
141 .y_res = LCD_YRES,
142 .hsw = 3, /* hsync_len (4) - 1 */
143 .hfp = 3, /* right_margin (4) - 1 */
144 .hbp = 39, /* left_margin (40) - 1 */
145 .vsw = 1, /* vsync_len (2) - 1 */
146 .vfp = 2, /* lower_margin */
147 .vbp = 7, /* upper_margin (8) - 1 */
148
149 .pixel_clock = LCD_PIXCLOCK_MAX,
150
151 .init = ldp_panel_init,
152 .cleanup = ldp_panel_cleanup,
153 .enable = ldp_panel_enable,
154 .disable = ldp_panel_disable,
155 .get_caps = ldp_panel_get_caps,
156};
157
158static int ldp_panel_probe(struct platform_device *pdev)
159{
160 omapfb_register_panel(&ldp_panel);
161 return 0;
162}
163
164static int ldp_panel_remove(struct platform_device *pdev)
165{
166 return 0;
167}
168
169static int ldp_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
170{
171 return 0;
172}
173
174static int ldp_panel_resume(struct platform_device *pdev)
175{
176 return 0;
177}
178
179struct platform_driver ldp_panel_driver = {
180 .probe = ldp_panel_probe,
181 .remove = ldp_panel_remove,
182 .suspend = ldp_panel_suspend,
183 .resume = ldp_panel_resume,
184 .driver = {
185 .name = "ldp_lcd",
186 .owner = THIS_MODULE,
187 },
188};
189
190static int __init ldp_panel_drv_init(void)
191{
192 return platform_driver_register(&ldp_panel_driver);
193}
194
195static void __exit ldp_panel_drv_exit(void)
196{
197 platform_driver_unregister(&ldp_panel_driver);
198}
199
200module_init(ldp_panel_drv_init);
201module_exit(ldp_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c
deleted file mode 100644
index d7c6c3e0afc..00000000000
--- a/drivers/video/omap/lcd_omap3beagle.c
+++ /dev/null
@@ -1,130 +0,0 @@
1/*
2 * LCD panel support for the TI OMAP3 Beagle board
3 *
4 * Author: Koen Kooi <koen@openembedded.org>
5 *
6 * Derived from drivers/video/omap/lcd-omap3evm.c
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/gpio.h>
26#include <linux/i2c/twl.h>
27
28#include <asm/mach-types.h>
29
30#include "omapfb.h"
31
32#define LCD_PANEL_ENABLE_GPIO 170
33
34static int omap3beagle_panel_init(struct lcd_panel *panel,
35 struct omapfb_device *fbdev)
36{
37 gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable");
38 return 0;
39}
40
41static void omap3beagle_panel_cleanup(struct lcd_panel *panel)
42{
43 gpio_free(LCD_PANEL_ENABLE_GPIO);
44}
45
46static int omap3beagle_panel_enable(struct lcd_panel *panel)
47{
48 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
49 return 0;
50}
51
52static void omap3beagle_panel_disable(struct lcd_panel *panel)
53{
54 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0);
55}
56
57static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel)
58{
59 return 0;
60}
61
62struct lcd_panel omap3beagle_panel = {
63 .name = "omap3beagle",
64 .config = OMAP_LCDC_PANEL_TFT,
65
66 .bpp = 16,
67 .data_lines = 24,
68 .x_res = 1024,
69 .y_res = 768,
70 .hsw = 3, /* hsync_len (4) - 1 */
71 .hfp = 3, /* right_margin (4) - 1 */
72 .hbp = 39, /* left_margin (40) - 1 */
73 .vsw = 1, /* vsync_len (2) - 1 */
74 .vfp = 2, /* lower_margin */
75 .vbp = 7, /* upper_margin (8) - 1 */
76
77 .pixel_clock = 64000,
78
79 .init = omap3beagle_panel_init,
80 .cleanup = omap3beagle_panel_cleanup,
81 .enable = omap3beagle_panel_enable,
82 .disable = omap3beagle_panel_disable,
83 .get_caps = omap3beagle_panel_get_caps,
84};
85
86static int omap3beagle_panel_probe(struct platform_device *pdev)
87{
88 omapfb_register_panel(&omap3beagle_panel);
89 return 0;
90}
91
92static int omap3beagle_panel_remove(struct platform_device *pdev)
93{
94 return 0;
95}
96
97static int omap3beagle_panel_suspend(struct platform_device *pdev,
98 pm_message_t mesg)
99{
100 return 0;
101}
102
103static int omap3beagle_panel_resume(struct platform_device *pdev)
104{
105 return 0;
106}
107
108struct platform_driver omap3beagle_panel_driver = {
109 .probe = omap3beagle_panel_probe,
110 .remove = omap3beagle_panel_remove,
111 .suspend = omap3beagle_panel_suspend,
112 .resume = omap3beagle_panel_resume,
113 .driver = {
114 .name = "omap3beagle_lcd",
115 .owner = THIS_MODULE,
116 },
117};
118
119static int __init omap3beagle_panel_drv_init(void)
120{
121 return platform_driver_register(&omap3beagle_panel_driver);
122}
123
124static void __exit omap3beagle_panel_drv_exit(void)
125{
126 platform_driver_unregister(&omap3beagle_panel_driver);
127}
128
129module_init(omap3beagle_panel_drv_init);
130module_exit(omap3beagle_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c
deleted file mode 100644
index 06840da0b09..00000000000
--- a/drivers/video/omap/lcd_omap3evm.c
+++ /dev/null
@@ -1,193 +0,0 @@
1/*
2 * LCD panel support for the TI OMAP3 EVM board
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * Derived from drivers/video/omap/lcd-apollon.c
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/gpio.h>
26#include <linux/i2c/twl.h>
27
28#include <plat/mux.h>
29#include <asm/mach-types.h>
30
31#include "omapfb.h"
32
33#define LCD_PANEL_ENABLE_GPIO 153
34#define LCD_PANEL_LR 2
35#define LCD_PANEL_UD 3
36#define LCD_PANEL_INI 152
37#define LCD_PANEL_QVGA 154
38#define LCD_PANEL_RESB 155
39
40#define ENABLE_VDAC_DEDICATED 0x03
41#define ENABLE_VDAC_DEV_GRP 0x20
42#define ENABLE_VPLL2_DEDICATED 0x05
43#define ENABLE_VPLL2_DEV_GRP 0xE0
44
45#define TWL_LED_LEDEN 0x00
46#define TWL_PWMA_PWMAON 0x00
47#define TWL_PWMA_PWMAOFF 0x01
48
49static unsigned int bklight_level;
50
51static int omap3evm_panel_init(struct lcd_panel *panel,
52 struct omapfb_device *fbdev)
53{
54 gpio_request(LCD_PANEL_LR, "LCD lr");
55 gpio_request(LCD_PANEL_UD, "LCD ud");
56 gpio_request(LCD_PANEL_INI, "LCD ini");
57 gpio_request(LCD_PANEL_RESB, "LCD resb");
58 gpio_request(LCD_PANEL_QVGA, "LCD qvga");
59
60 gpio_direction_output(LCD_PANEL_RESB, 1);
61 gpio_direction_output(LCD_PANEL_INI, 1);
62 gpio_direction_output(LCD_PANEL_QVGA, 0);
63 gpio_direction_output(LCD_PANEL_LR, 1);
64 gpio_direction_output(LCD_PANEL_UD, 1);
65
66 twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
67 twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
68 twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
69 bklight_level = 100;
70
71 return 0;
72}
73
74static void omap3evm_panel_cleanup(struct lcd_panel *panel)
75{
76 gpio_free(LCD_PANEL_QVGA);
77 gpio_free(LCD_PANEL_RESB);
78 gpio_free(LCD_PANEL_INI);
79 gpio_free(LCD_PANEL_UD);
80 gpio_free(LCD_PANEL_LR);
81}
82
83static int omap3evm_panel_enable(struct lcd_panel *panel)
84{
85 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0);
86 return 0;
87}
88
89static void omap3evm_panel_disable(struct lcd_panel *panel)
90{
91 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
92}
93
94static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel)
95{
96 return 0;
97}
98
99static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
100 unsigned int level)
101{
102 u8 c;
103 if ((level >= 0) && (level <= 100)) {
104 c = (125 * (100 - level)) / 100 + 2;
105 twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
106 bklight_level = level;
107 }
108 return 0;
109}
110
111static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel)
112{
113 return bklight_level;
114}
115
116static unsigned int omap3evm_bklight_getmaxlevel(struct lcd_panel *panel)
117{
118 return 100;
119}
120
121struct lcd_panel omap3evm_panel = {
122 .name = "omap3evm",
123 .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
124 OMAP_LCDC_INV_HSYNC,
125
126 .bpp = 16,
127 .data_lines = 18,
128 .x_res = 480,
129 .y_res = 640,
130 .hsw = 3, /* hsync_len (4) - 1 */
131 .hfp = 3, /* right_margin (4) - 1 */
132 .hbp = 39, /* left_margin (40) - 1 */
133 .vsw = 1, /* vsync_len (2) - 1 */
134 .vfp = 2, /* lower_margin */
135 .vbp = 7, /* upper_margin (8) - 1 */
136
137 .pixel_clock = 26000,
138
139 .init = omap3evm_panel_init,
140 .cleanup = omap3evm_panel_cleanup,
141 .enable = omap3evm_panel_enable,
142 .disable = omap3evm_panel_disable,
143 .get_caps = omap3evm_panel_get_caps,
144 .set_bklight_level = omap3evm_bklight_setlevel,
145 .get_bklight_level = omap3evm_bklight_getlevel,
146 .get_bklight_max = omap3evm_bklight_getmaxlevel,
147};
148
149static int omap3evm_panel_probe(struct platform_device *pdev)
150{
151 omapfb_register_panel(&omap3evm_panel);
152 return 0;
153}
154
155static int omap3evm_panel_remove(struct platform_device *pdev)
156{
157 return 0;
158}
159
160static int omap3evm_panel_suspend(struct platform_device *pdev,
161 pm_message_t mesg)
162{
163 return 0;
164}
165
166static int omap3evm_panel_resume(struct platform_device *pdev)
167{
168 return 0;
169}
170
171struct platform_driver omap3evm_panel_driver = {
172 .probe = omap3evm_panel_probe,
173 .remove = omap3evm_panel_remove,
174 .suspend = omap3evm_panel_suspend,
175 .resume = omap3evm_panel_resume,
176 .driver = {
177 .name = "omap3evm_lcd",
178 .owner = THIS_MODULE,
179 },
180};
181
182static int __init omap3evm_panel_drv_init(void)
183{
184 return platform_driver_register(&omap3evm_panel_driver);
185}
186
187static void __exit omap3evm_panel_drv_exit(void)
188{
189 platform_driver_unregister(&omap3evm_panel_driver);
190}
191
192module_init(omap3evm_panel_drv_init);
193module_exit(omap3evm_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c
deleted file mode 100644
index b8fd5b2ec29..00000000000
--- a/drivers/video/omap/lcd_overo.c
+++ /dev/null
@@ -1,180 +0,0 @@
1/*
2 * LCD panel support for the Gumstix Overo
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/platform_device.h>
24#include <linux/i2c/twl.h>
25
26#include <asm/gpio.h>
27#include <plat/mux.h>
28#include <asm/mach-types.h>
29
30#include "omapfb.h"
31
32#define LCD_ENABLE 144
33
34static int overo_panel_init(struct lcd_panel *panel,
35 struct omapfb_device *fbdev)
36{
37 if ((gpio_request(LCD_ENABLE, "LCD_ENABLE") == 0) &&
38 (gpio_direction_output(LCD_ENABLE, 1) == 0))
39 gpio_export(LCD_ENABLE, 0);
40 else
41 printk(KERN_ERR "could not obtain gpio for LCD_ENABLE\n");
42
43 return 0;
44}
45
46static void overo_panel_cleanup(struct lcd_panel *panel)
47{
48 gpio_free(LCD_ENABLE);
49}
50
51static int overo_panel_enable(struct lcd_panel *panel)
52{
53 gpio_set_value(LCD_ENABLE, 1);
54 return 0;
55}
56
57static void overo_panel_disable(struct lcd_panel *panel)
58{
59 gpio_set_value(LCD_ENABLE, 0);
60}
61
62static unsigned long overo_panel_get_caps(struct lcd_panel *panel)
63{
64 return 0;
65}
66
67struct lcd_panel overo_panel = {
68 .name = "overo",
69 .config = OMAP_LCDC_PANEL_TFT,
70 .bpp = 16,
71 .data_lines = 24,
72
73#if defined CONFIG_FB_OMAP_031M3R
74
75 /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
76 .x_res = 640,
77 .y_res = 480,
78 .hfp = 48,
79 .hsw = 32,
80 .hbp = 80,
81 .vfp = 3,
82 .vsw = 4,
83 .vbp = 7,
84 .pixel_clock = 23500,
85
86#elif defined CONFIG_FB_OMAP_048M3R
87
88 /* 800 x 600 @ 60 Hz Reduced blanking VESA CVT 0.48M3-R */
89 .x_res = 800,
90 .y_res = 600,
91 .hfp = 48,
92 .hsw = 32,
93 .hbp = 80,
94 .vfp = 3,
95 .vsw = 4,
96 .vbp = 11,
97 .pixel_clock = 35500,
98
99#elif defined CONFIG_FB_OMAP_079M3R
100
101 /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */
102 .x_res = 1024,
103 .y_res = 768,
104 .hfp = 48,
105 .hsw = 32,
106 .hbp = 80,
107 .vfp = 3,
108 .vsw = 4,
109 .vbp = 15,
110 .pixel_clock = 56000,
111
112#elif defined CONFIG_FB_OMAP_092M9R
113
114 /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
115 .x_res = 1280,
116 .y_res = 720,
117 .hfp = 48,
118 .hsw = 32,
119 .hbp = 80,
120 .vfp = 3,
121 .vsw = 5,
122 .vbp = 13,
123 .pixel_clock = 64000,
124
125#else
126
127 /* use 640 x 480 if no config option */
128 /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
129 .x_res = 640,
130 .y_res = 480,
131 .hfp = 48,
132 .hsw = 32,
133 .hbp = 80,
134 .vfp = 3,
135 .vsw = 4,
136 .vbp = 7,
137 .pixel_clock = 23500,
138
139#endif
140
141 .init = overo_panel_init,
142 .cleanup = overo_panel_cleanup,
143 .enable = overo_panel_enable,
144 .disable = overo_panel_disable,
145 .get_caps = overo_panel_get_caps,
146};
147
148static int overo_panel_probe(struct platform_device *pdev)
149{
150 omapfb_register_panel(&overo_panel);
151 return 0;
152}
153
154static int overo_panel_remove(struct platform_device *pdev)
155{
156 /* omapfb does not have unregister_panel */
157 return 0;
158}
159
160static struct platform_driver overo_panel_driver = {
161 .probe = overo_panel_probe,
162 .remove = overo_panel_remove,
163 .driver = {
164 .name = "overo_lcd",
165 .owner = THIS_MODULE,
166 },
167};
168
169static int __init overo_panel_drv_init(void)
170{
171 return platform_driver_register(&overo_panel_driver);
172}
173
174static void __exit overo_panel_drv_exit(void)
175{
176 platform_driver_unregister(&overo_panel_driver);
177}
178
179module_init(overo_panel_drv_init);
180module_exit(overo_panel_drv_exit);
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 609a2807317..8d8e1fe1901 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI
10 Supports LCD Panel used in TI SDP3430 and EVM boards, 10 Supports LCD Panel used in TI SDP3430 and EVM boards,
11 OMAP3517 EVM boards and CM-T35. 11 OMAP3517 EVM boards and CM-T35.
12 12
13config PANEL_DVI
14 tristate "DVI output"
15 depends on OMAP2_DSS_DPI
16 help
17 Driver for external monitors, connected via DVI. The driver uses i2c
18 to read EDID information from the monitor.
19
13config PANEL_LGPHILIPS_LB035Q02 20config PANEL_LGPHILIPS_LB035Q02
14 tristate "LG.Philips LB035Q02 LCD Panel" 21 tristate "LG.Philips LB035Q02 LCD Panel"
15 depends on OMAP2_DSS_DPI && SPI 22 depends on OMAP2_DSS_DPI && SPI
@@ -19,20 +26,30 @@ config PANEL_LGPHILIPS_LB035Q02
19config PANEL_SHARP_LS037V7DW01 26config PANEL_SHARP_LS037V7DW01
20 tristate "Sharp LS037V7DW01 LCD Panel" 27 tristate "Sharp LS037V7DW01 LCD Panel"
21 depends on OMAP2_DSS_DPI 28 depends on OMAP2_DSS_DPI
22 select BACKLIGHT_CLASS_DEVICE 29 depends on BACKLIGHT_CLASS_DEVICE
23 help 30 help
24 LCD Panel used in TI's SDP3430 and EVM boards 31 LCD Panel used in TI's SDP3430 and EVM boards
25 32
26config PANEL_NEC_NL8048HL11_01B 33config PANEL_NEC_NL8048HL11_01B
27 tristate "NEC NL8048HL11-01B Panel" 34 tristate "NEC NL8048HL11-01B Panel"
28 depends on OMAP2_DSS_DPI 35 depends on OMAP2_DSS_DPI
36 depends on SPI
37 depends on BACKLIGHT_CLASS_DEVICE
29 help 38 help
30 This NEC NL8048HL11-01B panel is TFT LCD 39 This NEC NL8048HL11-01B panel is TFT LCD
31 used in the Zoom2/3/3630 sdp boards. 40 used in the Zoom2/3/3630 sdp boards.
32 41
42config PANEL_PICODLP
43 tristate "TI PICO DLP mini-projector"
44 depends on OMAP2_DSS && I2C
45 help
46 A mini-projector used in TI's SDP4430 and EVM boards
47 For more info please visit http://www.dlp.com/projector/
48
33config PANEL_TAAL 49config PANEL_TAAL
34 tristate "Taal DSI Panel" 50 tristate "Taal DSI Panel"
35 depends on OMAP2_DSS_DSI 51 depends on OMAP2_DSS_DSI
52 depends on BACKLIGHT_CLASS_DEVICE
36 help 53 help
37 Taal DSI command mode panel from TPO. 54 Taal DSI command mode panel from TPO.
38 55
@@ -45,7 +62,14 @@ config PANEL_TPO_TD043MTEA1
45config PANEL_ACX565AKM 62config PANEL_ACX565AKM
46 tristate "ACX565AKM Panel" 63 tristate "ACX565AKM Panel"
47 depends on OMAP2_DSS_SDI && SPI 64 depends on OMAP2_DSS_SDI && SPI
48 select BACKLIGHT_CLASS_DEVICE 65 depends on BACKLIGHT_CLASS_DEVICE
49 help 66 help
50 This is the LCD panel used on Nokia N900 67 This is the LCD panel used on Nokia N900
68
69config PANEL_N8X0
70 tristate "N8X0 Panel"
71 depends on OMAP2_DSS_RFBI && SPI
72 depends on BACKLIGHT_CLASS_DEVICE
73 help
74 This is the LCD panel used on Nokia N8x0
51endmenu 75endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index 0f601ab3abf..fbfafc6eebb 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,8 +1,11 @@
1obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o 1obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
2obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
2obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o 3obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
3obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o 4obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
4obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o 5obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
5 6
6obj-$(CONFIG_PANEL_TAAL) += panel-taal.o 7obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
8obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o
7obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o 9obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
8obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o 10obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
11obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o
diff --git a/drivers/video/omap2/displays/panel-dvi.c b/drivers/video/omap2/displays/panel-dvi.c
new file mode 100644
index 00000000000..03eb14af33e
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-dvi.c
@@ -0,0 +1,363 @@
1/*
2 * DVI output support
3 *
4 * Copyright (C) 2011 Texas Instruments Inc
5 * Author: Tomi Valkeinen <tomi.valkeinen@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/module.h>
21#include <linux/slab.h>
22#include <video/omapdss.h>
23#include <linux/i2c.h>
24#include <drm/drm_edid.h>
25
26#include <video/omap-panel-dvi.h>
27
28static const struct omap_video_timings panel_dvi_default_timings = {
29 .x_res = 640,
30 .y_res = 480,
31
32 .pixel_clock = 23500,
33
34 .hfp = 48,
35 .hsw = 32,
36 .hbp = 80,
37
38 .vfp = 3,
39 .vsw = 4,
40 .vbp = 7,
41};
42
43struct panel_drv_data {
44 struct omap_dss_device *dssdev;
45
46 struct mutex lock;
47};
48
49static inline struct panel_dvi_platform_data
50*get_pdata(const struct omap_dss_device *dssdev)
51{
52 return dssdev->data;
53}
54
55static int panel_dvi_power_on(struct omap_dss_device *dssdev)
56{
57 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
58 int r;
59
60 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
61 return 0;
62
63 r = omapdss_dpi_display_enable(dssdev);
64 if (r)
65 goto err0;
66
67 if (pdata->platform_enable) {
68 r = pdata->platform_enable(dssdev);
69 if (r)
70 goto err1;
71 }
72
73 return 0;
74err1:
75 omapdss_dpi_display_disable(dssdev);
76err0:
77 return r;
78}
79
80static void panel_dvi_power_off(struct omap_dss_device *dssdev)
81{
82 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
83
84 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
85 return;
86
87 if (pdata->platform_disable)
88 pdata->platform_disable(dssdev);
89
90 omapdss_dpi_display_disable(dssdev);
91}
92
93static int panel_dvi_probe(struct omap_dss_device *dssdev)
94{
95 struct panel_drv_data *ddata;
96
97 ddata = kzalloc(sizeof(*ddata), GFP_KERNEL);
98 if (!ddata)
99 return -ENOMEM;
100
101 dssdev->panel.timings = panel_dvi_default_timings;
102 dssdev->panel.config = OMAP_DSS_LCD_TFT;
103
104 ddata->dssdev = dssdev;
105 mutex_init(&ddata->lock);
106
107 dev_set_drvdata(&dssdev->dev, ddata);
108
109 return 0;
110}
111
112static void __exit panel_dvi_remove(struct omap_dss_device *dssdev)
113{
114 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
115
116 mutex_lock(&ddata->lock);
117
118 dev_set_drvdata(&dssdev->dev, NULL);
119
120 mutex_unlock(&ddata->lock);
121
122 kfree(ddata);
123}
124
125static int panel_dvi_enable(struct omap_dss_device *dssdev)
126{
127 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
128 int r;
129
130 mutex_lock(&ddata->lock);
131
132 r = panel_dvi_power_on(dssdev);
133 if (r == 0)
134 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
135
136 mutex_unlock(&ddata->lock);
137
138 return r;
139}
140
141static void panel_dvi_disable(struct omap_dss_device *dssdev)
142{
143 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
144
145 mutex_lock(&ddata->lock);
146
147 panel_dvi_power_off(dssdev);
148
149 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
150
151 mutex_unlock(&ddata->lock);
152}
153
154static int panel_dvi_suspend(struct omap_dss_device *dssdev)
155{
156 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
157
158 mutex_lock(&ddata->lock);
159
160 panel_dvi_power_off(dssdev);
161
162 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
163
164 mutex_unlock(&ddata->lock);
165
166 return 0;
167}
168
169static int panel_dvi_resume(struct omap_dss_device *dssdev)
170{
171 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
172 int r;
173
174 mutex_lock(&ddata->lock);
175
176 r = panel_dvi_power_on(dssdev);
177 if (r == 0)
178 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
179
180 mutex_unlock(&ddata->lock);
181
182 return r;
183}
184
185static void panel_dvi_set_timings(struct omap_dss_device *dssdev,
186 struct omap_video_timings *timings)
187{
188 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
189
190 mutex_lock(&ddata->lock);
191 dpi_set_timings(dssdev, timings);
192 mutex_unlock(&ddata->lock);
193}
194
195static void panel_dvi_get_timings(struct omap_dss_device *dssdev,
196 struct omap_video_timings *timings)
197{
198 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
199
200 mutex_lock(&ddata->lock);
201 *timings = dssdev->panel.timings;
202 mutex_unlock(&ddata->lock);
203}
204
205static int panel_dvi_check_timings(struct omap_dss_device *dssdev,
206 struct omap_video_timings *timings)
207{
208 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
209 int r;
210
211 mutex_lock(&ddata->lock);
212 r = dpi_check_timings(dssdev, timings);
213 mutex_unlock(&ddata->lock);
214
215 return r;
216}
217
218
219static int panel_dvi_ddc_read(struct i2c_adapter *adapter,
220 unsigned char *buf, u16 count, u8 offset)
221{
222 int r, retries;
223
224 for (retries = 3; retries > 0; retries--) {
225 struct i2c_msg msgs[] = {
226 {
227 .addr = DDC_ADDR,
228 .flags = 0,
229 .len = 1,
230 .buf = &offset,
231 }, {
232 .addr = DDC_ADDR,
233 .flags = I2C_M_RD,
234 .len = count,
235 .buf = buf,
236 }
237 };
238
239 r = i2c_transfer(adapter, msgs, 2);
240 if (r == 2)
241 return 0;
242
243 if (r != -EAGAIN)
244 break;
245 }
246
247 return r < 0 ? r : -EIO;
248}
249
250static int panel_dvi_read_edid(struct omap_dss_device *dssdev,
251 u8 *edid, int len)
252{
253 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
254 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
255 struct i2c_adapter *adapter;
256 int r, l, bytes_read;
257
258 mutex_lock(&ddata->lock);
259
260 if (pdata->i2c_bus_num == 0) {
261 r = -ENODEV;
262 goto err;
263 }
264
265 adapter = i2c_get_adapter(pdata->i2c_bus_num);
266 if (!adapter) {
267 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
268 pdata->i2c_bus_num);
269 r = -EINVAL;
270 goto err;
271 }
272
273 l = min(EDID_LENGTH, len);
274 r = panel_dvi_ddc_read(adapter, edid, l, 0);
275 if (r)
276 goto err;
277
278 bytes_read = l;
279
280 /* if there are extensions, read second block */
281 if (len > EDID_LENGTH && edid[0x7e] > 0) {
282 l = min(EDID_LENGTH, len - EDID_LENGTH);
283
284 r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH,
285 l, EDID_LENGTH);
286 if (r)
287 goto err;
288
289 bytes_read += l;
290 }
291
292 mutex_unlock(&ddata->lock);
293
294 return bytes_read;
295
296err:
297 mutex_unlock(&ddata->lock);
298 return r;
299}
300
301static bool panel_dvi_detect(struct omap_dss_device *dssdev)
302{
303 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
304 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
305 struct i2c_adapter *adapter;
306 unsigned char out;
307 int r;
308
309 mutex_lock(&ddata->lock);
310
311 if (pdata->i2c_bus_num == 0)
312 goto out;
313
314 adapter = i2c_get_adapter(pdata->i2c_bus_num);
315 if (!adapter)
316 goto out;
317
318 r = panel_dvi_ddc_read(adapter, &out, 1, 0);
319
320 mutex_unlock(&ddata->lock);
321
322 return r == 0;
323
324out:
325 mutex_unlock(&ddata->lock);
326 return true;
327}
328
329static struct omap_dss_driver panel_dvi_driver = {
330 .probe = panel_dvi_probe,
331 .remove = __exit_p(panel_dvi_remove),
332
333 .enable = panel_dvi_enable,
334 .disable = panel_dvi_disable,
335 .suspend = panel_dvi_suspend,
336 .resume = panel_dvi_resume,
337
338 .set_timings = panel_dvi_set_timings,
339 .get_timings = panel_dvi_get_timings,
340 .check_timings = panel_dvi_check_timings,
341
342 .read_edid = panel_dvi_read_edid,
343 .detect = panel_dvi_detect,
344
345 .driver = {
346 .name = "dvi",
347 .owner = THIS_MODULE,
348 },
349};
350
351static int __init panel_dvi_init(void)
352{
353 return omap_dss_register_driver(&panel_dvi_driver);
354}
355
356static void __exit panel_dvi_exit(void)
357{
358 omap_dss_unregister_driver(&panel_dvi_driver);
359}
360
361module_init(panel_dvi_init);
362module_exit(panel_dvi_exit);
363MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 9c90f75653f..519c47d2057 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -58,30 +58,6 @@ struct panel_config {
58 58
59/* Panel configurations */ 59/* Panel configurations */
60static struct panel_config generic_dpi_panels[] = { 60static struct panel_config generic_dpi_panels[] = {
61 /* Generic Panel */
62 {
63 {
64 .x_res = 640,
65 .y_res = 480,
66
67 .pixel_clock = 23500,
68
69 .hfp = 48,
70 .hsw = 32,
71 .hbp = 80,
72
73 .vfp = 3,
74 .vsw = 4,
75 .vbp = 7,
76 },
77 .acbi = 0x0,
78 .acb = 0x0,
79 .config = OMAP_DSS_LCD_TFT,
80 .power_on_delay = 0,
81 .power_off_delay = 0,
82 .name = "generic",
83 },
84
85 /* Sharp LQ043T1DG01 */ 61 /* Sharp LQ043T1DG01 */
86 { 62 {
87 { 63 {
@@ -232,6 +208,95 @@ static struct panel_config generic_dpi_panels[] = {
232 .power_off_delay = 0, 208 .power_off_delay = 0,
233 .name = "powertip_ph480272t", 209 .name = "powertip_ph480272t",
234 }, 210 },
211
212 /* Innolux AT070TN83 */
213 {
214 {
215 .x_res = 800,
216 .y_res = 480,
217
218 .pixel_clock = 40000,
219
220 .hsw = 48,
221 .hfp = 1,
222 .hbp = 1,
223
224 .vsw = 3,
225 .vfp = 12,
226 .vbp = 25,
227 },
228 .acbi = 0x0,
229 .acb = 0x28,
230 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
231 OMAP_DSS_LCD_IHS,
232 .power_on_delay = 0,
233 .power_off_delay = 0,
234 .name = "innolux_at070tn83",
235 },
236
237 /* NEC NL2432DR22-11B */
238 {
239 {
240 .x_res = 240,
241 .y_res = 320,
242
243 .pixel_clock = 5400,
244
245 .hsw = 3,
246 .hfp = 3,
247 .hbp = 39,
248
249 .vsw = 1,
250 .vfp = 2,
251 .vbp = 7,
252 },
253 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
254 OMAP_DSS_LCD_IHS,
255 .name = "nec_nl2432dr22-11b",
256 },
257
258 /* Unknown panel used in OMAP H4 */
259 {
260 {
261 .x_res = 240,
262 .y_res = 320,
263
264 .pixel_clock = 6250,
265
266 .hsw = 15,
267 .hfp = 15,
268 .hbp = 60,
269
270 .vsw = 1,
271 .vfp = 1,
272 .vbp = 1,
273 },
274 .config = OMAP_DSS_LCD_TFT,
275
276 .name = "h4",
277 },
278
279 /* Unknown panel used in Samsung OMAP2 Apollon */
280 {
281 {
282 .x_res = 480,
283 .y_res = 272,
284
285 .pixel_clock = 6250,
286
287 .hsw = 41,
288 .hfp = 2,
289 .hbp = 2,
290
291 .vsw = 10,
292 .vfp = 2,
293 .vbp = 2,
294 },
295 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
296 OMAP_DSS_LCD_IHS,
297
298 .name = "apollon",
299 },
235}; 300};
236 301
237struct panel_drv_data { 302struct panel_drv_data {
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
new file mode 100644
index 00000000000..150e8bae35a
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -0,0 +1,747 @@
1/* #define DEBUG */
2
3#include <linux/module.h>
4#include <linux/delay.h>
5#include <linux/slab.h>
6#include <linux/gpio.h>
7#include <linux/spi/spi.h>
8#include <linux/backlight.h>
9#include <linux/fb.h>
10
11#include <video/omapdss.h>
12#include <video/omap-panel-n8x0.h>
13
14#define BLIZZARD_REV_CODE 0x00
15#define BLIZZARD_CONFIG 0x02
16#define BLIZZARD_PLL_DIV 0x04
17#define BLIZZARD_PLL_LOCK_RANGE 0x06
18#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
19#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
20#define BLIZZARD_PLL_MODE 0x0c
21#define BLIZZARD_CLK_SRC 0x0e
22#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
23#define BLIZZARD_MEM_BANK0_STATUS 0x14
24#define BLIZZARD_PANEL_CONFIGURATION 0x28
25#define BLIZZARD_HDISP 0x2a
26#define BLIZZARD_HNDP 0x2c
27#define BLIZZARD_VDISP0 0x2e
28#define BLIZZARD_VDISP1 0x30
29#define BLIZZARD_VNDP 0x32
30#define BLIZZARD_HSW 0x34
31#define BLIZZARD_VSW 0x38
32#define BLIZZARD_DISPLAY_MODE 0x68
33#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
34#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
35#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
36#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
37#define BLIZZARD_POWER_SAVE 0xE6
38#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
39
40/* Data source select */
41/* For S1D13745 */
42#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
43#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
44#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
45#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
46/* For S1D13744 */
47#define BLIZZARD_SRC_WRITE_LCD 0x00
48#define BLIZZARD_SRC_BLT_LCD 0x06
49
50#define BLIZZARD_COLOR_RGB565 0x01
51#define BLIZZARD_COLOR_YUV420 0x09
52
53#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
54#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
55
56#define MIPID_CMD_READ_DISP_ID 0x04
57#define MIPID_CMD_READ_RED 0x06
58#define MIPID_CMD_READ_GREEN 0x07
59#define MIPID_CMD_READ_BLUE 0x08
60#define MIPID_CMD_READ_DISP_STATUS 0x09
61#define MIPID_CMD_RDDSDR 0x0F
62#define MIPID_CMD_SLEEP_IN 0x10
63#define MIPID_CMD_SLEEP_OUT 0x11
64#define MIPID_CMD_DISP_OFF 0x28
65#define MIPID_CMD_DISP_ON 0x29
66
67static struct panel_drv_data {
68 struct mutex lock;
69
70 struct omap_dss_device *dssdev;
71 struct spi_device *spidev;
72 struct backlight_device *bldev;
73
74 int blizzard_ver;
75} s_drv_data;
76
77
78static inline
79struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
80{
81 return dssdev->data;
82}
83
84static inline
85struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
86{
87 return &s_drv_data;
88}
89
90
91static inline void blizzard_cmd(u8 cmd)
92{
93 omap_rfbi_write_command(&cmd, 1);
94}
95
96static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
97{
98 omap_rfbi_write_command(&cmd, 1);
99 omap_rfbi_write_data(buf, len);
100}
101
102static inline void blizzard_read(u8 cmd, u8 *buf, int len)
103{
104 omap_rfbi_write_command(&cmd, 1);
105 omap_rfbi_read_data(buf, len);
106}
107
108static u8 blizzard_read_reg(u8 cmd)
109{
110 u8 data;
111 blizzard_read(cmd, &data, 1);
112 return data;
113}
114
115static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
116 int x, int y, int w, int h)
117{
118 struct panel_drv_data *ddata = get_drv_data(dssdev);
119 u8 tmp[18];
120 int x_end, y_end;
121
122 x_end = x + w - 1;
123 y_end = y + h - 1;
124
125 tmp[0] = x;
126 tmp[1] = x >> 8;
127 tmp[2] = y;
128 tmp[3] = y >> 8;
129 tmp[4] = x_end;
130 tmp[5] = x_end >> 8;
131 tmp[6] = y_end;
132 tmp[7] = y_end >> 8;
133
134 /* scaling? */
135 tmp[8] = x;
136 tmp[9] = x >> 8;
137 tmp[10] = y;
138 tmp[11] = y >> 8;
139 tmp[12] = x_end;
140 tmp[13] = x_end >> 8;
141 tmp[14] = y_end;
142 tmp[15] = y_end >> 8;
143
144 tmp[16] = BLIZZARD_COLOR_RGB565;
145
146 if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745)
147 tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
148 else
149 tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ?
150 BLIZZARD_SRC_WRITE_LCD :
151 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
152
153 omap_rfbi_configure(dssdev, 16, 8);
154
155 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
156
157 omap_rfbi_configure(dssdev, 16, 16);
158}
159
160static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
161 int wlen, u8 *rbuf, int rlen)
162{
163 struct spi_message m;
164 struct spi_transfer *x, xfer[4];
165 u16 w;
166 int r;
167
168 spi_message_init(&m);
169
170 memset(xfer, 0, sizeof(xfer));
171 x = &xfer[0];
172
173 cmd &= 0xff;
174 x->tx_buf = &cmd;
175 x->bits_per_word = 9;
176 x->len = 2;
177 spi_message_add_tail(x, &m);
178
179 if (wlen) {
180 x++;
181 x->tx_buf = wbuf;
182 x->len = wlen;
183 x->bits_per_word = 9;
184 spi_message_add_tail(x, &m);
185 }
186
187 if (rlen) {
188 x++;
189 x->rx_buf = &w;
190 x->len = 1;
191 spi_message_add_tail(x, &m);
192
193 if (rlen > 1) {
194 /* Arrange for the extra clock before the first
195 * data bit.
196 */
197 x->bits_per_word = 9;
198 x->len = 2;
199
200 x++;
201 x->rx_buf = &rbuf[1];
202 x->len = rlen - 1;
203 spi_message_add_tail(x, &m);
204 }
205 }
206
207 r = spi_sync(spi, &m);
208 if (r < 0)
209 dev_dbg(&spi->dev, "spi_sync %d\n", r);
210
211 if (rlen)
212 rbuf[0] = w & 0xff;
213}
214
215static inline void mipid_cmd(struct spi_device *spi, int cmd)
216{
217 mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
218}
219
220static inline void mipid_write(struct spi_device *spi,
221 int reg, const u8 *buf, int len)
222{
223 mipid_transfer(spi, reg, buf, len, NULL, 0);
224}
225
226static inline void mipid_read(struct spi_device *spi,
227 int reg, u8 *buf, int len)
228{
229 mipid_transfer(spi, reg, NULL, 0, buf, len);
230}
231
232static void set_data_lines(struct spi_device *spi, int data_lines)
233{
234 u16 par;
235
236 switch (data_lines) {
237 case 16:
238 par = 0x150;
239 break;
240 case 18:
241 par = 0x160;
242 break;
243 case 24:
244 par = 0x170;
245 break;
246 }
247
248 mipid_write(spi, 0x3a, (u8 *)&par, 2);
249}
250
251static void send_init_string(struct spi_device *spi)
252{
253 u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
254 mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
255}
256
257static void send_display_on(struct spi_device *spi)
258{
259 mipid_cmd(spi, MIPID_CMD_DISP_ON);
260}
261
262static void send_display_off(struct spi_device *spi)
263{
264 mipid_cmd(spi, MIPID_CMD_DISP_OFF);
265}
266
267static void send_sleep_out(struct spi_device *spi)
268{
269 mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
270 msleep(120);
271}
272
273static void send_sleep_in(struct spi_device *spi)
274{
275 mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
276 msleep(50);
277}
278
279static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
280{
281 int r;
282 struct panel_n8x0_data *bdata = get_board_data(dssdev);
283 struct panel_drv_data *ddata = get_drv_data(dssdev);
284 struct spi_device *spi = ddata->spidev;
285 u8 rev, conf;
286 u8 display_id[3];
287 const char *panel_name;
288
289 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
290 return 0;
291
292 gpio_direction_output(bdata->ctrl_pwrdown, 1);
293
294 if (bdata->platform_enable) {
295 r = bdata->platform_enable(dssdev);
296 if (r)
297 goto err_plat_en;
298 }
299
300 r = omapdss_rfbi_display_enable(dssdev);
301 if (r)
302 goto err_rfbi_en;
303
304 rev = blizzard_read_reg(BLIZZARD_REV_CODE);
305 conf = blizzard_read_reg(BLIZZARD_CONFIG);
306
307 switch (rev & 0xfc) {
308 case 0x9c:
309 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
310 dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d "
311 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
312 break;
313 case 0xa4:
314 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
315 dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d "
316 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
317 break;
318 default:
319 dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
320 r = -ENODEV;
321 goto err_inv_chip;
322 }
323
324 /* panel */
325
326 gpio_direction_output(bdata->panel_reset, 1);
327
328 mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
329 dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
330 display_id[0], display_id[1], display_id[2]);
331
332 switch (display_id[0]) {
333 case 0x45:
334 panel_name = "lph8923";
335 break;
336 case 0x83:
337 panel_name = "ls041y3";
338 break;
339 default:
340 dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
341 display_id[0]);
342 r = -ENODEV;
343 goto err_inv_panel;
344 }
345
346 dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
347 panel_name, display_id[1]);
348
349 send_sleep_out(spi);
350 send_init_string(spi);
351 set_data_lines(spi, 24);
352 send_display_on(spi);
353
354 return 0;
355
356err_inv_panel:
357 /*
358 * HACK: we should turn off the panel here, but there is some problem
359 * with the initialization sequence, and we fail to init the panel if we
360 * have turned it off
361 */
362 /* gpio_direction_output(bdata->panel_reset, 0); */
363err_inv_chip:
364 omapdss_rfbi_display_disable(dssdev);
365err_rfbi_en:
366 if (bdata->platform_disable)
367 bdata->platform_disable(dssdev);
368err_plat_en:
369 gpio_direction_output(bdata->ctrl_pwrdown, 0);
370 return r;
371}
372
373static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
374{
375 struct panel_n8x0_data *bdata = get_board_data(dssdev);
376 struct panel_drv_data *ddata = get_drv_data(dssdev);
377 struct spi_device *spi = ddata->spidev;
378
379 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
380 return;
381
382 send_display_off(spi);
383 send_sleep_in(spi);
384
385 if (bdata->platform_disable)
386 bdata->platform_disable(dssdev);
387
388 /*
389 * HACK: we should turn off the panel here, but there is some problem
390 * with the initialization sequence, and we fail to init the panel if we
391 * have turned it off
392 */
393 /* gpio_direction_output(bdata->panel_reset, 0); */
394 gpio_direction_output(bdata->ctrl_pwrdown, 0);
395 omapdss_rfbi_display_disable(dssdev);
396}
397
398static const struct rfbi_timings n8x0_panel_timings = {
399 .cs_on_time = 0,
400
401 .we_on_time = 9000,
402 .we_off_time = 18000,
403 .we_cycle_time = 36000,
404
405 .re_on_time = 9000,
406 .re_off_time = 27000,
407 .re_cycle_time = 36000,
408
409 .access_time = 27000,
410 .cs_off_time = 36000,
411
412 .cs_pulse_width = 0,
413};
414
415static int n8x0_bl_update_status(struct backlight_device *dev)
416{
417 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
418 struct panel_n8x0_data *bdata = get_board_data(dssdev);
419 struct panel_drv_data *ddata = get_drv_data(dssdev);
420 int r;
421 int level;
422
423 mutex_lock(&ddata->lock);
424
425 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
426 dev->props.power == FB_BLANK_UNBLANK)
427 level = dev->props.brightness;
428 else
429 level = 0;
430
431 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
432
433 if (!bdata->set_backlight)
434 r = -EINVAL;
435 else
436 r = bdata->set_backlight(dssdev, level);
437
438 mutex_unlock(&ddata->lock);
439
440 return r;
441}
442
443static int n8x0_bl_get_intensity(struct backlight_device *dev)
444{
445 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
446 dev->props.power == FB_BLANK_UNBLANK)
447 return dev->props.brightness;
448
449 return 0;
450}
451
452static const struct backlight_ops n8x0_bl_ops = {
453 .get_brightness = n8x0_bl_get_intensity,
454 .update_status = n8x0_bl_update_status,
455};
456
457static int n8x0_panel_probe(struct omap_dss_device *dssdev)
458{
459 struct panel_n8x0_data *bdata = get_board_data(dssdev);
460 struct panel_drv_data *ddata;
461 struct backlight_device *bldev;
462 struct backlight_properties props;
463 int r;
464
465 dev_dbg(&dssdev->dev, "probe\n");
466
467 if (!bdata)
468 return -EINVAL;
469
470 s_drv_data.dssdev = dssdev;
471
472 ddata = &s_drv_data;
473
474 mutex_init(&ddata->lock);
475
476 dssdev->panel.config = OMAP_DSS_LCD_TFT;
477 dssdev->panel.timings.x_res = 800;
478 dssdev->panel.timings.y_res = 480;
479 dssdev->ctrl.pixel_size = 16;
480 dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
481
482 memset(&props, 0, sizeof(props));
483 props.max_brightness = 127;
484 props.type = BACKLIGHT_PLATFORM;
485 bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
486 dssdev, &n8x0_bl_ops, &props);
487 if (IS_ERR(bldev)) {
488 r = PTR_ERR(bldev);
489 dev_err(&dssdev->dev, "register backlight failed\n");
490 return r;
491 }
492
493 ddata->bldev = bldev;
494
495 bldev->props.fb_blank = FB_BLANK_UNBLANK;
496 bldev->props.power = FB_BLANK_UNBLANK;
497 bldev->props.brightness = 127;
498
499 n8x0_bl_update_status(bldev);
500
501 return 0;
502}
503
504static void n8x0_panel_remove(struct omap_dss_device *dssdev)
505{
506 struct panel_drv_data *ddata = get_drv_data(dssdev);
507 struct backlight_device *bldev;
508
509 dev_dbg(&dssdev->dev, "remove\n");
510
511 bldev = ddata->bldev;
512 bldev->props.power = FB_BLANK_POWERDOWN;
513 n8x0_bl_update_status(bldev);
514 backlight_device_unregister(bldev);
515
516 dev_set_drvdata(&dssdev->dev, NULL);
517}
518
519static int n8x0_panel_enable(struct omap_dss_device *dssdev)
520{
521 struct panel_drv_data *ddata = get_drv_data(dssdev);
522 int r;
523
524 dev_dbg(&dssdev->dev, "enable\n");
525
526 mutex_lock(&ddata->lock);
527
528 rfbi_bus_lock();
529
530 r = n8x0_panel_power_on(dssdev);
531
532 rfbi_bus_unlock();
533
534 if (r) {
535 mutex_unlock(&ddata->lock);
536 return r;
537 }
538
539 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
540
541 mutex_unlock(&ddata->lock);
542
543 return 0;
544}
545
546static void n8x0_panel_disable(struct omap_dss_device *dssdev)
547{
548 struct panel_drv_data *ddata = get_drv_data(dssdev);
549
550 dev_dbg(&dssdev->dev, "disable\n");
551
552 mutex_lock(&ddata->lock);
553
554 rfbi_bus_lock();
555
556 n8x0_panel_power_off(dssdev);
557
558 rfbi_bus_unlock();
559
560 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
561
562 mutex_unlock(&ddata->lock);
563}
564
565static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
566{
567 struct panel_drv_data *ddata = get_drv_data(dssdev);
568
569 dev_dbg(&dssdev->dev, "suspend\n");
570
571 mutex_lock(&ddata->lock);
572
573 rfbi_bus_lock();
574
575 n8x0_panel_power_off(dssdev);
576
577 rfbi_bus_unlock();
578
579 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
580
581 mutex_unlock(&ddata->lock);
582
583 return 0;
584}
585
586static int n8x0_panel_resume(struct omap_dss_device *dssdev)
587{
588 struct panel_drv_data *ddata = get_drv_data(dssdev);
589 int r;
590
591 dev_dbg(&dssdev->dev, "resume\n");
592
593 mutex_lock(&ddata->lock);
594
595 rfbi_bus_lock();
596
597 r = n8x0_panel_power_on(dssdev);
598
599 rfbi_bus_unlock();
600
601 if (r) {
602 mutex_unlock(&ddata->lock);
603 return r;
604 }
605
606 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
607
608 mutex_unlock(&ddata->lock);
609
610 return 0;
611}
612
613static void n8x0_panel_get_timings(struct omap_dss_device *dssdev,
614 struct omap_video_timings *timings)
615{
616 *timings = dssdev->panel.timings;
617}
618
619static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
620 u16 *xres, u16 *yres)
621{
622 *xres = dssdev->panel.timings.x_res;
623 *yres = dssdev->panel.timings.y_res;
624}
625
626static void update_done(void *data)
627{
628 rfbi_bus_unlock();
629}
630
631static int n8x0_panel_update(struct omap_dss_device *dssdev,
632 u16 x, u16 y, u16 w, u16 h)
633{
634 struct panel_drv_data *ddata = get_drv_data(dssdev);
635
636 dev_dbg(&dssdev->dev, "update\n");
637
638 mutex_lock(&ddata->lock);
639 rfbi_bus_lock();
640
641 omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
642
643 blizzard_ctrl_setup_update(dssdev, x, y, w, h);
644
645 omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL);
646
647 mutex_unlock(&ddata->lock);
648
649 return 0;
650}
651
652static int n8x0_panel_sync(struct omap_dss_device *dssdev)
653{
654 struct panel_drv_data *ddata = get_drv_data(dssdev);
655
656 dev_dbg(&dssdev->dev, "sync\n");
657
658 mutex_lock(&ddata->lock);
659 rfbi_bus_lock();
660 rfbi_bus_unlock();
661 mutex_unlock(&ddata->lock);
662
663 return 0;
664}
665
666static struct omap_dss_driver n8x0_panel_driver = {
667 .probe = n8x0_panel_probe,
668 .remove = n8x0_panel_remove,
669
670 .enable = n8x0_panel_enable,
671 .disable = n8x0_panel_disable,
672 .suspend = n8x0_panel_suspend,
673 .resume = n8x0_panel_resume,
674
675 .update = n8x0_panel_update,
676 .sync = n8x0_panel_sync,
677
678 .get_resolution = n8x0_panel_get_resolution,
679 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
680
681 .get_timings = n8x0_panel_get_timings,
682
683 .driver = {
684 .name = "n8x0_panel",
685 .owner = THIS_MODULE,
686 },
687};
688
689/* PANEL */
690
691static int mipid_spi_probe(struct spi_device *spi)
692{
693 dev_dbg(&spi->dev, "mipid_spi_probe\n");
694
695 spi->mode = SPI_MODE_0;
696
697 s_drv_data.spidev = spi;
698
699 return 0;
700}
701
702static int mipid_spi_remove(struct spi_device *spi)
703{
704 dev_dbg(&spi->dev, "mipid_spi_remove\n");
705 return 0;
706}
707
708static struct spi_driver mipid_spi_driver = {
709 .driver = {
710 .name = "lcd_mipid",
711 .bus = &spi_bus_type,
712 .owner = THIS_MODULE,
713 },
714 .probe = mipid_spi_probe,
715 .remove = __devexit_p(mipid_spi_remove),
716};
717
718static int __init n8x0_panel_drv_init(void)
719{
720 int r;
721
722 r = spi_register_driver(&mipid_spi_driver);
723 if (r) {
724 pr_err("n8x0_panel: spi driver registration failed\n");
725 return r;
726 }
727
728 r = omap_dss_register_driver(&n8x0_panel_driver);
729 if (r) {
730 pr_err("n8x0_panel: dss driver registration failed\n");
731 spi_unregister_driver(&mipid_spi_driver);
732 return r;
733 }
734
735 return 0;
736}
737
738static void __exit n8x0_panel_drv_exit(void)
739{
740 spi_unregister_driver(&mipid_spi_driver);
741
742 omap_dss_unregister_driver(&n8x0_panel_driver);
743}
744
745module_init(n8x0_panel_drv_init);
746module_exit(n8x0_panel_drv_exit);
747MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
new file mode 100644
index 00000000000..98ebdaddab5
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -0,0 +1,594 @@
1/*
2 * picodlp panel driver
3 * picodlp_i2c_driver: i2c_client driver
4 *
5 * Copyright (C) 2009-2011 Texas Instruments
6 * Author: Mythri P K <mythripk@ti.com>
7 * Mayuresh Janorkar <mayur@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <linux/module.h>
23#include <linux/input.h>
24#include <linux/platform_device.h>
25#include <linux/interrupt.h>
26#include <linux/firmware.h>
27#include <linux/slab.h>
28#include <linux/mutex.h>
29#include <linux/i2c.h>
30#include <linux/delay.h>
31#include <linux/gpio.h>
32
33#include <video/omapdss.h>
34#include <video/omap-panel-picodlp.h>
35
36#include "panel-picodlp.h"
37
38struct picodlp_data {
39 struct mutex lock;
40 struct i2c_client *picodlp_i2c_client;
41};
42
43static struct i2c_board_info picodlp_i2c_board_info = {
44 I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b),
45};
46
47struct picodlp_i2c_data {
48 struct mutex xfer_lock;
49};
50
51static struct i2c_device_id picodlp_i2c_id[] = {
52 { "picodlp_i2c_driver", 0 },
53};
54
55struct picodlp_i2c_command {
56 u8 reg;
57 u32 value;
58};
59
60static struct omap_video_timings pico_ls_timings = {
61 .x_res = 864,
62 .y_res = 480,
63 .hsw = 7,
64 .hfp = 11,
65 .hbp = 7,
66
67 .pixel_clock = 19200,
68
69 .vsw = 2,
70 .vfp = 3,
71 .vbp = 14,
72};
73
74static inline struct picodlp_panel_data
75 *get_panel_data(const struct omap_dss_device *dssdev)
76{
77 return (struct picodlp_panel_data *) dssdev->data;
78}
79
80static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg)
81{
82 u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4];
83 struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
84 struct i2c_msg msg[2];
85
86 mutex_lock(&picodlp_i2c_data->xfer_lock);
87
88 msg[0].addr = client->addr;
89 msg[0].flags = 0;
90 msg[0].len = 2;
91 msg[0].buf = read_cmd;
92
93 msg[1].addr = client->addr;
94 msg[1].flags = I2C_M_RD;
95 msg[1].len = 4;
96 msg[1].buf = data;
97
98 i2c_transfer(client->adapter, msg, 2);
99 mutex_unlock(&picodlp_i2c_data->xfer_lock);
100 return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24));
101}
102
103static int picodlp_i2c_write_block(struct i2c_client *client,
104 u8 *data, int len)
105{
106 struct i2c_msg msg;
107 int i, r, msg_count = 1;
108
109 struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
110
111 if (len < 1 || len > 32) {
112 dev_err(&client->dev,
113 "too long syn_write_block len %d\n", len);
114 return -EIO;
115 }
116 mutex_lock(&picodlp_i2c_data->xfer_lock);
117
118 msg.addr = client->addr;
119 msg.flags = 0;
120 msg.len = len;
121 msg.buf = data;
122 r = i2c_transfer(client->adapter, &msg, msg_count);
123 mutex_unlock(&picodlp_i2c_data->xfer_lock);
124
125 /*
126 * i2c_transfer returns:
127 * number of messages sent in case of success
128 * a negative error number in case of failure
129 */
130 if (r != msg_count)
131 goto err;
132
133 /* In case of success */
134 for (i = 0; i < len; i++)
135 dev_dbg(&client->dev,
136 "addr %x bw 0x%02x[%d]: 0x%02x\n",
137 client->addr, data[0] + i, i, data[i]);
138
139 return 0;
140err:
141 dev_err(&client->dev, "picodlp_i2c_write error\n");
142 return r;
143}
144
145static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value)
146{
147 u8 data[5];
148 int i;
149
150 data[0] = reg;
151 for (i = 1; i < 5; i++)
152 data[i] = (value >> (32 - (i) * 8)) & 0xFF;
153
154 return picodlp_i2c_write_block(client, data, 5);
155}
156
157static int picodlp_i2c_write_array(struct i2c_client *client,
158 const struct picodlp_i2c_command commands[],
159 int count)
160{
161 int i, r = 0;
162 for (i = 0; i < count; i++) {
163 r = picodlp_i2c_write(client, commands[i].reg,
164 commands[i].value);
165 if (r)
166 return r;
167 }
168 return r;
169}
170
171static int picodlp_wait_for_dma_done(struct i2c_client *client)
172{
173 u8 trial = 100;
174
175 do {
176 msleep(1);
177 if (!trial--)
178 return -ETIMEDOUT;
179 } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS);
180
181 return 0;
182}
183
184/**
185 * picodlp_i2c_init: i2c_initialization routine
186 * client: i2c_client for communication
187 *
188 * return
189 * 0 : Success, no error
190 * error code : Failure
191 */
192static int picodlp_i2c_init(struct i2c_client *client)
193{
194 int r;
195 static const struct picodlp_i2c_command init_cmd_set1[] = {
196 {SOFT_RESET, 1},
197 {DMD_PARK_TRIGGER, 1},
198 {MISC_REG, 5},
199 {SEQ_CONTROL, 0},
200 {SEQ_VECTOR, 0x100},
201 {DMD_BLOCK_COUNT, 7},
202 {DMD_VCC_CONTROL, 0x109},
203 {DMD_PARK_PULSE_COUNT, 0xA},
204 {DMD_PARK_PULSE_WIDTH, 0xB},
205 {DMD_PARK_DELAY, 0x2ED},
206 {DMD_SHADOW_ENABLE, 0},
207 {FLASH_OPCODE, 0xB},
208 {FLASH_DUMMY_BYTES, 1},
209 {FLASH_ADDR_BYTES, 3},
210 {PBC_CONTROL, 0},
211 {FLASH_START_ADDR, CMT_LUT_0_START_ADDR},
212 {FLASH_READ_BYTES, CMT_LUT_0_SIZE},
213 {CMT_SPLASH_LUT_START_ADDR, 0},
214 {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL},
215 {PBC_CONTROL, 1},
216 };
217
218 static const struct picodlp_i2c_command init_cmd_set2[] = {
219 {PBC_CONTROL, 0},
220 {CMT_SPLASH_LUT_DEST_SELECT, 0},
221 {PBC_CONTROL, 0},
222 {FLASH_START_ADDR, SEQUENCE_0_START_ADDR},
223 {FLASH_READ_BYTES, SEQUENCE_0_SIZE},
224 {SEQ_RESET_LUT_START_ADDR, 0},
225 {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT},
226 {PBC_CONTROL, 1},
227 };
228
229 static const struct picodlp_i2c_command init_cmd_set3[] = {
230 {PBC_CONTROL, 0},
231 {SEQ_RESET_LUT_DEST_SELECT, 0},
232 {PBC_CONTROL, 0},
233 {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR},
234 {FLASH_READ_BYTES, DRC_TABLE_0_SIZE},
235 {SEQ_RESET_LUT_START_ADDR, 0},
236 {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL},
237 {PBC_CONTROL, 1},
238 };
239
240 static const struct picodlp_i2c_command init_cmd_set4[] = {
241 {PBC_CONTROL, 0},
242 {SEQ_RESET_LUT_DEST_SELECT, 0},
243 {SDC_ENABLE, 1},
244 {AGC_CTRL, 7},
245 {CCA_C1A, 0x100},
246 {CCA_C1B, 0x0},
247 {CCA_C1C, 0x0},
248 {CCA_C2A, 0x0},
249 {CCA_C2B, 0x100},
250 {CCA_C2C, 0x0},
251 {CCA_C3A, 0x0},
252 {CCA_C3B, 0x0},
253 {CCA_C3C, 0x100},
254 {CCA_C7A, 0x100},
255 {CCA_C7B, 0x100},
256 {CCA_C7C, 0x100},
257 {CCA_ENABLE, 1},
258 {CPU_IF_MODE, 1},
259 {SHORT_FLIP, 1},
260 {CURTAIN_CONTROL, 0},
261 {DMD_PARK_TRIGGER, 0},
262 {R_DRIVE_CURRENT, 0x298},
263 {G_DRIVE_CURRENT, 0x298},
264 {B_DRIVE_CURRENT, 0x298},
265 {RGB_DRIVER_ENABLE, 7},
266 {SEQ_CONTROL, 0},
267 {ACTGEN_CONTROL, 0x10},
268 {SEQUENCE_MODE, SEQ_LOCK},
269 {DATA_FORMAT, RGB888},
270 {INPUT_RESOLUTION, WVGA_864_LANDSCAPE},
271 {INPUT_SOURCE, PARALLEL_RGB},
272 {CPU_IF_SYNC_METHOD, 1},
273 {SEQ_CONTROL, 1}
274 };
275
276 r = picodlp_i2c_write_array(client, init_cmd_set1,
277 ARRAY_SIZE(init_cmd_set1));
278 if (r)
279 return r;
280
281 r = picodlp_wait_for_dma_done(client);
282 if (r)
283 return r;
284
285 r = picodlp_i2c_write_array(client, init_cmd_set2,
286 ARRAY_SIZE(init_cmd_set2));
287 if (r)
288 return r;
289
290 r = picodlp_wait_for_dma_done(client);
291 if (r)
292 return r;
293
294 r = picodlp_i2c_write_array(client, init_cmd_set3,
295 ARRAY_SIZE(init_cmd_set3));
296 if (r)
297 return r;
298
299 r = picodlp_wait_for_dma_done(client);
300 if (r)
301 return r;
302
303 r = picodlp_i2c_write_array(client, init_cmd_set4,
304 ARRAY_SIZE(init_cmd_set4));
305 if (r)
306 return r;
307
308 return 0;
309}
310
311static int picodlp_i2c_probe(struct i2c_client *client,
312 const struct i2c_device_id *id)
313{
314 struct picodlp_i2c_data *picodlp_i2c_data;
315
316 picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL);
317
318 if (!picodlp_i2c_data)
319 return -ENOMEM;
320
321 mutex_init(&picodlp_i2c_data->xfer_lock);
322 i2c_set_clientdata(client, picodlp_i2c_data);
323
324 return 0;
325}
326
327static int picodlp_i2c_remove(struct i2c_client *client)
328{
329 struct picodlp_i2c_data *picodlp_i2c_data =
330 i2c_get_clientdata(client);
331 kfree(picodlp_i2c_data);
332 return 0;
333}
334
335static struct i2c_driver picodlp_i2c_driver = {
336 .driver = {
337 .name = "picodlp_i2c_driver",
338 },
339 .probe = picodlp_i2c_probe,
340 .remove = picodlp_i2c_remove,
341 .id_table = picodlp_i2c_id,
342};
343
344static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
345{
346 int r, trial = 100;
347 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
348 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
349
350 if (dssdev->platform_enable) {
351 r = dssdev->platform_enable(dssdev);
352 if (r)
353 return r;
354 }
355
356 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
357 msleep(1);
358 gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
359
360 while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) {
361 if (!trial--) {
362 dev_err(&dssdev->dev, "emu_done signal not"
363 " going high\n");
364 return -ETIMEDOUT;
365 }
366 msleep(5);
367 }
368 /*
369 * As per dpp2600 programming guide,
370 * it is required to sleep for 1000ms after emu_done signal goes high
371 * then only i2c commands can be successfully sent to dpp2600
372 */
373 msleep(1000);
374 r = omapdss_dpi_display_enable(dssdev);
375 if (r) {
376 dev_err(&dssdev->dev, "failed to enable DPI\n");
377 goto err1;
378 }
379
380 r = picodlp_i2c_init(picod->picodlp_i2c_client);
381 if (r)
382 goto err;
383
384 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
385
386 return r;
387err:
388 omapdss_dpi_display_disable(dssdev);
389err1:
390 if (dssdev->platform_disable)
391 dssdev->platform_disable(dssdev);
392
393 return r;
394}
395
396static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
397{
398 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
399
400 omapdss_dpi_display_disable(dssdev);
401
402 gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
403 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
404
405 if (dssdev->platform_disable)
406 dssdev->platform_disable(dssdev);
407}
408
409static int picodlp_panel_probe(struct omap_dss_device *dssdev)
410{
411 struct picodlp_data *picod;
412 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
413 struct i2c_adapter *adapter;
414 struct i2c_client *picodlp_i2c_client;
415 int r = 0, picodlp_adapter_id;
416
417 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_ONOFF |
418 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS;
419 dssdev->panel.acb = 0x0;
420 dssdev->panel.timings = pico_ls_timings;
421
422 picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL);
423 if (!picod)
424 return -ENOMEM;
425
426 mutex_init(&picod->lock);
427
428 picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id;
429
430 adapter = i2c_get_adapter(picodlp_adapter_id);
431 if (!adapter) {
432 dev_err(&dssdev->dev, "can't get i2c adapter\n");
433 r = -ENODEV;
434 goto err;
435 }
436
437 picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
438 if (!picodlp_i2c_client) {
439 dev_err(&dssdev->dev, "can't add i2c device::"
440 " picodlp_i2c_client is NULL\n");
441 r = -ENODEV;
442 goto err;
443 }
444
445 picod->picodlp_i2c_client = picodlp_i2c_client;
446
447 dev_set_drvdata(&dssdev->dev, picod);
448 return r;
449err:
450 kfree(picod);
451 return r;
452}
453
454static void picodlp_panel_remove(struct omap_dss_device *dssdev)
455{
456 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
457
458 i2c_unregister_device(picod->picodlp_i2c_client);
459 dev_set_drvdata(&dssdev->dev, NULL);
460 dev_dbg(&dssdev->dev, "removing picodlp panel\n");
461
462 kfree(picod);
463}
464
465static int picodlp_panel_enable(struct omap_dss_device *dssdev)
466{
467 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
468 int r;
469
470 dev_dbg(&dssdev->dev, "enabling picodlp panel\n");
471
472 mutex_lock(&picod->lock);
473 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
474 mutex_unlock(&picod->lock);
475 return -EINVAL;
476 }
477
478 r = picodlp_panel_power_on(dssdev);
479 mutex_unlock(&picod->lock);
480
481 return r;
482}
483
484static void picodlp_panel_disable(struct omap_dss_device *dssdev)
485{
486 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
487
488 mutex_lock(&picod->lock);
489 /* Turn off DLP Power */
490 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
491 picodlp_panel_power_off(dssdev);
492
493 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
494 mutex_unlock(&picod->lock);
495
496 dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
497}
498
499static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
500{
501 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
502
503 mutex_lock(&picod->lock);
504 /* Turn off DLP Power */
505 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
506 mutex_unlock(&picod->lock);
507 dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
508 " panel is not ACTIVE\n");
509 return -EINVAL;
510 }
511
512 picodlp_panel_power_off(dssdev);
513
514 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
515 mutex_unlock(&picod->lock);
516
517 dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
518 return 0;
519}
520
521static int picodlp_panel_resume(struct omap_dss_device *dssdev)
522{
523 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
524 int r;
525
526 mutex_lock(&picod->lock);
527 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
528 mutex_unlock(&picod->lock);
529 dev_err(&dssdev->dev, "unable to resume picodlp panel,"
530 " panel is not ACTIVE\n");
531 return -EINVAL;
532 }
533
534 r = picodlp_panel_power_on(dssdev);
535 mutex_unlock(&picod->lock);
536 dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
537 return r;
538}
539
540static void picodlp_get_resolution(struct omap_dss_device *dssdev,
541 u16 *xres, u16 *yres)
542{
543 *xres = dssdev->panel.timings.x_res;
544 *yres = dssdev->panel.timings.y_res;
545}
546
547static struct omap_dss_driver picodlp_driver = {
548 .probe = picodlp_panel_probe,
549 .remove = picodlp_panel_remove,
550
551 .enable = picodlp_panel_enable,
552 .disable = picodlp_panel_disable,
553
554 .get_resolution = picodlp_get_resolution,
555
556 .suspend = picodlp_panel_suspend,
557 .resume = picodlp_panel_resume,
558
559 .driver = {
560 .name = "picodlp_panel",
561 .owner = THIS_MODULE,
562 },
563};
564
565static int __init picodlp_init(void)
566{
567 int r = 0;
568
569 r = i2c_add_driver(&picodlp_i2c_driver);
570 if (r) {
571 printk(KERN_WARNING "picodlp_i2c_driver" \
572 " registration failed\n");
573 return r;
574 }
575
576 r = omap_dss_register_driver(&picodlp_driver);
577 if (r)
578 i2c_del_driver(&picodlp_i2c_driver);
579
580 return r;
581}
582
583static void __exit picodlp_exit(void)
584{
585 i2c_del_driver(&picodlp_i2c_driver);
586 omap_dss_unregister_driver(&picodlp_driver);
587}
588
589module_init(picodlp_init);
590module_exit(picodlp_exit);
591
592MODULE_AUTHOR("Mythri P K <mythripk@ti.com>");
593MODULE_DESCRIPTION("picodlp driver");
594MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h
new file mode 100644
index 00000000000..a34b431a726
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-picodlp.h
@@ -0,0 +1,288 @@
1/*
2 * Header file required by picodlp panel driver
3 *
4 * Copyright (C) 2009-2011 Texas Instruments
5 * Author: Mythri P K <mythripk@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_DISPLAY_PANEL_PICODLP_H
21#define __OMAP2_DISPLAY_PANEL_PICODLP_H
22
23/* Commands used for configuring picodlp panel */
24
25#define MAIN_STATUS 0x03
26#define PBC_CONTROL 0x08
27#define INPUT_SOURCE 0x0B
28#define INPUT_RESOLUTION 0x0C
29#define DATA_FORMAT 0x0D
30#define IMG_ROTATION 0x0E
31#define LONG_FLIP 0x0F
32#define SHORT_FLIP 0x10
33#define TEST_PAT_SELECT 0x11
34#define R_DRIVE_CURRENT 0x12
35#define G_DRIVE_CURRENT 0x13
36#define B_DRIVE_CURRENT 0x14
37#define READ_REG_SELECT 0x15
38#define RGB_DRIVER_ENABLE 0x16
39
40#define CPU_IF_MODE 0x18
41#define FRAME_RATE 0x19
42#define CPU_IF_SYNC_METHOD 0x1A
43#define CPU_IF_SOF 0x1B
44#define CPU_IF_EOF 0x1C
45#define CPU_IF_SLEEP 0x1D
46
47#define SEQUENCE_MODE 0x1E
48#define SOFT_RESET 0x1F
49#define FRONT_END_RESET 0x21
50#define AUTO_PWR_ENABLE 0x22
51
52#define VSYNC_LINE_DELAY 0x23
53#define CPU_PI_HORIZ_START 0x24
54#define CPU_PI_VERT_START 0x25
55#define CPU_PI_HORIZ_WIDTH 0x26
56#define CPU_PI_VERT_HEIGHT 0x27
57
58#define PIXEL_MASK_CROP 0x28
59#define CROP_FIRST_LINE 0x29
60#define CROP_LAST_LINE 0x2A
61#define CROP_FIRST_PIXEL 0x2B
62#define CROP_LAST_PIXEL 0x2C
63#define DMD_PARK_TRIGGER 0x2D
64
65#define MISC_REG 0x30
66
67/* AGC registers */
68#define AGC_CTRL 0x50
69#define AGC_CLIPPED_PIXS 0x55
70#define AGC_BRIGHT_PIXS 0x56
71#define AGC_BG_PIXS 0x57
72#define AGC_SAFETY_MARGIN 0x17
73
74/* Color Coordinate Adjustment registers */
75#define CCA_ENABLE 0x5E
76#define CCA_C1A 0x5F
77#define CCA_C1B 0x60
78#define CCA_C1C 0x61
79#define CCA_C2A 0x62
80#define CCA_C2B 0x63
81#define CCA_C2C 0x64
82#define CCA_C3A 0x65
83#define CCA_C3B 0x66
84#define CCA_C3C 0x67
85#define CCA_C7A 0x71
86#define CCA_C7B 0x72
87#define CCA_C7C 0x73
88
89/**
90 * DLP Pico Processor 2600 comes with flash
91 * We can do DMA operations from flash for accessing Look Up Tables
92 */
93#define DMA_STATUS 0x100
94#define FLASH_ADDR_BYTES 0x74
95#define FLASH_DUMMY_BYTES 0x75
96#define FLASH_WRITE_BYTES 0x76
97#define FLASH_READ_BYTES 0x77
98#define FLASH_OPCODE 0x78
99#define FLASH_START_ADDR 0x79
100#define FLASH_DUMMY2 0x7A
101#define FLASH_WRITE_DATA 0x7B
102
103#define TEMPORAL_DITH_DISABLE 0x7E
104#define SEQ_CONTROL 0x82
105#define SEQ_VECTOR 0x83
106
107/* DMD is Digital Micromirror Device */
108#define DMD_BLOCK_COUNT 0x84
109#define DMD_VCC_CONTROL 0x86
110#define DMD_PARK_PULSE_COUNT 0x87
111#define DMD_PARK_PULSE_WIDTH 0x88
112#define DMD_PARK_DELAY 0x89
113#define DMD_SHADOW_ENABLE 0x8E
114#define SEQ_STATUS 0x8F
115#define FLASH_CLOCK_CONTROL 0x98
116#define DMD_PARK 0x2D
117
118#define SDRAM_BIST_ENABLE 0x46
119#define DDR_DRIVER_STRENGTH 0x9A
120#define SDC_ENABLE 0x9D
121#define SDC_BUFF_SWAP_DISABLE 0xA3
122#define CURTAIN_CONTROL 0xA6
123#define DDR_BUS_SWAP_ENABLE 0xA7
124#define DMD_TRC_ENABLE 0xA8
125#define DMD_BUS_SWAP_ENABLE 0xA9
126
127#define ACTGEN_ENABLE 0xAE
128#define ACTGEN_CONTROL 0xAF
129#define ACTGEN_HORIZ_BP 0xB0
130#define ACTGEN_VERT_BP 0xB1
131
132/* Look Up Table access */
133#define CMT_SPLASH_LUT_START_ADDR 0xFA
134#define CMT_SPLASH_LUT_DEST_SELECT 0xFB
135#define CMT_SPLASH_LUT_DATA 0xFC
136#define SEQ_RESET_LUT_START_ADDR 0xFD
137#define SEQ_RESET_LUT_DEST_SELECT 0xFE
138#define SEQ_RESET_LUT_DATA 0xFF
139
140/* Input source definitions */
141#define PARALLEL_RGB 0
142#define INT_TEST_PATTERN 1
143#define SPLASH_SCREEN 2
144#define CPU_INTF 3
145#define BT656 4
146
147/* Standard input resolution definitions */
148#define QWVGA_LANDSCAPE 3 /* (427h*240v) */
149#define WVGA_864_LANDSCAPE 21 /* (864h*480v) */
150#define WVGA_DMD_OPTICAL_TEST 35 /* (608h*684v) */
151
152/* Standard data format definitions */
153#define RGB565 0
154#define RGB666 1
155#define RGB888 2
156
157/* Test Pattern definitions */
158#define TPG_CHECKERBOARD 0
159#define TPG_BLACK 1
160#define TPG_WHITE 2
161#define TPG_RED 3
162#define TPG_BLUE 4
163#define TPG_GREEN 5
164#define TPG_VLINES_BLACK 6
165#define TPG_HLINES_BLACK 7
166#define TPG_VLINES_ALT 8
167#define TPG_HLINES_ALT 9
168#define TPG_DIAG_LINES 10
169#define TPG_GREYRAMP_VERT 11
170#define TPG_GREYRAMP_HORIZ 12
171#define TPG_ANSI_CHECKERBOARD 13
172
173/* sequence mode definitions */
174#define SEQ_FREE_RUN 0
175#define SEQ_LOCK 1
176
177/* curtain color definitions */
178#define CURTAIN_BLACK 0
179#define CURTAIN_RED 1
180#define CURTAIN_GREEN 2
181#define CURTAIN_BLUE 3
182#define CURTAIN_YELLOW 4
183#define CURTAIN_MAGENTA 5
184#define CURTAIN_CYAN 6
185#define CURTAIN_WHITE 7
186
187/* LUT definitions */
188#define CMT_LUT_NONE 0
189#define CMT_LUT_GREEN 1
190#define CMT_LUT_RED 2
191#define CMT_LUT_BLUE 3
192#define CMT_LUT_ALL 4
193#define SPLASH_LUT 5
194
195#define SEQ_LUT_NONE 0
196#define SEQ_DRC_LUT_0 1
197#define SEQ_DRC_LUT_1 2
198#define SEQ_DRC_LUT_2 3
199#define SEQ_DRC_LUT_3 4
200#define SEQ_SEQ_LUT 5
201#define SEQ_DRC_LUT_ALL 6
202#define WPC_PROGRAM_LUT 7
203
204#define BITSTREAM_START_ADDR 0x00000000
205#define BITSTREAM_SIZE 0x00040000
206
207#define WPC_FW_0_START_ADDR 0x00040000
208#define WPC_FW_0_SIZE 0x00000ce8
209
210#define SEQUENCE_0_START_ADDR 0x00044000
211#define SEQUENCE_0_SIZE 0x00001000
212
213#define SEQUENCE_1_START_ADDR 0x00045000
214#define SEQUENCE_1_SIZE 0x00000d10
215
216#define SEQUENCE_2_START_ADDR 0x00046000
217#define SEQUENCE_2_SIZE 0x00000d10
218
219#define SEQUENCE_3_START_ADDR 0x00047000
220#define SEQUENCE_3_SIZE 0x00000d10
221
222#define SEQUENCE_4_START_ADDR 0x00048000
223#define SEQUENCE_4_SIZE 0x00000d10
224
225#define SEQUENCE_5_START_ADDR 0x00049000
226#define SEQUENCE_5_SIZE 0x00000d10
227
228#define SEQUENCE_6_START_ADDR 0x0004a000
229#define SEQUENCE_6_SIZE 0x00000d10
230
231#define CMT_LUT_0_START_ADDR 0x0004b200
232#define CMT_LUT_0_SIZE 0x00000600
233
234#define CMT_LUT_1_START_ADDR 0x0004b800
235#define CMT_LUT_1_SIZE 0x00000600
236
237#define CMT_LUT_2_START_ADDR 0x0004be00
238#define CMT_LUT_2_SIZE 0x00000600
239
240#define CMT_LUT_3_START_ADDR 0x0004c400
241#define CMT_LUT_3_SIZE 0x00000600
242
243#define CMT_LUT_4_START_ADDR 0x0004ca00
244#define CMT_LUT_4_SIZE 0x00000600
245
246#define CMT_LUT_5_START_ADDR 0x0004d000
247#define CMT_LUT_5_SIZE 0x00000600
248
249#define CMT_LUT_6_START_ADDR 0x0004d600
250#define CMT_LUT_6_SIZE 0x00000600
251
252#define DRC_TABLE_0_START_ADDR 0x0004dc00
253#define DRC_TABLE_0_SIZE 0x00000100
254
255#define SPLASH_0_START_ADDR 0x0004dd00
256#define SPLASH_0_SIZE 0x00032280
257
258#define SEQUENCE_7_START_ADDR 0x00080000
259#define SEQUENCE_7_SIZE 0x00000d10
260
261#define SEQUENCE_8_START_ADDR 0x00081800
262#define SEQUENCE_8_SIZE 0x00000d10
263
264#define SEQUENCE_9_START_ADDR 0x00083000
265#define SEQUENCE_9_SIZE 0x00000d10
266
267#define CMT_LUT_7_START_ADDR 0x0008e000
268#define CMT_LUT_7_SIZE 0x00000600
269
270#define CMT_LUT_8_START_ADDR 0x0008e800
271#define CMT_LUT_8_SIZE 0x00000600
272
273#define CMT_LUT_9_START_ADDR 0x0008f000
274#define CMT_LUT_9_SIZE 0x00000600
275
276#define SPLASH_1_START_ADDR 0x0009a000
277#define SPLASH_1_SIZE 0x00032280
278
279#define SPLASH_2_START_ADDR 0x000cd000
280#define SPLASH_2_SIZE 0x00032280
281
282#define SPLASH_3_START_ADDR 0x00100000
283#define SPLASH_3_SIZE 0x00032280
284
285#define OPT_SPLASH_0_START_ADDR 0x00134000
286#define OPT_SPLASH_0_SIZE 0x000cb100
287
288#endif
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 4e888ac09b3..80c3f6ab1a9 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -35,26 +35,12 @@
35 35
36#include <video/omapdss.h> 36#include <video/omapdss.h>
37#include <video/omap-panel-nokia-dsi.h> 37#include <video/omap-panel-nokia-dsi.h>
38#include <video/mipi_display.h>
38 39
39/* DSI Virtual channel. Hardcoded for now. */ 40/* DSI Virtual channel. Hardcoded for now. */
40#define TCH 0 41#define TCH 0
41 42
42#define DCS_READ_NUM_ERRORS 0x05 43#define DCS_READ_NUM_ERRORS 0x05
43#define DCS_READ_POWER_MODE 0x0a
44#define DCS_READ_MADCTL 0x0b
45#define DCS_READ_PIXEL_FORMAT 0x0c
46#define DCS_RDDSDR 0x0f
47#define DCS_SLEEP_IN 0x10
48#define DCS_SLEEP_OUT 0x11
49#define DCS_DISPLAY_OFF 0x28
50#define DCS_DISPLAY_ON 0x29
51#define DCS_COLUMN_ADDR 0x2a
52#define DCS_PAGE_ADDR 0x2b
53#define DCS_MEMORY_WRITE 0x2c
54#define DCS_TEAR_OFF 0x34
55#define DCS_TEAR_ON 0x35
56#define DCS_MEM_ACC_CTRL 0x36
57#define DCS_PIXEL_FORMAT 0x3a
58#define DCS_BRIGHTNESS 0x51 44#define DCS_BRIGHTNESS 0x51
59#define DCS_CTRL_DISPLAY 0x53 45#define DCS_CTRL_DISPLAY 0x53
60#define DCS_WRITE_CABC 0x55 46#define DCS_WRITE_CABC 0x55
@@ -222,8 +208,6 @@ struct taal_data {
222 208
223 struct delayed_work te_timeout_work; 209 struct delayed_work te_timeout_work;
224 210
225 bool use_dsi_bl;
226
227 bool cabc_broken; 211 bool cabc_broken;
228 unsigned cabc_mode; 212 unsigned cabc_mode;
229 213
@@ -302,7 +286,7 @@ static int taal_sleep_in(struct taal_data *td)
302 286
303 hw_guard_wait(td); 287 hw_guard_wait(td);
304 288
305 cmd = DCS_SLEEP_IN; 289 cmd = MIPI_DCS_ENTER_SLEEP_MODE;
306 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1); 290 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
307 if (r) 291 if (r)
308 return r; 292 return r;
@@ -321,7 +305,7 @@ static int taal_sleep_out(struct taal_data *td)
321 305
322 hw_guard_wait(td); 306 hw_guard_wait(td);
323 307
324 r = taal_dcs_write_0(td, DCS_SLEEP_OUT); 308 r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE);
325 if (r) 309 if (r)
326 return r; 310 return r;
327 311
@@ -356,7 +340,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
356 u8 mode; 340 u8 mode;
357 int b5, b6, b7; 341 int b5, b6, b7;
358 342
359 r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode); 343 r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);
360 if (r) 344 if (r)
361 return r; 345 return r;
362 346
@@ -390,7 +374,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
390 mode &= ~((1<<7) | (1<<6) | (1<<5)); 374 mode &= ~((1<<7) | (1<<6) | (1<<5));
391 mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); 375 mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
392 376
393 return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode); 377 return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);
394} 378}
395 379
396static int taal_set_update_window(struct taal_data *td, 380static int taal_set_update_window(struct taal_data *td,
@@ -403,7 +387,7 @@ static int taal_set_update_window(struct taal_data *td,
403 u16 y2 = y + h - 1; 387 u16 y2 = y + h - 1;
404 388
405 u8 buf[5]; 389 u8 buf[5];
406 buf[0] = DCS_COLUMN_ADDR; 390 buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
407 buf[1] = (x1 >> 8) & 0xff; 391 buf[1] = (x1 >> 8) & 0xff;
408 buf[2] = (x1 >> 0) & 0xff; 392 buf[2] = (x1 >> 0) & 0xff;
409 buf[3] = (x2 >> 8) & 0xff; 393 buf[3] = (x2 >> 8) & 0xff;
@@ -413,7 +397,7 @@ static int taal_set_update_window(struct taal_data *td,
413 if (r) 397 if (r)
414 return r; 398 return r;
415 399
416 buf[0] = DCS_PAGE_ADDR; 400 buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
417 buf[1] = (y1 >> 8) & 0xff; 401 buf[1] = (y1 >> 8) & 0xff;
418 buf[2] = (y1 >> 0) & 0xff; 402 buf[2] = (y1 >> 0) & 0xff;
419 buf[3] = (y2 >> 8) & 0xff; 403 buf[3] = (y2 >> 8) & 0xff;
@@ -555,7 +539,6 @@ static int taal_bl_update_status(struct backlight_device *dev)
555{ 539{
556 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); 540 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
557 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 541 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
558 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
559 int r; 542 int r;
560 int level; 543 int level;
561 544
@@ -569,23 +552,16 @@ static int taal_bl_update_status(struct backlight_device *dev)
569 552
570 mutex_lock(&td->lock); 553 mutex_lock(&td->lock);
571 554
572 if (td->use_dsi_bl) { 555 if (td->enabled) {
573 if (td->enabled) { 556 dsi_bus_lock(dssdev);
574 dsi_bus_lock(dssdev);
575 557
576 r = taal_wake_up(dssdev); 558 r = taal_wake_up(dssdev);
577 if (!r) 559 if (!r)
578 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); 560 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
579 561
580 dsi_bus_unlock(dssdev); 562 dsi_bus_unlock(dssdev);
581 } else {
582 r = 0;
583 }
584 } else { 563 } else {
585 if (!panel_data->set_backlight) 564 r = 0;
586 r = -EINVAL;
587 else
588 r = panel_data->set_backlight(dssdev, level);
589 } 565 }
590 566
591 mutex_unlock(&td->lock); 567 mutex_unlock(&td->lock);
@@ -964,7 +940,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
964{ 940{
965 struct backlight_properties props; 941 struct backlight_properties props;
966 struct taal_data *td; 942 struct taal_data *td;
967 struct backlight_device *bldev; 943 struct backlight_device *bldev = NULL;
968 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); 944 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
969 struct panel_config *panel_config = NULL; 945 struct panel_config *panel_config = NULL;
970 int r, i; 946 int r, i;
@@ -990,7 +966,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
990 966
991 dssdev->panel.config = OMAP_DSS_LCD_TFT; 967 dssdev->panel.config = OMAP_DSS_LCD_TFT;
992 dssdev->panel.timings = panel_config->timings; 968 dssdev->panel.timings = panel_config->timings;
993 dssdev->ctrl.pixel_size = 24; 969 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
994 970
995 td = kzalloc(sizeof(*td), GFP_KERNEL); 971 td = kzalloc(sizeof(*td), GFP_KERNEL);
996 if (!td) { 972 if (!td) {
@@ -1025,35 +1001,26 @@ static int taal_probe(struct omap_dss_device *dssdev)
1025 1001
1026 taal_hw_reset(dssdev); 1002 taal_hw_reset(dssdev);
1027 1003
1028 /* if no platform set_backlight() defined, presume DSI backlight 1004 if (panel_data->use_dsi_backlight) {
1029 * control */ 1005 memset(&props, 0, sizeof(struct backlight_properties));
1030 memset(&props, 0, sizeof(struct backlight_properties));
1031 if (!panel_data->set_backlight)
1032 td->use_dsi_bl = true;
1033
1034 if (td->use_dsi_bl)
1035 props.max_brightness = 255; 1006 props.max_brightness = 255;
1036 else
1037 props.max_brightness = 127;
1038
1039 props.type = BACKLIGHT_RAW;
1040 bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
1041 dssdev, &taal_bl_ops, &props);
1042 if (IS_ERR(bldev)) {
1043 r = PTR_ERR(bldev);
1044 goto err_bl;
1045 }
1046 1007
1047 td->bldev = bldev; 1008 props.type = BACKLIGHT_RAW;
1009 bldev = backlight_device_register(dev_name(&dssdev->dev),
1010 &dssdev->dev, dssdev, &taal_bl_ops, &props);
1011 if (IS_ERR(bldev)) {
1012 r = PTR_ERR(bldev);
1013 goto err_bl;
1014 }
1015
1016 td->bldev = bldev;
1048 1017
1049 bldev->props.fb_blank = FB_BLANK_UNBLANK; 1018 bldev->props.fb_blank = FB_BLANK_UNBLANK;
1050 bldev->props.power = FB_BLANK_UNBLANK; 1019 bldev->props.power = FB_BLANK_UNBLANK;
1051 if (td->use_dsi_bl)
1052 bldev->props.brightness = 255; 1020 bldev->props.brightness = 255;
1053 else
1054 bldev->props.brightness = 127;
1055 1021
1056 taal_bl_update_status(bldev); 1022 taal_bl_update_status(bldev);
1023 }
1057 1024
1058 if (panel_data->use_ext_te) { 1025 if (panel_data->use_ext_te) {
1059 int gpio = panel_data->ext_te_gpio; 1026 int gpio = panel_data->ext_te_gpio;
@@ -1067,7 +1034,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
1067 gpio_direction_input(gpio); 1034 gpio_direction_input(gpio);
1068 1035
1069 r = request_irq(gpio_to_irq(gpio), taal_te_isr, 1036 r = request_irq(gpio_to_irq(gpio), taal_te_isr,
1070 IRQF_DISABLED | IRQF_TRIGGER_RISING, 1037 IRQF_TRIGGER_RISING,
1071 "taal vsync", dssdev); 1038 "taal vsync", dssdev);
1072 1039
1073 if (r) { 1040 if (r) {
@@ -1111,7 +1078,8 @@ err_irq:
1111 if (panel_data->use_ext_te) 1078 if (panel_data->use_ext_te)
1112 gpio_free(panel_data->ext_te_gpio); 1079 gpio_free(panel_data->ext_te_gpio);
1113err_gpio: 1080err_gpio:
1114 backlight_device_unregister(bldev); 1081 if (bldev != NULL)
1082 backlight_device_unregister(bldev);
1115err_bl: 1083err_bl:
1116 destroy_workqueue(td->workqueue); 1084 destroy_workqueue(td->workqueue);
1117err_wq: 1085err_wq:
@@ -1140,9 +1108,11 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
1140 } 1108 }
1141 1109
1142 bldev = td->bldev; 1110 bldev = td->bldev;
1143 bldev->props.power = FB_BLANK_POWERDOWN; 1111 if (bldev != NULL) {
1144 taal_bl_update_status(bldev); 1112 bldev->props.power = FB_BLANK_POWERDOWN;
1145 backlight_device_unregister(bldev); 1113 taal_bl_update_status(bldev);
1114 backlight_device_unregister(bldev);
1115 }
1146 1116
1147 taal_cancel_ulps_work(dssdev); 1117 taal_cancel_ulps_work(dssdev);
1148 taal_cancel_esd_work(dssdev); 1118 taal_cancel_esd_work(dssdev);
@@ -1195,7 +1165,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1195 if (r) 1165 if (r)
1196 goto err; 1166 goto err;
1197 1167
1198 r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ 1168 r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT,
1169 MIPI_DCS_PIXEL_FMT_24BIT);
1199 if (r) 1170 if (r)
1200 goto err; 1171 goto err;
1201 1172
@@ -1209,7 +1180,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1209 goto err; 1180 goto err;
1210 } 1181 }
1211 1182
1212 r = taal_dcs_write_0(td, DCS_DISPLAY_ON); 1183 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON);
1213 if (r) 1184 if (r)
1214 goto err; 1185 goto err;
1215 1186
@@ -1246,7 +1217,7 @@ static void taal_power_off(struct omap_dss_device *dssdev)
1246 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1217 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1247 int r; 1218 int r;
1248 1219
1249 r = taal_dcs_write_0(td, DCS_DISPLAY_OFF); 1220 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
1250 if (!r) 1221 if (!r)
1251 r = taal_sleep_in(td); 1222 r = taal_sleep_in(td);
1252 1223
@@ -1529,9 +1500,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1529 int r; 1500 int r;
1530 1501
1531 if (enable) 1502 if (enable)
1532 r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); 1503 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
1533 else 1504 else
1534 r = taal_dcs_write_0(td, DCS_TEAR_OFF); 1505 r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
1535 1506
1536 if (!panel_data->use_ext_te) 1507 if (!panel_data->use_ext_te)
1537 omapdss_dsi_enable_te(dssdev, enable); 1508 omapdss_dsi_enable_te(dssdev, enable);
@@ -1851,7 +1822,7 @@ static void taal_esd_work(struct work_struct *work)
1851 goto err; 1822 goto err;
1852 } 1823 }
1853 1824
1854 r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); 1825 r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1);
1855 if (r) { 1826 if (r) {
1856 dev_err(&dssdev->dev, "failed to read Taal status\n"); 1827 dev_err(&dssdev->dev, "failed to read Taal status\n");
1857 goto err; 1828 goto err;
@@ -1864,7 +1835,7 @@ static void taal_esd_work(struct work_struct *work)
1864 goto err; 1835 goto err;
1865 } 1836 }
1866 1837
1867 r = taal_dcs_read_1(td, DCS_RDDSDR, &state2); 1838 r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2);
1868 if (r) { 1839 if (r) {
1869 dev_err(&dssdev->dev, "failed to read Taal status\n"); 1840 dev_err(&dssdev->dev, "failed to read Taal status\n");
1870 goto err; 1841 goto err;
@@ -1880,7 +1851,7 @@ static void taal_esd_work(struct work_struct *work)
1880 /* Self-diagnostics result is also shown on TE GPIO line. We need 1851 /* Self-diagnostics result is also shown on TE GPIO line. We need
1881 * to re-enable TE after self diagnostics */ 1852 * to re-enable TE after self diagnostics */
1882 if (td->te_enabled && panel_data->use_ext_te) { 1853 if (td->te_enabled && panel_data->use_ext_te) {
1883 r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); 1854 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
1884 if (r) 1855 if (r)
1885 goto err; 1856 goto err;
1886 } 1857 }
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 0d12524db14..7be7c06a249 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -1,5 +1,5 @@
1menuconfig OMAP2_DSS 1menuconfig OMAP2_DSS
2 tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)" 2 tristate "OMAP2+ Display Subsystem support"
3 depends on ARCH_OMAP2PLUS 3 depends on ARCH_OMAP2PLUS
4 help 4 help
5 OMAP2+ Display Subsystem support. 5 OMAP2+ Display Subsystem support.
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 10d9d3bb3e2..bd34ac5b202 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -6,4 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
6omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 6omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
7omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o 7omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
8omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ 8omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
9 hdmi_omap4_panel.o 9 hdmi_panel.o ti_hdmi_4xxx_ip.o
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 76821fefce9..86ec12e16c7 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -145,6 +145,10 @@ static int dss_initialize_debugfs(void)
145 debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, 145 debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
146 &venc_dump_regs, &dss_debug_fops); 146 &venc_dump_regs, &dss_debug_fops);
147#endif 147#endif
148#ifdef CONFIG_OMAP4_DSS_HDMI
149 debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir,
150 &hdmi_dump_regs, &dss_debug_fops);
151#endif
148 return 0; 152 return 0;
149} 153}
150 154
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 0f3961a1ce2..6892cfd2e3b 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -106,7 +106,7 @@ static struct {
106 int irq; 106 int irq;
107 struct clk *dss_clk; 107 struct clk *dss_clk;
108 108
109 u32 fifo_size[3]; 109 u32 fifo_size[MAX_DSS_OVERLAYS];
110 110
111 spinlock_t irq_lock; 111 spinlock_t irq_lock;
112 u32 irq_error_mask; 112 u32 irq_error_mask;
@@ -171,172 +171,98 @@ static int dispc_get_ctx_loss_count(void)
171 171
172static void dispc_save_context(void) 172static void dispc_save_context(void)
173{ 173{
174 int i; 174 int i, j;
175 175
176 DSSDBG("dispc_save_context\n"); 176 DSSDBG("dispc_save_context\n");
177 177
178 SR(IRQENABLE); 178 SR(IRQENABLE);
179 SR(CONTROL); 179 SR(CONTROL);
180 SR(CONFIG); 180 SR(CONFIG);
181 SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
182 SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
183 SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
184 SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
185 SR(LINE_NUMBER); 181 SR(LINE_NUMBER);
186 SR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); 182 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
187 SR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); 183 dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
188 SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
189 SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
190 if (dss_has_feature(FEAT_GLOBAL_ALPHA))
191 SR(GLOBAL_ALPHA); 184 SR(GLOBAL_ALPHA);
192 SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
193 SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
194 if (dss_has_feature(FEAT_MGR_LCD2)) { 185 if (dss_has_feature(FEAT_MGR_LCD2)) {
195 SR(CONTROL2); 186 SR(CONTROL2);
196 SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
197 SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
198 SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
199 SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
200 SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
201 SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
202 SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
203 SR(CONFIG2); 187 SR(CONFIG2);
204 } 188 }
205 189
206 SR(OVL_BA0(OMAP_DSS_GFX)); 190 for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
207 SR(OVL_BA1(OMAP_DSS_GFX)); 191 SR(DEFAULT_COLOR(i));
208 SR(OVL_POSITION(OMAP_DSS_GFX)); 192 SR(TRANS_COLOR(i));
209 SR(OVL_SIZE(OMAP_DSS_GFX)); 193 SR(SIZE_MGR(i));
210 SR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); 194 if (i == OMAP_DSS_CHANNEL_DIGIT)
211 SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); 195 continue;
212 SR(OVL_ROW_INC(OMAP_DSS_GFX)); 196 SR(TIMING_H(i));
213 SR(OVL_PIXEL_INC(OMAP_DSS_GFX)); 197 SR(TIMING_V(i));
214 SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); 198 SR(POL_FREQ(i));
215 SR(OVL_TABLE_BA(OMAP_DSS_GFX)); 199 SR(DIVISORo(i));
216 200
217 SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); 201 SR(DATA_CYCLE1(i));
218 SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); 202 SR(DATA_CYCLE2(i));
219 SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); 203 SR(DATA_CYCLE3(i));
220 204
221 if (dss_has_feature(FEAT_CPR)) {
222 SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
223 SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
224 SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
225 }
226 if (dss_has_feature(FEAT_MGR_LCD2)) {
227 if (dss_has_feature(FEAT_CPR)) { 205 if (dss_has_feature(FEAT_CPR)) {
228 SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); 206 SR(CPR_COEF_R(i));
229 SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); 207 SR(CPR_COEF_G(i));
230 SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); 208 SR(CPR_COEF_B(i));
231 } 209 }
232
233 SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
234 SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
235 SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
236 } 210 }
237 211
238 if (dss_has_feature(FEAT_PRELOAD)) 212 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
239 SR(OVL_PRELOAD(OMAP_DSS_GFX)); 213 SR(OVL_BA0(i));
240 214 SR(OVL_BA1(i));
241 /* VID1 */ 215 SR(OVL_POSITION(i));
242 SR(OVL_BA0(OMAP_DSS_VIDEO1)); 216 SR(OVL_SIZE(i));
243 SR(OVL_BA1(OMAP_DSS_VIDEO1)); 217 SR(OVL_ATTRIBUTES(i));
244 SR(OVL_POSITION(OMAP_DSS_VIDEO1)); 218 SR(OVL_FIFO_THRESHOLD(i));
245 SR(OVL_SIZE(OMAP_DSS_VIDEO1)); 219 SR(OVL_ROW_INC(i));
246 SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); 220 SR(OVL_PIXEL_INC(i));
247 SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); 221 if (dss_has_feature(FEAT_PRELOAD))
248 SR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); 222 SR(OVL_PRELOAD(i));
249 SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); 223 if (i == OMAP_DSS_GFX) {
250 SR(OVL_FIR(OMAP_DSS_VIDEO1)); 224 SR(OVL_WINDOW_SKIP(i));
251 SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); 225 SR(OVL_TABLE_BA(i));
252 SR(OVL_ACCU0(OMAP_DSS_VIDEO1)); 226 continue;
253 SR(OVL_ACCU1(OMAP_DSS_VIDEO1)); 227 }
254 228 SR(OVL_FIR(i));
255 for (i = 0; i < 8; i++) 229 SR(OVL_PICTURE_SIZE(i));
256 SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); 230 SR(OVL_ACCU0(i));
257 231 SR(OVL_ACCU1(i));
258 for (i = 0; i < 8; i++)
259 SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
260
261 for (i = 0; i < 5; i++)
262 SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
263
264 if (dss_has_feature(FEAT_FIR_COEF_V)) {
265 for (i = 0; i < 8; i++)
266 SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
267 }
268
269 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
270 SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
271 SR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
272 SR(OVL_FIR2(OMAP_DSS_VIDEO1));
273 SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
274 SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
275
276 for (i = 0; i < 8; i++)
277 SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
278
279 for (i = 0; i < 8; i++)
280 SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
281
282 for (i = 0; i < 8; i++)
283 SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
284 }
285 if (dss_has_feature(FEAT_ATTR2))
286 SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
287
288 if (dss_has_feature(FEAT_PRELOAD))
289 SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
290
291 /* VID2 */
292 SR(OVL_BA0(OMAP_DSS_VIDEO2));
293 SR(OVL_BA1(OMAP_DSS_VIDEO2));
294 SR(OVL_POSITION(OMAP_DSS_VIDEO2));
295 SR(OVL_SIZE(OMAP_DSS_VIDEO2));
296 SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
297 SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
298 SR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
299 SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
300 SR(OVL_FIR(OMAP_DSS_VIDEO2));
301 SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
302 SR(OVL_ACCU0(OMAP_DSS_VIDEO2));
303 SR(OVL_ACCU1(OMAP_DSS_VIDEO2));
304 232
305 for (i = 0; i < 8; i++) 233 for (j = 0; j < 8; j++)
306 SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); 234 SR(OVL_FIR_COEF_H(i, j));
307 235
308 for (i = 0; i < 8; i++) 236 for (j = 0; j < 8; j++)
309 SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); 237 SR(OVL_FIR_COEF_HV(i, j));
310 238
311 for (i = 0; i < 5; i++) 239 for (j = 0; j < 5; j++)
312 SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); 240 SR(OVL_CONV_COEF(i, j));
313 241
314 if (dss_has_feature(FEAT_FIR_COEF_V)) { 242 if (dss_has_feature(FEAT_FIR_COEF_V)) {
315 for (i = 0; i < 8; i++) 243 for (j = 0; j < 8; j++)
316 SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); 244 SR(OVL_FIR_COEF_V(i, j));
317 } 245 }
318 246
319 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { 247 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
320 SR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); 248 SR(OVL_BA0_UV(i));
321 SR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); 249 SR(OVL_BA1_UV(i));
322 SR(OVL_FIR2(OMAP_DSS_VIDEO2)); 250 SR(OVL_FIR2(i));
323 SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); 251 SR(OVL_ACCU2_0(i));
324 SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); 252 SR(OVL_ACCU2_1(i));
325 253
326 for (i = 0; i < 8; i++) 254 for (j = 0; j < 8; j++)
327 SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); 255 SR(OVL_FIR_COEF_H2(i, j));
328 256
329 for (i = 0; i < 8; i++) 257 for (j = 0; j < 8; j++)
330 SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); 258 SR(OVL_FIR_COEF_HV2(i, j));
331 259
332 for (i = 0; i < 8; i++) 260 for (j = 0; j < 8; j++)
333 SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); 261 SR(OVL_FIR_COEF_V2(i, j));
262 }
263 if (dss_has_feature(FEAT_ATTR2))
264 SR(OVL_ATTRIBUTES2(i));
334 } 265 }
335 if (dss_has_feature(FEAT_ATTR2))
336 SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
337
338 if (dss_has_feature(FEAT_PRELOAD))
339 SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
340 266
341 if (dss_has_feature(FEAT_CORE_CLK_DIV)) 267 if (dss_has_feature(FEAT_CORE_CLK_DIV))
342 SR(DIVISOR); 268 SR(DIVISOR);
@@ -349,7 +275,7 @@ static void dispc_save_context(void)
349 275
350static void dispc_restore_context(void) 276static void dispc_restore_context(void)
351{ 277{
352 int i, ctx; 278 int i, j, ctx;
353 279
354 DSSDBG("dispc_restore_context\n"); 280 DSSDBG("dispc_restore_context\n");
355 281
@@ -367,165 +293,89 @@ static void dispc_restore_context(void)
367 /*RR(IRQENABLE);*/ 293 /*RR(IRQENABLE);*/
368 /*RR(CONTROL);*/ 294 /*RR(CONTROL);*/
369 RR(CONFIG); 295 RR(CONFIG);
370 RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
371 RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
372 RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
373 RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
374 RR(LINE_NUMBER); 296 RR(LINE_NUMBER);
375 RR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); 297 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
376 RR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); 298 dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
377 RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
378 RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
379 if (dss_has_feature(FEAT_GLOBAL_ALPHA))
380 RR(GLOBAL_ALPHA); 299 RR(GLOBAL_ALPHA);
381 RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); 300 if (dss_has_feature(FEAT_MGR_LCD2))
382 RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
383 if (dss_has_feature(FEAT_MGR_LCD2)) {
384 RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
385 RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
386 RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
387 RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
388 RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
389 RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
390 RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
391 RR(CONFIG2); 301 RR(CONFIG2);
392 }
393
394 RR(OVL_BA0(OMAP_DSS_GFX));
395 RR(OVL_BA1(OMAP_DSS_GFX));
396 RR(OVL_POSITION(OMAP_DSS_GFX));
397 RR(OVL_SIZE(OMAP_DSS_GFX));
398 RR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
399 RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
400 RR(OVL_ROW_INC(OMAP_DSS_GFX));
401 RR(OVL_PIXEL_INC(OMAP_DSS_GFX));
402 RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
403 RR(OVL_TABLE_BA(OMAP_DSS_GFX));
404
405 302
406 RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); 303 for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
407 RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); 304 RR(DEFAULT_COLOR(i));
408 RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); 305 RR(TRANS_COLOR(i));
306 RR(SIZE_MGR(i));
307 if (i == OMAP_DSS_CHANNEL_DIGIT)
308 continue;
309 RR(TIMING_H(i));
310 RR(TIMING_V(i));
311 RR(POL_FREQ(i));
312 RR(DIVISORo(i));
409 313
410 if (dss_has_feature(FEAT_CPR)) { 314 RR(DATA_CYCLE1(i));
411 RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); 315 RR(DATA_CYCLE2(i));
412 RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); 316 RR(DATA_CYCLE3(i));
413 RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
414 }
415 if (dss_has_feature(FEAT_MGR_LCD2)) {
416 RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
417 RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
418 RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
419 317
420 if (dss_has_feature(FEAT_CPR)) { 318 if (dss_has_feature(FEAT_CPR)) {
421 RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); 319 RR(CPR_COEF_R(i));
422 RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); 320 RR(CPR_COEF_G(i));
423 RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); 321 RR(CPR_COEF_B(i));
424 } 322 }
425 } 323 }
426 324
427 if (dss_has_feature(FEAT_PRELOAD)) 325 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
428 RR(OVL_PRELOAD(OMAP_DSS_GFX)); 326 RR(OVL_BA0(i));
429 327 RR(OVL_BA1(i));
430 /* VID1 */ 328 RR(OVL_POSITION(i));
431 RR(OVL_BA0(OMAP_DSS_VIDEO1)); 329 RR(OVL_SIZE(i));
432 RR(OVL_BA1(OMAP_DSS_VIDEO1)); 330 RR(OVL_ATTRIBUTES(i));
433 RR(OVL_POSITION(OMAP_DSS_VIDEO1)); 331 RR(OVL_FIFO_THRESHOLD(i));
434 RR(OVL_SIZE(OMAP_DSS_VIDEO1)); 332 RR(OVL_ROW_INC(i));
435 RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); 333 RR(OVL_PIXEL_INC(i));
436 RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); 334 if (dss_has_feature(FEAT_PRELOAD))
437 RR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); 335 RR(OVL_PRELOAD(i));
438 RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); 336 if (i == OMAP_DSS_GFX) {
439 RR(OVL_FIR(OMAP_DSS_VIDEO1)); 337 RR(OVL_WINDOW_SKIP(i));
440 RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); 338 RR(OVL_TABLE_BA(i));
441 RR(OVL_ACCU0(OMAP_DSS_VIDEO1)); 339 continue;
442 RR(OVL_ACCU1(OMAP_DSS_VIDEO1)); 340 }
443 341 RR(OVL_FIR(i));
444 for (i = 0; i < 8; i++) 342 RR(OVL_PICTURE_SIZE(i));
445 RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); 343 RR(OVL_ACCU0(i));
446 344 RR(OVL_ACCU1(i));
447 for (i = 0; i < 8; i++)
448 RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
449
450 for (i = 0; i < 5; i++)
451 RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
452
453 if (dss_has_feature(FEAT_FIR_COEF_V)) {
454 for (i = 0; i < 8; i++)
455 RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
456 }
457
458 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
459 RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
460 RR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
461 RR(OVL_FIR2(OMAP_DSS_VIDEO1));
462 RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
463 RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
464
465 for (i = 0; i < 8; i++)
466 RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
467
468 for (i = 0; i < 8; i++)
469 RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
470
471 for (i = 0; i < 8; i++)
472 RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
473 }
474 if (dss_has_feature(FEAT_ATTR2))
475 RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
476
477 if (dss_has_feature(FEAT_PRELOAD))
478 RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
479
480 /* VID2 */
481 RR(OVL_BA0(OMAP_DSS_VIDEO2));
482 RR(OVL_BA1(OMAP_DSS_VIDEO2));
483 RR(OVL_POSITION(OMAP_DSS_VIDEO2));
484 RR(OVL_SIZE(OMAP_DSS_VIDEO2));
485 RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
486 RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
487 RR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
488 RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
489 RR(OVL_FIR(OMAP_DSS_VIDEO2));
490 RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
491 RR(OVL_ACCU0(OMAP_DSS_VIDEO2));
492 RR(OVL_ACCU1(OMAP_DSS_VIDEO2));
493 345
494 for (i = 0; i < 8; i++) 346 for (j = 0; j < 8; j++)
495 RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); 347 RR(OVL_FIR_COEF_H(i, j));
496 348
497 for (i = 0; i < 8; i++) 349 for (j = 0; j < 8; j++)
498 RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); 350 RR(OVL_FIR_COEF_HV(i, j));
499 351
500 for (i = 0; i < 5; i++) 352 for (j = 0; j < 5; j++)
501 RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); 353 RR(OVL_CONV_COEF(i, j));
502 354
503 if (dss_has_feature(FEAT_FIR_COEF_V)) { 355 if (dss_has_feature(FEAT_FIR_COEF_V)) {
504 for (i = 0; i < 8; i++) 356 for (j = 0; j < 8; j++)
505 RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); 357 RR(OVL_FIR_COEF_V(i, j));
506 } 358 }
507 359
508 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { 360 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
509 RR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); 361 RR(OVL_BA0_UV(i));
510 RR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); 362 RR(OVL_BA1_UV(i));
511 RR(OVL_FIR2(OMAP_DSS_VIDEO2)); 363 RR(OVL_FIR2(i));
512 RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); 364 RR(OVL_ACCU2_0(i));
513 RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); 365 RR(OVL_ACCU2_1(i));
514 366
515 for (i = 0; i < 8; i++) 367 for (j = 0; j < 8; j++)
516 RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); 368 RR(OVL_FIR_COEF_H2(i, j));
517 369
518 for (i = 0; i < 8; i++) 370 for (j = 0; j < 8; j++)
519 RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); 371 RR(OVL_FIR_COEF_HV2(i, j));
520 372
521 for (i = 0; i < 8; i++) 373 for (j = 0; j < 8; j++)
522 RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); 374 RR(OVL_FIR_COEF_V2(i, j));
375 }
376 if (dss_has_feature(FEAT_ATTR2))
377 RR(OVL_ATTRIBUTES2(i));
523 } 378 }
524 if (dss_has_feature(FEAT_ATTR2))
525 RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
526
527 if (dss_has_feature(FEAT_PRELOAD))
528 RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
529 379
530 if (dss_has_feature(FEAT_CORE_CLK_DIV)) 380 if (dss_has_feature(FEAT_CORE_CLK_DIV))
531 RR(DIVISOR); 381 RR(DIVISOR);
@@ -570,13 +420,28 @@ void dispc_runtime_put(void)
570 WARN_ON(r < 0); 420 WARN_ON(r < 0);
571} 421}
572 422
423static inline bool dispc_mgr_is_lcd(enum omap_channel channel)
424{
425 if (channel == OMAP_DSS_CHANNEL_LCD ||
426 channel == OMAP_DSS_CHANNEL_LCD2)
427 return true;
428 else
429 return false;
430}
431
432static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel)
433{
434 struct omap_overlay_manager *mgr =
435 omap_dss_get_overlay_manager(channel);
573 436
574bool dispc_go_busy(enum omap_channel channel) 437 return mgr ? mgr->device : NULL;
438}
439
440bool dispc_mgr_go_busy(enum omap_channel channel)
575{ 441{
576 int bit; 442 int bit;
577 443
578 if (channel == OMAP_DSS_CHANNEL_LCD || 444 if (dispc_mgr_is_lcd(channel))
579 channel == OMAP_DSS_CHANNEL_LCD2)
580 bit = 5; /* GOLCD */ 445 bit = 5; /* GOLCD */
581 else 446 else
582 bit = 6; /* GODIGIT */ 447 bit = 6; /* GODIGIT */
@@ -587,13 +452,12 @@ bool dispc_go_busy(enum omap_channel channel)
587 return REG_GET(DISPC_CONTROL, bit, bit) == 1; 452 return REG_GET(DISPC_CONTROL, bit, bit) == 1;
588} 453}
589 454
590void dispc_go(enum omap_channel channel) 455void dispc_mgr_go(enum omap_channel channel)
591{ 456{
592 int bit; 457 int bit;
593 bool enable_bit, go_bit; 458 bool enable_bit, go_bit;
594 459
595 if (channel == OMAP_DSS_CHANNEL_LCD || 460 if (dispc_mgr_is_lcd(channel))
596 channel == OMAP_DSS_CHANNEL_LCD2)
597 bit = 0; /* LCDENABLE */ 461 bit = 0; /* LCDENABLE */
598 else 462 else
599 bit = 1; /* DIGITALENABLE */ 463 bit = 1; /* DIGITALENABLE */
@@ -607,8 +471,7 @@ void dispc_go(enum omap_channel channel)
607 if (!enable_bit) 471 if (!enable_bit)
608 return; 472 return;
609 473
610 if (channel == OMAP_DSS_CHANNEL_LCD || 474 if (dispc_mgr_is_lcd(channel))
611 channel == OMAP_DSS_CHANNEL_LCD2)
612 bit = 5; /* GOLCD */ 475 bit = 5; /* GOLCD */
613 else 476 else
614 bit = 6; /* GODIGIT */ 477 bit = 6; /* GODIGIT */
@@ -632,43 +495,44 @@ void dispc_go(enum omap_channel channel)
632 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); 495 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
633} 496}
634 497
635static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) 498static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
636{ 499{
637 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); 500 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
638} 501}
639 502
640static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) 503static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
641{ 504{
642 dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value); 505 dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);
643} 506}
644 507
645static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) 508static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value)
646{ 509{
647 dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value); 510 dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);
648} 511}
649 512
650static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value) 513static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
651{ 514{
652 BUG_ON(plane == OMAP_DSS_GFX); 515 BUG_ON(plane == OMAP_DSS_GFX);
653 516
654 dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value); 517 dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value);
655} 518}
656 519
657static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value) 520static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg,
521 u32 value)
658{ 522{
659 BUG_ON(plane == OMAP_DSS_GFX); 523 BUG_ON(plane == OMAP_DSS_GFX);
660 524
661 dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value); 525 dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
662} 526}
663 527
664static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value) 528static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
665{ 529{
666 BUG_ON(plane == OMAP_DSS_GFX); 530 BUG_ON(plane == OMAP_DSS_GFX);
667 531
668 dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); 532 dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
669} 533}
670 534
671static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, 535static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup,
672 int vscaleup, int five_taps, 536 int vscaleup, int five_taps,
673 enum omap_color_component color_comp) 537 enum omap_color_component color_comp)
674{ 538{
@@ -769,11 +633,11 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
769 | FLD_VAL(v_coef[i].vc2, 31, 24); 633 | FLD_VAL(v_coef[i].vc2, 31, 24);
770 634
771 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { 635 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
772 _dispc_write_firh_reg(plane, i, h); 636 dispc_ovl_write_firh_reg(plane, i, h);
773 _dispc_write_firhv_reg(plane, i, hv); 637 dispc_ovl_write_firhv_reg(plane, i, hv);
774 } else { 638 } else {
775 _dispc_write_firh2_reg(plane, i, h); 639 dispc_ovl_write_firh2_reg(plane, i, h);
776 _dispc_write_firhv2_reg(plane, i, hv); 640 dispc_ovl_write_firhv2_reg(plane, i, hv);
777 } 641 }
778 642
779 } 643 }
@@ -784,15 +648,16 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
784 v = FLD_VAL(v_coef[i].vc00, 7, 0) 648 v = FLD_VAL(v_coef[i].vc00, 7, 0)
785 | FLD_VAL(v_coef[i].vc22, 15, 8); 649 | FLD_VAL(v_coef[i].vc22, 15, 8);
786 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) 650 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
787 _dispc_write_firv_reg(plane, i, v); 651 dispc_ovl_write_firv_reg(plane, i, v);
788 else 652 else
789 _dispc_write_firv2_reg(plane, i, v); 653 dispc_ovl_write_firv2_reg(plane, i, v);
790 } 654 }
791 } 655 }
792} 656}
793 657
794static void _dispc_setup_color_conv_coef(void) 658static void _dispc_setup_color_conv_coef(void)
795{ 659{
660 int i;
796 const struct color_conv_coef { 661 const struct color_conv_coef {
797 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; 662 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
798 int full_range; 663 int full_range;
@@ -806,65 +671,54 @@ static void _dispc_setup_color_conv_coef(void)
806 671
807 ct = &ctbl_bt601_5; 672 ct = &ctbl_bt601_5;
808 673
809 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0), 674 for (i = 1; i < dss_feat_get_num_ovls(); i++) {
810 CVAL(ct->rcr, ct->ry)); 675 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0),
811 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1), 676 CVAL(ct->rcr, ct->ry));
812 CVAL(ct->gy, ct->rcb)); 677 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1),
813 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2), 678 CVAL(ct->gy, ct->rcb));
814 CVAL(ct->gcb, ct->gcr)); 679 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2),
815 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3), 680 CVAL(ct->gcb, ct->gcr));
816 CVAL(ct->bcr, ct->by)); 681 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3),
817 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4), 682 CVAL(ct->bcr, ct->by));
818 CVAL(0, ct->bcb)); 683 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4),
819 684 CVAL(0, ct->bcb));
820 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0),
821 CVAL(ct->rcr, ct->ry));
822 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1),
823 CVAL(ct->gy, ct->rcb));
824 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2),
825 CVAL(ct->gcb, ct->gcr));
826 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3),
827 CVAL(ct->bcr, ct->by));
828 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4),
829 CVAL(0, ct->bcb));
830 685
831#undef CVAL 686 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range,
687 11, 11);
688 }
832 689
833 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1), 690#undef CVAL
834 ct->full_range, 11, 11);
835 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2),
836 ct->full_range, 11, 11);
837} 691}
838 692
839 693
840static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) 694static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
841{ 695{
842 dispc_write_reg(DISPC_OVL_BA0(plane), paddr); 696 dispc_write_reg(DISPC_OVL_BA0(plane), paddr);
843} 697}
844 698
845static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) 699static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr)
846{ 700{
847 dispc_write_reg(DISPC_OVL_BA1(plane), paddr); 701 dispc_write_reg(DISPC_OVL_BA1(plane), paddr);
848} 702}
849 703
850static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr) 704static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr)
851{ 705{
852 dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr); 706 dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr);
853} 707}
854 708
855static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr) 709static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
856{ 710{
857 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); 711 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
858} 712}
859 713
860static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) 714static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y)
861{ 715{
862 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); 716 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
863 717
864 dispc_write_reg(DISPC_OVL_POSITION(plane), val); 718 dispc_write_reg(DISPC_OVL_POSITION(plane), val);
865} 719}
866 720
867static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) 721static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height)
868{ 722{
869 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 723 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
870 724
@@ -874,7 +728,7 @@ static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
874 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); 728 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
875} 729}
876 730
877static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) 731static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)
878{ 732{
879 u32 val; 733 u32 val;
880 734
@@ -885,44 +739,61 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
885 dispc_write_reg(DISPC_OVL_SIZE(plane), val); 739 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
886} 740}
887 741
888static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable) 742static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder)
889{ 743{
890 if (!dss_has_feature(FEAT_PRE_MULT_ALPHA)) 744 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
745
746 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
891 return; 747 return;
892 748
893 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && 749 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
894 plane == OMAP_DSS_VIDEO1) 750}
751
752static void dispc_ovl_enable_zorder_planes(void)
753{
754 int i;
755
756 if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
895 return; 757 return;
896 758
897 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); 759 for (i = 0; i < dss_feat_get_num_ovls(); i++)
760 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
898} 761}
899 762
900static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) 763static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable)
901{ 764{
902 if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) 765 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
766
767 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
903 return; 768 return;
904 769
905 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && 770 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
906 plane == OMAP_DSS_VIDEO1) 771}
772
773static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
774{
775 static const unsigned shifts[] = { 0, 8, 16, 24, };
776 int shift;
777 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
778
779 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
907 return; 780 return;
908 781
909 if (plane == OMAP_DSS_GFX) 782 shift = shifts[plane];
910 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); 783 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift);
911 else if (plane == OMAP_DSS_VIDEO2)
912 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
913} 784}
914 785
915static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) 786static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc)
916{ 787{
917 dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc); 788 dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);
918} 789}
919 790
920static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) 791static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc)
921{ 792{
922 dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc); 793 dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);
923} 794}
924 795
925static void _dispc_set_color_mode(enum omap_plane plane, 796static void dispc_ovl_set_color_mode(enum omap_plane plane,
926 enum omap_color_mode color_mode) 797 enum omap_color_mode color_mode)
927{ 798{
928 u32 m = 0; 799 u32 m = 0;
@@ -1003,7 +874,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,
1003 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); 874 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
1004} 875}
1005 876
1006void dispc_set_channel_out(enum omap_plane plane, 877static void dispc_ovl_set_channel_out(enum omap_plane plane,
1007 enum omap_channel channel) 878 enum omap_channel channel)
1008{ 879{
1009 int shift; 880 int shift;
@@ -1016,6 +887,7 @@ void dispc_set_channel_out(enum omap_plane plane,
1016 break; 887 break;
1017 case OMAP_DSS_VIDEO1: 888 case OMAP_DSS_VIDEO1:
1018 case OMAP_DSS_VIDEO2: 889 case OMAP_DSS_VIDEO2:
890 case OMAP_DSS_VIDEO3:
1019 shift = 16; 891 shift = 16;
1020 break; 892 break;
1021 default: 893 default:
@@ -1050,24 +922,13 @@ void dispc_set_channel_out(enum omap_plane plane,
1050 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 922 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
1051} 923}
1052 924
1053static void dispc_set_burst_size(enum omap_plane plane, 925static void dispc_ovl_set_burst_size(enum omap_plane plane,
1054 enum omap_burst_size burst_size) 926 enum omap_burst_size burst_size)
1055{ 927{
928 static const unsigned shifts[] = { 6, 14, 14, 14, };
1056 int shift; 929 int shift;
1057 930
1058 switch (plane) { 931 shift = shifts[plane];
1059 case OMAP_DSS_GFX:
1060 shift = 6;
1061 break;
1062 case OMAP_DSS_VIDEO1:
1063 case OMAP_DSS_VIDEO2:
1064 shift = 14;
1065 break;
1066 default:
1067 BUG();
1068 return;
1069 }
1070
1071 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift); 932 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
1072} 933}
1073 934
@@ -1078,10 +939,10 @@ static void dispc_configure_burst_sizes(void)
1078 939
1079 /* Configure burst size always to maximum size */ 940 /* Configure burst size always to maximum size */
1080 for (i = 0; i < omap_dss_get_num_overlays(); ++i) 941 for (i = 0; i < omap_dss_get_num_overlays(); ++i)
1081 dispc_set_burst_size(i, burst_size); 942 dispc_ovl_set_burst_size(i, burst_size);
1082} 943}
1083 944
1084u32 dispc_get_burst_size(enum omap_plane plane) 945u32 dispc_ovl_get_burst_size(enum omap_plane plane)
1085{ 946{
1086 unsigned unit = dss_feat_get_burst_size_unit(); 947 unsigned unit = dss_feat_get_burst_size_unit();
1087 /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ 948 /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
@@ -1102,7 +963,7 @@ void dispc_enable_gamma_table(bool enable)
1102 REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); 963 REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
1103} 964}
1104 965
1105void dispc_enable_cpr(enum omap_channel channel, bool enable) 966void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
1106{ 967{
1107 u16 reg; 968 u16 reg;
1108 969
@@ -1116,12 +977,12 @@ void dispc_enable_cpr(enum omap_channel channel, bool enable)
1116 REG_FLD_MOD(reg, enable, 15, 15); 977 REG_FLD_MOD(reg, enable, 15, 15);
1117} 978}
1118 979
1119void dispc_set_cpr_coef(enum omap_channel channel, 980void dispc_mgr_set_cpr_coef(enum omap_channel channel,
1120 struct omap_dss_cpr_coefs *coefs) 981 struct omap_dss_cpr_coefs *coefs)
1121{ 982{
1122 u32 coef_r, coef_g, coef_b; 983 u32 coef_r, coef_g, coef_b;
1123 984
1124 if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2) 985 if (!dispc_mgr_is_lcd(channel))
1125 return; 986 return;
1126 987
1127 coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) | 988 coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
@@ -1136,7 +997,7 @@ void dispc_set_cpr_coef(enum omap_channel channel,
1136 dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b); 997 dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
1137} 998}
1138 999
1139static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) 1000static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
1140{ 1001{
1141 u32 val; 1002 u32 val;
1142 1003
@@ -1147,19 +1008,16 @@ static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
1147 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 1008 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
1148} 1009}
1149 1010
1150void dispc_enable_replication(enum omap_plane plane, bool enable) 1011static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable)
1151{ 1012{
1152 int bit; 1013 static const unsigned shifts[] = { 5, 10, 10, 10 };
1153 1014 int shift;
1154 if (plane == OMAP_DSS_GFX)
1155 bit = 5;
1156 else
1157 bit = 10;
1158 1015
1159 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); 1016 shift = shifts[plane];
1017 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
1160} 1018}
1161 1019
1162void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) 1020void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
1163{ 1021{
1164 u32 val; 1022 u32 val;
1165 BUG_ON((width > (1 << 11)) || (height > (1 << 11))); 1023 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
@@ -1186,19 +1044,20 @@ static void dispc_read_plane_fifo_sizes(void)
1186 1044
1187 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); 1045 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
1188 1046
1189 for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { 1047 for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) {
1190 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end); 1048 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
1191 size *= unit; 1049 size *= unit;
1192 dispc.fifo_size[plane] = size; 1050 dispc.fifo_size[plane] = size;
1193 } 1051 }
1194} 1052}
1195 1053
1196u32 dispc_get_plane_fifo_size(enum omap_plane plane) 1054u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
1197{ 1055{
1198 return dispc.fifo_size[plane]; 1056 return dispc.fifo_size[plane];
1199} 1057}
1200 1058
1201void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) 1059static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low,
1060 u32 high)
1202{ 1061{
1203 u8 hi_start, hi_end, lo_start, lo_end; 1062 u8 hi_start, hi_end, lo_start, lo_end;
1204 u32 unit; 1063 u32 unit;
@@ -1233,7 +1092,7 @@ void dispc_enable_fifomerge(bool enable)
1233 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); 1092 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1234} 1093}
1235 1094
1236static void _dispc_set_fir(enum omap_plane plane, 1095static void dispc_ovl_set_fir(enum omap_plane plane,
1237 int hinc, int vinc, 1096 int hinc, int vinc,
1238 enum omap_color_component color_comp) 1097 enum omap_color_component color_comp)
1239{ 1098{
@@ -1256,7 +1115,7 @@ static void _dispc_set_fir(enum omap_plane plane,
1256 } 1115 }
1257} 1116}
1258 1117
1259static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) 1118static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
1260{ 1119{
1261 u32 val; 1120 u32 val;
1262 u8 hor_start, hor_end, vert_start, vert_end; 1121 u8 hor_start, hor_end, vert_start, vert_end;
@@ -1270,7 +1129,7 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
1270 dispc_write_reg(DISPC_OVL_ACCU0(plane), val); 1129 dispc_write_reg(DISPC_OVL_ACCU0(plane), val);
1271} 1130}
1272 1131
1273static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) 1132static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
1274{ 1133{
1275 u32 val; 1134 u32 val;
1276 u8 hor_start, hor_end, vert_start, vert_end; 1135 u8 hor_start, hor_end, vert_start, vert_end;
@@ -1284,7 +1143,8 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
1284 dispc_write_reg(DISPC_OVL_ACCU1(plane), val); 1143 dispc_write_reg(DISPC_OVL_ACCU1(plane), val);
1285} 1144}
1286 1145
1287static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu) 1146static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu,
1147 int vaccu)
1288{ 1148{
1289 u32 val; 1149 u32 val;
1290 1150
@@ -1292,7 +1152,8 @@ static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu)
1292 dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val); 1152 dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val);
1293} 1153}
1294 1154
1295static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu) 1155static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu,
1156 int vaccu)
1296{ 1157{
1297 u32 val; 1158 u32 val;
1298 1159
@@ -1300,7 +1161,7 @@ static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)
1300 dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val); 1161 dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);
1301} 1162}
1302 1163
1303static void _dispc_set_scale_param(enum omap_plane plane, 1164static void dispc_ovl_set_scale_param(enum omap_plane plane,
1304 u16 orig_width, u16 orig_height, 1165 u16 orig_width, u16 orig_height,
1305 u16 out_width, u16 out_height, 1166 u16 out_width, u16 out_height,
1306 bool five_taps, u8 rotation, 1167 bool five_taps, u8 rotation,
@@ -1312,15 +1173,16 @@ static void _dispc_set_scale_param(enum omap_plane plane,
1312 hscaleup = orig_width <= out_width; 1173 hscaleup = orig_width <= out_width;
1313 vscaleup = orig_height <= out_height; 1174 vscaleup = orig_height <= out_height;
1314 1175
1315 _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp); 1176 dispc_ovl_set_scale_coef(plane, hscaleup, vscaleup, five_taps,
1177 color_comp);
1316 1178
1317 fir_hinc = 1024 * orig_width / out_width; 1179 fir_hinc = 1024 * orig_width / out_width;
1318 fir_vinc = 1024 * orig_height / out_height; 1180 fir_vinc = 1024 * orig_height / out_height;
1319 1181
1320 _dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp); 1182 dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
1321} 1183}
1322 1184
1323static void _dispc_set_scaling_common(enum omap_plane plane, 1185static void dispc_ovl_set_scaling_common(enum omap_plane plane,
1324 u16 orig_width, u16 orig_height, 1186 u16 orig_width, u16 orig_height,
1325 u16 out_width, u16 out_height, 1187 u16 out_width, u16 out_height,
1326 bool ilace, bool five_taps, 1188 bool ilace, bool five_taps,
@@ -1331,7 +1193,7 @@ static void _dispc_set_scaling_common(enum omap_plane plane,
1331 int accu1 = 0; 1193 int accu1 = 0;
1332 u32 l; 1194 u32 l;
1333 1195
1334 _dispc_set_scale_param(plane, orig_width, orig_height, 1196 dispc_ovl_set_scale_param(plane, orig_width, orig_height,
1335 out_width, out_height, five_taps, 1197 out_width, out_height, five_taps,
1336 rotation, DISPC_COLOR_COMPONENT_RGB_Y); 1198 rotation, DISPC_COLOR_COMPONENT_RGB_Y);
1337 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); 1199 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
@@ -1370,11 +1232,11 @@ static void _dispc_set_scaling_common(enum omap_plane plane,
1370 } 1232 }
1371 } 1233 }
1372 1234
1373 _dispc_set_vid_accu0(plane, 0, accu0); 1235 dispc_ovl_set_vid_accu0(plane, 0, accu0);
1374 _dispc_set_vid_accu1(plane, 0, accu1); 1236 dispc_ovl_set_vid_accu1(plane, 0, accu1);
1375} 1237}
1376 1238
1377static void _dispc_set_scaling_uv(enum omap_plane plane, 1239static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1378 u16 orig_width, u16 orig_height, 1240 u16 orig_width, u16 orig_height,
1379 u16 out_width, u16 out_height, 1241 u16 out_width, u16 out_height,
1380 bool ilace, bool five_taps, 1242 bool ilace, bool five_taps,
@@ -1422,7 +1284,7 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,
1422 if (out_height != orig_height) 1284 if (out_height != orig_height)
1423 scale_y = true; 1285 scale_y = true;
1424 1286
1425 _dispc_set_scale_param(plane, orig_width, orig_height, 1287 dispc_ovl_set_scale_param(plane, orig_width, orig_height,
1426 out_width, out_height, five_taps, 1288 out_width, out_height, five_taps,
1427 rotation, DISPC_COLOR_COMPONENT_UV); 1289 rotation, DISPC_COLOR_COMPONENT_UV);
1428 1290
@@ -1433,11 +1295,11 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,
1433 /* set V scaling */ 1295 /* set V scaling */
1434 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); 1296 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
1435 1297
1436 _dispc_set_vid_accu2_0(plane, 0x80, 0); 1298 dispc_ovl_set_vid_accu2_0(plane, 0x80, 0);
1437 _dispc_set_vid_accu2_1(plane, 0x80, 0); 1299 dispc_ovl_set_vid_accu2_1(plane, 0x80, 0);
1438} 1300}
1439 1301
1440static void _dispc_set_scaling(enum omap_plane plane, 1302static void dispc_ovl_set_scaling(enum omap_plane plane,
1441 u16 orig_width, u16 orig_height, 1303 u16 orig_width, u16 orig_height,
1442 u16 out_width, u16 out_height, 1304 u16 out_width, u16 out_height,
1443 bool ilace, bool five_taps, 1305 bool ilace, bool five_taps,
@@ -1446,14 +1308,14 @@ static void _dispc_set_scaling(enum omap_plane plane,
1446{ 1308{
1447 BUG_ON(plane == OMAP_DSS_GFX); 1309 BUG_ON(plane == OMAP_DSS_GFX);
1448 1310
1449 _dispc_set_scaling_common(plane, 1311 dispc_ovl_set_scaling_common(plane,
1450 orig_width, orig_height, 1312 orig_width, orig_height,
1451 out_width, out_height, 1313 out_width, out_height,
1452 ilace, five_taps, 1314 ilace, five_taps,
1453 fieldmode, color_mode, 1315 fieldmode, color_mode,
1454 rotation); 1316 rotation);
1455 1317
1456 _dispc_set_scaling_uv(plane, 1318 dispc_ovl_set_scaling_uv(plane,
1457 orig_width, orig_height, 1319 orig_width, orig_height,
1458 out_width, out_height, 1320 out_width, out_height,
1459 ilace, five_taps, 1321 ilace, five_taps,
@@ -1461,7 +1323,7 @@ static void _dispc_set_scaling(enum omap_plane plane,
1461 rotation); 1323 rotation);
1462} 1324}
1463 1325
1464static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, 1326static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1465 bool mirroring, enum omap_color_mode color_mode) 1327 bool mirroring, enum omap_color_mode color_mode)
1466{ 1328{
1467 bool row_repeat = false; 1329 bool row_repeat = false;
@@ -1789,12 +1651,11 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
1789 enum omap_color_mode color_mode) 1651 enum omap_color_mode color_mode)
1790{ 1652{
1791 u32 fclk = 0; 1653 u32 fclk = 0;
1792 /* FIXME venc pclk? */ 1654 u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
1793 u64 tmp, pclk = dispc_pclk_rate(channel);
1794 1655
1795 if (height > out_height) { 1656 if (height > out_height) {
1796 /* FIXME get real display PPL */ 1657 struct omap_dss_device *dssdev = dispc_mgr_get_device(channel);
1797 unsigned int ppl = 800; 1658 unsigned int ppl = dssdev->panel.timings.x_res;
1798 1659
1799 tmp = pclk * height * out_width; 1660 tmp = pclk * height * out_width;
1800 do_div(tmp, 2 * out_height * ppl); 1661 do_div(tmp, 2 * out_height * ppl);
@@ -1846,114 +1707,120 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1846 else 1707 else
1847 vf = 1; 1708 vf = 1;
1848 1709
1849 /* FIXME venc pclk? */ 1710 return dispc_mgr_pclk_rate(channel) * vf * hf;
1850 return dispc_pclk_rate(channel) * vf * hf;
1851} 1711}
1852 1712
1853int dispc_setup_plane(enum omap_plane plane, 1713static int dispc_ovl_calc_scaling(enum omap_plane plane,
1854 u32 paddr, u16 screen_width, 1714 enum omap_channel channel, u16 width, u16 height,
1855 u16 pos_x, u16 pos_y,
1856 u16 width, u16 height,
1857 u16 out_width, u16 out_height, 1715 u16 out_width, u16 out_height,
1858 enum omap_color_mode color_mode, 1716 enum omap_color_mode color_mode, bool *five_taps)
1859 bool ilace, 1717{
1860 enum omap_dss_rotation_type rotation_type, 1718 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
1861 u8 rotation, bool mirror, 1719 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
1862 u8 global_alpha, u8 pre_mult_alpha, 1720 unsigned long fclk = 0;
1863 enum omap_channel channel, u32 puv_addr)
1864{
1865 const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
1866 bool five_taps = 0;
1867 bool fieldmode = 0;
1868 int cconv = 0;
1869 unsigned offset0, offset1;
1870 s32 row_inc;
1871 s32 pix_inc;
1872 u16 frame_height = height;
1873 unsigned int field_offset = 0;
1874 1721
1875 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " 1722 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
1876 "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", 1723 if (width != out_width || height != out_height)
1877 plane, paddr, screen_width, pos_x, pos_y, 1724 return -EINVAL;
1878 width, height, 1725 else
1879 out_width, out_height, 1726 return 0;
1880 ilace, color_mode, 1727 }
1881 rotation, mirror, channel);
1882 1728
1883 if (paddr == 0) 1729 if (out_width < width / maxdownscale ||
1730 out_width > width * 8)
1884 return -EINVAL; 1731 return -EINVAL;
1885 1732
1886 if (ilace && height == out_height) 1733 if (out_height < height / maxdownscale ||
1887 fieldmode = 1; 1734 out_height > height * 8)
1735 return -EINVAL;
1888 1736
1889 if (ilace) { 1737 /* Must use 5-tap filter? */
1890 if (fieldmode) 1738 *five_taps = height > out_height * 2;
1891 height /= 2;
1892 pos_y /= 2;
1893 out_height /= 2;
1894 1739
1895 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 1740 if (!*five_taps) {
1896 "out_height %d\n", 1741 fclk = calc_fclk(channel, width, height, out_width,
1897 height, pos_y, out_height); 1742 out_height);
1743
1744 /* Try 5-tap filter if 3-tap fclk is too high */
1745 if (cpu_is_omap34xx() && height > out_height &&
1746 fclk > dispc_fclk_rate())
1747 *five_taps = true;
1898 } 1748 }
1899 1749
1900 if (!dss_feat_color_mode_supported(plane, color_mode)) 1750 if (width > (2048 >> *five_taps)) {
1751 DSSERR("failed to set up scaling, fclk too low\n");
1901 return -EINVAL; 1752 return -EINVAL;
1753 }
1902 1754
1903 if (plane == OMAP_DSS_GFX) { 1755 if (*five_taps)
1904 if (width != out_width || height != out_height) 1756 fclk = calc_fclk_five_taps(channel, width, height,
1905 return -EINVAL; 1757 out_width, out_height, color_mode);
1906 } else {
1907 /* video plane */
1908 1758
1909 unsigned long fclk = 0; 1759 DSSDBG("required fclk rate = %lu Hz\n", fclk);
1760 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
1910 1761
1911 if (out_width < width / maxdownscale || 1762 if (!fclk || fclk > dispc_fclk_rate()) {
1912 out_width > width * 8) 1763 DSSERR("failed to set up scaling, "
1913 return -EINVAL; 1764 "required fclk rate = %lu Hz, "
1765 "current fclk rate = %lu Hz\n",
1766 fclk, dispc_fclk_rate());
1767 return -EINVAL;
1768 }
1914 1769
1915 if (out_height < height / maxdownscale || 1770 return 0;
1916 out_height > height * 8) 1771}
1917 return -EINVAL;
1918 1772
1919 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1773int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1920 color_mode == OMAP_DSS_COLOR_UYVY || 1774 bool ilace, enum omap_channel channel, bool replication,
1921 color_mode == OMAP_DSS_COLOR_NV12) 1775 u32 fifo_low, u32 fifo_high)
1922 cconv = 1; 1776{
1777 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
1778 bool five_taps = false;
1779 bool fieldmode = 0;
1780 int r, cconv = 0;
1781 unsigned offset0, offset1;
1782 s32 row_inc;
1783 s32 pix_inc;
1784 u16 frame_height = oi->height;
1785 unsigned int field_offset = 0;
1923 1786
1924 /* Must use 5-tap filter? */ 1787 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
1925 five_taps = height > out_height * 2; 1788 "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d "
1789 "fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr,
1790 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
1791 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
1792 oi->mirror, ilace, channel, replication, fifo_low, fifo_high);
1926 1793
1927 if (!five_taps) { 1794 if (oi->paddr == 0)
1928 fclk = calc_fclk(channel, width, height, out_width, 1795 return -EINVAL;
1929 out_height);
1930 1796
1931 /* Try 5-tap filter if 3-tap fclk is too high */ 1797 if (ilace && oi->height == oi->out_height)
1932 if (cpu_is_omap34xx() && height > out_height && 1798 fieldmode = 1;
1933 fclk > dispc_fclk_rate())
1934 five_taps = true;
1935 }
1936 1799
1937 if (width > (2048 >> five_taps)) { 1800 if (ilace) {
1938 DSSERR("failed to set up scaling, fclk too low\n"); 1801 if (fieldmode)
1939 return -EINVAL; 1802 oi->height /= 2;
1940 } 1803 oi->pos_y /= 2;
1804 oi->out_height /= 2;
1941 1805
1942 if (five_taps) 1806 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
1943 fclk = calc_fclk_five_taps(channel, width, height, 1807 "out_height %d\n",
1944 out_width, out_height, color_mode); 1808 oi->height, oi->pos_y, oi->out_height);
1809 }
1945 1810
1946 DSSDBG("required fclk rate = %lu Hz\n", fclk); 1811 if (!dss_feat_color_mode_supported(plane, oi->color_mode))
1947 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); 1812 return -EINVAL;
1948 1813
1949 if (!fclk || fclk > dispc_fclk_rate()) { 1814 r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height,
1950 DSSERR("failed to set up scaling, " 1815 oi->out_width, oi->out_height, oi->color_mode,
1951 "required fclk rate = %lu Hz, " 1816 &five_taps);
1952 "current fclk rate = %lu Hz\n", 1817 if (r)
1953 fclk, dispc_fclk_rate()); 1818 return r;
1954 return -EINVAL; 1819
1955 } 1820 if (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
1956 } 1821 oi->color_mode == OMAP_DSS_COLOR_UYVY ||
1822 oi->color_mode == OMAP_DSS_COLOR_NV12)
1823 cconv = 1;
1957 1824
1958 if (ilace && !fieldmode) { 1825 if (ilace && !fieldmode) {
1959 /* 1826 /*
@@ -1963,69 +1830,76 @@ int dispc_setup_plane(enum omap_plane plane,
1963 * so the integer part must be added to the base address of the 1830 * so the integer part must be added to the base address of the
1964 * bottom field. 1831 * bottom field.
1965 */ 1832 */
1966 if (!height || height == out_height) 1833 if (!oi->height || oi->height == oi->out_height)
1967 field_offset = 0; 1834 field_offset = 0;
1968 else 1835 else
1969 field_offset = height / out_height / 2; 1836 field_offset = oi->height / oi->out_height / 2;
1970 } 1837 }
1971 1838
1972 /* Fields are independent but interleaved in memory. */ 1839 /* Fields are independent but interleaved in memory. */
1973 if (fieldmode) 1840 if (fieldmode)
1974 field_offset = 1; 1841 field_offset = 1;
1975 1842
1976 if (rotation_type == OMAP_DSS_ROT_DMA) 1843 if (oi->rotation_type == OMAP_DSS_ROT_DMA)
1977 calc_dma_rotation_offset(rotation, mirror, 1844 calc_dma_rotation_offset(oi->rotation, oi->mirror,
1978 screen_width, width, frame_height, color_mode, 1845 oi->screen_width, oi->width, frame_height,
1979 fieldmode, field_offset, 1846 oi->color_mode, fieldmode, field_offset,
1980 &offset0, &offset1, &row_inc, &pix_inc); 1847 &offset0, &offset1, &row_inc, &pix_inc);
1981 else 1848 else
1982 calc_vrfb_rotation_offset(rotation, mirror, 1849 calc_vrfb_rotation_offset(oi->rotation, oi->mirror,
1983 screen_width, width, frame_height, color_mode, 1850 oi->screen_width, oi->width, frame_height,
1984 fieldmode, field_offset, 1851 oi->color_mode, fieldmode, field_offset,
1985 &offset0, &offset1, &row_inc, &pix_inc); 1852 &offset0, &offset1, &row_inc, &pix_inc);
1986 1853
1987 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", 1854 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
1988 offset0, offset1, row_inc, pix_inc); 1855 offset0, offset1, row_inc, pix_inc);
1989 1856
1990 _dispc_set_color_mode(plane, color_mode); 1857 dispc_ovl_set_color_mode(plane, oi->color_mode);
1991 1858
1992 _dispc_set_plane_ba0(plane, paddr + offset0); 1859 dispc_ovl_set_ba0(plane, oi->paddr + offset0);
1993 _dispc_set_plane_ba1(plane, paddr + offset1); 1860 dispc_ovl_set_ba1(plane, oi->paddr + offset1);
1994 1861
1995 if (OMAP_DSS_COLOR_NV12 == color_mode) { 1862 if (OMAP_DSS_COLOR_NV12 == oi->color_mode) {
1996 _dispc_set_plane_ba0_uv(plane, puv_addr + offset0); 1863 dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0);
1997 _dispc_set_plane_ba1_uv(plane, puv_addr + offset1); 1864 dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1);
1998 } 1865 }
1999 1866
2000 1867
2001 _dispc_set_row_inc(plane, row_inc); 1868 dispc_ovl_set_row_inc(plane, row_inc);
2002 _dispc_set_pix_inc(plane, pix_inc); 1869 dispc_ovl_set_pix_inc(plane, pix_inc);
2003 1870
2004 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height, 1871 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width,
2005 out_width, out_height); 1872 oi->height, oi->out_width, oi->out_height);
2006 1873
2007 _dispc_set_plane_pos(plane, pos_x, pos_y); 1874 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
2008 1875
2009 _dispc_set_pic_size(plane, width, height); 1876 dispc_ovl_set_pic_size(plane, oi->width, oi->height);
2010 1877
2011 if (plane != OMAP_DSS_GFX) { 1878 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
2012 _dispc_set_scaling(plane, width, height, 1879 dispc_ovl_set_scaling(plane, oi->width, oi->height,
2013 out_width, out_height, 1880 oi->out_width, oi->out_height,
2014 ilace, five_taps, fieldmode, 1881 ilace, five_taps, fieldmode,
2015 color_mode, rotation); 1882 oi->color_mode, oi->rotation);
2016 _dispc_set_vid_size(plane, out_width, out_height); 1883 dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height);
2017 _dispc_set_vid_color_conv(plane, cconv); 1884 dispc_ovl_set_vid_color_conv(plane, cconv);
2018 } 1885 }
2019 1886
2020 _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); 1887 dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror,
1888 oi->color_mode);
1889
1890 dispc_ovl_set_zorder(plane, oi->zorder);
1891 dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha);
1892 dispc_ovl_setup_global_alpha(plane, oi->global_alpha);
2021 1893
2022 _dispc_set_pre_mult_alpha(plane, pre_mult_alpha); 1894 dispc_ovl_set_channel_out(plane, channel);
2023 _dispc_setup_global_alpha(plane, global_alpha); 1895
1896 dispc_ovl_enable_replication(plane, replication);
1897 dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high);
2024 1898
2025 return 0; 1899 return 0;
2026} 1900}
2027 1901
2028int dispc_enable_plane(enum omap_plane plane, bool enable) 1902int dispc_ovl_enable(enum omap_plane plane, bool enable)
2029{ 1903{
2030 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); 1904 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
2031 1905
@@ -2048,7 +1922,7 @@ static void _enable_lcd_out(enum omap_channel channel, bool enable)
2048 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); 1922 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
2049} 1923}
2050 1924
2051static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) 1925static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
2052{ 1926{
2053 struct completion frame_done_completion; 1927 struct completion frame_done_completion;
2054 bool is_on; 1928 bool is_on;
@@ -2095,14 +1969,19 @@ static void _enable_digit_out(bool enable)
2095 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); 1969 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
2096} 1970}
2097 1971
2098static void dispc_enable_digit_out(bool enable) 1972static void dispc_mgr_enable_digit_out(bool enable)
2099{ 1973{
2100 struct completion frame_done_completion; 1974 struct completion frame_done_completion;
2101 int r; 1975 enum dss_hdmi_venc_clk_source_select src;
1976 int r, i;
1977 u32 irq_mask;
1978 int num_irqs;
2102 1979
2103 if (REG_GET(DISPC_CONTROL, 1, 1) == enable) 1980 if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
2104 return; 1981 return;
2105 1982
1983 src = dss_get_hdmi_venc_clk_source();
1984
2106 if (enable) { 1985 if (enable) {
2107 unsigned long flags; 1986 unsigned long flags;
2108 /* When we enable digit output, we'll get an extra digit 1987 /* When we enable digit output, we'll get an extra digit
@@ -2119,43 +1998,47 @@ static void dispc_enable_digit_out(bool enable)
2119 * wait for the extra sync losts */ 1998 * wait for the extra sync losts */
2120 init_completion(&frame_done_completion); 1999 init_completion(&frame_done_completion);
2121 2000
2001 if (src == DSS_HDMI_M_PCLK && enable == false) {
2002 irq_mask = DISPC_IRQ_FRAMEDONETV;
2003 num_irqs = 1;
2004 } else {
2005 irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
2006 /* XXX I understand from TRM that we should only wait for the
2007 * current field to complete. But it seems we have to wait for
2008 * both fields */
2009 num_irqs = 2;
2010 }
2011
2122 r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, 2012 r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
2123 DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); 2013 irq_mask);
2124 if (r) 2014 if (r)
2125 DSSERR("failed to register EVSYNC isr\n"); 2015 DSSERR("failed to register %x isr\n", irq_mask);
2126 2016
2127 _enable_digit_out(enable); 2017 _enable_digit_out(enable);
2128 2018
2129 /* XXX I understand from TRM that we should only wait for the 2019 for (i = 0; i < num_irqs; ++i) {
2130 * current field to complete. But it seems we have to wait 2020 if (!wait_for_completion_timeout(&frame_done_completion,
2131 * for both fields */ 2021 msecs_to_jiffies(100)))
2132 if (!wait_for_completion_timeout(&frame_done_completion, 2022 DSSERR("timeout waiting for digit out to %s\n",
2133 msecs_to_jiffies(100))) 2023 enable ? "start" : "stop");
2134 DSSERR("timeout waiting for EVSYNC\n"); 2024 }
2135
2136 if (!wait_for_completion_timeout(&frame_done_completion,
2137 msecs_to_jiffies(100)))
2138 DSSERR("timeout waiting for EVSYNC\n");
2139 2025
2140 r = omap_dispc_unregister_isr(dispc_disable_isr, 2026 r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion,
2141 &frame_done_completion, 2027 irq_mask);
2142 DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
2143 if (r) 2028 if (r)
2144 DSSERR("failed to unregister EVSYNC isr\n"); 2029 DSSERR("failed to unregister %x isr\n", irq_mask);
2145 2030
2146 if (enable) { 2031 if (enable) {
2147 unsigned long flags; 2032 unsigned long flags;
2148 spin_lock_irqsave(&dispc.irq_lock, flags); 2033 spin_lock_irqsave(&dispc.irq_lock, flags);
2149 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; 2034 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;
2150 if (dss_has_feature(FEAT_MGR_LCD2))
2151 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
2152 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); 2035 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
2153 _omap_dispc_set_irqs(); 2036 _omap_dispc_set_irqs();
2154 spin_unlock_irqrestore(&dispc.irq_lock, flags); 2037 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2155 } 2038 }
2156} 2039}
2157 2040
2158bool dispc_is_channel_enabled(enum omap_channel channel) 2041bool dispc_mgr_is_enabled(enum omap_channel channel)
2159{ 2042{
2160 if (channel == OMAP_DSS_CHANNEL_LCD) 2043 if (channel == OMAP_DSS_CHANNEL_LCD)
2161 return !!REG_GET(DISPC_CONTROL, 0, 0); 2044 return !!REG_GET(DISPC_CONTROL, 0, 0);
@@ -2167,13 +2050,12 @@ bool dispc_is_channel_enabled(enum omap_channel channel)
2167 BUG(); 2050 BUG();
2168} 2051}
2169 2052
2170void dispc_enable_channel(enum omap_channel channel, bool enable) 2053void dispc_mgr_enable(enum omap_channel channel, bool enable)
2171{ 2054{
2172 if (channel == OMAP_DSS_CHANNEL_LCD || 2055 if (dispc_mgr_is_lcd(channel))
2173 channel == OMAP_DSS_CHANNEL_LCD2) 2056 dispc_mgr_enable_lcd_out(channel, enable);
2174 dispc_enable_lcd_out(channel, enable);
2175 else if (channel == OMAP_DSS_CHANNEL_DIGIT) 2057 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
2176 dispc_enable_digit_out(enable); 2058 dispc_mgr_enable_digit_out(enable);
2177 else 2059 else
2178 BUG(); 2060 BUG();
2179} 2061}
@@ -2202,7 +2084,7 @@ void dispc_pck_free_enable(bool enable)
2202 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); 2084 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
2203} 2085}
2204 2086
2205void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) 2087void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
2206{ 2088{
2207 if (channel == OMAP_DSS_CHANNEL_LCD2) 2089 if (channel == OMAP_DSS_CHANNEL_LCD2)
2208 REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); 2090 REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
@@ -2211,7 +2093,7 @@ void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
2211} 2093}
2212 2094
2213 2095
2214void dispc_set_lcd_display_type(enum omap_channel channel, 2096void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
2215 enum omap_lcd_display_type type) 2097 enum omap_lcd_display_type type)
2216{ 2098{
2217 int mode; 2099 int mode;
@@ -2242,12 +2124,12 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)
2242} 2124}
2243 2125
2244 2126
2245void dispc_set_default_color(enum omap_channel channel, u32 color) 2127void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
2246{ 2128{
2247 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); 2129 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
2248} 2130}
2249 2131
2250u32 dispc_get_default_color(enum omap_channel channel) 2132u32 dispc_mgr_get_default_color(enum omap_channel channel)
2251{ 2133{
2252 u32 l; 2134 u32 l;
2253 2135
@@ -2260,7 +2142,7 @@ u32 dispc_get_default_color(enum omap_channel channel)
2260 return l; 2142 return l;
2261} 2143}
2262 2144
2263void dispc_set_trans_key(enum omap_channel ch, 2145void dispc_mgr_set_trans_key(enum omap_channel ch,
2264 enum omap_dss_trans_key_type type, 2146 enum omap_dss_trans_key_type type,
2265 u32 trans_key) 2147 u32 trans_key)
2266{ 2148{
@@ -2274,7 +2156,7 @@ void dispc_set_trans_key(enum omap_channel ch,
2274 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); 2156 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
2275} 2157}
2276 2158
2277void dispc_get_trans_key(enum omap_channel ch, 2159void dispc_mgr_get_trans_key(enum omap_channel ch,
2278 enum omap_dss_trans_key_type *type, 2160 enum omap_dss_trans_key_type *type,
2279 u32 *trans_key) 2161 u32 *trans_key)
2280{ 2162{
@@ -2293,7 +2175,7 @@ void dispc_get_trans_key(enum omap_channel ch,
2293 *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); 2175 *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
2294} 2176}
2295 2177
2296void dispc_enable_trans_key(enum omap_channel ch, bool enable) 2178void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
2297{ 2179{
2298 if (ch == OMAP_DSS_CHANNEL_LCD) 2180 if (ch == OMAP_DSS_CHANNEL_LCD)
2299 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); 2181 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
@@ -2302,39 +2184,36 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable)
2302 else /* OMAP_DSS_CHANNEL_LCD2 */ 2184 else /* OMAP_DSS_CHANNEL_LCD2 */
2303 REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); 2185 REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
2304} 2186}
2305void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) 2187
2188void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable)
2306{ 2189{
2307 if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) 2190 if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
2308 return; 2191 return;
2309 2192
2310 if (ch == OMAP_DSS_CHANNEL_LCD) 2193 if (ch == OMAP_DSS_CHANNEL_LCD)
2311 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); 2194 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
2312 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2195 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2313 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); 2196 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
2314 else /* OMAP_DSS_CHANNEL_LCD2 */
2315 REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
2316} 2197}
2317bool dispc_alpha_blending_enabled(enum omap_channel ch) 2198
2199bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch)
2318{ 2200{
2319 bool enabled; 2201 bool enabled;
2320 2202
2321 if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) 2203 if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
2322 return false; 2204 return false;
2323 2205
2324 if (ch == OMAP_DSS_CHANNEL_LCD) 2206 if (ch == OMAP_DSS_CHANNEL_LCD)
2325 enabled = REG_GET(DISPC_CONFIG, 18, 18); 2207 enabled = REG_GET(DISPC_CONFIG, 18, 18);
2326 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2208 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2327 enabled = REG_GET(DISPC_CONFIG, 19, 19); 2209 enabled = REG_GET(DISPC_CONFIG, 19, 19);
2328 else if (ch == OMAP_DSS_CHANNEL_LCD2)
2329 enabled = REG_GET(DISPC_CONFIG2, 18, 18);
2330 else 2210 else
2331 BUG(); 2211 BUG();
2332 2212
2333 return enabled; 2213 return enabled;
2334} 2214}
2335 2215
2336 2216bool dispc_mgr_trans_key_enabled(enum omap_channel ch)
2337bool dispc_trans_key_enabled(enum omap_channel ch)
2338{ 2217{
2339 bool enabled; 2218 bool enabled;
2340 2219
@@ -2351,7 +2230,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
2351} 2230}
2352 2231
2353 2232
2354void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) 2233void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2355{ 2234{
2356 int code; 2235 int code;
2357 2236
@@ -2379,46 +2258,41 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2379 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); 2258 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
2380} 2259}
2381 2260
2382void dispc_set_parallel_interface_mode(enum omap_channel channel, 2261void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
2383 enum omap_parallel_interface_mode mode)
2384{ 2262{
2385 u32 l; 2263 u32 l;
2386 int stallmode; 2264 int gpout0, gpout1;
2387 int gpout0 = 1;
2388 int gpout1;
2389 2265
2390 switch (mode) { 2266 switch (mode) {
2391 case OMAP_DSS_PARALLELMODE_BYPASS: 2267 case DSS_IO_PAD_MODE_RESET:
2392 stallmode = 0; 2268 gpout0 = 0;
2393 gpout1 = 1; 2269 gpout1 = 0;
2394 break; 2270 break;
2395 2271 case DSS_IO_PAD_MODE_RFBI:
2396 case OMAP_DSS_PARALLELMODE_RFBI: 2272 gpout0 = 1;
2397 stallmode = 1;
2398 gpout1 = 0; 2273 gpout1 = 0;
2399 break; 2274 break;
2400 2275 case DSS_IO_PAD_MODE_BYPASS:
2401 case OMAP_DSS_PARALLELMODE_DSI: 2276 gpout0 = 1;
2402 stallmode = 1;
2403 gpout1 = 1; 2277 gpout1 = 1;
2404 break; 2278 break;
2405
2406 default: 2279 default:
2407 BUG(); 2280 BUG();
2408 return; 2281 return;
2409 } 2282 }
2410 2283
2411 if (channel == OMAP_DSS_CHANNEL_LCD2) { 2284 l = dispc_read_reg(DISPC_CONTROL);
2412 l = dispc_read_reg(DISPC_CONTROL2); 2285 l = FLD_MOD(l, gpout0, 15, 15);
2413 l = FLD_MOD(l, stallmode, 11, 11); 2286 l = FLD_MOD(l, gpout1, 16, 16);
2414 dispc_write_reg(DISPC_CONTROL2, l); 2287 dispc_write_reg(DISPC_CONTROL, l);
2415 } else { 2288}
2416 l = dispc_read_reg(DISPC_CONTROL); 2289
2417 l = FLD_MOD(l, stallmode, 11, 11); 2290void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
2418 l = FLD_MOD(l, gpout0, 15, 15); 2291{
2419 l = FLD_MOD(l, gpout1, 16, 16); 2292 if (channel == OMAP_DSS_CHANNEL_LCD2)
2420 dispc_write_reg(DISPC_CONTROL, l); 2293 REG_FLD_MOD(DISPC_CONTROL2, enable, 11, 11);
2421 } 2294 else
2295 REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11);
2422} 2296}
2423 2297
2424static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, 2298static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2452,7 +2326,7 @@ bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
2452 timings->vfp, timings->vbp); 2326 timings->vfp, timings->vbp);
2453} 2327}
2454 2328
2455static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw, 2329static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
2456 int hfp, int hbp, int vsw, int vfp, int vbp) 2330 int hfp, int hbp, int vsw, int vfp, int vbp)
2457{ 2331{
2458 u32 timing_h, timing_v; 2332 u32 timing_h, timing_v;
@@ -2476,7 +2350,7 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
2476} 2350}
2477 2351
2478/* change name to mode? */ 2352/* change name to mode? */
2479void dispc_set_lcd_timings(enum omap_channel channel, 2353void dispc_mgr_set_lcd_timings(enum omap_channel channel,
2480 struct omap_video_timings *timings) 2354 struct omap_video_timings *timings)
2481{ 2355{
2482 unsigned xtot, ytot; 2356 unsigned xtot, ytot;
@@ -2487,11 +2361,11 @@ void dispc_set_lcd_timings(enum omap_channel channel,
2487 timings->vfp, timings->vbp)) 2361 timings->vfp, timings->vbp))
2488 BUG(); 2362 BUG();
2489 2363
2490 _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp, 2364 _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp,
2491 timings->hbp, timings->vsw, timings->vfp, 2365 timings->hbp, timings->vsw, timings->vfp,
2492 timings->vbp); 2366 timings->vbp);
2493 2367
2494 dispc_set_lcd_size(channel, timings->x_res, timings->y_res); 2368 dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res);
2495 2369
2496 xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; 2370 xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
2497 ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; 2371 ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
@@ -2509,17 +2383,17 @@ void dispc_set_lcd_timings(enum omap_channel channel,
2509 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); 2383 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
2510} 2384}
2511 2385
2512static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, 2386static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
2513 u16 pck_div) 2387 u16 pck_div)
2514{ 2388{
2515 BUG_ON(lck_div < 1); 2389 BUG_ON(lck_div < 1);
2516 BUG_ON(pck_div < 2); 2390 BUG_ON(pck_div < 1);
2517 2391
2518 dispc_write_reg(DISPC_DIVISORo(channel), 2392 dispc_write_reg(DISPC_DIVISORo(channel),
2519 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); 2393 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
2520} 2394}
2521 2395
2522static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, 2396static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
2523 int *pck_div) 2397 int *pck_div)
2524{ 2398{
2525 u32 l; 2399 u32 l;
@@ -2552,7 +2426,7 @@ unsigned long dispc_fclk_rate(void)
2552 return r; 2426 return r;
2553} 2427}
2554 2428
2555unsigned long dispc_lclk_rate(enum omap_channel channel) 2429unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
2556{ 2430{
2557 struct platform_device *dsidev; 2431 struct platform_device *dsidev;
2558 int lcd; 2432 int lcd;
@@ -2582,19 +2456,34 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
2582 return r / lcd; 2456 return r / lcd;
2583} 2457}
2584 2458
2585unsigned long dispc_pclk_rate(enum omap_channel channel) 2459unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
2586{ 2460{
2587 int pcd;
2588 unsigned long r; 2461 unsigned long r;
2589 u32 l;
2590 2462
2591 l = dispc_read_reg(DISPC_DIVISORo(channel)); 2463 if (dispc_mgr_is_lcd(channel)) {
2464 int pcd;
2465 u32 l;
2592 2466
2593 pcd = FLD_GET(l, 7, 0); 2467 l = dispc_read_reg(DISPC_DIVISORo(channel));
2594 2468
2595 r = dispc_lclk_rate(channel); 2469 pcd = FLD_GET(l, 7, 0);
2596 2470
2597 return r / pcd; 2471 r = dispc_mgr_lclk_rate(channel);
2472
2473 return r / pcd;
2474 } else {
2475 struct omap_dss_device *dssdev =
2476 dispc_mgr_get_device(channel);
2477
2478 switch (dssdev->type) {
2479 case OMAP_DISPLAY_TYPE_VENC:
2480 return venc_get_pixel_clock();
2481 case OMAP_DISPLAY_TYPE_HDMI:
2482 return hdmi_get_pixel_clock();
2483 default:
2484 BUG();
2485 }
2486 }
2598} 2487}
2599 2488
2600void dispc_dump_clocks(struct seq_file *s) 2489void dispc_dump_clocks(struct seq_file *s)
@@ -2631,12 +2520,12 @@ void dispc_dump_clocks(struct seq_file *s)
2631 dss_get_generic_clk_source_name(lcd_clk_src), 2520 dss_get_generic_clk_source_name(lcd_clk_src),
2632 dss_feat_get_clk_source_name(lcd_clk_src)); 2521 dss_feat_get_clk_source_name(lcd_clk_src));
2633 2522
2634 dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); 2523 dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
2635 2524
2636 seq_printf(s, "lck\t\t%-16lulck div\t%u\n", 2525 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2637 dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd); 2526 dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd);
2638 seq_printf(s, "pck\t\t%-16lupck div\t%u\n", 2527 seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
2639 dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd); 2528 dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd);
2640 if (dss_has_feature(FEAT_MGR_LCD2)) { 2529 if (dss_has_feature(FEAT_MGR_LCD2)) {
2641 seq_printf(s, "- LCD2 -\n"); 2530 seq_printf(s, "- LCD2 -\n");
2642 2531
@@ -2646,12 +2535,12 @@ void dispc_dump_clocks(struct seq_file *s)
2646 dss_get_generic_clk_source_name(lcd_clk_src), 2535 dss_get_generic_clk_source_name(lcd_clk_src),
2647 dss_feat_get_clk_source_name(lcd_clk_src)); 2536 dss_feat_get_clk_source_name(lcd_clk_src));
2648 2537
2649 dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); 2538 dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
2650 2539
2651 seq_printf(s, "lck\t\t%-16lulck div\t%u\n", 2540 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2652 dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd); 2541 dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd);
2653 seq_printf(s, "pck\t\t%-16lupck div\t%u\n", 2542 seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
2654 dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); 2543 dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
2655 } 2544 }
2656 2545
2657 dispc_runtime_put(); 2546 dispc_runtime_put();
@@ -2692,6 +2581,10 @@ void dispc_dump_irqs(struct seq_file *s)
2692 PIS(VID1_END_WIN); 2581 PIS(VID1_END_WIN);
2693 PIS(VID2_FIFO_UNDERFLOW); 2582 PIS(VID2_FIFO_UNDERFLOW);
2694 PIS(VID2_END_WIN); 2583 PIS(VID2_END_WIN);
2584 if (dss_feat_get_num_ovls() > 3) {
2585 PIS(VID3_FIFO_UNDERFLOW);
2586 PIS(VID3_END_WIN);
2587 }
2695 PIS(SYNC_LOST); 2588 PIS(SYNC_LOST);
2696 PIS(SYNC_LOST_DIGIT); 2589 PIS(SYNC_LOST_DIGIT);
2697 PIS(WAKEUP); 2590 PIS(WAKEUP);
@@ -2707,11 +2600,26 @@ void dispc_dump_irqs(struct seq_file *s)
2707 2600
2708void dispc_dump_regs(struct seq_file *s) 2601void dispc_dump_regs(struct seq_file *s)
2709{ 2602{
2603 int i, j;
2604 const char *mgr_names[] = {
2605 [OMAP_DSS_CHANNEL_LCD] = "LCD",
2606 [OMAP_DSS_CHANNEL_DIGIT] = "TV",
2607 [OMAP_DSS_CHANNEL_LCD2] = "LCD2",
2608 };
2609 const char *ovl_names[] = {
2610 [OMAP_DSS_GFX] = "GFX",
2611 [OMAP_DSS_VIDEO1] = "VID1",
2612 [OMAP_DSS_VIDEO2] = "VID2",
2613 [OMAP_DSS_VIDEO3] = "VID3",
2614 };
2615 const char **p_names;
2616
2710#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) 2617#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
2711 2618
2712 if (dispc_runtime_get()) 2619 if (dispc_runtime_get())
2713 return; 2620 return;
2714 2621
2622 /* DISPC common registers */
2715 DUMPREG(DISPC_REVISION); 2623 DUMPREG(DISPC_REVISION);
2716 DUMPREG(DISPC_SYSCONFIG); 2624 DUMPREG(DISPC_SYSCONFIG);
2717 DUMPREG(DISPC_SYSSTATUS); 2625 DUMPREG(DISPC_SYSSTATUS);
@@ -2720,247 +2628,139 @@ void dispc_dump_regs(struct seq_file *s)
2720 DUMPREG(DISPC_CONTROL); 2628 DUMPREG(DISPC_CONTROL);
2721 DUMPREG(DISPC_CONFIG); 2629 DUMPREG(DISPC_CONFIG);
2722 DUMPREG(DISPC_CAPABLE); 2630 DUMPREG(DISPC_CAPABLE);
2723 DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
2724 DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
2725 DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
2726 DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
2727 DUMPREG(DISPC_LINE_STATUS); 2631 DUMPREG(DISPC_LINE_STATUS);
2728 DUMPREG(DISPC_LINE_NUMBER); 2632 DUMPREG(DISPC_LINE_NUMBER);
2729 DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD)); 2633 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
2730 DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD)); 2634 dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
2731 DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
2732 DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
2733 if (dss_has_feature(FEAT_GLOBAL_ALPHA))
2734 DUMPREG(DISPC_GLOBAL_ALPHA); 2635 DUMPREG(DISPC_GLOBAL_ALPHA);
2735 DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
2736 DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
2737 if (dss_has_feature(FEAT_MGR_LCD2)) { 2636 if (dss_has_feature(FEAT_MGR_LCD2)) {
2738 DUMPREG(DISPC_CONTROL2); 2637 DUMPREG(DISPC_CONTROL2);
2739 DUMPREG(DISPC_CONFIG2); 2638 DUMPREG(DISPC_CONFIG2);
2740 DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
2741 DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
2742 DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2));
2743 DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2));
2744 DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
2745 DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2));
2746 DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
2747 }
2748
2749 DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX));
2750 DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX));
2751 DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX));
2752 DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX));
2753 DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX));
2754 DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
2755 DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX));
2756 DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX));
2757 DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX));
2758 DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX));
2759 DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX));
2760
2761 DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
2762 DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
2763 DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
2764
2765 if (dss_has_feature(FEAT_CPR)) {
2766 DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
2767 DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
2768 DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
2769 } 2639 }
2770 if (dss_has_feature(FEAT_MGR_LCD2)) { 2640
2771 DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); 2641#undef DUMPREG
2772 DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); 2642
2773 DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); 2643#define DISPC_REG(i, name) name(i)
2644#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
2645 48 - strlen(#r) - strlen(p_names[i]), " ", \
2646 dispc_read_reg(DISPC_REG(i, r)))
2647
2648 p_names = mgr_names;
2649
2650 /* DISPC channel specific registers */
2651 for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
2652 DUMPREG(i, DISPC_DEFAULT_COLOR);
2653 DUMPREG(i, DISPC_TRANS_COLOR);
2654 DUMPREG(i, DISPC_SIZE_MGR);
2655
2656 if (i == OMAP_DSS_CHANNEL_DIGIT)
2657 continue;
2658
2659 DUMPREG(i, DISPC_DEFAULT_COLOR);
2660 DUMPREG(i, DISPC_TRANS_COLOR);
2661 DUMPREG(i, DISPC_TIMING_H);
2662 DUMPREG(i, DISPC_TIMING_V);
2663 DUMPREG(i, DISPC_POL_FREQ);
2664 DUMPREG(i, DISPC_DIVISORo);
2665 DUMPREG(i, DISPC_SIZE_MGR);
2666
2667 DUMPREG(i, DISPC_DATA_CYCLE1);
2668 DUMPREG(i, DISPC_DATA_CYCLE2);
2669 DUMPREG(i, DISPC_DATA_CYCLE3);
2774 2670
2775 if (dss_has_feature(FEAT_CPR)) { 2671 if (dss_has_feature(FEAT_CPR)) {
2776 DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); 2672 DUMPREG(i, DISPC_CPR_COEF_R);
2777 DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); 2673 DUMPREG(i, DISPC_CPR_COEF_G);
2778 DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); 2674 DUMPREG(i, DISPC_CPR_COEF_B);
2675 }
2676 }
2677
2678 p_names = ovl_names;
2679
2680 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
2681 DUMPREG(i, DISPC_OVL_BA0);
2682 DUMPREG(i, DISPC_OVL_BA1);
2683 DUMPREG(i, DISPC_OVL_POSITION);
2684 DUMPREG(i, DISPC_OVL_SIZE);
2685 DUMPREG(i, DISPC_OVL_ATTRIBUTES);
2686 DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD);
2687 DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS);
2688 DUMPREG(i, DISPC_OVL_ROW_INC);
2689 DUMPREG(i, DISPC_OVL_PIXEL_INC);
2690 if (dss_has_feature(FEAT_PRELOAD))
2691 DUMPREG(i, DISPC_OVL_PRELOAD);
2692
2693 if (i == OMAP_DSS_GFX) {
2694 DUMPREG(i, DISPC_OVL_WINDOW_SKIP);
2695 DUMPREG(i, DISPC_OVL_TABLE_BA);
2696 continue;
2697 }
2698
2699 DUMPREG(i, DISPC_OVL_FIR);
2700 DUMPREG(i, DISPC_OVL_PICTURE_SIZE);
2701 DUMPREG(i, DISPC_OVL_ACCU0);
2702 DUMPREG(i, DISPC_OVL_ACCU1);
2703 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
2704 DUMPREG(i, DISPC_OVL_BA0_UV);
2705 DUMPREG(i, DISPC_OVL_BA1_UV);
2706 DUMPREG(i, DISPC_OVL_FIR2);
2707 DUMPREG(i, DISPC_OVL_ACCU2_0);
2708 DUMPREG(i, DISPC_OVL_ACCU2_1);
2779 } 2709 }
2710 if (dss_has_feature(FEAT_ATTR2))
2711 DUMPREG(i, DISPC_OVL_ATTRIBUTES2);
2712 if (dss_has_feature(FEAT_PRELOAD))
2713 DUMPREG(i, DISPC_OVL_PRELOAD);
2780 } 2714 }
2781 2715
2782 if (dss_has_feature(FEAT_PRELOAD)) 2716#undef DISPC_REG
2783 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX)); 2717#undef DUMPREG
2784 2718
2785 DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1)); 2719#define DISPC_REG(plane, name, i) name(plane, i)
2786 DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1)); 2720#define DUMPREG(plane, name, i) \
2787 DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1)); 2721 seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
2788 DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1)); 2722 46 - strlen(#name) - strlen(p_names[plane]), " ", \
2789 DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); 2723 dispc_read_reg(DISPC_REG(plane, name, i)))
2790 DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); 2724
2791 DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1)); 2725 /* Video pipeline coefficient registers */
2792 DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1)); 2726
2793 DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); 2727 /* start from OMAP_DSS_VIDEO1 */
2794 DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1)); 2728 for (i = 1; i < dss_feat_get_num_ovls(); i++) {
2795 DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); 2729 for (j = 0; j < 8; j++)
2796 DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1)); 2730 DUMPREG(i, DISPC_OVL_FIR_COEF_H, j);
2797 DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1)); 2731
2798 2732 for (j = 0; j < 8; j++)
2799 DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2)); 2733 DUMPREG(i, DISPC_OVL_FIR_COEF_HV, j);
2800 DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2)); 2734
2801 DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2)); 2735 for (j = 0; j < 5; j++)
2802 DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2)); 2736 DUMPREG(i, DISPC_OVL_CONV_COEF, j);
2803 DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); 2737
2804 DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); 2738 if (dss_has_feature(FEAT_FIR_COEF_V)) {
2805 DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2)); 2739 for (j = 0; j < 8; j++)
2806 DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2)); 2740 DUMPREG(i, DISPC_OVL_FIR_COEF_V, j);
2807 DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); 2741 }
2808 DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2)); 2742
2809 DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); 2743 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
2810 DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2)); 2744 for (j = 0; j < 8; j++)
2811 DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2)); 2745 DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j);
2812 2746
2813 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0)); 2747 for (j = 0; j < 8; j++)
2814 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1)); 2748 DUMPREG(i, DISPC_OVL_FIR_COEF_HV2, j);
2815 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2)); 2749
2816 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3)); 2750 for (j = 0; j < 8; j++)
2817 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4)); 2751 DUMPREG(i, DISPC_OVL_FIR_COEF_V2, j);
2818 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5)); 2752 }
2819 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6));
2820 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7));
2821 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0));
2822 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1));
2823 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2));
2824 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3));
2825 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4));
2826 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5));
2827 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6));
2828 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7));
2829 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0));
2830 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1));
2831 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
2832 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
2833 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
2834 if (dss_has_feature(FEAT_FIR_COEF_V)) {
2835 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
2836 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
2837 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
2838 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
2839 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
2840 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
2841 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
2842 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
2843 }
2844
2845 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
2846 DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
2847 DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO1));
2848 DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO1));
2849 DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO1));
2850 DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO1));
2851
2852 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 0));
2853 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 1));
2854 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 2));
2855 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 3));
2856 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 4));
2857 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 5));
2858 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 6));
2859 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 7));
2860
2861 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 0));
2862 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 1));
2863 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 2));
2864 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 3));
2865 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 4));
2866 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 5));
2867 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 6));
2868 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 7));
2869
2870 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 0));
2871 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 1));
2872 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 2));
2873 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 3));
2874 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 4));
2875 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 5));
2876 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 6));
2877 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 7));
2878 }
2879 if (dss_has_feature(FEAT_ATTR2))
2880 DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
2881
2882
2883 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0));
2884 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1));
2885 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2));
2886 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3));
2887 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4));
2888 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5));
2889 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6));
2890 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7));
2891 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0));
2892 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1));
2893 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2));
2894 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3));
2895 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4));
2896 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5));
2897 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6));
2898 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7));
2899 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0));
2900 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1));
2901 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
2902 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
2903 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
2904
2905 if (dss_has_feature(FEAT_FIR_COEF_V)) {
2906 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
2907 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
2908 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
2909 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
2910 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
2911 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
2912 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
2913 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
2914 }
2915
2916 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
2917 DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
2918 DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO2));
2919 DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO2));
2920 DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO2));
2921 DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO2));
2922
2923 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 0));
2924 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 1));
2925 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 2));
2926 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 3));
2927 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 4));
2928 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 5));
2929 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 6));
2930 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 7));
2931
2932 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 0));
2933 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 1));
2934 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 2));
2935 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 3));
2936 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 4));
2937 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 5));
2938 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 6));
2939 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 7));
2940
2941 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 0));
2942 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 1));
2943 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 2));
2944 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 3));
2945 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 4));
2946 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 5));
2947 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 6));
2948 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 7));
2949 }
2950 if (dss_has_feature(FEAT_ATTR2))
2951 DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
2952
2953 if (dss_has_feature(FEAT_PRELOAD)) {
2954 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
2955 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
2956 } 2753 }
2957 2754
2958 dispc_runtime_put(); 2755 dispc_runtime_put();
2756
2757#undef DISPC_REG
2959#undef DUMPREG 2758#undef DUMPREG
2960} 2759}
2961 2760
2962static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf, 2761static void _dispc_mgr_set_pol_freq(enum omap_channel channel, bool onoff,
2963 bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb) 2762 bool rf, bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi,
2763 u8 acb)
2964{ 2764{
2965 u32 l = 0; 2765 u32 l = 0;
2966 2766
@@ -2979,10 +2779,10 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
2979 dispc_write_reg(DISPC_POL_FREQ(channel), l); 2779 dispc_write_reg(DISPC_POL_FREQ(channel), l);
2980} 2780}
2981 2781
2982void dispc_set_pol_freq(enum omap_channel channel, 2782void dispc_mgr_set_pol_freq(enum omap_channel channel,
2983 enum omap_panel_config config, u8 acbi, u8 acb) 2783 enum omap_panel_config config, u8 acbi, u8 acb)
2984{ 2784{
2985 _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0, 2785 _dispc_mgr_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0,
2986 (config & OMAP_DSS_LCD_RF) != 0, 2786 (config & OMAP_DSS_LCD_RF) != 0,
2987 (config & OMAP_DSS_LCD_IEO) != 0, 2787 (config & OMAP_DSS_LCD_IEO) != 0,
2988 (config & OMAP_DSS_LCD_IPC) != 0, 2788 (config & OMAP_DSS_LCD_IPC) != 0,
@@ -2995,11 +2795,17 @@ void dispc_set_pol_freq(enum omap_channel channel,
2995void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, 2795void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
2996 struct dispc_clock_info *cinfo) 2796 struct dispc_clock_info *cinfo)
2997{ 2797{
2998 u16 pcd_min = is_tft ? 2 : 3; 2798 u16 pcd_min, pcd_max;
2999 unsigned long best_pck; 2799 unsigned long best_pck;
3000 u16 best_ld, cur_ld; 2800 u16 best_ld, cur_ld;
3001 u16 best_pd, cur_pd; 2801 u16 best_pd, cur_pd;
3002 2802
2803 pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
2804 pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
2805
2806 if (!is_tft)
2807 pcd_min = 3;
2808
3003 best_pck = 0; 2809 best_pck = 0;
3004 best_ld = 0; 2810 best_ld = 0;
3005 best_pd = 0; 2811 best_pd = 0;
@@ -3007,7 +2813,7 @@ void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
3007 for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { 2813 for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
3008 unsigned long lck = fck / cur_ld; 2814 unsigned long lck = fck / cur_ld;
3009 2815
3010 for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) { 2816 for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) {
3011 unsigned long pck = lck / cur_pd; 2817 unsigned long pck = lck / cur_pd;
3012 long old_delta = abs(best_pck - req_pck); 2818 long old_delta = abs(best_pck - req_pck);
3013 long new_delta = abs(pck - req_pck); 2819 long new_delta = abs(pck - req_pck);
@@ -3042,7 +2848,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
3042{ 2848{
3043 if (cinfo->lck_div > 255 || cinfo->lck_div == 0) 2849 if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
3044 return -EINVAL; 2850 return -EINVAL;
3045 if (cinfo->pck_div < 2 || cinfo->pck_div > 255) 2851 if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
3046 return -EINVAL; 2852 return -EINVAL;
3047 2853
3048 cinfo->lck = dispc_fclk_rate / cinfo->lck_div; 2854 cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
@@ -3051,18 +2857,18 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
3051 return 0; 2857 return 0;
3052} 2858}
3053 2859
3054int dispc_set_clock_div(enum omap_channel channel, 2860int dispc_mgr_set_clock_div(enum omap_channel channel,
3055 struct dispc_clock_info *cinfo) 2861 struct dispc_clock_info *cinfo)
3056{ 2862{
3057 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); 2863 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
3058 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); 2864 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
3059 2865
3060 dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); 2866 dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
3061 2867
3062 return 0; 2868 return 0;
3063} 2869}
3064 2870
3065int dispc_get_clock_div(enum omap_channel channel, 2871int dispc_mgr_get_clock_div(enum omap_channel channel,
3066 struct dispc_clock_info *cinfo) 2872 struct dispc_clock_info *cinfo)
3067{ 2873{
3068 unsigned long fck; 2874 unsigned long fck;
@@ -3207,6 +3013,8 @@ static void print_irq_status(u32 status)
3207 PIS(OCP_ERR); 3013 PIS(OCP_ERR);
3208 PIS(VID1_FIFO_UNDERFLOW); 3014 PIS(VID1_FIFO_UNDERFLOW);
3209 PIS(VID2_FIFO_UNDERFLOW); 3015 PIS(VID2_FIFO_UNDERFLOW);
3016 if (dss_feat_get_num_ovls() > 3)
3017 PIS(VID3_FIFO_UNDERFLOW);
3210 PIS(SYNC_LOST); 3018 PIS(SYNC_LOST);
3211 PIS(SYNC_LOST_DIGIT); 3019 PIS(SYNC_LOST_DIGIT);
3212 if (dss_has_feature(FEAT_MGR_LCD2)) 3020 if (dss_has_feature(FEAT_MGR_LCD2))
@@ -3300,178 +3108,72 @@ static void dispc_error_worker(struct work_struct *work)
3300 int i; 3108 int i;
3301 u32 errors; 3109 u32 errors;
3302 unsigned long flags; 3110 unsigned long flags;
3111 static const unsigned fifo_underflow_bits[] = {
3112 DISPC_IRQ_GFX_FIFO_UNDERFLOW,
3113 DISPC_IRQ_VID1_FIFO_UNDERFLOW,
3114 DISPC_IRQ_VID2_FIFO_UNDERFLOW,
3115 DISPC_IRQ_VID3_FIFO_UNDERFLOW,
3116 };
3117
3118 static const unsigned sync_lost_bits[] = {
3119 DISPC_IRQ_SYNC_LOST,
3120 DISPC_IRQ_SYNC_LOST_DIGIT,
3121 DISPC_IRQ_SYNC_LOST2,
3122 };
3303 3123
3304 spin_lock_irqsave(&dispc.irq_lock, flags); 3124 spin_lock_irqsave(&dispc.irq_lock, flags);
3305 errors = dispc.error_irqs; 3125 errors = dispc.error_irqs;
3306 dispc.error_irqs = 0; 3126 dispc.error_irqs = 0;
3307 spin_unlock_irqrestore(&dispc.irq_lock, flags); 3127 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3308 3128
3309 if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) { 3129 dispc_runtime_get();
3310 DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
3311 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3312 struct omap_overlay *ovl;
3313 ovl = omap_dss_get_overlay(i);
3314
3315 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3316 continue;
3317
3318 if (ovl->id == 0) {
3319 dispc_enable_plane(ovl->id, 0);
3320 dispc_go(ovl->manager->id);
3321 mdelay(50);
3322 break;
3323 }
3324 }
3325 }
3326
3327 if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
3328 DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
3329 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3330 struct omap_overlay *ovl;
3331 ovl = omap_dss_get_overlay(i);
3332
3333 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3334 continue;
3335
3336 if (ovl->id == 1) {
3337 dispc_enable_plane(ovl->id, 0);
3338 dispc_go(ovl->manager->id);
3339 mdelay(50);
3340 break;
3341 }
3342 }
3343 }
3344
3345 if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
3346 DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
3347 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3348 struct omap_overlay *ovl;
3349 ovl = omap_dss_get_overlay(i);
3350
3351 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3352 continue;
3353 3130
3354 if (ovl->id == 2) { 3131 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3355 dispc_enable_plane(ovl->id, 0); 3132 struct omap_overlay *ovl;
3356 dispc_go(ovl->manager->id); 3133 unsigned bit;
3357 mdelay(50);
3358 break;
3359 }
3360 }
3361 }
3362
3363 if (errors & DISPC_IRQ_SYNC_LOST) {
3364 struct omap_overlay_manager *manager = NULL;
3365 bool enable = false;
3366 3134
3367 DSSERR("SYNC_LOST, disabling LCD\n"); 3135 ovl = omap_dss_get_overlay(i);
3136 bit = fifo_underflow_bits[i];
3368 3137
3369 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 3138 if (bit & errors) {
3370 struct omap_overlay_manager *mgr; 3139 DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
3371 mgr = omap_dss_get_overlay_manager(i); 3140 ovl->name);
3372 3141 dispc_ovl_enable(ovl->id, false);
3373 if (mgr->id == OMAP_DSS_CHANNEL_LCD) { 3142 dispc_mgr_go(ovl->manager->id);
3374 manager = mgr;
3375 enable = mgr->device->state ==
3376 OMAP_DSS_DISPLAY_ACTIVE;
3377 mgr->device->driver->disable(mgr->device);
3378 break;
3379 }
3380 }
3381
3382 if (manager) {
3383 struct omap_dss_device *dssdev = manager->device;
3384 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3385 struct omap_overlay *ovl;
3386 ovl = omap_dss_get_overlay(i);
3387
3388 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3389 continue;
3390
3391 if (ovl->id != 0 && ovl->manager == manager)
3392 dispc_enable_plane(ovl->id, 0);
3393 }
3394
3395 dispc_go(manager->id);
3396 mdelay(50); 3143 mdelay(50);
3397 if (enable)
3398 dssdev->driver->enable(dssdev);
3399 } 3144 }
3400 } 3145 }
3401 3146
3402 if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) { 3147 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3403 struct omap_overlay_manager *manager = NULL; 3148 struct omap_overlay_manager *mgr;
3404 bool enable = false; 3149 unsigned bit;
3405 3150
3406 DSSERR("SYNC_LOST_DIGIT, disabling TV\n"); 3151 mgr = omap_dss_get_overlay_manager(i);
3152 bit = sync_lost_bits[i];
3407 3153
3408 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 3154 if (bit & errors) {
3409 struct omap_overlay_manager *mgr; 3155 struct omap_dss_device *dssdev = mgr->device;
3410 mgr = omap_dss_get_overlay_manager(i); 3156 bool enable;
3411 3157
3412 if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) { 3158 DSSERR("SYNC_LOST on channel %s, restarting the output "
3413 manager = mgr; 3159 "with video overlays disabled\n",
3414 enable = mgr->device->state == 3160 mgr->name);
3415 OMAP_DSS_DISPLAY_ACTIVE;
3416 mgr->device->driver->disable(mgr->device);
3417 break;
3418 }
3419 }
3420 3161
3421 if (manager) { 3162 enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
3422 struct omap_dss_device *dssdev = manager->device; 3163 dssdev->driver->disable(dssdev);
3423 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3424 struct omap_overlay *ovl;
3425 ovl = omap_dss_get_overlay(i);
3426
3427 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3428 continue;
3429
3430 if (ovl->id != 0 && ovl->manager == manager)
3431 dispc_enable_plane(ovl->id, 0);
3432 }
3433 3164
3434 dispc_go(manager->id);
3435 mdelay(50);
3436 if (enable)
3437 dssdev->driver->enable(dssdev);
3438 }
3439 }
3440
3441 if (errors & DISPC_IRQ_SYNC_LOST2) {
3442 struct omap_overlay_manager *manager = NULL;
3443 bool enable = false;
3444
3445 DSSERR("SYNC_LOST for LCD2, disabling LCD2\n");
3446
3447 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3448 struct omap_overlay_manager *mgr;
3449 mgr = omap_dss_get_overlay_manager(i);
3450
3451 if (mgr->id == OMAP_DSS_CHANNEL_LCD2) {
3452 manager = mgr;
3453 enable = mgr->device->state ==
3454 OMAP_DSS_DISPLAY_ACTIVE;
3455 mgr->device->driver->disable(mgr->device);
3456 break;
3457 }
3458 }
3459
3460 if (manager) {
3461 struct omap_dss_device *dssdev = manager->device;
3462 for (i = 0; i < omap_dss_get_num_overlays(); ++i) { 3165 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3463 struct omap_overlay *ovl; 3166 struct omap_overlay *ovl;
3464 ovl = omap_dss_get_overlay(i); 3167 ovl = omap_dss_get_overlay(i);
3465 3168
3466 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) 3169 if (ovl->id != OMAP_DSS_GFX &&
3467 continue; 3170 ovl->manager == mgr)
3468 3171 dispc_ovl_enable(ovl->id, false);
3469 if (ovl->id != 0 && ovl->manager == manager)
3470 dispc_enable_plane(ovl->id, 0);
3471 } 3172 }
3472 3173
3473 dispc_go(manager->id); 3174 dispc_mgr_go(mgr->id);
3474 mdelay(50); 3175 mdelay(50);
3176
3475 if (enable) 3177 if (enable)
3476 dssdev->driver->enable(dssdev); 3178 dssdev->driver->enable(dssdev);
3477 } 3179 }
@@ -3482,9 +3184,7 @@ static void dispc_error_worker(struct work_struct *work)
3482 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 3184 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3483 struct omap_overlay_manager *mgr; 3185 struct omap_overlay_manager *mgr;
3484 mgr = omap_dss_get_overlay_manager(i); 3186 mgr = omap_dss_get_overlay_manager(i);
3485 3187 mgr->device->driver->disable(mgr->device);
3486 if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
3487 mgr->device->driver->disable(mgr->device);
3488 } 3188 }
3489 } 3189 }
3490 3190
@@ -3492,6 +3192,8 @@ static void dispc_error_worker(struct work_struct *work)
3492 dispc.irq_error_mask |= errors; 3192 dispc.irq_error_mask |= errors;
3493 _omap_dispc_set_irqs(); 3193 _omap_dispc_set_irqs();
3494 spin_unlock_irqrestore(&dispc.irq_lock, flags); 3194 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3195
3196 dispc_runtime_put();
3495} 3197}
3496 3198
3497int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) 3199int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
@@ -3586,6 +3288,8 @@ static void _omap_dispc_initialize_irq(void)
3586 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; 3288 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
3587 if (dss_has_feature(FEAT_MGR_LCD2)) 3289 if (dss_has_feature(FEAT_MGR_LCD2))
3588 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; 3290 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
3291 if (dss_feat_get_num_ovls() > 3)
3292 dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
3589 3293
3590 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, 3294 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
3591 * so clear it */ 3295 * so clear it */
@@ -3635,6 +3339,8 @@ static void _omap_dispc_initial_config(void)
3635 dispc_read_plane_fifo_sizes(); 3339 dispc_read_plane_fifo_sizes();
3636 3340
3637 dispc_configure_burst_sizes(); 3341 dispc_configure_burst_sizes();
3342
3343 dispc_ovl_enable_zorder_planes();
3638} 3344}
3639 3345
3640/* DISPC HW IP initialisation */ 3346/* DISPC HW IP initialisation */
@@ -3734,7 +3440,6 @@ static int omap_dispchw_remove(struct platform_device *pdev)
3734static int dispc_runtime_suspend(struct device *dev) 3440static int dispc_runtime_suspend(struct device *dev)
3735{ 3441{
3736 dispc_save_context(); 3442 dispc_save_context();
3737 clk_disable(dispc.dss_clk);
3738 dss_runtime_put(); 3443 dss_runtime_put();
3739 3444
3740 return 0; 3445 return 0;
@@ -3748,7 +3453,6 @@ static int dispc_runtime_resume(struct device *dev)
3748 if (r < 0) 3453 if (r < 0)
3749 return r; 3454 return r;
3750 3455
3751 clk_enable(dispc.dss_clk);
3752 dispc_restore_context(); 3456 dispc_restore_context();
3753 3457
3754 return 0; 3458 return 0;
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index 6c9ee0a0efb..c06efc38983 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -291,6 +291,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
291 return 0x00BC; 291 return 0x00BC;
292 case OMAP_DSS_VIDEO2: 292 case OMAP_DSS_VIDEO2:
293 return 0x014C; 293 return 0x014C;
294 case OMAP_DSS_VIDEO3:
295 return 0x0300;
294 default: 296 default:
295 BUG(); 297 BUG();
296 } 298 }
@@ -304,6 +306,8 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
304 case OMAP_DSS_VIDEO1: 306 case OMAP_DSS_VIDEO1:
305 case OMAP_DSS_VIDEO2: 307 case OMAP_DSS_VIDEO2:
306 return 0x0000; 308 return 0x0000;
309 case OMAP_DSS_VIDEO3:
310 return 0x0008;
307 default: 311 default:
308 BUG(); 312 BUG();
309 } 313 }
@@ -316,6 +320,8 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
316 case OMAP_DSS_VIDEO1: 320 case OMAP_DSS_VIDEO1:
317 case OMAP_DSS_VIDEO2: 321 case OMAP_DSS_VIDEO2:
318 return 0x0004; 322 return 0x0004;
323 case OMAP_DSS_VIDEO3:
324 return 0x000C;
319 default: 325 default:
320 BUG(); 326 BUG();
321 } 327 }
@@ -330,6 +336,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
330 return 0x0544; 336 return 0x0544;
331 case OMAP_DSS_VIDEO2: 337 case OMAP_DSS_VIDEO2:
332 return 0x04BC; 338 return 0x04BC;
339 case OMAP_DSS_VIDEO3:
340 return 0x0310;
333 default: 341 default:
334 BUG(); 342 BUG();
335 } 343 }
@@ -344,6 +352,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
344 return 0x0548; 352 return 0x0548;
345 case OMAP_DSS_VIDEO2: 353 case OMAP_DSS_VIDEO2:
346 return 0x04C0; 354 return 0x04C0;
355 case OMAP_DSS_VIDEO3:
356 return 0x0314;
347 default: 357 default:
348 BUG(); 358 BUG();
349 } 359 }
@@ -356,6 +366,8 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
356 case OMAP_DSS_VIDEO1: 366 case OMAP_DSS_VIDEO1:
357 case OMAP_DSS_VIDEO2: 367 case OMAP_DSS_VIDEO2:
358 return 0x0008; 368 return 0x0008;
369 case OMAP_DSS_VIDEO3:
370 return 0x009C;
359 default: 371 default:
360 BUG(); 372 BUG();
361 } 373 }
@@ -368,6 +380,8 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
368 case OMAP_DSS_VIDEO1: 380 case OMAP_DSS_VIDEO1:
369 case OMAP_DSS_VIDEO2: 381 case OMAP_DSS_VIDEO2:
370 return 0x000C; 382 return 0x000C;
383 case OMAP_DSS_VIDEO3:
384 return 0x00A8;
371 default: 385 default:
372 BUG(); 386 BUG();
373 } 387 }
@@ -381,6 +395,8 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
381 case OMAP_DSS_VIDEO1: 395 case OMAP_DSS_VIDEO1:
382 case OMAP_DSS_VIDEO2: 396 case OMAP_DSS_VIDEO2:
383 return 0x0010; 397 return 0x0010;
398 case OMAP_DSS_VIDEO3:
399 return 0x0070;
384 default: 400 default:
385 BUG(); 401 BUG();
386 } 402 }
@@ -395,6 +411,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
395 return 0x0568; 411 return 0x0568;
396 case OMAP_DSS_VIDEO2: 412 case OMAP_DSS_VIDEO2:
397 return 0x04DC; 413 return 0x04DC;
414 case OMAP_DSS_VIDEO3:
415 return 0x032C;
398 default: 416 default:
399 BUG(); 417 BUG();
400 } 418 }
@@ -408,6 +426,8 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
408 case OMAP_DSS_VIDEO1: 426 case OMAP_DSS_VIDEO1:
409 case OMAP_DSS_VIDEO2: 427 case OMAP_DSS_VIDEO2:
410 return 0x0014; 428 return 0x0014;
429 case OMAP_DSS_VIDEO3:
430 return 0x008C;
411 default: 431 default:
412 BUG(); 432 BUG();
413 } 433 }
@@ -421,6 +441,8 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
421 case OMAP_DSS_VIDEO1: 441 case OMAP_DSS_VIDEO1:
422 case OMAP_DSS_VIDEO2: 442 case OMAP_DSS_VIDEO2:
423 return 0x0018; 443 return 0x0018;
444 case OMAP_DSS_VIDEO3:
445 return 0x0088;
424 default: 446 default:
425 BUG(); 447 BUG();
426 } 448 }
@@ -434,6 +456,8 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
434 case OMAP_DSS_VIDEO1: 456 case OMAP_DSS_VIDEO1:
435 case OMAP_DSS_VIDEO2: 457 case OMAP_DSS_VIDEO2:
436 return 0x001C; 458 return 0x001C;
459 case OMAP_DSS_VIDEO3:
460 return 0x00A4;
437 default: 461 default:
438 BUG(); 462 BUG();
439 } 463 }
@@ -447,6 +471,8 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
447 case OMAP_DSS_VIDEO1: 471 case OMAP_DSS_VIDEO1:
448 case OMAP_DSS_VIDEO2: 472 case OMAP_DSS_VIDEO2:
449 return 0x0020; 473 return 0x0020;
474 case OMAP_DSS_VIDEO3:
475 return 0x0098;
450 default: 476 default:
451 BUG(); 477 BUG();
452 } 478 }
@@ -459,6 +485,7 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
459 return 0x0034; 485 return 0x0034;
460 case OMAP_DSS_VIDEO1: 486 case OMAP_DSS_VIDEO1:
461 case OMAP_DSS_VIDEO2: 487 case OMAP_DSS_VIDEO2:
488 case OMAP_DSS_VIDEO3:
462 BUG(); 489 BUG();
463 default: 490 default:
464 BUG(); 491 BUG();
@@ -472,6 +499,7 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
472 return 0x0038; 499 return 0x0038;
473 case OMAP_DSS_VIDEO1: 500 case OMAP_DSS_VIDEO1:
474 case OMAP_DSS_VIDEO2: 501 case OMAP_DSS_VIDEO2:
502 case OMAP_DSS_VIDEO3:
475 BUG(); 503 BUG();
476 default: 504 default:
477 BUG(); 505 BUG();
@@ -486,6 +514,8 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
486 case OMAP_DSS_VIDEO1: 514 case OMAP_DSS_VIDEO1:
487 case OMAP_DSS_VIDEO2: 515 case OMAP_DSS_VIDEO2:
488 return 0x0024; 516 return 0x0024;
517 case OMAP_DSS_VIDEO3:
518 return 0x0090;
489 default: 519 default:
490 BUG(); 520 BUG();
491 } 521 }
@@ -500,6 +530,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
500 return 0x0580; 530 return 0x0580;
501 case OMAP_DSS_VIDEO2: 531 case OMAP_DSS_VIDEO2:
502 return 0x055C; 532 return 0x055C;
533 case OMAP_DSS_VIDEO3:
534 return 0x0424;
503 default: 535 default:
504 BUG(); 536 BUG();
505 } 537 }
@@ -513,6 +545,8 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
513 case OMAP_DSS_VIDEO1: 545 case OMAP_DSS_VIDEO1:
514 case OMAP_DSS_VIDEO2: 546 case OMAP_DSS_VIDEO2:
515 return 0x0028; 547 return 0x0028;
548 case OMAP_DSS_VIDEO3:
549 return 0x0094;
516 default: 550 default:
517 BUG(); 551 BUG();
518 } 552 }
@@ -527,6 +561,8 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
527 case OMAP_DSS_VIDEO1: 561 case OMAP_DSS_VIDEO1:
528 case OMAP_DSS_VIDEO2: 562 case OMAP_DSS_VIDEO2:
529 return 0x002C; 563 return 0x002C;
564 case OMAP_DSS_VIDEO3:
565 return 0x0000;
530 default: 566 default:
531 BUG(); 567 BUG();
532 } 568 }
@@ -541,6 +577,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
541 return 0x0584; 577 return 0x0584;
542 case OMAP_DSS_VIDEO2: 578 case OMAP_DSS_VIDEO2:
543 return 0x0560; 579 return 0x0560;
580 case OMAP_DSS_VIDEO3:
581 return 0x0428;
544 default: 582 default:
545 BUG(); 583 BUG();
546 } 584 }
@@ -554,6 +592,8 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
554 case OMAP_DSS_VIDEO1: 592 case OMAP_DSS_VIDEO1:
555 case OMAP_DSS_VIDEO2: 593 case OMAP_DSS_VIDEO2:
556 return 0x0030; 594 return 0x0030;
595 case OMAP_DSS_VIDEO3:
596 return 0x0004;
557 default: 597 default:
558 BUG(); 598 BUG();
559 } 599 }
@@ -568,6 +608,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
568 return 0x0588; 608 return 0x0588;
569 case OMAP_DSS_VIDEO2: 609 case OMAP_DSS_VIDEO2:
570 return 0x0564; 610 return 0x0564;
611 case OMAP_DSS_VIDEO3:
612 return 0x042C;
571 default: 613 default:
572 BUG(); 614 BUG();
573 } 615 }
@@ -582,6 +624,8 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
582 case OMAP_DSS_VIDEO1: 624 case OMAP_DSS_VIDEO1:
583 case OMAP_DSS_VIDEO2: 625 case OMAP_DSS_VIDEO2:
584 return 0x0034 + i * 0x8; 626 return 0x0034 + i * 0x8;
627 case OMAP_DSS_VIDEO3:
628 return 0x0010 + i * 0x8;
585 default: 629 default:
586 BUG(); 630 BUG();
587 } 631 }
@@ -597,6 +641,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
597 return 0x058C + i * 0x8; 641 return 0x058C + i * 0x8;
598 case OMAP_DSS_VIDEO2: 642 case OMAP_DSS_VIDEO2:
599 return 0x0568 + i * 0x8; 643 return 0x0568 + i * 0x8;
644 case OMAP_DSS_VIDEO3:
645 return 0x0430 + i * 0x8;
600 default: 646 default:
601 BUG(); 647 BUG();
602 } 648 }
@@ -611,6 +657,8 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
611 case OMAP_DSS_VIDEO1: 657 case OMAP_DSS_VIDEO1:
612 case OMAP_DSS_VIDEO2: 658 case OMAP_DSS_VIDEO2:
613 return 0x0038 + i * 0x8; 659 return 0x0038 + i * 0x8;
660 case OMAP_DSS_VIDEO3:
661 return 0x0014 + i * 0x8;
614 default: 662 default:
615 BUG(); 663 BUG();
616 } 664 }
@@ -626,6 +674,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
626 return 0x0590 + i * 8; 674 return 0x0590 + i * 8;
627 case OMAP_DSS_VIDEO2: 675 case OMAP_DSS_VIDEO2:
628 return 0x056C + i * 0x8; 676 return 0x056C + i * 0x8;
677 case OMAP_DSS_VIDEO3:
678 return 0x0434 + i * 0x8;
629 default: 679 default:
630 BUG(); 680 BUG();
631 } 681 }
@@ -639,6 +689,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
639 BUG(); 689 BUG();
640 case OMAP_DSS_VIDEO1: 690 case OMAP_DSS_VIDEO1:
641 case OMAP_DSS_VIDEO2: 691 case OMAP_DSS_VIDEO2:
692 case OMAP_DSS_VIDEO3:
642 return 0x0074 + i * 0x4; 693 return 0x0074 + i * 0x4;
643 default: 694 default:
644 BUG(); 695 BUG();
@@ -655,6 +706,8 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
655 return 0x0124 + i * 0x4; 706 return 0x0124 + i * 0x4;
656 case OMAP_DSS_VIDEO2: 707 case OMAP_DSS_VIDEO2:
657 return 0x00B4 + i * 0x4; 708 return 0x00B4 + i * 0x4;
709 case OMAP_DSS_VIDEO3:
710 return 0x0050 + i * 0x4;
658 default: 711 default:
659 BUG(); 712 BUG();
660 } 713 }
@@ -670,6 +723,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
670 return 0x05CC + i * 0x4; 723 return 0x05CC + i * 0x4;
671 case OMAP_DSS_VIDEO2: 724 case OMAP_DSS_VIDEO2:
672 return 0x05A8 + i * 0x4; 725 return 0x05A8 + i * 0x4;
726 case OMAP_DSS_VIDEO3:
727 return 0x0470 + i * 0x4;
673 default: 728 default:
674 BUG(); 729 BUG();
675 } 730 }
@@ -684,6 +739,8 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
684 return 0x0174; 739 return 0x0174;
685 case OMAP_DSS_VIDEO2: 740 case OMAP_DSS_VIDEO2:
686 return 0x00E8; 741 return 0x00E8;
742 case OMAP_DSS_VIDEO3:
743 return 0x00A0;
687 default: 744 default:
688 BUG(); 745 BUG();
689 } 746 }
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 94495e45ec5..be331dc5a61 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -45,14 +45,13 @@ static ssize_t display_enabled_store(struct device *dev,
45 const char *buf, size_t size) 45 const char *buf, size_t size)
46{ 46{
47 struct omap_dss_device *dssdev = to_dss_device(dev); 47 struct omap_dss_device *dssdev = to_dss_device(dev);
48 int r, enabled; 48 int r;
49 bool enabled;
49 50
50 r = kstrtoint(buf, 0, &enabled); 51 r = strtobool(buf, &enabled);
51 if (r) 52 if (r)
52 return r; 53 return r;
53 54
54 enabled = !!enabled;
55
56 if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { 55 if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
57 if (enabled) { 56 if (enabled) {
58 r = dssdev->driver->enable(dssdev); 57 r = dssdev->driver->enable(dssdev);
@@ -79,17 +78,16 @@ static ssize_t display_tear_store(struct device *dev,
79 struct device_attribute *attr, const char *buf, size_t size) 78 struct device_attribute *attr, const char *buf, size_t size)
80{ 79{
81 struct omap_dss_device *dssdev = to_dss_device(dev); 80 struct omap_dss_device *dssdev = to_dss_device(dev);
82 int te, r; 81 int r;
82 bool te;
83 83
84 if (!dssdev->driver->enable_te || !dssdev->driver->get_te) 84 if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
85 return -ENOENT; 85 return -ENOENT;
86 86
87 r = kstrtoint(buf, 0, &te); 87 r = strtobool(buf, &te);
88 if (r) 88 if (r)
89 return r; 89 return r;
90 90
91 te = !!te;
92
93 r = dssdev->driver->enable_te(dssdev, te); 91 r = dssdev->driver->enable_te(dssdev, te);
94 if (r) 92 if (r)
95 return r; 93 return r;
@@ -195,17 +193,16 @@ static ssize_t display_mirror_store(struct device *dev,
195 struct device_attribute *attr, const char *buf, size_t size) 193 struct device_attribute *attr, const char *buf, size_t size)
196{ 194{
197 struct omap_dss_device *dssdev = to_dss_device(dev); 195 struct omap_dss_device *dssdev = to_dss_device(dev);
198 int mirror, r; 196 int r;
197 bool mirror;
199 198
200 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) 199 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
201 return -ENOENT; 200 return -ENOENT;
202 201
203 r = kstrtoint(buf, 0, &mirror); 202 r = strtobool(buf, &mirror);
204 if (r) 203 if (r)
205 return r; 204 return r;
206 205
207 mirror = !!mirror;
208
209 r = dssdev->driver->set_mirror(dssdev, mirror); 206 r = dssdev->driver->set_mirror(dssdev, mirror);
210 if (r) 207 if (r)
211 return r; 208 return r;
@@ -302,11 +299,15 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
302 return 16; 299 return 16;
303 300
304 case OMAP_DISPLAY_TYPE_DBI: 301 case OMAP_DISPLAY_TYPE_DBI:
305 case OMAP_DISPLAY_TYPE_DSI:
306 if (dssdev->ctrl.pixel_size == 24) 302 if (dssdev->ctrl.pixel_size == 24)
307 return 24; 303 return 24;
308 else 304 else
309 return 16; 305 return 16;
306 case OMAP_DISPLAY_TYPE_DSI:
307 if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16)
308 return 24;
309 else
310 return 16;
310 case OMAP_DISPLAY_TYPE_VENC: 311 case OMAP_DISPLAY_TYPE_VENC:
311 case OMAP_DISPLAY_TYPE_SDI: 312 case OMAP_DISPLAY_TYPE_SDI:
312 case OMAP_DISPLAY_TYPE_HDMI: 313 case OMAP_DISPLAY_TYPE_HDMI:
@@ -342,9 +343,11 @@ bool dss_use_replication(struct omap_dss_device *dssdev,
342 bpp = 24; 343 bpp = 24;
343 break; 344 break;
344 case OMAP_DISPLAY_TYPE_DBI: 345 case OMAP_DISPLAY_TYPE_DBI:
345 case OMAP_DISPLAY_TYPE_DSI:
346 bpp = dssdev->ctrl.pixel_size; 346 bpp = dssdev->ctrl.pixel_size;
347 break; 347 break;
348 case OMAP_DISPLAY_TYPE_DSI:
349 bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
350 break;
348 default: 351 default:
349 BUG(); 352 BUG();
350 } 353 }
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index f053b180ecd..483888a85cf 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -82,9 +82,11 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
82 82
83 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); 83 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
84 84
85 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); 85 r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
86 if (r) 86 if (r) {
87 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
87 return r; 88 return r;
89 }
88 90
89 *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; 91 *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
90 *lck_div = dispc_cinfo.lck_div; 92 *lck_div = dispc_cinfo.lck_div;
@@ -109,7 +111,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft,
109 if (r) 111 if (r)
110 return r; 112 return r;
111 113
112 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); 114 r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
113 if (r) 115 if (r)
114 return r; 116 return r;
115 117
@@ -129,7 +131,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
129 bool is_tft; 131 bool is_tft;
130 int r = 0; 132 int r = 0;
131 133
132 dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, 134 dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
133 dssdev->panel.acbi, dssdev->panel.acb); 135 dssdev->panel.acbi, dssdev->panel.acb);
134 136
135 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; 137 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
@@ -153,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
153 t->pixel_clock = pck; 155 t->pixel_clock = pck;
154 } 156 }
155 157
156 dispc_set_lcd_timings(dssdev->manager->id, t); 158 dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
157 159
158 return 0; 160 return 0;
159} 161}
@@ -164,11 +166,12 @@ static void dpi_basic_init(struct omap_dss_device *dssdev)
164 166
165 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; 167 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
166 168
167 dispc_set_parallel_interface_mode(dssdev->manager->id, 169 dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS);
168 OMAP_DSS_PARALLELMODE_BYPASS); 170 dispc_mgr_enable_stallmode(dssdev->manager->id, false);
169 dispc_set_lcd_display_type(dssdev->manager->id, is_tft ? 171
172 dispc_mgr_set_lcd_display_type(dssdev->manager->id, is_tft ?
170 OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); 173 OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
171 dispc_set_tft_data_lines(dssdev->manager->id, 174 dispc_mgr_set_tft_data_lines(dssdev->manager->id,
172 dssdev->phy.dpi.data_lines); 175 dssdev->phy.dpi.data_lines);
173} 176}
174 177
@@ -176,6 +179,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
176{ 179{
177 int r; 180 int r;
178 181
182 if (dssdev->manager == NULL) {
183 DSSERR("failed to enable display: no manager\n");
184 return -ENODEV;
185 }
186
179 r = omap_dss_start_device(dssdev); 187 r = omap_dss_start_device(dssdev);
180 if (r) { 188 if (r) {
181 DSSERR("failed to start device\n"); 189 DSSERR("failed to start device\n");
@@ -277,7 +285,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
277 } 285 }
278 286
279 dpi_set_mode(dssdev); 287 dpi_set_mode(dssdev);
280 dispc_go(dssdev->manager->id); 288 dispc_mgr_go(dssdev->manager->id);
281 289
282 dispc_runtime_put(); 290 dispc_runtime_put();
283 dss_runtime_put(); 291 dss_runtime_put();
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 7adbbeb8433..43c04a9889c 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -39,6 +39,7 @@
39#include <linux/pm_runtime.h> 39#include <linux/pm_runtime.h>
40 40
41#include <video/omapdss.h> 41#include <video/omapdss.h>
42#include <video/mipi_display.h>
42#include <plat/clock.h> 43#include <plat/clock.h>
43 44
44#include "dss.h" 45#include "dss.h"
@@ -131,7 +132,7 @@ struct dsi_reg { u16 idx; };
131#define DSI_IRQ_TA_TIMEOUT (1 << 20) 132#define DSI_IRQ_TA_TIMEOUT (1 << 20)
132#define DSI_IRQ_ERROR_MASK \ 133#define DSI_IRQ_ERROR_MASK \
133 (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ 134 (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
134 DSI_IRQ_TA_TIMEOUT) 135 DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST)
135#define DSI_IRQ_CHANNEL_MASK 0xf 136#define DSI_IRQ_CHANNEL_MASK 0xf
136 137
137/* Virtual channel interrupts */ 138/* Virtual channel interrupts */
@@ -198,18 +199,6 @@ struct dsi_reg { u16 idx; };
198 DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \ 199 DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \
199 DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5) 200 DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5)
200 201
201#define DSI_DT_DCS_SHORT_WRITE_0 0x05
202#define DSI_DT_DCS_SHORT_WRITE_1 0x15
203#define DSI_DT_DCS_READ 0x06
204#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
205#define DSI_DT_NULL_PACKET 0x09
206#define DSI_DT_DCS_LONG_WRITE 0x39
207
208#define DSI_DT_RX_ACK_WITH_ERR 0x02
209#define DSI_DT_RX_DCS_LONG_READ 0x1c
210#define DSI_DT_RX_SHORT_READ_1 0x21
211#define DSI_DT_RX_SHORT_READ_2 0x22
212
213typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); 202typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
214 203
215#define DSI_MAX_NR_ISRS 2 204#define DSI_MAX_NR_ISRS 2
@@ -228,9 +217,9 @@ enum fifo_size {
228 DSI_FIFO_SIZE_128 = 4, 217 DSI_FIFO_SIZE_128 = 4,
229}; 218};
230 219
231enum dsi_vc_mode { 220enum dsi_vc_source {
232 DSI_VC_MODE_L4 = 0, 221 DSI_VC_SOURCE_L4 = 0,
233 DSI_VC_MODE_VP, 222 DSI_VC_SOURCE_VP,
234}; 223};
235 224
236enum dsi_lane { 225enum dsi_lane {
@@ -274,7 +263,8 @@ struct dsi_data {
274 struct clk *dss_clk; 263 struct clk *dss_clk;
275 struct clk *sys_clk; 264 struct clk *sys_clk;
276 265
277 void (*dsi_mux_pads)(bool enable); 266 int (*enable_pads)(int dsi_id, unsigned lane_mask);
267 void (*disable_pads)(int dsi_id, unsigned lane_mask);
278 268
279 struct dsi_clock_info current_cinfo; 269 struct dsi_clock_info current_cinfo;
280 270
@@ -282,7 +272,7 @@ struct dsi_data {
282 struct regulator *vdds_dsi_reg; 272 struct regulator *vdds_dsi_reg;
283 273
284 struct { 274 struct {
285 enum dsi_vc_mode mode; 275 enum dsi_vc_source source;
286 struct omap_dss_device *dssdev; 276 struct omap_dss_device *dssdev;
287 enum fifo_size fifo_size; 277 enum fifo_size fifo_size;
288 int vc_id; 278 int vc_id;
@@ -368,14 +358,9 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
368 return dsi_pdev_map[module]; 358 return dsi_pdev_map[module];
369} 359}
370 360
371static int dsi_get_dsidev_id(struct platform_device *dsidev) 361static inline int dsi_get_dsidev_id(struct platform_device *dsidev)
372{ 362{
373 /* TEMP: Pass 0 as the dsi module index till the time the dsi platform 363 return dsidev->id;
374 * device names aren't changed to the form "omapdss_dsi.0",
375 * "omapdss_dsi.1" and so on */
376 BUG_ON(dsidev->id != -1);
377
378 return 0;
379} 364}
380 365
381static inline void dsi_write_reg(struct platform_device *dsidev, 366static inline void dsi_write_reg(struct platform_device *dsidev,
@@ -437,6 +422,21 @@ static inline int wait_for_bit_change(struct platform_device *dsidev,
437 return value; 422 return value;
438} 423}
439 424
425u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
426{
427 switch (fmt) {
428 case OMAP_DSS_DSI_FMT_RGB888:
429 case OMAP_DSS_DSI_FMT_RGB666:
430 return 24;
431 case OMAP_DSS_DSI_FMT_RGB666_PACKED:
432 return 18;
433 case OMAP_DSS_DSI_FMT_RGB565:
434 return 16;
435 default:
436 BUG();
437 }
438}
439
440#ifdef DEBUG 440#ifdef DEBUG
441static void dsi_perf_mark_setup(struct platform_device *dsidev) 441static void dsi_perf_mark_setup(struct platform_device *dsidev)
442{ 442{
@@ -453,6 +453,7 @@ static void dsi_perf_mark_start(struct platform_device *dsidev)
453static void dsi_perf_show(struct platform_device *dsidev, const char *name) 453static void dsi_perf_show(struct platform_device *dsidev, const char *name)
454{ 454{
455 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 455 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
456 struct omap_dss_device *dssdev = dsi->update_region.device;
456 ktime_t t, setup_time, trans_time; 457 ktime_t t, setup_time, trans_time;
457 u32 total_bytes; 458 u32 total_bytes;
458 u32 setup_us, trans_us, total_us; 459 u32 setup_us, trans_us, total_us;
@@ -476,7 +477,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
476 477
477 total_bytes = dsi->update_region.w * 478 total_bytes = dsi->update_region.w *
478 dsi->update_region.h * 479 dsi->update_region.h *
479 dsi->update_region.device->ctrl.pixel_size / 8; 480 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
480 481
481 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " 482 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
482 "%u bytes, %u kbytes/sec\n", 483 "%u bytes, %u kbytes/sec\n",
@@ -1287,7 +1288,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
1287 * with DSS_SYS_CLK source also */ 1288 * with DSS_SYS_CLK source also */
1288 cinfo->highfreq = 0; 1289 cinfo->highfreq = 0;
1289 } else { 1290 } else {
1290 cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); 1291 cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id);
1291 1292
1292 if (cinfo->clkin < 32000000) 1293 if (cinfo->clkin < 32000000)
1293 cinfo->highfreq = 0; 1294 cinfo->highfreq = 0;
@@ -2360,6 +2361,24 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
2360 return 0; 2361 return 0;
2361} 2362}
2362 2363
2364static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
2365{
2366 unsigned lanes = 0;
2367
2368 if (dssdev->phy.dsi.clk_lane != 0)
2369 lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1);
2370 if (dssdev->phy.dsi.data1_lane != 0)
2371 lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1);
2372 if (dssdev->phy.dsi.data2_lane != 0)
2373 lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1);
2374 if (dssdev->phy.dsi.data3_lane != 0)
2375 lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1);
2376 if (dssdev->phy.dsi.data4_lane != 0)
2377 lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1);
2378
2379 return lanes;
2380}
2381
2363static int dsi_cio_init(struct omap_dss_device *dssdev) 2382static int dsi_cio_init(struct omap_dss_device *dssdev)
2364{ 2383{
2365 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2384 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -2370,8 +2389,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2370 2389
2371 DSSDBGF(); 2390 DSSDBGF();
2372 2391
2373 if (dsi->dsi_mux_pads) 2392 r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
2374 dsi->dsi_mux_pads(true); 2393 if (r)
2394 return r;
2375 2395
2376 dsi_enable_scp_clk(dsidev); 2396 dsi_enable_scp_clk(dsidev);
2377 2397
@@ -2452,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2452 2472
2453 dsi_cio_timings(dsidev); 2473 dsi_cio_timings(dsidev);
2454 2474
2475 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
2476 /* DDR_CLK_ALWAYS_ON */
2477 REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
2478 dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13);
2479 }
2480
2455 dsi->ulps_enabled = false; 2481 dsi->ulps_enabled = false;
2456 2482
2457 DSSDBG("CIO init done\n"); 2483 DSSDBG("CIO init done\n");
@@ -2467,19 +2493,21 @@ err_cio_pwr:
2467 dsi_cio_disable_lane_override(dsidev); 2493 dsi_cio_disable_lane_override(dsidev);
2468err_scp_clk_dom: 2494err_scp_clk_dom:
2469 dsi_disable_scp_clk(dsidev); 2495 dsi_disable_scp_clk(dsidev);
2470 if (dsi->dsi_mux_pads) 2496 dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
2471 dsi->dsi_mux_pads(false);
2472 return r; 2497 return r;
2473} 2498}
2474 2499
2475static void dsi_cio_uninit(struct platform_device *dsidev) 2500static void dsi_cio_uninit(struct omap_dss_device *dssdev)
2476{ 2501{
2502 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2477 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2503 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2478 2504
2505 /* DDR_CLK_ALWAYS_ON */
2506 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
2507
2479 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); 2508 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
2480 dsi_disable_scp_clk(dsidev); 2509 dsi_disable_scp_clk(dsidev);
2481 if (dsi->dsi_mux_pads) 2510 dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
2482 dsi->dsi_mux_pads(false);
2483} 2511}
2484 2512
2485static void dsi_config_tx_fifo(struct platform_device *dsidev, 2513static void dsi_config_tx_fifo(struct platform_device *dsidev,
@@ -2669,10 +2697,10 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel)
2669 if (!dsi_vc_is_enabled(dsidev, channel)) 2697 if (!dsi_vc_is_enabled(dsidev, channel))
2670 return 0; 2698 return 0;
2671 2699
2672 switch (dsi->vc[channel].mode) { 2700 switch (dsi->vc[channel].source) {
2673 case DSI_VC_MODE_VP: 2701 case DSI_VC_SOURCE_VP:
2674 return dsi_sync_vc_vp(dsidev, channel); 2702 return dsi_sync_vc_vp(dsidev, channel);
2675 case DSI_VC_MODE_L4: 2703 case DSI_VC_SOURCE_L4:
2676 return dsi_sync_vc_l4(dsidev, channel); 2704 return dsi_sync_vc_l4(dsidev, channel);
2677 default: 2705 default:
2678 BUG(); 2706 BUG();
@@ -2726,43 +2754,12 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
2726 dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); 2754 dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);
2727} 2755}
2728 2756
2729static int dsi_vc_config_l4(struct platform_device *dsidev, int channel) 2757static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
2758 enum dsi_vc_source source)
2730{ 2759{
2731 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2760 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2732 2761
2733 if (dsi->vc[channel].mode == DSI_VC_MODE_L4) 2762 if (dsi->vc[channel].source == source)
2734 return 0;
2735
2736 DSSDBGF("%d", channel);
2737
2738 dsi_sync_vc(dsidev, channel);
2739
2740 dsi_vc_enable(dsidev, channel, 0);
2741
2742 /* VC_BUSY */
2743 if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) {
2744 DSSERR("vc(%d) busy when trying to config for L4\n", channel);
2745 return -EIO;
2746 }
2747
2748 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
2749
2750 /* DCS_CMD_ENABLE */
2751 if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
2752 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 30, 30);
2753
2754 dsi_vc_enable(dsidev, channel, 1);
2755
2756 dsi->vc[channel].mode = DSI_VC_MODE_L4;
2757
2758 return 0;
2759}
2760
2761static int dsi_vc_config_vp(struct platform_device *dsidev, int channel)
2762{
2763 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2764
2765 if (dsi->vc[channel].mode == DSI_VC_MODE_VP)
2766 return 0; 2763 return 0;
2767 2764
2768 DSSDBGF("%d", channel); 2765 DSSDBGF("%d", channel);
@@ -2777,21 +2774,22 @@ static int dsi_vc_config_vp(struct platform_device *dsidev, int channel)
2777 return -EIO; 2774 return -EIO;
2778 } 2775 }
2779 2776
2780 /* SOURCE, 1 = video port */ 2777 /* SOURCE, 0 = L4, 1 = video port */
2781 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 1, 1); 2778 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);
2782 2779
2783 /* DCS_CMD_ENABLE */ 2780 /* DCS_CMD_ENABLE */
2784 if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) 2781 if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
2785 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 30, 30); 2782 bool enable = source == DSI_VC_SOURCE_VP;
2783 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30);
2784 }
2786 2785
2787 dsi_vc_enable(dsidev, channel, 1); 2786 dsi_vc_enable(dsidev, channel, 1);
2788 2787
2789 dsi->vc[channel].mode = DSI_VC_MODE_VP; 2788 dsi->vc[channel].source = source;
2790 2789
2791 return 0; 2790 return 0;
2792} 2791}
2793 2792
2794
2795void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, 2793void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2796 bool enable) 2794 bool enable)
2797{ 2795{
@@ -2810,6 +2808,10 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2810 dsi_if_enable(dsidev, 1); 2808 dsi_if_enable(dsidev, 1);
2811 2809
2812 dsi_force_tx_stop_mode_io(dsidev); 2810 dsi_force_tx_stop_mode_io(dsidev);
2811
2812 /* start the DDR clock by sending a NULL packet */
2813 if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable)
2814 dsi_vc_send_null(dssdev, channel);
2813} 2815}
2814EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); 2816EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
2815 2817
@@ -2873,16 +2875,16 @@ static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev,
2873 val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); 2875 val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
2874 DSSERR("\trawval %#08x\n", val); 2876 DSSERR("\trawval %#08x\n", val);
2875 dt = FLD_GET(val, 5, 0); 2877 dt = FLD_GET(val, 5, 0);
2876 if (dt == DSI_DT_RX_ACK_WITH_ERR) { 2878 if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
2877 u16 err = FLD_GET(val, 23, 8); 2879 u16 err = FLD_GET(val, 23, 8);
2878 dsi_show_rx_ack_with_err(err); 2880 dsi_show_rx_ack_with_err(err);
2879 } else if (dt == DSI_DT_RX_SHORT_READ_1) { 2881 } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) {
2880 DSSERR("\tDCS short response, 1 byte: %#x\n", 2882 DSSERR("\tDCS short response, 1 byte: %#x\n",
2881 FLD_GET(val, 23, 8)); 2883 FLD_GET(val, 23, 8));
2882 } else if (dt == DSI_DT_RX_SHORT_READ_2) { 2884 } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {
2883 DSSERR("\tDCS short response, 2 byte: %#x\n", 2885 DSSERR("\tDCS short response, 2 byte: %#x\n",
2884 FLD_GET(val, 23, 8)); 2886 FLD_GET(val, 23, 8));
2885 } else if (dt == DSI_DT_RX_DCS_LONG_READ) { 2887 } else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
2886 DSSERR("\tDCS long response, len %d\n", 2888 DSSERR("\tDCS long response, len %d\n",
2887 FLD_GET(val, 23, 8)); 2889 FLD_GET(val, 23, 8));
2888 dsi_vc_flush_long_data(dsidev, channel); 2890 dsi_vc_flush_long_data(dsidev, channel);
@@ -3007,7 +3009,7 @@ static int dsi_vc_send_long(struct platform_device *dsidev, int channel,
3007 return -EINVAL; 3009 return -EINVAL;
3008 } 3010 }
3009 3011
3010 dsi_vc_config_l4(dsidev, channel); 3012 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
3011 3013
3012 dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc); 3014 dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc);
3013 3015
@@ -3066,7 +3068,7 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
3066 channel, 3068 channel,
3067 data_type, data & 0xff, (data >> 8) & 0xff); 3069 data_type, data & 0xff, (data >> 8) & 0xff);
3068 3070
3069 dsi_vc_config_l4(dsidev, channel); 3071 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
3070 3072
3071 if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) { 3073 if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) {
3072 DSSERR("ERROR FIFO FULL, aborting transfer\n"); 3074 DSSERR("ERROR FIFO FULL, aborting transfer\n");
@@ -3085,44 +3087,66 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
3085int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) 3087int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
3086{ 3088{
3087 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3089 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3088 u8 nullpkg[] = {0, 0, 0, 0};
3089 3090
3090 return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg, 3091 return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL,
3091 4, 0); 3092 0, 0);
3092} 3093}
3093EXPORT_SYMBOL(dsi_vc_send_null); 3094EXPORT_SYMBOL(dsi_vc_send_null);
3094 3095
3095int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, 3096static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev,
3096 u8 *data, int len) 3097 int channel, u8 *data, int len, enum dss_dsi_content_type type)
3097{ 3098{
3098 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3099 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3099 int r; 3100 int r;
3100 3101
3101 BUG_ON(len == 0); 3102 if (len == 0) {
3102 3103 BUG_ON(type == DSS_DSI_CONTENT_DCS);
3103 if (len == 1) { 3104 r = dsi_vc_send_short(dsidev, channel,
3104 r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0, 3105 MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0);
3105 data[0], 0); 3106 } else if (len == 1) {
3107 r = dsi_vc_send_short(dsidev, channel,
3108 type == DSS_DSI_CONTENT_GENERIC ?
3109 MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM :
3110 MIPI_DSI_DCS_SHORT_WRITE, data[0], 0);
3106 } else if (len == 2) { 3111 } else if (len == 2) {
3107 r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1, 3112 r = dsi_vc_send_short(dsidev, channel,
3113 type == DSS_DSI_CONTENT_GENERIC ?
3114 MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM :
3115 MIPI_DSI_DCS_SHORT_WRITE_PARAM,
3108 data[0] | (data[1] << 8), 0); 3116 data[0] | (data[1] << 8), 0);
3109 } else { 3117 } else {
3110 /* 0x39 = DCS Long Write */ 3118 r = dsi_vc_send_long(dsidev, channel,
3111 r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE, 3119 type == DSS_DSI_CONTENT_GENERIC ?
3112 data, len, 0); 3120 MIPI_DSI_GENERIC_LONG_WRITE :
3121 MIPI_DSI_DCS_LONG_WRITE, data, len, 0);
3113 } 3122 }
3114 3123
3115 return r; 3124 return r;
3116} 3125}
3126
3127int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
3128 u8 *data, int len)
3129{
3130 return dsi_vc_write_nosync_common(dssdev, channel, data, len,
3131 DSS_DSI_CONTENT_DCS);
3132}
3117EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); 3133EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
3118 3134
3119int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, 3135int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
3120 int len) 3136 u8 *data, int len)
3137{
3138 return dsi_vc_write_nosync_common(dssdev, channel, data, len,
3139 DSS_DSI_CONTENT_GENERIC);
3140}
3141EXPORT_SYMBOL(dsi_vc_generic_write_nosync);
3142
3143static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
3144 u8 *data, int len, enum dss_dsi_content_type type)
3121{ 3145{
3122 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3146 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3123 int r; 3147 int r;
3124 3148
3125 r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len); 3149 r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type);
3126 if (r) 3150 if (r)
3127 goto err; 3151 goto err;
3128 3152
@@ -3140,18 +3164,39 @@ int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
3140 3164
3141 return 0; 3165 return 0;
3142err: 3166err:
3143 DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n", 3167 DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n",
3144 channel, data[0], len); 3168 channel, data[0], len);
3145 return r; 3169 return r;
3146} 3170}
3171
3172int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
3173 int len)
3174{
3175 return dsi_vc_write_common(dssdev, channel, data, len,
3176 DSS_DSI_CONTENT_DCS);
3177}
3147EXPORT_SYMBOL(dsi_vc_dcs_write); 3178EXPORT_SYMBOL(dsi_vc_dcs_write);
3148 3179
3180int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
3181 int len)
3182{
3183 return dsi_vc_write_common(dssdev, channel, data, len,
3184 DSS_DSI_CONTENT_GENERIC);
3185}
3186EXPORT_SYMBOL(dsi_vc_generic_write);
3187
3149int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd) 3188int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd)
3150{ 3189{
3151 return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1); 3190 return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1);
3152} 3191}
3153EXPORT_SYMBOL(dsi_vc_dcs_write_0); 3192EXPORT_SYMBOL(dsi_vc_dcs_write_0);
3154 3193
3194int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel)
3195{
3196 return dsi_vc_generic_write(dssdev, channel, NULL, 0);
3197}
3198EXPORT_SYMBOL(dsi_vc_generic_write_0);
3199
3155int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, 3200int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3156 u8 param) 3201 u8 param)
3157{ 3202{
@@ -3162,25 +3207,87 @@ int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3162} 3207}
3163EXPORT_SYMBOL(dsi_vc_dcs_write_1); 3208EXPORT_SYMBOL(dsi_vc_dcs_write_1);
3164 3209
3165int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, 3210int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel,
3166 u8 *buf, int buflen) 3211 u8 param)
3212{
3213 return dsi_vc_generic_write(dssdev, channel, &param, 1);
3214}
3215EXPORT_SYMBOL(dsi_vc_generic_write_1);
3216
3217int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
3218 u8 param1, u8 param2)
3219{
3220 u8 buf[2];
3221 buf[0] = param1;
3222 buf[1] = param2;
3223 return dsi_vc_generic_write(dssdev, channel, buf, 2);
3224}
3225EXPORT_SYMBOL(dsi_vc_generic_write_2);
3226
3227static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev,
3228 int channel, u8 dcs_cmd)
3167{ 3229{
3168 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3230 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3169 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3231 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3170 u32 val;
3171 u8 dt;
3172 int r; 3232 int r;
3173 3233
3174 if (dsi->debug_read) 3234 if (dsi->debug_read)
3175 DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); 3235 DSSDBG("dsi_vc_dcs_send_read_request(ch%d, dcs_cmd %x)\n",
3236 channel, dcs_cmd);
3176 3237
3177 r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0); 3238 r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0);
3178 if (r) 3239 if (r) {
3179 goto err; 3240 DSSERR("dsi_vc_dcs_send_read_request(ch %d, cmd 0x%02x)"
3241 " failed\n", channel, dcs_cmd);
3242 return r;
3243 }
3180 3244
3181 r = dsi_vc_send_bta_sync(dssdev, channel); 3245 return 0;
3182 if (r) 3246}
3183 goto err; 3247
3248static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev,
3249 int channel, u8 *reqdata, int reqlen)
3250{
3251 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3252 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3253 u16 data;
3254 u8 data_type;
3255 int r;
3256
3257 if (dsi->debug_read)
3258 DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n",
3259 channel, reqlen);
3260
3261 if (reqlen == 0) {
3262 data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
3263 data = 0;
3264 } else if (reqlen == 1) {
3265 data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
3266 data = reqdata[0];
3267 } else if (reqlen == 2) {
3268 data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
3269 data = reqdata[0] | (reqdata[1] << 8);
3270 } else {
3271 BUG();
3272 }
3273
3274 r = dsi_vc_send_short(dsidev, channel, data_type, data, 0);
3275 if (r) {
3276 DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)"
3277 " failed\n", channel, reqlen);
3278 return r;
3279 }
3280
3281 return 0;
3282}
3283
3284static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
3285 u8 *buf, int buflen, enum dss_dsi_content_type type)
3286{
3287 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3288 u32 val;
3289 u8 dt;
3290 int r;
3184 3291
3185 /* RX_FIFO_NOT_EMPTY */ 3292 /* RX_FIFO_NOT_EMPTY */
3186 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) { 3293 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) {
@@ -3193,16 +3300,20 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3193 if (dsi->debug_read) 3300 if (dsi->debug_read)
3194 DSSDBG("\theader: %08x\n", val); 3301 DSSDBG("\theader: %08x\n", val);
3195 dt = FLD_GET(val, 5, 0); 3302 dt = FLD_GET(val, 5, 0);
3196 if (dt == DSI_DT_RX_ACK_WITH_ERR) { 3303 if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
3197 u16 err = FLD_GET(val, 23, 8); 3304 u16 err = FLD_GET(val, 23, 8);
3198 dsi_show_rx_ack_with_err(err); 3305 dsi_show_rx_ack_with_err(err);
3199 r = -EIO; 3306 r = -EIO;
3200 goto err; 3307 goto err;
3201 3308
3202 } else if (dt == DSI_DT_RX_SHORT_READ_1) { 3309 } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
3310 MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE :
3311 MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) {
3203 u8 data = FLD_GET(val, 15, 8); 3312 u8 data = FLD_GET(val, 15, 8);
3204 if (dsi->debug_read) 3313 if (dsi->debug_read)
3205 DSSDBG("\tDCS short response, 1 byte: %02x\n", data); 3314 DSSDBG("\t%s short response, 1 byte: %02x\n",
3315 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
3316 "DCS", data);
3206 3317
3207 if (buflen < 1) { 3318 if (buflen < 1) {
3208 r = -EIO; 3319 r = -EIO;
@@ -3212,10 +3323,14 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3212 buf[0] = data; 3323 buf[0] = data;
3213 3324
3214 return 1; 3325 return 1;
3215 } else if (dt == DSI_DT_RX_SHORT_READ_2) { 3326 } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
3327 MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE :
3328 MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) {
3216 u16 data = FLD_GET(val, 23, 8); 3329 u16 data = FLD_GET(val, 23, 8);
3217 if (dsi->debug_read) 3330 if (dsi->debug_read)
3218 DSSDBG("\tDCS short response, 2 byte: %04x\n", data); 3331 DSSDBG("\t%s short response, 2 byte: %04x\n",
3332 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
3333 "DCS", data);
3219 3334
3220 if (buflen < 2) { 3335 if (buflen < 2) {
3221 r = -EIO; 3336 r = -EIO;
@@ -3226,11 +3341,15 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3226 buf[1] = (data >> 8) & 0xff; 3341 buf[1] = (data >> 8) & 0xff;
3227 3342
3228 return 2; 3343 return 2;
3229 } else if (dt == DSI_DT_RX_DCS_LONG_READ) { 3344 } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
3345 MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE :
3346 MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) {
3230 int w; 3347 int w;
3231 int len = FLD_GET(val, 23, 8); 3348 int len = FLD_GET(val, 23, 8);
3232 if (dsi->debug_read) 3349 if (dsi->debug_read)
3233 DSSDBG("\tDCS long response, len %d\n", len); 3350 DSSDBG("\t%s long response, len %d\n",
3351 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
3352 "DCS", len);
3234 3353
3235 if (len > buflen) { 3354 if (len > buflen) {
3236 r = -EIO; 3355 r = -EIO;
@@ -3266,58 +3385,126 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3266 3385
3267 BUG(); 3386 BUG();
3268err: 3387err:
3269 DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", 3388 DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel,
3270 channel, dcs_cmd); 3389 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS");
3390
3271 return r; 3391 return r;
3392}
3272 3393
3394int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3395 u8 *buf, int buflen)
3396{
3397 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3398 int r;
3399
3400 r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd);
3401 if (r)
3402 goto err;
3403
3404 r = dsi_vc_send_bta_sync(dssdev, channel);
3405 if (r)
3406 goto err;
3407
3408 r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
3409 DSS_DSI_CONTENT_DCS);
3410 if (r < 0)
3411 goto err;
3412
3413 if (r != buflen) {
3414 r = -EIO;
3415 goto err;
3416 }
3417
3418 return 0;
3419err:
3420 DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd);
3421 return r;
3273} 3422}
3274EXPORT_SYMBOL(dsi_vc_dcs_read); 3423EXPORT_SYMBOL(dsi_vc_dcs_read);
3275 3424
3276int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, 3425static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
3277 u8 *data) 3426 u8 *reqdata, int reqlen, u8 *buf, int buflen)
3278{ 3427{
3428 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3279 int r; 3429 int r;
3280 3430
3281 r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1); 3431 r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen);
3432 if (r)
3433 return r;
3434
3435 r = dsi_vc_send_bta_sync(dssdev, channel);
3436 if (r)
3437 return r;
3282 3438
3439 r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
3440 DSS_DSI_CONTENT_GENERIC);
3283 if (r < 0) 3441 if (r < 0)
3284 return r; 3442 return r;
3285 3443
3286 if (r != 1) 3444 if (r != buflen) {
3287 return -EIO; 3445 r = -EIO;
3446 return r;
3447 }
3288 3448
3289 return 0; 3449 return 0;
3290} 3450}
3291EXPORT_SYMBOL(dsi_vc_dcs_read_1);
3292 3451
3293int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, 3452int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf,
3294 u8 *data1, u8 *data2) 3453 int buflen)
3295{ 3454{
3296 u8 buf[2];
3297 int r; 3455 int r;
3298 3456
3299 r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2); 3457 r = dsi_vc_generic_read(dssdev, channel, NULL, 0, buf, buflen);
3458 if (r) {
3459 DSSERR("dsi_vc_generic_read_0(ch %d) failed\n", channel);
3460 return r;
3461 }
3300 3462
3301 if (r < 0) 3463 return 0;
3464}
3465EXPORT_SYMBOL(dsi_vc_generic_read_0);
3466
3467int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param,
3468 u8 *buf, int buflen)
3469{
3470 int r;
3471
3472 r = dsi_vc_generic_read(dssdev, channel, &param, 1, buf, buflen);
3473 if (r) {
3474 DSSERR("dsi_vc_generic_read_1(ch %d) failed\n", channel);
3302 return r; 3475 return r;
3476 }
3303 3477
3304 if (r != 2) 3478 return 0;
3305 return -EIO; 3479}
3480EXPORT_SYMBOL(dsi_vc_generic_read_1);
3306 3481
3307 *data1 = buf[0]; 3482int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel,
3308 *data2 = buf[1]; 3483 u8 param1, u8 param2, u8 *buf, int buflen)
3484{
3485 int r;
3486 u8 reqdata[2];
3487
3488 reqdata[0] = param1;
3489 reqdata[1] = param2;
3490
3491 r = dsi_vc_generic_read(dssdev, channel, reqdata, 2, buf, buflen);
3492 if (r) {
3493 DSSERR("dsi_vc_generic_read_2(ch %d) failed\n", channel);
3494 return r;
3495 }
3309 3496
3310 return 0; 3497 return 0;
3311} 3498}
3312EXPORT_SYMBOL(dsi_vc_dcs_read_2); 3499EXPORT_SYMBOL(dsi_vc_generic_read_2);
3313 3500
3314int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, 3501int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
3315 u16 len) 3502 u16 len)
3316{ 3503{
3317 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3504 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3318 3505
3319 return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE, 3506 return dsi_vc_send_short(dsidev, channel,
3320 len, 0); 3507 MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
3321} 3508}
3322EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); 3509EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
3323 3510
@@ -3508,6 +3695,75 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
3508 ticks, x4 ? " x4" : "", x16 ? " x16" : "", 3695 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
3509 (total_ticks * 1000) / (fck / 1000 / 1000)); 3696 (total_ticks * 1000) / (fck / 1000 / 1000));
3510} 3697}
3698
3699static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
3700{
3701 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3702 int num_line_buffers;
3703
3704 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
3705 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
3706 unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
3707 struct omap_video_timings *timings = &dssdev->panel.timings;
3708 /*
3709 * Don't use line buffers if width is greater than the video
3710 * port's line buffer size
3711 */
3712 if (line_buf_size <= timings->x_res * bpp / 8)
3713 num_line_buffers = 0;
3714 else
3715 num_line_buffers = 2;
3716 } else {
3717 /* Use maximum number of line buffers in command mode */
3718 num_line_buffers = 2;
3719 }
3720
3721 /* LINE_BUFFER */
3722 REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
3723}
3724
3725static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
3726{
3727 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3728 int de_pol = dssdev->panel.dsi_vm_data.vp_de_pol;
3729 int hsync_pol = dssdev->panel.dsi_vm_data.vp_hsync_pol;
3730 int vsync_pol = dssdev->panel.dsi_vm_data.vp_vsync_pol;
3731 bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end;
3732 bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
3733 u32 r;
3734
3735 r = dsi_read_reg(dsidev, DSI_CTRL);
3736 r = FLD_MOD(r, de_pol, 9, 9); /* VP_DE_POL */
3737 r = FLD_MOD(r, hsync_pol, 10, 10); /* VP_HSYNC_POL */
3738 r = FLD_MOD(r, vsync_pol, 11, 11); /* VP_VSYNC_POL */
3739 r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */
3740 r = FLD_MOD(r, vsync_end, 16, 16); /* VP_VSYNC_END */
3741 r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */
3742 r = FLD_MOD(r, hsync_end, 18, 18); /* VP_HSYNC_END */
3743 dsi_write_reg(dsidev, DSI_CTRL, r);
3744}
3745
3746static void dsi_config_blanking_modes(struct omap_dss_device *dssdev)
3747{
3748 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3749 int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode;
3750 int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode;
3751 int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode;
3752 int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode;
3753 u32 r;
3754
3755 /*
3756 * 0 = TX FIFO packets sent or LPS in corresponding blanking periods
3757 * 1 = Long blanking packets are sent in corresponding blanking periods
3758 */
3759 r = dsi_read_reg(dsidev, DSI_CTRL);
3760 r = FLD_MOD(r, blanking_mode, 20, 20); /* BLANKING_MODE */
3761 r = FLD_MOD(r, hfp_blanking_mode, 21, 21); /* HFP_BLANKING */
3762 r = FLD_MOD(r, hbp_blanking_mode, 22, 22); /* HBP_BLANKING */
3763 r = FLD_MOD(r, hsa_blanking_mode, 23, 23); /* HSA_BLANKING */
3764 dsi_write_reg(dsidev, DSI_CTRL, r);
3765}
3766
3511static int dsi_proto_config(struct omap_dss_device *dssdev) 3767static int dsi_proto_config(struct omap_dss_device *dssdev)
3512{ 3768{
3513 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3769 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3530,7 +3786,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3530 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); 3786 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
3531 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); 3787 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
3532 3788
3533 switch (dssdev->ctrl.pixel_size) { 3789 switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) {
3534 case 16: 3790 case 16:
3535 buswidth = 0; 3791 buswidth = 0;
3536 break; 3792 break;
@@ -3551,7 +3807,6 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3551 r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/ 3807 r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/
3552 r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ 3808 r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
3553 r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ 3809 r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
3554 r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
3555 r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ 3810 r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
3556 r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ 3811 r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
3557 if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { 3812 if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
@@ -3562,6 +3817,13 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3562 3817
3563 dsi_write_reg(dsidev, DSI_CTRL, r); 3818 dsi_write_reg(dsidev, DSI_CTRL, r);
3564 3819
3820 dsi_config_vp_num_line_buffers(dssdev);
3821
3822 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
3823 dsi_config_vp_sync_events(dssdev);
3824 dsi_config_blanking_modes(dssdev);
3825 }
3826
3565 dsi_vc_initial_config(dsidev, 0); 3827 dsi_vc_initial_config(dsidev, 0);
3566 dsi_vc_initial_config(dsidev, 1); 3828 dsi_vc_initial_config(dsidev, 1);
3567 dsi_vc_initial_config(dsidev, 2); 3829 dsi_vc_initial_config(dsidev, 2);
@@ -3580,6 +3842,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3580 unsigned ddr_clk_pre, ddr_clk_post; 3842 unsigned ddr_clk_pre, ddr_clk_post;
3581 unsigned enter_hs_mode_lat, exit_hs_mode_lat; 3843 unsigned enter_hs_mode_lat, exit_hs_mode_lat;
3582 unsigned ths_eot; 3844 unsigned ths_eot;
3845 int ndl = dsi_get_num_data_lanes_dssdev(dssdev);
3583 u32 r; 3846 u32 r;
3584 3847
3585 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); 3848 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
@@ -3602,7 +3865,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3602 /* min 60ns + 52*UI */ 3865 /* min 60ns + 52*UI */
3603 tclk_post = ns2ddr(dsidev, 60) + 26; 3866 tclk_post = ns2ddr(dsidev, 60) + 26;
3604 3867
3605 ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev)); 3868 ths_eot = DIV_ROUND_UP(4, ndl);
3606 3869
3607 ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, 3870 ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
3608 4); 3871 4);
@@ -3632,162 +3895,114 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3632 3895
3633 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", 3896 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
3634 enter_hs_mode_lat, exit_hs_mode_lat); 3897 enter_hs_mode_lat, exit_hs_mode_lat);
3635}
3636
3637
3638#define DSI_DECL_VARS \
3639 int __dsi_cb = 0; u32 __dsi_cv = 0;
3640 3898
3641#define DSI_FLUSH(dsidev, ch) \ 3899 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
3642 if (__dsi_cb > 0) { \ 3900 /* TODO: Implement a video mode check_timings function */
3643 /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ 3901 int hsa = dssdev->panel.dsi_vm_data.hsa;
3644 dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ 3902 int hfp = dssdev->panel.dsi_vm_data.hfp;
3645 __dsi_cb = __dsi_cv = 0; \ 3903 int hbp = dssdev->panel.dsi_vm_data.hbp;
3904 int vsa = dssdev->panel.dsi_vm_data.vsa;
3905 int vfp = dssdev->panel.dsi_vm_data.vfp;
3906 int vbp = dssdev->panel.dsi_vm_data.vbp;
3907 int window_sync = dssdev->panel.dsi_vm_data.window_sync;
3908 bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
3909 struct omap_video_timings *timings = &dssdev->panel.timings;
3910 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
3911 int tl, t_he, width_bytes;
3912
3913 t_he = hsync_end ?
3914 ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
3915
3916 width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
3917
3918 /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */
3919 tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp +
3920 DIV_ROUND_UP(width_bytes + 6, ndl) + hbp;
3921
3922 DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp,
3923 hfp, hsync_end ? hsa : 0, tl);
3924 DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp,
3925 vsa, timings->y_res);
3926
3927 r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
3928 r = FLD_MOD(r, hbp, 11, 0); /* HBP */
3929 r = FLD_MOD(r, hfp, 23, 12); /* HFP */
3930 r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24); /* HSA */
3931 dsi_write_reg(dsidev, DSI_VM_TIMING1, r);
3932
3933 r = dsi_read_reg(dsidev, DSI_VM_TIMING2);
3934 r = FLD_MOD(r, vbp, 7, 0); /* VBP */
3935 r = FLD_MOD(r, vfp, 15, 8); /* VFP */
3936 r = FLD_MOD(r, vsa, 23, 16); /* VSA */
3937 r = FLD_MOD(r, window_sync, 27, 24); /* WINDOW_SYNC */
3938 dsi_write_reg(dsidev, DSI_VM_TIMING2, r);
3939
3940 r = dsi_read_reg(dsidev, DSI_VM_TIMING3);
3941 r = FLD_MOD(r, timings->y_res, 14, 0); /* VACT */
3942 r = FLD_MOD(r, tl, 31, 16); /* TL */
3943 dsi_write_reg(dsidev, DSI_VM_TIMING3, r);
3646 } 3944 }
3945}
3647 3946
3648#define DSI_PUSH(dsidev, ch, data) \ 3947int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel)
3649 do { \
3650 __dsi_cv |= (data) << (__dsi_cb * 8); \
3651 /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
3652 if (++__dsi_cb > 3) \
3653 DSI_FLUSH(dsidev, ch); \
3654 } while (0)
3655
3656static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
3657 int x, int y, int w, int h)
3658{ 3948{
3659 /* Note: supports only 24bit colors in 32bit container */
3660 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3949 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3661 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3950 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
3662 int first = 1; 3951 u8 data_type;
3663 int fifo_stalls = 0; 3952 u16 word_count;
3664 int max_dsi_packet_size;
3665 int max_data_per_packet;
3666 int max_pixels_per_packet;
3667 int pixels_left;
3668 int bytespp = dssdev->ctrl.pixel_size / 8;
3669 int scr_width;
3670 u32 __iomem *data;
3671 int start_offset;
3672 int horiz_inc;
3673 int current_x;
3674 struct omap_overlay *ovl;
3675
3676 debug_irq = 0;
3677
3678 DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
3679 x, y, w, h);
3680 3953
3681 ovl = dssdev->manager->overlays[0]; 3954 switch (dssdev->panel.dsi_pix_fmt) {
3682 3955 case OMAP_DSS_DSI_FMT_RGB888:
3683 if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U) 3956 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
3684 return -EINVAL; 3957 break;
3685 3958 case OMAP_DSS_DSI_FMT_RGB666:
3686 if (dssdev->ctrl.pixel_size != 24) 3959 data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
3687 return -EINVAL; 3960 break;
3688 3961 case OMAP_DSS_DSI_FMT_RGB666_PACKED:
3689 scr_width = ovl->info.screen_width; 3962 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
3690 data = ovl->info.vaddr; 3963 break;
3691 3964 case OMAP_DSS_DSI_FMT_RGB565:
3692 start_offset = scr_width * y + x; 3965 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
3693 horiz_inc = scr_width - w; 3966 break;
3694 current_x = x; 3967 default:
3695 3968 BUG();
3696 /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes 3969 };
3697 * in fifo */
3698
3699 /* When using CPU, max long packet size is TX buffer size */
3700 max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4;
3701
3702 /* we seem to get better perf if we divide the tx fifo to half,
3703 and while the other half is being sent, we fill the other half
3704 max_dsi_packet_size /= 2; */
3705
3706 max_data_per_packet = max_dsi_packet_size - 4 - 1;
3707
3708 max_pixels_per_packet = max_data_per_packet / bytespp;
3709
3710 DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
3711
3712 pixels_left = w * h;
3713 3970
3714 DSSDBG("total pixels %d\n", pixels_left); 3971 dsi_if_enable(dsidev, false);
3972 dsi_vc_enable(dsidev, channel, false);
3715 3973
3716 data += start_offset; 3974 /* MODE, 1 = video mode */
3975 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
3717 3976
3718 while (pixels_left > 0) { 3977 word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
3719 /* 0x2c = write_memory_start */
3720 /* 0x3c = write_memory_continue */
3721 u8 dcs_cmd = first ? 0x2c : 0x3c;
3722 int pixels;
3723 DSI_DECL_VARS;
3724 first = 0;
3725 3978
3726#if 1 3979 dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0);
3727 /* using fifo not empty */
3728 /* TX_FIFO_NOT_EMPTY */
3729 while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) {
3730 fifo_stalls++;
3731 if (fifo_stalls > 0xfffff) {
3732 DSSERR("fifo stalls overflow, pixels left %d\n",
3733 pixels_left);
3734 dsi_if_enable(dsidev, 0);
3735 return -EIO;
3736 }
3737 udelay(1);
3738 }
3739#elif 1
3740 /* using fifo emptiness */
3741 while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
3742 max_dsi_packet_size) {
3743 fifo_stalls++;
3744 if (fifo_stalls > 0xfffff) {
3745 DSSERR("fifo stalls overflow, pixels left %d\n",
3746 pixels_left);
3747 dsi_if_enable(dsidev, 0);
3748 return -EIO;
3749 }
3750 }
3751#else
3752 while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS,
3753 7, 0) + 1) * 4 == 0) {
3754 fifo_stalls++;
3755 if (fifo_stalls > 0xfffff) {
3756 DSSERR("fifo stalls overflow, pixels left %d\n",
3757 pixels_left);
3758 dsi_if_enable(dsidev, 0);
3759 return -EIO;
3760 }
3761 }
3762#endif
3763 pixels = min(max_pixels_per_packet, pixels_left);
3764 3980
3765 pixels_left -= pixels; 3981 dsi_vc_enable(dsidev, channel, true);
3982 dsi_if_enable(dsidev, true);
3766 3983
3767 dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE, 3984 dssdev->manager->enable(dssdev->manager);
3768 1 + pixels * bytespp, 0);
3769 3985
3770 DSI_PUSH(dsidev, 0, dcs_cmd); 3986 return 0;
3987}
3988EXPORT_SYMBOL(dsi_video_mode_enable);
3771 3989
3772 while (pixels-- > 0) { 3990void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel)
3773 u32 pix = __raw_readl(data++); 3991{
3992 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3774 3993
3775 DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff); 3994 dsi_if_enable(dsidev, false);
3776 DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff); 3995 dsi_vc_enable(dsidev, channel, false);
3777 DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff);
3778 3996
3779 current_x++; 3997 /* MODE, 0 = command mode */
3780 if (current_x == x+w) { 3998 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
3781 current_x = x;
3782 data += horiz_inc;
3783 }
3784 }
3785 3999
3786 DSI_FLUSH(dsidev, 0); 4000 dsi_vc_enable(dsidev, channel, true);
3787 } 4001 dsi_if_enable(dsidev, true);
3788 4002
3789 return 0; 4003 dssdev->manager->disable(dssdev->manager);
3790} 4004}
4005EXPORT_SYMBOL(dsi_video_mode_disable);
3791 4006
3792static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, 4007static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
3793 u16 x, u16 y, u16 w, u16 h) 4008 u16 x, u16 y, u16 w, u16 h)
@@ -3808,9 +4023,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
3808 DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", 4023 DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
3809 x, y, w, h); 4024 x, y, w, h);
3810 4025
3811 dsi_vc_config_vp(dsidev, channel); 4026 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
3812 4027
3813 bytespp = dssdev->ctrl.pixel_size / 8; 4028 bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
3814 bytespl = w * bytespp; 4029 bytespl = w * bytespp;
3815 bytespf = bytespl * h; 4030 bytespf = bytespl * h;
3816 4031
@@ -3831,7 +4046,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
3831 l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ 4046 l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
3832 dsi_write_reg(dsidev, DSI_VC_TE(channel), l); 4047 dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
3833 4048
3834 dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE, 4049 dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE,
3835 packet_len, 0); 4050 packet_len, 0);
3836 4051
3837 if (dsi->te_enabled) 4052 if (dsi->te_enabled)
@@ -3956,11 +4171,9 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
3956 4171
3957 dsi_perf_mark_setup(dsidev); 4172 dsi_perf_mark_setup(dsidev);
3958 4173
3959 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 4174 dss_setup_partial_planes(dssdev, x, y, w, h,
3960 dss_setup_partial_planes(dssdev, x, y, w, h, 4175 enlarge_update_area);
3961 enlarge_update_area); 4176 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
3962 dispc_set_lcd_size(dssdev->manager->id, *w, *h);
3963 }
3964 4177
3965 return 0; 4178 return 0;
3966} 4179}
@@ -3982,27 +4195,16 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
3982 * see rather obscure HW error happening, as DSS halts. */ 4195 * see rather obscure HW error happening, as DSS halts. */
3983 BUG_ON(x % 2 == 1); 4196 BUG_ON(x % 2 == 1);
3984 4197
3985 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 4198 dsi->framedone_callback = callback;
3986 dsi->framedone_callback = callback; 4199 dsi->framedone_data = data;
3987 dsi->framedone_data = data;
3988
3989 dsi->update_region.x = x;
3990 dsi->update_region.y = y;
3991 dsi->update_region.w = w;
3992 dsi->update_region.h = h;
3993 dsi->update_region.device = dssdev;
3994
3995 dsi_update_screen_dispc(dssdev, x, y, w, h);
3996 } else {
3997 int r;
3998 4200
3999 r = dsi_update_screen_l4(dssdev, x, y, w, h); 4201 dsi->update_region.x = x;
4000 if (r) 4202 dsi->update_region.y = y;
4001 return r; 4203 dsi->update_region.w = w;
4204 dsi->update_region.h = h;
4205 dsi->update_region.device = dssdev;
4002 4206
4003 dsi_perf_show(dsidev, "L4"); 4207 dsi_update_screen_dispc(dssdev, x, y, w, h);
4004 callback(0, data);
4005 }
4006 4208
4007 return 0; 4209 return 0;
4008} 4210}
@@ -4013,28 +4215,9 @@ EXPORT_SYMBOL(omap_dsi_update);
4013static int dsi_display_init_dispc(struct omap_dss_device *dssdev) 4215static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4014{ 4216{
4015 int r; 4217 int r;
4016 u32 irq;
4017
4018 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
4019 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
4020 4218
4021 r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev, 4219 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
4022 irq); 4220 u32 irq;
4023 if (r) {
4024 DSSERR("can't get FRAMEDONE irq\n");
4025 return r;
4026 }
4027
4028 dispc_set_lcd_display_type(dssdev->manager->id,
4029 OMAP_DSS_LCD_DISPLAY_TFT);
4030
4031 dispc_set_parallel_interface_mode(dssdev->manager->id,
4032 OMAP_DSS_PARALLELMODE_DSI);
4033 dispc_enable_fifohandcheck(dssdev->manager->id, 1);
4034
4035 dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
4036
4037 {
4038 struct omap_video_timings timings = { 4221 struct omap_video_timings timings = {
4039 .hsw = 1, 4222 .hsw = 1,
4040 .hfp = 1, 4223 .hfp = 1,
@@ -4044,21 +4227,46 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4044 .vbp = 0, 4227 .vbp = 0,
4045 }; 4228 };
4046 4229
4047 dispc_set_lcd_timings(dssdev->manager->id, &timings); 4230 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
4231 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
4232
4233 r = omap_dispc_register_isr(dsi_framedone_irq_callback,
4234 (void *) dssdev, irq);
4235 if (r) {
4236 DSSERR("can't get FRAMEDONE irq\n");
4237 return r;
4238 }
4239
4240 dispc_mgr_enable_stallmode(dssdev->manager->id, true);
4241 dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1);
4242
4243 dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings);
4244 } else {
4245 dispc_mgr_enable_stallmode(dssdev->manager->id, false);
4246 dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0);
4247
4248 dispc_mgr_set_lcd_timings(dssdev->manager->id,
4249 &dssdev->panel.timings);
4048 } 4250 }
4049 4251
4252 dispc_mgr_set_lcd_display_type(dssdev->manager->id,
4253 OMAP_DSS_LCD_DISPLAY_TFT);
4254 dispc_mgr_set_tft_data_lines(dssdev->manager->id,
4255 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt));
4050 return 0; 4256 return 0;
4051} 4257}
4052 4258
4053static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) 4259static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
4054{ 4260{
4055 u32 irq; 4261 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
4262 u32 irq;
4056 4263
4057 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? 4264 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
4058 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; 4265 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
4059 4266
4060 omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev, 4267 omap_dispc_unregister_isr(dsi_framedone_irq_callback,
4061 irq); 4268 (void *) dssdev, irq);
4269 }
4062} 4270}
4063 4271
4064static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) 4272static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
@@ -4106,7 +4314,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
4106 return r; 4314 return r;
4107 } 4315 }
4108 4316
4109 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); 4317 r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
4110 if (r) { 4318 if (r) {
4111 DSSERR("Failed to set dispc clocks\n"); 4319 DSSERR("Failed to set dispc clocks\n");
4112 return r; 4320 return r;
@@ -4166,10 +4374,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4166 4374
4167 return 0; 4375 return 0;
4168err3: 4376err3:
4169 dsi_cio_uninit(dsidev); 4377 dsi_cio_uninit(dssdev);
4170err2: 4378err2:
4171 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 4379 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4172 dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); 4380 dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
4381 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
4382
4173err1: 4383err1:
4174 dsi_pll_uninit(dsidev, true); 4384 dsi_pll_uninit(dsidev, true);
4175err0: 4385err0:
@@ -4195,7 +4405,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4195 4405
4196 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 4406 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4197 dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); 4407 dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
4198 dsi_cio_uninit(dsidev); 4408 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
4409 dsi_cio_uninit(dssdev);
4199 dsi_pll_uninit(dsidev, disconnect_lanes); 4410 dsi_pll_uninit(dsidev, disconnect_lanes);
4200} 4411}
4201 4412
@@ -4211,6 +4422,12 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4211 4422
4212 mutex_lock(&dsi->lock); 4423 mutex_lock(&dsi->lock);
4213 4424
4425 if (dssdev->manager == NULL) {
4426 DSSERR("failed to enable display: no manager\n");
4427 r = -ENODEV;
4428 goto err_start_dev;
4429 }
4430
4214 r = omap_dss_start_device(dssdev); 4431 r = omap_dss_start_device(dssdev);
4215 if (r) { 4432 if (r) {
4216 DSSERR("failed to start device\n"); 4433 DSSERR("failed to start device\n");
@@ -4307,9 +4524,10 @@ int dsi_init_display(struct omap_dss_device *dssdev)
4307 4524
4308 DSSDBG("DSI init\n"); 4525 DSSDBG("DSI init\n");
4309 4526
4310 /* XXX these should be figured out dynamically */ 4527 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
4311 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | 4528 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
4312 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; 4529 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
4530 }
4313 4531
4314 if (dsi->vdds_dsi_reg == NULL) { 4532 if (dsi->vdds_dsi_reg == NULL) {
4315 struct regulator *vdds_dsi; 4533 struct regulator *vdds_dsi;
@@ -4435,10 +4653,7 @@ static int dsi_get_clocks(struct platform_device *dsidev)
4435 4653
4436 dsi->dss_clk = clk; 4654 dsi->dss_clk = clk;
4437 4655
4438 if (cpu_is_omap34xx() || cpu_is_omap3630()) 4656 clk = clk_get(&dsidev->dev, "sys_clk");
4439 clk = clk_get(&dsidev->dev, "dss2_alwon_fck");
4440 else
4441 clk = clk_get(&dsidev->dev, "sys_clk");
4442 if (IS_ERR(clk)) { 4657 if (IS_ERR(clk)) {
4443 DSSERR("can't get sys_clk\n"); 4658 DSSERR("can't get sys_clk\n");
4444 clk_put(dsi->dss_clk); 4659 clk_put(dsi->dss_clk);
@@ -4462,7 +4677,7 @@ static void dsi_put_clocks(struct platform_device *dsidev)
4462} 4677}
4463 4678
4464/* DSI1 HW IP initialisation */ 4679/* DSI1 HW IP initialisation */
4465static int omap_dsi1hw_probe(struct platform_device *dsidev) 4680static int omap_dsihw_probe(struct platform_device *dsidev)
4466{ 4681{
4467 struct omap_display_platform_data *dss_plat_data; 4682 struct omap_display_platform_data *dss_plat_data;
4468 struct omap_dss_board_info *board_info; 4683 struct omap_dss_board_info *board_info;
@@ -4483,7 +4698,8 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
4483 4698
4484 dss_plat_data = dsidev->dev.platform_data; 4699 dss_plat_data = dsidev->dev.platform_data;
4485 board_info = dss_plat_data->board_data; 4700 board_info = dss_plat_data->board_data;
4486 dsi->dsi_mux_pads = board_info->dsi_mux_pads; 4701 dsi->enable_pads = board_info->dsi_enable_pads;
4702 dsi->disable_pads = board_info->dsi_disable_pads;
4487 4703
4488 spin_lock_init(&dsi->irq_lock); 4704 spin_lock_init(&dsi->irq_lock);
4489 spin_lock_init(&dsi->errors_lock); 4705 spin_lock_init(&dsi->errors_lock);
@@ -4539,7 +4755,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
4539 4755
4540 /* DSI VCs initialization */ 4756 /* DSI VCs initialization */
4541 for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { 4757 for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
4542 dsi->vc[i].mode = DSI_VC_MODE_L4; 4758 dsi->vc[i].source = DSI_VC_SOURCE_L4;
4543 dsi->vc[i].dssdev = NULL; 4759 dsi->vc[i].dssdev = NULL;
4544 dsi->vc[i].vc_id = 0; 4760 dsi->vc[i].vc_id = 0;
4545 } 4761 }
@@ -4572,7 +4788,7 @@ err_alloc:
4572 return r; 4788 return r;
4573} 4789}
4574 4790
4575static int omap_dsi1hw_remove(struct platform_device *dsidev) 4791static int omap_dsihw_remove(struct platform_device *dsidev)
4576{ 4792{
4577 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4793 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4578 4794
@@ -4602,10 +4818,6 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev)
4602 4818
4603static int dsi_runtime_suspend(struct device *dev) 4819static int dsi_runtime_suspend(struct device *dev)
4604{ 4820{
4605 struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
4606
4607 clk_disable(dsi->dss_clk);
4608
4609 dispc_runtime_put(); 4821 dispc_runtime_put();
4610 dss_runtime_put(); 4822 dss_runtime_put();
4611 4823
@@ -4614,7 +4826,6 @@ static int dsi_runtime_suspend(struct device *dev)
4614 4826
4615static int dsi_runtime_resume(struct device *dev) 4827static int dsi_runtime_resume(struct device *dev)
4616{ 4828{
4617 struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
4618 int r; 4829 int r;
4619 4830
4620 r = dss_runtime_get(); 4831 r = dss_runtime_get();
@@ -4625,8 +4836,6 @@ static int dsi_runtime_resume(struct device *dev)
4625 if (r) 4836 if (r)
4626 goto err_get_dispc; 4837 goto err_get_dispc;
4627 4838
4628 clk_enable(dsi->dss_clk);
4629
4630 return 0; 4839 return 0;
4631 4840
4632err_get_dispc: 4841err_get_dispc:
@@ -4640,11 +4849,11 @@ static const struct dev_pm_ops dsi_pm_ops = {
4640 .runtime_resume = dsi_runtime_resume, 4849 .runtime_resume = dsi_runtime_resume,
4641}; 4850};
4642 4851
4643static struct platform_driver omap_dsi1hw_driver = { 4852static struct platform_driver omap_dsihw_driver = {
4644 .probe = omap_dsi1hw_probe, 4853 .probe = omap_dsihw_probe,
4645 .remove = omap_dsi1hw_remove, 4854 .remove = omap_dsihw_remove,
4646 .driver = { 4855 .driver = {
4647 .name = "omapdss_dsi1", 4856 .name = "omapdss_dsi",
4648 .owner = THIS_MODULE, 4857 .owner = THIS_MODULE,
4649 .pm = &dsi_pm_ops, 4858 .pm = &dsi_pm_ops,
4650 }, 4859 },
@@ -4652,10 +4861,10 @@ static struct platform_driver omap_dsi1hw_driver = {
4652 4861
4653int dsi_init_platform_driver(void) 4862int dsi_init_platform_driver(void)
4654{ 4863{
4655 return platform_driver_register(&omap_dsi1hw_driver); 4864 return platform_driver_register(&omap_dsihw_driver);
4656} 4865}
4657 4866
4658void dsi_uninit_platform_driver(void) 4867void dsi_uninit_platform_driver(void)
4659{ 4868{
4660 return platform_driver_unregister(&omap_dsi1hw_driver); 4869 return platform_driver_unregister(&omap_dsihw_driver);
4661} 4870}
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 0f9c3a6457a..3e09726d32c 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -639,6 +639,17 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
639 REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ 639 REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
640} 640}
641 641
642enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
643{
644 enum omap_display_type displays;
645
646 displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
647 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
648 return DSS_VENC_TV_CLK;
649
650 return REG_GET(DSS_CONTROL, 15, 15);
651}
652
642static int dss_get_clocks(void) 653static int dss_get_clocks(void)
643{ 654{
644 struct clk *clk; 655 struct clk *clk;
@@ -691,11 +702,6 @@ static void dss_put_clocks(void)
691 clk_put(dss.dss_clk); 702 clk_put(dss.dss_clk);
692} 703}
693 704
694struct clk *dss_get_ick(void)
695{
696 return clk_get(&dss.pdev->dev, "ick");
697}
698
699int dss_runtime_get(void) 705int dss_runtime_get(void)
700{ 706{
701 int r; 707 int r;
@@ -824,13 +830,11 @@ static int omap_dsshw_remove(struct platform_device *pdev)
824static int dss_runtime_suspend(struct device *dev) 830static int dss_runtime_suspend(struct device *dev)
825{ 831{
826 dss_save_context(); 832 dss_save_context();
827 clk_disable(dss.dss_clk);
828 return 0; 833 return 0;
829} 834}
830 835
831static int dss_runtime_resume(struct device *dev) 836static int dss_runtime_resume(struct device *dev)
832{ 837{
833 clk_enable(dss.dss_clk);
834 dss_restore_context(); 838 dss_restore_context();
835 return 0; 839 return 0;
836} 840}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 9c94b1152c2..6308fc59fc9 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -97,10 +97,10 @@ extern unsigned int dss_debug;
97#define FLD_MOD(orig, val, start, end) \ 97#define FLD_MOD(orig, val, start, end) \
98 (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) 98 (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
99 99
100enum omap_parallel_interface_mode { 100enum dss_io_pad_mode {
101 OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */ 101 DSS_IO_PAD_MODE_RESET,
102 OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */ 102 DSS_IO_PAD_MODE_RFBI,
103 OMAP_DSS_PARALLELMODE_DSI, 103 DSS_IO_PAD_MODE_BYPASS,
104}; 104};
105 105
106enum dss_hdmi_venc_clk_source_select { 106enum dss_hdmi_venc_clk_source_select {
@@ -108,6 +108,11 @@ enum dss_hdmi_venc_clk_source_select {
108 DSS_HDMI_M_PCLK = 1, 108 DSS_HDMI_M_PCLK = 1,
109}; 109};
110 110
111enum dss_dsi_content_type {
112 DSS_DSI_CONTENT_DCS,
113 DSS_DSI_CONTENT_GENERIC,
114};
115
111struct dss_clock_info { 116struct dss_clock_info {
112 /* rates that we get with dividers below */ 117 /* rates that we get with dividers below */
113 unsigned long fck; 118 unsigned long fck;
@@ -150,16 +155,6 @@ struct dsi_clock_info {
150 bool use_sys_clk; 155 bool use_sys_clk;
151}; 156};
152 157
153/* HDMI PLL structure */
154struct hdmi_pll_info {
155 u16 regn;
156 u16 regm;
157 u32 regmf;
158 u16 regm2;
159 u16 regsd;
160 u16 dcofreq;
161};
162
163struct seq_file; 158struct seq_file;
164struct platform_device; 159struct platform_device;
165 160
@@ -209,9 +204,8 @@ void dss_uninit_platform_driver(void);
209int dss_runtime_get(void); 204int dss_runtime_get(void);
210void dss_runtime_put(void); 205void dss_runtime_put(void);
211 206
212struct clk *dss_get_ick(void);
213
214void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 207void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
208enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
215const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 209const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
216void dss_dump_clocks(struct seq_file *s); 210void dss_dump_clocks(struct seq_file *s);
217 211
@@ -279,6 +273,8 @@ void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
279 273
280int dsi_init_display(struct omap_dss_device *display); 274int dsi_init_display(struct omap_dss_device *display);
281void dsi_irq_handler(void); 275void dsi_irq_handler(void);
276u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
277
282unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); 278unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
283int dsi_pll_set_clock_div(struct platform_device *dsidev, 279int dsi_pll_set_clock_div(struct platform_device *dsidev,
284 struct dsi_clock_info *cinfo); 280 struct dsi_clock_info *cinfo);
@@ -309,6 +305,11 @@ static inline int dsi_runtime_get(struct platform_device *dsidev)
309static inline void dsi_runtime_put(struct platform_device *dsidev) 305static inline void dsi_runtime_put(struct platform_device *dsidev)
310{ 306{
311} 307}
308static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
309{
310 WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__);
311 return 0;
312}
312static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) 313static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
313{ 314{
314 WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); 315 WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -385,90 +386,71 @@ void dispc_disable_sidle(void);
385void dispc_lcd_enable_signal_polarity(bool act_high); 386void dispc_lcd_enable_signal_polarity(bool act_high);
386void dispc_lcd_enable_signal(bool enable); 387void dispc_lcd_enable_signal(bool enable);
387void dispc_pck_free_enable(bool enable); 388void dispc_pck_free_enable(bool enable);
388void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable);
389
390void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
391void dispc_set_digit_size(u16 width, u16 height); 389void dispc_set_digit_size(u16 width, u16 height);
392u32 dispc_get_plane_fifo_size(enum omap_plane plane);
393void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
394void dispc_enable_fifomerge(bool enable); 390void dispc_enable_fifomerge(bool enable);
395u32 dispc_get_burst_size(enum omap_plane plane);
396void dispc_enable_cpr(enum omap_channel channel, bool enable);
397void dispc_set_cpr_coef(enum omap_channel channel,
398 struct omap_dss_cpr_coefs *coefs);
399
400void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
401void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
402void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
403void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
404void dispc_set_channel_out(enum omap_plane plane,
405 enum omap_channel channel_out);
406
407void dispc_enable_gamma_table(bool enable); 391void dispc_enable_gamma_table(bool enable);
408int dispc_setup_plane(enum omap_plane plane,
409 u32 paddr, u16 screen_width,
410 u16 pos_x, u16 pos_y,
411 u16 width, u16 height,
412 u16 out_width, u16 out_height,
413 enum omap_color_mode color_mode,
414 bool ilace,
415 enum omap_dss_rotation_type rotation_type,
416 u8 rotation, bool mirror,
417 u8 global_alpha, u8 pre_mult_alpha,
418 enum omap_channel channel,
419 u32 puv_addr);
420
421bool dispc_go_busy(enum omap_channel channel);
422void dispc_go(enum omap_channel channel);
423void dispc_enable_channel(enum omap_channel channel, bool enable);
424bool dispc_is_channel_enabled(enum omap_channel channel);
425int dispc_enable_plane(enum omap_plane plane, bool enable);
426void dispc_enable_replication(enum omap_plane plane, bool enable);
427
428void dispc_set_parallel_interface_mode(enum omap_channel channel,
429 enum omap_parallel_interface_mode mode);
430void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
431void dispc_set_lcd_display_type(enum omap_channel channel,
432 enum omap_lcd_display_type type);
433void dispc_set_loadmode(enum omap_dss_load_mode mode); 392void dispc_set_loadmode(enum omap_dss_load_mode mode);
434 393
435void dispc_set_default_color(enum omap_channel channel, u32 color);
436u32 dispc_get_default_color(enum omap_channel channel);
437void dispc_set_trans_key(enum omap_channel ch,
438 enum omap_dss_trans_key_type type,
439 u32 trans_key);
440void dispc_get_trans_key(enum omap_channel ch,
441 enum omap_dss_trans_key_type *type,
442 u32 *trans_key);
443void dispc_enable_trans_key(enum omap_channel ch, bool enable);
444void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
445bool dispc_trans_key_enabled(enum omap_channel ch);
446bool dispc_alpha_blending_enabled(enum omap_channel ch);
447
448bool dispc_lcd_timings_ok(struct omap_video_timings *timings); 394bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
449void dispc_set_lcd_timings(enum omap_channel channel,
450 struct omap_video_timings *timings);
451unsigned long dispc_fclk_rate(void); 395unsigned long dispc_fclk_rate(void);
452unsigned long dispc_lclk_rate(enum omap_channel channel);
453unsigned long dispc_pclk_rate(enum omap_channel channel);
454void dispc_set_pol_freq(enum omap_channel channel,
455 enum omap_panel_config config, u8 acbi, u8 acb);
456void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, 396void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
457 struct dispc_clock_info *cinfo); 397 struct dispc_clock_info *cinfo);
458int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, 398int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
459 struct dispc_clock_info *cinfo); 399 struct dispc_clock_info *cinfo);
460int dispc_set_clock_div(enum omap_channel channel, 400
401
402u32 dispc_ovl_get_fifo_size(enum omap_plane plane);
403u32 dispc_ovl_get_burst_size(enum omap_plane plane);
404int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
405 bool ilace, enum omap_channel channel, bool replication,
406 u32 fifo_low, u32 fifo_high);
407int dispc_ovl_enable(enum omap_plane plane, bool enable);
408
409
410void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
411void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
412void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable);
413void dispc_mgr_set_cpr_coef(enum omap_channel channel,
414 struct omap_dss_cpr_coefs *coefs);
415bool dispc_mgr_go_busy(enum omap_channel channel);
416void dispc_mgr_go(enum omap_channel channel);
417void dispc_mgr_enable(enum omap_channel channel, bool enable);
418bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
419void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
420void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
421void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
422void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
423 enum omap_lcd_display_type type);
424void dispc_mgr_set_default_color(enum omap_channel channel, u32 color);
425u32 dispc_mgr_get_default_color(enum omap_channel channel);
426void dispc_mgr_set_trans_key(enum omap_channel ch,
427 enum omap_dss_trans_key_type type,
428 u32 trans_key);
429void dispc_mgr_get_trans_key(enum omap_channel ch,
430 enum omap_dss_trans_key_type *type,
431 u32 *trans_key);
432void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable);
433void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable);
434bool dispc_mgr_trans_key_enabled(enum omap_channel ch);
435bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch);
436void dispc_mgr_set_lcd_timings(enum omap_channel channel,
437 struct omap_video_timings *timings);
438void dispc_mgr_set_pol_freq(enum omap_channel channel,
439 enum omap_panel_config config, u8 acbi, u8 acb);
440unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
441unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
442int dispc_mgr_set_clock_div(enum omap_channel channel,
461 struct dispc_clock_info *cinfo); 443 struct dispc_clock_info *cinfo);
462int dispc_get_clock_div(enum omap_channel channel, 444int dispc_mgr_get_clock_div(enum omap_channel channel,
463 struct dispc_clock_info *cinfo); 445 struct dispc_clock_info *cinfo);
464 446
465
466/* VENC */ 447/* VENC */
467#ifdef CONFIG_OMAP2_DSS_VENC 448#ifdef CONFIG_OMAP2_DSS_VENC
468int venc_init_platform_driver(void); 449int venc_init_platform_driver(void);
469void venc_uninit_platform_driver(void); 450void venc_uninit_platform_driver(void);
470void venc_dump_regs(struct seq_file *s); 451void venc_dump_regs(struct seq_file *s);
471int venc_init_display(struct omap_dss_device *display); 452int venc_init_display(struct omap_dss_device *display);
453unsigned long venc_get_pixel_clock(void);
472#else 454#else
473static inline int venc_init_platform_driver(void) 455static inline int venc_init_platform_driver(void)
474{ 456{
@@ -477,6 +459,11 @@ static inline int venc_init_platform_driver(void)
477static inline void venc_uninit_platform_driver(void) 459static inline void venc_uninit_platform_driver(void)
478{ 460{
479} 461}
462static inline unsigned long venc_get_pixel_clock(void)
463{
464 WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__);
465 return 0;
466}
480#endif 467#endif
481 468
482/* HDMI */ 469/* HDMI */
@@ -484,6 +471,8 @@ static inline void venc_uninit_platform_driver(void)
484int hdmi_init_platform_driver(void); 471int hdmi_init_platform_driver(void);
485void hdmi_uninit_platform_driver(void); 472void hdmi_uninit_platform_driver(void);
486int hdmi_init_display(struct omap_dss_device *dssdev); 473int hdmi_init_display(struct omap_dss_device *dssdev);
474unsigned long hdmi_get_pixel_clock(void);
475void hdmi_dump_regs(struct seq_file *s);
487#else 476#else
488static inline int hdmi_init_display(struct omap_dss_device *dssdev) 477static inline int hdmi_init_display(struct omap_dss_device *dssdev)
489{ 478{
@@ -496,12 +485,19 @@ static inline int hdmi_init_platform_driver(void)
496static inline void hdmi_uninit_platform_driver(void) 485static inline void hdmi_uninit_platform_driver(void)
497{ 486{
498} 487}
488static inline unsigned long hdmi_get_pixel_clock(void)
489{
490 WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__);
491 return 0;
492}
499#endif 493#endif
500int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); 494int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
501void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); 495void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
502void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); 496void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
503int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 497int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
504 struct omap_video_timings *timings); 498 struct omap_video_timings *timings);
499int omapdss_hdmi_read_edid(u8 *buf, int len);
500bool omapdss_hdmi_detect(void);
505int hdmi_panel_init(void); 501int hdmi_panel_init(void);
506void hdmi_panel_exit(void); 502void hdmi_panel_exit(void);
507 503
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index b415c4ee621..b402699168a 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -47,6 +47,7 @@ struct omap_dss_features {
47 const int num_ovls; 47 const int num_ovls;
48 const enum omap_display_type *supported_displays; 48 const enum omap_display_type *supported_displays;
49 const enum omap_color_mode *supported_color_modes; 49 const enum omap_color_mode *supported_color_modes;
50 const enum omap_overlay_caps *overlay_caps;
50 const char * const *clksrc_names; 51 const char * const *clksrc_names;
51 const struct dss_param_range *dss_params; 52 const struct dss_param_range *dss_params;
52 53
@@ -209,6 +210,68 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
209 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | 210 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
210 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | 211 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
211 OMAP_DSS_COLOR_RGBX32, 212 OMAP_DSS_COLOR_RGBX32,
213
214 /* OMAP_DSS_VIDEO3 */
215 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
216 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
217 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
218 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
219 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
220 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
221 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
222 OMAP_DSS_COLOR_RGBX32,
223};
224
225static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
226 /* OMAP_DSS_GFX */
227 0,
228
229 /* OMAP_DSS_VIDEO1 */
230 OMAP_DSS_OVL_CAP_SCALE,
231
232 /* OMAP_DSS_VIDEO2 */
233 OMAP_DSS_OVL_CAP_SCALE,
234};
235
236static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
237 /* OMAP_DSS_GFX */
238 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
239
240 /* OMAP_DSS_VIDEO1 */
241 OMAP_DSS_OVL_CAP_SCALE,
242
243 /* OMAP_DSS_VIDEO2 */
244 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
245};
246
247static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
248 /* OMAP_DSS_GFX */
249 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
250
251 /* OMAP_DSS_VIDEO1 */
252 OMAP_DSS_OVL_CAP_SCALE,
253
254 /* OMAP_DSS_VIDEO2 */
255 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
256 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
257};
258
259static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
260 /* OMAP_DSS_GFX */
261 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
262 OMAP_DSS_OVL_CAP_ZORDER,
263
264 /* OMAP_DSS_VIDEO1 */
265 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
266 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
267
268 /* OMAP_DSS_VIDEO2 */
269 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
270 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
271
272 /* OMAP_DSS_VIDEO3 */
273 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
274 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
212}; 275};
213 276
214static const char * const omap2_dss_clk_source_names[] = { 277static const char * const omap2_dss_clk_source_names[] = {
@@ -233,32 +296,38 @@ static const char * const omap4_dss_clk_source_names[] = {
233 296
234static const struct dss_param_range omap2_dss_param_range[] = { 297static const struct dss_param_range omap2_dss_param_range[] = {
235 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, 298 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
299 [FEAT_PARAM_DSS_PCD] = { 2, 255 },
236 [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, 300 [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 },
237 [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, 301 [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 },
238 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, 302 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 },
239 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, 303 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 },
240 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, 304 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
241 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, 305 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
306 [FEAT_PARAM_DOWNSCALE] = { 1, 2 },
242}; 307};
243 308
244static const struct dss_param_range omap3_dss_param_range[] = { 309static const struct dss_param_range omap3_dss_param_range[] = {
245 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, 310 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
311 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
246 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, 312 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 },
247 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, 313 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 },
248 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, 314 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 },
249 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, 315 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
250 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, 316 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
251 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, 317 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
318 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
252}; 319};
253 320
254static const struct dss_param_range omap4_dss_param_range[] = { 321static const struct dss_param_range omap4_dss_param_range[] = {
255 [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, 322 [FEAT_PARAM_DSS_FCK] = { 0, 186000000 },
323 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
256 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, 324 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
257 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, 325 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
258 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, 326 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
259 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, 327 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
260 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, 328 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
261 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 329 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
330 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
262}; 331};
263 332
264/* OMAP2 DSS Features */ 333/* OMAP2 DSS Features */
@@ -275,6 +344,7 @@ static const struct omap_dss_features omap2_dss_features = {
275 .num_ovls = 3, 344 .num_ovls = 3,
276 .supported_displays = omap2_dss_supported_displays, 345 .supported_displays = omap2_dss_supported_displays,
277 .supported_color_modes = omap2_dss_supported_color_modes, 346 .supported_color_modes = omap2_dss_supported_color_modes,
347 .overlay_caps = omap2_dss_overlay_caps,
278 .clksrc_names = omap2_dss_clk_source_names, 348 .clksrc_names = omap2_dss_clk_source_names,
279 .dss_params = omap2_dss_param_range, 349 .dss_params = omap2_dss_param_range,
280 .buffer_size_unit = 1, 350 .buffer_size_unit = 1,
@@ -287,18 +357,19 @@ static const struct omap_dss_features omap3430_dss_features = {
287 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), 357 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
288 358
289 .has_feature = 359 .has_feature =
290 FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | 360 FEAT_LCDENABLEPOL |
291 FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | 361 FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
292 FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | 362 FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
293 FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | 363 FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
294 FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | 364 FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
295 FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | 365 FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
296 FEAT_FIR_COEF_V, 366 FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
297 367
298 .num_mgrs = 2, 368 .num_mgrs = 2,
299 .num_ovls = 3, 369 .num_ovls = 3,
300 .supported_displays = omap3430_dss_supported_displays, 370 .supported_displays = omap3430_dss_supported_displays,
301 .supported_color_modes = omap3_dss_supported_color_modes, 371 .supported_color_modes = omap3_dss_supported_color_modes,
372 .overlay_caps = omap3430_dss_overlay_caps,
302 .clksrc_names = omap3_dss_clk_source_names, 373 .clksrc_names = omap3_dss_clk_source_names,
303 .dss_params = omap3_dss_param_range, 374 .dss_params = omap3_dss_param_range,
304 .buffer_size_unit = 1, 375 .buffer_size_unit = 1,
@@ -310,18 +381,19 @@ static const struct omap_dss_features omap3630_dss_features = {
310 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), 381 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
311 382
312 .has_feature = 383 .has_feature =
313 FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | 384 FEAT_LCDENABLEPOL |
314 FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | 385 FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
315 FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | 386 FEAT_FUNCGATED |
316 FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | 387 FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
317 FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | 388 FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
318 FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | 389 FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
319 FEAT_FIR_COEF_V, 390 FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
320 391
321 .num_mgrs = 2, 392 .num_mgrs = 2,
322 .num_ovls = 3, 393 .num_ovls = 3,
323 .supported_displays = omap3630_dss_supported_displays, 394 .supported_displays = omap3630_dss_supported_displays,
324 .supported_color_modes = omap3_dss_supported_color_modes, 395 .supported_color_modes = omap3_dss_supported_color_modes,
396 .overlay_caps = omap3630_dss_overlay_caps,
325 .clksrc_names = omap3_dss_clk_source_names, 397 .clksrc_names = omap3_dss_clk_source_names,
326 .dss_params = omap3_dss_param_range, 398 .dss_params = omap3_dss_param_range,
327 .buffer_size_unit = 1, 399 .buffer_size_unit = 1,
@@ -335,17 +407,18 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
335 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), 407 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
336 408
337 .has_feature = 409 .has_feature =
338 FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | 410 FEAT_MGR_LCD2 |
339 FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
340 FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | 411 FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
341 FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | 412 FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
342 FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | 413 FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
343 FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V, 414 FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V |
415 FEAT_ALPHA_FREE_ZORDER,
344 416
345 .num_mgrs = 3, 417 .num_mgrs = 3,
346 .num_ovls = 3, 418 .num_ovls = 4,
347 .supported_displays = omap4_dss_supported_displays, 419 .supported_displays = omap4_dss_supported_displays,
348 .supported_color_modes = omap4_dss_supported_color_modes, 420 .supported_color_modes = omap4_dss_supported_color_modes,
421 .overlay_caps = omap4_dss_overlay_caps,
349 .clksrc_names = omap4_dss_clk_source_names, 422 .clksrc_names = omap4_dss_clk_source_names,
350 .dss_params = omap4_dss_param_range, 423 .dss_params = omap4_dss_param_range,
351 .buffer_size_unit = 16, 424 .buffer_size_unit = 16,
@@ -358,24 +431,50 @@ static const struct omap_dss_features omap4_dss_features = {
358 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), 431 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
359 432
360 .has_feature = 433 .has_feature =
361 FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | 434 FEAT_MGR_LCD2 |
362 FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
363 FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | 435 FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
364 FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | 436 FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
365 FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | 437 FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
366 FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | 438 FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
367 FEAT_PRELOAD | FEAT_FIR_COEF_V, 439 FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER,
368 440
369 .num_mgrs = 3, 441 .num_mgrs = 3,
370 .num_ovls = 3, 442 .num_ovls = 4,
371 .supported_displays = omap4_dss_supported_displays, 443 .supported_displays = omap4_dss_supported_displays,
372 .supported_color_modes = omap4_dss_supported_color_modes, 444 .supported_color_modes = omap4_dss_supported_color_modes,
445 .overlay_caps = omap4_dss_overlay_caps,
373 .clksrc_names = omap4_dss_clk_source_names, 446 .clksrc_names = omap4_dss_clk_source_names,
374 .dss_params = omap4_dss_param_range, 447 .dss_params = omap4_dss_param_range,
375 .buffer_size_unit = 16, 448 .buffer_size_unit = 16,
376 .burst_size_unit = 16, 449 .burst_size_unit = 16,
377}; 450};
378 451
452#if defined(CONFIG_OMAP4_DSS_HDMI)
453/* HDMI OMAP4 Functions*/
454static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
455
456 .video_configure = ti_hdmi_4xxx_basic_configure,
457 .phy_enable = ti_hdmi_4xxx_phy_enable,
458 .phy_disable = ti_hdmi_4xxx_phy_disable,
459 .read_edid = ti_hdmi_4xxx_read_edid,
460 .detect = ti_hdmi_4xxx_detect,
461 .pll_enable = ti_hdmi_4xxx_pll_enable,
462 .pll_disable = ti_hdmi_4xxx_pll_disable,
463 .video_enable = ti_hdmi_4xxx_wp_video_start,
464 .dump_wrapper = ti_hdmi_4xxx_wp_dump,
465 .dump_core = ti_hdmi_4xxx_core_dump,
466 .dump_pll = ti_hdmi_4xxx_pll_dump,
467 .dump_phy = ti_hdmi_4xxx_phy_dump,
468
469};
470
471void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
472{
473 if (cpu_is_omap44xx())
474 ip_data->ops = &omap4_hdmi_functions;
475}
476#endif
477
379/* Functions returning values related to a DSS feature */ 478/* Functions returning values related to a DSS feature */
380int dss_feat_get_num_mgrs(void) 479int dss_feat_get_num_mgrs(void)
381{ 480{
@@ -407,6 +506,11 @@ enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
407 return omap_current_dss_features->supported_color_modes[plane]; 506 return omap_current_dss_features->supported_color_modes[plane];
408} 507}
409 508
509enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
510{
511 return omap_current_dss_features->overlay_caps[plane];
512}
513
410bool dss_feat_color_mode_supported(enum omap_plane plane, 514bool dss_feat_color_mode_supported(enum omap_plane plane,
411 enum omap_color_mode color_mode) 515 enum omap_color_mode color_mode)
412{ 516{
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index b7398cbcda5..6a6c05dd45c 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -20,16 +20,17 @@
20#ifndef __OMAP2_DSS_FEATURES_H 20#ifndef __OMAP2_DSS_FEATURES_H
21#define __OMAP2_DSS_FEATURES_H 21#define __OMAP2_DSS_FEATURES_H
22 22
23#if defined(CONFIG_OMAP4_DSS_HDMI)
24#include "ti_hdmi.h"
25#endif
26
23#define MAX_DSS_MANAGERS 3 27#define MAX_DSS_MANAGERS 3
24#define MAX_DSS_OVERLAYS 3 28#define MAX_DSS_OVERLAYS 4
25#define MAX_DSS_LCD_MANAGERS 2 29#define MAX_DSS_LCD_MANAGERS 2
26#define MAX_NUM_DSI 2 30#define MAX_NUM_DSI 2
27 31
28/* DSS has feature id */ 32/* DSS has feature id */
29enum dss_feat_id { 33enum dss_feat_id {
30 FEAT_GLOBAL_ALPHA = 1 << 0,
31 FEAT_GLOBAL_ALPHA_VID1 = 1 << 1,
32 FEAT_PRE_MULT_ALPHA = 1 << 2,
33 FEAT_LCDENABLEPOL = 1 << 3, 34 FEAT_LCDENABLEPOL = 1 << 3,
34 FEAT_LCDENABLESIGNAL = 1 << 4, 35 FEAT_LCDENABLESIGNAL = 1 << 4,
35 FEAT_PCKFREEENABLE = 1 << 5, 36 FEAT_PCKFREEENABLE = 1 << 5,
@@ -55,6 +56,8 @@ enum dss_feat_id {
55 FEAT_CPR = 1 << 23, 56 FEAT_CPR = 1 << 23,
56 FEAT_PRELOAD = 1 << 24, 57 FEAT_PRELOAD = 1 << 24,
57 FEAT_FIR_COEF_V = 1 << 25, 58 FEAT_FIR_COEF_V = 1 << 25,
59 FEAT_ALPHA_FIXED_ZORDER = 1 << 26,
60 FEAT_ALPHA_FREE_ZORDER = 1 << 27,
58}; 61};
59 62
60/* DSS register field id */ 63/* DSS register field id */
@@ -75,12 +78,14 @@ enum dss_feat_reg_field {
75 78
76enum dss_range_param { 79enum dss_range_param {
77 FEAT_PARAM_DSS_FCK, 80 FEAT_PARAM_DSS_FCK,
81 FEAT_PARAM_DSS_PCD,
78 FEAT_PARAM_DSIPLL_REGN, 82 FEAT_PARAM_DSIPLL_REGN,
79 FEAT_PARAM_DSIPLL_REGM, 83 FEAT_PARAM_DSIPLL_REGM,
80 FEAT_PARAM_DSIPLL_REGM_DISPC, 84 FEAT_PARAM_DSIPLL_REGM_DISPC,
81 FEAT_PARAM_DSIPLL_REGM_DSI, 85 FEAT_PARAM_DSIPLL_REGM_DSI,
82 FEAT_PARAM_DSIPLL_FINT, 86 FEAT_PARAM_DSIPLL_FINT,
83 FEAT_PARAM_DSIPLL_LPDIV, 87 FEAT_PARAM_DSIPLL_LPDIV,
88 FEAT_PARAM_DOWNSCALE,
84}; 89};
85 90
86/* DSS Feature Functions */ 91/* DSS Feature Functions */
@@ -90,6 +95,7 @@ unsigned long dss_feat_get_param_min(enum dss_range_param param);
90unsigned long dss_feat_get_param_max(enum dss_range_param param); 95unsigned long dss_feat_get_param_max(enum dss_range_param param);
91enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); 96enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
92enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); 97enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
98enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
93bool dss_feat_color_mode_supported(enum omap_plane plane, 99bool dss_feat_color_mode_supported(enum omap_plane plane,
94 enum omap_color_mode color_mode); 100 enum omap_color_mode color_mode);
95const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); 101const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
@@ -100,4 +106,7 @@ u32 dss_feat_get_burst_size_unit(void); /* in bytes */
100bool dss_has_feature(enum dss_feat_id id); 106bool dss_has_feature(enum dss_feat_id id);
101void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); 107void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
102void dss_features_init(void); 108void dss_features_init(void);
109#if defined(CONFIG_OMAP4_DSS_HDMI)
110void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
111#endif
103#endif 112#endif
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 256f27a9064..3262f0f1fa3 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -37,26 +37,41 @@
37 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 37 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
38#include <sound/soc.h> 38#include <sound/soc.h>
39#include <sound/pcm_params.h> 39#include <sound/pcm_params.h>
40#include "ti_hdmi_4xxx_ip.h"
40#endif 41#endif
41 42
43#include "ti_hdmi.h"
42#include "dss.h" 44#include "dss.h"
43#include "hdmi.h"
44#include "dss_features.h" 45#include "dss_features.h"
45 46
47#define HDMI_WP 0x0
48#define HDMI_CORE_SYS 0x400
49#define HDMI_CORE_AV 0x900
50#define HDMI_PLLCTRL 0x200
51#define HDMI_PHY 0x300
52
53/* HDMI EDID Length move this */
54#define HDMI_EDID_MAX_LENGTH 256
55#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
56#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
57#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
58#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
59#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
60
61#define OMAP_HDMI_TIMINGS_NB 34
62
63#define HDMI_DEFAULT_REGN 16
64#define HDMI_DEFAULT_REGM2 1
65
46static struct { 66static struct {
47 struct mutex lock; 67 struct mutex lock;
48 struct omap_display_platform_data *pdata; 68 struct omap_display_platform_data *pdata;
49 struct platform_device *pdev; 69 struct platform_device *pdev;
50 void __iomem *base_wp; /* HDMI wrapper */ 70 struct hdmi_ip_data ip_data;
51 int code; 71 int code;
52 int mode; 72 int mode;
53 u8 edid[HDMI_EDID_MAX_LENGTH];
54 u8 edid_set;
55 bool custom_set;
56 struct hdmi_config cfg;
57 73
58 struct clk *sys_clk; 74 struct clk *sys_clk;
59 struct clk *hdmi_clk;
60} hdmi; 75} hdmi;
61 76
62/* 77/*
@@ -144,30 +159,6 @@ static const int code_vesa[85] = {
144 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 159 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
145 -1, 27, 28, -1, 33}; 160 -1, 27, 28, -1, 33};
146 161
147static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0};
148
149static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val)
150{
151 __raw_writel(val, hdmi.base_wp + idx.idx);
152}
153
154static inline u32 hdmi_read_reg(const struct hdmi_reg idx)
155{
156 return __raw_readl(hdmi.base_wp + idx.idx);
157}
158
159static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
160 int b2, int b1, u32 val)
161{
162 u32 t = 0;
163 while (val != REG_GET(idx, b2, b1)) {
164 udelay(1);
165 if (t++ > 10000)
166 return !val;
167 }
168 return val;
169}
170
171static int hdmi_runtime_get(void) 162static int hdmi_runtime_get(void)
172{ 163{
173 int r; 164 int r;
@@ -193,304 +184,7 @@ int hdmi_init_display(struct omap_dss_device *dssdev)
193{ 184{
194 DSSDBG("init_display\n"); 185 DSSDBG("init_display\n");
195 186
196 return 0; 187 dss_init_hdmi_ip_ops(&hdmi.ip_data);
197}
198
199static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq,
200 struct hdmi_pll_info *fmt, u16 sd)
201{
202 u32 r;
203
204 /* PLL start always use manual mode */
205 REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
206
207 r = hdmi_read_reg(PLLCTRL_CFG1);
208 r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
209 r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */
210
211 hdmi_write_reg(PLLCTRL_CFG1, r);
212
213 r = hdmi_read_reg(PLLCTRL_CFG2);
214
215 r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
216 r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
217 r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
218
219 if (dcofreq) {
220 /* divider programming for frequency beyond 1000Mhz */
221 REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10);
222 r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
223 } else {
224 r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
225 }
226
227 hdmi_write_reg(PLLCTRL_CFG2, r);
228
229 r = hdmi_read_reg(PLLCTRL_CFG4);
230 r = FLD_MOD(r, fmt->regm2, 24, 18);
231 r = FLD_MOD(r, fmt->regmf, 17, 0);
232
233 hdmi_write_reg(PLLCTRL_CFG4, r);
234
235 /* go now */
236 REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0);
237
238 /* wait for bit change */
239 if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) {
240 DSSERR("PLL GO bit not set\n");
241 return -ETIMEDOUT;
242 }
243
244 /* Wait till the lock bit is set in PLL status */
245 if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
246 DSSWARN("cannot lock PLL\n");
247 DSSWARN("CFG1 0x%x\n",
248 hdmi_read_reg(PLLCTRL_CFG1));
249 DSSWARN("CFG2 0x%x\n",
250 hdmi_read_reg(PLLCTRL_CFG2));
251 DSSWARN("CFG4 0x%x\n",
252 hdmi_read_reg(PLLCTRL_CFG4));
253 return -ETIMEDOUT;
254 }
255
256 DSSDBG("PLL locked!\n");
257
258 return 0;
259}
260
261/* PHY_PWR_CMD */
262static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val)
263{
264 /* Command for power control of HDMI PHY */
265 REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6);
266
267 /* Status of the power control of HDMI PHY */
268 if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
269 DSSERR("Failed to set PHY power mode to %d\n", val);
270 return -ETIMEDOUT;
271 }
272
273 return 0;
274}
275
276/* PLL_PWR_CMD */
277static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val)
278{
279 /* Command for power control of HDMI PLL */
280 REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2);
281
282 /* wait till PHY_PWR_STATUS is set */
283 if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) {
284 DSSERR("Failed to set PHY_PWR_STATUS\n");
285 return -ETIMEDOUT;
286 }
287
288 return 0;
289}
290
291static int hdmi_pll_reset(void)
292{
293 /* SYSRESET controlled by power FSM */
294 REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
295
296 /* READ 0x0 reset is in progress */
297 if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
298 DSSERR("Failed to sysreset PLL\n");
299 return -ETIMEDOUT;
300 }
301
302 return 0;
303}
304
305static int hdmi_phy_init(void)
306{
307 u16 r = 0;
308
309 r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON);
310 if (r)
311 return r;
312
313 r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON);
314 if (r)
315 return r;
316
317 /*
318 * Read address 0 in order to get the SCP reset done completed
319 * Dummy access performed to make sure reset is done
320 */
321 hdmi_read_reg(HDMI_TXPHY_TX_CTRL);
322
323 /*
324 * Write to phy address 0 to configure the clock
325 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
326 */
327 REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
328
329 /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
330 hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
331
332 /* Setup max LDO voltage */
333 REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
334
335 /* Write to phy address 3 to change the polarity control */
336 REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
337
338 return 0;
339}
340
341static int hdmi_pll_program(struct hdmi_pll_info *fmt)
342{
343 u16 r = 0;
344 enum hdmi_clk_refsel refsel;
345
346 r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
347 if (r)
348 return r;
349
350 r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
351 if (r)
352 return r;
353
354 r = hdmi_pll_reset();
355 if (r)
356 return r;
357
358 refsel = HDMI_REFSEL_SYSCLK;
359
360 r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd);
361 if (r)
362 return r;
363
364 return 0;
365}
366
367static void hdmi_phy_off(void)
368{
369 hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
370}
371
372static int hdmi_core_ddc_edid(u8 *pedid, int ext)
373{
374 u32 i, j;
375 char checksum = 0;
376 u32 offset = 0;
377
378 /* Turn on CLK for DDC */
379 REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0);
380
381 /*
382 * SW HACK : Without the Delay DDC(i2c bus) reads 0 values /
383 * right shifted values( The behavior is not consistent and seen only
384 * with some TV's)
385 */
386 usleep_range(800, 1000);
387
388 if (!ext) {
389 /* Clk SCL Devices */
390 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
391
392 /* HDMI_CORE_DDC_STATUS_IN_PROG */
393 if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
394 4, 4, 0) != 0) {
395 DSSERR("Failed to program DDC\n");
396 return -ETIMEDOUT;
397 }
398
399 /* Clear FIFO */
400 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0);
401
402 /* HDMI_CORE_DDC_STATUS_IN_PROG */
403 if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
404 4, 4, 0) != 0) {
405 DSSERR("Failed to program DDC\n");
406 return -ETIMEDOUT;
407 }
408
409 } else {
410 if (ext % 2 != 0)
411 offset = 0x80;
412 }
413
414 /* Load Segment Address Register */
415 REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
416
417 /* Load Slave Address Register */
418 REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
419
420 /* Load Offset Address Register */
421 REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0);
422
423 /* Load Byte Count */
424 REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
425 REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
426
427 /* Set DDC_CMD */
428 if (ext)
429 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0);
430 else
431 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0);
432
433 /* HDMI_CORE_DDC_STATUS_BUS_LOW */
434 if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
435 DSSWARN("I2C Bus Low?\n");
436 return -EIO;
437 }
438 /* HDMI_CORE_DDC_STATUS_NO_ACK */
439 if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
440 DSSWARN("I2C No Ack\n");
441 return -EIO;
442 }
443
444 i = ext * 128;
445 j = 0;
446 while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) ||
447 (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) &&
448 j < 128) {
449
450 if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) {
451 /* FIFO not empty */
452 pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
453 j++;
454 }
455 }
456
457 for (j = 0; j < 128; j++)
458 checksum += pedid[j];
459
460 if (checksum != 0) {
461 DSSERR("E-EDID checksum failed!!\n");
462 return -EIO;
463 }
464
465 return 0;
466}
467
468static int read_edid(u8 *pedid, u16 max_length)
469{
470 int r = 0, n = 0, i = 0;
471 int max_ext_blocks = (max_length / 128) - 1;
472
473 r = hdmi_core_ddc_edid(pedid, 0);
474 if (r) {
475 return r;
476 } else {
477 n = pedid[0x7e];
478
479 /*
480 * README: need to comply with max_length set by the caller.
481 * Better implementation should be to allocate necessary
482 * memory to store EDID according to nb_block field found
483 * in first block
484 */
485 if (n > max_ext_blocks)
486 n = max_ext_blocks;
487
488 for (i = 1; i <= n; i++) {
489 r = hdmi_core_ddc_edid(pedid, i);
490 if (r)
491 return r;
492 }
493 }
494 return 0; 188 return 0;
495} 189}
496 190
@@ -518,7 +212,7 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
518{ 212{
519 int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; 213 int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0;
520 int timing_vsync = 0, timing_hsync = 0; 214 int timing_vsync = 0, timing_hsync = 0;
521 struct omap_video_timings temp; 215 struct hdmi_video_timings temp;
522 struct hdmi_cm cm = {-1}; 216 struct hdmi_cm cm = {-1};
523 DSSDBG("hdmi_get_code\n"); 217 DSSDBG("hdmi_get_code\n");
524 218
@@ -556,500 +250,6 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
556 return cm; 250 return cm;
557} 251}
558 252
559static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid ,
560 struct omap_video_timings *timings)
561{
562 /* X and Y resolution */
563 timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) |
564 edid[current_descriptor_addrs + 2]);
565 timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) |
566 edid[current_descriptor_addrs + 5]);
567
568 timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) |
569 edid[current_descriptor_addrs]);
570
571 timings->pixel_clock = 10 * timings->pixel_clock;
572
573 /* HORIZONTAL FRONT PORCH */
574 timings->hfp = edid[current_descriptor_addrs + 8] |
575 ((edid[current_descriptor_addrs + 11] & 0xc0) << 2);
576 /* HORIZONTAL SYNC WIDTH */
577 timings->hsw = edid[current_descriptor_addrs + 9] |
578 ((edid[current_descriptor_addrs + 11] & 0x30) << 4);
579 /* HORIZONTAL BACK PORCH */
580 timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) |
581 edid[current_descriptor_addrs + 3]) -
582 (timings->hfp + timings->hsw);
583 /* VERTICAL FRONT PORCH */
584 timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) |
585 ((edid[current_descriptor_addrs + 11] & 0x0f) << 2);
586 /* VERTICAL SYNC WIDTH */
587 timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) |
588 ((edid[current_descriptor_addrs + 11] & 0x03) << 4);
589 /* VERTICAL BACK PORCH */
590 timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) |
591 edid[current_descriptor_addrs + 6]) -
592 (timings->vfp + timings->vsw);
593
594}
595
596/* Description : This function gets the resolution information from EDID */
597static void get_edid_timing_data(u8 *edid)
598{
599 u8 count;
600 u16 current_descriptor_addrs;
601 struct hdmi_cm cm;
602 struct omap_video_timings edid_timings;
603
604 /* search block 0, there are 4 DTDs arranged in priority order */
605 for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
606 current_descriptor_addrs =
607 EDID_DESCRIPTOR_BLOCK0_ADDRESS +
608 count * EDID_TIMING_DESCRIPTOR_SIZE;
609 get_horz_vert_timing_info(current_descriptor_addrs,
610 edid, &edid_timings);
611 cm = hdmi_get_code(&edid_timings);
612 DSSDBG("Block0[%d] value matches code = %d , mode = %d\n",
613 count, cm.code, cm.mode);
614 if (cm.code == -1) {
615 continue;
616 } else {
617 hdmi.code = cm.code;
618 hdmi.mode = cm.mode;
619 DSSDBG("code = %d , mode = %d\n",
620 hdmi.code, hdmi.mode);
621 return;
622 }
623 }
624 if (edid[0x7e] != 0x00) {
625 for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
626 count++) {
627 current_descriptor_addrs =
628 EDID_DESCRIPTOR_BLOCK1_ADDRESS +
629 count * EDID_TIMING_DESCRIPTOR_SIZE;
630 get_horz_vert_timing_info(current_descriptor_addrs,
631 edid, &edid_timings);
632 cm = hdmi_get_code(&edid_timings);
633 DSSDBG("Block1[%d] value matches code = %d, mode = %d",
634 count, cm.code, cm.mode);
635 if (cm.code == -1) {
636 continue;
637 } else {
638 hdmi.code = cm.code;
639 hdmi.mode = cm.mode;
640 DSSDBG("code = %d , mode = %d\n",
641 hdmi.code, hdmi.mode);
642 return;
643 }
644 }
645 }
646
647 DSSINFO("no valid timing found , falling back to VGA\n");
648 hdmi.code = 4; /* setting default value of 640 480 VGA */
649 hdmi.mode = HDMI_DVI;
650}
651
652static void hdmi_read_edid(struct omap_video_timings *dp)
653{
654 int ret = 0, code;
655
656 memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
657
658 if (!hdmi.edid_set)
659 ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
660
661 if (!ret) {
662 if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
663 /* search for timings of default resolution */
664 get_edid_timing_data(hdmi.edid);
665 hdmi.edid_set = true;
666 }
667 } else {
668 DSSWARN("failed to read E-EDID\n");
669 }
670
671 if (!hdmi.edid_set) {
672 DSSINFO("fallback to VGA\n");
673 hdmi.code = 4; /* setting default value of 640 480 VGA */
674 hdmi.mode = HDMI_DVI;
675 }
676
677 code = get_timings_index();
678
679 *dp = cea_vesa_timings[code].timings;
680}
681
682static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
683 struct hdmi_core_infoframe_avi *avi_cfg,
684 struct hdmi_core_packet_enable_repeat *repeat_cfg)
685{
686 DSSDBG("Enter hdmi_core_init\n");
687
688 /* video core */
689 video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
690 video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
691 video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
692 video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
693 video_cfg->hdmi_dvi = HDMI_DVI;
694 video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
695
696 /* info frame */
697 avi_cfg->db1_format = 0;
698 avi_cfg->db1_active_info = 0;
699 avi_cfg->db1_bar_info_dv = 0;
700 avi_cfg->db1_scan_info = 0;
701 avi_cfg->db2_colorimetry = 0;
702 avi_cfg->db2_aspect_ratio = 0;
703 avi_cfg->db2_active_fmt_ar = 0;
704 avi_cfg->db3_itc = 0;
705 avi_cfg->db3_ec = 0;
706 avi_cfg->db3_q_range = 0;
707 avi_cfg->db3_nup_scaling = 0;
708 avi_cfg->db4_videocode = 0;
709 avi_cfg->db5_pixel_repeat = 0;
710 avi_cfg->db6_7_line_eoftop = 0 ;
711 avi_cfg->db8_9_line_sofbottom = 0;
712 avi_cfg->db10_11_pixel_eofleft = 0;
713 avi_cfg->db12_13_pixel_sofright = 0;
714
715 /* packet enable and repeat */
716 repeat_cfg->audio_pkt = 0;
717 repeat_cfg->audio_pkt_repeat = 0;
718 repeat_cfg->avi_infoframe = 0;
719 repeat_cfg->avi_infoframe_repeat = 0;
720 repeat_cfg->gen_cntrl_pkt = 0;
721 repeat_cfg->gen_cntrl_pkt_repeat = 0;
722 repeat_cfg->generic_pkt = 0;
723 repeat_cfg->generic_pkt_repeat = 0;
724}
725
726static void hdmi_core_powerdown_disable(void)
727{
728 DSSDBG("Enter hdmi_core_powerdown_disable\n");
729 REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0);
730}
731
732static void hdmi_core_swreset_release(void)
733{
734 DSSDBG("Enter hdmi_core_swreset_release\n");
735 REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0);
736}
737
738static void hdmi_core_swreset_assert(void)
739{
740 DSSDBG("Enter hdmi_core_swreset_assert\n");
741 REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0);
742}
743
744/* DSS_HDMI_CORE_VIDEO_CONFIG */
745static void hdmi_core_video_config(struct hdmi_core_video_config *cfg)
746{
747 u32 r = 0;
748
749 /* sys_ctrl1 default configuration not tunable */
750 r = hdmi_read_reg(HDMI_CORE_CTRL1);
751 r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
752 r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
753 r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
754 r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
755 hdmi_write_reg(HDMI_CORE_CTRL1, r);
756
757 REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
758
759 /* Vid_Mode */
760 r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE);
761
762 /* dither truncation configuration */
763 if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
764 r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
765 r = FLD_MOD(r, 1, 5, 5);
766 } else {
767 r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
768 r = FLD_MOD(r, 0, 5, 5);
769 }
770 hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r);
771
772 /* HDMI_Ctrl */
773 r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL);
774 r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
775 r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
776 r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
777 hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r);
778
779 /* TMDS_CTRL */
780 REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL,
781 cfg->tclk_sel_clkmult, 6, 5);
782}
783
784static void hdmi_core_aux_infoframe_avi_config(
785 struct hdmi_core_infoframe_avi info_avi)
786{
787 u32 val;
788 char sum = 0, checksum = 0;
789
790 sum += 0x82 + 0x002 + 0x00D;
791 hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082);
792 hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002);
793 hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D);
794
795 val = (info_avi.db1_format << 5) |
796 (info_avi.db1_active_info << 4) |
797 (info_avi.db1_bar_info_dv << 2) |
798 (info_avi.db1_scan_info);
799 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val);
800 sum += val;
801
802 val = (info_avi.db2_colorimetry << 6) |
803 (info_avi.db2_aspect_ratio << 4) |
804 (info_avi.db2_active_fmt_ar);
805 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val);
806 sum += val;
807
808 val = (info_avi.db3_itc << 7) |
809 (info_avi.db3_ec << 4) |
810 (info_avi.db3_q_range << 2) |
811 (info_avi.db3_nup_scaling);
812 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val);
813 sum += val;
814
815 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode);
816 sum += info_avi.db4_videocode;
817
818 val = info_avi.db5_pixel_repeat;
819 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val);
820 sum += val;
821
822 val = info_avi.db6_7_line_eoftop & 0x00FF;
823 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val);
824 sum += val;
825
826 val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
827 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val);
828 sum += val;
829
830 val = info_avi.db8_9_line_sofbottom & 0x00FF;
831 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val);
832 sum += val;
833
834 val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
835 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val);
836 sum += val;
837
838 val = info_avi.db10_11_pixel_eofleft & 0x00FF;
839 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val);
840 sum += val;
841
842 val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
843 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val);
844 sum += val;
845
846 val = info_avi.db12_13_pixel_sofright & 0x00FF;
847 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val);
848 sum += val;
849
850 val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
851 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val);
852 sum += val;
853
854 checksum = 0x100 - sum;
855 hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum);
856}
857
858static void hdmi_core_av_packet_config(
859 struct hdmi_core_packet_enable_repeat repeat_cfg)
860{
861 /* enable/repeat the infoframe */
862 hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1,
863 (repeat_cfg.audio_pkt << 5) |
864 (repeat_cfg.audio_pkt_repeat << 4) |
865 (repeat_cfg.avi_infoframe << 1) |
866 (repeat_cfg.avi_infoframe_repeat));
867
868 /* enable/repeat the packet */
869 hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2,
870 (repeat_cfg.gen_cntrl_pkt << 3) |
871 (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
872 (repeat_cfg.generic_pkt << 1) |
873 (repeat_cfg.generic_pkt_repeat));
874}
875
876static void hdmi_wp_init(struct omap_video_timings *timings,
877 struct hdmi_video_format *video_fmt,
878 struct hdmi_video_interface *video_int)
879{
880 DSSDBG("Enter hdmi_wp_init\n");
881
882 timings->hbp = 0;
883 timings->hfp = 0;
884 timings->hsw = 0;
885 timings->vbp = 0;
886 timings->vfp = 0;
887 timings->vsw = 0;
888
889 video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
890 video_fmt->y_res = 0;
891 video_fmt->x_res = 0;
892
893 video_int->vsp = 0;
894 video_int->hsp = 0;
895
896 video_int->interlacing = 0;
897 video_int->tm = 0; /* HDMI_TIMING_SLAVE */
898
899}
900
901static void hdmi_wp_video_start(bool start)
902{
903 REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31);
904}
905
906static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
907 struct omap_video_timings *timings, struct hdmi_config *param)
908{
909 DSSDBG("Enter hdmi_wp_video_init_format\n");
910
911 video_fmt->y_res = param->timings.timings.y_res;
912 video_fmt->x_res = param->timings.timings.x_res;
913
914 timings->hbp = param->timings.timings.hbp;
915 timings->hfp = param->timings.timings.hfp;
916 timings->hsw = param->timings.timings.hsw;
917 timings->vbp = param->timings.timings.vbp;
918 timings->vfp = param->timings.timings.vfp;
919 timings->vsw = param->timings.timings.vsw;
920}
921
922static void hdmi_wp_video_config_format(
923 struct hdmi_video_format *video_fmt)
924{
925 u32 l = 0;
926
927 REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8);
928
929 l |= FLD_VAL(video_fmt->y_res, 31, 16);
930 l |= FLD_VAL(video_fmt->x_res, 15, 0);
931 hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l);
932}
933
934static void hdmi_wp_video_config_interface(
935 struct hdmi_video_interface *video_int)
936{
937 u32 r;
938 DSSDBG("Enter hdmi_wp_video_config_interface\n");
939
940 r = hdmi_read_reg(HDMI_WP_VIDEO_CFG);
941 r = FLD_MOD(r, video_int->vsp, 7, 7);
942 r = FLD_MOD(r, video_int->hsp, 6, 6);
943 r = FLD_MOD(r, video_int->interlacing, 3, 3);
944 r = FLD_MOD(r, video_int->tm, 1, 0);
945 hdmi_write_reg(HDMI_WP_VIDEO_CFG, r);
946}
947
948static void hdmi_wp_video_config_timing(
949 struct omap_video_timings *timings)
950{
951 u32 timing_h = 0;
952 u32 timing_v = 0;
953
954 DSSDBG("Enter hdmi_wp_video_config_timing\n");
955
956 timing_h |= FLD_VAL(timings->hbp, 31, 20);
957 timing_h |= FLD_VAL(timings->hfp, 19, 8);
958 timing_h |= FLD_VAL(timings->hsw, 7, 0);
959 hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h);
960
961 timing_v |= FLD_VAL(timings->vbp, 31, 20);
962 timing_v |= FLD_VAL(timings->vfp, 19, 8);
963 timing_v |= FLD_VAL(timings->vsw, 7, 0);
964 hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v);
965}
966
967static void hdmi_basic_configure(struct hdmi_config *cfg)
968{
969 /* HDMI */
970 struct omap_video_timings video_timing;
971 struct hdmi_video_format video_format;
972 struct hdmi_video_interface video_interface;
973 /* HDMI core */
974 struct hdmi_core_infoframe_avi avi_cfg;
975 struct hdmi_core_video_config v_core_cfg;
976 struct hdmi_core_packet_enable_repeat repeat_cfg;
977
978 hdmi_wp_init(&video_timing, &video_format,
979 &video_interface);
980
981 hdmi_core_init(&v_core_cfg,
982 &avi_cfg,
983 &repeat_cfg);
984
985 hdmi_wp_video_init_format(&video_format,
986 &video_timing, cfg);
987
988 hdmi_wp_video_config_timing(&video_timing);
989
990 /* video config */
991 video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
992
993 hdmi_wp_video_config_format(&video_format);
994
995 video_interface.vsp = cfg->timings.vsync_pol;
996 video_interface.hsp = cfg->timings.hsync_pol;
997 video_interface.interlacing = cfg->interlace;
998 video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
999
1000 hdmi_wp_video_config_interface(&video_interface);
1001
1002 /*
1003 * configure core video part
1004 * set software reset in the core
1005 */
1006 hdmi_core_swreset_assert();
1007
1008 /* power down off */
1009 hdmi_core_powerdown_disable();
1010
1011 v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
1012 v_core_cfg.hdmi_dvi = cfg->cm.mode;
1013
1014 hdmi_core_video_config(&v_core_cfg);
1015
1016 /* release software reset in the core */
1017 hdmi_core_swreset_release();
1018
1019 /*
1020 * configure packet
1021 * info frame video see doc CEA861-D page 65
1022 */
1023 avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
1024 avi_cfg.db1_active_info =
1025 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
1026 avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
1027 avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
1028 avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
1029 avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
1030 avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
1031 avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
1032 avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
1033 avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
1034 avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
1035 avi_cfg.db4_videocode = cfg->cm.code;
1036 avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
1037 avi_cfg.db6_7_line_eoftop = 0;
1038 avi_cfg.db8_9_line_sofbottom = 0;
1039 avi_cfg.db10_11_pixel_eofleft = 0;
1040 avi_cfg.db12_13_pixel_sofright = 0;
1041
1042 hdmi_core_aux_infoframe_avi_config(avi_cfg);
1043
1044 /* enable/repeat the infoframe */
1045 repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
1046 repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
1047 /* wakeup */
1048 repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
1049 repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
1050 hdmi_core_av_packet_config(repeat_cfg);
1051}
1052
1053static void update_hdmi_timings(struct hdmi_config *cfg, 253static void update_hdmi_timings(struct hdmi_config *cfg,
1054 struct omap_video_timings *timings, int code) 254 struct omap_video_timings *timings, int code)
1055{ 255{
@@ -1066,6 +266,12 @@ static void update_hdmi_timings(struct hdmi_config *cfg,
1066 cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; 266 cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol;
1067} 267}
1068 268
269unsigned long hdmi_get_pixel_clock(void)
270{
271 /* HDMI Pixel Clock in Mhz */
272 return hdmi.ip_data.cfg.timings.timings.pixel_clock * 10000;
273}
274
1069static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, 275static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
1070 struct hdmi_pll_info *pi) 276 struct hdmi_pll_info *pi)
1071{ 277{
@@ -1077,15 +283,23 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
1077 * Input clock is predivided by N + 1 283 * Input clock is predivided by N + 1
1078 * out put of which is reference clk 284 * out put of which is reference clk
1079 */ 285 */
1080 pi->regn = dssdev->clocks.hdmi.regn; 286 if (dssdev->clocks.hdmi.regn == 0)
1081 refclk = clkin / (pi->regn + 1); 287 pi->regn = HDMI_DEFAULT_REGN;
288 else
289 pi->regn = dssdev->clocks.hdmi.regn;
290
291 refclk = clkin / pi->regn;
1082 292
1083 /* 293 /*
1084 * multiplier is pixel_clk/ref_clk 294 * multiplier is pixel_clk/ref_clk
1085 * Multiplying by 100 to avoid fractional part removal 295 * Multiplying by 100 to avoid fractional part removal
1086 */ 296 */
1087 pi->regm = (phy * 100 / (refclk)) / 100; 297 pi->regm = (phy * 100 / (refclk)) / 100;
1088 pi->regm2 = dssdev->clocks.hdmi.regm2; 298
299 if (dssdev->clocks.hdmi.regm2 == 0)
300 pi->regm2 = HDMI_DEFAULT_REGM2;
301 else
302 pi->regm2 = dssdev->clocks.hdmi.regm2;
1089 303
1090 /* 304 /*
1091 * fractional multiplier is remainder of the difference between 305 * fractional multiplier is remainder of the difference between
@@ -1100,7 +314,10 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
1100 * is greater than 1000MHz 314 * is greater than 1000MHz
1101 */ 315 */
1102 pi->dcofreq = phy > 1000 * 100; 316 pi->dcofreq = phy > 1000 * 100;
1103 pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10; 317 pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
318
319 /* Set the reference clock to sysclk reference */
320 pi->refsel = HDMI_REFSEL_SYSCLK;
1104 321
1105 DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); 322 DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
1106 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); 323 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
@@ -1109,7 +326,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
1109static int hdmi_power_on(struct omap_dss_device *dssdev) 326static int hdmi_power_on(struct omap_dss_device *dssdev)
1110{ 327{
1111 int r, code = 0; 328 int r, code = 0;
1112 struct hdmi_pll_info pll_data;
1113 struct omap_video_timings *p; 329 struct omap_video_timings *p;
1114 unsigned long phy; 330 unsigned long phy;
1115 331
@@ -1117,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
1117 if (r) 333 if (r)
1118 return r; 334 return r;
1119 335
1120 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); 336 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);
1121 337
1122 p = &dssdev->panel.timings; 338 p = &dssdev->panel.timings;
1123 339
@@ -1125,36 +341,31 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
1125 dssdev->panel.timings.x_res, 341 dssdev->panel.timings.x_res,
1126 dssdev->panel.timings.y_res); 342 dssdev->panel.timings.y_res);
1127 343
1128 if (!hdmi.custom_set) {
1129 DSSDBG("Read EDID as no EDID is not set on poweron\n");
1130 hdmi_read_edid(p);
1131 }
1132 code = get_timings_index(); 344 code = get_timings_index();
1133 dssdev->panel.timings = cea_vesa_timings[code].timings; 345 update_hdmi_timings(&hdmi.ip_data.cfg, p, code);
1134 update_hdmi_timings(&hdmi.cfg, p, code);
1135 346
1136 phy = p->pixel_clock; 347 phy = p->pixel_clock;
1137 348
1138 hdmi_compute_pll(dssdev, phy, &pll_data); 349 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
1139 350
1140 hdmi_wp_video_start(0); 351 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
1141 352
1142 /* config the PLL and PHY first */ 353 /* config the PLL and PHY hdmi_set_pll_pwrfirst */
1143 r = hdmi_pll_program(&pll_data); 354 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
1144 if (r) { 355 if (r) {
1145 DSSDBG("Failed to lock PLL\n"); 356 DSSDBG("Failed to lock PLL\n");
1146 goto err; 357 goto err;
1147 } 358 }
1148 359
1149 r = hdmi_phy_init(); 360 r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
1150 if (r) { 361 if (r) {
1151 DSSDBG("Failed to start PHY\n"); 362 DSSDBG("Failed to start PHY\n");
1152 goto err; 363 goto err;
1153 } 364 }
1154 365
1155 hdmi.cfg.cm.mode = hdmi.mode; 366 hdmi.ip_data.cfg.cm.mode = hdmi.mode;
1156 hdmi.cfg.cm.code = hdmi.code; 367 hdmi.ip_data.cfg.cm.code = hdmi.code;
1157 hdmi_basic_configure(&hdmi.cfg); 368 hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
1158 369
1159 /* Make selection of HDMI in DSS */ 370 /* Make selection of HDMI in DSS */
1160 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); 371 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
@@ -1174,9 +385,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
1174 dispc_set_digit_size(dssdev->panel.timings.x_res, 385 dispc_set_digit_size(dssdev->panel.timings.x_res,
1175 dssdev->panel.timings.y_res); 386 dssdev->panel.timings.y_res);
1176 387
1177 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1); 388 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1);
1178 389
1179 hdmi_wp_video_start(1); 390 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1);
1180 391
1181 return 0; 392 return 0;
1182err: 393err:
@@ -1186,14 +397,12 @@ err:
1186 397
1187static void hdmi_power_off(struct omap_dss_device *dssdev) 398static void hdmi_power_off(struct omap_dss_device *dssdev)
1188{ 399{
1189 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); 400 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);
1190 401
1191 hdmi_wp_video_start(0); 402 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
1192 hdmi_phy_off(); 403 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
1193 hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); 404 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
1194 hdmi_runtime_put(); 405 hdmi_runtime_put();
1195
1196 hdmi.edid_set = 0;
1197} 406}
1198 407
1199int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 408int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -1203,7 +412,6 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
1203 412
1204 cm = hdmi_get_code(timings); 413 cm = hdmi_get_code(timings);
1205 if (cm.code == -1) { 414 if (cm.code == -1) {
1206 DSSERR("Invalid timing entered\n");
1207 return -EINVAL; 415 return -EINVAL;
1208 } 416 }
1209 417
@@ -1215,12 +423,69 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
1215{ 423{
1216 struct hdmi_cm cm; 424 struct hdmi_cm cm;
1217 425
1218 hdmi.custom_set = 1;
1219 cm = hdmi_get_code(&dssdev->panel.timings); 426 cm = hdmi_get_code(&dssdev->panel.timings);
1220 hdmi.code = cm.code; 427 hdmi.code = cm.code;
1221 hdmi.mode = cm.mode; 428 hdmi.mode = cm.mode;
1222 omapdss_hdmi_display_enable(dssdev); 429
1223 hdmi.custom_set = 0; 430 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
431 int r;
432
433 hdmi_power_off(dssdev);
434
435 r = hdmi_power_on(dssdev);
436 if (r)
437 DSSERR("failed to power on device\n");
438 }
439}
440
441void hdmi_dump_regs(struct seq_file *s)
442{
443 mutex_lock(&hdmi.lock);
444
445 if (hdmi_runtime_get())
446 return;
447
448 hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
449 hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
450 hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s);
451 hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s);
452
453 hdmi_runtime_put();
454 mutex_unlock(&hdmi.lock);
455}
456
457int omapdss_hdmi_read_edid(u8 *buf, int len)
458{
459 int r;
460
461 mutex_lock(&hdmi.lock);
462
463 r = hdmi_runtime_get();
464 BUG_ON(r);
465
466 r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);
467
468 hdmi_runtime_put();
469 mutex_unlock(&hdmi.lock);
470
471 return r;
472}
473
474bool omapdss_hdmi_detect(void)
475{
476 int r;
477
478 mutex_lock(&hdmi.lock);
479
480 r = hdmi_runtime_get();
481 BUG_ON(r);
482
483 r = hdmi.ip_data.ops->detect(&hdmi.ip_data);
484
485 hdmi_runtime_put();
486 mutex_unlock(&hdmi.lock);
487
488 return r == 1;
1224} 489}
1225 490
1226int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) 491int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
@@ -1231,6 +496,12 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
1231 496
1232 mutex_lock(&hdmi.lock); 497 mutex_lock(&hdmi.lock);
1233 498
499 if (dssdev->manager == NULL) {
500 DSSERR("failed to enable display: no manager\n");
501 r = -ENODEV;
502 goto err0;
503 }
504
1234 r = omap_dss_start_device(dssdev); 505 r = omap_dss_start_device(dssdev);
1235 if (r) { 506 if (r) {
1236 DSSERR("failed to start device\n"); 507 DSSERR("failed to start device\n");
@@ -1282,219 +553,9 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
1282 553
1283#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 554#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
1284 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 555 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1285static void hdmi_wp_audio_config_format(
1286 struct hdmi_audio_format *aud_fmt)
1287{
1288 u32 r;
1289
1290 DSSDBG("Enter hdmi_wp_audio_config_format\n");
1291
1292 r = hdmi_read_reg(HDMI_WP_AUDIO_CFG);
1293 r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
1294 r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
1295 r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
1296 r = FLD_MOD(r, aud_fmt->type, 4, 4);
1297 r = FLD_MOD(r, aud_fmt->justification, 3, 3);
1298 r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
1299 r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
1300 r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
1301 hdmi_write_reg(HDMI_WP_AUDIO_CFG, r);
1302}
1303
1304static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma)
1305{
1306 u32 r;
1307
1308 DSSDBG("Enter hdmi_wp_audio_config_dma\n");
1309
1310 r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2);
1311 r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
1312 r = FLD_MOD(r, aud_dma->block_size, 7, 0);
1313 hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r);
1314
1315 r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL);
1316 r = FLD_MOD(r, aud_dma->mode, 9, 9);
1317 r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
1318 hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r);
1319}
1320
1321static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg)
1322{
1323 u32 r;
1324
1325 /* audio clock recovery parameters */
1326 r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL);
1327 r = FLD_MOD(r, cfg->use_mclk, 2, 2);
1328 r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
1329 r = FLD_MOD(r, cfg->cts_mode, 0, 0);
1330 hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r);
1331
1332 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
1333 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
1334 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
1335
1336 if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
1337 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
1338 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
1339 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
1340 } else {
1341 /*
1342 * HDMI IP uses this configuration to divide the MCLK to
1343 * update CTS value.
1344 */
1345 REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
1346
1347 /* Configure clock for audio packets */
1348 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
1349 cfg->aud_par_busclk, 7, 0);
1350 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
1351 (cfg->aud_par_busclk >> 8), 7, 0);
1352 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
1353 (cfg->aud_par_busclk >> 16), 7, 0);
1354 }
1355
1356 /* Override of SPDIF sample frequency with value in I2S_CHST4 */
1357 REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1);
1358
1359 /* I2S parameters */
1360 REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0);
1361
1362 r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL);
1363 r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
1364 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
1365 r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
1366 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
1367 r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
1368 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
1369 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
1370 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
1371 hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r);
1372
1373 r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5);
1374 r = FLD_MOD(r, cfg->freq_sample, 7, 4);
1375 r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
1376 r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
1377 hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r);
1378
1379 REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0);
1380
1381 /* Audio channels and mode parameters */
1382 REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
1383 r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE);
1384 r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
1385 r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
1386 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
1387 r = FLD_MOD(r, cfg->en_spdif, 1, 1);
1388 hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r);
1389}
1390
1391static void hdmi_core_audio_infoframe_config(
1392 struct hdmi_core_infoframe_audio *info_aud)
1393{
1394 u8 val;
1395 u8 sum = 0, checksum = 0;
1396
1397 /*
1398 * Set audio info frame type, version and length as
1399 * described in HDMI 1.4a Section 8.2.2 specification.
1400 * Checksum calculation is defined in Section 5.3.5.
1401 */
1402 hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84);
1403 hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01);
1404 hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a);
1405 sum += 0x84 + 0x001 + 0x00a;
1406
1407 val = (info_aud->db1_coding_type << 4)
1408 | (info_aud->db1_channel_count - 1);
1409 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val);
1410 sum += val;
1411
1412 val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
1413 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val);
1414 sum += val;
1415
1416 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
1417
1418 val = info_aud->db4_channel_alloc;
1419 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val);
1420 sum += val;
1421
1422 val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
1423 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val);
1424 sum += val;
1425
1426 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
1427 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
1428 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
1429 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
1430 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
1431 556
1432 checksum = 0x100 - sum; 557static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data,
1433 hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum); 558 struct snd_pcm_substream *substream,
1434
1435 /*
1436 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
1437 * is available.
1438 */
1439}
1440
1441static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
1442{
1443 u32 r;
1444 u32 deep_color = 0;
1445 u32 pclk = hdmi.cfg.timings.timings.pixel_clock;
1446
1447 if (n == NULL || cts == NULL)
1448 return -EINVAL;
1449 /*
1450 * Obtain current deep color configuration. This needed
1451 * to calculate the TMDS clock based on the pixel clock.
1452 */
1453 r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0);
1454 switch (r) {
1455 case 1: /* No deep color selected */
1456 deep_color = 100;
1457 break;
1458 case 2: /* 10-bit deep color selected */
1459 deep_color = 125;
1460 break;
1461 case 3: /* 12-bit deep color selected */
1462 deep_color = 150;
1463 break;
1464 default:
1465 return -EINVAL;
1466 }
1467
1468 switch (sample_freq) {
1469 case 32000:
1470 if ((deep_color == 125) && ((pclk == 54054)
1471 || (pclk == 74250)))
1472 *n = 8192;
1473 else
1474 *n = 4096;
1475 break;
1476 case 44100:
1477 *n = 6272;
1478 break;
1479 case 48000:
1480 if ((deep_color == 125) && ((pclk == 54054)
1481 || (pclk == 74250)))
1482 *n = 8192;
1483 else
1484 *n = 6144;
1485 break;
1486 default:
1487 *n = 0;
1488 return -EINVAL;
1489 }
1490
1491 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
1492 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
1493
1494 return 0;
1495}
1496
1497static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
1498 struct snd_pcm_hw_params *params, 559 struct snd_pcm_hw_params *params,
1499 struct snd_soc_dai *dai) 560 struct snd_soc_dai *dai)
1500{ 561{
@@ -1548,7 +609,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
1548 return -EINVAL; 609 return -EINVAL;
1549 } 610 }
1550 611
1551 err = hdmi_config_audio_acr(params_rate(params), &n, &cts); 612 err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts);
1552 if (err < 0) 613 if (err < 0)
1553 return err; 614 return err;
1554 615
@@ -1564,8 +625,8 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
1564 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; 625 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
1565 audio_dma.fifo_threshold = 0x20; /* in number of samples */ 626 audio_dma.fifo_threshold = 0x20; /* in number of samples */
1566 627
1567 hdmi_wp_audio_config_dma(&audio_dma); 628 hdmi_wp_audio_config_dma(ip_data, &audio_dma);
1568 hdmi_wp_audio_config_format(&audio_format); 629 hdmi_wp_audio_config_format(ip_data, &audio_format);
1569 630
1570 /* 631 /*
1571 * I2S config 632 * I2S config
@@ -1609,7 +670,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
1609 /* Use parallel audio interface */ 670 /* Use parallel audio interface */
1610 core_cfg.en_parallel_aud_input = true; 671 core_cfg.en_parallel_aud_input = true;
1611 672
1612 hdmi_core_audio_config(&core_cfg); 673 hdmi_core_audio_config(ip_data, &core_cfg);
1613 674
1614 /* 675 /*
1615 * Configure packet 676 * Configure packet
@@ -1623,36 +684,10 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
1623 aud_if_cfg.db5_downmix_inh = false; 684 aud_if_cfg.db5_downmix_inh = false;
1624 aud_if_cfg.db5_lsv = 0; 685 aud_if_cfg.db5_lsv = 0;
1625 686
1626 hdmi_core_audio_infoframe_config(&aud_if_cfg); 687 hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg);
1627 return 0; 688 return 0;
1628} 689}
1629 690
1630static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
1631 struct snd_soc_dai *dai)
1632{
1633 int err = 0;
1634 switch (cmd) {
1635 case SNDRV_PCM_TRIGGER_START:
1636 case SNDRV_PCM_TRIGGER_RESUME:
1637 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1638 REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
1639 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31);
1640 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30);
1641 break;
1642
1643 case SNDRV_PCM_TRIGGER_STOP:
1644 case SNDRV_PCM_TRIGGER_SUSPEND:
1645 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1646 REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
1647 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30);
1648 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31);
1649 break;
1650 default:
1651 err = -EINVAL;
1652 }
1653 return err;
1654}
1655
1656static int hdmi_audio_startup(struct snd_pcm_substream *substream, 691static int hdmi_audio_startup(struct snd_pcm_substream *substream,
1657 struct snd_soc_dai *dai) 692 struct snd_soc_dai *dai)
1658{ 693{
@@ -1698,15 +733,6 @@ static int hdmi_get_clocks(struct platform_device *pdev)
1698 733
1699 hdmi.sys_clk = clk; 734 hdmi.sys_clk = clk;
1700 735
1701 clk = clk_get(&pdev->dev, "dss_48mhz_clk");
1702 if (IS_ERR(clk)) {
1703 DSSERR("can't get hdmi_clk\n");
1704 clk_put(hdmi.sys_clk);
1705 return PTR_ERR(clk);
1706 }
1707
1708 hdmi.hdmi_clk = clk;
1709
1710 return 0; 736 return 0;
1711} 737}
1712 738
@@ -1714,8 +740,6 @@ static void hdmi_put_clocks(void)
1714{ 740{
1715 if (hdmi.sys_clk) 741 if (hdmi.sys_clk)
1716 clk_put(hdmi.sys_clk); 742 clk_put(hdmi.sys_clk);
1717 if (hdmi.hdmi_clk)
1718 clk_put(hdmi.hdmi_clk);
1719} 743}
1720 744
1721/* HDMI HW IP initialisation */ 745/* HDMI HW IP initialisation */
@@ -1736,20 +760,26 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
1736 } 760 }
1737 761
1738 /* Base address taken from platform */ 762 /* Base address taken from platform */
1739 hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem)); 763 hdmi.ip_data.base_wp = ioremap(hdmi_mem->start,
1740 if (!hdmi.base_wp) { 764 resource_size(hdmi_mem));
765 if (!hdmi.ip_data.base_wp) {
1741 DSSERR("can't ioremap WP\n"); 766 DSSERR("can't ioremap WP\n");
1742 return -ENOMEM; 767 return -ENOMEM;
1743 } 768 }
1744 769
1745 r = hdmi_get_clocks(pdev); 770 r = hdmi_get_clocks(pdev);
1746 if (r) { 771 if (r) {
1747 iounmap(hdmi.base_wp); 772 iounmap(hdmi.ip_data.base_wp);
1748 return r; 773 return r;
1749 } 774 }
1750 775
1751 pm_runtime_enable(&pdev->dev); 776 pm_runtime_enable(&pdev->dev);
1752 777
778 hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS;
779 hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
780 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
781 hdmi.ip_data.phy_offset = HDMI_PHY;
782
1753 hdmi_panel_init(); 783 hdmi_panel_init();
1754 784
1755#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 785#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
@@ -1779,14 +809,13 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
1779 809
1780 hdmi_put_clocks(); 810 hdmi_put_clocks();
1781 811
1782 iounmap(hdmi.base_wp); 812 iounmap(hdmi.ip_data.base_wp);
1783 813
1784 return 0; 814 return 0;
1785} 815}
1786 816
1787static int hdmi_runtime_suspend(struct device *dev) 817static int hdmi_runtime_suspend(struct device *dev)
1788{ 818{
1789 clk_disable(hdmi.hdmi_clk);
1790 clk_disable(hdmi.sys_clk); 819 clk_disable(hdmi.sys_clk);
1791 820
1792 dispc_runtime_put(); 821 dispc_runtime_put();
@@ -1809,7 +838,6 @@ static int hdmi_runtime_resume(struct device *dev)
1809 838
1810 839
1811 clk_enable(hdmi.sys_clk); 840 clk_enable(hdmi.sys_clk);
1812 clk_enable(hdmi.hdmi_clk);
1813 841
1814 return 0; 842 return 0;
1815 843
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index 7d4f2bd7c50..533d5dc634d 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * hdmi_omap4_panel.c 2 * hdmi_panel.c
3 * 3 *
4 * HDMI library support functions for TI OMAP4 processors. 4 * HDMI library support functions for TI OMAP4 processors.
5 * 5 *
@@ -25,6 +25,7 @@
25#include <linux/mutex.h> 25#include <linux/mutex.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <video/omapdss.h> 27#include <video/omapdss.h>
28#include <linux/slab.h>
28 29
29#include "dss.h" 30#include "dss.h"
30 31
@@ -40,13 +41,7 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev)
40 dssdev->panel.config = OMAP_DSS_LCD_TFT | 41 dssdev->panel.config = OMAP_DSS_LCD_TFT |
41 OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; 42 OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS;
42 43
43 /* 44 dssdev->panel.timings = (struct omap_video_timings){640, 480, 25175, 96, 16, 48, 2 , 11, 31};
44 * Initialize the timings to 640 * 480
45 * This is only for framebuffer update not for TV timing setting
46 * Setting TV timing will be done only on enable
47 */
48 dssdev->panel.timings.x_res = 640;
49 dssdev->panel.timings.y_res = 480;
50 45
51 DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", 46 DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
52 dssdev->panel.timings.x_res, 47 dssdev->panel.timings.x_res,
@@ -161,12 +156,7 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
161 mutex_lock(&hdmi.hdmi_lock); 156 mutex_lock(&hdmi.hdmi_lock);
162 157
163 dssdev->panel.timings = *timings; 158 dssdev->panel.timings = *timings;
164 159 omapdss_hdmi_display_set_timing(dssdev);
165 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
166 /* turn the hdmi off and on to get new timings to use */
167 omapdss_hdmi_display_disable(dssdev);
168 omapdss_hdmi_display_set_timing(dssdev);
169 }
170 160
171 mutex_unlock(&hdmi.hdmi_lock); 161 mutex_unlock(&hdmi.hdmi_lock);
172} 162}
@@ -181,12 +171,54 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
181 mutex_lock(&hdmi.hdmi_lock); 171 mutex_lock(&hdmi.hdmi_lock);
182 172
183 r = omapdss_hdmi_display_check_timing(dssdev, timings); 173 r = omapdss_hdmi_display_check_timing(dssdev, timings);
184 if (r) { 174
185 DSSERR("Timing cannot be applied\n"); 175 mutex_unlock(&hdmi.hdmi_lock);
186 goto err; 176 return r;
177}
178
179static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
180{
181 int r;
182
183 mutex_lock(&hdmi.hdmi_lock);
184
185 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
186 r = omapdss_hdmi_display_enable(dssdev);
187 if (r)
188 goto err;
189 }
190
191 r = omapdss_hdmi_read_edid(buf, len);
192
193 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
194 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
195 omapdss_hdmi_display_disable(dssdev);
196err:
197 mutex_unlock(&hdmi.hdmi_lock);
198
199 return r;
200}
201
202static bool hdmi_detect(struct omap_dss_device *dssdev)
203{
204 int r;
205
206 mutex_lock(&hdmi.hdmi_lock);
207
208 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
209 r = omapdss_hdmi_display_enable(dssdev);
210 if (r)
211 goto err;
187 } 212 }
213
214 r = omapdss_hdmi_detect();
215
216 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
217 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
218 omapdss_hdmi_display_disable(dssdev);
188err: 219err:
189 mutex_unlock(&hdmi.hdmi_lock); 220 mutex_unlock(&hdmi.hdmi_lock);
221
190 return r; 222 return r;
191} 223}
192 224
@@ -200,6 +232,8 @@ static struct omap_dss_driver hdmi_driver = {
200 .get_timings = hdmi_get_timings, 232 .get_timings = hdmi_get_timings,
201 .set_timings = hdmi_set_timings, 233 .set_timings = hdmi_set_timings,
202 .check_timings = hdmi_check_timings, 234 .check_timings = hdmi_check_timings,
235 .read_edid = hdmi_read_edid,
236 .detect = hdmi_detect,
203 .driver = { 237 .driver = {
204 .name = "hdmi_panel", 238 .name = "hdmi_panel",
205 .owner = THIS_MODULE, 239 .owner = THIS_MODULE,
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 13d72d5c714..6e63845cc7d 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -106,7 +106,7 @@ put_device:
106static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, 106static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
107 char *buf) 107 char *buf)
108{ 108{
109 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color); 109 return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color);
110} 110}
111 111
112static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, 112static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
@@ -116,8 +116,9 @@ static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
116 u32 color; 116 u32 color;
117 int r; 117 int r;
118 118
119 if (sscanf(buf, "%d", &color) != 1) 119 r = kstrtouint(buf, 0, &color);
120 return -EINVAL; 120 if (r)
121 return r;
121 122
122 mgr->get_manager_info(mgr, &info); 123 mgr->get_manager_info(mgr, &info);
123 124
@@ -184,7 +185,7 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
184static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, 185static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
185 char *buf) 186 char *buf)
186{ 187{
187 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key); 188 return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key);
188} 189}
189 190
190static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, 191static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
@@ -194,8 +195,9 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
194 u32 key_value; 195 u32 key_value;
195 int r; 196 int r;
196 197
197 if (sscanf(buf, "%d", &key_value) != 1) 198 r = kstrtouint(buf, 0, &key_value);
198 return -EINVAL; 199 if (r)
200 return r;
199 201
200 mgr->get_manager_info(mgr, &info); 202 mgr->get_manager_info(mgr, &info);
201 203
@@ -222,15 +224,16 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
222 const char *buf, size_t size) 224 const char *buf, size_t size)
223{ 225{
224 struct omap_overlay_manager_info info; 226 struct omap_overlay_manager_info info;
225 int enable; 227 bool enable;
226 int r; 228 int r;
227 229
228 if (sscanf(buf, "%d", &enable) != 1) 230 r = strtobool(buf, &enable);
229 return -EINVAL; 231 if (r)
232 return r;
230 233
231 mgr->get_manager_info(mgr, &info); 234 mgr->get_manager_info(mgr, &info);
232 235
233 info.trans_enabled = enable ? true : false; 236 info.trans_enabled = enable;
234 237
235 r = mgr->set_manager_info(mgr, &info); 238 r = mgr->set_manager_info(mgr, &info);
236 if (r) 239 if (r)
@@ -246,7 +249,10 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
246static ssize_t manager_alpha_blending_enabled_show( 249static ssize_t manager_alpha_blending_enabled_show(
247 struct omap_overlay_manager *mgr, char *buf) 250 struct omap_overlay_manager *mgr, char *buf)
248{ 251{
249 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled); 252 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
253
254 return snprintf(buf, PAGE_SIZE, "%d\n",
255 mgr->info.partial_alpha_enabled);
250} 256}
251 257
252static ssize_t manager_alpha_blending_enabled_store( 258static ssize_t manager_alpha_blending_enabled_store(
@@ -254,15 +260,18 @@ static ssize_t manager_alpha_blending_enabled_store(
254 const char *buf, size_t size) 260 const char *buf, size_t size)
255{ 261{
256 struct omap_overlay_manager_info info; 262 struct omap_overlay_manager_info info;
257 int enable; 263 bool enable;
258 int r; 264 int r;
259 265
260 if (sscanf(buf, "%d", &enable) != 1) 266 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
261 return -EINVAL; 267
268 r = strtobool(buf, &enable);
269 if (r)
270 return r;
262 271
263 mgr->get_manager_info(mgr, &info); 272 mgr->get_manager_info(mgr, &info);
264 273
265 info.alpha_enabled = enable ? true : false; 274 info.partial_alpha_enabled = enable;
266 275
267 r = mgr->set_manager_info(mgr, &info); 276 r = mgr->set_manager_info(mgr, &info);
268 if (r) 277 if (r)
@@ -285,19 +294,16 @@ static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
285 const char *buf, size_t size) 294 const char *buf, size_t size)
286{ 295{
287 struct omap_overlay_manager_info info; 296 struct omap_overlay_manager_info info;
288 int v;
289 int r; 297 int r;
290 bool enable; 298 bool enable;
291 299
292 if (!dss_has_feature(FEAT_CPR)) 300 if (!dss_has_feature(FEAT_CPR))
293 return -ENODEV; 301 return -ENODEV;
294 302
295 r = kstrtoint(buf, 0, &v); 303 r = strtobool(buf, &enable);
296 if (r) 304 if (r)
297 return r; 305 return r;
298 306
299 enable = !!v;
300
301 mgr->get_manager_info(mgr, &info); 307 mgr->get_manager_info(mgr, &info);
302 308
303 if (info.cpr_enable == enable) 309 if (info.cpr_enable == enable)
@@ -586,6 +592,13 @@ static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
586 return -EINVAL; 592 return -EINVAL;
587 } 593 }
588 594
595 /*
596 * Don't allow currently enabled displays to have the overlay manager
597 * pulled out from underneath them
598 */
599 if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED)
600 return -EINVAL;
601
589 mgr->device->manager = NULL; 602 mgr->device->manager = NULL;
590 mgr->device = NULL; 603 mgr->device = NULL;
591 mgr->device_changed = true; 604 mgr->device_changed = true;
@@ -801,7 +814,7 @@ static int configure_overlay(enum omap_plane plane)
801{ 814{
802 struct overlay_cache_data *c; 815 struct overlay_cache_data *c;
803 struct manager_cache_data *mc; 816 struct manager_cache_data *mc;
804 struct omap_overlay_info *oi; 817 struct omap_overlay_info *oi, new_oi;
805 struct omap_overlay_manager_info *mi; 818 struct omap_overlay_manager_info *mi;
806 u16 outw, outh; 819 u16 outw, outh;
807 u16 x, y, w, h; 820 u16 x, y, w, h;
@@ -815,7 +828,7 @@ static int configure_overlay(enum omap_plane plane)
815 oi = &c->info; 828 oi = &c->info;
816 829
817 if (!c->enabled) { 830 if (!c->enabled) {
818 dispc_enable_plane(plane, 0); 831 dispc_ovl_enable(plane, 0);
819 return 0; 832 return 0;
820 } 833 }
821 834
@@ -843,7 +856,7 @@ static int configure_overlay(enum omap_plane plane)
843 /* If the overlay is outside the update region, disable it */ 856 /* If the overlay is outside the update region, disable it */
844 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, 857 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
845 x, y, outw, outh)) { 858 x, y, outw, outh)) {
846 dispc_enable_plane(plane, 0); 859 dispc_ovl_enable(plane, 0);
847 return 0; 860 return 0;
848 } 861 }
849 862
@@ -921,34 +934,27 @@ static int configure_overlay(enum omap_plane plane)
921 } 934 }
922 } 935 }
923 936
924 r = dispc_setup_plane(plane, 937 new_oi = *oi;
925 paddr, 938
926 oi->screen_width, 939 /* update new_oi members which could have been possibly updated */
927 x, y, 940 new_oi.pos_x = x;
928 w, h, 941 new_oi.pos_y = y;
929 outw, outh, 942 new_oi.width = w;
930 oi->color_mode, 943 new_oi.height = h;
931 c->ilace, 944 new_oi.out_width = outw;
932 oi->rotation_type, 945 new_oi.out_height = outh;
933 oi->rotation, 946 new_oi.paddr = paddr;
934 oi->mirror,
935 oi->global_alpha,
936 oi->pre_mult_alpha,
937 c->channel,
938 oi->p_uv_addr);
939 947
948 r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel,
949 c->replication, c->fifo_low, c->fifo_high);
940 if (r) { 950 if (r) {
941 /* this shouldn't happen */ 951 /* this shouldn't happen */
942 DSSERR("dispc_setup_plane failed for ovl %d\n", plane); 952 DSSERR("dispc_ovl_setup failed for ovl %d\n", plane);
943 dispc_enable_plane(plane, 0); 953 dispc_ovl_enable(plane, 0);
944 return r; 954 return r;
945 } 955 }
946 956
947 dispc_enable_replication(plane, c->replication); 957 dispc_ovl_enable(plane, 1);
948
949 dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high);
950
951 dispc_enable_plane(plane, 1);
952 958
953 return 0; 959 return 0;
954} 960}
@@ -962,13 +968,13 @@ static void configure_manager(enum omap_channel channel)
962 /* picking info from the cache */ 968 /* picking info from the cache */
963 mi = &dss_cache.manager_cache[channel].info; 969 mi = &dss_cache.manager_cache[channel].info;
964 970
965 dispc_set_default_color(channel, mi->default_color); 971 dispc_mgr_set_default_color(channel, mi->default_color);
966 dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key); 972 dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
967 dispc_enable_trans_key(channel, mi->trans_enabled); 973 dispc_mgr_enable_trans_key(channel, mi->trans_enabled);
968 dispc_enable_alpha_blending(channel, mi->alpha_enabled); 974 dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled);
969 if (dss_has_feature(FEAT_CPR)) { 975 if (dss_has_feature(FEAT_CPR)) {
970 dispc_enable_cpr(channel, mi->cpr_enable); 976 dispc_mgr_enable_cpr(channel, mi->cpr_enable);
971 dispc_set_cpr_coef(channel, &mi->cpr_coefs); 977 dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs);
972 } 978 }
973} 979}
974 980
@@ -992,7 +998,7 @@ static int configure_dispc(void)
992 busy = false; 998 busy = false;
993 999
994 for (i = 0; i < num_mgrs; i++) { 1000 for (i = 0; i < num_mgrs; i++) {
995 mgr_busy[i] = dispc_go_busy(i); 1001 mgr_busy[i] = dispc_mgr_go_busy(i);
996 mgr_go[i] = false; 1002 mgr_go[i] = false;
997 } 1003 }
998 1004
@@ -1053,7 +1059,7 @@ static int configure_dispc(void)
1053 * always be turned off after frame, and new settings will be 1059 * always be turned off after frame, and new settings will be
1054 * taken in to use at next update */ 1060 * taken in to use at next update */
1055 if (!mc->manual_update) 1061 if (!mc->manual_update)
1056 dispc_go(i); 1062 dispc_mgr_go(i);
1057 } 1063 }
1058 1064
1059 if (busy) 1065 if (busy)
@@ -1258,7 +1264,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
1258 u32 irq_mask; 1264 u32 irq_mask;
1259 1265
1260 for (i = 0; i < num_mgrs; i++) 1266 for (i = 0; i < num_mgrs; i++)
1261 mgr_busy[i] = dispc_go_busy(i); 1267 mgr_busy[i] = dispc_mgr_go_busy(i);
1262 1268
1263 spin_lock(&dss_cache.lock); 1269 spin_lock(&dss_cache.lock);
1264 1270
@@ -1280,7 +1286,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
1280 1286
1281 /* re-read busy flags */ 1287 /* re-read busy flags */
1282 for (i = 0; i < num_mgrs; i++) 1288 for (i = 0; i < num_mgrs; i++)
1283 mgr_busy[i] = dispc_go_busy(i); 1289 mgr_busy[i] = dispc_mgr_go_busy(i);
1284 1290
1285 /* keep running as long as there are busy managers, so that 1291 /* keep running as long as there are busy managers, so that
1286 * we can collect overlay-applied information */ 1292 * we can collect overlay-applied information */
@@ -1326,11 +1332,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1326 1332
1327 ovl = omap_dss_get_overlay(i); 1333 ovl = omap_dss_get_overlay(i);
1328 1334
1329 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
1330 continue;
1331
1332 oc = &dss_cache.overlay_cache[ovl->id]; 1335 oc = &dss_cache.overlay_cache[ovl->id];
1333 1336
1337 if (ovl->manager_changed) {
1338 ovl->manager_changed = false;
1339 ovl->info_dirty = true;
1340 }
1341
1334 if (!overlay_enabled(ovl)) { 1342 if (!overlay_enabled(ovl)) {
1335 if (oc->enabled) { 1343 if (oc->enabled) {
1336 oc->enabled = false; 1344 oc->enabled = false;
@@ -1375,9 +1383,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1375 list_for_each_entry(mgr, &manager_list, list) { 1383 list_for_each_entry(mgr, &manager_list, list) {
1376 struct omap_dss_device *dssdev; 1384 struct omap_dss_device *dssdev;
1377 1385
1378 if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
1379 continue;
1380
1381 mc = &dss_cache.manager_cache[mgr->id]; 1386 mc = &dss_cache.manager_cache[mgr->id];
1382 1387
1383 if (mgr->device_changed) { 1388 if (mgr->device_changed) {
@@ -1423,9 +1428,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1423 1428
1424 ovl = omap_dss_get_overlay(i); 1429 ovl = omap_dss_get_overlay(i);
1425 1430
1426 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
1427 continue;
1428
1429 oc = &dss_cache.overlay_cache[ovl->id]; 1431 oc = &dss_cache.overlay_cache[ovl->id];
1430 1432
1431 if (!oc->enabled) 1433 if (!oc->enabled)
@@ -1433,11 +1435,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1433 1435
1434 dssdev = ovl->manager->device; 1436 dssdev = ovl->manager->device;
1435 1437
1436 size = dispc_get_plane_fifo_size(ovl->id); 1438 size = dispc_ovl_get_fifo_size(ovl->id);
1437 if (use_fifomerge) 1439 if (use_fifomerge)
1438 size *= 3; 1440 size *= 3;
1439 1441
1440 burst_size = dispc_get_burst_size(ovl->id); 1442 burst_size = dispc_ovl_get_burst_size(ovl->id);
1441 1443
1442 switch (dssdev->type) { 1444 switch (dssdev->type) {
1443 case OMAP_DISPLAY_TYPE_DPI: 1445 case OMAP_DISPLAY_TYPE_DPI:
@@ -1484,12 +1486,17 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1484 1486
1485static int dss_check_manager(struct omap_overlay_manager *mgr) 1487static int dss_check_manager(struct omap_overlay_manager *mgr)
1486{ 1488{
1487 /* OMAP supports only graphics source transparency color key and alpha 1489 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
1488 * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */ 1490 /*
1489 1491 * OMAP3 supports only graphics source transparency color key
1490 if (mgr->info.alpha_enabled && mgr->info.trans_enabled && 1492 * and alpha blending simultaneously. See TRM 15.4.2.4.2.2
1491 mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) 1493 * Alpha Mode
1492 return -EINVAL; 1494 */
1495 if (mgr->info.partial_alpha_enabled && mgr->info.trans_enabled
1496 && mgr->info.trans_key_type !=
1497 OMAP_DSS_COLOR_KEY_GFX_DST)
1498 return -EINVAL;
1499 }
1493 1500
1494 return 0; 1501 return 0;
1495} 1502}
@@ -1522,13 +1529,13 @@ static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
1522 1529
1523static int dss_mgr_enable(struct omap_overlay_manager *mgr) 1530static int dss_mgr_enable(struct omap_overlay_manager *mgr)
1524{ 1531{
1525 dispc_enable_channel(mgr->id, 1); 1532 dispc_mgr_enable(mgr->id, 1);
1526 return 0; 1533 return 0;
1527} 1534}
1528 1535
1529static int dss_mgr_disable(struct omap_overlay_manager *mgr) 1536static int dss_mgr_disable(struct omap_overlay_manager *mgr)
1530{ 1537{
1531 dispc_enable_channel(mgr->id, 0); 1538 dispc_mgr_enable(mgr->id, 0);
1532 return 0; 1539 return 0;
1533} 1540}
1534 1541
@@ -1580,7 +1587,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
1580 mgr->enable = &dss_mgr_enable; 1587 mgr->enable = &dss_mgr_enable;
1581 mgr->disable = &dss_mgr_disable; 1588 mgr->disable = &dss_mgr_disable;
1582 1589
1583 mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; 1590 mgr->caps = 0;
1584 mgr->supported_displays = 1591 mgr->supported_displays =
1585 dss_feat_get_supported_displays(mgr->id); 1592 dss_feat_get_supported_displays(mgr->id);
1586 1593
@@ -1597,42 +1604,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)
1597 } 1604 }
1598 } 1605 }
1599 1606
1600#ifdef L4_EXAMPLE
1601 {
1602 int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
1603 {
1604 DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
1605
1606 return 0;
1607 }
1608
1609 struct omap_overlay_manager *mgr;
1610 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1611
1612 BUG_ON(mgr == NULL);
1613
1614 mgr->name = "l4";
1615 mgr->supported_displays =
1616 OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
1617
1618 mgr->set_device = &omap_dss_set_device;
1619 mgr->unset_device = &omap_dss_unset_device;
1620 mgr->apply = &omap_dss_mgr_apply_l4;
1621 mgr->set_manager_info = &omap_dss_mgr_set_info;
1622 mgr->get_manager_info = &omap_dss_mgr_get_info;
1623
1624 dss_overlay_setup_l4_manager(mgr);
1625
1626 omap_dss_add_overlay_manager(mgr);
1627
1628 r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
1629 &pdev->dev.kobj, "managerl4");
1630
1631 if (r)
1632 DSSERR("failed to create sysfs file\n");
1633 }
1634#endif
1635
1636 return 0; 1607 return 0;
1637} 1608}
1638 1609
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index c84380c53c3..ab8e40e4875 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -211,16 +211,17 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
211static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, 211static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
212 size_t size) 212 size_t size)
213{ 213{
214 int r, enable; 214 int r;
215 bool enable;
215 struct omap_overlay_info info; 216 struct omap_overlay_info info;
216 217
217 ovl->get_overlay_info(ovl, &info); 218 ovl->get_overlay_info(ovl, &info);
218 219
219 r = kstrtoint(buf, 0, &enable); 220 r = strtobool(buf, &enable);
220 if (r) 221 if (r)
221 return r; 222 return r;
222 223
223 info.enabled = !!enable; 224 info.enabled = enable;
224 225
225 r = ovl->set_overlay_info(ovl, &info); 226 r = ovl->set_overlay_info(ovl, &info);
226 if (r) 227 if (r)
@@ -248,7 +249,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
248 u8 alpha; 249 u8 alpha;
249 struct omap_overlay_info info; 250 struct omap_overlay_info info;
250 251
251 if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) 252 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
252 return -ENODEV; 253 return -ENODEV;
253 254
254 r = kstrtou8(buf, 0, &alpha); 255 r = kstrtou8(buf, 0, &alpha);
@@ -257,14 +258,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
257 258
258 ovl->get_overlay_info(ovl, &info); 259 ovl->get_overlay_info(ovl, &info);
259 260
260 /* Video1 plane does not support global alpha 261 info.global_alpha = alpha;
261 * to always make it 255 completely opaque
262 */
263 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
264 ovl->id == OMAP_DSS_VIDEO1)
265 info.global_alpha = 255;
266 else
267 info.global_alpha = alpha;
268 262
269 r = ovl->set_overlay_info(ovl, &info); 263 r = ovl->set_overlay_info(ovl, &info);
270 if (r) 264 if (r)
@@ -293,20 +287,52 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
293 u8 alpha; 287 u8 alpha;
294 struct omap_overlay_info info; 288 struct omap_overlay_info info;
295 289
290 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
291 return -ENODEV;
292
296 r = kstrtou8(buf, 0, &alpha); 293 r = kstrtou8(buf, 0, &alpha);
297 if (r) 294 if (r)
298 return r; 295 return r;
299 296
300 ovl->get_overlay_info(ovl, &info); 297 ovl->get_overlay_info(ovl, &info);
301 298
302 /* only GFX and Video2 plane support pre alpha multiplied 299 info.pre_mult_alpha = alpha;
303 * set zero for Video1 plane 300
304 */ 301 r = ovl->set_overlay_info(ovl, &info);
305 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && 302 if (r)
306 ovl->id == OMAP_DSS_VIDEO1) 303 return r;
307 info.pre_mult_alpha = 0; 304
308 else 305 if (ovl->manager) {
309 info.pre_mult_alpha = alpha; 306 r = ovl->manager->apply(ovl->manager);
307 if (r)
308 return r;
309 }
310
311 return size;
312}
313
314static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
315{
316 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder);
317}
318
319static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
320 const char *buf, size_t size)
321{
322 int r;
323 u8 zorder;
324 struct omap_overlay_info info;
325
326 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
327 return -ENODEV;
328
329 r = kstrtou8(buf, 0, &zorder);
330 if (r)
331 return r;
332
333 ovl->get_overlay_info(ovl, &info);
334
335 info.zorder = zorder;
310 336
311 r = ovl->set_overlay_info(ovl, &info); 337 r = ovl->set_overlay_info(ovl, &info);
312 if (r) 338 if (r)
@@ -347,6 +373,8 @@ static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
347static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, 373static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
348 overlay_pre_mult_alpha_show, 374 overlay_pre_mult_alpha_show,
349 overlay_pre_mult_alpha_store); 375 overlay_pre_mult_alpha_store);
376static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
377 overlay_zorder_show, overlay_zorder_store);
350 378
351static struct attribute *overlay_sysfs_attrs[] = { 379static struct attribute *overlay_sysfs_attrs[] = {
352 &overlay_attr_name.attr, 380 &overlay_attr_name.attr,
@@ -358,6 +386,7 @@ static struct attribute *overlay_sysfs_attrs[] = {
358 &overlay_attr_enabled.attr, 386 &overlay_attr_enabled.attr,
359 &overlay_attr_global_alpha.attr, 387 &overlay_attr_global_alpha.attr,
360 &overlay_attr_pre_mult_alpha.attr, 388 &overlay_attr_pre_mult_alpha.attr,
389 &overlay_attr_zorder.attr,
361 NULL 390 NULL
362}; 391};
363 392
@@ -407,6 +436,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
407 struct omap_overlay_info *info; 436 struct omap_overlay_info *info;
408 u16 outw, outh; 437 u16 outw, outh;
409 u16 dw, dh; 438 u16 dw, dh;
439 int i;
410 440
411 if (!dssdev) 441 if (!dssdev)
412 return 0; 442 return 0;
@@ -462,6 +492,31 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
462 return -EINVAL; 492 return -EINVAL;
463 } 493 }
464 494
495 if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) {
496 if (info->zorder < 0 || info->zorder > 3) {
497 DSSERR("zorder out of range: %d\n",
498 info->zorder);
499 return -EINVAL;
500 }
501 /*
502 * Check that zorder doesn't match with zorder of any other
503 * overlay which is enabled and is also connected to the same
504 * manager
505 */
506 for (i = 0; i < omap_dss_get_num_overlays(); i++) {
507 struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i);
508
509 if (tmp_ovl->id != ovl->id &&
510 tmp_ovl->manager == ovl->manager &&
511 tmp_ovl->info.enabled == true &&
512 tmp_ovl->info.zorder == info->zorder) {
513 DSSERR("%s and %s have same zorder: %d\n",
514 ovl->name, tmp_ovl->name, info->zorder);
515 return -EINVAL;
516 }
517 }
518 }
519
465 return 0; 520 return 0;
466} 521}
467 522
@@ -516,6 +571,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
516 } 571 }
517 572
518 ovl->manager = mgr; 573 ovl->manager = mgr;
574 ovl->manager_changed = true;
519 575
520 /* XXX: When there is an overlay on a DSI manual update display, and 576 /* XXX: When there is an overlay on a DSI manual update display, and
521 * the overlay is first disabled, then moved to tv, and enabled, we 577 * the overlay is first disabled, then moved to tv, and enabled, we
@@ -529,15 +585,12 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
529 * Userspace workaround for this is to update the LCD after disabling 585 * Userspace workaround for this is to update the LCD after disabling
530 * the overlay, but before moving the overlay to TV. 586 * the overlay, but before moving the overlay to TV.
531 */ 587 */
532 dispc_set_channel_out(ovl->id, mgr->id);
533 588
534 return 0; 589 return 0;
535} 590}
536 591
537static int omap_dss_unset_manager(struct omap_overlay *ovl) 592static int omap_dss_unset_manager(struct omap_overlay *ovl)
538{ 593{
539 int r;
540
541 if (!ovl->manager) { 594 if (!ovl->manager) {
542 DSSERR("failed to detach overlay: manager not set\n"); 595 DSSERR("failed to detach overlay: manager not set\n");
543 return -EINVAL; 596 return -EINVAL;
@@ -548,11 +601,8 @@ static int omap_dss_unset_manager(struct omap_overlay *ovl)
548 return -EINVAL; 601 return -EINVAL;
549 } 602 }
550 603
551 r = ovl->wait_for_go(ovl);
552 if (r)
553 return r;
554
555 ovl->manager = NULL; 604 ovl->manager = NULL;
605 ovl->manager_changed = true;
556 606
557 return 0; 607 return 0;
558} 608}
@@ -618,22 +668,29 @@ void dss_init_overlays(struct platform_device *pdev)
618 case 0: 668 case 0:
619 ovl->name = "gfx"; 669 ovl->name = "gfx";
620 ovl->id = OMAP_DSS_GFX; 670 ovl->id = OMAP_DSS_GFX;
621 ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
622 ovl->info.global_alpha = 255; 671 ovl->info.global_alpha = 255;
672 ovl->info.zorder = 0;
623 break; 673 break;
624 case 1: 674 case 1:
625 ovl->name = "vid1"; 675 ovl->name = "vid1";
626 ovl->id = OMAP_DSS_VIDEO1; 676 ovl->id = OMAP_DSS_VIDEO1;
627 ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
628 OMAP_DSS_OVL_CAP_DISPC;
629 ovl->info.global_alpha = 255; 677 ovl->info.global_alpha = 255;
678 ovl->info.zorder =
679 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
630 break; 680 break;
631 case 2: 681 case 2:
632 ovl->name = "vid2"; 682 ovl->name = "vid2";
633 ovl->id = OMAP_DSS_VIDEO2; 683 ovl->id = OMAP_DSS_VIDEO2;
634 ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
635 OMAP_DSS_OVL_CAP_DISPC;
636 ovl->info.global_alpha = 255; 684 ovl->info.global_alpha = 255;
685 ovl->info.zorder =
686 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
687 break;
688 case 3:
689 ovl->name = "vid3";
690 ovl->id = OMAP_DSS_VIDEO3;
691 ovl->info.global_alpha = 255;
692 ovl->info.zorder =
693 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
637 break; 694 break;
638 } 695 }
639 696
@@ -643,6 +700,7 @@ void dss_init_overlays(struct platform_device *pdev)
643 ovl->get_overlay_info = &dss_ovl_get_overlay_info; 700 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
644 ovl->wait_for_go = &dss_ovl_wait_for_go; 701 ovl->wait_for_go = &dss_ovl_wait_for_go;
645 702
703 ovl->caps = dss_feat_get_overlay_caps(ovl->id);
646 ovl->supported_modes = 704 ovl->supported_modes =
647 dss_feat_get_supported_color_modes(ovl->id); 705 dss_feat_get_supported_color_modes(ovl->id);
648 706
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 39f4c597026..1bd3703e42f 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -309,9 +309,9 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
309 309
310 DSSDBG("rfbi_transfer_area %dx%d\n", width, height); 310 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
311 311
312 dispc_set_lcd_size(dssdev->manager->id, width, height); 312 dispc_mgr_set_lcd_size(dssdev->manager->id, width, height);
313 313
314 dispc_enable_channel(dssdev->manager->id, true); 314 dispc_mgr_enable(dssdev->manager->id, true);
315 315
316 rfbi.framedone_callback = callback; 316 rfbi.framedone_callback = callback;
317 rfbi.framedone_callback_data = data; 317 rfbi.framedone_callback_data = data;
@@ -783,10 +783,8 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
783 if (*w == 0 || *h == 0) 783 if (*w == 0 || *h == 0)
784 return -EINVAL; 784 return -EINVAL;
785 785
786 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 786 dss_setup_partial_planes(dssdev, x, y, w, h, true);
787 dss_setup_partial_planes(dssdev, x, y, w, h, true); 787 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
788 dispc_set_lcd_size(dssdev->manager->id, *w, *h);
789 }
790 788
791 return 0; 789 return 0;
792} 790}
@@ -796,22 +794,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev,
796 u16 x, u16 y, u16 w, u16 h, 794 u16 x, u16 y, u16 w, u16 h,
797 void (*callback)(void *), void *data) 795 void (*callback)(void *), void *data)
798{ 796{
799 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 797 rfbi_transfer_area(dssdev, w, h, callback, data);
800 rfbi_transfer_area(dssdev, w, h, callback, data);
801 } else {
802 struct omap_overlay *ovl;
803 void __iomem *addr;
804 int scr_width;
805
806 ovl = dssdev->manager->overlays[0];
807 scr_width = ovl->info.screen_width;
808 addr = ovl->info.vaddr;
809
810 omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
811
812 callback(data);
813 }
814
815 return 0; 798 return 0;
816} 799}
817EXPORT_SYMBOL(omap_rfbi_update); 800EXPORT_SYMBOL(omap_rfbi_update);
@@ -860,6 +843,11 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
860{ 843{
861 int r; 844 int r;
862 845
846 if (dssdev->manager == NULL) {
847 DSSERR("failed to enable display: no manager\n");
848 return -ENODEV;
849 }
850
863 r = rfbi_runtime_get(); 851 r = rfbi_runtime_get();
864 if (r) 852 if (r)
865 return r; 853 return r;
@@ -877,13 +865,13 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
877 goto err1; 865 goto err1;
878 } 866 }
879 867
880 dispc_set_lcd_display_type(dssdev->manager->id, 868 dispc_mgr_set_lcd_display_type(dssdev->manager->id,
881 OMAP_DSS_LCD_DISPLAY_TFT); 869 OMAP_DSS_LCD_DISPLAY_TFT);
882 870
883 dispc_set_parallel_interface_mode(dssdev->manager->id, 871 dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_RFBI);
884 OMAP_DSS_PARALLELMODE_RFBI); 872 dispc_mgr_enable_stallmode(dssdev->manager->id, true);
885 873
886 dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); 874 dispc_mgr_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
887 875
888 rfbi_configure(dssdev->phy.rfbi.channel, 876 rfbi_configure(dssdev->phy.rfbi.channel,
889 dssdev->ctrl.pixel_size, 877 dssdev->ctrl.pixel_size,
@@ -952,10 +940,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
952 940
953 msleep(10); 941 msleep(10);
954 942
955 if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630()) 943 clk = clk_get(&pdev->dev, "ick");
956 clk = dss_get_ick();
957 else
958 clk = clk_get(&pdev->dev, "ick");
959 if (IS_ERR(clk)) { 944 if (IS_ERR(clk)) {
960 DSSERR("can't get ick\n"); 945 DSSERR("can't get ick\n");
961 r = PTR_ERR(clk); 946 r = PTR_ERR(clk);
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 3a688c871a4..695dc04cabb 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -35,13 +35,13 @@ static struct {
35static void sdi_basic_init(struct omap_dss_device *dssdev) 35static void sdi_basic_init(struct omap_dss_device *dssdev)
36 36
37{ 37{
38 dispc_set_parallel_interface_mode(dssdev->manager->id, 38 dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS);
39 OMAP_DSS_PARALLELMODE_BYPASS); 39 dispc_mgr_enable_stallmode(dssdev->manager->id, false);
40 40
41 dispc_set_lcd_display_type(dssdev->manager->id, 41 dispc_mgr_set_lcd_display_type(dssdev->manager->id,
42 OMAP_DSS_LCD_DISPLAY_TFT); 42 OMAP_DSS_LCD_DISPLAY_TFT);
43 43
44 dispc_set_tft_data_lines(dssdev->manager->id, 24); 44 dispc_mgr_set_tft_data_lines(dssdev->manager->id, 24);
45 dispc_lcd_enable_signal_polarity(1); 45 dispc_lcd_enable_signal_polarity(1);
46} 46}
47 47
@@ -55,6 +55,11 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
55 unsigned long pck; 55 unsigned long pck;
56 int r; 56 int r;
57 57
58 if (dssdev->manager == NULL) {
59 DSSERR("failed to enable display: no manager\n");
60 return -ENODEV;
61 }
62
58 r = omap_dss_start_device(dssdev); 63 r = omap_dss_start_device(dssdev);
59 if (r) { 64 if (r) {
60 DSSERR("failed to start device\n"); 65 DSSERR("failed to start device\n");
@@ -78,7 +83,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
78 /* 15.5.9.1.2 */ 83 /* 15.5.9.1.2 */
79 dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; 84 dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
80 85
81 dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, 86 dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
82 dssdev->panel.acbi, dssdev->panel.acb); 87 dssdev->panel.acbi, dssdev->panel.acb);
83 88
84 r = dss_calc_clock_div(1, t->pixel_clock * 1000, 89 r = dss_calc_clock_div(1, t->pixel_clock * 1000,
@@ -101,13 +106,13 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
101 } 106 }
102 107
103 108
104 dispc_set_lcd_timings(dssdev->manager->id, t); 109 dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
105 110
106 r = dss_set_clock_div(&dss_cinfo); 111 r = dss_set_clock_div(&dss_cinfo);
107 if (r) 112 if (r)
108 goto err_set_dss_clock_div; 113 goto err_set_dss_clock_div;
109 114
110 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); 115 r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
111 if (r) 116 if (r)
112 goto err_set_dispc_clock_div; 117 goto err_set_dispc_clock_div;
113 118
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
new file mode 100644
index 00000000000..2c3443dabb1
--- /dev/null
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -0,0 +1,138 @@
1/*
2 * ti_hdmi.h
3 *
4 * HDMI driver definition for TI OMAP4, DM81xx, DM38xx Processor.
5 *
6 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef _TI_HDMI_H
22#define _TI_HDMI_H
23
24struct hdmi_ip_data;
25
26enum hdmi_pll_pwr {
27 HDMI_PLLPWRCMD_ALLOFF = 0,
28 HDMI_PLLPWRCMD_PLLONLY = 1,
29 HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
30 HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
31};
32
33enum hdmi_core_hdmi_dvi {
34 HDMI_DVI = 0,
35 HDMI_HDMI = 1
36};
37
38enum hdmi_clk_refsel {
39 HDMI_REFSEL_PCLK = 0,
40 HDMI_REFSEL_REF1 = 1,
41 HDMI_REFSEL_REF2 = 2,
42 HDMI_REFSEL_SYSCLK = 3
43};
44
45struct hdmi_video_timings {
46 u16 x_res;
47 u16 y_res;
48 /* Unit: KHz */
49 u32 pixel_clock;
50 u16 hsw;
51 u16 hfp;
52 u16 hbp;
53 u16 vsw;
54 u16 vfp;
55 u16 vbp;
56};
57
58/* HDMI timing structure */
59struct hdmi_timings {
60 struct hdmi_video_timings timings;
61 int vsync_pol;
62 int hsync_pol;
63};
64
65struct hdmi_cm {
66 int code;
67 int mode;
68};
69
70struct hdmi_config {
71 struct hdmi_timings timings;
72 u16 interlace;
73 struct hdmi_cm cm;
74};
75
76/* HDMI PLL structure */
77struct hdmi_pll_info {
78 u16 regn;
79 u16 regm;
80 u32 regmf;
81 u16 regm2;
82 u16 regsd;
83 u16 dcofreq;
84 enum hdmi_clk_refsel refsel;
85};
86
87struct ti_hdmi_ip_ops {
88
89 void (*video_configure)(struct hdmi_ip_data *ip_data);
90
91 int (*phy_enable)(struct hdmi_ip_data *ip_data);
92
93 void (*phy_disable)(struct hdmi_ip_data *ip_data);
94
95 int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len);
96
97 bool (*detect)(struct hdmi_ip_data *ip_data);
98
99 int (*pll_enable)(struct hdmi_ip_data *ip_data);
100
101 void (*pll_disable)(struct hdmi_ip_data *ip_data);
102
103 void (*video_enable)(struct hdmi_ip_data *ip_data, bool start);
104
105 void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s);
106
107 void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s);
108
109 void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s);
110
111 void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
112
113};
114
115struct hdmi_ip_data {
116 void __iomem *base_wp; /* HDMI wrapper */
117 unsigned long core_sys_offset;
118 unsigned long core_av_offset;
119 unsigned long pll_offset;
120 unsigned long phy_offset;
121 const struct ti_hdmi_ip_ops *ops;
122 struct hdmi_config cfg;
123 struct hdmi_pll_info pll_data;
124};
125int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
126void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
127int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
128bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data);
129void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start);
130int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
131void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data);
132void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data);
133void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
134void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
135void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
136void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
137
138#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
new file mode 100644
index 00000000000..e1a6ce518af
--- /dev/null
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -0,0 +1,1239 @@
1/*
2 * ti_hdmi_4xxx_ip.c
3 *
4 * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library
5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
6 * Authors: Yong Zhi
7 * Mythri pk <mythripk@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/io.h>
26#include <linux/interrupt.h>
27#include <linux/mutex.h>
28#include <linux/delay.h>
29#include <linux/string.h>
30#include <linux/seq_file.h>
31
32#include "ti_hdmi_4xxx_ip.h"
33#include "dss.h"
34
35static inline void hdmi_write_reg(void __iomem *base_addr,
36 const u16 idx, u32 val)
37{
38 __raw_writel(val, base_addr + idx);
39}
40
41static inline u32 hdmi_read_reg(void __iomem *base_addr,
42 const u16 idx)
43{
44 return __raw_readl(base_addr + idx);
45}
46
47static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data)
48{
49 return ip_data->base_wp;
50}
51
52static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data)
53{
54 return ip_data->base_wp + ip_data->phy_offset;
55}
56
57static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data)
58{
59 return ip_data->base_wp + ip_data->pll_offset;
60}
61
62static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data)
63{
64 return ip_data->base_wp + ip_data->core_av_offset;
65}
66
67static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data)
68{
69 return ip_data->base_wp + ip_data->core_sys_offset;
70}
71
72static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
73 const u16 idx,
74 int b2, int b1, u32 val)
75{
76 u32 t = 0;
77 while (val != REG_GET(base_addr, idx, b2, b1)) {
78 udelay(1);
79 if (t++ > 10000)
80 return !val;
81 }
82 return val;
83}
84
85static int hdmi_pll_init(struct hdmi_ip_data *ip_data)
86{
87 u32 r;
88 void __iomem *pll_base = hdmi_pll_base(ip_data);
89 struct hdmi_pll_info *fmt = &ip_data->pll_data;
90
91 /* PLL start always use manual mode */
92 REG_FLD_MOD(pll_base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
93
94 r = hdmi_read_reg(pll_base, PLLCTRL_CFG1);
95 r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
96 r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */
97
98 hdmi_write_reg(pll_base, PLLCTRL_CFG1, r);
99
100 r = hdmi_read_reg(pll_base, PLLCTRL_CFG2);
101
102 r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
103 r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
104 r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
105 r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */
106
107 if (fmt->dcofreq) {
108 /* divider programming for frequency beyond 1000Mhz */
109 REG_FLD_MOD(pll_base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
110 r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
111 } else {
112 r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
113 }
114
115 hdmi_write_reg(pll_base, PLLCTRL_CFG2, r);
116
117 r = hdmi_read_reg(pll_base, PLLCTRL_CFG4);
118 r = FLD_MOD(r, fmt->regm2, 24, 18);
119 r = FLD_MOD(r, fmt->regmf, 17, 0);
120
121 hdmi_write_reg(pll_base, PLLCTRL_CFG4, r);
122
123 /* go now */
124 REG_FLD_MOD(pll_base, PLLCTRL_PLL_GO, 0x1, 0, 0);
125
126 /* wait for bit change */
127 if (hdmi_wait_for_bit_change(pll_base, PLLCTRL_PLL_GO,
128 0, 0, 1) != 1) {
129 pr_err("PLL GO bit not set\n");
130 return -ETIMEDOUT;
131 }
132
133 /* Wait till the lock bit is set in PLL status */
134 if (hdmi_wait_for_bit_change(pll_base,
135 PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
136 pr_err("cannot lock PLL\n");
137 pr_err("CFG1 0x%x\n",
138 hdmi_read_reg(pll_base, PLLCTRL_CFG1));
139 pr_err("CFG2 0x%x\n",
140 hdmi_read_reg(pll_base, PLLCTRL_CFG2));
141 pr_err("CFG4 0x%x\n",
142 hdmi_read_reg(pll_base, PLLCTRL_CFG4));
143 return -ETIMEDOUT;
144 }
145
146 pr_debug("PLL locked!\n");
147
148 return 0;
149}
150
151/* PHY_PWR_CMD */
152static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val)
153{
154 /* Command for power control of HDMI PHY */
155 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6);
156
157 /* Status of the power control of HDMI PHY */
158 if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data),
159 HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
160 pr_err("Failed to set PHY power mode to %d\n", val);
161 return -ETIMEDOUT;
162 }
163
164 return 0;
165}
166
167/* PLL_PWR_CMD */
168static int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val)
169{
170 /* Command for power control of HDMI PLL */
171 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2);
172
173 /* wait till PHY_PWR_STATUS is set */
174 if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL,
175 1, 0, val) != val) {
176 pr_err("Failed to set PLL_PWR_STATUS\n");
177 return -ETIMEDOUT;
178 }
179
180 return 0;
181}
182
183static int hdmi_pll_reset(struct hdmi_ip_data *ip_data)
184{
185 /* SYSRESET controlled by power FSM */
186 REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
187
188 /* READ 0x0 reset is in progress */
189 if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
190 PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
191 pr_err("Failed to sysreset PLL\n");
192 return -ETIMEDOUT;
193 }
194
195 return 0;
196}
197
198int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data)
199{
200 u16 r = 0;
201
202 r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
203 if (r)
204 return r;
205
206 r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
207 if (r)
208 return r;
209
210 r = hdmi_pll_reset(ip_data);
211 if (r)
212 return r;
213
214 r = hdmi_pll_init(ip_data);
215 if (r)
216 return r;
217
218 return 0;
219}
220
221void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)
222{
223 hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
224}
225
226int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
227{
228 u16 r = 0;
229 void __iomem *phy_base = hdmi_phy_base(ip_data);
230
231 r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
232 if (r)
233 return r;
234
235 r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
236 if (r)
237 return r;
238
239 /*
240 * Read address 0 in order to get the SCP reset done completed
241 * Dummy access performed to make sure reset is done
242 */
243 hdmi_read_reg(phy_base, HDMI_TXPHY_TX_CTRL);
244
245 /*
246 * Write to phy address 0 to configure the clock
247 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
248 */
249 REG_FLD_MOD(phy_base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
250
251 /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
252 hdmi_write_reg(phy_base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
253
254 /* Setup max LDO voltage */
255 REG_FLD_MOD(phy_base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
256
257 /* Write to phy address 3 to change the polarity control */
258 REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
259
260 return 0;
261}
262
263void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data)
264{
265 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
266}
267
268static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data)
269{
270 void __iomem *base = hdmi_core_sys_base(ip_data);
271
272 /* Turn on CLK for DDC */
273 REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0);
274
275 /* IN_PROG */
276 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) {
277 /* Abort transaction */
278 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0);
279 /* IN_PROG */
280 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
281 4, 4, 0) != 0) {
282 DSSERR("Timeout aborting DDC transaction\n");
283 return -ETIMEDOUT;
284 }
285 }
286
287 /* Clk SCL Devices */
288 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0);
289
290 /* HDMI_CORE_DDC_STATUS_IN_PROG */
291 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
292 4, 4, 0) != 0) {
293 DSSERR("Timeout starting SCL clock\n");
294 return -ETIMEDOUT;
295 }
296
297 /* Clear FIFO */
298 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0);
299
300 /* HDMI_CORE_DDC_STATUS_IN_PROG */
301 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
302 4, 4, 0) != 0) {
303 DSSERR("Timeout clearing DDC fifo\n");
304 return -ETIMEDOUT;
305 }
306
307 return 0;
308}
309
310static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data,
311 u8 *pedid, int ext)
312{
313 void __iomem *base = hdmi_core_sys_base(ip_data);
314 u32 i;
315 char checksum;
316 u32 offset = 0;
317
318 /* HDMI_CORE_DDC_STATUS_IN_PROG */
319 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
320 4, 4, 0) != 0) {
321 DSSERR("Timeout waiting DDC to be ready\n");
322 return -ETIMEDOUT;
323 }
324
325 if (ext % 2 != 0)
326 offset = 0x80;
327
328 /* Load Segment Address Register */
329 REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0);
330
331 /* Load Slave Address Register */
332 REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
333
334 /* Load Offset Address Register */
335 REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0);
336
337 /* Load Byte Count */
338 REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
339 REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
340
341 /* Set DDC_CMD */
342 if (ext)
343 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0);
344 else
345 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0);
346
347 /* HDMI_CORE_DDC_STATUS_BUS_LOW */
348 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
349 pr_err("I2C Bus Low?\n");
350 return -EIO;
351 }
352 /* HDMI_CORE_DDC_STATUS_NO_ACK */
353 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
354 pr_err("I2C No Ack\n");
355 return -EIO;
356 }
357
358 for (i = 0; i < 0x80; ++i) {
359 int t;
360
361 /* IN_PROG */
362 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) {
363 DSSERR("operation stopped when reading edid\n");
364 return -EIO;
365 }
366
367 t = 0;
368 /* FIFO_EMPTY */
369 while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) {
370 if (t++ > 10000) {
371 DSSERR("timeout reading edid\n");
372 return -ETIMEDOUT;
373 }
374 udelay(1);
375 }
376
377 pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0);
378 }
379
380 checksum = 0;
381 for (i = 0; i < 0x80; ++i)
382 checksum += pedid[i];
383
384 if (checksum != 0) {
385 pr_err("E-EDID checksum failed!!\n");
386 return -EIO;
387 }
388
389 return 0;
390}
391
392int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data,
393 u8 *edid, int len)
394{
395 int r, l;
396
397 if (len < 128)
398 return -EINVAL;
399
400 r = hdmi_core_ddc_init(ip_data);
401 if (r)
402 return r;
403
404 r = hdmi_core_ddc_edid(ip_data, edid, 0);
405 if (r)
406 return r;
407
408 l = 128;
409
410 if (len >= 128 * 2 && edid[0x7e] > 0) {
411 r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1);
412 if (r)
413 return r;
414 l += 128;
415 }
416
417 return l;
418}
419
420bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data)
421{
422 int r;
423
424 void __iomem *base = hdmi_core_sys_base(ip_data);
425
426 /* HPD */
427 r = REG_GET(base, HDMI_CORE_SYS_SYS_STAT, 1, 1);
428
429 return r == 1;
430}
431
432static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
433 struct hdmi_core_infoframe_avi *avi_cfg,
434 struct hdmi_core_packet_enable_repeat *repeat_cfg)
435{
436 pr_debug("Enter hdmi_core_init\n");
437
438 /* video core */
439 video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
440 video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
441 video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
442 video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
443 video_cfg->hdmi_dvi = HDMI_DVI;
444 video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
445
446 /* info frame */
447 avi_cfg->db1_format = 0;
448 avi_cfg->db1_active_info = 0;
449 avi_cfg->db1_bar_info_dv = 0;
450 avi_cfg->db1_scan_info = 0;
451 avi_cfg->db2_colorimetry = 0;
452 avi_cfg->db2_aspect_ratio = 0;
453 avi_cfg->db2_active_fmt_ar = 0;
454 avi_cfg->db3_itc = 0;
455 avi_cfg->db3_ec = 0;
456 avi_cfg->db3_q_range = 0;
457 avi_cfg->db3_nup_scaling = 0;
458 avi_cfg->db4_videocode = 0;
459 avi_cfg->db5_pixel_repeat = 0;
460 avi_cfg->db6_7_line_eoftop = 0 ;
461 avi_cfg->db8_9_line_sofbottom = 0;
462 avi_cfg->db10_11_pixel_eofleft = 0;
463 avi_cfg->db12_13_pixel_sofright = 0;
464
465 /* packet enable and repeat */
466 repeat_cfg->audio_pkt = 0;
467 repeat_cfg->audio_pkt_repeat = 0;
468 repeat_cfg->avi_infoframe = 0;
469 repeat_cfg->avi_infoframe_repeat = 0;
470 repeat_cfg->gen_cntrl_pkt = 0;
471 repeat_cfg->gen_cntrl_pkt_repeat = 0;
472 repeat_cfg->generic_pkt = 0;
473 repeat_cfg->generic_pkt_repeat = 0;
474}
475
476static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data)
477{
478 pr_debug("Enter hdmi_core_powerdown_disable\n");
479 REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0);
480}
481
482static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data)
483{
484 pr_debug("Enter hdmi_core_swreset_release\n");
485 REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0);
486}
487
488static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data)
489{
490 pr_debug("Enter hdmi_core_swreset_assert\n");
491 REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0);
492}
493
494/* HDMI_CORE_VIDEO_CONFIG */
495static void hdmi_core_video_config(struct hdmi_ip_data *ip_data,
496 struct hdmi_core_video_config *cfg)
497{
498 u32 r = 0;
499 void __iomem *core_sys_base = hdmi_core_sys_base(ip_data);
500
501 /* sys_ctrl1 default configuration not tunable */
502 r = hdmi_read_reg(core_sys_base, HDMI_CORE_CTRL1);
503 r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
504 r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
505 r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
506 r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
507 hdmi_write_reg(core_sys_base, HDMI_CORE_CTRL1, r);
508
509 REG_FLD_MOD(core_sys_base,
510 HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
511
512 /* Vid_Mode */
513 r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE);
514
515 /* dither truncation configuration */
516 if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
517 r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
518 r = FLD_MOD(r, 1, 5, 5);
519 } else {
520 r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
521 r = FLD_MOD(r, 0, 5, 5);
522 }
523 hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r);
524
525 /* HDMI_Ctrl */
526 r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL);
527 r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
528 r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
529 r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
530 hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r);
531
532 /* TMDS_CTRL */
533 REG_FLD_MOD(core_sys_base,
534 HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
535}
536
537static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data,
538 struct hdmi_core_infoframe_avi info_avi)
539{
540 u32 val;
541 char sum = 0, checksum = 0;
542 void __iomem *av_base = hdmi_av_base(ip_data);
543
544 sum += 0x82 + 0x002 + 0x00D;
545 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082);
546 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002);
547 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D);
548
549 val = (info_avi.db1_format << 5) |
550 (info_avi.db1_active_info << 4) |
551 (info_avi.db1_bar_info_dv << 2) |
552 (info_avi.db1_scan_info);
553 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val);
554 sum += val;
555
556 val = (info_avi.db2_colorimetry << 6) |
557 (info_avi.db2_aspect_ratio << 4) |
558 (info_avi.db2_active_fmt_ar);
559 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val);
560 sum += val;
561
562 val = (info_avi.db3_itc << 7) |
563 (info_avi.db3_ec << 4) |
564 (info_avi.db3_q_range << 2) |
565 (info_avi.db3_nup_scaling);
566 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val);
567 sum += val;
568
569 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3),
570 info_avi.db4_videocode);
571 sum += info_avi.db4_videocode;
572
573 val = info_avi.db5_pixel_repeat;
574 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val);
575 sum += val;
576
577 val = info_avi.db6_7_line_eoftop & 0x00FF;
578 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val);
579 sum += val;
580
581 val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
582 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val);
583 sum += val;
584
585 val = info_avi.db8_9_line_sofbottom & 0x00FF;
586 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val);
587 sum += val;
588
589 val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
590 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val);
591 sum += val;
592
593 val = info_avi.db10_11_pixel_eofleft & 0x00FF;
594 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val);
595 sum += val;
596
597 val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
598 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val);
599 sum += val;
600
601 val = info_avi.db12_13_pixel_sofright & 0x00FF;
602 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val);
603 sum += val;
604
605 val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
606 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val);
607 sum += val;
608
609 checksum = 0x100 - sum;
610 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum);
611}
612
613static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data,
614 struct hdmi_core_packet_enable_repeat repeat_cfg)
615{
616 /* enable/repeat the infoframe */
617 hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1,
618 (repeat_cfg.audio_pkt << 5) |
619 (repeat_cfg.audio_pkt_repeat << 4) |
620 (repeat_cfg.avi_infoframe << 1) |
621 (repeat_cfg.avi_infoframe_repeat));
622
623 /* enable/repeat the packet */
624 hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2,
625 (repeat_cfg.gen_cntrl_pkt << 3) |
626 (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
627 (repeat_cfg.generic_pkt << 1) |
628 (repeat_cfg.generic_pkt_repeat));
629}
630
631static void hdmi_wp_init(struct omap_video_timings *timings,
632 struct hdmi_video_format *video_fmt,
633 struct hdmi_video_interface *video_int)
634{
635 pr_debug("Enter hdmi_wp_init\n");
636
637 timings->hbp = 0;
638 timings->hfp = 0;
639 timings->hsw = 0;
640 timings->vbp = 0;
641 timings->vfp = 0;
642 timings->vsw = 0;
643
644 video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
645 video_fmt->y_res = 0;
646 video_fmt->x_res = 0;
647
648 video_int->vsp = 0;
649 video_int->hsp = 0;
650
651 video_int->interlacing = 0;
652 video_int->tm = 0; /* HDMI_TIMING_SLAVE */
653
654}
655
656void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
657{
658 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31);
659}
660
661static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
662 struct omap_video_timings *timings, struct hdmi_config *param)
663{
664 pr_debug("Enter hdmi_wp_video_init_format\n");
665
666 video_fmt->y_res = param->timings.timings.y_res;
667 video_fmt->x_res = param->timings.timings.x_res;
668
669 timings->hbp = param->timings.timings.hbp;
670 timings->hfp = param->timings.timings.hfp;
671 timings->hsw = param->timings.timings.hsw;
672 timings->vbp = param->timings.timings.vbp;
673 timings->vfp = param->timings.timings.vfp;
674 timings->vsw = param->timings.timings.vsw;
675}
676
677static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data,
678 struct hdmi_video_format *video_fmt)
679{
680 u32 l = 0;
681
682 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG,
683 video_fmt->packing_mode, 10, 8);
684
685 l |= FLD_VAL(video_fmt->y_res, 31, 16);
686 l |= FLD_VAL(video_fmt->x_res, 15, 0);
687 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l);
688}
689
690static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data,
691 struct hdmi_video_interface *video_int)
692{
693 u32 r;
694 pr_debug("Enter hdmi_wp_video_config_interface\n");
695
696 r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG);
697 r = FLD_MOD(r, video_int->vsp, 7, 7);
698 r = FLD_MOD(r, video_int->hsp, 6, 6);
699 r = FLD_MOD(r, video_int->interlacing, 3, 3);
700 r = FLD_MOD(r, video_int->tm, 1, 0);
701 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r);
702}
703
704static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data,
705 struct omap_video_timings *timings)
706{
707 u32 timing_h = 0;
708 u32 timing_v = 0;
709
710 pr_debug("Enter hdmi_wp_video_config_timing\n");
711
712 timing_h |= FLD_VAL(timings->hbp, 31, 20);
713 timing_h |= FLD_VAL(timings->hfp, 19, 8);
714 timing_h |= FLD_VAL(timings->hsw, 7, 0);
715 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h);
716
717 timing_v |= FLD_VAL(timings->vbp, 31, 20);
718 timing_v |= FLD_VAL(timings->vfp, 19, 8);
719 timing_v |= FLD_VAL(timings->vsw, 7, 0);
720 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v);
721}
722
723void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
724{
725 /* HDMI */
726 struct omap_video_timings video_timing;
727 struct hdmi_video_format video_format;
728 struct hdmi_video_interface video_interface;
729 /* HDMI core */
730 struct hdmi_core_infoframe_avi avi_cfg;
731 struct hdmi_core_video_config v_core_cfg;
732 struct hdmi_core_packet_enable_repeat repeat_cfg;
733 struct hdmi_config *cfg = &ip_data->cfg;
734
735 hdmi_wp_init(&video_timing, &video_format,
736 &video_interface);
737
738 hdmi_core_init(&v_core_cfg,
739 &avi_cfg,
740 &repeat_cfg);
741
742 hdmi_wp_video_init_format(&video_format, &video_timing, cfg);
743
744 hdmi_wp_video_config_timing(ip_data, &video_timing);
745
746 /* video config */
747 video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
748
749 hdmi_wp_video_config_format(ip_data, &video_format);
750
751 video_interface.vsp = cfg->timings.vsync_pol;
752 video_interface.hsp = cfg->timings.hsync_pol;
753 video_interface.interlacing = cfg->interlace;
754 video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
755
756 hdmi_wp_video_config_interface(ip_data, &video_interface);
757
758 /*
759 * configure core video part
760 * set software reset in the core
761 */
762 hdmi_core_swreset_assert(ip_data);
763
764 /* power down off */
765 hdmi_core_powerdown_disable(ip_data);
766
767 v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
768 v_core_cfg.hdmi_dvi = cfg->cm.mode;
769
770 hdmi_core_video_config(ip_data, &v_core_cfg);
771
772 /* release software reset in the core */
773 hdmi_core_swreset_release(ip_data);
774
775 /*
776 * configure packet
777 * info frame video see doc CEA861-D page 65
778 */
779 avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
780 avi_cfg.db1_active_info =
781 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
782 avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
783 avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
784 avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
785 avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
786 avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
787 avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
788 avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
789 avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
790 avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
791 avi_cfg.db4_videocode = cfg->cm.code;
792 avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
793 avi_cfg.db6_7_line_eoftop = 0;
794 avi_cfg.db8_9_line_sofbottom = 0;
795 avi_cfg.db10_11_pixel_eofleft = 0;
796 avi_cfg.db12_13_pixel_sofright = 0;
797
798 hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg);
799
800 /* enable/repeat the infoframe */
801 repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
802 repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
803 /* wakeup */
804 repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
805 repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
806 hdmi_core_av_packet_config(ip_data, repeat_cfg);
807}
808
809void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
810{
811#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r,\
812 hdmi_read_reg(hdmi_wp_base(ip_data), r))
813
814 DUMPREG(HDMI_WP_REVISION);
815 DUMPREG(HDMI_WP_SYSCONFIG);
816 DUMPREG(HDMI_WP_IRQSTATUS_RAW);
817 DUMPREG(HDMI_WP_IRQSTATUS);
818 DUMPREG(HDMI_WP_PWR_CTRL);
819 DUMPREG(HDMI_WP_IRQENABLE_SET);
820 DUMPREG(HDMI_WP_VIDEO_CFG);
821 DUMPREG(HDMI_WP_VIDEO_SIZE);
822 DUMPREG(HDMI_WP_VIDEO_TIMING_H);
823 DUMPREG(HDMI_WP_VIDEO_TIMING_V);
824 DUMPREG(HDMI_WP_WP_CLK);
825 DUMPREG(HDMI_WP_AUDIO_CFG);
826 DUMPREG(HDMI_WP_AUDIO_CFG2);
827 DUMPREG(HDMI_WP_AUDIO_CTRL);
828 DUMPREG(HDMI_WP_AUDIO_DATA);
829}
830
831void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
832{
833#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
834 hdmi_read_reg(hdmi_pll_base(ip_data), r))
835
836 DUMPPLL(PLLCTRL_PLL_CONTROL);
837 DUMPPLL(PLLCTRL_PLL_STATUS);
838 DUMPPLL(PLLCTRL_PLL_GO);
839 DUMPPLL(PLLCTRL_CFG1);
840 DUMPPLL(PLLCTRL_CFG2);
841 DUMPPLL(PLLCTRL_CFG3);
842 DUMPPLL(PLLCTRL_CFG4);
843}
844
845void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
846{
847 int i;
848
849#define CORE_REG(i, name) name(i)
850#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
851 hdmi_read_reg(hdmi_pll_base(ip_data), r))
852#define DUMPCOREAV(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
853 (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
854 hdmi_read_reg(hdmi_pll_base(ip_data), CORE_REG(i, r)))
855
856 DUMPCORE(HDMI_CORE_SYS_VND_IDL);
857 DUMPCORE(HDMI_CORE_SYS_DEV_IDL);
858 DUMPCORE(HDMI_CORE_SYS_DEV_IDH);
859 DUMPCORE(HDMI_CORE_SYS_DEV_REV);
860 DUMPCORE(HDMI_CORE_SYS_SRST);
861 DUMPCORE(HDMI_CORE_CTRL1);
862 DUMPCORE(HDMI_CORE_SYS_SYS_STAT);
863 DUMPCORE(HDMI_CORE_SYS_VID_ACEN);
864 DUMPCORE(HDMI_CORE_SYS_VID_MODE);
865 DUMPCORE(HDMI_CORE_SYS_INTR_STATE);
866 DUMPCORE(HDMI_CORE_SYS_INTR1);
867 DUMPCORE(HDMI_CORE_SYS_INTR2);
868 DUMPCORE(HDMI_CORE_SYS_INTR3);
869 DUMPCORE(HDMI_CORE_SYS_INTR4);
870 DUMPCORE(HDMI_CORE_SYS_UMASK1);
871 DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL);
872 DUMPCORE(HDMI_CORE_SYS_DE_DLY);
873 DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
874 DUMPCORE(HDMI_CORE_SYS_DE_TOP);
875 DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
876 DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
877 DUMPCORE(HDMI_CORE_SYS_DE_LINL);
878 DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
879
880 DUMPCORE(HDMI_CORE_DDC_CMD);
881 DUMPCORE(HDMI_CORE_DDC_STATUS);
882 DUMPCORE(HDMI_CORE_DDC_ADDR);
883 DUMPCORE(HDMI_CORE_DDC_OFFSET);
884 DUMPCORE(HDMI_CORE_DDC_COUNT1);
885 DUMPCORE(HDMI_CORE_DDC_COUNT2);
886 DUMPCORE(HDMI_CORE_DDC_DATA);
887 DUMPCORE(HDMI_CORE_DDC_SEGM);
888
889 DUMPCORE(HDMI_CORE_AV_HDMI_CTRL);
890 DUMPCORE(HDMI_CORE_AV_DPD);
891 DUMPCORE(HDMI_CORE_AV_PB_CTRL1);
892 DUMPCORE(HDMI_CORE_AV_PB_CTRL2);
893 DUMPCORE(HDMI_CORE_AV_AVI_TYPE);
894 DUMPCORE(HDMI_CORE_AV_AVI_VERS);
895 DUMPCORE(HDMI_CORE_AV_AVI_LEN);
896 DUMPCORE(HDMI_CORE_AV_AVI_CHSUM);
897
898 for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++)
899 DUMPCOREAV(i, HDMI_CORE_AV_AVI_DBYTE);
900
901 for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++)
902 DUMPCOREAV(i, HDMI_CORE_AV_SPD_DBYTE);
903
904 for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++)
905 DUMPCOREAV(i, HDMI_CORE_AV_AUD_DBYTE);
906
907 for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++)
908 DUMPCOREAV(i, HDMI_CORE_AV_MPEG_DBYTE);
909
910 for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++)
911 DUMPCOREAV(i, HDMI_CORE_AV_GEN_DBYTE);
912
913 for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++)
914 DUMPCOREAV(i, HDMI_CORE_AV_GEN2_DBYTE);
915
916 DUMPCORE(HDMI_CORE_AV_ACR_CTRL);
917 DUMPCORE(HDMI_CORE_AV_FREQ_SVAL);
918 DUMPCORE(HDMI_CORE_AV_N_SVAL1);
919 DUMPCORE(HDMI_CORE_AV_N_SVAL2);
920 DUMPCORE(HDMI_CORE_AV_N_SVAL3);
921 DUMPCORE(HDMI_CORE_AV_CTS_SVAL1);
922 DUMPCORE(HDMI_CORE_AV_CTS_SVAL2);
923 DUMPCORE(HDMI_CORE_AV_CTS_SVAL3);
924 DUMPCORE(HDMI_CORE_AV_CTS_HVAL1);
925 DUMPCORE(HDMI_CORE_AV_CTS_HVAL2);
926 DUMPCORE(HDMI_CORE_AV_CTS_HVAL3);
927 DUMPCORE(HDMI_CORE_AV_AUD_MODE);
928 DUMPCORE(HDMI_CORE_AV_SPDIF_CTRL);
929 DUMPCORE(HDMI_CORE_AV_HW_SPDIF_FS);
930 DUMPCORE(HDMI_CORE_AV_SWAP_I2S);
931 DUMPCORE(HDMI_CORE_AV_SPDIF_ERTH);
932 DUMPCORE(HDMI_CORE_AV_I2S_IN_MAP);
933 DUMPCORE(HDMI_CORE_AV_I2S_IN_CTRL);
934 DUMPCORE(HDMI_CORE_AV_I2S_CHST0);
935 DUMPCORE(HDMI_CORE_AV_I2S_CHST1);
936 DUMPCORE(HDMI_CORE_AV_I2S_CHST2);
937 DUMPCORE(HDMI_CORE_AV_I2S_CHST4);
938 DUMPCORE(HDMI_CORE_AV_I2S_CHST5);
939 DUMPCORE(HDMI_CORE_AV_ASRC);
940 DUMPCORE(HDMI_CORE_AV_I2S_IN_LEN);
941 DUMPCORE(HDMI_CORE_AV_HDMI_CTRL);
942 DUMPCORE(HDMI_CORE_AV_AUDO_TXSTAT);
943 DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
944 DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
945 DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
946 DUMPCORE(HDMI_CORE_AV_TEST_TXCTRL);
947 DUMPCORE(HDMI_CORE_AV_DPD);
948 DUMPCORE(HDMI_CORE_AV_PB_CTRL1);
949 DUMPCORE(HDMI_CORE_AV_PB_CTRL2);
950 DUMPCORE(HDMI_CORE_AV_AVI_TYPE);
951 DUMPCORE(HDMI_CORE_AV_AVI_VERS);
952 DUMPCORE(HDMI_CORE_AV_AVI_LEN);
953 DUMPCORE(HDMI_CORE_AV_AVI_CHSUM);
954 DUMPCORE(HDMI_CORE_AV_SPD_TYPE);
955 DUMPCORE(HDMI_CORE_AV_SPD_VERS);
956 DUMPCORE(HDMI_CORE_AV_SPD_LEN);
957 DUMPCORE(HDMI_CORE_AV_SPD_CHSUM);
958 DUMPCORE(HDMI_CORE_AV_AUDIO_TYPE);
959 DUMPCORE(HDMI_CORE_AV_AUDIO_VERS);
960 DUMPCORE(HDMI_CORE_AV_AUDIO_LEN);
961 DUMPCORE(HDMI_CORE_AV_AUDIO_CHSUM);
962 DUMPCORE(HDMI_CORE_AV_MPEG_TYPE);
963 DUMPCORE(HDMI_CORE_AV_MPEG_VERS);
964 DUMPCORE(HDMI_CORE_AV_MPEG_LEN);
965 DUMPCORE(HDMI_CORE_AV_MPEG_CHSUM);
966 DUMPCORE(HDMI_CORE_AV_CP_BYTE1);
967 DUMPCORE(HDMI_CORE_AV_CEC_ADDR_ID);
968}
969
970void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
971{
972#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
973 hdmi_read_reg(hdmi_phy_base(ip_data), r))
974
975 DUMPPHY(HDMI_TXPHY_TX_CTRL);
976 DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
977 DUMPPHY(HDMI_TXPHY_POWER_CTRL);
978 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
979}
980
981#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
982 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
983void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
984 struct hdmi_audio_format *aud_fmt)
985{
986 u32 r;
987
988 DSSDBG("Enter hdmi_wp_audio_config_format\n");
989
990 r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG);
991 r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
992 r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
993 r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
994 r = FLD_MOD(r, aud_fmt->type, 4, 4);
995 r = FLD_MOD(r, aud_fmt->justification, 3, 3);
996 r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
997 r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
998 r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
999 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r);
1000}
1001
1002void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
1003 struct hdmi_audio_dma *aud_dma)
1004{
1005 u32 r;
1006
1007 DSSDBG("Enter hdmi_wp_audio_config_dma\n");
1008
1009 r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2);
1010 r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
1011 r = FLD_MOD(r, aud_dma->block_size, 7, 0);
1012 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2, r);
1013
1014 r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL);
1015 r = FLD_MOD(r, aud_dma->mode, 9, 9);
1016 r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
1017 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r);
1018}
1019
1020void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
1021 struct hdmi_core_audio_config *cfg)
1022{
1023 u32 r;
1024 void __iomem *av_base = hdmi_av_base(ip_data);
1025
1026 /* audio clock recovery parameters */
1027 r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL);
1028 r = FLD_MOD(r, cfg->use_mclk, 2, 2);
1029 r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
1030 r = FLD_MOD(r, cfg->cts_mode, 0, 0);
1031 hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
1032
1033 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
1034 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
1035 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
1036
1037 if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
1038 REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
1039 REG_FLD_MOD(av_base,
1040 HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
1041 REG_FLD_MOD(av_base,
1042 HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
1043 } else {
1044 /*
1045 * HDMI IP uses this configuration to divide the MCLK to
1046 * update CTS value.
1047 */
1048 REG_FLD_MOD(av_base,
1049 HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
1050
1051 /* Configure clock for audio packets */
1052 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
1053 cfg->aud_par_busclk, 7, 0);
1054 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
1055 (cfg->aud_par_busclk >> 8), 7, 0);
1056 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
1057 (cfg->aud_par_busclk >> 16), 7, 0);
1058 }
1059
1060 /* Override of SPDIF sample frequency with value in I2S_CHST4 */
1061 REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
1062 cfg->fs_override, 1, 1);
1063
1064 /* I2S parameters */
1065 REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_CHST4,
1066 cfg->freq_sample, 3, 0);
1067
1068 r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL);
1069 r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
1070 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
1071 r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
1072 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
1073 r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
1074 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
1075 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
1076 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
1077 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r);
1078
1079 r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_CHST5);
1080 r = FLD_MOD(r, cfg->freq_sample, 7, 4);
1081 r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
1082 r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
1083 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, r);
1084
1085 REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN,
1086 cfg->i2s_cfg.in_length_bits, 3, 0);
1087
1088 /* Audio channels and mode parameters */
1089 REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
1090 r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE);
1091 r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
1092 r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
1093 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
1094 r = FLD_MOD(r, cfg->en_spdif, 1, 1);
1095 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
1096}
1097
1098void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
1099 struct hdmi_core_infoframe_audio *info_aud)
1100{
1101 u8 val;
1102 u8 sum = 0, checksum = 0;
1103 void __iomem *av_base = hdmi_av_base(ip_data);
1104
1105 /*
1106 * Set audio info frame type, version and length as
1107 * described in HDMI 1.4a Section 8.2.2 specification.
1108 * Checksum calculation is defined in Section 5.3.5.
1109 */
1110 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84);
1111 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01);
1112 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a);
1113 sum += 0x84 + 0x001 + 0x00a;
1114
1115 val = (info_aud->db1_coding_type << 4)
1116 | (info_aud->db1_channel_count - 1);
1117 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), val);
1118 sum += val;
1119
1120 val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
1121 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), val);
1122 sum += val;
1123
1124 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
1125
1126 val = info_aud->db4_channel_alloc;
1127 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), val);
1128 sum += val;
1129
1130 val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
1131 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), val);
1132 sum += val;
1133
1134 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
1135 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
1136 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
1137 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
1138 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
1139
1140 checksum = 0x100 - sum;
1141 hdmi_write_reg(av_base,
1142 HDMI_CORE_AV_AUDIO_CHSUM, checksum);
1143
1144 /*
1145 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
1146 * is available.
1147 */
1148}
1149
1150int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
1151 u32 sample_freq, u32 *n, u32 *cts)
1152{
1153 u32 r;
1154 u32 deep_color = 0;
1155 u32 pclk = ip_data->cfg.timings.timings.pixel_clock;
1156
1157 if (n == NULL || cts == NULL)
1158 return -EINVAL;
1159 /*
1160 * Obtain current deep color configuration. This needed
1161 * to calculate the TMDS clock based on the pixel clock.
1162 */
1163 r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0);
1164 switch (r) {
1165 case 1: /* No deep color selected */
1166 deep_color = 100;
1167 break;
1168 case 2: /* 10-bit deep color selected */
1169 deep_color = 125;
1170 break;
1171 case 3: /* 12-bit deep color selected */
1172 deep_color = 150;
1173 break;
1174 default:
1175 return -EINVAL;
1176 }
1177
1178 switch (sample_freq) {
1179 case 32000:
1180 if ((deep_color == 125) && ((pclk == 54054)
1181 || (pclk == 74250)))
1182 *n = 8192;
1183 else
1184 *n = 4096;
1185 break;
1186 case 44100:
1187 *n = 6272;
1188 break;
1189 case 48000:
1190 if ((deep_color == 125) && ((pclk == 54054)
1191 || (pclk == 74250)))
1192 *n = 8192;
1193 else
1194 *n = 6144;
1195 break;
1196 default:
1197 *n = 0;
1198 return -EINVAL;
1199 }
1200
1201 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
1202 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
1203
1204 return 0;
1205}
1206
1207int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
1208 struct snd_pcm_substream *substream, int cmd,
1209 struct snd_soc_dai *dai)
1210{
1211 int err = 0;
1212 switch (cmd) {
1213 case SNDRV_PCM_TRIGGER_START:
1214 case SNDRV_PCM_TRIGGER_RESUME:
1215 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1216 REG_FLD_MOD(hdmi_av_base(ip_data),
1217 HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
1218 REG_FLD_MOD(hdmi_wp_base(ip_data),
1219 HDMI_WP_AUDIO_CTRL, 1, 31, 31);
1220 REG_FLD_MOD(hdmi_wp_base(ip_data),
1221 HDMI_WP_AUDIO_CTRL, 1, 30, 30);
1222 break;
1223
1224 case SNDRV_PCM_TRIGGER_STOP:
1225 case SNDRV_PCM_TRIGGER_SUSPEND:
1226 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1227 REG_FLD_MOD(hdmi_av_base(ip_data),
1228 HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
1229 REG_FLD_MOD(hdmi_wp_base(ip_data),
1230 HDMI_WP_AUDIO_CTRL, 0, 30, 30);
1231 REG_FLD_MOD(hdmi_wp_base(ip_data),
1232 HDMI_WP_AUDIO_CTRL, 0, 31, 31);
1233 break;
1234 default:
1235 err = -EINVAL;
1236 }
1237 return err;
1238}
1239#endif
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
index c885f9cb065..204095632d2 100644
--- a/drivers/video/omap2/dss/hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * hdmi.h 2 * ti_hdmi_4xxx_ip.h
3 * 3 *
4 * HDMI driver definition for TI OMAP4 processors. 4 * HDMI header definition for DM81xx, DM38xx, TI OMAP4 etc processors.
5 * 5 *
6 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ 6 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
7 * 7 *
@@ -18,202 +18,177 @@
18 * this program. If not, see <http://www.gnu.org/licenses/>. 18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */ 19 */
20 20
21#ifndef _OMAP4_DSS_HDMI_H_ 21#ifndef _HDMI_TI_4xxx_H_
22#define _OMAP4_DSS_HDMI_H_ 22#define _HDMI_TI_4xxx_H_
23 23
24#include <linux/string.h> 24#include <linux/string.h>
25#include <video/omapdss.h> 25#include <video/omapdss.h>
26 26#include "ti_hdmi.h"
27#define HDMI_WP 0x0 27#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
28#define HDMI_CORE_SYS 0x400 28 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
29#define HDMI_CORE_AV 0x900 29#include <sound/soc.h>
30#define HDMI_PLLCTRL 0x200 30#include <sound/pcm_params.h>
31#define HDMI_PHY 0x300 31#endif
32
33struct hdmi_reg { u16 idx; };
34
35#define HDMI_REG(idx) ((const struct hdmi_reg) { idx })
36 32
37/* HDMI Wrapper */ 33/* HDMI Wrapper */
38#define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx) 34
39 35#define HDMI_WP_REVISION 0x0
40#define HDMI_WP_REVISION HDMI_WP_REG(0x0) 36#define HDMI_WP_SYSCONFIG 0x10
41#define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10) 37#define HDMI_WP_IRQSTATUS_RAW 0x24
42#define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24) 38#define HDMI_WP_IRQSTATUS 0x28
43#define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28) 39#define HDMI_WP_PWR_CTRL 0x40
44#define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40) 40#define HDMI_WP_IRQENABLE_SET 0x2C
45#define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C) 41#define HDMI_WP_VIDEO_CFG 0x50
46#define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50) 42#define HDMI_WP_VIDEO_SIZE 0x60
47#define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60) 43#define HDMI_WP_VIDEO_TIMING_H 0x68
48#define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68) 44#define HDMI_WP_VIDEO_TIMING_V 0x6C
49#define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C) 45#define HDMI_WP_WP_CLK 0x70
50#define HDMI_WP_WP_CLK HDMI_WP_REG(0x70) 46#define HDMI_WP_AUDIO_CFG 0x80
51#define HDMI_WP_AUDIO_CFG HDMI_WP_REG(0x80) 47#define HDMI_WP_AUDIO_CFG2 0x84
52#define HDMI_WP_AUDIO_CFG2 HDMI_WP_REG(0x84) 48#define HDMI_WP_AUDIO_CTRL 0x88
53#define HDMI_WP_AUDIO_CTRL HDMI_WP_REG(0x88) 49#define HDMI_WP_AUDIO_DATA 0x8C
54#define HDMI_WP_AUDIO_DATA HDMI_WP_REG(0x8C)
55 50
56/* HDMI IP Core System */ 51/* HDMI IP Core System */
57#define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx) 52
58 53#define HDMI_CORE_SYS_VND_IDL 0x0
59#define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0) 54#define HDMI_CORE_SYS_DEV_IDL 0x8
60#define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8) 55#define HDMI_CORE_SYS_DEV_IDH 0xC
61#define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC) 56#define HDMI_CORE_SYS_DEV_REV 0x10
62#define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10) 57#define HDMI_CORE_SYS_SRST 0x14
63#define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14) 58#define HDMI_CORE_CTRL1 0x20
64#define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20) 59#define HDMI_CORE_SYS_SYS_STAT 0x24
65#define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24) 60#define HDMI_CORE_SYS_VID_ACEN 0x124
66#define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124) 61#define HDMI_CORE_SYS_VID_MODE 0x128
67#define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128) 62#define HDMI_CORE_SYS_INTR_STATE 0x1C0
68#define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0) 63#define HDMI_CORE_SYS_INTR1 0x1C4
69#define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4) 64#define HDMI_CORE_SYS_INTR2 0x1C8
70#define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8) 65#define HDMI_CORE_SYS_INTR3 0x1CC
71#define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC) 66#define HDMI_CORE_SYS_INTR4 0x1D0
72#define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0) 67#define HDMI_CORE_SYS_UMASK1 0x1D4
73#define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4) 68#define HDMI_CORE_SYS_TMDS_CTRL 0x208
74#define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208) 69#define HDMI_CORE_SYS_DE_DLY 0xC8
75#define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8) 70#define HDMI_CORE_SYS_DE_CTRL 0xCC
76#define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC) 71#define HDMI_CORE_SYS_DE_TOP 0xD0
77#define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0) 72#define HDMI_CORE_SYS_DE_CNTL 0xD8
78#define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8) 73#define HDMI_CORE_SYS_DE_CNTH 0xDC
79#define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC) 74#define HDMI_CORE_SYS_DE_LINL 0xE0
80#define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0) 75#define HDMI_CORE_SYS_DE_LINH_1 0xE4
81#define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4)
82#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 76#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1
83#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 77#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1
84#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 78#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1
85#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 79#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1
86 80
87/* HDMI DDC E-DID */ 81/* HDMI DDC E-DID */
88#define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC) 82#define HDMI_CORE_DDC_CMD 0x3CC
89#define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8) 83#define HDMI_CORE_DDC_STATUS 0x3C8
90#define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4) 84#define HDMI_CORE_DDC_ADDR 0x3B4
91#define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC) 85#define HDMI_CORE_DDC_OFFSET 0x3BC
92#define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0) 86#define HDMI_CORE_DDC_COUNT1 0x3C0
93#define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4) 87#define HDMI_CORE_DDC_COUNT2 0x3C4
94#define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0) 88#define HDMI_CORE_DDC_DATA 0x3D0
95#define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8) 89#define HDMI_CORE_DDC_SEGM 0x3B8
96 90
97/* HDMI IP Core Audio Video */ 91/* HDMI IP Core Audio Video */
98#define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx) 92
99 93#define HDMI_CORE_AV_HDMI_CTRL 0xBC
100#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) 94#define HDMI_CORE_AV_DPD 0xF4
101#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) 95#define HDMI_CORE_AV_PB_CTRL1 0xF8
102#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) 96#define HDMI_CORE_AV_PB_CTRL2 0xFC
103#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) 97#define HDMI_CORE_AV_AVI_TYPE 0x100
104#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) 98#define HDMI_CORE_AV_AVI_VERS 0x104
105#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) 99#define HDMI_CORE_AV_AVI_LEN 0x108
106#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) 100#define HDMI_CORE_AV_AVI_CHSUM 0x10C
107#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) 101#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110)
108#define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110) 102#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15
109#define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15) 103#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190)
110#define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190) 104#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27
111#define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27) 105#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210)
112#define HDMI_CORE_AV_AUD_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x210) 106#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10
113#define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_CORE_AV_REG(10) 107#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290)
114#define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290) 108#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27
115#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27) 109#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300)
116#define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300) 110#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31
117#define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31) 111#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380)
118#define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380) 112#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31
119#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31) 113#define HDMI_CORE_AV_ACR_CTRL 0x4
120#define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4) 114#define HDMI_CORE_AV_FREQ_SVAL 0x8
121#define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8) 115#define HDMI_CORE_AV_N_SVAL1 0xC
122#define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC) 116#define HDMI_CORE_AV_N_SVAL2 0x10
123#define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10) 117#define HDMI_CORE_AV_N_SVAL3 0x14
124#define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14) 118#define HDMI_CORE_AV_CTS_SVAL1 0x18
125#define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18) 119#define HDMI_CORE_AV_CTS_SVAL2 0x1C
126#define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C) 120#define HDMI_CORE_AV_CTS_SVAL3 0x20
127#define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20) 121#define HDMI_CORE_AV_CTS_HVAL1 0x24
128#define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24) 122#define HDMI_CORE_AV_CTS_HVAL2 0x28
129#define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28) 123#define HDMI_CORE_AV_CTS_HVAL3 0x2C
130#define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C) 124#define HDMI_CORE_AV_AUD_MODE 0x50
131#define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50) 125#define HDMI_CORE_AV_SPDIF_CTRL 0x54
132#define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54) 126#define HDMI_CORE_AV_HW_SPDIF_FS 0x60
133#define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60) 127#define HDMI_CORE_AV_SWAP_I2S 0x64
134#define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64) 128#define HDMI_CORE_AV_SPDIF_ERTH 0x6C
135#define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C) 129#define HDMI_CORE_AV_I2S_IN_MAP 0x70
136#define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70) 130#define HDMI_CORE_AV_I2S_IN_CTRL 0x74
137#define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74) 131#define HDMI_CORE_AV_I2S_CHST0 0x78
138#define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78) 132#define HDMI_CORE_AV_I2S_CHST1 0x7C
139#define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C) 133#define HDMI_CORE_AV_I2S_CHST2 0x80
140#define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80) 134#define HDMI_CORE_AV_I2S_CHST4 0x84
141#define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84) 135#define HDMI_CORE_AV_I2S_CHST5 0x88
142#define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88) 136#define HDMI_CORE_AV_ASRC 0x8C
143#define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C) 137#define HDMI_CORE_AV_I2S_IN_LEN 0x90
144#define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90) 138#define HDMI_CORE_AV_HDMI_CTRL 0xBC
145#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) 139#define HDMI_CORE_AV_AUDO_TXSTAT 0xC0
146#define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0) 140#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 0xCC
147#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC) 141#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 0xD0
148#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0) 142#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 0xD4
149#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4) 143#define HDMI_CORE_AV_TEST_TXCTRL 0xF0
150#define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0) 144#define HDMI_CORE_AV_DPD 0xF4
151#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) 145#define HDMI_CORE_AV_PB_CTRL1 0xF8
152#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) 146#define HDMI_CORE_AV_PB_CTRL2 0xFC
153#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) 147#define HDMI_CORE_AV_AVI_TYPE 0x100
154#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) 148#define HDMI_CORE_AV_AVI_VERS 0x104
155#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) 149#define HDMI_CORE_AV_AVI_LEN 0x108
156#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) 150#define HDMI_CORE_AV_AVI_CHSUM 0x10C
157#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) 151#define HDMI_CORE_AV_SPD_TYPE 0x180
158#define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180) 152#define HDMI_CORE_AV_SPD_VERS 0x184
159#define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184) 153#define HDMI_CORE_AV_SPD_LEN 0x188
160#define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188) 154#define HDMI_CORE_AV_SPD_CHSUM 0x18C
161#define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C) 155#define HDMI_CORE_AV_AUDIO_TYPE 0x200
162#define HDMI_CORE_AV_AUDIO_TYPE HDMI_CORE_AV_REG(0x200) 156#define HDMI_CORE_AV_AUDIO_VERS 0x204
163#define HDMI_CORE_AV_AUDIO_VERS HDMI_CORE_AV_REG(0x204) 157#define HDMI_CORE_AV_AUDIO_LEN 0x208
164#define HDMI_CORE_AV_AUDIO_LEN HDMI_CORE_AV_REG(0x208) 158#define HDMI_CORE_AV_AUDIO_CHSUM 0x20C
165#define HDMI_CORE_AV_AUDIO_CHSUM HDMI_CORE_AV_REG(0x20C) 159#define HDMI_CORE_AV_MPEG_TYPE 0x280
166#define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280) 160#define HDMI_CORE_AV_MPEG_VERS 0x284
167#define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284) 161#define HDMI_CORE_AV_MPEG_LEN 0x288
168#define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288) 162#define HDMI_CORE_AV_MPEG_CHSUM 0x28C
169#define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C) 163#define HDMI_CORE_AV_CP_BYTE1 0x37C
170#define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C) 164#define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC
171#define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC)
172#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 165#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4
173#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 166#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4
174#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 167#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4
175#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 168#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4
176 169
177/* PLL */ 170/* PLL */
178#define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx)
179 171
180#define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0) 172#define PLLCTRL_PLL_CONTROL 0x0
181#define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4) 173#define PLLCTRL_PLL_STATUS 0x4
182#define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8) 174#define PLLCTRL_PLL_GO 0x8
183#define PLLCTRL_CFG1 HDMI_PLL_REG(0xC) 175#define PLLCTRL_CFG1 0xC
184#define PLLCTRL_CFG2 HDMI_PLL_REG(0x10) 176#define PLLCTRL_CFG2 0x10
185#define PLLCTRL_CFG3 HDMI_PLL_REG(0x14) 177#define PLLCTRL_CFG3 0x14
186#define PLLCTRL_CFG4 HDMI_PLL_REG(0x20) 178#define PLLCTRL_CFG4 0x20
187 179
188/* HDMI PHY */ 180/* HDMI PHY */
189#define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx)
190
191#define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0)
192#define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4)
193#define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8)
194#define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC)
195
196/* HDMI EDID Length */
197#define HDMI_EDID_MAX_LENGTH 256
198#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
199#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
200#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
201#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
202#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
203 181
204#define OMAP_HDMI_TIMINGS_NB 34 182#define HDMI_TXPHY_TX_CTRL 0x0
183#define HDMI_TXPHY_DIGITAL_CTRL 0x4
184#define HDMI_TXPHY_POWER_CTRL 0x8
185#define HDMI_TXPHY_PAD_CFG_CTRL 0xC
205 186
206#define REG_FLD_MOD(idx, val, start, end) \ 187#define REG_FLD_MOD(base, idx, val, start, end) \
207 hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end)) 188 hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
208#define REG_GET(idx, start, end) \ 189 val, start, end))
209 FLD_GET(hdmi_read_reg(idx), start, end) 190#define REG_GET(base, idx, start, end) \
210 191 FLD_GET(hdmi_read_reg(base, idx), start, end)
211/* HDMI timing structure */
212struct hdmi_timings {
213 struct omap_video_timings timings;
214 int vsync_pol;
215 int hsync_pol;
216};
217 192
218enum hdmi_phy_pwr { 193enum hdmi_phy_pwr {
219 HDMI_PHYPWRCMD_OFF = 0, 194 HDMI_PHYPWRCMD_OFF = 0,
@@ -221,20 +196,6 @@ enum hdmi_phy_pwr {
221 HDMI_PHYPWRCMD_TXON = 2 196 HDMI_PHYPWRCMD_TXON = 2
222}; 197};
223 198
224enum hdmi_pll_pwr {
225 HDMI_PLLPWRCMD_ALLOFF = 0,
226 HDMI_PLLPWRCMD_PLLONLY = 1,
227 HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
228 HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
229};
230
231enum hdmi_clk_refsel {
232 HDMI_REFSEL_PCLK = 0,
233 HDMI_REFSEL_REF1 = 1,
234 HDMI_REFSEL_REF2 = 2,
235 HDMI_REFSEL_SYSCLK = 3
236};
237
238enum hdmi_core_inputbus_width { 199enum hdmi_core_inputbus_width {
239 HDMI_INPUT_8BIT = 0, 200 HDMI_INPUT_8BIT = 0,
240 HDMI_INPUT_10BIT = 1, 201 HDMI_INPUT_10BIT = 1,
@@ -263,11 +224,6 @@ enum hdmi_core_packet_mode {
263 HDMI_PACKETMODE48BITPERPIXEL = 7 224 HDMI_PACKETMODE48BITPERPIXEL = 7
264}; 225};
265 226
266enum hdmi_core_hdmi_dvi {
267 HDMI_DVI = 0,
268 HDMI_HDMI = 1
269};
270
271enum hdmi_core_tclkselclkmult { 227enum hdmi_core_tclkselclkmult {
272 HDMI_FPLL05IDCK = 0, 228 HDMI_FPLL05IDCK = 0,
273 HDMI_FPLL10IDCK = 1, 229 HDMI_FPLL10IDCK = 1,
@@ -495,40 +451,40 @@ struct hdmi_core_video_config {
495 * details about infoframe databytes 451 * details about infoframe databytes
496 */ 452 */
497struct hdmi_core_infoframe_avi { 453struct hdmi_core_infoframe_avi {
454 /* Y0, Y1 rgb,yCbCr */
498 u8 db1_format; 455 u8 db1_format;
499 /* Y0, Y1 rgb,yCbCr */ 456 /* A0 Active information Present */
500 u8 db1_active_info; 457 u8 db1_active_info;
501 /* A0 Active information Present */ 458 /* B0, B1 Bar info data valid */
502 u8 db1_bar_info_dv; 459 u8 db1_bar_info_dv;
503 /* B0, B1 Bar info data valid */ 460 /* S0, S1 scan information */
504 u8 db1_scan_info; 461 u8 db1_scan_info;
505 /* S0, S1 scan information */ 462 /* C0, C1 colorimetry */
506 u8 db2_colorimetry; 463 u8 db2_colorimetry;
507 /* C0, C1 colorimetry */ 464 /* M0, M1 Aspect ratio (4:3, 16:9) */
508 u8 db2_aspect_ratio; 465 u8 db2_aspect_ratio;
509 /* M0, M1 Aspect ratio (4:3, 16:9) */ 466 /* R0...R3 Active format aspect ratio */
510 u8 db2_active_fmt_ar; 467 u8 db2_active_fmt_ar;
511 /* R0...R3 Active format aspect ratio */ 468 /* ITC IT content. */
512 u8 db3_itc; 469 u8 db3_itc;
513 /* ITC IT content. */ 470 /* EC0, EC1, EC2 Extended colorimetry */
514 u8 db3_ec; 471 u8 db3_ec;
515 /* EC0, EC1, EC2 Extended colorimetry */ 472 /* Q1, Q0 Quantization range */
516 u8 db3_q_range; 473 u8 db3_q_range;
517 /* Q1, Q0 Quantization range */ 474 /* SC1, SC0 Non-uniform picture scaling */
518 u8 db3_nup_scaling; 475 u8 db3_nup_scaling;
519 /* SC1, SC0 Non-uniform picture scaling */ 476 /* VIC0..6 Video format identification */
520 u8 db4_videocode; 477 u8 db4_videocode;
521 /* VIC0..6 Video format identification */ 478 /* PR0..PR3 Pixel repetition factor */
522 u8 db5_pixel_repeat; 479 u8 db5_pixel_repeat;
523 /* PR0..PR3 Pixel repetition factor */ 480 /* Line number end of top bar */
524 u16 db6_7_line_eoftop; 481 u16 db6_7_line_eoftop;
525 /* Line number end of top bar */ 482 /* Line number start of bottom bar */
526 u16 db8_9_line_sofbottom; 483 u16 db8_9_line_sofbottom;
527 /* Line number start of bottom bar */ 484 /* Pixel number end of left bar */
528 u16 db10_11_pixel_eofleft; 485 u16 db10_11_pixel_eofleft;
529 /* Pixel number end of left bar */ 486 /* Pixel number start of right bar */
530 u16 db12_13_pixel_sofright; 487 u16 db12_13_pixel_sofright;
531 /* Pixel number start of right bar */
532}; 488};
533/* 489/*
534 * Refer to section 8.2 in HDMI 1.3 specification for 490 * Refer to section 8.2 in HDMI 1.3 specification for
@@ -568,17 +524,6 @@ struct hdmi_video_interface {
568 int tm; /* Timing mode */ 524 int tm; /* Timing mode */
569}; 525};
570 526
571struct hdmi_cm {
572 int code;
573 int mode;
574};
575
576struct hdmi_config {
577 struct hdmi_timings timings;
578 u16 interlace;
579 struct hdmi_cm cm;
580};
581
582struct hdmi_audio_format { 527struct hdmi_audio_format {
583 enum hdmi_stereo_channels stereo_channels; 528 enum hdmi_stereo_channels stereo_channels;
584 u8 active_chnnls_msk; 529 u8 active_chnnls_msk;
@@ -628,4 +573,21 @@ struct hdmi_core_audio_config {
628 bool en_parallel_aud_input; 573 bool en_parallel_aud_input;
629 bool en_spdif; 574 bool en_spdif;
630}; 575};
576
577#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
578 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
579int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
580 struct snd_pcm_substream *substream, int cmd,
581 struct snd_soc_dai *dai);
582int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
583 u32 sample_freq, u32 *n, u32 *cts);
584void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
585 struct hdmi_core_infoframe_audio *info_aud);
586void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
587 struct hdmi_core_audio_config *cfg);
588void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
589 struct hdmi_audio_dma *aud_dma);
590void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
591 struct hdmi_audio_format *aud_fmt);
592#endif
631#endif 593#endif
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 173c66430da..7533458ba4d 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -295,7 +295,6 @@ static struct {
295 u32 wss_data; 295 u32 wss_data;
296 struct regulator *vdda_dac_reg; 296 struct regulator *vdda_dac_reg;
297 297
298 struct clk *tv_clk;
299 struct clk *tv_dac_clk; 298 struct clk *tv_dac_clk;
300} venc; 299} venc;
301 300
@@ -464,9 +463,11 @@ static void venc_power_off(struct omap_dss_device *dssdev)
464 regulator_disable(venc.vdda_dac_reg); 463 regulator_disable(venc.vdda_dac_reg);
465} 464}
466 465
467 466unsigned long venc_get_pixel_clock(void)
468 467{
469 468 /* VENC Pixel Clock in Mhz */
469 return 13500000;
470}
470 471
471/* driver */ 472/* driver */
472static int venc_panel_probe(struct omap_dss_device *dssdev) 473static int venc_panel_probe(struct omap_dss_device *dssdev)
@@ -732,22 +733,10 @@ static int venc_get_clocks(struct platform_device *pdev)
732{ 733{
733 struct clk *clk; 734 struct clk *clk;
734 735
735 clk = clk_get(&pdev->dev, "fck");
736 if (IS_ERR(clk)) {
737 DSSERR("can't get fck\n");
738 return PTR_ERR(clk);
739 }
740
741 venc.tv_clk = clk;
742
743 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { 736 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
744 if (cpu_is_omap34xx() || cpu_is_omap3630()) 737 clk = clk_get(&pdev->dev, "tv_dac_clk");
745 clk = clk_get(&pdev->dev, "dss_96m_fck");
746 else
747 clk = clk_get(&pdev->dev, "tv_dac_clk");
748 if (IS_ERR(clk)) { 738 if (IS_ERR(clk)) {
749 DSSERR("can't get tv_dac_clk\n"); 739 DSSERR("can't get tv_dac_clk\n");
750 clk_put(venc.tv_clk);
751 return PTR_ERR(clk); 740 return PTR_ERR(clk);
752 } 741 }
753 } else { 742 } else {
@@ -761,8 +750,6 @@ static int venc_get_clocks(struct platform_device *pdev)
761 750
762static void venc_put_clocks(void) 751static void venc_put_clocks(void)
763{ 752{
764 if (venc.tv_clk)
765 clk_put(venc.tv_clk);
766 if (venc.tv_dac_clk) 753 if (venc.tv_dac_clk)
767 clk_put(venc.tv_dac_clk); 754 clk_put(venc.tv_dac_clk);
768} 755}
@@ -838,7 +825,6 @@ static int venc_runtime_suspend(struct device *dev)
838{ 825{
839 if (venc.tv_dac_clk) 826 if (venc.tv_dac_clk)
840 clk_disable(venc.tv_dac_clk); 827 clk_disable(venc.tv_dac_clk);
841 clk_disable(venc.tv_clk);
842 828
843 dispc_runtime_put(); 829 dispc_runtime_put();
844 dss_runtime_put(); 830 dss_runtime_put();
@@ -858,7 +844,6 @@ static int venc_runtime_resume(struct device *dev)
858 if (r < 0) 844 if (r < 0)
859 goto err_get_dispc; 845 goto err_get_dispc;
860 846
861 clk_enable(venc.tv_clk);
862 if (venc.tv_dac_clk) 847 if (venc.tv_dac_clk)
863 clk_enable(venc.tv_dac_clk); 848 clk_enable(venc.tv_dac_clk);
864 849
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index aa33386c81f..83d3fe7ec9a 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -1,5 +1,5 @@
1menuconfig FB_OMAP2 1menuconfig FB_OMAP2
2 tristate "OMAP2+ frame buffer support (EXPERIMENTAL)" 2 tristate "OMAP2+ frame buffer support"
3 depends on FB && OMAP2_DSS 3 depends on FB && OMAP2_DSS
4 4
5 select OMAP2_VRAM 5 select OMAP2_VRAM
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 602b71a92d3..70aa47de714 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -808,19 +808,15 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
808static void omapfb_calc_addr(const struct omapfb_info *ofbi, 808static void omapfb_calc_addr(const struct omapfb_info *ofbi,
809 const struct fb_var_screeninfo *var, 809 const struct fb_var_screeninfo *var,
810 const struct fb_fix_screeninfo *fix, 810 const struct fb_fix_screeninfo *fix,
811 int rotation, u32 *paddr, void __iomem **vaddr) 811 int rotation, u32 *paddr)
812{ 812{
813 u32 data_start_p; 813 u32 data_start_p;
814 void __iomem *data_start_v;
815 int offset; 814 int offset;
816 815
817 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 816 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
818 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); 817 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
819 data_start_v = NULL; 818 else
820 } else {
821 data_start_p = omapfb_get_region_paddr(ofbi); 819 data_start_p = omapfb_get_region_paddr(ofbi);
822 data_start_v = omapfb_get_region_vaddr(ofbi);
823 }
824 820
825 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 821 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
826 offset = calc_rotation_offset_vrfb(var, fix, rotation); 822 offset = calc_rotation_offset_vrfb(var, fix, rotation);
@@ -828,16 +824,14 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi,
828 offset = calc_rotation_offset_dma(var, fix, rotation); 824 offset = calc_rotation_offset_dma(var, fix, rotation);
829 825
830 data_start_p += offset; 826 data_start_p += offset;
831 data_start_v += offset;
832 827
833 if (offset) 828 if (offset)
834 DBG("offset %d, %d = %d\n", 829 DBG("offset %d, %d = %d\n",
835 var->xoffset, var->yoffset, offset); 830 var->xoffset, var->yoffset, offset);
836 831
837 DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v); 832 DBG("paddr %x\n", data_start_p);
838 833
839 *paddr = data_start_p; 834 *paddr = data_start_p;
840 *vaddr = data_start_v;
841} 835}
842 836
843/* setup overlay according to the fb */ 837/* setup overlay according to the fb */
@@ -850,7 +844,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
850 struct fb_fix_screeninfo *fix = &fbi->fix; 844 struct fb_fix_screeninfo *fix = &fbi->fix;
851 enum omap_color_mode mode = 0; 845 enum omap_color_mode mode = 0;
852 u32 data_start_p = 0; 846 u32 data_start_p = 0;
853 void __iomem *data_start_v = NULL;
854 struct omap_overlay_info info; 847 struct omap_overlay_info info;
855 int xres, yres; 848 int xres, yres;
856 int screen_width; 849 int screen_width;
@@ -880,8 +873,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
880 } 873 }
881 874
882 if (ofbi->region->size) 875 if (ofbi->region->size)
883 omapfb_calc_addr(ofbi, var, fix, rotation, 876 omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
884 &data_start_p, &data_start_v);
885 877
886 r = fb_mode_to_dss_mode(var, &mode); 878 r = fb_mode_to_dss_mode(var, &mode);
887 if (r) { 879 if (r) {
@@ -910,7 +902,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
910 mirror = ofbi->mirror; 902 mirror = ofbi->mirror;
911 903
912 info.paddr = data_start_p; 904 info.paddr = data_start_p;
913 info.vaddr = data_start_v;
914 info.screen_width = screen_width; 905 info.screen_width = screen_width;
915 info.width = xres; 906 info.width = xres;
916 info.height = yres; 907 info.height = yres;
@@ -2276,6 +2267,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2276 return r; 2267 return r;
2277} 2268}
2278 2269
2270static void fb_videomode_to_omap_timings(struct fb_videomode *m,
2271 struct omap_video_timings *t)
2272{
2273 t->x_res = m->xres;
2274 t->y_res = m->yres;
2275 t->pixel_clock = PICOS2KHZ(m->pixclock);
2276 t->hsw = m->hsync_len;
2277 t->hfp = m->right_margin;
2278 t->hbp = m->left_margin;
2279 t->vsw = m->vsync_len;
2280 t->vfp = m->lower_margin;
2281 t->vbp = m->upper_margin;
2282}
2283
2284static int omapfb_find_best_mode(struct omap_dss_device *display,
2285 struct omap_video_timings *timings)
2286{
2287 struct fb_monspecs *specs;
2288 u8 *edid;
2289 int r, i, best_xres, best_idx, len;
2290
2291 if (!display->driver->read_edid)
2292 return -ENODEV;
2293
2294 len = 0x80 * 2;
2295 edid = kmalloc(len, GFP_KERNEL);
2296
2297 r = display->driver->read_edid(display, edid, len);
2298 if (r < 0)
2299 goto err1;
2300
2301 specs = kzalloc(sizeof(*specs), GFP_KERNEL);
2302
2303 fb_edid_to_monspecs(edid, specs);
2304
2305 if (edid[126] > 0)
2306 fb_edid_add_monspecs(edid + 0x80, specs);
2307
2308 best_xres = 0;
2309 best_idx = -1;
2310
2311 for (i = 0; i < specs->modedb_len; ++i) {
2312 struct fb_videomode *m;
2313 struct omap_video_timings t;
2314
2315 m = &specs->modedb[i];
2316
2317 if (m->pixclock == 0)
2318 continue;
2319
2320 /* skip repeated pixel modes */
2321 if (m->xres == 2880 || m->xres == 1440)
2322 continue;
2323
2324 fb_videomode_to_omap_timings(m, &t);
2325
2326 r = display->driver->check_timings(display, &t);
2327 if (r == 0 && best_xres < m->xres) {
2328 best_xres = m->xres;
2329 best_idx = i;
2330 }
2331 }
2332
2333 if (best_xres == 0) {
2334 r = -ENOENT;
2335 goto err2;
2336 }
2337
2338 fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
2339
2340 r = 0;
2341
2342err2:
2343 fb_destroy_modedb(specs->modedb);
2344 kfree(specs);
2345err1:
2346 kfree(edid);
2347
2348 return r;
2349}
2350
2279static int omapfb_init_display(struct omapfb2_device *fbdev, 2351static int omapfb_init_display(struct omapfb2_device *fbdev,
2280 struct omap_dss_device *dssdev) 2352 struct omap_dss_device *dssdev)
2281{ 2353{
@@ -2373,8 +2445,10 @@ static int omapfb_probe(struct platform_device *pdev)
2373 omap_dss_get_device(dssdev); 2445 omap_dss_get_device(dssdev);
2374 2446
2375 if (!dssdev->driver) { 2447 if (!dssdev->driver) {
2376 dev_err(&pdev->dev, "no driver for display\n"); 2448 dev_warn(&pdev->dev, "no driver for display: %s\n",
2377 r = -ENODEV; 2449 dssdev->name);
2450 omap_dss_put_device(dssdev);
2451 continue;
2378 } 2452 }
2379 2453
2380 d = &fbdev->displays[fbdev->num_displays++]; 2454 d = &fbdev->displays[fbdev->num_displays++];
@@ -2402,9 +2476,27 @@ static int omapfb_probe(struct platform_device *pdev)
2402 for (i = 0; i < fbdev->num_managers; i++) 2476 for (i = 0; i < fbdev->num_managers; i++)
2403 fbdev->managers[i] = omap_dss_get_overlay_manager(i); 2477 fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2404 2478
2479 /* gfx overlay should be the default one. find a display
2480 * connected to that, and use it as default display */
2481 ovl = omap_dss_get_overlay(0);
2482 if (ovl->manager && ovl->manager->device) {
2483 def_display = ovl->manager->device;
2484 } else {
2485 dev_warn(&pdev->dev, "cannot find default display\n");
2486 def_display = NULL;
2487 }
2488
2405 if (def_mode && strlen(def_mode) > 0) { 2489 if (def_mode && strlen(def_mode) > 0) {
2406 if (omapfb_parse_def_modes(fbdev)) 2490 if (omapfb_parse_def_modes(fbdev))
2407 dev_warn(&pdev->dev, "cannot parse default modes\n"); 2491 dev_warn(&pdev->dev, "cannot parse default modes\n");
2492 } else if (def_display && def_display->driver->set_timings &&
2493 def_display->driver->check_timings) {
2494 struct omap_video_timings t;
2495
2496 r = omapfb_find_best_mode(def_display, &t);
2497
2498 if (r == 0)
2499 def_display->driver->set_timings(def_display, &t);
2408 } 2500 }
2409 2501
2410 r = omapfb_create_framebuffers(fbdev); 2502 r = omapfb_create_framebuffers(fbdev);
@@ -2421,16 +2513,6 @@ static int omapfb_probe(struct platform_device *pdev)
2421 2513
2422 DBG("mgr->apply'ed\n"); 2514 DBG("mgr->apply'ed\n");
2423 2515
2424 /* gfx overlay should be the default one. find a display
2425 * connected to that, and use it as default display */
2426 ovl = omap_dss_get_overlay(0);
2427 if (ovl->manager && ovl->manager->device) {
2428 def_display = ovl->manager->device;
2429 } else {
2430 dev_warn(&pdev->dev, "cannot find default display\n");
2431 def_display = NULL;
2432 }
2433
2434 if (def_display) { 2516 if (def_display) {
2435 r = omapfb_init_display(fbdev, def_display); 2517 r = omapfb_init_display(fbdev, def_display);
2436 if (r) { 2518 if (r) {
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 153bf1aceeb..1694d5148f3 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -104,16 +104,14 @@ static ssize_t store_mirror(struct device *dev,
104{ 104{
105 struct fb_info *fbi = dev_get_drvdata(dev); 105 struct fb_info *fbi = dev_get_drvdata(dev);
106 struct omapfb_info *ofbi = FB2OFB(fbi); 106 struct omapfb_info *ofbi = FB2OFB(fbi);
107 int mirror; 107 bool mirror;
108 int r; 108 int r;
109 struct fb_var_screeninfo new_var; 109 struct fb_var_screeninfo new_var;
110 110
111 r = kstrtoint(buf, 0, &mirror); 111 r = strtobool(buf, &mirror);
112 if (r) 112 if (r)
113 return r; 113 return r;
114 114
115 mirror = !!mirror;
116
117 if (!lock_fb_info(fbi)) 115 if (!lock_fb_info(fbi))
118 return -ENODEV; 116 return -ENODEV;
119 117
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index f27ae16ead2..ae3caa6755c 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -490,7 +490,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var,
490 490
491 491
492/* 492/*
493 * Parse user speficied options (`video=platinumfb:') 493 * Parse user specified options (`video=platinumfb:')
494 */ 494 */
495static int __init platinumfb_setup(char *options) 495static int __init platinumfb_setup(char *options)
496{ 496{
@@ -683,7 +683,7 @@ static struct platform_driver platinum_driver =
683 .of_match_table = platinumfb_match, 683 .of_match_table = platinumfb_match,
684 }, 684 },
685 .probe = platinumfb_probe, 685 .probe = platinumfb_probe,
686 .remove = platinumfb_remove, 686 .remove = __devexit_p(platinumfb_remove),
687}; 687};
688 688
689static int __init platinumfb_init(void) 689static int __init platinumfb_init(void)
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 27f93aab6dd..dc7bfa91e57 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -973,8 +973,8 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var,
973{ 973{
974 struct pm2fb_par *p = info->par; 974 struct pm2fb_par *p = info->par;
975 u32 base; 975 u32 base;
976 u32 depth = (var->bits_per_pixel + 7) & ~7; 976 u32 depth = (info->var.bits_per_pixel + 7) & ~7;
977 u32 xres = (var->xres + 31) & ~31; 977 u32 xres = (info->var.xres + 31) & ~31;
978 978
979 depth = (depth > 32) ? 32 : depth; 979 depth = (depth > 32) ? 32 : depth;
980 base = to3264(var->yoffset * xres + var->xoffset, depth, 1); 980 base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
@@ -1773,7 +1773,7 @@ MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
1773 1773
1774#ifndef MODULE 1774#ifndef MODULE
1775/** 1775/**
1776 * Parse user speficied options. 1776 * Parse user specified options.
1777 * 1777 *
1778 * This is, comma-separated options following `video=pm2fb:'. 1778 * This is, comma-separated options following `video=pm2fb:'.
1779 */ 1779 */
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 6666f45a2f8..6632ee5ecb7 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -1147,9 +1147,9 @@ static int pm3fb_pan_display(struct fb_var_screeninfo *var,
1147 struct fb_info *info) 1147 struct fb_info *info)
1148{ 1148{
1149 struct pm3_par *par = info->par; 1149 struct pm3_par *par = info->par;
1150 const u32 xres = (var->xres + 31) & ~31; 1150 const u32 xres = (info->var.xres + 31) & ~31;
1151 1151
1152 par->base = pm3fb_shift_bpp(var->bits_per_pixel, 1152 par->base = pm3fb_shift_bpp(info->var.bits_per_pixel,
1153 (var->yoffset * xres) 1153 (var->yoffset * xres)
1154 + var->xoffset); 1154 + var->xoffset);
1155 PM3_WAIT(par, 1); 1155 PM3_WAIT(par, 1);
@@ -1525,7 +1525,7 @@ static int __init pm3fb_setup(char *options)
1525{ 1525{
1526 char *this_opt; 1526 char *this_opt;
1527 1527
1528 /* Parse user speficied options (`video=pm3fb:') */ 1528 /* Parse user specified options (`video=pm3fb:') */
1529 if (!options || !*options) 1529 if (!options || !*options)
1530 return 0; 1530 return 0;
1531 1531
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 65560a1a043..213fbbcf613 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -1082,7 +1082,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1082 } 1082 }
1083 1083
1084 retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, 1084 retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt,
1085 IRQF_DISABLED, DEVICE_NAME, &dev->core); 1085 0, DEVICE_NAME, &dev->core);
1086 if (retval) { 1086 if (retval) {
1087 dev_err(&dev->core, "%s: request_irq failed %d\n", __func__, 1087 dev_err(&dev->core, "%s: request_irq failed %d\n", __func__,
1088 retval); 1088 retval);
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
index 0283c702109..1ed8b366618 100644
--- a/drivers/video/pxa3xx-gcu.c
+++ b/drivers/video/pxa3xx-gcu.c
@@ -31,8 +31,6 @@
31 */ 31 */
32 32
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/version.h>
35
36#include <linux/platform_device.h> 34#include <linux/platform_device.h>
37#include <linux/dma-mapping.h> 35#include <linux/dma-mapping.h>
38#include <linux/miscdevice.h> 36#include <linux/miscdevice.h>
@@ -678,7 +676,7 @@ pxa3xx_gcu_probe(struct platform_device *dev)
678 } 676 }
679 677
680 ret = request_irq(irq, pxa3xx_gcu_handle_irq, 678 ret = request_irq(irq, pxa3xx_gcu_handle_irq,
681 IRQF_DISABLED, DRV_NAME, priv); 679 0, DRV_NAME, priv);
682 if (ret) { 680 if (ret) {
683 dev_err(&dev->dev, "request_irq failed\n"); 681 dev_err(&dev->dev, "request_irq failed\n");
684 ret = -EBUSY; 682 ret = -EBUSY;
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 0f4e8c942f9..e89778f4081 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -2191,7 +2191,7 @@ static int __devinit pxafb_probe(struct platform_device *dev)
2191 goto failed_free_mem; 2191 goto failed_free_mem;
2192 } 2192 }
2193 2193
2194 ret = request_irq(irq, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi); 2194 ret = request_irq(irq, pxafb_handle_irq, 0, "LCD", fbi);
2195 if (ret) { 2195 if (ret) {
2196 dev_err(&dev->dev, "request_irq failed: %d\n", ret); 2196 dev_err(&dev->dev, "request_irq failed: %d\n", ret);
2197 ret = -EBUSY; 2197 ret = -EBUSY;
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 4aecf213c9b..0753b1cfcb8 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -81,6 +81,7 @@ struct s3c_fb;
81 * @palette: Address of palette memory, or 0 if none. 81 * @palette: Address of palette memory, or 0 if none.
82 * @has_prtcon: Set if has PRTCON register. 82 * @has_prtcon: Set if has PRTCON register.
83 * @has_shadowcon: Set if has SHADOWCON register. 83 * @has_shadowcon: Set if has SHADOWCON register.
84 * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
84 */ 85 */
85struct s3c_fb_variant { 86struct s3c_fb_variant {
86 unsigned int is_2443:1; 87 unsigned int is_2443:1;
@@ -98,6 +99,7 @@ struct s3c_fb_variant {
98 99
99 unsigned int has_prtcon:1; 100 unsigned int has_prtcon:1;
100 unsigned int has_shadowcon:1; 101 unsigned int has_shadowcon:1;
102 unsigned int has_clksel:1;
101}; 103};
102 104
103/** 105/**
@@ -186,6 +188,7 @@ struct s3c_fb_vsync {
186 * @dev: The device that we bound to, for printing, etc. 188 * @dev: The device that we bound to, for printing, etc.
187 * @regs_res: The resource we claimed for the IO registers. 189 * @regs_res: The resource we claimed for the IO registers.
188 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. 190 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
191 * @lcd_clk: The clk (sclk) feeding pixclk.
189 * @regs: The mapped hardware registers. 192 * @regs: The mapped hardware registers.
190 * @variant: Variant information for this hardware. 193 * @variant: Variant information for this hardware.
191 * @enabled: A bitmask of enabled hardware windows. 194 * @enabled: A bitmask of enabled hardware windows.
@@ -200,6 +203,7 @@ struct s3c_fb {
200 struct device *dev; 203 struct device *dev;
201 struct resource *regs_res; 204 struct resource *regs_res;
202 struct clk *bus_clk; 205 struct clk *bus_clk;
206 struct clk *lcd_clk;
203 void __iomem *regs; 207 void __iomem *regs;
204 struct s3c_fb_variant variant; 208 struct s3c_fb_variant variant;
205 209
@@ -336,10 +340,15 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
336 */ 340 */
337static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) 341static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
338{ 342{
339 unsigned long clk = clk_get_rate(sfb->bus_clk); 343 unsigned long clk;
340 unsigned long long tmp; 344 unsigned long long tmp;
341 unsigned int result; 345 unsigned int result;
342 346
347 if (sfb->variant.has_clksel)
348 clk = clk_get_rate(sfb->bus_clk);
349 else
350 clk = clk_get_rate(sfb->lcd_clk);
351
343 tmp = (unsigned long long)clk; 352 tmp = (unsigned long long)clk;
344 tmp *= pixclk; 353 tmp *= pixclk;
345 354
@@ -883,7 +892,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
883 } 892 }
884 } 893 }
885 /* Offset in bytes to the end of the displayed area */ 894 /* Offset in bytes to the end of the displayed area */
886 end_boff = start_boff + var->yres * info->fix.line_length; 895 end_boff = start_boff + info->var.yres * info->fix.line_length;
887 896
888 /* Temporarily turn off per-vsync update from shadow registers until 897 /* Temporarily turn off per-vsync update from shadow registers until
889 * both start and end addresses are updated to prevent corruption */ 898 * both start and end addresses are updated to prevent corruption */
@@ -1354,13 +1363,24 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1354 1363
1355 clk_enable(sfb->bus_clk); 1364 clk_enable(sfb->bus_clk);
1356 1365
1366 if (!sfb->variant.has_clksel) {
1367 sfb->lcd_clk = clk_get(dev, "sclk_fimd");
1368 if (IS_ERR(sfb->lcd_clk)) {
1369 dev_err(dev, "failed to get lcd clock\n");
1370 ret = PTR_ERR(sfb->lcd_clk);
1371 goto err_bus_clk;
1372 }
1373
1374 clk_enable(sfb->lcd_clk);
1375 }
1376
1357 pm_runtime_enable(sfb->dev); 1377 pm_runtime_enable(sfb->dev);
1358 1378
1359 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1379 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1360 if (!res) { 1380 if (!res) {
1361 dev_err(dev, "failed to find registers\n"); 1381 dev_err(dev, "failed to find registers\n");
1362 ret = -ENOENT; 1382 ret = -ENOENT;
1363 goto err_clk; 1383 goto err_lcd_clk;
1364 } 1384 }
1365 1385
1366 sfb->regs_res = request_mem_region(res->start, resource_size(res), 1386 sfb->regs_res = request_mem_region(res->start, resource_size(res),
@@ -1368,7 +1388,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1368 if (!sfb->regs_res) { 1388 if (!sfb->regs_res) {
1369 dev_err(dev, "failed to claim register region\n"); 1389 dev_err(dev, "failed to claim register region\n");
1370 ret = -ENOENT; 1390 ret = -ENOENT;
1371 goto err_clk; 1391 goto err_lcd_clk;
1372 } 1392 }
1373 1393
1374 sfb->regs = ioremap(res->start, resource_size(res)); 1394 sfb->regs = ioremap(res->start, resource_size(res));
@@ -1450,7 +1470,13 @@ err_ioremap:
1450err_req_region: 1470err_req_region:
1451 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); 1471 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
1452 1472
1453err_clk: 1473err_lcd_clk:
1474 if (!sfb->variant.has_clksel) {
1475 clk_disable(sfb->lcd_clk);
1476 clk_put(sfb->lcd_clk);
1477 }
1478
1479err_bus_clk:
1454 clk_disable(sfb->bus_clk); 1480 clk_disable(sfb->bus_clk);
1455 clk_put(sfb->bus_clk); 1481 clk_put(sfb->bus_clk);
1456 1482
@@ -1481,6 +1507,11 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1481 1507
1482 iounmap(sfb->regs); 1508 iounmap(sfb->regs);
1483 1509
1510 if (!sfb->variant.has_clksel) {
1511 clk_disable(sfb->lcd_clk);
1512 clk_put(sfb->lcd_clk);
1513 }
1514
1484 clk_disable(sfb->bus_clk); 1515 clk_disable(sfb->bus_clk);
1485 clk_put(sfb->bus_clk); 1516 clk_put(sfb->bus_clk);
1486 1517
@@ -1510,6 +1541,9 @@ static int s3c_fb_suspend(struct device *dev)
1510 s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); 1541 s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
1511 } 1542 }
1512 1543
1544 if (!sfb->variant.has_clksel)
1545 clk_disable(sfb->lcd_clk);
1546
1513 clk_disable(sfb->bus_clk); 1547 clk_disable(sfb->bus_clk);
1514 return 0; 1548 return 0;
1515} 1549}
@@ -1524,6 +1558,9 @@ static int s3c_fb_resume(struct device *dev)
1524 1558
1525 clk_enable(sfb->bus_clk); 1559 clk_enable(sfb->bus_clk);
1526 1560
1561 if (!sfb->variant.has_clksel)
1562 clk_enable(sfb->lcd_clk);
1563
1527 /* setup gpio and output polarity controls */ 1564 /* setup gpio and output polarity controls */
1528 pd->setup_gpio(); 1565 pd->setup_gpio();
1529 writel(pd->vidcon1, sfb->regs + VIDCON1); 1566 writel(pd->vidcon1, sfb->regs + VIDCON1);
@@ -1569,6 +1606,9 @@ static int s3c_fb_runtime_suspend(struct device *dev)
1569 s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); 1606 s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
1570 } 1607 }
1571 1608
1609 if (!sfb->variant.has_clksel)
1610 clk_disable(sfb->lcd_clk);
1611
1572 clk_disable(sfb->bus_clk); 1612 clk_disable(sfb->bus_clk);
1573 return 0; 1613 return 0;
1574} 1614}
@@ -1583,6 +1623,9 @@ static int s3c_fb_runtime_resume(struct device *dev)
1583 1623
1584 clk_enable(sfb->bus_clk); 1624 clk_enable(sfb->bus_clk);
1585 1625
1626 if (!sfb->variant.has_clksel)
1627 clk_enable(sfb->lcd_clk);
1628
1586 /* setup gpio and output polarity controls */ 1629 /* setup gpio and output polarity controls */
1587 pd->setup_gpio(); 1630 pd->setup_gpio();
1588 writel(pd->vidcon1, sfb->regs + VIDCON1); 1631 writel(pd->vidcon1, sfb->regs + VIDCON1);
@@ -1755,6 +1798,7 @@ static struct s3c_fb_driverdata s3c_fb_data_64xx = {
1755 }, 1798 },
1756 1799
1757 .has_prtcon = 1, 1800 .has_prtcon = 1,
1801 .has_clksel = 1,
1758 }, 1802 },
1759 .win[0] = &s3c_fb_data_64xx_wins[0], 1803 .win[0] = &s3c_fb_data_64xx_wins[0],
1760 .win[1] = &s3c_fb_data_64xx_wins[1], 1804 .win[1] = &s3c_fb_data_64xx_wins[1],
@@ -1785,6 +1829,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
1785 }, 1829 },
1786 1830
1787 .has_prtcon = 1, 1831 .has_prtcon = 1,
1832 .has_clksel = 1,
1788 }, 1833 },
1789 .win[0] = &s3c_fb_data_s5p_wins[0], 1834 .win[0] = &s3c_fb_data_s5p_wins[0],
1790 .win[1] = &s3c_fb_data_s5p_wins[1], 1835 .win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1815,6 +1860,37 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
1815 }, 1860 },
1816 1861
1817 .has_shadowcon = 1, 1862 .has_shadowcon = 1,
1863 .has_clksel = 1,
1864 },
1865 .win[0] = &s3c_fb_data_s5p_wins[0],
1866 .win[1] = &s3c_fb_data_s5p_wins[1],
1867 .win[2] = &s3c_fb_data_s5p_wins[2],
1868 .win[3] = &s3c_fb_data_s5p_wins[3],
1869 .win[4] = &s3c_fb_data_s5p_wins[4],
1870};
1871
1872static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
1873 .variant = {
1874 .nr_windows = 5,
1875 .vidtcon = VIDTCON0,
1876 .wincon = WINCON(0),
1877 .winmap = WINxMAP(0),
1878 .keycon = WKEYCON,
1879 .osd = VIDOSD_BASE,
1880 .osd_stride = 16,
1881 .buf_start = VIDW_BUF_START(0),
1882 .buf_size = VIDW_BUF_SIZE(0),
1883 .buf_end = VIDW_BUF_END(0),
1884
1885 .palette = {
1886 [0] = 0x2400,
1887 [1] = 0x2800,
1888 [2] = 0x2c00,
1889 [3] = 0x3000,
1890 [4] = 0x3400,
1891 },
1892
1893 .has_shadowcon = 1,
1818 }, 1894 },
1819 .win[0] = &s3c_fb_data_s5p_wins[0], 1895 .win[0] = &s3c_fb_data_s5p_wins[0],
1820 .win[1] = &s3c_fb_data_s5p_wins[1], 1896 .win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1843,6 +1919,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
1843 [0] = 0x400, 1919 [0] = 0x400,
1844 [1] = 0x800, 1920 [1] = 0x800,
1845 }, 1921 },
1922 .has_clksel = 1,
1846 }, 1923 },
1847 .win[0] = &(struct s3c_fb_win_variant) { 1924 .win[0] = &(struct s3c_fb_win_variant) {
1848 .palette_sz = 256, 1925 .palette_sz = 256,
@@ -1859,6 +1936,30 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
1859 }, 1936 },
1860}; 1937};
1861 1938
1939static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
1940 .variant = {
1941 .nr_windows = 3,
1942 .vidtcon = VIDTCON0,
1943 .wincon = WINCON(0),
1944 .winmap = WINxMAP(0),
1945 .keycon = WKEYCON,
1946 .osd = VIDOSD_BASE,
1947 .osd_stride = 16,
1948 .buf_start = VIDW_BUF_START(0),
1949 .buf_size = VIDW_BUF_SIZE(0),
1950 .buf_end = VIDW_BUF_END(0),
1951
1952 .palette = {
1953 [0] = 0x2400,
1954 [1] = 0x2800,
1955 [2] = 0x2c00,
1956 },
1957 },
1958 .win[0] = &s3c_fb_data_s5p_wins[0],
1959 .win[1] = &s3c_fb_data_s5p_wins[1],
1960 .win[2] = &s3c_fb_data_s5p_wins[2],
1961};
1962
1862static struct platform_device_id s3c_fb_driver_ids[] = { 1963static struct platform_device_id s3c_fb_driver_ids[] = {
1863 { 1964 {
1864 .name = "s3c-fb", 1965 .name = "s3c-fb",
@@ -1870,8 +1971,14 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
1870 .name = "s5pv210-fb", 1971 .name = "s5pv210-fb",
1871 .driver_data = (unsigned long)&s3c_fb_data_s5pv210, 1972 .driver_data = (unsigned long)&s3c_fb_data_s5pv210,
1872 }, { 1973 }, {
1974 .name = "exynos4-fb",
1975 .driver_data = (unsigned long)&s3c_fb_data_exynos4,
1976 }, {
1873 .name = "s3c2443-fb", 1977 .name = "s3c2443-fb",
1874 .driver_data = (unsigned long)&s3c_fb_data_s3c2443, 1978 .driver_data = (unsigned long)&s3c_fb_data_s3c2443,
1979 }, {
1980 .name = "s5p64x0-fb",
1981 .driver_data = (unsigned long)&s3c_fb_data_s5p64x0,
1875 }, 1982 },
1876 {}, 1983 {},
1877}; 1984};
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 0aa13761de6..ee4c0df217f 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -767,7 +767,6 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
767static int s3c2410fb_cpufreq_transition(struct notifier_block *nb, 767static int s3c2410fb_cpufreq_transition(struct notifier_block *nb,
768 unsigned long val, void *data) 768 unsigned long val, void *data)
769{ 769{
770 struct cpufreq_freqs *freqs = data;
771 struct s3c2410fb_info *info; 770 struct s3c2410fb_info *info;
772 struct fb_info *fbinfo; 771 struct fb_info *fbinfo;
773 long delta_f; 772 long delta_f;
@@ -911,7 +910,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
911 for (i = 0; i < 256; i++) 910 for (i = 0; i < 256; i++)
912 info->palette_buffer[i] = PALETTE_BUFF_CLEAR; 911 info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
913 912
914 ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info); 913 ret = request_irq(irq, s3c2410fb_irq, 0, pdev->name, info);
915 if (ret) { 914 if (ret) {
916 dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret); 915 dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
917 ret = -EBUSY; 916 ret = -EBUSY;
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index 4ca5d0c8fe8..946a949f4c7 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -1019,12 +1019,13 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1019 unsigned int offset; 1019 unsigned int offset;
1020 1020
1021 /* Calculate the offset */ 1021 /* Calculate the offset */
1022 if (var->bits_per_pixel == 0) { 1022 if (info->var.bits_per_pixel == 0) {
1023 offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); 1023 offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
1024 + (var->xoffset / 2);
1024 offset = offset >> 2; 1025 offset = offset >> 2;
1025 } else { 1026 } else {
1026 offset = (var->yoffset * info->fix.line_length) + 1027 offset = (var->yoffset * info->fix.line_length) +
1027 (var->xoffset * var->bits_per_pixel / 8); 1028 (var->xoffset * info->var.bits_per_pixel / 8);
1028 offset = offset >> 2; 1029 offset = offset >> 2;
1029 } 1030 }
1030 1031
@@ -1504,7 +1505,7 @@ static struct pci_driver s3fb_pci_driver = {
1504 .resume = s3_pci_resume, 1505 .resume = s3_pci_resume,
1505}; 1506};
1506 1507
1507/* Parse user speficied options */ 1508/* Parse user specified options */
1508 1509
1509#ifndef MODULE 1510#ifndef MODULE
1510static int __init s3fb_setup(char *options) 1511static int __init s3fb_setup(char *options)
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index e8b76d65a07..98d55d0e2da 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1457,8 +1457,7 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
1457 if (ret) 1457 if (ret)
1458 goto failed; 1458 goto failed;
1459 1459
1460 ret = request_irq(irq, sa1100fb_handle_irq, IRQF_DISABLED, 1460 ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi);
1461 "LCD", fbi);
1462 if (ret) { 1461 if (ret) {
1463 printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); 1462 printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
1464 goto failed; 1463 goto failed;
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 4de541ca9c5..beb495044b2 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1477,15 +1477,9 @@ static void savagefb_set_par_int(struct savagefb_par *par, struct savage_reg *r
1477 vgaHWProtect(par, 0); 1477 vgaHWProtect(par, 0);
1478} 1478}
1479 1479
1480static void savagefb_update_start(struct savagefb_par *par, 1480static void savagefb_update_start(struct savagefb_par *par, int base)
1481 struct fb_var_screeninfo *var)
1482{ 1481{
1483 int base; 1482 /* program the start address registers */
1484
1485 base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1))
1486 * ((var->bits_per_pixel+7) / 8)) >> 2;
1487
1488 /* now program the start address registers */
1489 vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par); 1483 vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);
1490 vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par); 1484 vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);
1491 vga_out8(0x3d4, 0x69, par); 1485 vga_out8(0x3d4, 0x69, par);
@@ -1550,8 +1544,12 @@ static int savagefb_pan_display(struct fb_var_screeninfo *var,
1550 struct fb_info *info) 1544 struct fb_info *info)
1551{ 1545{
1552 struct savagefb_par *par = info->par; 1546 struct savagefb_par *par = info->par;
1547 int base;
1548
1549 base = (var->yoffset * info->fix.line_length
1550 + (var->xoffset & ~1) * ((info->var.bits_per_pixel+7) / 8)) >> 2;
1553 1551
1554 savagefb_update_start(par, var); 1552 savagefb_update_start(par, base);
1555 return 0; 1553 return 0;
1556} 1554}
1557 1555
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 7d54e2c612f..647ba984f00 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -1111,6 +1111,7 @@ static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
1111static void sh_hdmi_edid_work_fn(struct work_struct *work) 1111static void sh_hdmi_edid_work_fn(struct work_struct *work)
1112{ 1112{
1113 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); 1113 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
1114 struct fb_info *info;
1114 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 1115 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1115 struct sh_mobile_lcdc_chan *ch; 1116 struct sh_mobile_lcdc_chan *ch;
1116 int ret; 1117 int ret;
@@ -1123,8 +1124,9 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
1123 1124
1124 mutex_lock(&hdmi->mutex); 1125 mutex_lock(&hdmi->mutex);
1125 1126
1127 info = hdmi->info;
1128
1126 if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { 1129 if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
1127 struct fb_info *info = hdmi->info;
1128 unsigned long parent_rate = 0, hdmi_rate; 1130 unsigned long parent_rate = 0, hdmi_rate;
1129 1131
1130 ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); 1132 ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
@@ -1148,42 +1150,45 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
1148 1150
1149 ch = info->par; 1151 ch = info->par;
1150 1152
1151 console_lock(); 1153 if (lock_fb_info(info)) {
1154 console_lock();
1152 1155
1153 /* HDMI plug in */ 1156 /* HDMI plug in */
1154 if (!sh_hdmi_must_reconfigure(hdmi) && 1157 if (!sh_hdmi_must_reconfigure(hdmi) &&
1155 info->state == FBINFO_STATE_RUNNING) { 1158 info->state == FBINFO_STATE_RUNNING) {
1156 /* 1159 /*
1157 * First activation with the default monitor - just turn 1160 * First activation with the default monitor - just turn
1158 * on, if we run a resume here, the logo disappears 1161 * on, if we run a resume here, the logo disappears
1159 */ 1162 */
1160 if (lock_fb_info(info)) {
1161 info->var.width = hdmi->var.width; 1163 info->var.width = hdmi->var.width;
1162 info->var.height = hdmi->var.height; 1164 info->var.height = hdmi->var.height;
1163 sh_hdmi_display_on(hdmi, info); 1165 sh_hdmi_display_on(hdmi, info);
1164 unlock_fb_info(info); 1166 } else {
1167 /* New monitor or have to wake up */
1168 fb_set_suspend(info, 0);
1165 } 1169 }
1166 } else {
1167 /* New monitor or have to wake up */
1168 fb_set_suspend(info, 0);
1169 }
1170 1170
1171 console_unlock(); 1171 console_unlock();
1172 unlock_fb_info(info);
1173 }
1172 } else { 1174 } else {
1173 ret = 0; 1175 ret = 0;
1174 if (!hdmi->info) 1176 if (!info)
1175 goto out; 1177 goto out;
1176 1178
1177 hdmi->monspec.modedb_len = 0; 1179 hdmi->monspec.modedb_len = 0;
1178 fb_destroy_modedb(hdmi->monspec.modedb); 1180 fb_destroy_modedb(hdmi->monspec.modedb);
1179 hdmi->monspec.modedb = NULL; 1181 hdmi->monspec.modedb = NULL;
1180 1182
1181 console_lock(); 1183 if (lock_fb_info(info)) {
1184 console_lock();
1182 1185
1183 /* HDMI disconnect */ 1186 /* HDMI disconnect */
1184 fb_set_suspend(hdmi->info, 1); 1187 fb_set_suspend(info, 1);
1185 1188
1186 console_unlock(); 1189 console_unlock();
1190 unlock_fb_info(info);
1191 }
1187 } 1192 }
1188 1193
1189out: 1194out:
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index b048417247e..3a41c013d03 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -24,39 +24,14 @@
24#include <linux/backlight.h> 24#include <linux/backlight.h>
25#include <linux/gpio.h> 25#include <linux/gpio.h>
26#include <video/sh_mobile_lcdc.h> 26#include <video/sh_mobile_lcdc.h>
27#include <video/sh_mobile_meram.h>
27#include <linux/atomic.h> 28#include <linux/atomic.h>
28 29
29#include "sh_mobile_lcdcfb.h" 30#include "sh_mobile_lcdcfb.h"
30#include "sh_mobile_meram.h"
31 31
32#define SIDE_B_OFFSET 0x1000 32#define SIDE_B_OFFSET 0x1000
33#define MIRROR_OFFSET 0x2000 33#define MIRROR_OFFSET 0x2000
34 34
35/* shared registers */
36#define _LDDCKR 0x410
37#define _LDDCKSTPR 0x414
38#define _LDINTR 0x468
39#define _LDSR 0x46c
40#define _LDCNT1R 0x470
41#define _LDCNT2R 0x474
42#define _LDRCNTR 0x478
43#define _LDDDSR 0x47c
44#define _LDDWD0R 0x800
45#define _LDDRDR 0x840
46#define _LDDWAR 0x900
47#define _LDDRAR 0x904
48
49/* shared registers and their order for context save/restore */
50static int lcdc_shared_regs[] = {
51 _LDDCKR,
52 _LDDCKSTPR,
53 _LDINTR,
54 _LDDDSR,
55 _LDCNT1R,
56 _LDCNT2R,
57};
58#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
59
60#define MAX_XRES 1920 35#define MAX_XRES 1920
61#define MAX_YRES 1080 36#define MAX_YRES 1080
62 37
@@ -98,22 +73,6 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
98 [LDPMR] = 0x63c, 73 [LDPMR] = 0x63c,
99}; 74};
100 75
101#define START_LCDC 0x00000001
102#define LCDC_RESET 0x00000100
103#define DISPLAY_BEU 0x00000008
104#define LCDC_ENABLE 0x00000001
105#define LDINTR_FE 0x00000400
106#define LDINTR_VSE 0x00000200
107#define LDINTR_VEE 0x00000100
108#define LDINTR_FS 0x00000004
109#define LDINTR_VSS 0x00000002
110#define LDINTR_VES 0x00000001
111#define LDRCNTR_SRS 0x00020000
112#define LDRCNTR_SRC 0x00010000
113#define LDRCNTR_MRS 0x00000002
114#define LDRCNTR_MRC 0x00000001
115#define LDSR_MRS 0x00000100
116
117static const struct fb_videomode default_720p = { 76static const struct fb_videomode default_720p = {
118 .name = "HDMI 720p", 77 .name = "HDMI 720p",
119 .xres = 1280, 78 .xres = 1280,
@@ -141,7 +100,6 @@ struct sh_mobile_lcdc_priv {
141 unsigned long lddckr; 100 unsigned long lddckr;
142 struct sh_mobile_lcdc_chan ch[2]; 101 struct sh_mobile_lcdc_chan ch[2];
143 struct notifier_block notifier; 102 struct notifier_block notifier;
144 unsigned long saved_shared_regs[NR_SHARED_REGS];
145 int started; 103 int started;
146 int forced_bpp; /* 2 channel LCDC must share bpp setting */ 104 int forced_bpp; /* 2 channel LCDC must share bpp setting */
147 struct sh_mobile_meram_info *meram_dev; 105 struct sh_mobile_meram_info *meram_dev;
@@ -218,33 +176,36 @@ static void lcdc_sys_write_index(void *handle, unsigned long data)
218{ 176{
219 struct sh_mobile_lcdc_chan *ch = handle; 177 struct sh_mobile_lcdc_chan *ch = handle;
220 178
221 lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000); 179 lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT);
222 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 180 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
223 lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 181 lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
224 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 182 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
183 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
225} 184}
226 185
227static void lcdc_sys_write_data(void *handle, unsigned long data) 186static void lcdc_sys_write_data(void *handle, unsigned long data)
228{ 187{
229 struct sh_mobile_lcdc_chan *ch = handle; 188 struct sh_mobile_lcdc_chan *ch = handle;
230 189
231 lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000); 190 lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW);
232 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 191 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
233 lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 192 lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
234 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 193 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
194 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
235} 195}
236 196
237static unsigned long lcdc_sys_read_data(void *handle) 197static unsigned long lcdc_sys_read_data(void *handle)
238{ 198{
239 struct sh_mobile_lcdc_chan *ch = handle; 199 struct sh_mobile_lcdc_chan *ch = handle;
240 200
241 lcdc_write(ch->lcdc, _LDDRDR, 0x01000000); 201 lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR);
242 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 202 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
243 lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 203 lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA |
204 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
244 udelay(1); 205 udelay(1);
245 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 206 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
246 207
247 return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff; 208 return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
248} 209}
249 210
250struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { 211struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
@@ -256,18 +217,22 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
256static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) 217static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
257{ 218{
258 if (atomic_inc_and_test(&priv->hw_usecnt)) { 219 if (atomic_inc_and_test(&priv->hw_usecnt)) {
259 pm_runtime_get_sync(priv->dev);
260 if (priv->dot_clk) 220 if (priv->dot_clk)
261 clk_enable(priv->dot_clk); 221 clk_enable(priv->dot_clk);
222 pm_runtime_get_sync(priv->dev);
223 if (priv->meram_dev && priv->meram_dev->pdev)
224 pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
262 } 225 }
263} 226}
264 227
265static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) 228static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
266{ 229{
267 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) { 230 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
231 if (priv->meram_dev && priv->meram_dev->pdev)
232 pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
233 pm_runtime_put(priv->dev);
268 if (priv->dot_clk) 234 if (priv->dot_clk)
269 clk_disable(priv->dot_clk); 235 clk_disable(priv->dot_clk);
270 pm_runtime_put(priv->dev);
271 } 236 }
272} 237}
273 238
@@ -319,13 +284,13 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
319 if (bcfg->start_transfer) 284 if (bcfg->start_transfer)
320 bcfg->start_transfer(bcfg->board_data, ch, 285 bcfg->start_transfer(bcfg->board_data, ch,
321 &sh_mobile_lcdc_sys_bus_ops); 286 &sh_mobile_lcdc_sys_bus_ops);
322 lcdc_write_chan(ch, LDSM2R, 1); 287 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
323 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 288 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
324 } else { 289 } else {
325 if (bcfg->start_transfer) 290 if (bcfg->start_transfer)
326 bcfg->start_transfer(bcfg->board_data, ch, 291 bcfg->start_transfer(bcfg->board_data, ch,
327 &sh_mobile_lcdc_sys_bus_ops); 292 &sh_mobile_lcdc_sys_bus_ops);
328 lcdc_write_chan(ch, LDSM2R, 1); 293 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
329 } 294 }
330} 295}
331 296
@@ -341,22 +306,16 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
341{ 306{
342 struct sh_mobile_lcdc_priv *priv = data; 307 struct sh_mobile_lcdc_priv *priv = data;
343 struct sh_mobile_lcdc_chan *ch; 308 struct sh_mobile_lcdc_chan *ch;
344 unsigned long tmp;
345 unsigned long ldintr; 309 unsigned long ldintr;
346 int is_sub; 310 int is_sub;
347 int k; 311 int k;
348 312
349 /* acknowledge interrupt */ 313 /* Acknowledge interrupts and disable further VSYNC End IRQs. */
350 ldintr = tmp = lcdc_read(priv, _LDINTR); 314 ldintr = lcdc_read(priv, _LDINTR);
351 /* 315 lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE);
352 * disable further VSYNC End IRQs, preserve all other enabled IRQs,
353 * write 0 to bits 0-6 to ack all triggered IRQs.
354 */
355 tmp &= 0xffffff00 & ~LDINTR_VEE;
356 lcdc_write(priv, _LDINTR, tmp);
357 316
358 /* figure out if this interrupt is for main or sub lcd */ 317 /* figure out if this interrupt is for main or sub lcd */
359 is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0; 318 is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0;
360 319
361 /* wake up channel and disable clocks */ 320 /* wake up channel and disable clocks */
362 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 321 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
@@ -365,7 +324,7 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
365 if (!ch->enabled) 324 if (!ch->enabled)
366 continue; 325 continue;
367 326
368 /* Frame Start */ 327 /* Frame End */
369 if (ldintr & LDINTR_FS) { 328 if (ldintr & LDINTR_FS) {
370 if (is_sub == lcdc_chan_is_sublcd(ch)) { 329 if (is_sub == lcdc_chan_is_sublcd(ch)) {
371 ch->frame_end = 1; 330 ch->frame_end = 1;
@@ -391,16 +350,17 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
391 350
392 /* start or stop the lcdc */ 351 /* start or stop the lcdc */
393 if (start) 352 if (start)
394 lcdc_write(priv, _LDCNT2R, tmp | START_LCDC); 353 lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO);
395 else 354 else
396 lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC); 355 lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO);
397 356
398 /* wait until power is applied/stopped on all channels */ 357 /* wait until power is applied/stopped on all channels */
399 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) 358 for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
400 if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) 359 if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
401 while (1) { 360 while (1) {
402 tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3; 361 tmp = lcdc_read_chan(&priv->ch[k], LDPMR)
403 if (start && tmp == 3) 362 & LDPMR_LPS;
363 if (start && tmp == LDPMR_LPS)
404 break; 364 break;
405 if (!start && tmp == 0) 365 if (!start && tmp == 0)
406 break; 366 break;
@@ -418,13 +378,13 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
418 u32 tmp; 378 u32 tmp;
419 379
420 tmp = ch->ldmt1r_value; 380 tmp = ch->ldmt1r_value;
421 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28; 381 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL;
422 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27; 382 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL;
423 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0; 383 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0;
424 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0; 384 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0;
425 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0; 385 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0;
426 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0; 386 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0;
427 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0; 387 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0;
428 lcdc_write_chan(ch, LDMT1R, tmp); 388 lcdc_write_chan(ch, LDMT1R, tmp);
429 389
430 /* setup SYS bus */ 390 /* setup SYS bus */
@@ -463,242 +423,239 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
463 lcdc_write_chan(ch, LDHAJR, tmp); 423 lcdc_write_chan(ch, LDHAJR, tmp);
464} 424}
465 425
466static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 426/*
427 * __sh_mobile_lcdc_start - Configure and tart the LCDC
428 * @priv: LCDC device
429 *
430 * Configure all enabled channels and start the LCDC device. All external
431 * devices (clocks, MERAM, panels, ...) are not touched by this function.
432 */
433static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
467{ 434{
468 struct sh_mobile_lcdc_chan *ch; 435 struct sh_mobile_lcdc_chan *ch;
469 struct sh_mobile_lcdc_board_cfg *board_cfg;
470 unsigned long tmp; 436 unsigned long tmp;
471 int bpp = 0; 437 int bpp = 0;
472 unsigned long ldddsr; 438 int k, m;
473 int k, m, ret;
474 439
475 /* enable clocks before accessing the hardware */ 440 /* Enable LCDC channels. Read data from external memory, avoid using the
476 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 441 * BEU for now.
477 if (priv->ch[k].enabled) { 442 */
478 sh_mobile_lcdc_clk_on(priv); 443 lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled);
479 if (!bpp)
480 bpp = priv->ch[k].info->var.bits_per_pixel;
481 }
482 }
483
484 /* reset */
485 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
486 lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
487
488 /* enable LCDC channels */
489 tmp = lcdc_read(priv, _LDCNT2R);
490 tmp |= priv->ch[0].enabled;
491 tmp |= priv->ch[1].enabled;
492 lcdc_write(priv, _LDCNT2R, tmp);
493
494 /* read data from external memory, avoid using the BEU for now */
495 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU);
496 444
497 /* stop the lcdc first */ 445 /* Stop the LCDC first and disable all interrupts. */
498 sh_mobile_lcdc_start_stop(priv, 0); 446 sh_mobile_lcdc_start_stop(priv, 0);
447 lcdc_write(priv, _LDINTR, 0);
499 448
500 /* configure clocks */ 449 /* Configure power supply, dot clocks and start them. */
501 tmp = priv->lddckr; 450 tmp = priv->lddckr;
502 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 451 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
503 ch = &priv->ch[k]; 452 ch = &priv->ch[k];
504 453 if (!ch->enabled)
505 if (!priv->ch[k].enabled)
506 continue; 454 continue;
507 455
456 if (!bpp)
457 bpp = ch->info->var.bits_per_pixel;
458
459 /* Power supply */
460 lcdc_write_chan(ch, LDPMR, 0);
461
508 m = ch->cfg.clock_divider; 462 m = ch->cfg.clock_divider;
509 if (!m) 463 if (!m)
510 continue; 464 continue;
511 465
512 if (m == 1) 466 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
513 m = 1 << 6; 467 * denominator.
514 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); 468 */
515
516 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */
517 lcdc_write_chan(ch, LDDCKPAT1R, 0); 469 lcdc_write_chan(ch, LDDCKPAT1R, 0);
518 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); 470 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
471
472 if (m == 1)
473 m = LDDCKR_MOSEL;
474 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
519 } 475 }
520 476
521 lcdc_write(priv, _LDDCKR, tmp); 477 lcdc_write(priv, _LDDCKR, tmp);
522
523 /* start dotclock again */
524 lcdc_write(priv, _LDDCKSTPR, 0); 478 lcdc_write(priv, _LDDCKSTPR, 0);
525 lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0); 479 lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
526 480
527 /* interrupts are disabled to begin with */ 481 /* Setup geometry, format, frame buffer memory and operation mode. */
528 lcdc_write(priv, _LDINTR, 0);
529
530 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 482 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
531 ch = &priv->ch[k]; 483 ch = &priv->ch[k];
532
533 if (!ch->enabled) 484 if (!ch->enabled)
534 continue; 485 continue;
535 486
536 sh_mobile_lcdc_geometry(ch); 487 sh_mobile_lcdc_geometry(ch);
537 488
538 /* power supply */
539 lcdc_write_chan(ch, LDPMR, 0);
540
541 board_cfg = &ch->cfg.board_cfg;
542 if (board_cfg->setup_sys) {
543 ret = board_cfg->setup_sys(board_cfg->board_data,
544 ch, &sh_mobile_lcdc_sys_bus_ops);
545 if (ret)
546 return ret;
547 }
548 }
549
550 /* word and long word swap */
551 ldddsr = lcdc_read(priv, _LDDDSR);
552 if (priv->ch[0].info->var.nonstd)
553 lcdc_write(priv, _LDDDSR, ldddsr | 7);
554 else {
555 switch (bpp) {
556 case 16:
557 lcdc_write(priv, _LDDDSR, ldddsr | 6);
558 break;
559 case 24:
560 lcdc_write(priv, _LDDDSR, ldddsr | 7);
561 break;
562 case 32:
563 lcdc_write(priv, _LDDDSR, ldddsr | 4);
564 break;
565 }
566 }
567
568 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
569 unsigned long base_addr_y;
570 unsigned long base_addr_c = 0;
571 int pitch;
572 ch = &priv->ch[k];
573
574 if (!priv->ch[k].enabled)
575 continue;
576
577 /* set bpp format in PKF[4:0] */
578 tmp = lcdc_read_chan(ch, LDDFR);
579 tmp &= ~0x0003031f;
580 if (ch->info->var.nonstd) { 489 if (ch->info->var.nonstd) {
581 tmp |= (ch->info->var.nonstd << 16); 490 tmp = (ch->info->var.nonstd << 16);
582 switch (ch->info->var.bits_per_pixel) { 491 switch (ch->info->var.bits_per_pixel) {
583 case 12: 492 case 12:
493 tmp |= LDDFR_YF_420;
584 break; 494 break;
585 case 16: 495 case 16:
586 tmp |= (0x1 << 8); 496 tmp |= LDDFR_YF_422;
587 break; 497 break;
588 case 24: 498 case 24:
589 tmp |= (0x2 << 8); 499 default:
500 tmp |= LDDFR_YF_444;
590 break; 501 break;
591 } 502 }
592 } else { 503 } else {
593 switch (ch->info->var.bits_per_pixel) { 504 switch (ch->info->var.bits_per_pixel) {
594 case 16: 505 case 16:
595 tmp |= 0x03; 506 tmp = LDDFR_PKF_RGB16;
596 break; 507 break;
597 case 24: 508 case 24:
598 tmp |= 0x0b; 509 tmp = LDDFR_PKF_RGB24;
599 break; 510 break;
600 case 32: 511 case 32:
512 default:
513 tmp = LDDFR_PKF_ARGB32;
601 break; 514 break;
602 } 515 }
603 } 516 }
517
604 lcdc_write_chan(ch, LDDFR, tmp); 518 lcdc_write_chan(ch, LDDFR, tmp);
519 lcdc_write_chan(ch, LDMLSR, ch->pitch);
520 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
521 if (ch->info->var.nonstd)
522 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
605 523
606 base_addr_y = ch->info->fix.smem_start; 524 /* When using deferred I/O mode, configure the LCDC for one-shot
607 base_addr_c = base_addr_y + 525 * operation and enable the frame end interrupt. Otherwise use
608 ch->info->var.xres * 526 * continuous read mode.
609 ch->info->var.yres_virtual; 527 */
610 pitch = ch->info->fix.line_length; 528 if (ch->ldmt1r_value & LDMT1R_IFM &&
529 ch->cfg.sys_bus_cfg.deferred_io_msec) {
530 lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
531 lcdc_write(priv, _LDINTR, LDINTR_FE);
532 } else {
533 lcdc_write_chan(ch, LDSM1R, 0);
534 }
535 }
611 536
612 /* test if we can enable meram */ 537 /* Word and long word swap. */
613 if (ch->cfg.meram_cfg && priv->meram_dev && 538 if (priv->ch[0].info->var.nonstd)
614 priv->meram_dev->ops) { 539 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
615 struct sh_mobile_meram_cfg *cfg; 540 else {
616 struct sh_mobile_meram_info *mdev; 541 switch (bpp) {
617 unsigned long icb_addr_y, icb_addr_c; 542 case 16:
618 int icb_pitch; 543 tmp = LDDDSR_LS | LDDDSR_WS;
619 int pf; 544 break;
545 case 24:
546 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
547 break;
548 case 32:
549 default:
550 tmp = LDDDSR_LS;
551 break;
552 }
553 }
554 lcdc_write(priv, _LDDDSR, tmp);
620 555
621 cfg = ch->cfg.meram_cfg; 556 /* Enable the display output. */
622 mdev = priv->meram_dev; 557 lcdc_write(priv, _LDCNT1R, LDCNT1R_DE);
623 /* we need to de-init configured ICBs before we 558 sh_mobile_lcdc_start_stop(priv, 1);
624 * we can re-initialize them. 559 priv->started = 1;
625 */ 560}
626 if (ch->meram_enabled)
627 mdev->ops->meram_unregister(mdev, cfg);
628 561
629 ch->meram_enabled = 0; 562static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
563{
564 struct sh_mobile_meram_info *mdev = priv->meram_dev;
565 struct sh_mobile_lcdc_board_cfg *board_cfg;
566 struct sh_mobile_lcdc_chan *ch;
567 unsigned long tmp;
568 int ret;
569 int k;
630 570
631 if (ch->info->var.nonstd) { 571 /* enable clocks before accessing the hardware */
632 if (ch->info->var.bits_per_pixel == 24) 572 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
633 pf = SH_MOBILE_MERAM_PF_NV24; 573 if (priv->ch[k].enabled)
634 else 574 sh_mobile_lcdc_clk_on(priv);
635 pf = SH_MOBILE_MERAM_PF_NV; 575 }
636 } else {
637 pf = SH_MOBILE_MERAM_PF_RGB;
638 }
639 576
640 ret = mdev->ops->meram_register(mdev, cfg, pitch, 577 /* reset */
641 ch->info->var.yres, 578 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR);
642 pf, 579 lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
643 base_addr_y,
644 base_addr_c,
645 &icb_addr_y,
646 &icb_addr_c,
647 &icb_pitch);
648 if (!ret) {
649 /* set LDSA1R value */
650 base_addr_y = icb_addr_y;
651 pitch = icb_pitch;
652
653 /* set LDSA2R value if required */
654 if (base_addr_c)
655 base_addr_c = icb_addr_c;
656
657 ch->meram_enabled = 1;
658 }
659 }
660 580
661 /* point out our frame buffer */ 581 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
662 lcdc_write_chan(ch, LDSA1R, base_addr_y); 582 ch = &priv->ch[k];
663 if (ch->info->var.nonstd)
664 lcdc_write_chan(ch, LDSA2R, base_addr_c);
665 583
666 /* set line size */ 584 if (!ch->enabled)
667 lcdc_write_chan(ch, LDMLSR, pitch); 585 continue;
668 586
669 /* setup deferred io if SYS bus */ 587 board_cfg = &ch->cfg.board_cfg;
670 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; 588 if (board_cfg->setup_sys) {
671 if (ch->ldmt1r_value & (1 << 12) && tmp) { 589 ret = board_cfg->setup_sys(board_cfg->board_data, ch,
672 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; 590 &sh_mobile_lcdc_sys_bus_ops);
673 ch->defio.delay = msecs_to_jiffies(tmp); 591 if (ret)
674 ch->info->fbdefio = &ch->defio; 592 return ret;
675 fb_deferred_io_init(ch->info); 593 }
594 }
676 595
677 /* one-shot mode */ 596 /* Compute frame buffer base address and pitch for each channel. */
678 lcdc_write_chan(ch, LDSM1R, 1); 597 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
598 struct sh_mobile_meram_cfg *cfg;
599 int pixelformat;
679 600
680 /* enable "Frame End Interrupt Enable" bit */ 601 ch = &priv->ch[k];
681 lcdc_write(priv, _LDINTR, LDINTR_FE); 602 if (!ch->enabled)
603 continue;
682 604
683 } else { 605 ch->base_addr_y = ch->info->fix.smem_start;
684 /* continuous read mode */ 606 ch->base_addr_c = ch->base_addr_y
685 lcdc_write_chan(ch, LDSM1R, 0); 607 + ch->info->var.xres
608 * ch->info->var.yres_virtual;
609 ch->pitch = ch->info->fix.line_length;
610
611 /* Enable MERAM if possible. */
612 cfg = ch->cfg.meram_cfg;
613 if (mdev == NULL || mdev->ops == NULL || cfg == NULL)
614 continue;
615
616 /* we need to de-init configured ICBs before we can
617 * re-initialize them.
618 */
619 if (ch->meram_enabled) {
620 mdev->ops->meram_unregister(mdev, cfg);
621 ch->meram_enabled = 0;
686 } 622 }
623
624 if (!ch->info->var.nonstd)
625 pixelformat = SH_MOBILE_MERAM_PF_RGB;
626 else if (ch->info->var.bits_per_pixel == 24)
627 pixelformat = SH_MOBILE_MERAM_PF_NV24;
628 else
629 pixelformat = SH_MOBILE_MERAM_PF_NV;
630
631 ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
632 ch->info->var.yres, pixelformat,
633 ch->base_addr_y, ch->base_addr_c,
634 &ch->base_addr_y, &ch->base_addr_c,
635 &ch->pitch);
636 if (!ret)
637 ch->meram_enabled = 1;
687 } 638 }
688 639
689 /* display output */ 640 /* Start the LCDC. */
690 lcdc_write(priv, _LDCNT1R, LCDC_ENABLE); 641 __sh_mobile_lcdc_start(priv);
691 642
692 /* start the lcdc */ 643 /* Setup deferred I/O, tell the board code to enable the panels, and
693 sh_mobile_lcdc_start_stop(priv, 1); 644 * turn backlight on.
694 priv->started = 1; 645 */
695
696 /* tell the board code to enable the panel */
697 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 646 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
698 ch = &priv->ch[k]; 647 ch = &priv->ch[k];
699 if (!ch->enabled) 648 if (!ch->enabled)
700 continue; 649 continue;
701 650
651 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
652 if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
653 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
654 ch->defio.delay = msecs_to_jiffies(tmp);
655 ch->info->fbdefio = &ch->defio;
656 fb_deferred_io_init(ch->info);
657 }
658
702 board_cfg = &ch->cfg.board_cfg; 659 board_cfg = &ch->cfg.board_cfg;
703 if (board_cfg->display_on && try_module_get(board_cfg->owner)) { 660 if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
704 board_cfg->display_on(board_cfg->board_data, ch->info); 661 board_cfg->display_on(board_cfg->board_data, ch->info);
@@ -776,42 +733,42 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
776 733
777static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) 734static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
778{ 735{
779 int ifm, miftyp; 736 int interface_type = ch->cfg.interface_type;
780 737
781 switch (ch->cfg.interface_type) { 738 switch (interface_type) {
782 case RGB8: ifm = 0; miftyp = 0; break; 739 case RGB8:
783 case RGB9: ifm = 0; miftyp = 4; break; 740 case RGB9:
784 case RGB12A: ifm = 0; miftyp = 5; break; 741 case RGB12A:
785 case RGB12B: ifm = 0; miftyp = 6; break; 742 case RGB12B:
786 case RGB16: ifm = 0; miftyp = 7; break; 743 case RGB16:
787 case RGB18: ifm = 0; miftyp = 10; break; 744 case RGB18:
788 case RGB24: ifm = 0; miftyp = 11; break; 745 case RGB24:
789 case SYS8A: ifm = 1; miftyp = 0; break; 746 case SYS8A:
790 case SYS8B: ifm = 1; miftyp = 1; break; 747 case SYS8B:
791 case SYS8C: ifm = 1; miftyp = 2; break; 748 case SYS8C:
792 case SYS8D: ifm = 1; miftyp = 3; break; 749 case SYS8D:
793 case SYS9: ifm = 1; miftyp = 4; break; 750 case SYS9:
794 case SYS12: ifm = 1; miftyp = 5; break; 751 case SYS12:
795 case SYS16A: ifm = 1; miftyp = 7; break; 752 case SYS16A:
796 case SYS16B: ifm = 1; miftyp = 8; break; 753 case SYS16B:
797 case SYS16C: ifm = 1; miftyp = 9; break; 754 case SYS16C:
798 case SYS18: ifm = 1; miftyp = 10; break; 755 case SYS18:
799 case SYS24: ifm = 1; miftyp = 11; break; 756 case SYS24:
800 default: goto bad; 757 break;
758 default:
759 return -EINVAL;
801 } 760 }
802 761
803 /* SUBLCD only supports SYS interface */ 762 /* SUBLCD only supports SYS interface */
804 if (lcdc_chan_is_sublcd(ch)) { 763 if (lcdc_chan_is_sublcd(ch)) {
805 if (ifm == 0) 764 if (!(interface_type & LDMT1R_IFM))
806 goto bad; 765 return -EINVAL;
807 else 766
808 ifm = 0; 767 interface_type &= ~LDMT1R_IFM;
809 } 768 }
810 769
811 ch->ldmt1r_value = (ifm << 12) | miftyp; 770 ch->ldmt1r_value = interface_type;
812 return 0; 771 return 0;
813 bad:
814 return -EINVAL;
815} 772}
816 773
817static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, 774static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
@@ -819,18 +776,24 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
819 struct sh_mobile_lcdc_priv *priv) 776 struct sh_mobile_lcdc_priv *priv)
820{ 777{
821 char *str; 778 char *str;
822 int icksel;
823 779
824 switch (clock_source) { 780 switch (clock_source) {
825 case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break; 781 case LCDC_CLK_BUS:
826 case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break; 782 str = "bus_clk";
827 case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break; 783 priv->lddckr = LDDCKR_ICKSEL_BUS;
784 break;
785 case LCDC_CLK_PERIPHERAL:
786 str = "peripheral_clk";
787 priv->lddckr = LDDCKR_ICKSEL_MIPI;
788 break;
789 case LCDC_CLK_EXTERNAL:
790 str = NULL;
791 priv->lddckr = LDDCKR_ICKSEL_HDMI;
792 break;
828 default: 793 default:
829 return -EINVAL; 794 return -EINVAL;
830 } 795 }
831 796
832 priv->lddckr = icksel << 16;
833
834 if (str) { 797 if (str) {
835 priv->dot_clk = clk_get(&pdev->dev, str); 798 priv->dot_clk = clk_get(&pdev->dev, str);
836 if (IS_ERR(priv->dot_clk)) { 799 if (IS_ERR(priv->dot_clk)) {
@@ -914,12 +877,12 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
914 unsigned long base_addr_y, base_addr_c; 877 unsigned long base_addr_y, base_addr_c;
915 unsigned long c_offset; 878 unsigned long c_offset;
916 879
917 if (!var->nonstd) 880 if (!info->var.nonstd)
918 new_pan_offset = (var->yoffset * info->fix.line_length) + 881 new_pan_offset = var->yoffset * info->fix.line_length
919 (var->xoffset * (info->var.bits_per_pixel / 8)); 882 + var->xoffset * (info->var.bits_per_pixel / 8);
920 else 883 else
921 new_pan_offset = (var->yoffset * info->fix.line_length) + 884 new_pan_offset = var->yoffset * info->fix.line_length
922 (var->xoffset); 885 + var->xoffset;
923 886
924 if (new_pan_offset == ch->pan_offset) 887 if (new_pan_offset == ch->pan_offset)
925 return 0; /* No change, do nothing */ 888 return 0; /* No change, do nothing */
@@ -928,44 +891,40 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
928 891
929 /* Set the source address for the next refresh */ 892 /* Set the source address for the next refresh */
930 base_addr_y = ch->dma_handle + new_pan_offset; 893 base_addr_y = ch->dma_handle + new_pan_offset;
931 if (var->nonstd) { 894 if (info->var.nonstd) {
932 /* Set y offset */ 895 /* Set y offset */
933 c_offset = (var->yoffset * 896 c_offset = var->yoffset * info->fix.line_length
934 info->fix.line_length * 897 * (info->var.bits_per_pixel - 8) / 8;
935 (info->var.bits_per_pixel - 8)) / 8; 898 base_addr_c = ch->dma_handle
936 base_addr_c = ch->dma_handle + var->xres * var->yres_virtual + 899 + info->var.xres * info->var.yres_virtual
937 c_offset; 900 + c_offset;
938 /* Set x offset */ 901 /* Set x offset */
939 if (info->var.bits_per_pixel == 24) 902 if (info->var.bits_per_pixel == 24)
940 base_addr_c += 2 * var->xoffset; 903 base_addr_c += 2 * var->xoffset;
941 else 904 else
942 base_addr_c += var->xoffset; 905 base_addr_c += var->xoffset;
943 } else 906 }
944 base_addr_c = 0;
945 907
946 if (!ch->meram_enabled) { 908 if (ch->meram_enabled) {
947 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
948 if (base_addr_c)
949 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
950 } else {
951 struct sh_mobile_meram_cfg *cfg; 909 struct sh_mobile_meram_cfg *cfg;
952 struct sh_mobile_meram_info *mdev; 910 struct sh_mobile_meram_info *mdev;
953 unsigned long icb_addr_y, icb_addr_c;
954 int ret; 911 int ret;
955 912
956 cfg = ch->cfg.meram_cfg; 913 cfg = ch->cfg.meram_cfg;
957 mdev = priv->meram_dev; 914 mdev = priv->meram_dev;
958 ret = mdev->ops->meram_update(mdev, cfg, 915 ret = mdev->ops->meram_update(mdev, cfg,
959 base_addr_y, base_addr_c, 916 base_addr_y, base_addr_c,
960 &icb_addr_y, &icb_addr_c); 917 &base_addr_y, &base_addr_c);
961 if (ret) 918 if (ret)
962 return ret; 919 return ret;
920 }
963 921
964 lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y); 922 ch->base_addr_y = base_addr_y;
965 if (icb_addr_c) 923 ch->base_addr_c = base_addr_c;
966 lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c);
967 924
968 } 925 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
926 if (info->var.nonstd)
927 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
969 928
970 if (lcdc_chan_is_sublcd(ch)) 929 if (lcdc_chan_is_sublcd(ch))
971 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); 930 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
@@ -985,9 +944,11 @@ static int sh_mobile_wait_for_vsync(struct fb_info *info)
985 unsigned long ldintr; 944 unsigned long ldintr;
986 int ret; 945 int ret;
987 946
988 /* Enable VSync End interrupt */ 947 /* Enable VSync End interrupt and be careful not to acknowledge any
948 * pending interrupt.
949 */
989 ldintr = lcdc_read(ch->lcdc, _LDINTR); 950 ldintr = lcdc_read(ch->lcdc, _LDINTR);
990 ldintr |= LDINTR_VEE; 951 ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
991 lcdc_write(ch->lcdc, _LDINTR, ldintr); 952 lcdc_write(ch->lcdc, _LDINTR, ldintr);
992 953
993 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion, 954 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
@@ -1037,11 +998,6 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
1037 /* Couldn't reconfigure, hopefully, can continue as before */ 998 /* Couldn't reconfigure, hopefully, can continue as before */
1038 return; 999 return;
1039 1000
1040 if (info->var.nonstd)
1041 info->fix.line_length = mode1.xres;
1042 else
1043 info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8);
1044
1045 /* 1001 /*
1046 * fb_set_var() calls the notifier change internally, only if 1002 * fb_set_var() calls the notifier change internally, only if
1047 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a 1003 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
@@ -1094,30 +1050,126 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1094{ 1050{
1095 struct sh_mobile_lcdc_chan *ch = info->par; 1051 struct sh_mobile_lcdc_chan *ch = info->par;
1096 struct sh_mobile_lcdc_priv *p = ch->lcdc; 1052 struct sh_mobile_lcdc_priv *p = ch->lcdc;
1053 unsigned int best_dist = (unsigned int)-1;
1054 unsigned int best_xres = 0;
1055 unsigned int best_yres = 0;
1056 unsigned int i;
1097 1057
1098 if (var->xres > MAX_XRES || var->yres > MAX_YRES || 1058 if (var->xres > MAX_XRES || var->yres > MAX_YRES)
1099 var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
1100 dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %lukHz!\n",
1101 var->left_margin, var->xres, var->right_margin, var->hsync_len,
1102 var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
1103 PICOS2KHZ(var->pixclock));
1104 return -EINVAL; 1059 return -EINVAL;
1060
1061 /* If board code provides us with a list of available modes, make sure
1062 * we use one of them. Find the mode closest to the requested one. The
1063 * distance between two modes is defined as the size of the
1064 * non-overlapping parts of the two rectangles.
1065 */
1066 for (i = 0; i < ch->cfg.num_cfg; ++i) {
1067 const struct fb_videomode *mode = &ch->cfg.lcd_cfg[i];
1068 unsigned int dist;
1069
1070 /* We can only round up. */
1071 if (var->xres > mode->xres || var->yres > mode->yres)
1072 continue;
1073
1074 dist = var->xres * var->yres + mode->xres * mode->yres
1075 - 2 * min(var->xres, mode->xres)
1076 * min(var->yres, mode->yres);
1077
1078 if (dist < best_dist) {
1079 best_xres = mode->xres;
1080 best_yres = mode->yres;
1081 best_dist = dist;
1082 }
1083 }
1084
1085 /* If no available mode can be used, return an error. */
1086 if (ch->cfg.num_cfg != 0) {
1087 if (best_dist == (unsigned int)-1)
1088 return -EINVAL;
1089
1090 var->xres = best_xres;
1091 var->yres = best_yres;
1105 } 1092 }
1106 1093
1094 /* Make sure the virtual resolution is at least as big as the visible
1095 * resolution.
1096 */
1097 if (var->xres_virtual < var->xres)
1098 var->xres_virtual = var->xres;
1099 if (var->yres_virtual < var->yres)
1100 var->yres_virtual = var->yres;
1101
1102 if (var->bits_per_pixel <= 16) { /* RGB 565 */
1103 var->bits_per_pixel = 16;
1104 var->red.offset = 11;
1105 var->red.length = 5;
1106 var->green.offset = 5;
1107 var->green.length = 6;
1108 var->blue.offset = 0;
1109 var->blue.length = 5;
1110 var->transp.offset = 0;
1111 var->transp.length = 0;
1112 } else if (var->bits_per_pixel <= 24) { /* RGB 888 */
1113 var->bits_per_pixel = 24;
1114 var->red.offset = 16;
1115 var->red.length = 8;
1116 var->green.offset = 8;
1117 var->green.length = 8;
1118 var->blue.offset = 0;
1119 var->blue.length = 8;
1120 var->transp.offset = 0;
1121 var->transp.length = 0;
1122 } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
1123 var->bits_per_pixel = 32;
1124 var->red.offset = 16;
1125 var->red.length = 8;
1126 var->green.offset = 8;
1127 var->green.length = 8;
1128 var->blue.offset = 0;
1129 var->blue.length = 8;
1130 var->transp.offset = 24;
1131 var->transp.length = 8;
1132 } else
1133 return -EINVAL;
1134
1135 var->red.msb_right = 0;
1136 var->green.msb_right = 0;
1137 var->blue.msb_right = 0;
1138 var->transp.msb_right = 0;
1139
1140 /* Make sure we don't exceed our allocated memory. */
1141 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
1142 info->fix.smem_len)
1143 return -EINVAL;
1144
1107 /* only accept the forced_bpp for dual channel configurations */ 1145 /* only accept the forced_bpp for dual channel configurations */
1108 if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel) 1146 if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel)
1109 return -EINVAL; 1147 return -EINVAL;
1110 1148
1111 switch (var->bits_per_pixel) { 1149 return 0;
1112 case 16: /* PKF[4:0] = 00011 - RGB 565 */ 1150}
1113 case 24: /* PKF[4:0] = 01011 - RGB 888 */ 1151
1114 case 32: /* PKF[4:0] = 00000 - RGBA 888 */ 1152static int sh_mobile_set_par(struct fb_info *info)
1115 break; 1153{
1116 default: 1154 struct sh_mobile_lcdc_chan *ch = info->par;
1117 return -EINVAL; 1155 u32 line_length = info->fix.line_length;
1156 int ret;
1157
1158 sh_mobile_lcdc_stop(ch->lcdc);
1159
1160 if (info->var.nonstd)
1161 info->fix.line_length = info->var.xres;
1162 else
1163 info->fix.line_length = info->var.xres
1164 * info->var.bits_per_pixel / 8;
1165
1166 ret = sh_mobile_lcdc_start(ch->lcdc);
1167 if (ret < 0) {
1168 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
1169 info->fix.line_length = line_length;
1118 } 1170 }
1119 1171
1120 return 0; 1172 return ret;
1121} 1173}
1122 1174
1123/* 1175/*
@@ -1177,6 +1229,7 @@ static struct fb_ops sh_mobile_lcdc_ops = {
1177 .fb_open = sh_mobile_open, 1229 .fb_open = sh_mobile_open,
1178 .fb_release = sh_mobile_release, 1230 .fb_release = sh_mobile_release,
1179 .fb_check_var = sh_mobile_check_var, 1231 .fb_check_var = sh_mobile_check_var,
1232 .fb_set_par = sh_mobile_set_par,
1180}; 1233};
1181 1234
1182static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) 1235static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
@@ -1238,66 +1291,6 @@ static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
1238 backlight_device_unregister(bdev); 1291 backlight_device_unregister(bdev);
1239} 1292}
1240 1293
1241static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp,
1242 int nonstd)
1243{
1244 if (nonstd) {
1245 switch (bpp) {
1246 case 12:
1247 case 16:
1248 case 24:
1249 var->bits_per_pixel = bpp;
1250 var->nonstd = nonstd;
1251 return 0;
1252 default:
1253 return -EINVAL;
1254 }
1255 }
1256
1257 switch (bpp) {
1258 case 16: /* PKF[4:0] = 00011 - RGB 565 */
1259 var->red.offset = 11;
1260 var->red.length = 5;
1261 var->green.offset = 5;
1262 var->green.length = 6;
1263 var->blue.offset = 0;
1264 var->blue.length = 5;
1265 var->transp.offset = 0;
1266 var->transp.length = 0;
1267 break;
1268
1269 case 24: /* PKF[4:0] = 01011 - RGB 888 */
1270 var->red.offset = 16;
1271 var->red.length = 8;
1272 var->green.offset = 8;
1273 var->green.length = 8;
1274 var->blue.offset = 0;
1275 var->blue.length = 8;
1276 var->transp.offset = 0;
1277 var->transp.length = 0;
1278 break;
1279
1280 case 32: /* PKF[4:0] = 00000 - RGBA 888 */
1281 var->red.offset = 16;
1282 var->red.length = 8;
1283 var->green.offset = 8;
1284 var->green.length = 8;
1285 var->blue.offset = 0;
1286 var->blue.length = 8;
1287 var->transp.offset = 24;
1288 var->transp.length = 8;
1289 break;
1290 default:
1291 return -EINVAL;
1292 }
1293 var->bits_per_pixel = bpp;
1294 var->red.msb_right = 0;
1295 var->green.msb_right = 0;
1296 var->blue.msb_right = 0;
1297 var->transp.msb_right = 0;
1298 return 0;
1299}
1300
1301static int sh_mobile_lcdc_suspend(struct device *dev) 1294static int sh_mobile_lcdc_suspend(struct device *dev)
1302{ 1295{
1303 struct platform_device *pdev = to_platform_device(dev); 1296 struct platform_device *pdev = to_platform_device(dev);
@@ -1316,47 +1309,20 @@ static int sh_mobile_lcdc_resume(struct device *dev)
1316static int sh_mobile_lcdc_runtime_suspend(struct device *dev) 1309static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
1317{ 1310{
1318 struct platform_device *pdev = to_platform_device(dev); 1311 struct platform_device *pdev = to_platform_device(dev);
1319 struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev); 1312 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
1320 struct sh_mobile_lcdc_chan *ch;
1321 int k, n;
1322
1323 /* save per-channel registers */
1324 for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
1325 ch = &p->ch[k];
1326 if (!ch->enabled)
1327 continue;
1328 for (n = 0; n < NR_CH_REGS; n++)
1329 ch->saved_ch_regs[n] = lcdc_read_chan(ch, n);
1330 }
1331
1332 /* save shared registers */
1333 for (n = 0; n < NR_SHARED_REGS; n++)
1334 p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]);
1335 1313
1336 /* turn off LCDC hardware */ 1314 /* turn off LCDC hardware */
1337 lcdc_write(p, _LDCNT1R, 0); 1315 lcdc_write(priv, _LDCNT1R, 0);
1316
1338 return 0; 1317 return 0;
1339} 1318}
1340 1319
1341static int sh_mobile_lcdc_runtime_resume(struct device *dev) 1320static int sh_mobile_lcdc_runtime_resume(struct device *dev)
1342{ 1321{
1343 struct platform_device *pdev = to_platform_device(dev); 1322 struct platform_device *pdev = to_platform_device(dev);
1344 struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev); 1323 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
1345 struct sh_mobile_lcdc_chan *ch;
1346 int k, n;
1347
1348 /* restore per-channel registers */
1349 for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
1350 ch = &p->ch[k];
1351 if (!ch->enabled)
1352 continue;
1353 for (n = 0; n < NR_CH_REGS; n++)
1354 lcdc_write_chan(ch, n, ch->saved_ch_regs[n]);
1355 }
1356 1324
1357 /* restore shared registers */ 1325 __sh_mobile_lcdc_start(priv);
1358 for (n = 0; n < NR_SHARED_REGS; n++)
1359 lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]);
1360 1326
1361 return 0; 1327 return 0;
1362} 1328}
@@ -1408,17 +1374,187 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1408 return NOTIFY_OK; 1374 return NOTIFY_OK;
1409} 1375}
1410 1376
1411static int sh_mobile_lcdc_remove(struct platform_device *pdev); 1377static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1378{
1379 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
1380 struct fb_info *info;
1381 int i;
1412 1382
1413static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) 1383 fb_unregister_client(&priv->notifier);
1384
1385 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1386 if (priv->ch[i].info && priv->ch[i].info->dev)
1387 unregister_framebuffer(priv->ch[i].info);
1388
1389 sh_mobile_lcdc_stop(priv);
1390
1391 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
1392 info = priv->ch[i].info;
1393
1394 if (!info || !info->device)
1395 continue;
1396
1397 if (priv->ch[i].sglist)
1398 vfree(priv->ch[i].sglist);
1399
1400 if (info->screen_base)
1401 dma_free_coherent(&pdev->dev, info->fix.smem_len,
1402 info->screen_base,
1403 priv->ch[i].dma_handle);
1404 fb_dealloc_cmap(&info->cmap);
1405 framebuffer_release(info);
1406 }
1407
1408 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
1409 if (priv->ch[i].bl)
1410 sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
1411 }
1412
1413 if (priv->dot_clk)
1414 clk_put(priv->dot_clk);
1415
1416 if (priv->dev)
1417 pm_runtime_disable(priv->dev);
1418
1419 if (priv->base)
1420 iounmap(priv->base);
1421
1422 if (priv->irq)
1423 free_irq(priv->irq, priv);
1424 kfree(priv);
1425 return 0;
1426}
1427
1428static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
1429 struct device *dev)
1414{ 1430{
1431 struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg;
1432 const struct fb_videomode *max_mode;
1433 const struct fb_videomode *mode;
1434 struct fb_var_screeninfo *var;
1415 struct fb_info *info; 1435 struct fb_info *info;
1416 struct sh_mobile_lcdc_priv *priv; 1436 unsigned int max_size;
1437 int num_cfg;
1438 void *buf;
1439 int ret;
1440 int i;
1441
1442 mutex_init(&ch->open_lock);
1443
1444 /* Allocate the frame buffer device. */
1445 ch->info = framebuffer_alloc(0, dev);
1446 if (!ch->info) {
1447 dev_err(dev, "unable to allocate fb_info\n");
1448 return -ENOMEM;
1449 }
1450
1451 info = ch->info;
1452 info->fbops = &sh_mobile_lcdc_ops;
1453 info->par = ch;
1454 info->pseudo_palette = &ch->pseudo_palette;
1455 info->flags = FBINFO_FLAG_DEFAULT;
1456
1457 /* Iterate through the modes to validate them and find the highest
1458 * resolution.
1459 */
1460 max_mode = NULL;
1461 max_size = 0;
1462
1463 for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) {
1464 unsigned int size = mode->yres * mode->xres;
1465
1466 /* NV12 buffers must have even number of lines */
1467 if ((cfg->nonstd) && cfg->bpp == 12 &&
1468 (mode->yres & 0x1)) {
1469 dev_err(dev, "yres must be multiple of 2 for YCbCr420 "
1470 "mode.\n");
1471 return -EINVAL;
1472 }
1473
1474 if (size > max_size) {
1475 max_mode = mode;
1476 max_size = size;
1477 }
1478 }
1479
1480 if (!max_size)
1481 max_size = MAX_XRES * MAX_YRES;
1482 else
1483 dev_dbg(dev, "Found largest videomode %ux%u\n",
1484 max_mode->xres, max_mode->yres);
1485
1486 /* Initialize fixed screen information. Restrict pan to 2 lines steps
1487 * for NV12.
1488 */
1489 info->fix = sh_mobile_lcdc_fix;
1490 info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
1491 if (cfg->nonstd && cfg->bpp == 12)
1492 info->fix.ypanstep = 2;
1493
1494 /* Create the mode list. */
1495 if (cfg->lcd_cfg == NULL) {
1496 mode = &default_720p;
1497 num_cfg = 1;
1498 } else {
1499 mode = cfg->lcd_cfg;
1500 num_cfg = cfg->num_cfg;
1501 }
1502
1503 fb_videomode_to_modelist(mode, num_cfg, &info->modelist);
1504
1505 /* Initialize variable screen information using the first mode as
1506 * default. The default Y virtual resolution is twice the panel size to
1507 * allow for double-buffering.
1508 */
1509 var = &info->var;
1510 fb_videomode_to_var(var, mode);
1511 var->bits_per_pixel = cfg->bpp;
1512 var->width = cfg->lcd_size_cfg.width;
1513 var->height = cfg->lcd_size_cfg.height;
1514 var->yres_virtual = var->yres * 2;
1515 var->activate = FB_ACTIVATE_NOW;
1516
1517 ret = sh_mobile_check_var(var, info);
1518 if (ret)
1519 return ret;
1520
1521 /* Allocate frame buffer memory and color map. */
1522 buf = dma_alloc_coherent(dev, info->fix.smem_len, &ch->dma_handle,
1523 GFP_KERNEL);
1524 if (!buf) {
1525 dev_err(dev, "unable to allocate buffer\n");
1526 return -ENOMEM;
1527 }
1528
1529 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1530 if (ret < 0) {
1531 dev_err(dev, "unable to allocate cmap\n");
1532 dma_free_coherent(dev, info->fix.smem_len,
1533 buf, ch->dma_handle);
1534 return ret;
1535 }
1536
1537 info->fix.smem_start = ch->dma_handle;
1538 if (var->nonstd)
1539 info->fix.line_length = var->xres;
1540 else
1541 info->fix.line_length = var->xres * (cfg->bpp / 8);
1542
1543 info->screen_base = buf;
1544 info->device = dev;
1545 ch->display_var = *var;
1546
1547 return 0;
1548}
1549
1550static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1551{
1417 struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; 1552 struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
1553 struct sh_mobile_lcdc_priv *priv;
1418 struct resource *res; 1554 struct resource *res;
1555 int num_channels;
1419 int error; 1556 int error;
1420 void *buf; 1557 int i;
1421 int i, j;
1422 1558
1423 if (!pdata) { 1559 if (!pdata) {
1424 dev_err(&pdev->dev, "no platform data defined\n"); 1560 dev_err(&pdev->dev, "no platform data defined\n");
@@ -1440,7 +1576,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1440 1576
1441 platform_set_drvdata(pdev, priv); 1577 platform_set_drvdata(pdev, priv);
1442 1578
1443 error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, 1579 error = request_irq(i, sh_mobile_lcdc_irq, 0,
1444 dev_name(&pdev->dev), priv); 1580 dev_name(&pdev->dev), priv);
1445 if (error) { 1581 if (error) {
1446 dev_err(&pdev->dev, "unable to request irq\n"); 1582 dev_err(&pdev->dev, "unable to request irq\n");
@@ -1450,9 +1586,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1450 priv->irq = i; 1586 priv->irq = i;
1451 atomic_set(&priv->hw_usecnt, -1); 1587 atomic_set(&priv->hw_usecnt, -1);
1452 1588
1453 j = 0; 1589 for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) {
1454 for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { 1590 struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels;
1455 struct sh_mobile_lcdc_chan *ch = priv->ch + j;
1456 1591
1457 ch->lcdc = priv; 1592 ch->lcdc = priv;
1458 memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i])); 1593 memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
@@ -1472,26 +1607,26 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1472 1607
1473 switch (pdata->ch[i].chan) { 1608 switch (pdata->ch[i].chan) {
1474 case LCDC_CHAN_MAINLCD: 1609 case LCDC_CHAN_MAINLCD:
1475 ch->enabled = 1 << 1; 1610 ch->enabled = LDCNT2R_ME;
1476 ch->reg_offs = lcdc_offs_mainlcd; 1611 ch->reg_offs = lcdc_offs_mainlcd;
1477 j++; 1612 num_channels++;
1478 break; 1613 break;
1479 case LCDC_CHAN_SUBLCD: 1614 case LCDC_CHAN_SUBLCD:
1480 ch->enabled = 1 << 2; 1615 ch->enabled = LDCNT2R_SE;
1481 ch->reg_offs = lcdc_offs_sublcd; 1616 ch->reg_offs = lcdc_offs_sublcd;
1482 j++; 1617 num_channels++;
1483 break; 1618 break;
1484 } 1619 }
1485 } 1620 }
1486 1621
1487 if (!j) { 1622 if (!num_channels) {
1488 dev_err(&pdev->dev, "no channels defined\n"); 1623 dev_err(&pdev->dev, "no channels defined\n");
1489 error = -EINVAL; 1624 error = -EINVAL;
1490 goto err1; 1625 goto err1;
1491 } 1626 }
1492 1627
1493 /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */ 1628 /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */
1494 if (j == 2) 1629 if (num_channels == 2)
1495 priv->forced_bpp = pdata->ch[0].bpp; 1630 priv->forced_bpp = pdata->ch[0].bpp;
1496 1631
1497 priv->base = ioremap_nocache(res->start, resource_size(res)); 1632 priv->base = ioremap_nocache(res->start, resource_size(res));
@@ -1506,125 +1641,23 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1506 1641
1507 priv->meram_dev = pdata->meram_dev; 1642 priv->meram_dev = pdata->meram_dev;
1508 1643
1509 for (i = 0; i < j; i++) { 1644 for (i = 0; i < num_channels; i++) {
1510 struct fb_var_screeninfo *var;
1511 const struct fb_videomode *lcd_cfg, *max_cfg = NULL;
1512 struct sh_mobile_lcdc_chan *ch = priv->ch + i; 1645 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1513 struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg;
1514 const struct fb_videomode *mode = cfg->lcd_cfg;
1515 unsigned long max_size = 0;
1516 int k;
1517 int num_cfg;
1518
1519 ch->info = framebuffer_alloc(0, &pdev->dev);
1520 if (!ch->info) {
1521 dev_err(&pdev->dev, "unable to allocate fb_info\n");
1522 error = -ENOMEM;
1523 break;
1524 }
1525
1526 info = ch->info;
1527 var = &info->var;
1528 info->fbops = &sh_mobile_lcdc_ops;
1529 info->par = ch;
1530
1531 mutex_init(&ch->open_lock);
1532
1533 for (k = 0, lcd_cfg = mode;
1534 k < cfg->num_cfg && lcd_cfg;
1535 k++, lcd_cfg++) {
1536 unsigned long size = lcd_cfg->yres * lcd_cfg->xres;
1537 /* NV12 buffers must have even number of lines */
1538 if ((cfg->nonstd) && cfg->bpp == 12 &&
1539 (lcd_cfg->yres & 0x1)) {
1540 dev_err(&pdev->dev, "yres must be multiple of 2"
1541 " for YCbCr420 mode.\n");
1542 error = -EINVAL;
1543 goto err1;
1544 }
1545
1546 if (size > max_size) {
1547 max_cfg = lcd_cfg;
1548 max_size = size;
1549 }
1550 }
1551
1552 if (!mode)
1553 max_size = MAX_XRES * MAX_YRES;
1554 else if (max_cfg)
1555 dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
1556 max_cfg->xres, max_cfg->yres);
1557 1646
1558 info->fix = sh_mobile_lcdc_fix; 1647 error = sh_mobile_lcdc_channel_init(ch, &pdev->dev);
1559 info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
1560
1561 /* Only pan in 2 line steps for NV12 */
1562 if (cfg->nonstd && cfg->bpp == 12)
1563 info->fix.ypanstep = 2;
1564
1565 if (!mode) {
1566 mode = &default_720p;
1567 num_cfg = 1;
1568 } else {
1569 num_cfg = cfg->num_cfg;
1570 }
1571
1572 fb_videomode_to_modelist(mode, num_cfg, &info->modelist);
1573
1574 fb_videomode_to_var(var, mode);
1575 var->width = cfg->lcd_size_cfg.width;
1576 var->height = cfg->lcd_size_cfg.height;
1577 /* Default Y virtual resolution is 2x panel size */
1578 var->yres_virtual = var->yres * 2;
1579 var->activate = FB_ACTIVATE_NOW;
1580
1581 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp, cfg->nonstd);
1582 if (error) 1648 if (error)
1583 break; 1649 goto err1;
1584
1585 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
1586 &ch->dma_handle, GFP_KERNEL);
1587 if (!buf) {
1588 dev_err(&pdev->dev, "unable to allocate buffer\n");
1589 error = -ENOMEM;
1590 break;
1591 }
1592
1593 info->pseudo_palette = &ch->pseudo_palette;
1594 info->flags = FBINFO_FLAG_DEFAULT;
1595
1596 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1597 if (error < 0) {
1598 dev_err(&pdev->dev, "unable to allocate cmap\n");
1599 dma_free_coherent(&pdev->dev, info->fix.smem_len,
1600 buf, ch->dma_handle);
1601 break;
1602 }
1603
1604 info->fix.smem_start = ch->dma_handle;
1605 if (var->nonstd)
1606 info->fix.line_length = var->xres;
1607 else
1608 info->fix.line_length = var->xres * (cfg->bpp / 8);
1609
1610 info->screen_base = buf;
1611 info->device = &pdev->dev;
1612 ch->display_var = *var;
1613 } 1650 }
1614 1651
1615 if (error)
1616 goto err1;
1617
1618 error = sh_mobile_lcdc_start(priv); 1652 error = sh_mobile_lcdc_start(priv);
1619 if (error) { 1653 if (error) {
1620 dev_err(&pdev->dev, "unable to start hardware\n"); 1654 dev_err(&pdev->dev, "unable to start hardware\n");
1621 goto err1; 1655 goto err1;
1622 } 1656 }
1623 1657
1624 for (i = 0; i < j; i++) { 1658 for (i = 0; i < num_channels; i++) {
1625 struct sh_mobile_lcdc_chan *ch = priv->ch + i; 1659 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1626 1660 struct fb_info *info = ch->info;
1627 info = ch->info;
1628 1661
1629 if (info->fbdefio) { 1662 if (info->fbdefio) {
1630 ch->sglist = vmalloc(sizeof(struct scatterlist) * 1663 ch->sglist = vmalloc(sizeof(struct scatterlist) *
@@ -1665,57 +1698,6 @@ err1:
1665 return error; 1698 return error;
1666} 1699}
1667 1700
1668static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1669{
1670 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
1671 struct fb_info *info;
1672 int i;
1673
1674 fb_unregister_client(&priv->notifier);
1675
1676 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1677 if (priv->ch[i].info && priv->ch[i].info->dev)
1678 unregister_framebuffer(priv->ch[i].info);
1679
1680 sh_mobile_lcdc_stop(priv);
1681
1682 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
1683 info = priv->ch[i].info;
1684
1685 if (!info || !info->device)
1686 continue;
1687
1688 if (priv->ch[i].sglist)
1689 vfree(priv->ch[i].sglist);
1690
1691 if (info->screen_base)
1692 dma_free_coherent(&pdev->dev, info->fix.smem_len,
1693 info->screen_base,
1694 priv->ch[i].dma_handle);
1695 fb_dealloc_cmap(&info->cmap);
1696 framebuffer_release(info);
1697 }
1698
1699 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
1700 if (priv->ch[i].bl)
1701 sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
1702 }
1703
1704 if (priv->dot_clk)
1705 clk_put(priv->dot_clk);
1706
1707 if (priv->dev)
1708 pm_runtime_disable(priv->dev);
1709
1710 if (priv->base)
1711 iounmap(priv->base);
1712
1713 if (priv->irq)
1714 free_irq(priv->irq, priv);
1715 kfree(priv);
1716 return 0;
1717}
1718
1719static struct platform_driver sh_mobile_lcdc_driver = { 1701static struct platform_driver sh_mobile_lcdc_driver = {
1720 .driver = { 1702 .driver = {
1721 .name = "sh_mobile_lcdc_fb", 1703 .name = "sh_mobile_lcdc_fb",
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index aeed6687e6a..a58a0f38848 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -18,6 +18,13 @@ struct sh_mobile_lcdc_priv;
18struct fb_info; 18struct fb_info;
19struct backlight_device; 19struct backlight_device;
20 20
21/*
22 * struct sh_mobile_lcdc_chan - LCDC display channel
23 *
24 * @base_addr_y: Frame buffer viewport base address (luma component)
25 * @base_addr_c: Frame buffer viewport base address (chroma component)
26 * @pitch: Frame buffer line pitch
27 */
21struct sh_mobile_lcdc_chan { 28struct sh_mobile_lcdc_chan {
22 struct sh_mobile_lcdc_priv *lcdc; 29 struct sh_mobile_lcdc_priv *lcdc;
23 unsigned long *reg_offs; 30 unsigned long *reg_offs;
@@ -25,7 +32,6 @@ struct sh_mobile_lcdc_chan {
25 unsigned long enabled; /* ME and SE in LDCNT2R */ 32 unsigned long enabled; /* ME and SE in LDCNT2R */
26 struct sh_mobile_lcdc_chan_cfg cfg; 33 struct sh_mobile_lcdc_chan_cfg cfg;
27 u32 pseudo_palette[PALETTE_NR]; 34 u32 pseudo_palette[PALETTE_NR];
28 unsigned long saved_ch_regs[NR_CH_REGS];
29 struct fb_info *info; 35 struct fb_info *info;
30 struct backlight_device *bl; 36 struct backlight_device *bl;
31 dma_addr_t dma_handle; 37 dma_addr_t dma_handle;
@@ -40,6 +46,10 @@ struct sh_mobile_lcdc_chan {
40 int blank_status; 46 int blank_status;
41 struct mutex open_lock; /* protects the use counter */ 47 struct mutex open_lock; /* protects the use counter */
42 int meram_enabled; 48 int meram_enabled;
49
50 unsigned long base_addr_y;
51 unsigned long base_addr_c;
52 unsigned int pitch;
43}; 53};
44 54
45#endif 55#endif
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index cc7d7329dc1..4d63490209c 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -12,29 +12,103 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/device.h> 14#include <linux/device.h>
15#include <linux/pm_runtime.h>
15#include <linux/io.h> 16#include <linux/io.h>
16#include <linux/slab.h> 17#include <linux/slab.h>
17#include <linux/platform_device.h> 18#include <linux/platform_device.h>
18 19#include <video/sh_mobile_meram.h>
19#include "sh_mobile_meram.h"
20 20
21/* meram registers */ 21/* meram registers */
22#define MExxCTL 0x0 22#define MEVCR1 0x4
23#define MExxBSIZE 0x4 23#define MEVCR1_RST (1 << 31)
24#define MExxMNCF 0x8 24#define MEVCR1_WD (1 << 30)
25#define MExxSARA 0x10 25#define MEVCR1_AMD1 (1 << 29)
26#define MExxSARB 0x14 26#define MEVCR1_AMD0 (1 << 28)
27#define MExxSBSIZE 0x18 27#define MEQSEL1 0x40
28 28#define MEQSEL2 0x44
29#define MERAM_MExxCTL_VAL(ctl, next_icb, addr) \ 29
30 ((ctl) | (((next_icb) & 0x1f) << 11) | (((addr) & 0x7ff) << 16)) 30#define MExxCTL 0x400
31#define MERAM_MExxBSIZE_VAL(a, b, c) \ 31#define MExxCTL_BV (1 << 31)
32 (((a) << 28) | ((b) << 16) | (c)) 32#define MExxCTL_BSZ_SHIFT 28
33 33#define MExxCTL_MSAR_MASK (0x7ff << MExxCTL_MSAR_SHIFT)
34#define MEVCR1 0x4 34#define MExxCTL_MSAR_SHIFT 16
35#define MEACTS 0x10 35#define MExxCTL_NXT_MASK (0x1f << MExxCTL_NXT_SHIFT)
36#define MEQSEL1 0x40 36#define MExxCTL_NXT_SHIFT 11
37#define MEQSEL2 0x44 37#define MExxCTL_WD1 (1 << 10)
38#define MExxCTL_WD0 (1 << 9)
39#define MExxCTL_WS (1 << 8)
40#define MExxCTL_CB (1 << 7)
41#define MExxCTL_WBF (1 << 6)
42#define MExxCTL_WF (1 << 5)
43#define MExxCTL_RF (1 << 4)
44#define MExxCTL_CM (1 << 3)
45#define MExxCTL_MD_READ (1 << 0)
46#define MExxCTL_MD_WRITE (2 << 0)
47#define MExxCTL_MD_ICB_WB (3 << 0)
48#define MExxCTL_MD_ICB (4 << 0)
49#define MExxCTL_MD_FB (7 << 0)
50#define MExxCTL_MD_MASK (7 << 0)
51#define MExxBSIZE 0x404
52#define MExxBSIZE_RCNT_SHIFT 28
53#define MExxBSIZE_YSZM1_SHIFT 16
54#define MExxBSIZE_XSZM1_SHIFT 0
55#define MExxMNCF 0x408
56#define MExxMNCF_KWBNM_SHIFT 28
57#define MExxMNCF_KRBNM_SHIFT 24
58#define MExxMNCF_BNM_SHIFT 16
59#define MExxMNCF_XBV (1 << 15)
60#define MExxMNCF_CPL_YCBCR444 (1 << 12)
61#define MExxMNCF_CPL_YCBCR420 (2 << 12)
62#define MExxMNCF_CPL_YCBCR422 (3 << 12)
63#define MExxMNCF_CPL_MSK (3 << 12)
64#define MExxMNCF_BL (1 << 2)
65#define MExxMNCF_LNM_SHIFT 0
66#define MExxSARA 0x410
67#define MExxSARB 0x414
68#define MExxSBSIZE 0x418
69#define MExxSBSIZE_HDV (1 << 31)
70#define MExxSBSIZE_HSZ16 (0 << 28)
71#define MExxSBSIZE_HSZ32 (1 << 28)
72#define MExxSBSIZE_HSZ64 (2 << 28)
73#define MExxSBSIZE_HSZ128 (3 << 28)
74#define MExxSBSIZE_SBSIZZ_SHIFT 0
75
76#define MERAM_MExxCTL_VAL(next, addr) \
77 ((((next) << MExxCTL_NXT_SHIFT) & MExxCTL_NXT_MASK) | \
78 (((addr) << MExxCTL_MSAR_SHIFT) & MExxCTL_MSAR_MASK))
79#define MERAM_MExxBSIZE_VAL(rcnt, yszm1, xszm1) \
80 (((rcnt) << MExxBSIZE_RCNT_SHIFT) | \
81 ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \
82 ((xszm1) << MExxBSIZE_XSZM1_SHIFT))
83
84#define SH_MOBILE_MERAM_ICB_NUM 32
85
86static unsigned long common_regs[] = {
87 MEVCR1,
88 MEQSEL1,
89 MEQSEL2,
90};
91#define CMN_REGS_SIZE ARRAY_SIZE(common_regs)
92
93static unsigned long icb_regs[] = {
94 MExxCTL,
95 MExxBSIZE,
96 MExxMNCF,
97 MExxSARA,
98 MExxSARB,
99 MExxSBSIZE,
100};
101#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
102
103struct sh_mobile_meram_priv {
104 void __iomem *base;
105 struct mutex lock;
106 unsigned long used_icb;
107 int used_meram_cache_regions;
108 unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
109 unsigned long cmn_saved_regs[CMN_REGS_SIZE];
110 unsigned long icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM];
111};
38 112
39/* settings */ 113/* settings */
40#define MERAM_SEC_LINE 15 114#define MERAM_SEC_LINE 15
@@ -44,8 +118,7 @@
44 * MERAM/ICB access functions 118 * MERAM/ICB access functions
45 */ 119 */
46 120
47#define MERAM_ICB_OFFSET(base, idx, off) \ 121#define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20)
48 ((base) + (0x400 + ((idx) * 0x20) + (off)))
49 122
50static inline void meram_write_icb(void __iomem *base, int idx, int off, 123static inline void meram_write_icb(void __iomem *base, int idx, int off,
51 unsigned long val) 124 unsigned long val)
@@ -280,17 +353,18 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
280 /* 353 /*
281 * Set MERAM for framebuffer 354 * Set MERAM for framebuffer
282 * 355 *
283 * 0x70f: WD = 0x3, WS=0x1, CM=0x1, MD=FB mode
284 * we also chain the cache_icb and the marker_icb. 356 * we also chain the cache_icb and the marker_icb.
285 * we also split the allocated MERAM buffer between two ICBs. 357 * we also split the allocated MERAM buffer between two ICBs.
286 */ 358 */
287 meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 359 meram_write_icb(priv->base, icb->cache_icb, MExxCTL,
288 MERAM_MExxCTL_VAL(0x70f, icb->marker_icb, 360 MERAM_MExxCTL_VAL(icb->marker_icb, icb->meram_offset) |
289 icb->meram_offset)); 361 MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
362 MExxCTL_MD_FB);
290 meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 363 meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
291 MERAM_MExxCTL_VAL(0x70f, icb->cache_icb, 364 MERAM_MExxCTL_VAL(icb->cache_icb, icb->meram_offset +
292 icb->meram_offset + 365 icb->meram_size / 2) |
293 icb->meram_size / 2)); 366 MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
367 MExxCTL_MD_FB);
294 368
295 return 0; 369 return 0;
296} 370}
@@ -299,8 +373,10 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv,
299 struct sh_mobile_meram_icb *icb) 373 struct sh_mobile_meram_icb *icb)
300{ 374{
301 /* disable ICB */ 375 /* disable ICB */
302 meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 0); 376 meram_write_icb(priv->base, icb->cache_icb, MExxCTL,
303 meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 0); 377 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
378 meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
379 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
304 icb->cache_unit = 0; 380 icb->cache_unit = 0;
305} 381}
306 382
@@ -337,24 +413,22 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
337 xres, yres, (!pixelformat) ? "yuv" : "rgb", 413 xres, yres, (!pixelformat) ? "yuv" : "rgb",
338 base_addr_y, base_addr_c); 414 base_addr_y, base_addr_c);
339 415
340 mutex_lock(&priv->lock);
341
342 /* we can't handle wider than 8192px */ 416 /* we can't handle wider than 8192px */
343 if (xres > 8192) { 417 if (xres > 8192) {
344 dev_err(&pdev->dev, "width exceeding the limit (> 8192)."); 418 dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
345 error = -EINVAL; 419 return -EINVAL;
346 goto err;
347 }
348
349 if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
350 dev_err(&pdev->dev, "no more ICB available.");
351 error = -EINVAL;
352 goto err;
353 } 420 }
354 421
355 /* do we have at least one ICB config? */ 422 /* do we have at least one ICB config? */
356 if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) { 423 if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) {
357 dev_err(&pdev->dev, "at least one ICB is required."); 424 dev_err(&pdev->dev, "at least one ICB is required.");
425 return -EINVAL;
426 }
427
428 mutex_lock(&priv->lock);
429
430 if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
431 dev_err(&pdev->dev, "no more ICB available.");
358 error = -EINVAL; 432 error = -EINVAL;
359 goto err; 433 goto err;
360 } 434 }
@@ -460,6 +534,57 @@ static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata,
460 return 0; 534 return 0;
461} 535}
462 536
537static int sh_mobile_meram_runtime_suspend(struct device *dev)
538{
539 struct platform_device *pdev = to_platform_device(dev);
540 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
541 int k, j;
542
543 for (k = 0; k < CMN_REGS_SIZE; k++)
544 priv->cmn_saved_regs[k] = meram_read_reg(priv->base,
545 common_regs[k]);
546
547 for (j = 0; j < 32; j++) {
548 if (!test_bit(j, &priv->used_icb))
549 continue;
550 for (k = 0; k < ICB_REGS_SIZE; k++) {
551 priv->icb_saved_regs[j * ICB_REGS_SIZE + k] =
552 meram_read_icb(priv->base, j, icb_regs[k]);
553 /* Reset ICB on resume */
554 if (icb_regs[k] == MExxCTL)
555 priv->icb_saved_regs[j * ICB_REGS_SIZE + k] |=
556 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF;
557 }
558 }
559 return 0;
560}
561
562static int sh_mobile_meram_runtime_resume(struct device *dev)
563{
564 struct platform_device *pdev = to_platform_device(dev);
565 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
566 int k, j;
567
568 for (j = 0; j < 32; j++) {
569 if (!test_bit(j, &priv->used_icb))
570 continue;
571 for (k = 0; k < ICB_REGS_SIZE; k++) {
572 meram_write_icb(priv->base, j, icb_regs[k],
573 priv->icb_saved_regs[j * ICB_REGS_SIZE + k]);
574 }
575 }
576
577 for (k = 0; k < CMN_REGS_SIZE; k++)
578 meram_write_reg(priv->base, common_regs[k],
579 priv->cmn_saved_regs[k]);
580 return 0;
581}
582
583static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = {
584 .runtime_suspend = sh_mobile_meram_runtime_suspend,
585 .runtime_resume = sh_mobile_meram_runtime_resume,
586};
587
463static struct sh_mobile_meram_ops sh_mobile_meram_ops = { 588static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
464 .module = THIS_MODULE, 589 .module = THIS_MODULE,
465 .meram_register = sh_mobile_meram_register, 590 .meram_register = sh_mobile_meram_register,
@@ -513,7 +638,9 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
513 638
514 /* initialize ICB addressing mode */ 639 /* initialize ICB addressing mode */
515 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1) 640 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1)
516 meram_write_reg(priv->base, MEVCR1, 1 << 29); 641 meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1);
642
643 pm_runtime_enable(&pdev->dev);
517 644
518 dev_info(&pdev->dev, "sh_mobile_meram initialized."); 645 dev_info(&pdev->dev, "sh_mobile_meram initialized.");
519 646
@@ -530,6 +657,8 @@ static int sh_mobile_meram_remove(struct platform_device *pdev)
530{ 657{
531 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); 658 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
532 659
660 pm_runtime_disable(&pdev->dev);
661
533 if (priv->base) 662 if (priv->base)
534 iounmap(priv->base); 663 iounmap(priv->base);
535 664
@@ -544,6 +673,7 @@ static struct platform_driver sh_mobile_meram_driver = {
544 .driver = { 673 .driver = {
545 .name = "sh_mobile_meram", 674 .name = "sh_mobile_meram",
546 .owner = THIS_MODULE, 675 .owner = THIS_MODULE,
676 .pm = &sh_mobile_meram_dev_pm_ops,
547 }, 677 },
548 .probe = sh_mobile_meram_probe, 678 .probe = sh_mobile_meram_probe,
549 .remove = sh_mobile_meram_remove, 679 .remove = sh_mobile_meram_remove,
diff --git a/drivers/video/sh_mobile_meram.h b/drivers/video/sh_mobile_meram.h
deleted file mode 100644
index 82c54fbce8b..00000000000
--- a/drivers/video/sh_mobile_meram.h
+++ /dev/null
@@ -1,41 +0,0 @@
1#ifndef __sh_mobile_meram_h__
2#define __sh_mobile_meram_h__
3
4#include <linux/mutex.h>
5#include <video/sh_mobile_meram.h>
6
7/*
8 * MERAM private
9 */
10
11#define MERAM_ICB_Y 0x1
12#define MERAM_ICB_C 0x2
13
14/* MERAM cache size */
15#define SH_MOBILE_MERAM_ICB_NUM 32
16
17#define SH_MOBILE_MERAM_CACHE_OFFSET(p) ((p) >> 16)
18#define SH_MOBILE_MERAM_CACHE_SIZE(p) ((p) & 0xffff)
19
20struct sh_mobile_meram_priv {
21 void __iomem *base;
22 struct mutex lock;
23 unsigned long used_icb;
24 int used_meram_cache_regions;
25 unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
26};
27
28int sh_mobile_meram_alloc_icb(const struct sh_mobile_meram_cfg *cfg,
29 int xres,
30 int yres,
31 unsigned int base_addr,
32 int yuv_mode,
33 int *marker_icb,
34 int *out_pitch);
35
36void sh_mobile_meram_free_icb(int marker_icb);
37
38#define SH_MOBILE_MERAM_START(ind, ab) \
39 (0xC0000000 | ((ab & 0x1) << 23) | ((ind & 0x1F) << 24))
40
41#endif /* !__sh_mobile_meram_h__ */
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 75259845933..078ca2167d6 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1333,19 +1333,14 @@ sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1333} 1333}
1334 1334
1335static int 1335static int
1336sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) 1336sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
1337 struct fb_var_screeninfo *var)
1337{ 1338{
1338 if(var->xoffset > (var->xres_virtual - var->xres)) { 1339 ivideo->current_base = var->yoffset * info->var.xres_virtual
1339 return -EINVAL; 1340 + var->xoffset;
1340 }
1341 if(var->yoffset > (var->yres_virtual - var->yres)) {
1342 return -EINVAL;
1343 }
1344
1345 ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
1346 1341
1347 /* calculate base bpp dep. */ 1342 /* calculate base bpp dep. */
1348 switch(var->bits_per_pixel) { 1343 switch (info->var.bits_per_pixel) {
1349 case 32: 1344 case 32:
1350 break; 1345 break;
1351 case 16: 1346 case 16:
@@ -1635,20 +1630,15 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1635 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1630 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1636 int err; 1631 int err;
1637 1632
1638 if(var->xoffset > (var->xres_virtual - var->xres)) 1633 if (var->vmode & FB_VMODE_YWRAP)
1639 return -EINVAL;
1640
1641 if(var->yoffset > (var->yres_virtual - var->yres))
1642 return -EINVAL;
1643
1644 if(var->vmode & FB_VMODE_YWRAP)
1645 return -EINVAL; 1634 return -EINVAL;
1646 1635
1647 if(var->xoffset + info->var.xres > info->var.xres_virtual || 1636 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1648 var->yoffset + info->var.yres > info->var.yres_virtual) 1637 var->yoffset + info->var.yres > info->var.yres_virtual)
1649 return -EINVAL; 1638 return -EINVAL;
1650 1639
1651 if((err = sisfb_pan_var(ivideo, var)) < 0) 1640 err = sisfb_pan_var(ivideo, info, var);
1641 if (err < 0)
1652 return err; 1642 return err;
1653 1643
1654 info->var.xoffset = var->xoffset; 1644 info->var.xoffset = var->xoffset;
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 89158bc71da..30f7a815a62 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -989,7 +989,7 @@ static struct platform_device *xxxfb_device;
989 */ 989 */
990int __init xxxfb_setup(char *options) 990int __init xxxfb_setup(char *options)
991{ 991{
992 /* Parse user speficied options (`video=xxxfb:') */ 992 /* Parse user specified options (`video=xxxfb:') */
993} 993}
994#endif /* MODULE */ 994#endif /* MODULE */
995 995
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 6294dca9550..a78254cf8e8 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -582,7 +582,7 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
582{ 582{
583 struct sm501fb_par *par = info->par; 583 struct sm501fb_par *par = info->par;
584 struct sm501fb_info *fbi = par->info; 584 struct sm501fb_info *fbi = par->info;
585 unsigned int bytes_pixel = var->bits_per_pixel / 8; 585 unsigned int bytes_pixel = info->var.bits_per_pixel / 8;
586 unsigned long reg; 586 unsigned long reg;
587 unsigned long xoffs; 587 unsigned long xoffs;
588 588
@@ -614,10 +614,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
614 struct sm501fb_info *fbi = par->info; 614 struct sm501fb_info *fbi = par->info;
615 unsigned long reg; 615 unsigned long reg;
616 616
617 reg = var->xoffset | (var->xres_virtual << 16); 617 reg = var->xoffset | (info->var.xres_virtual << 16);
618 smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); 618 smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
619 619
620 reg = var->yoffset | (var->yres_virtual << 16); 620 reg = var->yoffset | (info->var.yres_virtual << 16);
621 smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); 621 smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
622 622
623 sm501fb_sync_regs(fbi); 623 sm501fb_sync_regs(fbi);
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c
new file mode 100644
index 00000000000..aaccffac67a
--- /dev/null
+++ b/drivers/video/smscufx.c
@@ -0,0 +1,1994 @@
1/*
2 * smscufx.c -- Framebuffer driver for SMSC UFX USB controller
3 *
4 * Copyright (C) 2011 Steve Glendinning <steve.glendinning@smsc.com>
5 * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
6 * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
7 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License v2. See the file COPYING in the main directory of this archive for
11 * more details.
12 *
13 * Based on udlfb, with work from Florian Echtler, Henrik Bjerregaard Pedersen,
14 * and others.
15 *
16 * Works well with Bernie Thompson's X DAMAGE patch to xf86-video-fbdev
17 * available from http://git.plugable.com
18 *
19 * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven,
20 * usb-skeleton by GregKH.
21 */
22
23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/init.h>
28#include <linux/usb.h>
29#include <linux/uaccess.h>
30#include <linux/mm.h>
31#include <linux/fb.h>
32#include <linux/vmalloc.h>
33#include <linux/slab.h>
34#include <linux/delay.h>
35#include "edid.h"
36
37#define check_warn(status, fmt, args...) \
38 ({ if (status < 0) pr_warn(fmt, ##args); })
39
40#define check_warn_return(status, fmt, args...) \
41 ({ if (status < 0) { pr_warn(fmt, ##args); return status; } })
42
43#define check_warn_goto_error(status, fmt, args...) \
44 ({ if (status < 0) { pr_warn(fmt, ##args); goto error; } })
45
46#define all_bits_set(x, bits) (((x) & (bits)) == (bits))
47
48#define USB_VENDOR_REQUEST_WRITE_REGISTER 0xA0
49#define USB_VENDOR_REQUEST_READ_REGISTER 0xA1
50
51/*
52 * TODO: Propose standard fb.h ioctl for reporting damage,
53 * using _IOWR() and one of the existing area structs from fb.h
54 * Consider these ioctls deprecated, but they're still used by the
55 * DisplayLink X server as yet - need both to be modified in tandem
56 * when new ioctl(s) are ready.
57 */
58#define UFX_IOCTL_RETURN_EDID (0xAD)
59#define UFX_IOCTL_REPORT_DAMAGE (0xAA)
60
61/* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */
62#define BULK_SIZE (512)
63#define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE)
64#define WRITES_IN_FLIGHT (4)
65
66#define GET_URB_TIMEOUT (HZ)
67#define FREE_URB_TIMEOUT (HZ*2)
68
69#define BPP 2
70
71#define UFX_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */
72#define UFX_DEFIO_WRITE_DISABLE (HZ*60) /* "disable" with long delay */
73
74struct dloarea {
75 int x, y;
76 int w, h;
77};
78
79struct urb_node {
80 struct list_head entry;
81 struct ufx_data *dev;
82 struct delayed_work release_urb_work;
83 struct urb *urb;
84};
85
86struct urb_list {
87 struct list_head list;
88 spinlock_t lock;
89 struct semaphore limit_sem;
90 int available;
91 int count;
92 size_t size;
93};
94
95struct ufx_data {
96 struct usb_device *udev;
97 struct device *gdev; /* &udev->dev */
98 struct fb_info *info;
99 struct urb_list urbs;
100 struct kref kref;
101 int fb_count;
102 bool virtualized; /* true when physical usb device not present */
103 struct delayed_work free_framebuffer_work;
104 atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
105 atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
106 u8 *edid; /* null until we read edid from hw or get from sysfs */
107 size_t edid_size;
108 u32 pseudo_palette[256];
109};
110
111static struct fb_fix_screeninfo ufx_fix = {
112 .id = "smscufx",
113 .type = FB_TYPE_PACKED_PIXELS,
114 .visual = FB_VISUAL_TRUECOLOR,
115 .xpanstep = 0,
116 .ypanstep = 0,
117 .ywrapstep = 0,
118 .accel = FB_ACCEL_NONE,
119};
120
121static const u32 smscufx_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
122 FBINFO_VIRTFB | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT |
123 FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
124
125static struct usb_device_id id_table[] = {
126 {USB_DEVICE(0x0424, 0x9d00),},
127 {USB_DEVICE(0x0424, 0x9d01),},
128 {},
129};
130MODULE_DEVICE_TABLE(usb, id_table);
131
132/* module options */
133static int console; /* Optionally allow fbcon to consume first framebuffer */
134static int fb_defio = true; /* Optionally enable fb_defio mmap support */
135
136/* ufx keeps a list of urbs for efficient bulk transfers */
137static void ufx_urb_completion(struct urb *urb);
138static struct urb *ufx_get_urb(struct ufx_data *dev);
139static int ufx_submit_urb(struct ufx_data *dev, struct urb * urb, size_t len);
140static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size);
141static void ufx_free_urb_list(struct ufx_data *dev);
142
143/* reads a control register */
144static int ufx_reg_read(struct ufx_data *dev, u32 index, u32 *data)
145{
146 u32 *buf = kmalloc(4, GFP_KERNEL);
147 int ret;
148
149 BUG_ON(!dev);
150
151 if (!buf)
152 return -ENOMEM;
153
154 ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
155 USB_VENDOR_REQUEST_READ_REGISTER,
156 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
157 00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
158
159 le32_to_cpus(buf);
160 *data = *buf;
161 kfree(buf);
162
163 if (unlikely(ret < 0))
164 pr_warn("Failed to read register index 0x%08x\n", index);
165
166 return ret;
167}
168
169/* writes a control register */
170static int ufx_reg_write(struct ufx_data *dev, u32 index, u32 data)
171{
172 u32 *buf = kmalloc(4, GFP_KERNEL);
173 int ret;
174
175 BUG_ON(!dev);
176
177 if (!buf)
178 return -ENOMEM;
179
180 *buf = data;
181 cpu_to_le32s(buf);
182
183 ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
184 USB_VENDOR_REQUEST_WRITE_REGISTER,
185 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
186 00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
187
188 kfree(buf);
189
190 if (unlikely(ret < 0))
191 pr_warn("Failed to write register index 0x%08x with value "
192 "0x%08x\n", index, data);
193
194 return ret;
195}
196
197static int ufx_reg_clear_and_set_bits(struct ufx_data *dev, u32 index,
198 u32 bits_to_clear, u32 bits_to_set)
199{
200 u32 data;
201 int status = ufx_reg_read(dev, index, &data);
202 check_warn_return(status, "ufx_reg_clear_and_set_bits error reading "
203 "0x%x", index);
204
205 data &= (~bits_to_clear);
206 data |= bits_to_set;
207
208 status = ufx_reg_write(dev, index, data);
209 check_warn_return(status, "ufx_reg_clear_and_set_bits error writing "
210 "0x%x", index);
211
212 return 0;
213}
214
215static int ufx_reg_set_bits(struct ufx_data *dev, u32 index, u32 bits)
216{
217 return ufx_reg_clear_and_set_bits(dev, index, 0, bits);
218}
219
220static int ufx_reg_clear_bits(struct ufx_data *dev, u32 index, u32 bits)
221{
222 return ufx_reg_clear_and_set_bits(dev, index, bits, 0);
223}
224
225static int ufx_lite_reset(struct ufx_data *dev)
226{
227 int status;
228 u32 value;
229
230 status = ufx_reg_write(dev, 0x3008, 0x00000001);
231 check_warn_return(status, "ufx_lite_reset error writing 0x3008");
232
233 status = ufx_reg_read(dev, 0x3008, &value);
234 check_warn_return(status, "ufx_lite_reset error reading 0x3008");
235
236 return (value == 0) ? 0 : -EIO;
237}
238
239/* If display is unblanked, then blank it */
240static int ufx_blank(struct ufx_data *dev, bool wait)
241{
242 u32 dc_ctrl, dc_sts;
243 int i;
244
245 int status = ufx_reg_read(dev, 0x2004, &dc_sts);
246 check_warn_return(status, "ufx_blank error reading 0x2004");
247
248 status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
249 check_warn_return(status, "ufx_blank error reading 0x2000");
250
251 /* return success if display is already blanked */
252 if ((dc_sts & 0x00000100) || (dc_ctrl & 0x00000100))
253 return 0;
254
255 /* request the DC to blank the display */
256 dc_ctrl |= 0x00000100;
257 status = ufx_reg_write(dev, 0x2000, dc_ctrl);
258 check_warn_return(status, "ufx_blank error writing 0x2000");
259
260 /* return success immediately if we don't have to wait */
261 if (!wait)
262 return 0;
263
264 for (i = 0; i < 250; i++) {
265 status = ufx_reg_read(dev, 0x2004, &dc_sts);
266 check_warn_return(status, "ufx_blank error reading 0x2004");
267
268 if (dc_sts & 0x00000100)
269 return 0;
270 }
271
272 /* timed out waiting for display to blank */
273 return -EIO;
274}
275
276/* If display is blanked, then unblank it */
277static int ufx_unblank(struct ufx_data *dev, bool wait)
278{
279 u32 dc_ctrl, dc_sts;
280 int i;
281
282 int status = ufx_reg_read(dev, 0x2004, &dc_sts);
283 check_warn_return(status, "ufx_unblank error reading 0x2004");
284
285 status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
286 check_warn_return(status, "ufx_unblank error reading 0x2000");
287
288 /* return success if display is already unblanked */
289 if (((dc_sts & 0x00000100) == 0) || ((dc_ctrl & 0x00000100) == 0))
290 return 0;
291
292 /* request the DC to unblank the display */
293 dc_ctrl &= ~0x00000100;
294 status = ufx_reg_write(dev, 0x2000, dc_ctrl);
295 check_warn_return(status, "ufx_unblank error writing 0x2000");
296
297 /* return success immediately if we don't have to wait */
298 if (!wait)
299 return 0;
300
301 for (i = 0; i < 250; i++) {
302 status = ufx_reg_read(dev, 0x2004, &dc_sts);
303 check_warn_return(status, "ufx_unblank error reading 0x2004");
304
305 if ((dc_sts & 0x00000100) == 0)
306 return 0;
307 }
308
309 /* timed out waiting for display to unblank */
310 return -EIO;
311}
312
313/* If display is enabled, then disable it */
314static int ufx_disable(struct ufx_data *dev, bool wait)
315{
316 u32 dc_ctrl, dc_sts;
317 int i;
318
319 int status = ufx_reg_read(dev, 0x2004, &dc_sts);
320 check_warn_return(status, "ufx_disable error reading 0x2004");
321
322 status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
323 check_warn_return(status, "ufx_disable error reading 0x2000");
324
325 /* return success if display is already disabled */
326 if (((dc_sts & 0x00000001) == 0) || ((dc_ctrl & 0x00000001) == 0))
327 return 0;
328
329 /* request the DC to disable the display */
330 dc_ctrl &= ~(0x00000001);
331 status = ufx_reg_write(dev, 0x2000, dc_ctrl);
332 check_warn_return(status, "ufx_disable error writing 0x2000");
333
334 /* return success immediately if we don't have to wait */
335 if (!wait)
336 return 0;
337
338 for (i = 0; i < 250; i++) {
339 status = ufx_reg_read(dev, 0x2004, &dc_sts);
340 check_warn_return(status, "ufx_disable error reading 0x2004");
341
342 if ((dc_sts & 0x00000001) == 0)
343 return 0;
344 }
345
346 /* timed out waiting for display to disable */
347 return -EIO;
348}
349
350/* If display is disabled, then enable it */
351static int ufx_enable(struct ufx_data *dev, bool wait)
352{
353 u32 dc_ctrl, dc_sts;
354 int i;
355
356 int status = ufx_reg_read(dev, 0x2004, &dc_sts);
357 check_warn_return(status, "ufx_enable error reading 0x2004");
358
359 status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
360 check_warn_return(status, "ufx_enable error reading 0x2000");
361
362 /* return success if display is already enabled */
363 if ((dc_sts & 0x00000001) || (dc_ctrl & 0x00000001))
364 return 0;
365
366 /* request the DC to enable the display */
367 dc_ctrl |= 0x00000001;
368 status = ufx_reg_write(dev, 0x2000, dc_ctrl);
369 check_warn_return(status, "ufx_enable error writing 0x2000");
370
371 /* return success immediately if we don't have to wait */
372 if (!wait)
373 return 0;
374
375 for (i = 0; i < 250; i++) {
376 status = ufx_reg_read(dev, 0x2004, &dc_sts);
377 check_warn_return(status, "ufx_enable error reading 0x2004");
378
379 if (dc_sts & 0x00000001)
380 return 0;
381 }
382
383 /* timed out waiting for display to enable */
384 return -EIO;
385}
386
387static int ufx_config_sys_clk(struct ufx_data *dev)
388{
389 int status = ufx_reg_write(dev, 0x700C, 0x8000000F);
390 check_warn_return(status, "error writing 0x700C");
391
392 status = ufx_reg_write(dev, 0x7014, 0x0010024F);
393 check_warn_return(status, "error writing 0x7014");
394
395 status = ufx_reg_write(dev, 0x7010, 0x00000000);
396 check_warn_return(status, "error writing 0x7010");
397
398 status = ufx_reg_clear_bits(dev, 0x700C, 0x0000000A);
399 check_warn_return(status, "error clearing PLL1 bypass in 0x700C");
400 msleep(1);
401
402 status = ufx_reg_clear_bits(dev, 0x700C, 0x80000000);
403 check_warn_return(status, "error clearing output gate in 0x700C");
404
405 return 0;
406}
407
408static int ufx_config_ddr2(struct ufx_data *dev)
409{
410 int status, i = 0;
411 u32 tmp;
412
413 status = ufx_reg_write(dev, 0x0004, 0x001F0F77);
414 check_warn_return(status, "error writing 0x0004");
415
416 status = ufx_reg_write(dev, 0x0008, 0xFFF00000);
417 check_warn_return(status, "error writing 0x0008");
418
419 status = ufx_reg_write(dev, 0x000C, 0x0FFF2222);
420 check_warn_return(status, "error writing 0x000C");
421
422 status = ufx_reg_write(dev, 0x0010, 0x00030814);
423 check_warn_return(status, "error writing 0x0010");
424
425 status = ufx_reg_write(dev, 0x0014, 0x00500019);
426 check_warn_return(status, "error writing 0x0014");
427
428 status = ufx_reg_write(dev, 0x0018, 0x020D0F15);
429 check_warn_return(status, "error writing 0x0018");
430
431 status = ufx_reg_write(dev, 0x001C, 0x02532305);
432 check_warn_return(status, "error writing 0x001C");
433
434 status = ufx_reg_write(dev, 0x0020, 0x0B030905);
435 check_warn_return(status, "error writing 0x0020");
436
437 status = ufx_reg_write(dev, 0x0024, 0x00000827);
438 check_warn_return(status, "error writing 0x0024");
439
440 status = ufx_reg_write(dev, 0x0028, 0x00000000);
441 check_warn_return(status, "error writing 0x0028");
442
443 status = ufx_reg_write(dev, 0x002C, 0x00000042);
444 check_warn_return(status, "error writing 0x002C");
445
446 status = ufx_reg_write(dev, 0x0030, 0x09520000);
447 check_warn_return(status, "error writing 0x0030");
448
449 status = ufx_reg_write(dev, 0x0034, 0x02223314);
450 check_warn_return(status, "error writing 0x0034");
451
452 status = ufx_reg_write(dev, 0x0038, 0x00430043);
453 check_warn_return(status, "error writing 0x0038");
454
455 status = ufx_reg_write(dev, 0x003C, 0xF00F000F);
456 check_warn_return(status, "error writing 0x003C");
457
458 status = ufx_reg_write(dev, 0x0040, 0xF380F00F);
459 check_warn_return(status, "error writing 0x0040");
460
461 status = ufx_reg_write(dev, 0x0044, 0xF00F0496);
462 check_warn_return(status, "error writing 0x0044");
463
464 status = ufx_reg_write(dev, 0x0048, 0x03080406);
465 check_warn_return(status, "error writing 0x0048");
466
467 status = ufx_reg_write(dev, 0x004C, 0x00001000);
468 check_warn_return(status, "error writing 0x004C");
469
470 status = ufx_reg_write(dev, 0x005C, 0x00000007);
471 check_warn_return(status, "error writing 0x005C");
472
473 status = ufx_reg_write(dev, 0x0100, 0x54F00012);
474 check_warn_return(status, "error writing 0x0100");
475
476 status = ufx_reg_write(dev, 0x0104, 0x00004012);
477 check_warn_return(status, "error writing 0x0104");
478
479 status = ufx_reg_write(dev, 0x0118, 0x40404040);
480 check_warn_return(status, "error writing 0x0118");
481
482 status = ufx_reg_write(dev, 0x0000, 0x00000001);
483 check_warn_return(status, "error writing 0x0000");
484
485 while (i++ < 500) {
486 status = ufx_reg_read(dev, 0x0000, &tmp);
487 check_warn_return(status, "error reading 0x0000");
488
489 if (all_bits_set(tmp, 0xC0000000))
490 return 0;
491 }
492
493 pr_err("DDR2 initialisation timed out, reg 0x0000=0x%08x", tmp);
494 return -ETIMEDOUT;
495}
496
497struct pll_values {
498 u32 div_r0;
499 u32 div_f0;
500 u32 div_q0;
501 u32 range0;
502 u32 div_r1;
503 u32 div_f1;
504 u32 div_q1;
505 u32 range1;
506};
507
508static u32 ufx_calc_range(u32 ref_freq)
509{
510 if (ref_freq >= 88000000)
511 return 7;
512
513 if (ref_freq >= 54000000)
514 return 6;
515
516 if (ref_freq >= 34000000)
517 return 5;
518
519 if (ref_freq >= 21000000)
520 return 4;
521
522 if (ref_freq >= 13000000)
523 return 3;
524
525 if (ref_freq >= 8000000)
526 return 2;
527
528 return 1;
529}
530
531/* calculates PLL divider settings for a desired target frequency */
532static void ufx_calc_pll_values(const u32 clk_pixel_pll, struct pll_values *asic_pll)
533{
534 const u32 ref_clk = 25000000;
535 u32 div_r0, div_f0, div_q0, div_r1, div_f1, div_q1;
536 u32 min_error = clk_pixel_pll;
537
538 for (div_r0 = 1; div_r0 <= 32; div_r0++) {
539 u32 ref_freq0 = ref_clk / div_r0;
540 if (ref_freq0 < 5000000)
541 break;
542
543 if (ref_freq0 > 200000000)
544 continue;
545
546 for (div_f0 = 1; div_f0 <= 256; div_f0++) {
547 u32 vco_freq0 = ref_freq0 * div_f0;
548
549 if (vco_freq0 < 350000000)
550 continue;
551
552 if (vco_freq0 > 700000000)
553 break;
554
555 for (div_q0 = 0; div_q0 < 7; div_q0++) {
556 u32 pllout_freq0 = vco_freq0 / (1 << div_q0);
557
558 if (pllout_freq0 < 5000000)
559 break;
560
561 if (pllout_freq0 > 200000000)
562 continue;
563
564 for (div_r1 = 1; div_r1 <= 32; div_r1++) {
565 u32 ref_freq1 = pllout_freq0 / div_r1;
566
567 if (ref_freq1 < 5000000)
568 break;
569
570 for (div_f1 = 1; div_f1 <= 256; div_f1++) {
571 u32 vco_freq1 = ref_freq1 * div_f1;
572
573 if (vco_freq1 < 350000000)
574 continue;
575
576 if (vco_freq1 > 700000000)
577 break;
578
579 for (div_q1 = 0; div_q1 < 7; div_q1++) {
580 u32 pllout_freq1 = vco_freq1 / (1 << div_q1);
581 int error = abs(pllout_freq1 - clk_pixel_pll);
582
583 if (pllout_freq1 < 5000000)
584 break;
585
586 if (pllout_freq1 > 700000000)
587 continue;
588
589 if (error < min_error) {
590 min_error = error;
591
592 /* final returned value is equal to calculated value - 1
593 * because a value of 0 = divide by 1 */
594 asic_pll->div_r0 = div_r0 - 1;
595 asic_pll->div_f0 = div_f0 - 1;
596 asic_pll->div_q0 = div_q0;
597 asic_pll->div_r1 = div_r1 - 1;
598 asic_pll->div_f1 = div_f1 - 1;
599 asic_pll->div_q1 = div_q1;
600
601 asic_pll->range0 = ufx_calc_range(ref_freq0);
602 asic_pll->range1 = ufx_calc_range(ref_freq1);
603
604 if (min_error == 0)
605 return;
606 }
607 }
608 }
609 }
610 }
611 }
612 }
613}
614
615/* sets analog bit PLL configuration values */
616static int ufx_config_pix_clk(struct ufx_data *dev, u32 pixclock)
617{
618 struct pll_values asic_pll = {0};
619 u32 value, clk_pixel, clk_pixel_pll;
620 int status;
621
622 /* convert pixclock (in ps) to frequency (in Hz) */
623 clk_pixel = PICOS2KHZ(pixclock) * 1000;
624 pr_debug("pixclock %d ps = clk_pixel %d Hz", pixclock, clk_pixel);
625
626 /* clk_pixel = 1/2 clk_pixel_pll */
627 clk_pixel_pll = clk_pixel * 2;
628
629 ufx_calc_pll_values(clk_pixel_pll, &asic_pll);
630
631 /* Keep BYPASS and RESET signals asserted until configured */
632 status = ufx_reg_write(dev, 0x7000, 0x8000000F);
633 check_warn_return(status, "error writing 0x7000");
634
635 value = (asic_pll.div_f1 | (asic_pll.div_r1 << 8) |
636 (asic_pll.div_q1 << 16) | (asic_pll.range1 << 20));
637 status = ufx_reg_write(dev, 0x7008, value);
638 check_warn_return(status, "error writing 0x7008");
639
640 value = (asic_pll.div_f0 | (asic_pll.div_r0 << 8) |
641 (asic_pll.div_q0 << 16) | (asic_pll.range0 << 20));
642 status = ufx_reg_write(dev, 0x7004, value);
643 check_warn_return(status, "error writing 0x7004");
644
645 status = ufx_reg_clear_bits(dev, 0x7000, 0x00000005);
646 check_warn_return(status,
647 "error clearing PLL0 bypass bits in 0x7000");
648 msleep(1);
649
650 status = ufx_reg_clear_bits(dev, 0x7000, 0x0000000A);
651 check_warn_return(status,
652 "error clearing PLL1 bypass bits in 0x7000");
653 msleep(1);
654
655 status = ufx_reg_clear_bits(dev, 0x7000, 0x80000000);
656 check_warn_return(status, "error clearing gate bits in 0x7000");
657
658 return 0;
659}
660
661static int ufx_set_vid_mode(struct ufx_data *dev, struct fb_var_screeninfo *var)
662{
663 u32 temp;
664 u16 h_total, h_active, h_blank_start, h_blank_end, h_sync_start, h_sync_end;
665 u16 v_total, v_active, v_blank_start, v_blank_end, v_sync_start, v_sync_end;
666
667 int status = ufx_reg_write(dev, 0x8028, 0);
668 check_warn_return(status, "ufx_set_vid_mode error disabling RGB pad");
669
670 status = ufx_reg_write(dev, 0x8024, 0);
671 check_warn_return(status, "ufx_set_vid_mode error disabling VDAC");
672
673 /* shut everything down before changing timing */
674 status = ufx_blank(dev, true);
675 check_warn_return(status, "ufx_set_vid_mode error blanking display");
676
677 status = ufx_disable(dev, true);
678 check_warn_return(status, "ufx_set_vid_mode error disabling display");
679
680 status = ufx_config_pix_clk(dev, var->pixclock);
681 check_warn_return(status, "ufx_set_vid_mode error configuring pixclock");
682
683 status = ufx_reg_write(dev, 0x2000, 0x00000104);
684 check_warn_return(status, "ufx_set_vid_mode error writing 0x2000");
685
686 /* set horizontal timings */
687 h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
688 h_active = var->xres;
689 h_blank_start = var->xres + var->right_margin;
690 h_blank_end = var->xres + var->right_margin + var->hsync_len;
691 h_sync_start = var->xres + var->right_margin;
692 h_sync_end = var->xres + var->right_margin + var->hsync_len;
693
694 temp = ((h_total - 1) << 16) | (h_active - 1);
695 status = ufx_reg_write(dev, 0x2008, temp);
696 check_warn_return(status, "ufx_set_vid_mode error writing 0x2008");
697
698 temp = ((h_blank_start - 1) << 16) | (h_blank_end - 1);
699 status = ufx_reg_write(dev, 0x200C, temp);
700 check_warn_return(status, "ufx_set_vid_mode error writing 0x200C");
701
702 temp = ((h_sync_start - 1) << 16) | (h_sync_end - 1);
703 status = ufx_reg_write(dev, 0x2010, temp);
704 check_warn_return(status, "ufx_set_vid_mode error writing 0x2010");
705
706 /* set vertical timings */
707 v_total = var->upper_margin + var->yres + var->lower_margin + var->vsync_len;
708 v_active = var->yres;
709 v_blank_start = var->yres + var->lower_margin;
710 v_blank_end = var->yres + var->lower_margin + var->vsync_len;
711 v_sync_start = var->yres + var->lower_margin;
712 v_sync_end = var->yres + var->lower_margin + var->vsync_len;
713
714 temp = ((v_total - 1) << 16) | (v_active - 1);
715 status = ufx_reg_write(dev, 0x2014, temp);
716 check_warn_return(status, "ufx_set_vid_mode error writing 0x2014");
717
718 temp = ((v_blank_start - 1) << 16) | (v_blank_end - 1);
719 status = ufx_reg_write(dev, 0x2018, temp);
720 check_warn_return(status, "ufx_set_vid_mode error writing 0x2018");
721
722 temp = ((v_sync_start - 1) << 16) | (v_sync_end - 1);
723 status = ufx_reg_write(dev, 0x201C, temp);
724 check_warn_return(status, "ufx_set_vid_mode error writing 0x201C");
725
726 status = ufx_reg_write(dev, 0x2020, 0x00000000);
727 check_warn_return(status, "ufx_set_vid_mode error writing 0x2020");
728
729 status = ufx_reg_write(dev, 0x2024, 0x00000000);
730 check_warn_return(status, "ufx_set_vid_mode error writing 0x2024");
731
732 /* Set the frame length register (#pix * 2 bytes/pixel) */
733 temp = var->xres * var->yres * 2;
734 temp = (temp + 7) & (~0x7);
735 status = ufx_reg_write(dev, 0x2028, temp);
736 check_warn_return(status, "ufx_set_vid_mode error writing 0x2028");
737
738 /* enable desired output interface & disable others */
739 status = ufx_reg_write(dev, 0x2040, 0);
740 check_warn_return(status, "ufx_set_vid_mode error writing 0x2040");
741
742 status = ufx_reg_write(dev, 0x2044, 0);
743 check_warn_return(status, "ufx_set_vid_mode error writing 0x2044");
744
745 status = ufx_reg_write(dev, 0x2048, 0);
746 check_warn_return(status, "ufx_set_vid_mode error writing 0x2048");
747
748 /* set the sync polarities & enable bit */
749 temp = 0x00000001;
750 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
751 temp |= 0x00000010;
752
753 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
754 temp |= 0x00000008;
755
756 status = ufx_reg_write(dev, 0x2040, temp);
757 check_warn_return(status, "ufx_set_vid_mode error writing 0x2040");
758
759 /* start everything back up */
760 status = ufx_enable(dev, true);
761 check_warn_return(status, "ufx_set_vid_mode error enabling display");
762
763 /* Unblank the display */
764 status = ufx_unblank(dev, true);
765 check_warn_return(status, "ufx_set_vid_mode error unblanking display");
766
767 /* enable RGB pad */
768 status = ufx_reg_write(dev, 0x8028, 0x00000003);
769 check_warn_return(status, "ufx_set_vid_mode error enabling RGB pad");
770
771 /* enable VDAC */
772 status = ufx_reg_write(dev, 0x8024, 0x00000007);
773 check_warn_return(status, "ufx_set_vid_mode error enabling VDAC");
774
775 return 0;
776}
777
778static int ufx_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
779{
780 unsigned long start = vma->vm_start;
781 unsigned long size = vma->vm_end - vma->vm_start;
782 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
783 unsigned long page, pos;
784
785 if (offset + size > info->fix.smem_len)
786 return -EINVAL;
787
788 pos = (unsigned long)info->fix.smem_start + offset;
789
790 pr_debug("mmap() framebuffer addr:%lu size:%lu\n",
791 pos, size);
792
793 while (size > 0) {
794 page = vmalloc_to_pfn((void *)pos);
795 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
796 return -EAGAIN;
797
798 start += PAGE_SIZE;
799 pos += PAGE_SIZE;
800 if (size > PAGE_SIZE)
801 size -= PAGE_SIZE;
802 else
803 size = 0;
804 }
805
806 vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
807 return 0;
808}
809
810static void ufx_raw_rect(struct ufx_data *dev, u16 *cmd, int x, int y,
811 int width, int height)
812{
813 size_t packed_line_len = ALIGN((width * 2), 4);
814 size_t packed_rect_len = packed_line_len * height;
815 int line;
816
817 BUG_ON(!dev);
818 BUG_ON(!dev->info);
819
820 /* command word */
821 *((u32 *)&cmd[0]) = cpu_to_le32(0x01);
822
823 /* length word */
824 *((u32 *)&cmd[2]) = cpu_to_le32(packed_rect_len + 16);
825
826 cmd[4] = cpu_to_le16(x);
827 cmd[5] = cpu_to_le16(y);
828 cmd[6] = cpu_to_le16(width);
829 cmd[7] = cpu_to_le16(height);
830
831 /* frame base address */
832 *((u32 *)&cmd[8]) = cpu_to_le32(0);
833
834 /* color mode and horizontal resolution */
835 cmd[10] = cpu_to_le16(0x4000 | dev->info->var.xres);
836
837 /* vertical resolution */
838 cmd[11] = cpu_to_le16(dev->info->var.yres);
839
840 /* packed data */
841 for (line = 0; line < height; line++) {
842 const int line_offset = dev->info->fix.line_length * (y + line);
843 const int byte_offset = line_offset + (x * BPP);
844 memcpy(&cmd[(24 + (packed_line_len * line)) / 2],
845 (char *)dev->info->fix.smem_start + byte_offset, width * BPP);
846 }
847}
848
849int ufx_handle_damage(struct ufx_data *dev, int x, int y,
850 int width, int height)
851{
852 size_t packed_line_len = ALIGN((width * 2), 4);
853 int len, status, urb_lines, start_line = 0;
854
855 if ((width <= 0) || (height <= 0) ||
856 (x + width > dev->info->var.xres) ||
857 (y + height > dev->info->var.yres))
858 return -EINVAL;
859
860 if (!atomic_read(&dev->usb_active))
861 return 0;
862
863 while (start_line < height) {
864 struct urb *urb = ufx_get_urb(dev);
865 if (!urb) {
866 pr_warn("ufx_handle_damage unable to get urb");
867 return 0;
868 }
869
870 /* assume we have enough space to transfer at least one line */
871 BUG_ON(urb->transfer_buffer_length < (24 + (width * 2)));
872
873 /* calculate the maximum number of lines we could fit in */
874 urb_lines = (urb->transfer_buffer_length - 24) / packed_line_len;
875
876 /* but we might not need this many */
877 urb_lines = min(urb_lines, (height - start_line));
878
879 memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
880
881 ufx_raw_rect(dev, urb->transfer_buffer, x, (y + start_line), width, urb_lines);
882 len = 24 + (packed_line_len * urb_lines);
883
884 status = ufx_submit_urb(dev, urb, len);
885 check_warn_return(status, "Error submitting URB");
886
887 start_line += urb_lines;
888 }
889
890 return 0;
891}
892
893/* Path triggered by usermode clients who write to filesystem
894 * e.g. cat filename > /dev/fb1
895 * Not used by X Windows or text-mode console. But useful for testing.
896 * Slow because of extra copy and we must assume all pixels dirty. */
897static ssize_t ufx_ops_write(struct fb_info *info, const char __user *buf,
898 size_t count, loff_t *ppos)
899{
900 ssize_t result;
901 struct ufx_data *dev = info->par;
902 u32 offset = (u32) *ppos;
903
904 result = fb_sys_write(info, buf, count, ppos);
905
906 if (result > 0) {
907 int start = max((int)(offset / info->fix.line_length) - 1, 0);
908 int lines = min((u32)((result / info->fix.line_length) + 1),
909 (u32)info->var.yres);
910
911 ufx_handle_damage(dev, 0, start, info->var.xres, lines);
912 }
913
914 return result;
915}
916
917static void ufx_ops_copyarea(struct fb_info *info,
918 const struct fb_copyarea *area)
919{
920
921 struct ufx_data *dev = info->par;
922
923 sys_copyarea(info, area);
924
925 ufx_handle_damage(dev, area->dx, area->dy,
926 area->width, area->height);
927}
928
929static void ufx_ops_imageblit(struct fb_info *info,
930 const struct fb_image *image)
931{
932 struct ufx_data *dev = info->par;
933
934 sys_imageblit(info, image);
935
936 ufx_handle_damage(dev, image->dx, image->dy,
937 image->width, image->height);
938}
939
940static void ufx_ops_fillrect(struct fb_info *info,
941 const struct fb_fillrect *rect)
942{
943 struct ufx_data *dev = info->par;
944
945 sys_fillrect(info, rect);
946
947 ufx_handle_damage(dev, rect->dx, rect->dy, rect->width,
948 rect->height);
949}
950
951/* NOTE: fb_defio.c is holding info->fbdefio.mutex
952 * Touching ANY framebuffer memory that triggers a page fault
953 * in fb_defio will cause a deadlock, when it also tries to
954 * grab the same mutex. */
955static void ufx_dpy_deferred_io(struct fb_info *info,
956 struct list_head *pagelist)
957{
958 struct page *cur;
959 struct fb_deferred_io *fbdefio = info->fbdefio;
960 struct ufx_data *dev = info->par;
961
962 if (!fb_defio)
963 return;
964
965 if (!atomic_read(&dev->usb_active))
966 return;
967
968 /* walk the written page list and render each to device */
969 list_for_each_entry(cur, &fbdefio->pagelist, lru) {
970 /* create a rectangle of full screen width that encloses the
971 * entire dirty framebuffer page */
972 const int x = 0;
973 const int width = dev->info->var.xres;
974 const int y = (cur->index << PAGE_SHIFT) / (width * 2);
975 int height = (PAGE_SIZE / (width * 2)) + 1;
976 height = min(height, (int)(dev->info->var.yres - y));
977
978 BUG_ON(y >= dev->info->var.yres);
979 BUG_ON((y + height) > dev->info->var.yres);
980
981 ufx_handle_damage(dev, x, y, width, height);
982 }
983}
984
985static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd,
986 unsigned long arg)
987{
988 struct ufx_data *dev = info->par;
989 struct dloarea *area = NULL;
990
991 if (!atomic_read(&dev->usb_active))
992 return 0;
993
994 /* TODO: Update X server to get this from sysfs instead */
995 if (cmd == UFX_IOCTL_RETURN_EDID) {
996 u8 __user *edid = (u8 __user *)arg;
997 if (copy_to_user(edid, dev->edid, dev->edid_size))
998 return -EFAULT;
999 return 0;
1000 }
1001
1002 /* TODO: Help propose a standard fb.h ioctl to report mmap damage */
1003 if (cmd == UFX_IOCTL_REPORT_DAMAGE) {
1004 /* If we have a damage-aware client, turn fb_defio "off"
1005 * To avoid perf imact of unecessary page fault handling.
1006 * Done by resetting the delay for this fb_info to a very
1007 * long period. Pages will become writable and stay that way.
1008 * Reset to normal value when all clients have closed this fb.
1009 */
1010 if (info->fbdefio)
1011 info->fbdefio->delay = UFX_DEFIO_WRITE_DISABLE;
1012
1013 area = (struct dloarea *)arg;
1014
1015 if (area->x < 0)
1016 area->x = 0;
1017
1018 if (area->x > info->var.xres)
1019 area->x = info->var.xres;
1020
1021 if (area->y < 0)
1022 area->y = 0;
1023
1024 if (area->y > info->var.yres)
1025 area->y = info->var.yres;
1026
1027 ufx_handle_damage(dev, area->x, area->y, area->w, area->h);
1028 }
1029
1030 return 0;
1031}
1032
1033/* taken from vesafb */
1034static int
1035ufx_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
1036 unsigned blue, unsigned transp, struct fb_info *info)
1037{
1038 int err = 0;
1039
1040 if (regno >= info->cmap.len)
1041 return 1;
1042
1043 if (regno < 16) {
1044 if (info->var.red.offset == 10) {
1045 /* 1:5:5:5 */
1046 ((u32 *) (info->pseudo_palette))[regno] =
1047 ((red & 0xf800) >> 1) |
1048 ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
1049 } else {
1050 /* 0:5:6:5 */
1051 ((u32 *) (info->pseudo_palette))[regno] =
1052 ((red & 0xf800)) |
1053 ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
1054 }
1055 }
1056
1057 return err;
1058}
1059
1060/* It's common for several clients to have framebuffer open simultaneously.
1061 * e.g. both fbcon and X. Makes things interesting.
1062 * Assumes caller is holding info->lock (for open and release at least) */
1063static int ufx_ops_open(struct fb_info *info, int user)
1064{
1065 struct ufx_data *dev = info->par;
1066
1067 /* fbcon aggressively connects to first framebuffer it finds,
1068 * preventing other clients (X) from working properly. Usually
1069 * not what the user wants. Fail by default with option to enable. */
1070 if (user == 0 && !console)
1071 return -EBUSY;
1072
1073 /* If the USB device is gone, we don't accept new opens */
1074 if (dev->virtualized)
1075 return -ENODEV;
1076
1077 dev->fb_count++;
1078
1079 kref_get(&dev->kref);
1080
1081 if (fb_defio && (info->fbdefio == NULL)) {
1082 /* enable defio at last moment if not disabled by client */
1083
1084 struct fb_deferred_io *fbdefio;
1085
1086 fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
1087
1088 if (fbdefio) {
1089 fbdefio->delay = UFX_DEFIO_WRITE_DELAY;
1090 fbdefio->deferred_io = ufx_dpy_deferred_io;
1091 }
1092
1093 info->fbdefio = fbdefio;
1094 fb_deferred_io_init(info);
1095 }
1096
1097 pr_debug("open /dev/fb%d user=%d fb_info=%p count=%d",
1098 info->node, user, info, dev->fb_count);
1099
1100 return 0;
1101}
1102
1103/*
1104 * Called when all client interfaces to start transactions have been disabled,
1105 * and all references to our device instance (ufx_data) are released.
1106 * Every transaction must have a reference, so we know are fully spun down
1107 */
1108static void ufx_free(struct kref *kref)
1109{
1110 struct ufx_data *dev = container_of(kref, struct ufx_data, kref);
1111
1112 /* this function will wait for all in-flight urbs to complete */
1113 if (dev->urbs.count > 0)
1114 ufx_free_urb_list(dev);
1115
1116 pr_debug("freeing ufx_data %p", dev);
1117
1118 kfree(dev);
1119}
1120
1121static void ufx_release_urb_work(struct work_struct *work)
1122{
1123 struct urb_node *unode = container_of(work, struct urb_node,
1124 release_urb_work.work);
1125
1126 up(&unode->dev->urbs.limit_sem);
1127}
1128
1129static void ufx_free_framebuffer_work(struct work_struct *work)
1130{
1131 struct ufx_data *dev = container_of(work, struct ufx_data,
1132 free_framebuffer_work.work);
1133 struct fb_info *info = dev->info;
1134 int node = info->node;
1135
1136 unregister_framebuffer(info);
1137
1138 if (info->cmap.len != 0)
1139 fb_dealloc_cmap(&info->cmap);
1140 if (info->monspecs.modedb)
1141 fb_destroy_modedb(info->monspecs.modedb);
1142 if (info->screen_base)
1143 vfree(info->screen_base);
1144
1145 fb_destroy_modelist(&info->modelist);
1146
1147 dev->info = 0;
1148
1149 /* Assume info structure is freed after this point */
1150 framebuffer_release(info);
1151
1152 pr_debug("fb_info for /dev/fb%d has been freed", node);
1153
1154 /* ref taken in probe() as part of registering framebfufer */
1155 kref_put(&dev->kref, ufx_free);
1156}
1157
1158/*
1159 * Assumes caller is holding info->lock mutex (for open and release at least)
1160 */
1161static int ufx_ops_release(struct fb_info *info, int user)
1162{
1163 struct ufx_data *dev = info->par;
1164
1165 dev->fb_count--;
1166
1167 /* We can't free fb_info here - fbmem will touch it when we return */
1168 if (dev->virtualized && (dev->fb_count == 0))
1169 schedule_delayed_work(&dev->free_framebuffer_work, HZ);
1170
1171 if ((dev->fb_count == 0) && (info->fbdefio)) {
1172 fb_deferred_io_cleanup(info);
1173 kfree(info->fbdefio);
1174 info->fbdefio = NULL;
1175 info->fbops->fb_mmap = ufx_ops_mmap;
1176 }
1177
1178 pr_debug("released /dev/fb%d user=%d count=%d",
1179 info->node, user, dev->fb_count);
1180
1181 kref_put(&dev->kref, ufx_free);
1182
1183 return 0;
1184}
1185
1186/* Check whether a video mode is supported by the chip
1187 * We start from monitor's modes, so don't need to filter that here */
1188static int ufx_is_valid_mode(struct fb_videomode *mode,
1189 struct fb_info *info)
1190{
1191 if ((mode->xres * mode->yres) > (2048 * 1152)) {
1192 pr_debug("%dx%d too many pixels",
1193 mode->xres, mode->yres);
1194 return 0;
1195 }
1196
1197 if (mode->pixclock < 5000) {
1198 pr_debug("%dx%d %dps pixel clock too fast",
1199 mode->xres, mode->yres, mode->pixclock);
1200 return 0;
1201 }
1202
1203 pr_debug("%dx%d (pixclk %dps %dMHz) valid mode", mode->xres, mode->yres,
1204 mode->pixclock, (1000000 / mode->pixclock));
1205 return 1;
1206}
1207
1208static void ufx_var_color_format(struct fb_var_screeninfo *var)
1209{
1210 const struct fb_bitfield red = { 11, 5, 0 };
1211 const struct fb_bitfield green = { 5, 6, 0 };
1212 const struct fb_bitfield blue = { 0, 5, 0 };
1213
1214 var->bits_per_pixel = 16;
1215 var->red = red;
1216 var->green = green;
1217 var->blue = blue;
1218}
1219
1220static int ufx_ops_check_var(struct fb_var_screeninfo *var,
1221 struct fb_info *info)
1222{
1223 struct fb_videomode mode;
1224
1225 /* TODO: support dynamically changing framebuffer size */
1226 if ((var->xres * var->yres * 2) > info->fix.smem_len)
1227 return -EINVAL;
1228
1229 /* set device-specific elements of var unrelated to mode */
1230 ufx_var_color_format(var);
1231
1232 fb_var_to_videomode(&mode, var);
1233
1234 if (!ufx_is_valid_mode(&mode, info))
1235 return -EINVAL;
1236
1237 return 0;
1238}
1239
1240static int ufx_ops_set_par(struct fb_info *info)
1241{
1242 struct ufx_data *dev = info->par;
1243 int result;
1244 u16 *pix_framebuffer;
1245 int i;
1246
1247 pr_debug("set_par mode %dx%d", info->var.xres, info->var.yres);
1248 result = ufx_set_vid_mode(dev, &info->var);
1249
1250 if ((result == 0) && (dev->fb_count == 0)) {
1251 /* paint greenscreen */
1252 pix_framebuffer = (u16 *) info->screen_base;
1253 for (i = 0; i < info->fix.smem_len / 2; i++)
1254 pix_framebuffer[i] = 0x37e6;
1255
1256 ufx_handle_damage(dev, 0, 0, info->var.xres, info->var.yres);
1257 }
1258
1259 /* re-enable defio if previously disabled by damage tracking */
1260 if (info->fbdefio)
1261 info->fbdefio->delay = UFX_DEFIO_WRITE_DELAY;
1262
1263 return result;
1264}
1265
1266/* In order to come back from full DPMS off, we need to set the mode again */
1267static int ufx_ops_blank(int blank_mode, struct fb_info *info)
1268{
1269 struct ufx_data *dev = info->par;
1270 ufx_set_vid_mode(dev, &info->var);
1271 return 0;
1272}
1273
1274static struct fb_ops ufx_ops = {
1275 .owner = THIS_MODULE,
1276 .fb_read = fb_sys_read,
1277 .fb_write = ufx_ops_write,
1278 .fb_setcolreg = ufx_ops_setcolreg,
1279 .fb_fillrect = ufx_ops_fillrect,
1280 .fb_copyarea = ufx_ops_copyarea,
1281 .fb_imageblit = ufx_ops_imageblit,
1282 .fb_mmap = ufx_ops_mmap,
1283 .fb_ioctl = ufx_ops_ioctl,
1284 .fb_open = ufx_ops_open,
1285 .fb_release = ufx_ops_release,
1286 .fb_blank = ufx_ops_blank,
1287 .fb_check_var = ufx_ops_check_var,
1288 .fb_set_par = ufx_ops_set_par,
1289};
1290
1291/* Assumes &info->lock held by caller
1292 * Assumes no active clients have framebuffer open */
1293static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info)
1294{
1295 int retval = -ENOMEM;
1296 int old_len = info->fix.smem_len;
1297 int new_len;
1298 unsigned char *old_fb = info->screen_base;
1299 unsigned char *new_fb;
1300
1301 pr_debug("Reallocating framebuffer. Addresses will change!");
1302
1303 new_len = info->fix.line_length * info->var.yres;
1304
1305 if (PAGE_ALIGN(new_len) > old_len) {
1306 /*
1307 * Alloc system memory for virtual framebuffer
1308 */
1309 new_fb = vmalloc(new_len);
1310 if (!new_fb) {
1311 pr_err("Virtual framebuffer alloc failed");
1312 goto error;
1313 }
1314
1315 if (info->screen_base) {
1316 memcpy(new_fb, old_fb, old_len);
1317 vfree(info->screen_base);
1318 }
1319
1320 info->screen_base = new_fb;
1321 info->fix.smem_len = PAGE_ALIGN(new_len);
1322 info->fix.smem_start = (unsigned long) new_fb;
1323 info->flags = smscufx_info_flags;
1324 }
1325
1326 retval = 0;
1327
1328error:
1329 return retval;
1330}
1331
1332/* sets up I2C Controller for 100 Kbps, std. speed, 7-bit addr, master,
1333 * restart enabled, but no start byte, enable controller */
1334static int ufx_i2c_init(struct ufx_data *dev)
1335{
1336 u32 tmp;
1337
1338 /* disable the controller before it can be reprogrammed */
1339 int status = ufx_reg_write(dev, 0x106C, 0x00);
1340 check_warn_return(status, "failed to disable I2C");
1341
1342 /* Setup the clock count registers
1343 * (12+1) = 13 clks @ 2.5 MHz = 5.2 uS */
1344 status = ufx_reg_write(dev, 0x1018, 12);
1345 check_warn_return(status, "error writing 0x1018");
1346
1347 /* (6+8) = 14 clks @ 2.5 MHz = 5.6 uS */
1348 status = ufx_reg_write(dev, 0x1014, 6);
1349 check_warn_return(status, "error writing 0x1014");
1350
1351 status = ufx_reg_read(dev, 0x1000, &tmp);
1352 check_warn_return(status, "error reading 0x1000");
1353
1354 /* set speed to std mode */
1355 tmp &= ~(0x06);
1356 tmp |= 0x02;
1357
1358 /* 7-bit (not 10-bit) addressing */
1359 tmp &= ~(0x10);
1360
1361 /* enable restart conditions and master mode */
1362 tmp |= 0x21;
1363
1364 status = ufx_reg_write(dev, 0x1000, tmp);
1365 check_warn_return(status, "error writing 0x1000");
1366
1367 /* Set normal tx using target address 0 */
1368 status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0xC00, 0x000);
1369 check_warn_return(status, "error setting TX mode bits in 0x1004");
1370
1371 /* Enable the controller */
1372 status = ufx_reg_write(dev, 0x106C, 0x01);
1373 check_warn_return(status, "failed to enable I2C");
1374
1375 return 0;
1376}
1377
1378/* sets the I2C port mux and target address */
1379static int ufx_i2c_configure(struct ufx_data *dev)
1380{
1381 int status = ufx_reg_write(dev, 0x106C, 0x00);
1382 check_warn_return(status, "failed to disable I2C");
1383
1384 status = ufx_reg_write(dev, 0x3010, 0x00000000);
1385 check_warn_return(status, "failed to write 0x3010");
1386
1387 /* A0h is std for any EDID, right shifted by one */
1388 status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0x3FF, (0xA0 >> 1));
1389 check_warn_return(status, "failed to set TAR bits in 0x1004");
1390
1391 status = ufx_reg_write(dev, 0x106C, 0x01);
1392 check_warn_return(status, "failed to enable I2C");
1393
1394 return 0;
1395}
1396
1397/* wait for BUSY to clear, with a timeout of 50ms with 10ms sleeps. if no
1398 * monitor is connected, there is no error except for timeout */
1399static int ufx_i2c_wait_busy(struct ufx_data *dev)
1400{
1401 u32 tmp;
1402 int i, status;
1403
1404 for (i = 0; i < 15; i++) {
1405 status = ufx_reg_read(dev, 0x1100, &tmp);
1406 check_warn_return(status, "0x1100 read failed");
1407
1408 /* if BUSY is clear, check for error */
1409 if ((tmp & 0x80000000) == 0) {
1410 if (tmp & 0x20000000) {
1411 pr_warn("I2C read failed, 0x1100=0x%08x", tmp);
1412 return -EIO;
1413 }
1414
1415 return 0;
1416 }
1417
1418 /* perform the first 10 retries without delay */
1419 if (i >= 10)
1420 msleep(10);
1421 }
1422
1423 pr_warn("I2C access timed out, resetting I2C hardware");
1424 status = ufx_reg_write(dev, 0x1100, 0x40000000);
1425 check_warn_return(status, "0x1100 write failed");
1426
1427 return -ETIMEDOUT;
1428}
1429
1430/* reads a 128-byte EDID block from the currently selected port and TAR */
1431static int ufx_read_edid(struct ufx_data *dev, u8 *edid, int edid_len)
1432{
1433 int i, j, status;
1434 u32 *edid_u32 = (u32 *)edid;
1435
1436 BUG_ON(edid_len != EDID_LENGTH);
1437
1438 status = ufx_i2c_configure(dev);
1439 if (status < 0) {
1440 pr_err("ufx_i2c_configure failed");
1441 return status;
1442 }
1443
1444 memset(edid, 0xff, EDID_LENGTH);
1445
1446 /* Read the 128-byte EDID as 2 bursts of 64 bytes */
1447 for (i = 0; i < 2; i++) {
1448 u32 temp = 0x28070000 | (63 << 20) | (((u32)(i * 64)) << 8);
1449 status = ufx_reg_write(dev, 0x1100, temp);
1450 check_warn_return(status, "Failed to write 0x1100");
1451
1452 temp |= 0x80000000;
1453 status = ufx_reg_write(dev, 0x1100, temp);
1454 check_warn_return(status, "Failed to write 0x1100");
1455
1456 status = ufx_i2c_wait_busy(dev);
1457 check_warn_return(status, "Timeout waiting for I2C BUSY to clear");
1458
1459 for (j = 0; j < 16; j++) {
1460 u32 data_reg_addr = 0x1110 + (j * 4);
1461 status = ufx_reg_read(dev, data_reg_addr, edid_u32++);
1462 check_warn_return(status, "Error reading i2c data");
1463 }
1464 }
1465
1466 /* all FF's in the first 16 bytes indicates nothing is connected */
1467 for (i = 0; i < 16; i++) {
1468 if (edid[i] != 0xFF) {
1469 pr_debug("edid data read succesfully");
1470 return EDID_LENGTH;
1471 }
1472 }
1473
1474 pr_warn("edid data contains all 0xff");
1475 return -ETIMEDOUT;
1476}
1477
1478/* 1) use sw default
1479 * 2) Parse into various fb_info structs
1480 * 3) Allocate virtual framebuffer memory to back highest res mode
1481 *
1482 * Parses EDID into three places used by various parts of fbdev:
1483 * fb_var_screeninfo contains the timing of the monitor's preferred mode
1484 * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
1485 * fb_info.modelist is a linked list of all monitor & VESA modes which work
1486 *
1487 * If EDID is not readable/valid, then modelist is all VESA modes,
1488 * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
1489 * Returns 0 if successful */
1490static int ufx_setup_modes(struct ufx_data *dev, struct fb_info *info,
1491 char *default_edid, size_t default_edid_size)
1492{
1493 const struct fb_videomode *default_vmode = NULL;
1494 u8 *edid;
1495 int i, result = 0, tries = 3;
1496
1497 if (info->dev) /* only use mutex if info has been registered */
1498 mutex_lock(&info->lock);
1499
1500 edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
1501 if (!edid) {
1502 result = -ENOMEM;
1503 goto error;
1504 }
1505
1506 fb_destroy_modelist(&info->modelist);
1507 memset(&info->monspecs, 0, sizeof(info->monspecs));
1508
1509 /* Try to (re)read EDID from hardware first
1510 * EDID data may return, but not parse as valid
1511 * Try again a few times, in case of e.g. analog cable noise */
1512 while (tries--) {
1513 i = ufx_read_edid(dev, edid, EDID_LENGTH);
1514
1515 if (i >= EDID_LENGTH)
1516 fb_edid_to_monspecs(edid, &info->monspecs);
1517
1518 if (info->monspecs.modedb_len > 0) {
1519 dev->edid = edid;
1520 dev->edid_size = i;
1521 break;
1522 }
1523 }
1524
1525 /* If that fails, use a previously returned EDID if available */
1526 if (info->monspecs.modedb_len == 0) {
1527 pr_err("Unable to get valid EDID from device/display\n");
1528
1529 if (dev->edid) {
1530 fb_edid_to_monspecs(dev->edid, &info->monspecs);
1531 if (info->monspecs.modedb_len > 0)
1532 pr_err("Using previously queried EDID\n");
1533 }
1534 }
1535
1536 /* If that fails, use the default EDID we were handed */
1537 if (info->monspecs.modedb_len == 0) {
1538 if (default_edid_size >= EDID_LENGTH) {
1539 fb_edid_to_monspecs(default_edid, &info->monspecs);
1540 if (info->monspecs.modedb_len > 0) {
1541 memcpy(edid, default_edid, default_edid_size);
1542 dev->edid = edid;
1543 dev->edid_size = default_edid_size;
1544 pr_err("Using default/backup EDID\n");
1545 }
1546 }
1547 }
1548
1549 /* If we've got modes, let's pick a best default mode */
1550 if (info->monspecs.modedb_len > 0) {
1551
1552 for (i = 0; i < info->monspecs.modedb_len; i++) {
1553 if (ufx_is_valid_mode(&info->monspecs.modedb[i], info))
1554 fb_add_videomode(&info->monspecs.modedb[i],
1555 &info->modelist);
1556 else /* if we've removed top/best mode */
1557 info->monspecs.misc &= ~FB_MISC_1ST_DETAIL;
1558 }
1559
1560 default_vmode = fb_find_best_display(&info->monspecs,
1561 &info->modelist);
1562 }
1563
1564 /* If everything else has failed, fall back to safe default mode */
1565 if (default_vmode == NULL) {
1566
1567 struct fb_videomode fb_vmode = {0};
1568
1569 /* Add the standard VESA modes to our modelist
1570 * Since we don't have EDID, there may be modes that
1571 * overspec monitor and/or are incorrect aspect ratio, etc.
1572 * But at least the user has a chance to choose
1573 */
1574 for (i = 0; i < VESA_MODEDB_SIZE; i++) {
1575 if (ufx_is_valid_mode((struct fb_videomode *)
1576 &vesa_modes[i], info))
1577 fb_add_videomode(&vesa_modes[i],
1578 &info->modelist);
1579 }
1580
1581 /* default to resolution safe for projectors
1582 * (since they are most common case without EDID)
1583 */
1584 fb_vmode.xres = 800;
1585 fb_vmode.yres = 600;
1586 fb_vmode.refresh = 60;
1587 default_vmode = fb_find_nearest_mode(&fb_vmode,
1588 &info->modelist);
1589 }
1590
1591 /* If we have good mode and no active clients */
1592 if ((default_vmode != NULL) && (dev->fb_count == 0)) {
1593
1594 fb_videomode_to_var(&info->var, default_vmode);
1595 ufx_var_color_format(&info->var);
1596
1597 /* with mode size info, we can now alloc our framebuffer */
1598 memcpy(&info->fix, &ufx_fix, sizeof(ufx_fix));
1599 info->fix.line_length = info->var.xres *
1600 (info->var.bits_per_pixel / 8);
1601
1602 result = ufx_realloc_framebuffer(dev, info);
1603
1604 } else
1605 result = -EINVAL;
1606
1607error:
1608 if (edid && (dev->edid != edid))
1609 kfree(edid);
1610
1611 if (info->dev)
1612 mutex_unlock(&info->lock);
1613
1614 return result;
1615}
1616
1617static int ufx_usb_probe(struct usb_interface *interface,
1618 const struct usb_device_id *id)
1619{
1620 struct usb_device *usbdev;
1621 struct ufx_data *dev;
1622 struct fb_info *info = 0;
1623 int retval = -ENOMEM;
1624 u32 id_rev, fpga_rev;
1625
1626 /* usb initialization */
1627 usbdev = interface_to_usbdev(interface);
1628 BUG_ON(!usbdev);
1629
1630 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1631 if (dev == NULL) {
1632 dev_err(&usbdev->dev, "ufx_usb_probe: failed alloc of dev struct\n");
1633 goto error;
1634 }
1635
1636 /* we need to wait for both usb and fbdev to spin down on disconnect */
1637 kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
1638 kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
1639
1640 dev->udev = usbdev;
1641 dev->gdev = &usbdev->dev; /* our generic struct device * */
1642 usb_set_intfdata(interface, dev);
1643
1644 dev_dbg(dev->gdev, "%s %s - serial #%s\n",
1645 usbdev->manufacturer, usbdev->product, usbdev->serial);
1646 dev_dbg(dev->gdev, "vid_%04x&pid_%04x&rev_%04x driver's ufx_data struct at %p\n",
1647 usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
1648 usbdev->descriptor.bcdDevice, dev);
1649 dev_dbg(dev->gdev, "console enable=%d\n", console);
1650 dev_dbg(dev->gdev, "fb_defio enable=%d\n", fb_defio);
1651
1652 if (!ufx_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
1653 retval = -ENOMEM;
1654 dev_err(dev->gdev, "ufx_alloc_urb_list failed\n");
1655 goto error;
1656 }
1657
1658 /* We don't register a new USB class. Our client interface is fbdev */
1659
1660 /* allocates framebuffer driver structure, not framebuffer memory */
1661 info = framebuffer_alloc(0, &usbdev->dev);
1662 if (!info) {
1663 retval = -ENOMEM;
1664 dev_err(dev->gdev, "framebuffer_alloc failed\n");
1665 goto error;
1666 }
1667
1668 dev->info = info;
1669 info->par = dev;
1670 info->pseudo_palette = dev->pseudo_palette;
1671 info->fbops = &ufx_ops;
1672
1673 retval = fb_alloc_cmap(&info->cmap, 256, 0);
1674 if (retval < 0) {
1675 dev_err(dev->gdev, "fb_alloc_cmap failed %x\n", retval);
1676 goto error;
1677 }
1678
1679 INIT_DELAYED_WORK(&dev->free_framebuffer_work,
1680 ufx_free_framebuffer_work);
1681
1682 INIT_LIST_HEAD(&info->modelist);
1683
1684 retval = ufx_reg_read(dev, 0x3000, &id_rev);
1685 check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval);
1686 dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev);
1687
1688 retval = ufx_reg_read(dev, 0x3004, &fpga_rev);
1689 check_warn_goto_error(retval, "error %d reading 0x3004 register from device", retval);
1690 dev_dbg(dev->gdev, "FPGA_REV register value 0x%08x", fpga_rev);
1691
1692 dev_dbg(dev->gdev, "resetting device");
1693 retval = ufx_lite_reset(dev);
1694 check_warn_goto_error(retval, "error %d resetting device", retval);
1695
1696 dev_dbg(dev->gdev, "configuring system clock");
1697 retval = ufx_config_sys_clk(dev);
1698 check_warn_goto_error(retval, "error %d configuring system clock", retval);
1699
1700 dev_dbg(dev->gdev, "configuring DDR2 controller");
1701 retval = ufx_config_ddr2(dev);
1702 check_warn_goto_error(retval, "error %d initialising DDR2 controller", retval);
1703
1704 dev_dbg(dev->gdev, "configuring I2C controller");
1705 retval = ufx_i2c_init(dev);
1706 check_warn_goto_error(retval, "error %d initialising I2C controller", retval);
1707
1708 dev_dbg(dev->gdev, "selecting display mode");
1709 retval = ufx_setup_modes(dev, info, NULL, 0);
1710 check_warn_goto_error(retval, "unable to find common mode for display and adapter");
1711
1712 retval = ufx_reg_set_bits(dev, 0x4000, 0x00000001);
1713 check_warn_goto_error(retval, "error %d enabling graphics engine", retval);
1714
1715 /* ready to begin using device */
1716 atomic_set(&dev->usb_active, 1);
1717
1718 dev_dbg(dev->gdev, "checking var");
1719 retval = ufx_ops_check_var(&info->var, info);
1720 check_warn_goto_error(retval, "error %d ufx_ops_check_var", retval);
1721
1722 dev_dbg(dev->gdev, "setting par");
1723 retval = ufx_ops_set_par(info);
1724 check_warn_goto_error(retval, "error %d ufx_ops_set_par", retval);
1725
1726 dev_dbg(dev->gdev, "registering framebuffer");
1727 retval = register_framebuffer(info);
1728 check_warn_goto_error(retval, "error %d register_framebuffer", retval);
1729
1730 dev_info(dev->gdev, "SMSC UDX USB device /dev/fb%d attached. %dx%d resolution."
1731 " Using %dK framebuffer memory\n", info->node,
1732 info->var.xres, info->var.yres, info->fix.smem_len >> 10);
1733
1734 return 0;
1735
1736error:
1737 if (dev) {
1738 if (info) {
1739 if (info->cmap.len != 0)
1740 fb_dealloc_cmap(&info->cmap);
1741 if (info->monspecs.modedb)
1742 fb_destroy_modedb(info->monspecs.modedb);
1743 if (info->screen_base)
1744 vfree(info->screen_base);
1745
1746 fb_destroy_modelist(&info->modelist);
1747
1748 framebuffer_release(info);
1749 }
1750
1751 kref_put(&dev->kref, ufx_free); /* ref for framebuffer */
1752 kref_put(&dev->kref, ufx_free); /* last ref from kref_init */
1753
1754 /* dev has been deallocated. Do not dereference */
1755 }
1756
1757 return retval;
1758}
1759
1760static void ufx_usb_disconnect(struct usb_interface *interface)
1761{
1762 struct ufx_data *dev;
1763 struct fb_info *info;
1764
1765 dev = usb_get_intfdata(interface);
1766 info = dev->info;
1767
1768 pr_debug("USB disconnect starting\n");
1769
1770 /* we virtualize until all fb clients release. Then we free */
1771 dev->virtualized = true;
1772
1773 /* When non-active we'll update virtual framebuffer, but no new urbs */
1774 atomic_set(&dev->usb_active, 0);
1775
1776 usb_set_intfdata(interface, NULL);
1777
1778 /* if clients still have us open, will be freed on last close */
1779 if (dev->fb_count == 0)
1780 schedule_delayed_work(&dev->free_framebuffer_work, 0);
1781
1782 /* release reference taken by kref_init in probe() */
1783 kref_put(&dev->kref, ufx_free);
1784
1785 /* consider ufx_data freed */
1786}
1787
1788static struct usb_driver ufx_driver = {
1789 .name = "smscufx",
1790 .probe = ufx_usb_probe,
1791 .disconnect = ufx_usb_disconnect,
1792 .id_table = id_table,
1793};
1794
1795static int __init ufx_module_init(void)
1796{
1797 int res;
1798
1799 res = usb_register(&ufx_driver);
1800 if (res)
1801 err("usb_register failed. Error number %d", res);
1802
1803 return res;
1804}
1805
1806static void __exit ufx_module_exit(void)
1807{
1808 usb_deregister(&ufx_driver);
1809}
1810
1811module_init(ufx_module_init);
1812module_exit(ufx_module_exit);
1813
1814static void ufx_urb_completion(struct urb *urb)
1815{
1816 struct urb_node *unode = urb->context;
1817 struct ufx_data *dev = unode->dev;
1818 unsigned long flags;
1819
1820 /* sync/async unlink faults aren't errors */
1821 if (urb->status) {
1822 if (!(urb->status == -ENOENT ||
1823 urb->status == -ECONNRESET ||
1824 urb->status == -ESHUTDOWN)) {
1825 pr_err("%s - nonzero write bulk status received: %d\n",
1826 __func__, urb->status);
1827 atomic_set(&dev->lost_pixels, 1);
1828 }
1829 }
1830
1831 urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */
1832
1833 spin_lock_irqsave(&dev->urbs.lock, flags);
1834 list_add_tail(&unode->entry, &dev->urbs.list);
1835 dev->urbs.available++;
1836 spin_unlock_irqrestore(&dev->urbs.lock, flags);
1837
1838 /* When using fb_defio, we deadlock if up() is called
1839 * while another is waiting. So queue to another process */
1840 if (fb_defio)
1841 schedule_delayed_work(&unode->release_urb_work, 0);
1842 else
1843 up(&dev->urbs.limit_sem);
1844}
1845
1846static void ufx_free_urb_list(struct ufx_data *dev)
1847{
1848 int count = dev->urbs.count;
1849 struct list_head *node;
1850 struct urb_node *unode;
1851 struct urb *urb;
1852 int ret;
1853 unsigned long flags;
1854
1855 pr_debug("Waiting for completes and freeing all render urbs\n");
1856
1857 /* keep waiting and freeing, until we've got 'em all */
1858 while (count--) {
1859 /* Getting interrupted means a leak, but ok at shutdown*/
1860 ret = down_interruptible(&dev->urbs.limit_sem);
1861 if (ret)
1862 break;
1863
1864 spin_lock_irqsave(&dev->urbs.lock, flags);
1865
1866 node = dev->urbs.list.next; /* have reserved one with sem */
1867 list_del_init(node);
1868
1869 spin_unlock_irqrestore(&dev->urbs.lock, flags);
1870
1871 unode = list_entry(node, struct urb_node, entry);
1872 urb = unode->urb;
1873
1874 /* Free each separately allocated piece */
1875 usb_free_coherent(urb->dev, dev->urbs.size,
1876 urb->transfer_buffer, urb->transfer_dma);
1877 usb_free_urb(urb);
1878 kfree(node);
1879 }
1880}
1881
1882static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size)
1883{
1884 int i = 0;
1885 struct urb *urb;
1886 struct urb_node *unode;
1887 char *buf;
1888
1889 spin_lock_init(&dev->urbs.lock);
1890
1891 dev->urbs.size = size;
1892 INIT_LIST_HEAD(&dev->urbs.list);
1893
1894 while (i < count) {
1895 unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL);
1896 if (!unode)
1897 break;
1898 unode->dev = dev;
1899
1900 INIT_DELAYED_WORK(&unode->release_urb_work,
1901 ufx_release_urb_work);
1902
1903 urb = usb_alloc_urb(0, GFP_KERNEL);
1904 if (!urb) {
1905 kfree(unode);
1906 break;
1907 }
1908 unode->urb = urb;
1909
1910 buf = usb_alloc_coherent(dev->udev, size, GFP_KERNEL,
1911 &urb->transfer_dma);
1912 if (!buf) {
1913 kfree(unode);
1914 usb_free_urb(urb);
1915 break;
1916 }
1917
1918 /* urb->transfer_buffer_length set to actual before submit */
1919 usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1),
1920 buf, size, ufx_urb_completion, unode);
1921 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1922
1923 list_add_tail(&unode->entry, &dev->urbs.list);
1924
1925 i++;
1926 }
1927
1928 sema_init(&dev->urbs.limit_sem, i);
1929 dev->urbs.count = i;
1930 dev->urbs.available = i;
1931
1932 pr_debug("allocated %d %d byte urbs\n", i, (int) size);
1933
1934 return i;
1935}
1936
1937static struct urb *ufx_get_urb(struct ufx_data *dev)
1938{
1939 int ret = 0;
1940 struct list_head *entry;
1941 struct urb_node *unode;
1942 struct urb *urb = NULL;
1943 unsigned long flags;
1944
1945 /* Wait for an in-flight buffer to complete and get re-queued */
1946 ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
1947 if (ret) {
1948 atomic_set(&dev->lost_pixels, 1);
1949 pr_warn("wait for urb interrupted: %x available: %d\n",
1950 ret, dev->urbs.available);
1951 goto error;
1952 }
1953
1954 spin_lock_irqsave(&dev->urbs.lock, flags);
1955
1956 BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */
1957 entry = dev->urbs.list.next;
1958 list_del_init(entry);
1959 dev->urbs.available--;
1960
1961 spin_unlock_irqrestore(&dev->urbs.lock, flags);
1962
1963 unode = list_entry(entry, struct urb_node, entry);
1964 urb = unode->urb;
1965
1966error:
1967 return urb;
1968}
1969
1970static int ufx_submit_urb(struct ufx_data *dev, struct urb *urb, size_t len)
1971{
1972 int ret;
1973
1974 BUG_ON(len > dev->urbs.size);
1975
1976 urb->transfer_buffer_length = len; /* set to actual payload len */
1977 ret = usb_submit_urb(urb, GFP_KERNEL);
1978 if (ret) {
1979 ufx_urb_completion(urb); /* because no one else will */
1980 atomic_set(&dev->lost_pixels, 1);
1981 pr_err("usb_submit_urb error %x\n", ret);
1982 }
1983 return ret;
1984}
1985
1986module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1987MODULE_PARM_DESC(console, "Allow fbcon to be used on this display");
1988
1989module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1990MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support");
1991
1992MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>");
1993MODULE_DESCRIPTION("SMSC UFX kernel framebuffer driver");
1994MODULE_LICENSE("GPL");
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
index cd1c4dcef8f..8e4a446b5ed 100644
--- a/drivers/video/tmiofb.c
+++ b/drivers/video/tmiofb.c
@@ -744,7 +744,7 @@ static int __devinit tmiofb_probe(struct platform_device *dev)
744 goto err_ioremap_vram; 744 goto err_ioremap_vram;
745 } 745 }
746 746
747 retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED, 747 retval = request_irq(irq, &tmiofb_irq, 0,
748 dev_name(&dev->dev), info); 748 dev_name(&dev->dev), info);
749 749
750 if (retval) 750 if (retval)
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index c6c77562839..34cf019bba4 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -987,8 +987,8 @@ static int tridentfb_pan_display(struct fb_var_screeninfo *var,
987 unsigned int offset; 987 unsigned int offset;
988 988
989 debug("enter\n"); 989 debug("enter\n");
990 offset = (var->xoffset + (var->yoffset * var->xres_virtual)) 990 offset = (var->xoffset + (var->yoffset * info->var.xres_virtual))
991 * var->bits_per_pixel / 32; 991 * info->var.bits_per_pixel / 32;
992 set_screen_start(par, offset); 992 set_screen_start(par, offset);
993 debug("exit\n"); 993 debug("exit\n");
994 return 0; 994 return 0;
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index 087fc9960bb..3473e75ce78 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -48,20 +48,30 @@ static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
48 FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR; 48 FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
49 49
50/* 50/*
51 * There are many DisplayLink-based products, all with unique PIDs. We are able 51 * There are many DisplayLink-based graphics products, all with unique PIDs.
52 * to support all volume ones (circa 2009) with a single driver, so we match 52 * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff)
53 * globally on VID. TODO: Probe() needs to detect when we might be running 53 * We also require a match on SubClass (0x00) and Protocol (0x00),
54 * "future" chips, and bail on those, so a compatible driver can match. 54 * which is compatible with all known USB 2.0 era graphics chips and firmware,
55 * but allows DisplayLink to increment those for any future incompatible chips
55 */ 56 */
56static struct usb_device_id id_table[] = { 57static struct usb_device_id id_table[] = {
57 {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,}, 58 {.idVendor = 0x17e9,
59 .bInterfaceClass = 0xff,
60 .bInterfaceSubClass = 0x00,
61 .bInterfaceProtocol = 0x00,
62 .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
63 USB_DEVICE_ID_MATCH_INT_CLASS |
64 USB_DEVICE_ID_MATCH_INT_SUBCLASS |
65 USB_DEVICE_ID_MATCH_INT_PROTOCOL,
66 },
58 {}, 67 {},
59}; 68};
60MODULE_DEVICE_TABLE(usb, id_table); 69MODULE_DEVICE_TABLE(usb, id_table);
61 70
62/* module options */ 71/* module options */
63static int console; /* Optionally allow fbcon to consume first framebuffer */ 72static int console = 1; /* Allow fbcon to open framebuffer */
64static int fb_defio; /* Optionally enable experimental fb_defio mmap support */ 73static int fb_defio = 1; /* Detect mmap writes using page faults */
74static int shadow = 1; /* Optionally disable shadow framebuffer */
65 75
66/* dlfb keeps a list of urbs for efficient bulk transfers */ 76/* dlfb keeps a list of urbs for efficient bulk transfers */
67static void dlfb_urb_completion(struct urb *urb); 77static void dlfb_urb_completion(struct urb *urb);
@@ -94,17 +104,39 @@ static char *dlfb_vidreg_unlock(char *buf)
94} 104}
95 105
96/* 106/*
97 * On/Off for driving the DisplayLink framebuffer to the display 107 * Map FB_BLANK_* to DisplayLink register
98 * 0x00 H and V sync on 108 * DLReg FB_BLANK_*
99 * 0x01 H and V sync off (screen blank but powered) 109 * ----- -----------------------------
100 * 0x07 DPMS powerdown (requires modeset to come back) 110 * 0x00 FB_BLANK_UNBLANK (0)
111 * 0x01 FB_BLANK (1)
112 * 0x03 FB_BLANK_VSYNC_SUSPEND (2)
113 * 0x05 FB_BLANK_HSYNC_SUSPEND (3)
114 * 0x07 FB_BLANK_POWERDOWN (4) Note: requires modeset to come back
101 */ 115 */
102static char *dlfb_enable_hvsync(char *buf, bool enable) 116static char *dlfb_blanking(char *buf, int fb_blank)
103{ 117{
104 if (enable) 118 u8 reg;
105 return dlfb_set_register(buf, 0x1F, 0x00); 119
106 else 120 switch (fb_blank) {
107 return dlfb_set_register(buf, 0x1F, 0x07); 121 case FB_BLANK_POWERDOWN:
122 reg = 0x07;
123 break;
124 case FB_BLANK_HSYNC_SUSPEND:
125 reg = 0x05;
126 break;
127 case FB_BLANK_VSYNC_SUSPEND:
128 reg = 0x03;
129 break;
130 case FB_BLANK_NORMAL:
131 reg = 0x01;
132 break;
133 default:
134 reg = 0x00;
135 }
136
137 buf = dlfb_set_register(buf, 0x1F, reg);
138
139 return buf;
108} 140}
109 141
110static char *dlfb_set_color_depth(char *buf, u8 selection) 142static char *dlfb_set_color_depth(char *buf, u8 selection)
@@ -272,13 +304,15 @@ static int dlfb_set_video_mode(struct dlfb_data *dev,
272 wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len); 304 wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len);
273 305
274 wrptr = dlfb_set_vid_cmds(wrptr, var); 306 wrptr = dlfb_set_vid_cmds(wrptr, var);
275 wrptr = dlfb_enable_hvsync(wrptr, true); 307 wrptr = dlfb_blanking(wrptr, FB_BLANK_UNBLANK);
276 wrptr = dlfb_vidreg_unlock(wrptr); 308 wrptr = dlfb_vidreg_unlock(wrptr);
277 309
278 writesize = wrptr - buf; 310 writesize = wrptr - buf;
279 311
280 retval = dlfb_submit_urb(dev, urb, writesize); 312 retval = dlfb_submit_urb(dev, urb, writesize);
281 313
314 dev->blank_mode = FB_BLANK_UNBLANK;
315
282 return retval; 316 return retval;
283} 317}
284 318
@@ -752,14 +786,13 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
752{ 786{
753 787
754 struct dlfb_data *dev = info->par; 788 struct dlfb_data *dev = info->par;
755 struct dloarea *area = NULL;
756 789
757 if (!atomic_read(&dev->usb_active)) 790 if (!atomic_read(&dev->usb_active))
758 return 0; 791 return 0;
759 792
760 /* TODO: Update X server to get this from sysfs instead */ 793 /* TODO: Update X server to get this from sysfs instead */
761 if (cmd == DLFB_IOCTL_RETURN_EDID) { 794 if (cmd == DLFB_IOCTL_RETURN_EDID) {
762 char *edid = (char *)arg; 795 void __user *edid = (void __user *)arg;
763 if (copy_to_user(edid, dev->edid, dev->edid_size)) 796 if (copy_to_user(edid, dev->edid, dev->edid_size))
764 return -EFAULT; 797 return -EFAULT;
765 return 0; 798 return 0;
@@ -767,6 +800,11 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
767 800
768 /* TODO: Help propose a standard fb.h ioctl to report mmap damage */ 801 /* TODO: Help propose a standard fb.h ioctl to report mmap damage */
769 if (cmd == DLFB_IOCTL_REPORT_DAMAGE) { 802 if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
803 struct dloarea area;
804
805 if (copy_from_user(&area, (void __user *)arg,
806 sizeof(struct dloarea)))
807 return -EFAULT;
770 808
771 /* 809 /*
772 * If we have a damage-aware client, turn fb_defio "off" 810 * If we have a damage-aware client, turn fb_defio "off"
@@ -778,21 +816,19 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
778 if (info->fbdefio) 816 if (info->fbdefio)
779 info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE; 817 info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE;
780 818
781 area = (struct dloarea *)arg; 819 if (area.x < 0)
820 area.x = 0;
782 821
783 if (area->x < 0) 822 if (area.x > info->var.xres)
784 area->x = 0; 823 area.x = info->var.xres;
785 824
786 if (area->x > info->var.xres) 825 if (area.y < 0)
787 area->x = info->var.xres; 826 area.y = 0;
788 827
789 if (area->y < 0) 828 if (area.y > info->var.yres)
790 area->y = 0; 829 area.y = info->var.yres;
791 830
792 if (area->y > info->var.yres) 831 dlfb_handle_damage(dev, area.x, area.y, area.w, area.h,
793 area->y = info->var.yres;
794
795 dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
796 info->screen_base); 832 info->screen_base);
797 } 833 }
798 834
@@ -840,7 +876,7 @@ static int dlfb_ops_open(struct fb_info *info, int user)
840 * preventing other clients (X) from working properly. Usually 876 * preventing other clients (X) from working properly. Usually
841 * not what the user wants. Fail by default with option to enable. 877 * not what the user wants. Fail by default with option to enable.
842 */ 878 */
843 if ((user == 0) & (!console)) 879 if ((user == 0) && (!console))
844 return -EBUSY; 880 return -EBUSY;
845 881
846 /* If the USB device is gone, we don't accept new opens */ 882 /* If the USB device is gone, we don't accept new opens */
@@ -1039,32 +1075,57 @@ static int dlfb_ops_set_par(struct fb_info *info)
1039 return result; 1075 return result;
1040} 1076}
1041 1077
1078/* To fonzi the jukebox (e.g. make blanking changes take effect) */
1079static char *dlfb_dummy_render(char *buf)
1080{
1081 *buf++ = 0xAF;
1082 *buf++ = 0x6A; /* copy */
1083 *buf++ = 0x00; /* from address*/
1084 *buf++ = 0x00;
1085 *buf++ = 0x00;
1086 *buf++ = 0x01; /* one pixel */
1087 *buf++ = 0x00; /* to address */
1088 *buf++ = 0x00;
1089 *buf++ = 0x00;
1090 return buf;
1091}
1092
1042/* 1093/*
1043 * In order to come back from full DPMS off, we need to set the mode again 1094 * In order to come back from full DPMS off, we need to set the mode again
1044 */ 1095 */
1045static int dlfb_ops_blank(int blank_mode, struct fb_info *info) 1096static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
1046{ 1097{
1047 struct dlfb_data *dev = info->par; 1098 struct dlfb_data *dev = info->par;
1099 char *bufptr;
1100 struct urb *urb;
1048 1101
1049 if (blank_mode != FB_BLANK_UNBLANK) { 1102 pr_info("/dev/fb%d FB_BLANK mode %d --> %d\n",
1050 char *bufptr; 1103 info->node, dev->blank_mode, blank_mode);
1051 struct urb *urb;
1052
1053 urb = dlfb_get_urb(dev);
1054 if (!urb)
1055 return 0;
1056 1104
1057 bufptr = (char *) urb->transfer_buffer; 1105 if ((dev->blank_mode == FB_BLANK_POWERDOWN) &&
1058 bufptr = dlfb_vidreg_lock(bufptr); 1106 (blank_mode != FB_BLANK_POWERDOWN)) {
1059 bufptr = dlfb_enable_hvsync(bufptr, false);
1060 bufptr = dlfb_vidreg_unlock(bufptr);
1061 1107
1062 dlfb_submit_urb(dev, urb, bufptr - 1108 /* returning from powerdown requires a fresh modeset */
1063 (char *) urb->transfer_buffer);
1064 } else {
1065 dlfb_set_video_mode(dev, &info->var); 1109 dlfb_set_video_mode(dev, &info->var);
1066 } 1110 }
1067 1111
1112 urb = dlfb_get_urb(dev);
1113 if (!urb)
1114 return 0;
1115
1116 bufptr = (char *) urb->transfer_buffer;
1117 bufptr = dlfb_vidreg_lock(bufptr);
1118 bufptr = dlfb_blanking(bufptr, blank_mode);
1119 bufptr = dlfb_vidreg_unlock(bufptr);
1120
1121 /* seems like a render op is needed to have blank change take effect */
1122 bufptr = dlfb_dummy_render(bufptr);
1123
1124 dlfb_submit_urb(dev, urb, bufptr -
1125 (char *) urb->transfer_buffer);
1126
1127 dev->blank_mode = blank_mode;
1128
1068 return 0; 1129 return 0;
1069} 1130}
1070 1131
@@ -1097,7 +1158,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
1097 int new_len; 1158 int new_len;
1098 unsigned char *old_fb = info->screen_base; 1159 unsigned char *old_fb = info->screen_base;
1099 unsigned char *new_fb; 1160 unsigned char *new_fb;
1100 unsigned char *new_back; 1161 unsigned char *new_back = 0;
1101 1162
1102 pr_warn("Reallocating framebuffer. Addresses will change!\n"); 1163 pr_warn("Reallocating framebuffer. Addresses will change!\n");
1103 1164
@@ -1129,7 +1190,8 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
1129 * But with imperfect damage info we may send pixels over USB 1190 * But with imperfect damage info we may send pixels over USB
1130 * that were, in fact, unchanged - wasting limited USB bandwidth 1191 * that were, in fact, unchanged - wasting limited USB bandwidth
1131 */ 1192 */
1132 new_back = vzalloc(new_len); 1193 if (shadow)
1194 new_back = vzalloc(new_len);
1133 if (!new_back) 1195 if (!new_back)
1134 pr_info("No shadow/backing buffer allocated\n"); 1196 pr_info("No shadow/backing buffer allocated\n");
1135 else { 1197 else {
@@ -1430,21 +1492,30 @@ static int dlfb_select_std_channel(struct dlfb_data *dev)
1430} 1492}
1431 1493
1432static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, 1494static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
1433 struct usb_device *usbdev) 1495 struct usb_interface *interface)
1434{ 1496{
1435 char *desc; 1497 char *desc;
1436 char *buf; 1498 char *buf;
1437 char *desc_end; 1499 char *desc_end;
1438 1500
1439 u8 total_len = 0; 1501 int total_len = 0;
1440 1502
1441 buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); 1503 buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL);
1442 if (!buf) 1504 if (!buf)
1443 return false; 1505 return false;
1444 desc = buf; 1506 desc = buf;
1445 1507
1446 total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */ 1508 total_len = usb_get_descriptor(interface_to_usbdev(interface),
1447 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); 1509 0x5f, /* vendor specific */
1510 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
1511
1512 /* if not found, look in configuration descriptor */
1513 if (total_len < 0) {
1514 if (0 == usb_get_extra_descriptor(interface->cur_altsetting,
1515 0x5f, &desc))
1516 total_len = (int) desc[0];
1517 }
1518
1448 if (total_len > 5) { 1519 if (total_len > 5) {
1449 pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \ 1520 pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \
1450 "%02x %02x %02x %02x %02x %02x %02x\n", 1521 "%02x %02x %02x %02x %02x %02x %02x\n",
@@ -1485,6 +1556,8 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
1485 } 1556 }
1486 desc += length; 1557 desc += length;
1487 } 1558 }
1559 } else {
1560 pr_info("vendor descriptor not available (%d)\n", total_len);
1488 } 1561 }
1489 1562
1490 goto success; 1563 goto success;
@@ -1531,10 +1604,11 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1531 usbdev->descriptor.bcdDevice, dev); 1604 usbdev->descriptor.bcdDevice, dev);
1532 pr_info("console enable=%d\n", console); 1605 pr_info("console enable=%d\n", console);
1533 pr_info("fb_defio enable=%d\n", fb_defio); 1606 pr_info("fb_defio enable=%d\n", fb_defio);
1607 pr_info("shadow enable=%d\n", shadow);
1534 1608
1535 dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */ 1609 dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
1536 1610
1537 if (!dlfb_parse_vendor_descriptor(dev, usbdev)) { 1611 if (!dlfb_parse_vendor_descriptor(dev, interface)) {
1538 pr_err("firmware not recognized. Assume incompatible device\n"); 1612 pr_err("firmware not recognized. Assume incompatible device\n");
1539 goto error; 1613 goto error;
1540 } 1614 }
@@ -1548,7 +1622,7 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1548 /* We don't register a new USB class. Our client interface is fbdev */ 1622 /* We don't register a new USB class. Our client interface is fbdev */
1549 1623
1550 /* allocates framebuffer driver structure, not framebuffer memory */ 1624 /* allocates framebuffer driver structure, not framebuffer memory */
1551 info = framebuffer_alloc(0, &usbdev->dev); 1625 info = framebuffer_alloc(0, &interface->dev);
1552 if (!info) { 1626 if (!info) {
1553 retval = -ENOMEM; 1627 retval = -ENOMEM;
1554 pr_err("framebuffer_alloc failed\n"); 1628 pr_err("framebuffer_alloc failed\n");
@@ -1883,10 +1957,13 @@ static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len)
1883} 1957}
1884 1958
1885module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); 1959module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1886MODULE_PARM_DESC(console, "Allow fbcon to consume first framebuffer found"); 1960MODULE_PARM_DESC(console, "Allow fbcon to open framebuffer");
1887 1961
1888module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); 1962module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1889MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support. *Experimental*"); 1963MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes");
1964
1965module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1966MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf");
1890 1967
1891MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " 1968MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
1892 "Jaya Kumar <jayakumar.lkml@gmail.com>, " 1969 "Jaya Kumar <jayakumar.lkml@gmail.com>, "
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index 6b52bf65f0b..3f5a041601d 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -555,7 +555,7 @@ static int __init valkyrie_init_info(struct fb_info *info,
555 555
556 556
557/* 557/*
558 * Parse user speficied options (`video=valkyriefb:') 558 * Parse user specified options (`video=valkyriefb:')
559 */ 559 */
560int __init valkyriefb_setup(char *options) 560int __init valkyriefb_setup(char *options)
561{ 561{
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index bc67251f1a2..bf2f78065cf 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -395,8 +395,8 @@ static int vfb_pan_display(struct fb_var_screeninfo *var,
395 || var->xoffset) 395 || var->xoffset)
396 return -EINVAL; 396 return -EINVAL;
397 } else { 397 } else {
398 if (var->xoffset + var->xres > info->var.xres_virtual || 398 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
399 var->yoffset + var->yres > info->var.yres_virtual) 399 var->yoffset + info->var.yres > info->var.yres_virtual)
400 return -EINVAL; 400 return -EINVAL;
401 } 401 }
402 info->var.xoffset = var->xoffset; 402 info->var.xoffset = var->xoffset;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 305c975b178..0267acd8dc8 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -207,7 +207,7 @@ static void vga16fb_pan_var(struct fb_info *info,
207 * granularity if someone supports xoffset in bit resolution */ 207 * granularity if someone supports xoffset in bit resolution */
208 vga_io_r(VGA_IS1_RC); /* reset flip-flop */ 208 vga_io_r(VGA_IS1_RC); /* reset flip-flop */
209 vga_io_w(VGA_ATT_IW, VGA_ATC_PEL); 209 vga_io_w(VGA_ATT_IW, VGA_ATC_PEL);
210 if (var->bits_per_pixel == 8) 210 if (info->var.bits_per_pixel == 8)
211 vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1); 211 vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1);
212 else 212 else
213 vga_io_w(VGA_ATT_IW, xoffset & 7); 213 vga_io_w(VGA_ATT_IW, xoffset & 7);
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index b1f364745ca..9138e517267 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -172,30 +172,20 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
172} 172}
173 173
174/* DVI Set Mode */ 174/* DVI Set Mode */
175void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp, 175void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga)
176 int set_iga)
177{ 176{
178 struct VideoModeTable *rb_mode; 177 struct fb_var_screeninfo dvi_var = *var;
179 struct crt_mode_table *pDviTiming; 178 struct crt_mode_table *rb_mode;
180 unsigned long desirePixelClock, maxPixelClock; 179 int maxPixelClock;
181 pDviTiming = mode->crtc; 180
182 desirePixelClock = pDviTiming->refresh_rate 181 maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;
183 * pDviTiming->crtc.hor_total * pDviTiming->crtc.ver_total 182 if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) {
184 / 1000000; 183 rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60);
185 maxPixelClock = (unsigned long)viaparinfo-> 184 if (rb_mode)
186 tmds_setting_info->max_pixel_clock; 185 viafb_fill_var_timing_info(&dvi_var, rb_mode);
187
188 DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
189
190 if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
191 rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr,
192 mode->crtc[0].crtc.ver_addr);
193 if (rb_mode) {
194 mode = rb_mode;
195 pDviTiming = rb_mode->crtc;
196 }
197 } 186 }
198 viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga); 187
188 viafb_fill_crtc_timing(&dvi_var, iga);
199} 189}
200 190
201/* Sense DVI Connector */ 191/* Sense DVI Connector */
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
index f473dd01097..e2116aaf797 100644
--- a/drivers/video/via/dvi.h
+++ b/drivers/video/via/dvi.h
@@ -59,7 +59,6 @@ void viafb_dvi_enable(void);
59bool __devinit viafb_tmds_trasmitter_identify(void); 59bool __devinit viafb_tmds_trasmitter_identify(void);
60void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, 60void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
61 struct tmds_setting_information *tmds_setting); 61 struct tmds_setting_information *tmds_setting);
62void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp, 62void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga);
63 int set_iga);
64 63
65#endif /* __DVI_H__ */ 64#endif /* __DVI_H__ */
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
index e10d8249534..3102171c167 100644
--- a/drivers/video/via/global.c
+++ b/drivers/video/via/global.c
@@ -35,6 +35,8 @@ int viafb_LCD_ON ;
35int viafb_LCD2_ON; 35int viafb_LCD2_ON;
36int viafb_SAMM_ON; 36int viafb_SAMM_ON;
37int viafb_dual_fb; 37int viafb_dual_fb;
38unsigned int viafb_second_xres = 640;
39unsigned int viafb_second_yres = 480;
38int viafb_hotplug_Xres = 640; 40int viafb_hotplug_Xres = 640;
39int viafb_hotplug_Yres = 480; 41int viafb_hotplug_Yres = 480;
40int viafb_hotplug_bpp = 32; 42int viafb_hotplug_bpp = 32;
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
index ff969dc3459..275dbbbd6b8 100644
--- a/drivers/video/via/global.h
+++ b/drivers/video/via/global.h
@@ -67,6 +67,8 @@ extern int viafb_lcd_dsp_method;
67extern int viafb_lcd_mode; 67extern int viafb_lcd_mode;
68 68
69extern int viafb_CRT_ON; 69extern int viafb_CRT_ON;
70extern unsigned int viafb_second_xres;
71extern unsigned int viafb_second_yres;
70extern int viafb_hotplug_Xres; 72extern int viafb_hotplug_Xres;
71extern int viafb_hotplug_Yres; 73extern int viafb_hotplug_Yres;
72extern int viafb_hotplug_bpp; 74extern int viafb_hotplug_bpp;
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 47b13535ed2..d5aaca9cfa7 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -191,67 +191,6 @@ static struct fetch_count fetch_count_reg = {
191 {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } } 191 {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
192}; 192};
193 193
194static struct iga1_crtc_timing iga1_crtc_reg = {
195 /* IGA1 Horizontal Total */
196 {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } },
197 /* IGA1 Horizontal Addressable Video */
198 {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } },
199 /* IGA1 Horizontal Blank Start */
200 {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } },
201 /* IGA1 Horizontal Blank End */
202 {IGA1_HOR_BLANK_END_REG_NUM,
203 {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } },
204 /* IGA1 Horizontal Sync Start */
205 {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } },
206 /* IGA1 Horizontal Sync End */
207 {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } },
208 /* IGA1 Vertical Total */
209 {IGA1_VER_TOTAL_REG_NUM,
210 {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } },
211 /* IGA1 Vertical Addressable Video */
212 {IGA1_VER_ADDR_REG_NUM,
213 {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } },
214 /* IGA1 Vertical Blank Start */
215 {IGA1_VER_BLANK_START_REG_NUM,
216 {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } },
217 /* IGA1 Vertical Blank End */
218 {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } },
219 /* IGA1 Vertical Sync Start */
220 {IGA1_VER_SYNC_START_REG_NUM,
221 {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } },
222 /* IGA1 Vertical Sync End */
223 {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } }
224};
225
226static struct iga2_crtc_timing iga2_crtc_reg = {
227 /* IGA2 Horizontal Total */
228 {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } },
229 /* IGA2 Horizontal Addressable Video */
230 {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } },
231 /* IGA2 Horizontal Blank Start */
232 {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } },
233 /* IGA2 Horizontal Blank End */
234 {IGA2_HOR_BLANK_END_REG_NUM,
235 {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } },
236 /* IGA2 Horizontal Sync Start */
237 {IGA2_HOR_SYNC_START_REG_NUM,
238 {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } },
239 /* IGA2 Horizontal Sync End */
240 {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } },
241 /* IGA2 Vertical Total */
242 {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } },
243 /* IGA2 Vertical Addressable Video */
244 {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } },
245 /* IGA2 Vertical Blank Start */
246 {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } },
247 /* IGA2 Vertical Blank End */
248 {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } },
249 /* IGA2 Vertical Sync Start */
250 {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } },
251 /* IGA2 Vertical Sync End */
252 {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } }
253};
254
255static struct rgbLUT palLUT_table[] = { 194static struct rgbLUT palLUT_table[] = {
256 /* {R,G,B} */ 195 /* {R,G,B} */
257 /* Index 0x00~0x03 */ 196 /* Index 0x00~0x03 */
@@ -1528,302 +1467,40 @@ void viafb_set_vclock(u32 clk, int set_iga)
1528 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ 1467 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
1529} 1468}
1530 1469
1531void viafb_load_crtc_timing(struct display_timing device_timing, 1470static struct display_timing var_to_timing(const struct fb_var_screeninfo *var)
1532 int set_iga)
1533{ 1471{
1534 int i; 1472 struct display_timing timing;
1535 int viafb_load_reg_num = 0; 1473
1536 int reg_value = 0; 1474 timing.hor_addr = var->xres;
1537 struct io_register *reg = NULL; 1475 timing.hor_sync_start = timing.hor_addr + var->right_margin;
1538 1476 timing.hor_sync_end = timing.hor_sync_start + var->hsync_len;
1539 viafb_unlock_crt(); 1477 timing.hor_total = timing.hor_sync_end + var->left_margin;
1540 1478 timing.hor_blank_start = timing.hor_addr;
1541 for (i = 0; i < 12; i++) { 1479 timing.hor_blank_end = timing.hor_total;
1542 if (set_iga == IGA1) { 1480 timing.ver_addr = var->yres;
1543 switch (i) { 1481 timing.ver_sync_start = timing.ver_addr + var->lower_margin;
1544 case H_TOTAL_INDEX: 1482 timing.ver_sync_end = timing.ver_sync_start + var->vsync_len;
1545 reg_value = 1483 timing.ver_total = timing.ver_sync_end + var->upper_margin;
1546 IGA1_HOR_TOTAL_FORMULA(device_timing. 1484 timing.ver_blank_start = timing.ver_addr;
1547 hor_total); 1485 timing.ver_blank_end = timing.ver_total;
1548 viafb_load_reg_num = 1486 return timing;
1549 iga1_crtc_reg.hor_total.reg_num;
1550 reg = iga1_crtc_reg.hor_total.reg;
1551 break;
1552 case H_ADDR_INDEX:
1553 reg_value =
1554 IGA1_HOR_ADDR_FORMULA(device_timing.
1555 hor_addr);
1556 viafb_load_reg_num =
1557 iga1_crtc_reg.hor_addr.reg_num;
1558 reg = iga1_crtc_reg.hor_addr.reg;
1559 break;
1560 case H_BLANK_START_INDEX:
1561 reg_value =
1562 IGA1_HOR_BLANK_START_FORMULA
1563 (device_timing.hor_blank_start);
1564 viafb_load_reg_num =
1565 iga1_crtc_reg.hor_blank_start.reg_num;
1566 reg = iga1_crtc_reg.hor_blank_start.reg;
1567 break;
1568 case H_BLANK_END_INDEX:
1569 reg_value =
1570 IGA1_HOR_BLANK_END_FORMULA
1571 (device_timing.hor_blank_start,
1572 device_timing.hor_blank_end);
1573 viafb_load_reg_num =
1574 iga1_crtc_reg.hor_blank_end.reg_num;
1575 reg = iga1_crtc_reg.hor_blank_end.reg;
1576 break;
1577 case H_SYNC_START_INDEX:
1578 reg_value =
1579 IGA1_HOR_SYNC_START_FORMULA
1580 (device_timing.hor_sync_start);
1581 viafb_load_reg_num =
1582 iga1_crtc_reg.hor_sync_start.reg_num;
1583 reg = iga1_crtc_reg.hor_sync_start.reg;
1584 break;
1585 case H_SYNC_END_INDEX:
1586 reg_value =
1587 IGA1_HOR_SYNC_END_FORMULA
1588 (device_timing.hor_sync_start,
1589 device_timing.hor_sync_end);
1590 viafb_load_reg_num =
1591 iga1_crtc_reg.hor_sync_end.reg_num;
1592 reg = iga1_crtc_reg.hor_sync_end.reg;
1593 break;
1594 case V_TOTAL_INDEX:
1595 reg_value =
1596 IGA1_VER_TOTAL_FORMULA(device_timing.
1597 ver_total);
1598 viafb_load_reg_num =
1599 iga1_crtc_reg.ver_total.reg_num;
1600 reg = iga1_crtc_reg.ver_total.reg;
1601 break;
1602 case V_ADDR_INDEX:
1603 reg_value =
1604 IGA1_VER_ADDR_FORMULA(device_timing.
1605 ver_addr);
1606 viafb_load_reg_num =
1607 iga1_crtc_reg.ver_addr.reg_num;
1608 reg = iga1_crtc_reg.ver_addr.reg;
1609 break;
1610 case V_BLANK_START_INDEX:
1611 reg_value =
1612 IGA1_VER_BLANK_START_FORMULA
1613 (device_timing.ver_blank_start);
1614 viafb_load_reg_num =
1615 iga1_crtc_reg.ver_blank_start.reg_num;
1616 reg = iga1_crtc_reg.ver_blank_start.reg;
1617 break;
1618 case V_BLANK_END_INDEX:
1619 reg_value =
1620 IGA1_VER_BLANK_END_FORMULA
1621 (device_timing.ver_blank_start,
1622 device_timing.ver_blank_end);
1623 viafb_load_reg_num =
1624 iga1_crtc_reg.ver_blank_end.reg_num;
1625 reg = iga1_crtc_reg.ver_blank_end.reg;
1626 break;
1627 case V_SYNC_START_INDEX:
1628 reg_value =
1629 IGA1_VER_SYNC_START_FORMULA
1630 (device_timing.ver_sync_start);
1631 viafb_load_reg_num =
1632 iga1_crtc_reg.ver_sync_start.reg_num;
1633 reg = iga1_crtc_reg.ver_sync_start.reg;
1634 break;
1635 case V_SYNC_END_INDEX:
1636 reg_value =
1637 IGA1_VER_SYNC_END_FORMULA
1638 (device_timing.ver_sync_start,
1639 device_timing.ver_sync_end);
1640 viafb_load_reg_num =
1641 iga1_crtc_reg.ver_sync_end.reg_num;
1642 reg = iga1_crtc_reg.ver_sync_end.reg;
1643 break;
1644
1645 }
1646 }
1647
1648 if (set_iga == IGA2) {
1649 switch (i) {
1650 case H_TOTAL_INDEX:
1651 reg_value =
1652 IGA2_HOR_TOTAL_FORMULA(device_timing.
1653 hor_total);
1654 viafb_load_reg_num =
1655 iga2_crtc_reg.hor_total.reg_num;
1656 reg = iga2_crtc_reg.hor_total.reg;
1657 break;
1658 case H_ADDR_INDEX:
1659 reg_value =
1660 IGA2_HOR_ADDR_FORMULA(device_timing.
1661 hor_addr);
1662 viafb_load_reg_num =
1663 iga2_crtc_reg.hor_addr.reg_num;
1664 reg = iga2_crtc_reg.hor_addr.reg;
1665 break;
1666 case H_BLANK_START_INDEX:
1667 reg_value =
1668 IGA2_HOR_BLANK_START_FORMULA
1669 (device_timing.hor_blank_start);
1670 viafb_load_reg_num =
1671 iga2_crtc_reg.hor_blank_start.reg_num;
1672 reg = iga2_crtc_reg.hor_blank_start.reg;
1673 break;
1674 case H_BLANK_END_INDEX:
1675 reg_value =
1676 IGA2_HOR_BLANK_END_FORMULA
1677 (device_timing.hor_blank_start,
1678 device_timing.hor_blank_end);
1679 viafb_load_reg_num =
1680 iga2_crtc_reg.hor_blank_end.reg_num;
1681 reg = iga2_crtc_reg.hor_blank_end.reg;
1682 break;
1683 case H_SYNC_START_INDEX:
1684 reg_value =
1685 IGA2_HOR_SYNC_START_FORMULA
1686 (device_timing.hor_sync_start);
1687 if (UNICHROME_CN700 <=
1688 viaparinfo->chip_info->gfx_chip_name)
1689 viafb_load_reg_num =
1690 iga2_crtc_reg.hor_sync_start.
1691 reg_num;
1692 else
1693 viafb_load_reg_num = 3;
1694 reg = iga2_crtc_reg.hor_sync_start.reg;
1695 break;
1696 case H_SYNC_END_INDEX:
1697 reg_value =
1698 IGA2_HOR_SYNC_END_FORMULA
1699 (device_timing.hor_sync_start,
1700 device_timing.hor_sync_end);
1701 viafb_load_reg_num =
1702 iga2_crtc_reg.hor_sync_end.reg_num;
1703 reg = iga2_crtc_reg.hor_sync_end.reg;
1704 break;
1705 case V_TOTAL_INDEX:
1706 reg_value =
1707 IGA2_VER_TOTAL_FORMULA(device_timing.
1708 ver_total);
1709 viafb_load_reg_num =
1710 iga2_crtc_reg.ver_total.reg_num;
1711 reg = iga2_crtc_reg.ver_total.reg;
1712 break;
1713 case V_ADDR_INDEX:
1714 reg_value =
1715 IGA2_VER_ADDR_FORMULA(device_timing.
1716 ver_addr);
1717 viafb_load_reg_num =
1718 iga2_crtc_reg.ver_addr.reg_num;
1719 reg = iga2_crtc_reg.ver_addr.reg;
1720 break;
1721 case V_BLANK_START_INDEX:
1722 reg_value =
1723 IGA2_VER_BLANK_START_FORMULA
1724 (device_timing.ver_blank_start);
1725 viafb_load_reg_num =
1726 iga2_crtc_reg.ver_blank_start.reg_num;
1727 reg = iga2_crtc_reg.ver_blank_start.reg;
1728 break;
1729 case V_BLANK_END_INDEX:
1730 reg_value =
1731 IGA2_VER_BLANK_END_FORMULA
1732 (device_timing.ver_blank_start,
1733 device_timing.ver_blank_end);
1734 viafb_load_reg_num =
1735 iga2_crtc_reg.ver_blank_end.reg_num;
1736 reg = iga2_crtc_reg.ver_blank_end.reg;
1737 break;
1738 case V_SYNC_START_INDEX:
1739 reg_value =
1740 IGA2_VER_SYNC_START_FORMULA
1741 (device_timing.ver_sync_start);
1742 viafb_load_reg_num =
1743 iga2_crtc_reg.ver_sync_start.reg_num;
1744 reg = iga2_crtc_reg.ver_sync_start.reg;
1745 break;
1746 case V_SYNC_END_INDEX:
1747 reg_value =
1748 IGA2_VER_SYNC_END_FORMULA
1749 (device_timing.ver_sync_start,
1750 device_timing.ver_sync_end);
1751 viafb_load_reg_num =
1752 iga2_crtc_reg.ver_sync_end.reg_num;
1753 reg = iga2_crtc_reg.ver_sync_end.reg;
1754 break;
1755
1756 }
1757 }
1758 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1759 }
1760
1761 viafb_lock_crt();
1762} 1487}
1763 1488
1764void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, 1489void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga)
1765 struct VideoModeTable *video_mode, int bpp_byte, int set_iga)
1766{ 1490{
1767 struct display_timing crt_reg; 1491 struct display_timing crt_reg = var_to_timing(var);
1768 int i;
1769 int index = 0;
1770 int h_addr, v_addr;
1771 u32 clock, refresh = viafb_refresh;
1772
1773 if (viafb_SAMM_ON && set_iga == IGA2)
1774 refresh = viafb_refresh1;
1775
1776 for (i = 0; i < video_mode->mode_array; i++) {
1777 index = i;
1778
1779 if (crt_table[i].refresh_rate == refresh)
1780 break;
1781 }
1782 1492
1783 crt_reg = crt_table[index].crtc; 1493 if (iga == IGA1)
1494 via_set_primary_timing(&crt_reg);
1495 else if (iga == IGA2)
1496 via_set_secondary_timing(&crt_reg);
1784 1497
1785 /* Mode 640x480 has border, but LCD/DFP didn't have border. */ 1498 viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga);
1786 /* So we would delete border. */ 1499 if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266
1787 if ((viafb_LCD_ON | viafb_DVI_ON) 1500 && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)
1788 && video_mode->crtc[0].crtc.hor_addr == 640 1501 viafb_load_FIFO_reg(iga, var->xres, var->yres);
1789 && video_mode->crtc[0].crtc.ver_addr == 480
1790 && refresh == 60) {
1791 /* The border is 8 pixels. */
1792 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
1793
1794 /* Blanking time should add left and right borders. */
1795 crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
1796 }
1797
1798 h_addr = crt_reg.hor_addr;
1799 v_addr = crt_reg.ver_addr;
1800 if (set_iga == IGA1) {
1801 viafb_unlock_crt();
1802 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
1803 }
1804
1805 switch (set_iga) {
1806 case IGA1:
1807 viafb_load_crtc_timing(crt_reg, IGA1);
1808 break;
1809 case IGA2:
1810 viafb_load_crtc_timing(crt_reg, IGA2);
1811 break;
1812 }
1813
1814 viafb_lock_crt();
1815 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
1816 viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
1817
1818 /* load FIFO */
1819 if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
1820 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
1821 viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
1822
1823 clock = crt_reg.hor_total * crt_reg.ver_total
1824 * crt_table[index].refresh_rate;
1825 viafb_set_vclock(clock, set_iga);
1826 1502
1503 viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga);
1827} 1504}
1828 1505
1829void __devinit viafb_init_chip_info(int chip_type) 1506void __devinit viafb_init_chip_info(int chip_type)
@@ -2092,23 +1769,9 @@ static u8 get_sync(struct fb_info *info)
2092 return polarity; 1769 return polarity;
2093} 1770}
2094 1771
2095int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, 1772static void hw_init(void)
2096 struct VideoModeTable *vmode_tbl1, int video_bpp1)
2097{ 1773{
2098 int i, j; 1774 int i;
2099 int port;
2100 u32 devices = viaparinfo->shared->iga1_devices
2101 | viaparinfo->shared->iga2_devices;
2102 u8 value, index, mask;
2103 struct crt_mode_table *crt_timing;
2104 struct crt_mode_table *crt_timing1 = NULL;
2105
2106 device_screen_off();
2107 crt_timing = vmode_tbl->crtc;
2108
2109 if (viafb_SAMM_ON == 1) {
2110 crt_timing1 = vmode_tbl1->crtc;
2111 }
2112 1775
2113 inb(VIAStatus); 1776 inb(VIAStatus);
2114 outb(0x00, VIAAR); 1777 outb(0x00, VIAAR);
@@ -2147,9 +1810,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2147 break; 1810 break;
2148 } 1811 }
2149 1812
1813 /* probably this should go to the scaling code one day */
2150 viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters)); 1814 viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
2151 device_off();
2152 via_set_state(devices, VIA_STATE_OFF);
2153 1815
2154 /* Fill VPIT Parameters */ 1816 /* Fill VPIT Parameters */
2155 /* Write Misc Register */ 1817 /* Write Misc Register */
@@ -2175,12 +1837,29 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2175 inb(VIAStatus); 1837 inb(VIAStatus);
2176 outb(0x20, VIAAR); 1838 outb(0x20, VIAAR);
2177 1839
1840 load_fix_bit_crtc_reg();
1841}
1842
1843int viafb_setmode(int video_bpp, int video_bpp1)
1844{
1845 int j;
1846 int port;
1847 u32 devices = viaparinfo->shared->iga1_devices
1848 | viaparinfo->shared->iga2_devices;
1849 u8 value, index, mask;
1850 struct fb_var_screeninfo var2;
1851
1852 device_screen_off();
1853 device_off();
1854 via_set_state(devices, VIA_STATE_OFF);
1855
1856 hw_init();
1857
2178 /* Update Patch Register */ 1858 /* Update Patch Register */
2179 1859
2180 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 1860 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
2181 || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) 1861 || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
2182 && vmode_tbl->crtc[0].crtc.hor_addr == 1024 1862 && viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) {
2183 && vmode_tbl->crtc[0].crtc.ver_addr == 768) {
2184 for (j = 0; j < res_patch_table[0].table_length; j++) { 1863 for (j = 0; j < res_patch_table[0].table_length; j++) {
2185 index = res_patch_table[0].io_reg_table[j].index; 1864 index = res_patch_table[0].io_reg_table[j].index;
2186 port = res_patch_table[0].io_reg_table[j].port; 1865 port = res_patch_table[0].io_reg_table[j].port;
@@ -2190,7 +1869,6 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2190 } 1869 }
2191 } 1870 }
2192 1871
2193 load_fix_bit_crtc_reg();
2194 via_set_primary_pitch(viafbinfo->fix.line_length); 1872 via_set_primary_pitch(viafbinfo->fix.line_length);
2195 via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length 1873 via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
2196 : viafbinfo->fix.line_length); 1874 : viafbinfo->fix.line_length);
@@ -2208,23 +1886,28 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2208 1886
2209 /* Clear On Screen */ 1887 /* Clear On Screen */
2210 1888
1889 if (viafb_dual_fb) {
1890 var2 = viafbinfo1->var;
1891 } else if (viafb_SAMM_ON) {
1892 viafb_fill_var_timing_info(&var2, viafb_get_best_mode(
1893 viafb_second_xres, viafb_second_yres, viafb_refresh1));
1894 var2.bits_per_pixel = viafbinfo->var.bits_per_pixel;
1895 }
1896
2211 /* CRT set mode */ 1897 /* CRT set mode */
2212 if (viafb_CRT_ON) { 1898 if (viafb_CRT_ON) {
2213 if (viafb_SAMM_ON && 1899 if (viaparinfo->shared->iga2_devices & VIA_CRT
2214 viaparinfo->shared->iga2_devices & VIA_CRT) { 1900 && viafb_SAMM_ON)
2215 viafb_fill_crtc_timing(crt_timing1, vmode_tbl1, 1901 viafb_fill_crtc_timing(&var2, IGA2);
2216 video_bpp1 / 8, IGA2); 1902 else
2217 } else { 1903 viafb_fill_crtc_timing(&viafbinfo->var,
2218 viafb_fill_crtc_timing(crt_timing, vmode_tbl,
2219 video_bpp / 8,
2220 (viaparinfo->shared->iga1_devices & VIA_CRT) 1904 (viaparinfo->shared->iga1_devices & VIA_CRT)
2221 ? IGA1 : IGA2); 1905 ? IGA1 : IGA2);
2222 }
2223 1906
2224 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode 1907 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
2225 to 8 alignment (1368),there is several pixels (2 pixels) 1908 to 8 alignment (1368),there is several pixels (2 pixels)
2226 on right side of screen. */ 1909 on right side of screen. */
2227 if (vmode_tbl->crtc[0].crtc.hor_addr % 8) { 1910 if (viafbinfo->var.xres % 8) {
2228 viafb_unlock_crt(); 1911 viafb_unlock_crt();
2229 viafb_write_reg(CR02, VIACR, 1912 viafb_write_reg(CR02, VIACR,
2230 viafb_read_reg(VIACR, CR02) - 1); 1913 viafb_read_reg(VIACR, CR02) - 1);
@@ -2233,31 +1916,20 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2233 } 1916 }
2234 1917
2235 if (viafb_DVI_ON) { 1918 if (viafb_DVI_ON) {
2236 if (viafb_SAMM_ON && 1919 if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2
2237 (viaparinfo->tmds_setting_info->iga_path == IGA2)) { 1920 && viafb_SAMM_ON)
2238 viafb_dvi_set_mode(viafb_get_mode 1921 viafb_dvi_set_mode(&var2, IGA2);
2239 (viaparinfo->tmds_setting_info->h_active, 1922 else
2240 viaparinfo->tmds_setting_info-> 1923 viafb_dvi_set_mode(&viafbinfo->var,
2241 v_active), 1924 viaparinfo->tmds_setting_info->iga_path);
2242 video_bpp1, viaparinfo->
2243 tmds_setting_info->iga_path);
2244 } else {
2245 viafb_dvi_set_mode(viafb_get_mode
2246 (viaparinfo->tmds_setting_info->h_active,
2247 viaparinfo->
2248 tmds_setting_info->v_active),
2249 video_bpp, viaparinfo->
2250 tmds_setting_info->iga_path);
2251 }
2252 } 1925 }
2253 1926
2254 if (viafb_LCD_ON) { 1927 if (viafb_LCD_ON) {
2255 if (viafb_SAMM_ON && 1928 if (viafb_SAMM_ON &&
2256 (viaparinfo->lvds_setting_info->iga_path == IGA2)) { 1929 (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
2257 viaparinfo->lvds_setting_info->bpp = video_bpp1; 1930 viaparinfo->lvds_setting_info->bpp = video_bpp1;
2258 viafb_lcd_set_mode(crt_timing1, viaparinfo-> 1931 viafb_lcd_set_mode(viaparinfo->lvds_setting_info,
2259 lvds_setting_info, 1932 &viaparinfo->chip_info->lvds_chip_info);
2260 &viaparinfo->chip_info->lvds_chip_info);
2261 } else { 1933 } else {
2262 /* IGA1 doesn't have LCD scaling, so set it center. */ 1934 /* IGA1 doesn't have LCD scaling, so set it center. */
2263 if (viaparinfo->lvds_setting_info->iga_path == IGA1) { 1935 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
@@ -2265,18 +1937,16 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2265 LCD_CENTERING; 1937 LCD_CENTERING;
2266 } 1938 }
2267 viaparinfo->lvds_setting_info->bpp = video_bpp; 1939 viaparinfo->lvds_setting_info->bpp = video_bpp;
2268 viafb_lcd_set_mode(crt_timing, viaparinfo-> 1940 viafb_lcd_set_mode(viaparinfo->lvds_setting_info,
2269 lvds_setting_info, 1941 &viaparinfo->chip_info->lvds_chip_info);
2270 &viaparinfo->chip_info->lvds_chip_info);
2271 } 1942 }
2272 } 1943 }
2273 if (viafb_LCD2_ON) { 1944 if (viafb_LCD2_ON) {
2274 if (viafb_SAMM_ON && 1945 if (viafb_SAMM_ON &&
2275 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { 1946 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
2276 viaparinfo->lvds_setting_info2->bpp = video_bpp1; 1947 viaparinfo->lvds_setting_info2->bpp = video_bpp1;
2277 viafb_lcd_set_mode(crt_timing1, viaparinfo-> 1948 viafb_lcd_set_mode(viaparinfo->lvds_setting_info2,
2278 lvds_setting_info2, 1949 &viaparinfo->chip_info->lvds_chip_info2);
2279 &viaparinfo->chip_info->lvds_chip_info2);
2280 } else { 1950 } else {
2281 /* IGA1 doesn't have LCD scaling, so set it center. */ 1951 /* IGA1 doesn't have LCD scaling, so set it center. */
2282 if (viaparinfo->lvds_setting_info2->iga_path == IGA1) { 1952 if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
@@ -2284,9 +1954,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2284 LCD_CENTERING; 1954 LCD_CENTERING;
2285 } 1955 }
2286 viaparinfo->lvds_setting_info2->bpp = video_bpp; 1956 viaparinfo->lvds_setting_info2->bpp = video_bpp;
2287 viafb_lcd_set_mode(crt_timing, viaparinfo-> 1957 viafb_lcd_set_mode(viaparinfo->lvds_setting_info2,
2288 lvds_setting_info2, 1958 &viaparinfo->chip_info->lvds_chip_info2);
2289 &viaparinfo->chip_info->lvds_chip_info2);
2290 } 1959 }
2291 } 1960 }
2292 1961
@@ -2296,8 +1965,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2296 1965
2297 /* If set mode normally, save resolution information for hot-plug . */ 1966 /* If set mode normally, save resolution information for hot-plug . */
2298 if (!viafb_hotplug) { 1967 if (!viafb_hotplug) {
2299 viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr; 1968 viafb_hotplug_Xres = viafbinfo->var.xres;
2300 viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr; 1969 viafb_hotplug_Yres = viafbinfo->var.yres;
2301 viafb_hotplug_bpp = video_bpp; 1970 viafb_hotplug_bpp = video_bpp;
2302 viafb_hotplug_refresh = viafb_refresh; 1971 viafb_hotplug_refresh = viafb_refresh;
2303 1972
@@ -2348,42 +2017,14 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2348 return 1; 2017 return 1;
2349} 2018}
2350 2019
2351int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
2352{
2353 int i;
2354 struct crt_mode_table *best;
2355 struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
2356
2357 if (!vmode)
2358 return RES_640X480_60HZ_PIXCLOCK;
2359
2360 best = &vmode->crtc[0];
2361 for (i = 1; i < vmode->mode_array; i++) {
2362 if (abs(vmode->crtc[i].refresh_rate - vmode_refresh)
2363 < abs(best->refresh_rate - vmode_refresh))
2364 best = &vmode->crtc[i];
2365 }
2366
2367 return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total)
2368 * 1000 / best->refresh_rate;
2369}
2370
2371int viafb_get_refresh(int hres, int vres, u32 long_refresh) 2020int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2372{ 2021{
2373 int i;
2374 struct crt_mode_table *best; 2022 struct crt_mode_table *best;
2375 struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
2376 2023
2377 if (!vmode) 2024 best = viafb_get_best_mode(hres, vres, long_refresh);
2025 if (!best)
2378 return 60; 2026 return 60;
2379 2027
2380 best = &vmode->crtc[0];
2381 for (i = 1; i < vmode->mode_array; i++) {
2382 if (abs(vmode->crtc[i].refresh_rate - long_refresh)
2383 < abs(best->refresh_rate - long_refresh))
2384 best = &vmode->crtc[i];
2385 }
2386
2387 if (abs(best->refresh_rate - long_refresh) > 3) { 2028 if (abs(best->refresh_rate - long_refresh) > 3) {
2388 if (hres == 1200 && vres == 900) 2029 if (hres == 1200 && vres == 900)
2389 return 49; /* OLPC DCON only supports 50 Hz */ 2030 return 49; /* OLPC DCON only supports 50 Hz */
@@ -2485,21 +2126,14 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2485} 2126}
2486 2127
2487/*According var's xres, yres fill var's other timing information*/ 2128/*According var's xres, yres fill var's other timing information*/
2488void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, 2129void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
2489 struct VideoModeTable *vmode_tbl) 2130 struct crt_mode_table *mode)
2490{ 2131{
2491 struct crt_mode_table *crt_timing = NULL;
2492 struct display_timing crt_reg; 2132 struct display_timing crt_reg;
2493 int i = 0, index = 0;
2494 crt_timing = vmode_tbl->crtc;
2495 for (i = 0; i < vmode_tbl->mode_array; i++) {
2496 index = i;
2497 if (crt_timing[i].refresh_rate == refresh)
2498 break;
2499 }
2500 2133
2501 crt_reg = crt_timing[index].crtc; 2134 crt_reg = mode->crtc;
2502 var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); 2135 var->pixclock = 1000000000 / (crt_reg.hor_total * crt_reg.ver_total)
2136 * 1000 / mode->refresh_rate;
2503 var->left_margin = 2137 var->left_margin =
2504 crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); 2138 crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
2505 var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; 2139 var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
@@ -2509,8 +2143,8 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
2509 var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; 2143 var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
2510 var->vsync_len = crt_reg.ver_sync_end; 2144 var->vsync_len = crt_reg.ver_sync_end;
2511 var->sync = 0; 2145 var->sync = 0;
2512 if (crt_timing[index].h_sync_polarity == POSITIVE) 2146 if (mode->h_sync_polarity == POSITIVE)
2513 var->sync |= FB_SYNC_HOR_HIGH_ACT; 2147 var->sync |= FB_SYNC_HOR_HIGH_ACT;
2514 if (crt_timing[index].v_sync_polarity == POSITIVE) 2148 if (mode->v_sync_polarity == POSITIVE)
2515 var->sync |= FB_SYNC_VERT_HIGH_ACT; 2149 var->sync |= FB_SYNC_VERT_HIGH_ACT;
2516} 2150}
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index c7239eb83ba..4db5b6e8d8d 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -51,40 +51,6 @@
51#define VIA_HSYNC_NEGATIVE 0x01 51#define VIA_HSYNC_NEGATIVE 0x01
52#define VIA_VSYNC_NEGATIVE 0x02 52#define VIA_VSYNC_NEGATIVE 0x02
53 53
54/***************************************************
55* Definition IGA1 Design Method of CRTC Registers *
56****************************************************/
57#define IGA1_HOR_TOTAL_FORMULA(x) (((x)/8)-5)
58#define IGA1_HOR_ADDR_FORMULA(x) (((x)/8)-1)
59#define IGA1_HOR_BLANK_START_FORMULA(x) (((x)/8)-1)
60#define IGA1_HOR_BLANK_END_FORMULA(x, y) (((x+y)/8)-1)
61#define IGA1_HOR_SYNC_START_FORMULA(x) ((x)/8)
62#define IGA1_HOR_SYNC_END_FORMULA(x, y) ((x+y)/8)
63
64#define IGA1_VER_TOTAL_FORMULA(x) ((x)-2)
65#define IGA1_VER_ADDR_FORMULA(x) ((x)-1)
66#define IGA1_VER_BLANK_START_FORMULA(x) ((x)-1)
67#define IGA1_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
68#define IGA1_VER_SYNC_START_FORMULA(x) ((x)-1)
69#define IGA1_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
70
71/***************************************************
72** Definition IGA2 Design Method of CRTC Registers *
73****************************************************/
74#define IGA2_HOR_TOTAL_FORMULA(x) ((x)-1)
75#define IGA2_HOR_ADDR_FORMULA(x) ((x)-1)
76#define IGA2_HOR_BLANK_START_FORMULA(x) ((x)-1)
77#define IGA2_HOR_BLANK_END_FORMULA(x, y) ((x+y)-1)
78#define IGA2_HOR_SYNC_START_FORMULA(x) ((x)-1)
79#define IGA2_HOR_SYNC_END_FORMULA(x, y) ((x+y)-1)
80
81#define IGA2_VER_TOTAL_FORMULA(x) ((x)-1)
82#define IGA2_VER_ADDR_FORMULA(x) ((x)-1)
83#define IGA2_VER_BLANK_START_FORMULA(x) ((x)-1)
84#define IGA2_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
85#define IGA2_VER_SYNC_START_FORMULA(x) ((x)-1)
86#define IGA2_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
87
88/**********************************************************/ 54/**********************************************************/
89/* Definition IGA2 Design Method of CRTC Shadow Registers */ 55/* Definition IGA2 Design Method of CRTC Shadow Registers */
90/**********************************************************/ 56/**********************************************************/
@@ -97,33 +63,6 @@
97#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x) 63#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x)
98#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y) 64#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y)
99 65
100/* Define Register Number for IGA1 CRTC Timing */
101
102/* location: {CR00,0,7},{CR36,3,3} */
103#define IGA1_HOR_TOTAL_REG_NUM 2
104/* location: {CR01,0,7} */
105#define IGA1_HOR_ADDR_REG_NUM 1
106/* location: {CR02,0,7} */
107#define IGA1_HOR_BLANK_START_REG_NUM 1
108/* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */
109#define IGA1_HOR_BLANK_END_REG_NUM 3
110/* location: {CR04,0,7},{CR33,4,4} */
111#define IGA1_HOR_SYNC_START_REG_NUM 2
112/* location: {CR05,0,4} */
113#define IGA1_HOR_SYNC_END_REG_NUM 1
114/* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */
115#define IGA1_VER_TOTAL_REG_NUM 4
116/* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */
117#define IGA1_VER_ADDR_REG_NUM 4
118/* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */
119#define IGA1_VER_BLANK_START_REG_NUM 4
120/* location: {CR16,0,7} */
121#define IGA1_VER_BLANK_END_REG_NUM 1
122/* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */
123#define IGA1_VER_SYNC_START_REG_NUM 4
124/* location: {CR11,0,3} */
125#define IGA1_VER_SYNC_END_REG_NUM 1
126
127/* Define Register Number for IGA2 Shadow CRTC Timing */ 66/* Define Register Number for IGA2 Shadow CRTC Timing */
128 67
129/* location: {CR6D,0,7},{CR71,3,3} */ 68/* location: {CR6D,0,7},{CR71,3,3} */
@@ -143,37 +82,6 @@
143/* location: {CR76,0,3} */ 82/* location: {CR76,0,3} */
144#define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1 83#define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1
145 84
146/* Define Register Number for IGA2 CRTC Timing */
147
148/* location: {CR50,0,7},{CR55,0,3} */
149#define IGA2_HOR_TOTAL_REG_NUM 2
150/* location: {CR51,0,7},{CR55,4,6} */
151#define IGA2_HOR_ADDR_REG_NUM 2
152/* location: {CR52,0,7},{CR54,0,2} */
153#define IGA2_HOR_BLANK_START_REG_NUM 2
154/* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6]
155is reserved, so it may have problem to set 1600x1200 on IGA2. */
156/* Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */
157#define IGA2_HOR_BLANK_END_REG_NUM 3
158/* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */
159/* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */
160#define IGA2_HOR_SYNC_START_REG_NUM 4
161
162/* location: {CR57,0,7},{CR5C,6,6} */
163#define IGA2_HOR_SYNC_END_REG_NUM 2
164/* location: {CR58,0,7},{CR5D,0,2} */
165#define IGA2_VER_TOTAL_REG_NUM 2
166/* location: {CR59,0,7},{CR5D,3,5} */
167#define IGA2_VER_ADDR_REG_NUM 2
168/* location: {CR5A,0,7},{CR5C,0,2} */
169#define IGA2_VER_BLANK_START_REG_NUM 2
170/* location: {CR5E,0,7},{CR5C,3,5} */
171#define IGA2_VER_BLANK_END_REG_NUM 2
172/* location: {CR5E,0,7},{CR5F,5,7} */
173#define IGA2_VER_SYNC_START_REG_NUM 2
174/* location: {CR5F,0,4} */
175#define IGA2_VER_SYNC_END_REG_NUM 1
176
177/* Define Fetch Count Register*/ 85/* Define Fetch Count Register*/
178 86
179/* location: {SR1C,0,7},{SR1D,0,1} */ 87/* location: {SR1C,0,7},{SR1D,0,1} */
@@ -446,87 +354,12 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */
446/* location: {CR78,0,7},{CR79,6,7} */ 354/* location: {CR78,0,7},{CR79,6,7} */
447#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2 355#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2
448 356
449/************************************************
450 ***** Define IGA1 Display Timing *****
451 ************************************************/
452struct io_register { 357struct io_register {
453 u8 io_addr; 358 u8 io_addr;
454 u8 start_bit; 359 u8 start_bit;
455 u8 end_bit; 360 u8 end_bit;
456}; 361};
457 362
458/* IGA1 Horizontal Total */
459struct iga1_hor_total {
460 int reg_num;
461 struct io_register reg[IGA1_HOR_TOTAL_REG_NUM];
462};
463
464/* IGA1 Horizontal Addressable Video */
465struct iga1_hor_addr {
466 int reg_num;
467 struct io_register reg[IGA1_HOR_ADDR_REG_NUM];
468};
469
470/* IGA1 Horizontal Blank Start */
471struct iga1_hor_blank_start {
472 int reg_num;
473 struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM];
474};
475
476/* IGA1 Horizontal Blank End */
477struct iga1_hor_blank_end {
478 int reg_num;
479 struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM];
480};
481
482/* IGA1 Horizontal Sync Start */
483struct iga1_hor_sync_start {
484 int reg_num;
485 struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM];
486};
487
488/* IGA1 Horizontal Sync End */
489struct iga1_hor_sync_end {
490 int reg_num;
491 struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM];
492};
493
494/* IGA1 Vertical Total */
495struct iga1_ver_total {
496 int reg_num;
497 struct io_register reg[IGA1_VER_TOTAL_REG_NUM];
498};
499
500/* IGA1 Vertical Addressable Video */
501struct iga1_ver_addr {
502 int reg_num;
503 struct io_register reg[IGA1_VER_ADDR_REG_NUM];
504};
505
506/* IGA1 Vertical Blank Start */
507struct iga1_ver_blank_start {
508 int reg_num;
509 struct io_register reg[IGA1_VER_BLANK_START_REG_NUM];
510};
511
512/* IGA1 Vertical Blank End */
513struct iga1_ver_blank_end {
514 int reg_num;
515 struct io_register reg[IGA1_VER_BLANK_END_REG_NUM];
516};
517
518/* IGA1 Vertical Sync Start */
519struct iga1_ver_sync_start {
520 int reg_num;
521 struct io_register reg[IGA1_VER_SYNC_START_REG_NUM];
522};
523
524/* IGA1 Vertical Sync End */
525struct iga1_ver_sync_end {
526 int reg_num;
527 struct io_register reg[IGA1_VER_SYNC_END_REG_NUM];
528};
529
530/***************************************************** 363/*****************************************************
531** Define IGA2 Shadow Display Timing **** 364** Define IGA2 Shadow Display Timing ****
532*****************************************************/ 365*****************************************************/
@@ -579,82 +412,6 @@ struct iga2_shadow_ver_sync_end {
579 struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM]; 412 struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
580}; 413};
581 414
582/*****************************************************
583** Define IGA2 Display Timing ****
584******************************************************/
585
586/* IGA2 Horizontal Total */
587struct iga2_hor_total {
588 int reg_num;
589 struct io_register reg[IGA2_HOR_TOTAL_REG_NUM];
590};
591
592/* IGA2 Horizontal Addressable Video */
593struct iga2_hor_addr {
594 int reg_num;
595 struct io_register reg[IGA2_HOR_ADDR_REG_NUM];
596};
597
598/* IGA2 Horizontal Blank Start */
599struct iga2_hor_blank_start {
600 int reg_num;
601 struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM];
602};
603
604/* IGA2 Horizontal Blank End */
605struct iga2_hor_blank_end {
606 int reg_num;
607 struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM];
608};
609
610/* IGA2 Horizontal Sync Start */
611struct iga2_hor_sync_start {
612 int reg_num;
613 struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM];
614};
615
616/* IGA2 Horizontal Sync End */
617struct iga2_hor_sync_end {
618 int reg_num;
619 struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM];
620};
621
622/* IGA2 Vertical Total */
623struct iga2_ver_total {
624 int reg_num;
625 struct io_register reg[IGA2_VER_TOTAL_REG_NUM];
626};
627
628/* IGA2 Vertical Addressable Video */
629struct iga2_ver_addr {
630 int reg_num;
631 struct io_register reg[IGA2_VER_ADDR_REG_NUM];
632};
633
634/* IGA2 Vertical Blank Start */
635struct iga2_ver_blank_start {
636 int reg_num;
637 struct io_register reg[IGA2_VER_BLANK_START_REG_NUM];
638};
639
640/* IGA2 Vertical Blank End */
641struct iga2_ver_blank_end {
642 int reg_num;
643 struct io_register reg[IGA2_VER_BLANK_END_REG_NUM];
644};
645
646/* IGA2 Vertical Sync Start */
647struct iga2_ver_sync_start {
648 int reg_num;
649 struct io_register reg[IGA2_VER_SYNC_START_REG_NUM];
650};
651
652/* IGA2 Vertical Sync End */
653struct iga2_ver_sync_end {
654 int reg_num;
655 struct io_register reg[IGA2_VER_SYNC_END_REG_NUM];
656};
657
658/* IGA1 Fetch Count Register */ 415/* IGA1 Fetch Count Register */
659struct iga1_fetch_count { 416struct iga1_fetch_count {
660 int reg_num; 417 int reg_num;
@@ -817,21 +574,6 @@ struct display_queue_expire_num {
817 iga2_display_queue_expire_num_reg; 574 iga2_display_queue_expire_num_reg;
818}; 575};
819 576
820struct iga1_crtc_timing {
821 struct iga1_hor_total hor_total;
822 struct iga1_hor_addr hor_addr;
823 struct iga1_hor_blank_start hor_blank_start;
824 struct iga1_hor_blank_end hor_blank_end;
825 struct iga1_hor_sync_start hor_sync_start;
826 struct iga1_hor_sync_end hor_sync_end;
827 struct iga1_ver_total ver_total;
828 struct iga1_ver_addr ver_addr;
829 struct iga1_ver_blank_start ver_blank_start;
830 struct iga1_ver_blank_end ver_blank_end;
831 struct iga1_ver_sync_start ver_sync_start;
832 struct iga1_ver_sync_end ver_sync_end;
833};
834
835struct iga2_shadow_crtc_timing { 577struct iga2_shadow_crtc_timing {
836 struct iga2_shadow_hor_total hor_total_shadow; 578 struct iga2_shadow_hor_total hor_total_shadow;
837 struct iga2_shadow_hor_blank_end hor_blank_end_shadow; 579 struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
@@ -843,21 +585,6 @@ struct iga2_shadow_crtc_timing {
843 struct iga2_shadow_ver_sync_end ver_sync_end_shadow; 585 struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
844}; 586};
845 587
846struct iga2_crtc_timing {
847 struct iga2_hor_total hor_total;
848 struct iga2_hor_addr hor_addr;
849 struct iga2_hor_blank_start hor_blank_start;
850 struct iga2_hor_blank_end hor_blank_end;
851 struct iga2_hor_sync_start hor_sync_start;
852 struct iga2_hor_sync_end hor_sync_end;
853 struct iga2_ver_total ver_total;
854 struct iga2_ver_addr ver_addr;
855 struct iga2_ver_blank_start ver_blank_start;
856 struct iga2_ver_blank_end ver_blank_end;
857 struct iga2_ver_sync_start ver_sync_start;
858 struct iga2_ver_sync_end ver_sync_end;
859};
860
861/* device ID */ 588/* device ID */
862#define CLE266_FUNCTION3 0x3123 589#define CLE266_FUNCTION3 0x3123
863#define KM400_FUNCTION3 0x3205 590#define KM400_FUNCTION3 0x3205
@@ -910,9 +637,7 @@ extern int viafb_LCD_ON;
910extern int viafb_DVI_ON; 637extern int viafb_DVI_ON;
911extern int viafb_hotplug; 638extern int viafb_hotplug;
912 639
913void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, 640void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga);
914 struct VideoModeTable *video_mode, int bpp_byte, int set_iga);
915
916void viafb_set_vclock(u32 CLK, int set_iga); 641void viafb_set_vclock(u32 CLK, int set_iga);
917void viafb_load_reg(int timing_value, int viafb_load_reg_num, 642void viafb_load_reg(int timing_value, int viafb_load_reg_num,
918 struct io_register *reg, 643 struct io_register *reg,
@@ -932,13 +657,11 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
932void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ 657void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
933 *p_gfx_dpa_setting); 658 *p_gfx_dpa_setting);
934 659
935int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, 660int viafb_setmode(int video_bpp, int video_bpp1);
936 struct VideoModeTable *vmode_tbl1, int video_bpp1); 661void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
937void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, 662 struct crt_mode_table *mode);
938 struct VideoModeTable *vmode_tbl);
939void __devinit viafb_init_chip_info(int chip_type); 663void __devinit viafb_init_chip_info(int chip_type);
940void __devinit viafb_init_dac(int set_iga); 664void __devinit viafb_init_dac(int set_iga);
941int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
942int viafb_get_refresh(int hres, int vres, u32 float_refresh); 665int viafb_get_refresh(int hres, int vres, u32 float_refresh);
943void viafb_update_device_setting(int hres, int vres, int bpp, int flag); 666void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
944 667
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 6e06981d638..5f3b4e394e8 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -548,9 +548,8 @@ static void lcd_patch_skew(struct lvds_setting_information
548} 548}
549 549
550/* LCD Set Mode */ 550/* LCD Set Mode */
551void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, 551void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info,
552 struct lvds_setting_information *plvds_setting_info, 552 struct lvds_chip_information *plvds_chip_info)
553 struct lvds_chip_information *plvds_chip_info)
554{ 553{
555 int set_iga = plvds_setting_info->iga_path; 554 int set_iga = plvds_setting_info->iga_path;
556 int mode_bpp = plvds_setting_info->bpp; 555 int mode_bpp = plvds_setting_info->bpp;
@@ -559,16 +558,15 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
559 int panel_hres = plvds_setting_info->lcd_panel_hres; 558 int panel_hres = plvds_setting_info->lcd_panel_hres;
560 int panel_vres = plvds_setting_info->lcd_panel_vres; 559 int panel_vres = plvds_setting_info->lcd_panel_vres;
561 u32 clock; 560 u32 clock;
562 struct display_timing mode_crt_reg, panel_crt_reg; 561 struct display_timing mode_crt_reg, panel_crt_reg, timing;
563 struct crt_mode_table *panel_crt_table = NULL; 562 struct crt_mode_table *mode_crt_table, *panel_crt_table;
564 struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres,
565 panel_vres);
566 563
567 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); 564 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
568 /* Get mode table */ 565 /* Get mode table */
566 mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60);
569 mode_crt_reg = mode_crt_table->crtc; 567 mode_crt_reg = mode_crt_table->crtc;
570 /* Get panel table Pointer */ 568 /* Get panel table Pointer */
571 panel_crt_table = vmode_tbl->crtc; 569 panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
572 panel_crt_reg = panel_crt_table->crtc; 570 panel_crt_reg = panel_crt_table->crtc;
573 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); 571 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
574 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) 572 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
@@ -576,31 +574,28 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
576 clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total 574 clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total
577 * panel_crt_table->refresh_rate; 575 * panel_crt_table->refresh_rate;
578 plvds_setting_info->vclk = clock; 576 plvds_setting_info->vclk = clock;
579 if (set_iga == IGA1) { 577
580 /* IGA1 doesn't have LCD scaling, so set it as centering. */ 578 if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
581 viafb_load_crtc_timing(lcd_centering_timging 579 && plvds_setting_info->display_method == LCD_EXPANDSION) {
582 (mode_crt_reg, panel_crt_reg), IGA1); 580 timing = panel_crt_reg;
581 load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
583 } else { 582 } else {
584 /* Expansion */ 583 timing = lcd_centering_timging(mode_crt_reg, panel_crt_reg);
585 if (plvds_setting_info->display_method == LCD_EXPANDSION 584 if (set_iga == IGA2)
586 && (set_hres < panel_hres || set_vres < panel_vres)) { 585 /* disable scaling */
587 /* expansion timing IGA2 loaded panel set timing*/ 586 via_write_reg_mask(VIACR, 0x79, 0x00,
588 viafb_load_crtc_timing(panel_crt_reg, IGA2);
589 DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
590 load_lcd_scaling(set_hres, set_vres, panel_hres,
591 panel_vres);
592 DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
593 } else { /* Centering */
594 /* centering timing IGA2 always loaded panel
595 and mode releative timing */
596 viafb_load_crtc_timing(lcd_centering_timging
597 (mode_crt_reg, panel_crt_reg), IGA2);
598 viafb_write_reg_mask(CR79, VIACR, 0x00,
599 BIT0 + BIT1 + BIT2); 587 BIT0 + BIT1 + BIT2);
600 /* LCD scaling disabled */
601 }
602 } 588 }
603 589
590 timing.hor_blank_end += timing.hor_blank_start;
591 timing.hor_sync_end += timing.hor_sync_start;
592 timing.ver_blank_end += timing.ver_blank_start;
593 timing.ver_sync_end += timing.ver_sync_start;
594 if (set_iga == IGA1)
595 via_set_primary_timing(&timing);
596 else if (set_iga == IGA2)
597 via_set_secondary_timing(&timing);
598
604 /* Fetch count for IGA2 only */ 599 /* Fetch count for IGA2 only */
605 viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); 600 viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
606 601
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h
index 75f60a655b0..77ca7b862e6 100644
--- a/drivers/video/via/lcd.h
+++ b/drivers/video/via/lcd.h
@@ -76,16 +76,13 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
76 *plvds_chip_info, 76 *plvds_chip_info,
77 struct lvds_setting_information 77 struct lvds_setting_information
78 *plvds_setting_info); 78 *plvds_setting_info);
79void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, 79void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info,
80 struct lvds_setting_information *plvds_setting_info, 80 struct lvds_chip_information *plvds_chip_info);
81 struct lvds_chip_information *plvds_chip_info);
82bool __devinit viafb_lvds_trasmitter_identify(void); 81bool __devinit viafb_lvds_trasmitter_identify(void);
83void viafb_init_lvds_output_interface(struct lvds_chip_information 82void viafb_init_lvds_output_interface(struct lvds_chip_information
84 *plvds_chip_info, 83 *plvds_chip_info,
85 struct lvds_setting_information 84 struct lvds_setting_information
86 *plvds_setting_info); 85 *plvds_setting_info);
87bool viafb_lcd_get_mobile_state(bool *mobile); 86bool viafb_lcd_get_mobile_state(bool *mobile);
88void viafb_load_crtc_timing(struct display_timing device_timing,
89 int set_iga);
90 87
91#endif /* __LCD_H__ */ 88#endif /* __LCD_H__ */
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 61b0bd596b8..69d882cbe70 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -22,6 +22,8 @@
22#ifndef __SHARE_H__ 22#ifndef __SHARE_H__
23#define __SHARE_H__ 23#define __SHARE_H__
24 24
25#include "via_modesetting.h"
26
25/* Define Bit Field */ 27/* Define Bit Field */
26#define BIT0 0x01 28#define BIT0 0x01
27#define BIT1 0x02 29#define BIT1 0x02
@@ -634,10 +636,6 @@
634#define V_SYNC_SATRT_SHADOW_INDEX 18 636#define V_SYNC_SATRT_SHADOW_INDEX 18
635#define V_SYNC_END_SHADOW_INDEX 19 637#define V_SYNC_END_SHADOW_INDEX 19
636 638
637/* Definition Video Mode Pixel Clock (picoseconds)
638*/
639#define RES_640X480_60HZ_PIXCLOCK 39722
640
641/* LCD display method 639/* LCD display method
642*/ 640*/
643#define LCD_EXPANDSION 0x00 641#define LCD_EXPANDSION 0x00
@@ -648,23 +646,6 @@
648#define LCD_OPENLDI 0x00 646#define LCD_OPENLDI 0x00
649#define LCD_SPWG 0x01 647#define LCD_SPWG 0x01
650 648
651/* Define display timing
652*/
653struct display_timing {
654 u16 hor_total;
655 u16 hor_addr;
656 u16 hor_blank_start;
657 u16 hor_blank_end;
658 u16 hor_sync_start;
659 u16 hor_sync_end;
660 u16 ver_total;
661 u16 ver_addr;
662 u16 ver_blank_start;
663 u16 ver_blank_end;
664 u16 ver_sync_start;
665 u16 ver_sync_end;
666};
667
668struct crt_mode_table { 649struct crt_mode_table {
669 int refresh_rate; 650 int refresh_rate;
670 int h_sync_polarity; 651 int h_sync_polarity;
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index eb112b62173..dd58b530c0d 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -35,7 +35,7 @@ static struct via_port_cfg adap_configs[] = {
35 * The OLPC XO-1.5 puts the camera power and reset lines onto 35 * The OLPC XO-1.5 puts the camera power and reset lines onto
36 * GPIO 2C. 36 * GPIO 2C.
37 */ 37 */
38static const struct via_port_cfg olpc_adap_configs[] = { 38static struct via_port_cfg olpc_adap_configs[] = {
39 [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 }, 39 [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
40 [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, 40 [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
41 [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, 41 [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c
index 3cddcff88ab..0e431aee17b 100644
--- a/drivers/video/via/via_modesetting.c
+++ b/drivers/video/via/via_modesetting.c
@@ -29,6 +29,110 @@
29#include "share.h" 29#include "share.h"
30#include "debug.h" 30#include "debug.h"
31 31
32
33void via_set_primary_timing(const struct display_timing *timing)
34{
35 struct display_timing raw;
36
37 raw.hor_total = timing->hor_total / 8 - 5;
38 raw.hor_addr = timing->hor_addr / 8 - 1;
39 raw.hor_blank_start = timing->hor_blank_start / 8 - 1;
40 raw.hor_blank_end = timing->hor_blank_end / 8 - 1;
41 raw.hor_sync_start = timing->hor_sync_start / 8;
42 raw.hor_sync_end = timing->hor_sync_end / 8;
43 raw.ver_total = timing->ver_total - 2;
44 raw.ver_addr = timing->ver_addr - 1;
45 raw.ver_blank_start = timing->ver_blank_start - 1;
46 raw.ver_blank_end = timing->ver_blank_end - 1;
47 raw.ver_sync_start = timing->ver_sync_start - 1;
48 raw.ver_sync_end = timing->ver_sync_end - 1;
49
50 /* unlock timing registers */
51 via_write_reg_mask(VIACR, 0x11, 0x00, 0x80);
52
53 via_write_reg(VIACR, 0x00, raw.hor_total & 0xFF);
54 via_write_reg(VIACR, 0x01, raw.hor_addr & 0xFF);
55 via_write_reg(VIACR, 0x02, raw.hor_blank_start & 0xFF);
56 via_write_reg_mask(VIACR, 0x03, raw.hor_blank_end & 0x1F, 0x1F);
57 via_write_reg(VIACR, 0x04, raw.hor_sync_start & 0xFF);
58 via_write_reg_mask(VIACR, 0x05, (raw.hor_sync_end & 0x1F)
59 | (raw.hor_blank_end << (7 - 5) & 0x80), 0x9F);
60 via_write_reg(VIACR, 0x06, raw.ver_total & 0xFF);
61 via_write_reg_mask(VIACR, 0x07, (raw.ver_total >> 8 & 0x01)
62 | (raw.ver_addr >> (8 - 1) & 0x02)
63 | (raw.ver_sync_start >> (8 - 2) & 0x04)
64 | (raw.ver_blank_start >> (8 - 3) & 0x08)
65 | (raw.ver_total >> (9 - 5) & 0x20)
66 | (raw.ver_addr >> (9 - 6) & 0x40)
67 | (raw.ver_sync_start >> (9 - 7) & 0x80), 0xEF);
68 via_write_reg_mask(VIACR, 0x09, raw.ver_blank_start >> (9 - 5) & 0x20,
69 0x20);
70 via_write_reg(VIACR, 0x10, raw.ver_sync_start & 0xFF);
71 via_write_reg_mask(VIACR, 0x11, raw.ver_sync_end & 0x0F, 0x0F);
72 via_write_reg(VIACR, 0x12, raw.ver_addr & 0xFF);
73 via_write_reg(VIACR, 0x15, raw.ver_blank_start & 0xFF);
74 via_write_reg(VIACR, 0x16, raw.ver_blank_end & 0xFF);
75 via_write_reg_mask(VIACR, 0x33, (raw.hor_sync_start >> (8 - 4) & 0x10)
76 | (raw.hor_blank_end >> (6 - 5) & 0x20), 0x30);
77 via_write_reg_mask(VIACR, 0x35, (raw.ver_total >> 10 & 0x01)
78 | (raw.ver_sync_start >> (10 - 1) & 0x02)
79 | (raw.ver_addr >> (10 - 2) & 0x04)
80 | (raw.ver_blank_start >> (10 - 3) & 0x08), 0x0F);
81 via_write_reg_mask(VIACR, 0x36, raw.hor_total >> (8 - 3) & 0x08, 0x08);
82
83 /* lock timing registers */
84 via_write_reg_mask(VIACR, 0x11, 0x80, 0x80);
85
86 /* reset timing control */
87 via_write_reg_mask(VIACR, 0x17, 0x00, 0x80);
88 via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
89}
90
91void via_set_secondary_timing(const struct display_timing *timing)
92{
93 struct display_timing raw;
94
95 raw.hor_total = timing->hor_total - 1;
96 raw.hor_addr = timing->hor_addr - 1;
97 raw.hor_blank_start = timing->hor_blank_start - 1;
98 raw.hor_blank_end = timing->hor_blank_end - 1;
99 raw.hor_sync_start = timing->hor_sync_start - 1;
100 raw.hor_sync_end = timing->hor_sync_end - 1;
101 raw.ver_total = timing->ver_total - 1;
102 raw.ver_addr = timing->ver_addr - 1;
103 raw.ver_blank_start = timing->ver_blank_start - 1;
104 raw.ver_blank_end = timing->ver_blank_end - 1;
105 raw.ver_sync_start = timing->ver_sync_start - 1;
106 raw.ver_sync_end = timing->ver_sync_end - 1;
107
108 via_write_reg(VIACR, 0x50, raw.hor_total & 0xFF);
109 via_write_reg(VIACR, 0x51, raw.hor_addr & 0xFF);
110 via_write_reg(VIACR, 0x52, raw.hor_blank_start & 0xFF);
111 via_write_reg(VIACR, 0x53, raw.hor_blank_end & 0xFF);
112 via_write_reg(VIACR, 0x54, (raw.hor_blank_start >> 8 & 0x07)
113 | (raw.hor_blank_end >> (8 - 3) & 0x38)
114 | (raw.hor_sync_start >> (8 - 6) & 0xC0));
115 via_write_reg_mask(VIACR, 0x55, (raw.hor_total >> 8 & 0x0F)
116 | (raw.hor_addr >> (8 - 4) & 0x70), 0x7F);
117 via_write_reg(VIACR, 0x56, raw.hor_sync_start & 0xFF);
118 via_write_reg(VIACR, 0x57, raw.hor_sync_end & 0xFF);
119 via_write_reg(VIACR, 0x58, raw.ver_total & 0xFF);
120 via_write_reg(VIACR, 0x59, raw.ver_addr & 0xFF);
121 via_write_reg(VIACR, 0x5A, raw.ver_blank_start & 0xFF);
122 via_write_reg(VIACR, 0x5B, raw.ver_blank_end & 0xFF);
123 via_write_reg(VIACR, 0x5C, (raw.ver_blank_start >> 8 & 0x07)
124 | (raw.ver_blank_end >> (8 - 3) & 0x38)
125 | (raw.hor_sync_end >> (8 - 6) & 0x40)
126 | (raw.hor_sync_start >> (10 - 7) & 0x80));
127 via_write_reg(VIACR, 0x5D, (raw.ver_total >> 8 & 0x07)
128 | (raw.ver_addr >> (8 - 3) & 0x38)
129 | (raw.hor_blank_end >> (11 - 6) & 0x40)
130 | (raw.hor_sync_start >> (11 - 7) & 0x80));
131 via_write_reg(VIACR, 0x5E, raw.ver_sync_start & 0xFF);
132 via_write_reg(VIACR, 0x5F, (raw.ver_sync_end & 0x1F)
133 | (raw.ver_sync_start >> (8 - 5) & 0xE0));
134}
135
32void via_set_primary_address(u32 addr) 136void via_set_primary_address(u32 addr)
33{ 137{
34 DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr); 138 DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr);
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h
index ae35cfdeb37..06e09fe351a 100644
--- a/drivers/video/via/via_modesetting.h
+++ b/drivers/video/via/via_modesetting.h
@@ -28,6 +28,29 @@
28 28
29#include <linux/types.h> 29#include <linux/types.h>
30 30
31
32#define VIA_PITCH_SIZE (1<<3)
33#define VIA_PITCH_MAX 0x3FF8
34
35
36struct display_timing {
37 u16 hor_total;
38 u16 hor_addr;
39 u16 hor_blank_start;
40 u16 hor_blank_end;
41 u16 hor_sync_start;
42 u16 hor_sync_end;
43 u16 ver_total;
44 u16 ver_addr;
45 u16 ver_blank_start;
46 u16 ver_blank_end;
47 u16 ver_sync_start;
48 u16 ver_sync_end;
49};
50
51
52void via_set_primary_timing(const struct display_timing *timing);
53void via_set_secondary_timing(const struct display_timing *timing);
31void via_set_primary_address(u32 addr); 54void via_set_primary_address(u32 addr);
32void via_set_secondary_address(u32 addr); 55void via_set_secondary_address(u32 addr);
33void via_set_primary_pitch(u32 pitch); 56void via_set_primary_pitch(u32 pitch);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 53aa4430d86..a13c258bd32 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -38,8 +38,6 @@ static char *viafb_mode1;
38static int viafb_bpp = 32; 38static int viafb_bpp = 32;
39static int viafb_bpp1 = 32; 39static int viafb_bpp1 = 32;
40 40
41static unsigned int viafb_second_xres = 640;
42static unsigned int viafb_second_yres = 480;
43static unsigned int viafb_second_offset; 41static unsigned int viafb_second_offset;
44static int viafb_second_size; 42static int viafb_second_size;
45 43
@@ -151,7 +149,8 @@ static void viafb_update_fix(struct fb_info *info)
151 149
152 info->fix.visual = 150 info->fix.visual =
153 bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 151 bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
154 info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7; 152 info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8,
153 VIA_PITCH_SIZE);
155} 154}
156 155
157static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, 156static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
@@ -200,7 +199,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
200 struct fb_info *info) 199 struct fb_info *info)
201{ 200{
202 int depth, refresh; 201 int depth, refresh;
203 struct VideoModeTable *vmode_entry;
204 struct viafb_par *ppar = info->par; 202 struct viafb_par *ppar = info->par;
205 u32 line; 203 u32 line;
206 204
@@ -210,8 +208,10 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
210 if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) 208 if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
211 return -EINVAL; 209 return -EINVAL;
212 210
213 vmode_entry = viafb_get_mode(var->xres, var->yres); 211 /* the refresh rate is not important here, as we only want to know
214 if (!vmode_entry) { 212 * whether the resolution exists
213 */
214 if (!viafb_get_best_mode(var->xres, var->yres, 60)) {
215 DEBUG_MSG(KERN_INFO 215 DEBUG_MSG(KERN_INFO
216 "viafb: Mode %dx%dx%d not supported!!\n", 216 "viafb: Mode %dx%dx%d not supported!!\n",
217 var->xres, var->yres, var->bits_per_pixel); 217 var->xres, var->yres, var->bits_per_pixel);
@@ -238,8 +238,12 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
238 depth = 24; 238 depth = 24;
239 239
240 viafb_fill_var_color_info(var, depth); 240 viafb_fill_var_color_info(var, depth);
241 line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7; 241 if (var->xres_virtual < var->xres)
242 if (line * var->yres_virtual > ppar->memsize) 242 var->xres_virtual = var->xres;
243
244 line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8,
245 VIA_PITCH_SIZE);
246 if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize)
243 return -EINVAL; 247 return -EINVAL;
244 248
245 /* Based on var passed in to calculate the refresh, 249 /* Based on var passed in to calculate the refresh,
@@ -249,7 +253,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
249 get_var_refresh(var)); 253 get_var_refresh(var));
250 254
251 /* Adjust var according to our driver's own table */ 255 /* Adjust var according to our driver's own table */
252 viafb_fill_var_timing_info(var, refresh, vmode_entry); 256 viafb_fill_var_timing_info(var,
257 viafb_get_best_mode(var->xres, var->yres, refresh));
253 if (var->accel_flags & FB_ACCELF_TEXT && 258 if (var->accel_flags & FB_ACCELF_TEXT &&
254 !ppar->shared->vdev->engine_mmio) 259 !ppar->shared->vdev->engine_mmio)
255 var->accel_flags = 0; 260 var->accel_flags = 0;
@@ -260,7 +265,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
260static int viafb_set_par(struct fb_info *info) 265static int viafb_set_par(struct fb_info *info)
261{ 266{
262 struct viafb_par *viapar = info->par; 267 struct viafb_par *viapar = info->par;
263 struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
264 int refresh; 268 int refresh;
265 DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); 269 DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
266 270
@@ -269,10 +273,7 @@ static int viafb_set_par(struct fb_info *info)
269 viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, 273 viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
270 viafbinfo->var.bits_per_pixel, 0); 274 viafbinfo->var.bits_per_pixel, 0);
271 275
272 vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
273 if (viafb_dual_fb) { 276 if (viafb_dual_fb) {
274 vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres,
275 viafbinfo1->var.yres);
276 viafb_update_device_setting(viafbinfo1->var.xres, 277 viafb_update_device_setting(viafbinfo1->var.xres,
277 viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, 278 viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
278 1); 279 1);
@@ -280,8 +281,6 @@ static int viafb_set_par(struct fb_info *info)
280 DEBUG_MSG(KERN_INFO 281 DEBUG_MSG(KERN_INFO
281 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", 282 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
282 viafb_second_xres, viafb_second_yres, viafb_bpp1); 283 viafb_second_xres, viafb_second_yres, viafb_bpp1);
283 vmode_entry1 = viafb_get_mode(viafb_second_xres,
284 viafb_second_yres);
285 284
286 viafb_update_device_setting(viafb_second_xres, 285 viafb_update_device_setting(viafb_second_xres,
287 viafb_second_yres, viafb_bpp1, 1); 286 viafb_second_yres, viafb_bpp1, 1);
@@ -289,7 +288,8 @@ static int viafb_set_par(struct fb_info *info)
289 288
290 refresh = viafb_get_refresh(info->var.xres, info->var.yres, 289 refresh = viafb_get_refresh(info->var.xres, info->var.yres,
291 get_var_refresh(&info->var)); 290 get_var_refresh(&info->var));
292 if (vmode_entry) { 291 if (viafb_get_best_mode(viafbinfo->var.xres, viafbinfo->var.yres,
292 refresh)) {
293 if (viafb_dual_fb && viapar->iga_path == IGA2) { 293 if (viafb_dual_fb && viapar->iga_path == IGA2) {
294 viafb_bpp1 = info->var.bits_per_pixel; 294 viafb_bpp1 = info->var.bits_per_pixel;
295 viafb_refresh1 = refresh; 295 viafb_refresh1 = refresh;
@@ -302,8 +302,7 @@ static int viafb_set_par(struct fb_info *info)
302 info->flags &= ~FBINFO_HWACCEL_DISABLED; 302 info->flags &= ~FBINFO_HWACCEL_DISABLED;
303 else 303 else
304 info->flags |= FBINFO_HWACCEL_DISABLED; 304 info->flags |= FBINFO_HWACCEL_DISABLED;
305 viafb_setmode(vmode_entry, info->var.bits_per_pixel, 305 viafb_setmode(info->var.bits_per_pixel, viafb_bpp1);
306 vmode_entry1, viafb_bpp1);
307 viafb_pan_display(&info->var, info); 306 viafb_pan_display(&info->var, info);
308 } 307 }
309 308
@@ -348,8 +347,9 @@ static int viafb_pan_display(struct fb_var_screeninfo *var,
348 struct fb_info *info) 347 struct fb_info *info)
349{ 348{
350 struct viafb_par *viapar = info->par; 349 struct viafb_par *viapar = info->par;
351 u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset) 350 u32 vram_addr = viapar->vram_addr
352 * (var->bits_per_pixel / 8) + viapar->vram_addr; 351 + var->yoffset * info->fix.line_length
352 + var->xoffset * info->var.bits_per_pixel / 8;
353 353
354 DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); 354 DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
355 if (!viafb_dual_fb) { 355 if (!viafb_dual_fb) {
@@ -1158,7 +1158,8 @@ static ssize_t viafb_dvp0_proc_write(struct file *file,
1158 for (i = 0; i < 3; i++) { 1158 for (i = 0; i < 3; i++) {
1159 value = strsep(&pbuf, " "); 1159 value = strsep(&pbuf, " ");
1160 if (value != NULL) { 1160 if (value != NULL) {
1161 strict_strtoul(value, 0, (unsigned long *)&reg_val); 1161 if (kstrtou8(value, 0, &reg_val) < 0)
1162 return -EINVAL;
1162 DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i, 1163 DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
1163 reg_val); 1164 reg_val);
1164 switch (i) { 1165 switch (i) {
@@ -1228,7 +1229,8 @@ static ssize_t viafb_dvp1_proc_write(struct file *file,
1228 for (i = 0; i < 3; i++) { 1229 for (i = 0; i < 3; i++) {
1229 value = strsep(&pbuf, " "); 1230 value = strsep(&pbuf, " ");
1230 if (value != NULL) { 1231 if (value != NULL) {
1231 strict_strtoul(value, 0, (unsigned long *)&reg_val); 1232 if (kstrtou8(value, 0, &reg_val) < 0)
1233 return -EINVAL;
1232 switch (i) { 1234 switch (i) {
1233 case 0: 1235 case 0:
1234 viafb_write_reg_mask(CR9B, VIACR, 1236 viafb_write_reg_mask(CR9B, VIACR,
@@ -1286,7 +1288,8 @@ static ssize_t viafb_dfph_proc_write(struct file *file,
1286 if (copy_from_user(&buf[0], buffer, length)) 1288 if (copy_from_user(&buf[0], buffer, length))
1287 return -EFAULT; 1289 return -EFAULT;
1288 buf[length - 1] = '\0'; /*Ensure end string */ 1290 buf[length - 1] = '\0'; /*Ensure end string */
1289 strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val); 1291 if (kstrtou8(buf, 0, &reg_val) < 0)
1292 return -EINVAL;
1290 viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); 1293 viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
1291 return count; 1294 return count;
1292} 1295}
@@ -1325,7 +1328,8 @@ static ssize_t viafb_dfpl_proc_write(struct file *file,
1325 if (copy_from_user(&buf[0], buffer, length)) 1328 if (copy_from_user(&buf[0], buffer, length))
1326 return -EFAULT; 1329 return -EFAULT;
1327 buf[length - 1] = '\0'; /*Ensure end string */ 1330 buf[length - 1] = '\0'; /*Ensure end string */
1328 strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val); 1331 if (kstrtou8(buf, 0, &reg_val) < 0)
1332 return -EINVAL;
1329 viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); 1333 viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
1330 return count; 1334 return count;
1331} 1335}
@@ -1394,8 +1398,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file,
1394 for (i = 0; i < 2; i++) { 1398 for (i = 0; i < 2; i++) {
1395 value = strsep(&pbuf, " "); 1399 value = strsep(&pbuf, " ");
1396 if (value != NULL) { 1400 if (value != NULL) {
1397 strict_strtoul(value, 0, 1401 if (kstrtou8(value, 0, &reg_val.Data) < 0)
1398 (unsigned long *)&reg_val.Data); 1402 return -EINVAL;
1399 switch (i) { 1403 switch (i) {
1400 case 0: 1404 case 0:
1401 reg_val.Index = 0x08; 1405 reg_val.Index = 0x08;
@@ -1431,8 +1435,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file,
1431 for (i = 0; i < 2; i++) { 1435 for (i = 0; i < 2; i++) {
1432 value = strsep(&pbuf, " "); 1436 value = strsep(&pbuf, " ");
1433 if (value != NULL) { 1437 if (value != NULL) {
1434 strict_strtoul(value, 0, 1438 if (kstrtou8(value, 0, &reg_val.Data) < 0)
1435 (unsigned long *)&reg_val.Data); 1439 return -EINVAL;
1436 switch (i) { 1440 switch (i) {
1437 case 0: 1441 case 0:
1438 reg_val.Index = 0x08; 1442 reg_val.Index = 0x08;
@@ -1729,7 +1733,6 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = {
1729int __devinit via_fb_pci_probe(struct viafb_dev *vdev) 1733int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1730{ 1734{
1731 u32 default_xres, default_yres; 1735 u32 default_xres, default_yres;
1732 struct VideoModeTable *vmode_entry;
1733 struct fb_var_screeninfo default_var; 1736 struct fb_var_screeninfo default_var;
1734 int rc; 1737 int rc;
1735 u32 viafb_par_length; 1738 u32 viafb_par_length;
@@ -1802,7 +1805,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1802 } 1805 }
1803 1806
1804 parse_mode(viafb_mode, &default_xres, &default_yres); 1807 parse_mode(viafb_mode, &default_xres, &default_yres);
1805 vmode_entry = viafb_get_mode(default_xres, default_yres);
1806 if (viafb_SAMM_ON == 1) 1808 if (viafb_SAMM_ON == 1)
1807 parse_mode(viafb_mode1, &viafb_second_xres, 1809 parse_mode(viafb_mode1, &viafb_second_xres,
1808 &viafb_second_yres); 1810 &viafb_second_yres);
@@ -1812,9 +1814,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1812 default_var.xres_virtual = default_xres; 1814 default_var.xres_virtual = default_xres;
1813 default_var.yres_virtual = default_yres; 1815 default_var.yres_virtual = default_yres;
1814 default_var.bits_per_pixel = viafb_bpp; 1816 default_var.bits_per_pixel = viafb_bpp;
1815 viafb_fill_var_timing_info(&default_var, viafb_get_refresh( 1817 viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
1816 default_var.xres, default_var.yres, viafb_refresh), 1818 default_var.xres, default_var.yres, viafb_refresh));
1817 viafb_get_mode(default_var.xres, default_var.yres));
1818 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); 1819 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
1819 viafbinfo->var = default_var; 1820 viafbinfo->var = default_var;
1820 1821
@@ -1853,9 +1854,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1853 default_var.xres_virtual = viafb_second_xres; 1854 default_var.xres_virtual = viafb_second_xres;
1854 default_var.yres_virtual = viafb_second_yres; 1855 default_var.yres_virtual = viafb_second_yres;
1855 default_var.bits_per_pixel = viafb_bpp1; 1856 default_var.bits_per_pixel = viafb_bpp1;
1856 viafb_fill_var_timing_info(&default_var, viafb_get_refresh( 1857 viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
1857 default_var.xres, default_var.yres, viafb_refresh1), 1858 default_var.xres, default_var.yres, viafb_refresh1));
1858 viafb_get_mode(default_var.xres, default_var.yres));
1859 1859
1860 viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); 1860 viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
1861 viafb_check_var(&default_var, viafbinfo1); 1861 viafb_check_var(&default_var, viafbinfo1);
@@ -1950,61 +1950,67 @@ static int __init viafb_setup(void)
1950 if (!*this_opt) 1950 if (!*this_opt)
1951 continue; 1951 continue;
1952 1952
1953 if (!strncmp(this_opt, "viafb_mode1=", 12)) 1953 if (!strncmp(this_opt, "viafb_mode1=", 12)) {
1954 viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL); 1954 viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
1955 else if (!strncmp(this_opt, "viafb_mode=", 11)) 1955 } else if (!strncmp(this_opt, "viafb_mode=", 11)) {
1956 viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL); 1956 viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
1957 else if (!strncmp(this_opt, "viafb_bpp1=", 11)) 1957 } else if (!strncmp(this_opt, "viafb_bpp1=", 11)) {
1958 strict_strtoul(this_opt + 11, 0, 1958 if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0)
1959 (unsigned long *)&viafb_bpp1); 1959 return -EINVAL;
1960 else if (!strncmp(this_opt, "viafb_bpp=", 10)) 1960 } else if (!strncmp(this_opt, "viafb_bpp=", 10)) {
1961 strict_strtoul(this_opt + 10, 0, 1961 if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0)
1962 (unsigned long *)&viafb_bpp); 1962 return -EINVAL;
1963 else if (!strncmp(this_opt, "viafb_refresh1=", 15)) 1963 } else if (!strncmp(this_opt, "viafb_refresh1=", 15)) {
1964 strict_strtoul(this_opt + 15, 0, 1964 if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0)
1965 (unsigned long *)&viafb_refresh1); 1965 return -EINVAL;
1966 else if (!strncmp(this_opt, "viafb_refresh=", 14)) 1966 } else if (!strncmp(this_opt, "viafb_refresh=", 14)) {
1967 strict_strtoul(this_opt + 14, 0, 1967 if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0)
1968 (unsigned long *)&viafb_refresh); 1968 return -EINVAL;
1969 else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) 1969 } else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) {
1970 strict_strtoul(this_opt + 21, 0, 1970 if (kstrtoint(this_opt + 21, 0,
1971 (unsigned long *)&viafb_lcd_dsp_method); 1971 &viafb_lcd_dsp_method) < 0)
1972 else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) 1972 return -EINVAL;
1973 strict_strtoul(this_opt + 19, 0, 1973 } else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) {
1974 (unsigned long *)&viafb_lcd_panel_id); 1974 if (kstrtoint(this_opt + 19, 0,
1975 else if (!strncmp(this_opt, "viafb_accel=", 12)) 1975 &viafb_lcd_panel_id) < 0)
1976 strict_strtoul(this_opt + 12, 0, 1976 return -EINVAL;
1977 (unsigned long *)&viafb_accel); 1977 } else if (!strncmp(this_opt, "viafb_accel=", 12)) {
1978 else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) 1978 if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0)
1979 strict_strtoul(this_opt + 14, 0, 1979 return -EINVAL;
1980 (unsigned long *)&viafb_SAMM_ON); 1980 } else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) {
1981 else if (!strncmp(this_opt, "viafb_active_dev=", 17)) 1981 if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0)
1982 return -EINVAL;
1983 } else if (!strncmp(this_opt, "viafb_active_dev=", 17)) {
1982 viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL); 1984 viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
1983 else if (!strncmp(this_opt, 1985 } else if (!strncmp(this_opt,
1984 "viafb_display_hardware_layout=", 30)) 1986 "viafb_display_hardware_layout=", 30)) {
1985 strict_strtoul(this_opt + 30, 0, 1987 if (kstrtoint(this_opt + 30, 0,
1986 (unsigned long *)&viafb_display_hardware_layout); 1988 &viafb_display_hardware_layout) < 0)
1987 else if (!strncmp(this_opt, "viafb_second_size=", 18)) 1989 return -EINVAL;
1988 strict_strtoul(this_opt + 18, 0, 1990 } else if (!strncmp(this_opt, "viafb_second_size=", 18)) {
1989 (unsigned long *)&viafb_second_size); 1991 if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0)
1990 else if (!strncmp(this_opt, 1992 return -EINVAL;
1991 "viafb_platform_epia_dvi=", 24)) 1993 } else if (!strncmp(this_opt,
1992 strict_strtoul(this_opt + 24, 0, 1994 "viafb_platform_epia_dvi=", 24)) {
1993 (unsigned long *)&viafb_platform_epia_dvi); 1995 if (kstrtoint(this_opt + 24, 0,
1994 else if (!strncmp(this_opt, 1996 &viafb_platform_epia_dvi) < 0)
1995 "viafb_device_lcd_dualedge=", 26)) 1997 return -EINVAL;
1996 strict_strtoul(this_opt + 26, 0, 1998 } else if (!strncmp(this_opt,
1997 (unsigned long *)&viafb_device_lcd_dualedge); 1999 "viafb_device_lcd_dualedge=", 26)) {
1998 else if (!strncmp(this_opt, "viafb_bus_width=", 16)) 2000 if (kstrtoint(this_opt + 26, 0,
1999 strict_strtoul(this_opt + 16, 0, 2001 &viafb_device_lcd_dualedge) < 0)
2000 (unsigned long *)&viafb_bus_width); 2002 return -EINVAL;
2001 else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) 2003 } else if (!strncmp(this_opt, "viafb_bus_width=", 16)) {
2002 strict_strtoul(this_opt + 15, 0, 2004 if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0)
2003 (unsigned long *)&viafb_lcd_mode); 2005 return -EINVAL;
2004 else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) 2006 } else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) {
2007 if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0)
2008 return -EINVAL;
2009 } else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) {
2005 viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL); 2010 viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
2006 else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) 2011 } else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) {
2007 viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL); 2012 viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
2013 }
2008 } 2014 }
2009 return 0; 2015 return 0;
2010} 2016}
@@ -2028,9 +2034,9 @@ int __init viafb_init(void)
2028 return r; 2034 return r;
2029#endif 2035#endif
2030 if (parse_mode(viafb_mode, &dummy_x, &dummy_y) 2036 if (parse_mode(viafb_mode, &dummy_x, &dummy_y)
2031 || !viafb_get_mode(dummy_x, dummy_y) 2037 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh)
2032 || parse_mode(viafb_mode1, &dummy_x, &dummy_y) 2038 || parse_mode(viafb_mode1, &dummy_x, &dummy_y)
2033 || !viafb_get_mode(dummy_x, dummy_y) 2039 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1)
2034 || viafb_bpp < 0 || viafb_bpp > 32 2040 || viafb_bpp < 0 || viafb_bpp > 32
2035 || viafb_bpp1 < 0 || viafb_bpp1 > 32 2041 || viafb_bpp1 < 0 || viafb_bpp1 > 32
2036 || parse_active_dev()) 2042 || parse_active_dev())
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 58df74e1417..0911cac1b2f 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -281,7 +281,7 @@ static struct crt_mode_table CRTM640x480[] = {
281 /*r_rate,hsp,vsp */ 281 /*r_rate,hsp,vsp */
282 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 282 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
283 {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP, 283 {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP,
284 {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} }, 284 {800, 640, 640, 160, 656, 96, 525, 480, 480, 45, 490, 2} },
285 {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP, 285 {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP,
286 {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} }, 286 {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} },
287 {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP, 287 {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP,
@@ -863,26 +863,56 @@ int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
863int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); 863int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
864 864
865 865
866struct VideoModeTable *viafb_get_mode(int hres, int vres) 866static struct VideoModeTable *get_modes(struct VideoModeTable *vmt, int n,
867 int hres, int vres)
867{ 868{
868 u32 i; 869 int i;
869 for (i = 0; i < ARRAY_SIZE(viafb_modes); i++) 870
870 if (viafb_modes[i].mode_array && 871 for (i = 0; i < n; i++)
871 viafb_modes[i].crtc[0].crtc.hor_addr == hres && 872 if (vmt[i].mode_array &&
872 viafb_modes[i].crtc[0].crtc.ver_addr == vres) 873 vmt[i].crtc[0].crtc.hor_addr == hres &&
874 vmt[i].crtc[0].crtc.ver_addr == vres)
873 return &viafb_modes[i]; 875 return &viafb_modes[i];
874 876
875 return NULL; 877 return NULL;
876} 878}
877 879
878struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) 880static struct crt_mode_table *get_best_mode(struct VideoModeTable *vmt,
881 int refresh)
879{ 882{
880 u32 i; 883 struct crt_mode_table *best;
881 for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++) 884 int i;
882 if (viafb_rb_modes[i].mode_array &&
883 viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres &&
884 viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres)
885 return &viafb_rb_modes[i];
886 885
887 return NULL; 886 if (!vmt)
887 return NULL;
888
889 best = &vmt->crtc[0];
890 for (i = 1; i < vmt->mode_array; i++) {
891 if (abs(vmt->crtc[i].refresh_rate - refresh)
892 < abs(best->refresh_rate - refresh))
893 best = &vmt->crtc[i];
894 }
895
896 return best;
897}
898
899static struct VideoModeTable *viafb_get_mode(int hres, int vres)
900{
901 return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres);
902}
903
904struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh)
905{
906 return get_best_mode(viafb_get_mode(hres, vres), refresh);
907}
908
909static struct VideoModeTable *viafb_get_rb_mode(int hres, int vres)
910{
911 return get_modes(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes), hres,
912 vres);
913}
914
915struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh)
916{
917 return get_best_mode(viafb_get_rb_mode(hres, vres), refresh);
888} 918}
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index 3751289eb45..5917a2b00e1 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -60,7 +60,7 @@ extern struct io_reg PM1024x768[];
60extern struct patch_table res_patch_table[]; 60extern struct patch_table res_patch_table[];
61extern struct VPITTable VPIT; 61extern struct VPITTable VPIT;
62 62
63struct VideoModeTable *viafb_get_mode(int hres, int vres); 63struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh);
64struct VideoModeTable *viafb_get_rb_mode(int hres, int vres); 64struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh);
65 65
66#endif /* __VIAMODE_H__ */ 66#endif /* __VIAMODE_H__ */
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
index 0e120d67eb6..777c21dd7a6 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/vt8500lcdfb.c
@@ -210,8 +210,8 @@ static int vt8500lcd_pan_display(struct fb_var_screeninfo *var,
210 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info); 210 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
211 211
212 writel((1 << 31) 212 writel((1 << 31)
213 | (((var->xres_virtual - var->xres) * pixlen / 4) << 20) 213 | (((info->var.xres_virtual - info->var.xres) * pixlen / 4) << 20)
214 | (off >> 2), fbi->regbase + 0x20); 214 | (off >> 2), fbi->regbase + 0x20);
215 return 0; 215 return 0;
216} 216}
217 217
@@ -355,7 +355,7 @@ static int __devinit vt8500lcd_probe(struct platform_device *pdev)
355 goto failed_free_palette; 355 goto failed_free_palette;
356 } 356 }
357 357
358 ret = request_irq(irq, vt8500lcd_handle_irq, IRQF_DISABLED, "LCD", fbi); 358 ret = request_irq(irq, vt8500lcd_handle_irq, 0, "LCD", fbi);
359 if (ret) { 359 if (ret) {
360 dev_err(&pdev->dev, "request_irq failed: %d\n", ret); 360 dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
361 ret = -EBUSY; 361 ret = -EBUSY;
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index f9b3e3dc242..4e74d262cf3 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -620,13 +620,14 @@ static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *i
620 unsigned int offset; 620 unsigned int offset;
621 621
622 /* Calculate the offset */ 622 /* Calculate the offset */
623 if (var->bits_per_pixel == 0) { 623 if (info->var.bits_per_pixel == 0) {
624 offset = (var->yoffset / 16) * var->xres_virtual + var->xoffset; 624 offset = (var->yoffset / 16) * info->var.xres_virtual
625 + var->xoffset;
625 offset = offset >> 3; 626 offset = offset >> 3;
626 } else { 627 } else {
627 offset = (var->yoffset * info->fix.line_length) + 628 offset = (var->yoffset * info->fix.line_length) +
628 (var->xoffset * var->bits_per_pixel / 8); 629 (var->xoffset * info->var.bits_per_pixel / 8);
629 offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 1); 630 offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 1);
630 } 631 }
631 632
632 /* Set the offset */ 633 /* Set the offset */
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 77dea015ff6..fcb6cd90f64 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -23,7 +23,6 @@
23#include <linux/device.h> 23#include <linux/device.h>
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/version.h>
27#include <linux/errno.h> 26#include <linux/errno.h>
28#include <linux/string.h> 27#include <linux/string.h>
29#include <linux/mm.h> 28#include <linux/mm.h>