diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-25 11:42:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-25 11:42:37 -0400 |
commit | 0f1493a60167cf6333626456d3fc8aff4e6fa237 (patch) | |
tree | 3b46a263bbab4fd396f01f35f0ceca7f3b063163 /drivers/video | |
parent | 023bc8e75f8cf9e4da8411154be22a4f809d3314 (diff) | |
parent | 087faf77a57b06f9a8ce37781c68e3f02468322b (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6: (126 commits)
sh_mobile_meram: Safely disable MERAM operation when not initialized
video: mb862xxfb: add support for L1 displaying
video: mb862xx: add support for controller's I2C bus adapter
video: mb862xxfb: relocate register space to get contiguous vram
video: mb862xxfb: use pre-initialized configuration for PCI GDCs
video: mb862xxfb: correct fix.smem_len field initialization
video: s3c-fb: correct transparency checking in 32bpp
video: s3c-fb: add gpio setup function to resume function
fbdev/amifb: Remove superfluous alignment of frame buffer memory
fbdev/amifb: Do not call panic() if there's not enough Chip RAM
fbdev/amifb: Correct check for video memory size
video: mb862xxfb: Require either FB_MB862XX_PCI_GDC or FB_MB862XX_LIME
video: s3c-fb: add window variant information for S5P
video: s3c-fb: add additional validate bpps
video: s3c-fb: correct window osd size offset values
udlfb: include prefetch.h explicitly
drivers/video/s3c2410fb.c: Convert release_resource to release_mem_region
drivers/video/sm501fb.c: Convert release_resource to release_mem_region
drivers/video: Convert release_resource to release_mem_region
video, udlfb: Fix two build warnings about 'ignoring return value'
...
Diffstat (limited to 'drivers/video')
59 files changed, 6520 insertions, 2176 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index f9916ca5ca4d..549b960667c8 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1460,6 +1460,14 @@ config FB_S3 | |||
1460 | ---help--- | 1460 | ---help--- |
1461 | Driver for graphics boards with S3 Trio / S3 Virge chip. | 1461 | Driver for graphics boards with S3 Trio / S3 Virge chip. |
1462 | 1462 | ||
1463 | config FB_S3_DDC | ||
1464 | bool "DDC for S3 support" | ||
1465 | depends on FB_S3 | ||
1466 | select FB_DDC | ||
1467 | default y | ||
1468 | help | ||
1469 | Say Y here if you want DDC support for your S3 graphics card. | ||
1470 | |||
1463 | config FB_SAVAGE | 1471 | config FB_SAVAGE |
1464 | tristate "S3 Savage support" | 1472 | tristate "S3 Savage support" |
1465 | depends on FB && PCI && EXPERIMENTAL | 1473 | depends on FB && PCI && EXPERIMENTAL |
@@ -1983,6 +1991,18 @@ config FB_SH_MOBILE_HDMI | |||
1983 | ---help--- | 1991 | ---help--- |
1984 | Driver for the on-chip SH-Mobile HDMI controller. | 1992 | Driver for the on-chip SH-Mobile HDMI controller. |
1985 | 1993 | ||
1994 | config FB_SH_MOBILE_MERAM | ||
1995 | tristate "SuperH Mobile MERAM read ahead support for LCDC" | ||
1996 | depends on FB_SH_MOBILE_LCDC | ||
1997 | default y | ||
1998 | ---help--- | ||
1999 | Enable MERAM support for the SH-Mobile LCD controller. | ||
2000 | |||
2001 | This will allow for caching of the framebuffer to provide more | ||
2002 | reliable access under heavy main memory bus traffic situations. | ||
2003 | Up to 4 memory channels can be configured, allowing 4 RGB or | ||
2004 | 2 YCbCr framebuffers to be configured. | ||
2005 | |||
1986 | config FB_TMIO | 2006 | config FB_TMIO |
1987 | tristate "Toshiba Mobile IO FrameBuffer support" | 2007 | tristate "Toshiba Mobile IO FrameBuffer support" |
1988 | depends on FB && MFD_CORE | 2008 | depends on FB && MFD_CORE |
@@ -2246,29 +2266,43 @@ config FB_METRONOME | |||
2246 | config FB_MB862XX | 2266 | config FB_MB862XX |
2247 | tristate "Fujitsu MB862xx GDC support" | 2267 | tristate "Fujitsu MB862xx GDC support" |
2248 | depends on FB | 2268 | depends on FB |
2269 | depends on PCI || (OF && PPC) | ||
2249 | select FB_CFB_FILLRECT | 2270 | select FB_CFB_FILLRECT |
2250 | select FB_CFB_COPYAREA | 2271 | select FB_CFB_COPYAREA |
2251 | select FB_CFB_IMAGEBLIT | 2272 | select FB_CFB_IMAGEBLIT |
2252 | ---help--- | 2273 | ---help--- |
2253 | Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers. | 2274 | Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers. |
2254 | 2275 | ||
2276 | choice | ||
2277 | prompt "GDC variant" | ||
2278 | depends on FB_MB862XX | ||
2279 | |||
2255 | config FB_MB862XX_PCI_GDC | 2280 | config FB_MB862XX_PCI_GDC |
2256 | bool "Carmine/Coral-P(A) GDC" | 2281 | bool "Carmine/Coral-P(A) GDC" |
2257 | depends on PCI && FB_MB862XX | 2282 | depends on PCI |
2258 | ---help--- | 2283 | ---help--- |
2259 | This enables framebuffer support for Fujitsu Carmine/Coral-P(A) | 2284 | This enables framebuffer support for Fujitsu Carmine/Coral-P(A) |
2260 | PCI graphics controller devices. | 2285 | PCI graphics controller devices. |
2261 | 2286 | ||
2262 | config FB_MB862XX_LIME | 2287 | config FB_MB862XX_LIME |
2263 | bool "Lime GDC" | 2288 | bool "Lime GDC" |
2264 | depends on FB_MB862XX | 2289 | depends on OF && PPC |
2265 | depends on OF && !FB_MB862XX_PCI_GDC | ||
2266 | depends on PPC | ||
2267 | select FB_FOREIGN_ENDIAN | 2290 | select FB_FOREIGN_ENDIAN |
2268 | select FB_LITTLE_ENDIAN | 2291 | select FB_LITTLE_ENDIAN |
2269 | ---help--- | 2292 | ---help--- |
2270 | Framebuffer support for Fujitsu Lime GDC on host CPU bus. | 2293 | Framebuffer support for Fujitsu Lime GDC on host CPU bus. |
2271 | 2294 | ||
2295 | endchoice | ||
2296 | |||
2297 | config FB_MB862XX_I2C | ||
2298 | bool "Support I2C bus on MB862XX GDC" | ||
2299 | depends on FB_MB862XX && I2C | ||
2300 | default y | ||
2301 | help | ||
2302 | Selecting this option adds Coral-P(A)/Lime GDC I2C bus adapter | ||
2303 | driver to support accessing I2C devices on controller's I2C bus. | ||
2304 | These are usually some video decoder chips. | ||
2305 | |||
2272 | config FB_EP93XX | 2306 | config FB_EP93XX |
2273 | tristate "EP93XX frame buffer support" | 2307 | tristate "EP93XX frame buffer support" |
2274 | depends on FB && ARCH_EP93XX | 2308 | depends on FB && ARCH_EP93XX |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 2ea44b6625fe..8b83129e209c 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -130,6 +130,7 @@ obj-$(CONFIG_FB_UDL) += udlfb.o | |||
130 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o | 130 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o |
131 | obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o | 131 | obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o |
132 | obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o | 132 | obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o |
133 | obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o | ||
133 | obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o | 134 | obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o |
134 | obj-$(CONFIG_FB_OMAP) += omap/ | 135 | obj-$(CONFIG_FB_OMAP) += omap/ |
135 | obj-y += omap2/ | 136 | obj-y += omap2/ |
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index e5d6b56d4447..5ea6596dd824 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c | |||
@@ -2224,22 +2224,23 @@ static int amifb_ioctl(struct fb_info *info, | |||
2224 | * Allocate, Clear and Align a Block of Chip Memory | 2224 | * Allocate, Clear and Align a Block of Chip Memory |
2225 | */ | 2225 | */ |
2226 | 2226 | ||
2227 | static u_long unaligned_chipptr = 0; | 2227 | static void *aligned_chipptr; |
2228 | 2228 | ||
2229 | static inline u_long __init chipalloc(u_long size) | 2229 | static inline u_long __init chipalloc(u_long size) |
2230 | { | 2230 | { |
2231 | size += PAGE_SIZE-1; | 2231 | aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]"); |
2232 | if (!(unaligned_chipptr = (u_long)amiga_chip_alloc(size, | 2232 | if (!aligned_chipptr) { |
2233 | "amifb [RAM]"))) | 2233 | pr_err("amifb: No Chip RAM for frame buffer"); |
2234 | panic("No Chip RAM for frame buffer"); | 2234 | return 0; |
2235 | memset((void *)unaligned_chipptr, 0, size); | 2235 | } |
2236 | return PAGE_ALIGN(unaligned_chipptr); | 2236 | memset(aligned_chipptr, 0, size); |
2237 | return (u_long)aligned_chipptr; | ||
2237 | } | 2238 | } |
2238 | 2239 | ||
2239 | static inline void chipfree(void) | 2240 | static inline void chipfree(void) |
2240 | { | 2241 | { |
2241 | if (unaligned_chipptr) | 2242 | if (aligned_chipptr) |
2242 | amiga_chip_free((void *)unaligned_chipptr); | 2243 | amiga_chip_free(aligned_chipptr); |
2243 | } | 2244 | } |
2244 | 2245 | ||
2245 | 2246 | ||
@@ -2295,7 +2296,7 @@ default_chipset: | |||
2295 | defmode = amiga_vblank == 50 ? DEFMODE_PAL | 2296 | defmode = amiga_vblank == 50 ? DEFMODE_PAL |
2296 | : DEFMODE_NTSC; | 2297 | : DEFMODE_NTSC; |
2297 | if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > | 2298 | if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > |
2298 | VIDEOMEMSIZE_ECS_1M) | 2299 | VIDEOMEMSIZE_ECS_2M) |
2299 | fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M; | 2300 | fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M; |
2300 | else | 2301 | else |
2301 | fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M; | 2302 | fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M; |
@@ -2312,7 +2313,7 @@ default_chipset: | |||
2312 | maxfmode = TAG_FMODE_4; | 2313 | maxfmode = TAG_FMODE_4; |
2313 | defmode = DEFMODE_AGA; | 2314 | defmode = DEFMODE_AGA; |
2314 | if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > | 2315 | if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > |
2315 | VIDEOMEMSIZE_AGA_1M) | 2316 | VIDEOMEMSIZE_AGA_2M) |
2316 | fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M; | 2317 | fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M; |
2317 | else | 2318 | else |
2318 | fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M; | 2319 | fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M; |
@@ -2385,6 +2386,10 @@ default_chipset: | |||
2385 | DUMMYSPRITEMEMSIZE+ | 2386 | DUMMYSPRITEMEMSIZE+ |
2386 | COPINITSIZE+ | 2387 | COPINITSIZE+ |
2387 | 4*COPLISTSIZE); | 2388 | 4*COPLISTSIZE); |
2389 | if (!chipptr) { | ||
2390 | err = -ENOMEM; | ||
2391 | goto amifb_error; | ||
2392 | } | ||
2388 | 2393 | ||
2389 | assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len); | 2394 | assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len); |
2390 | assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE); | 2395 | assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE); |
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 8b7d47386f39..fcdac872522d 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c | |||
@@ -899,7 +899,7 @@ static struct fb_ops da8xx_fb_ops = { | |||
899 | .fb_blank = cfb_blank, | 899 | .fb_blank = cfb_blank, |
900 | }; | 900 | }; |
901 | 901 | ||
902 | static int __init fb_probe(struct platform_device *device) | 902 | static int __devinit fb_probe(struct platform_device *device) |
903 | { | 903 | { |
904 | struct da8xx_lcdc_platform_data *fb_pdata = | 904 | struct da8xx_lcdc_platform_data *fb_pdata = |
905 | device->dev.platform_data; | 905 | device->dev.platform_data; |
@@ -1165,7 +1165,7 @@ static int fb_resume(struct platform_device *dev) | |||
1165 | 1165 | ||
1166 | static struct platform_driver da8xx_fb_driver = { | 1166 | static struct platform_driver da8xx_fb_driver = { |
1167 | .probe = fb_probe, | 1167 | .probe = fb_probe, |
1168 | .remove = fb_remove, | 1168 | .remove = __devexit_p(fb_remove), |
1169 | .suspend = fb_suspend, | 1169 | .suspend = fb_suspend, |
1170 | .resume = fb_resume, | 1170 | .resume = fb_resume, |
1171 | .driver = { | 1171 | .driver = { |
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 4eb38db36e4b..fb205843c2c7 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c | |||
@@ -242,9 +242,9 @@ static int set_system(const struct dmi_system_id *id) | |||
242 | return 0; | 242 | return 0; |
243 | } | 243 | } |
244 | 244 | ||
245 | printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " | 245 | printk(KERN_INFO "efifb: dmi detected %s - framebuffer at 0x%08x " |
246 | "(%dx%d, stride %d)\n", id->ident, | 246 | "(%dx%d, stride %d)\n", id->ident, |
247 | (void *)screen_info.lfb_base, screen_info.lfb_width, | 247 | screen_info.lfb_base, screen_info.lfb_width, |
248 | screen_info.lfb_height, screen_info.lfb_linelength); | 248 | screen_info.lfb_height, screen_info.lfb_linelength); |
249 | 249 | ||
250 | 250 | ||
diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile index d7777714166b..5707ed0e31a7 100644 --- a/drivers/video/mb862xx/Makefile +++ b/drivers/video/mb862xx/Makefile | |||
@@ -2,4 +2,7 @@ | |||
2 | # Makefile for the MB862xx framebuffer driver | 2 | # Makefile for the MB862xx framebuffer driver |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_FB_MB862XX) := mb862xxfb.o mb862xxfb_accel.o | 5 | obj-$(CONFIG_FB_MB862XX) += mb862xxfb.o |
6 | |||
7 | mb862xxfb-y := mb862xxfbdrv.o mb862xxfb_accel.o | ||
8 | mb862xxfb-$(CONFIG_FB_MB862XX_I2C) += mb862xx-i2c.o | ||
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c new file mode 100644 index 000000000000..cb77d3b4657d --- /dev/null +++ b/drivers/video/mb862xx/mb862xx-i2c.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Coral-P(A)/Lime I2C adapter driver | ||
3 | * | ||
4 | * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/fb.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/io.h> | ||
15 | |||
16 | #include "mb862xxfb.h" | ||
17 | #include "mb862xx_reg.h" | ||
18 | |||
19 | static int mb862xx_i2c_wait_event(struct i2c_adapter *adap) | ||
20 | { | ||
21 | struct mb862xxfb_par *par = adap->algo_data; | ||
22 | u32 reg; | ||
23 | |||
24 | do { | ||
25 | udelay(1); | ||
26 | reg = inreg(i2c, GC_I2C_BCR); | ||
27 | if (reg & (I2C_INT | I2C_BER)) | ||
28 | break; | ||
29 | } while (1); | ||
30 | |||
31 | return (reg & I2C_BER) ? 0 : 1; | ||
32 | } | ||
33 | |||
34 | static int mb862xx_i2c_do_address(struct i2c_adapter *adap, int addr) | ||
35 | { | ||
36 | struct mb862xxfb_par *par = adap->algo_data; | ||
37 | |||
38 | outreg(i2c, GC_I2C_DAR, addr); | ||
39 | outreg(i2c, GC_I2C_CCR, I2C_CLOCK_AND_ENABLE); | ||
40 | outreg(i2c, GC_I2C_BCR, par->i2c_rs ? I2C_REPEATED_START : I2C_START); | ||
41 | if (!mb862xx_i2c_wait_event(adap)) | ||
42 | return -EIO; | ||
43 | par->i2c_rs = !(inreg(i2c, GC_I2C_BSR) & I2C_LRB); | ||
44 | return par->i2c_rs; | ||
45 | } | ||
46 | |||
47 | static int mb862xx_i2c_write_byte(struct i2c_adapter *adap, u8 byte) | ||
48 | { | ||
49 | struct mb862xxfb_par *par = adap->algo_data; | ||
50 | |||
51 | outreg(i2c, GC_I2C_DAR, byte); | ||
52 | outreg(i2c, GC_I2C_BCR, I2C_START); | ||
53 | if (!mb862xx_i2c_wait_event(adap)) | ||
54 | return -EIO; | ||
55 | return !(inreg(i2c, GC_I2C_BSR) & I2C_LRB); | ||
56 | } | ||
57 | |||
58 | static int mb862xx_i2c_read_byte(struct i2c_adapter *adap, u8 *byte, int last) | ||
59 | { | ||
60 | struct mb862xxfb_par *par = adap->algo_data; | ||
61 | |||
62 | outreg(i2c, GC_I2C_BCR, I2C_START | (last ? 0 : I2C_ACK)); | ||
63 | if (!mb862xx_i2c_wait_event(adap)) | ||
64 | return 0; | ||
65 | *byte = inreg(i2c, GC_I2C_DAR); | ||
66 | return 1; | ||
67 | } | ||
68 | |||
69 | void mb862xx_i2c_stop(struct i2c_adapter *adap) | ||
70 | { | ||
71 | struct mb862xxfb_par *par = adap->algo_data; | ||
72 | |||
73 | outreg(i2c, GC_I2C_BCR, I2C_STOP); | ||
74 | outreg(i2c, GC_I2C_CCR, I2C_DISABLE); | ||
75 | par->i2c_rs = 0; | ||
76 | } | ||
77 | |||
78 | static int mb862xx_i2c_read(struct i2c_adapter *adap, struct i2c_msg *m) | ||
79 | { | ||
80 | int i, ret = 0; | ||
81 | int last = m->len - 1; | ||
82 | |||
83 | for (i = 0; i < m->len; i++) { | ||
84 | if (!mb862xx_i2c_read_byte(adap, &m->buf[i], i == last)) { | ||
85 | ret = -EIO; | ||
86 | break; | ||
87 | } | ||
88 | } | ||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | static int mb862xx_i2c_write(struct i2c_adapter *adap, struct i2c_msg *m) | ||
93 | { | ||
94 | int i, ret = 0; | ||
95 | |||
96 | for (i = 0; i < m->len; i++) { | ||
97 | if (!mb862xx_i2c_write_byte(adap, m->buf[i])) { | ||
98 | ret = -EIO; | ||
99 | break; | ||
100 | } | ||
101 | } | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | static int mb862xx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, | ||
106 | int num) | ||
107 | { | ||
108 | struct mb862xxfb_par *par = adap->algo_data; | ||
109 | struct i2c_msg *m; | ||
110 | int addr; | ||
111 | int i = 0, err = 0; | ||
112 | |||
113 | dev_dbg(par->dev, "%s: %d msgs\n", __func__, num); | ||
114 | |||
115 | for (i = 0; i < num; i++) { | ||
116 | m = &msgs[i]; | ||
117 | if (!m->len) { | ||
118 | dev_dbg(par->dev, "%s: null msgs\n", __func__); | ||
119 | continue; | ||
120 | } | ||
121 | addr = m->addr; | ||
122 | if (m->flags & I2C_M_RD) | ||
123 | addr |= 1; | ||
124 | |||
125 | err = mb862xx_i2c_do_address(adap, addr); | ||
126 | if (err < 0) | ||
127 | break; | ||
128 | if (m->flags & I2C_M_RD) | ||
129 | err = mb862xx_i2c_read(adap, m); | ||
130 | else | ||
131 | err = mb862xx_i2c_write(adap, m); | ||
132 | } | ||
133 | |||
134 | if (i) | ||
135 | mb862xx_i2c_stop(adap); | ||
136 | |||
137 | return (err < 0) ? err : i; | ||
138 | } | ||
139 | |||
140 | static u32 mb862xx_func(struct i2c_adapter *adap) | ||
141 | { | ||
142 | return I2C_FUNC_SMBUS_BYTE_DATA; | ||
143 | } | ||
144 | |||
145 | static const struct i2c_algorithm mb862xx_algo = { | ||
146 | .master_xfer = mb862xx_xfer, | ||
147 | .functionality = mb862xx_func, | ||
148 | }; | ||
149 | |||
150 | static struct i2c_adapter mb862xx_i2c_adapter = { | ||
151 | .name = "MB862xx I2C adapter", | ||
152 | .algo = &mb862xx_algo, | ||
153 | .owner = THIS_MODULE, | ||
154 | }; | ||
155 | |||
156 | int mb862xx_i2c_init(struct mb862xxfb_par *par) | ||
157 | { | ||
158 | int ret; | ||
159 | |||
160 | mb862xx_i2c_adapter.algo_data = par; | ||
161 | par->adap = &mb862xx_i2c_adapter; | ||
162 | |||
163 | ret = i2c_add_adapter(par->adap); | ||
164 | if (ret < 0) { | ||
165 | dev_err(par->dev, "failed to add %s\n", | ||
166 | mb862xx_i2c_adapter.name); | ||
167 | } | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | void mb862xx_i2c_exit(struct mb862xxfb_par *par) | ||
172 | { | ||
173 | if (par->adap) { | ||
174 | i2c_del_adapter(par->adap); | ||
175 | par->adap = NULL; | ||
176 | } | ||
177 | } | ||
diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/mb862xx/mb862xx_reg.h index 2ba65e118500..9df48b8edc94 100644 --- a/drivers/video/mb862xx/mb862xx_reg.h +++ b/drivers/video/mb862xx/mb862xx_reg.h | |||
@@ -5,11 +5,8 @@ | |||
5 | #ifndef _MB862XX_REG_H | 5 | #ifndef _MB862XX_REG_H |
6 | #define _MB862XX_REG_H | 6 | #define _MB862XX_REG_H |
7 | 7 | ||
8 | #ifdef MB862XX_MMIO_BOTTOM | ||
9 | #define MB862XX_MMIO_BASE 0x03fc0000 | ||
10 | #else | ||
11 | #define MB862XX_MMIO_BASE 0x01fc0000 | 8 | #define MB862XX_MMIO_BASE 0x01fc0000 |
12 | #endif | 9 | #define MB862XX_MMIO_HIGH_BASE 0x03fc0000 |
13 | #define MB862XX_I2C_BASE 0x0000c000 | 10 | #define MB862XX_I2C_BASE 0x0000c000 |
14 | #define MB862XX_DISP_BASE 0x00010000 | 11 | #define MB862XX_DISP_BASE 0x00010000 |
15 | #define MB862XX_CAP_BASE 0x00018000 | 12 | #define MB862XX_CAP_BASE 0x00018000 |
@@ -23,6 +20,7 @@ | |||
23 | #define GC_IMASK 0x00000024 | 20 | #define GC_IMASK 0x00000024 |
24 | #define GC_SRST 0x0000002c | 21 | #define GC_SRST 0x0000002c |
25 | #define GC_CCF 0x00000038 | 22 | #define GC_CCF 0x00000038 |
23 | #define GC_RSW 0x0000005c | ||
26 | #define GC_CID 0x000000f0 | 24 | #define GC_CID 0x000000f0 |
27 | #define GC_REVISION 0x00000084 | 25 | #define GC_REVISION 0x00000084 |
28 | 26 | ||
@@ -53,10 +51,16 @@ | |||
53 | #define GC_L0OA0 0x00000024 | 51 | #define GC_L0OA0 0x00000024 |
54 | #define GC_L0DA0 0x00000028 | 52 | #define GC_L0DA0 0x00000028 |
55 | #define GC_L0DY_L0DX 0x0000002c | 53 | #define GC_L0DY_L0DX 0x0000002c |
54 | #define GC_L1M 0x00000030 | ||
55 | #define GC_L1DA 0x00000034 | ||
56 | #define GC_DCM1 0x00000100 | 56 | #define GC_DCM1 0x00000100 |
57 | #define GC_L0EM 0x00000110 | 57 | #define GC_L0EM 0x00000110 |
58 | #define GC_L0WY_L0WX 0x00000114 | 58 | #define GC_L0WY_L0WX 0x00000114 |
59 | #define GC_L0WH_L0WW 0x00000118 | 59 | #define GC_L0WH_L0WW 0x00000118 |
60 | #define GC_L1EM 0x00000120 | ||
61 | #define GC_L1WY_L1WX 0x00000124 | ||
62 | #define GC_L1WH_L1WW 0x00000128 | ||
63 | #define GC_DLS 0x00000180 | ||
60 | #define GC_DCM2 0x00000104 | 64 | #define GC_DCM2 0x00000104 |
61 | #define GC_DCM3 0x00000108 | 65 | #define GC_DCM3 0x00000108 |
62 | #define GC_CPM_CUTC 0x000000a0 | 66 | #define GC_CPM_CUTC 0x000000a0 |
@@ -68,6 +72,11 @@ | |||
68 | 72 | ||
69 | #define GC_CPM_CEN0 0x00100000 | 73 | #define GC_CPM_CEN0 0x00100000 |
70 | #define GC_CPM_CEN1 0x00200000 | 74 | #define GC_CPM_CEN1 0x00200000 |
75 | #define GC_DCM1_DEN 0x80000000 | ||
76 | #define GC_DCM1_L1E 0x00020000 | ||
77 | #define GC_L1M_16 0x80000000 | ||
78 | #define GC_L1M_YC 0x40000000 | ||
79 | #define GC_L1M_CS 0x20000000 | ||
71 | 80 | ||
72 | #define GC_DCM01_ESY 0x00000004 | 81 | #define GC_DCM01_ESY 0x00000004 |
73 | #define GC_DCM01_SC 0x00003f00 | 82 | #define GC_DCM01_SC 0x00003f00 |
@@ -79,9 +88,50 @@ | |||
79 | #define GC_L0M_L0C_16 0x80000000 | 88 | #define GC_L0M_L0C_16 0x80000000 |
80 | #define GC_L0EM_L0EC_24 0x40000000 | 89 | #define GC_L0EM_L0EC_24 0x40000000 |
81 | #define GC_L0M_L0W_UNIT 64 | 90 | #define GC_L0M_L0W_UNIT 64 |
91 | #define GC_L1EM_DM 0x02000000 | ||
82 | 92 | ||
83 | #define GC_DISP_REFCLK_400 400 | 93 | #define GC_DISP_REFCLK_400 400 |
84 | 94 | ||
95 | /* I2C */ | ||
96 | #define GC_I2C_BSR 0x00000000 /* BSR */ | ||
97 | #define GC_I2C_BCR 0x00000004 /* BCR */ | ||
98 | #define GC_I2C_CCR 0x00000008 /* CCR */ | ||
99 | #define GC_I2C_ADR 0x0000000C /* ADR */ | ||
100 | #define GC_I2C_DAR 0x00000010 /* DAR */ | ||
101 | |||
102 | #define I2C_DISABLE 0x00000000 | ||
103 | #define I2C_STOP 0x00000000 | ||
104 | #define I2C_START 0x00000010 | ||
105 | #define I2C_REPEATED_START 0x00000030 | ||
106 | #define I2C_CLOCK_AND_ENABLE 0x0000003f | ||
107 | #define I2C_READY 0x01 | ||
108 | #define I2C_INT 0x01 | ||
109 | #define I2C_INTE 0x02 | ||
110 | #define I2C_ACK 0x08 | ||
111 | #define I2C_BER 0x80 | ||
112 | #define I2C_BEIE 0x40 | ||
113 | #define I2C_TRX 0x80 | ||
114 | #define I2C_LRB 0x10 | ||
115 | |||
116 | /* Capture registers and bits */ | ||
117 | #define GC_CAP_VCM 0x00000000 | ||
118 | #define GC_CAP_CSC 0x00000004 | ||
119 | #define GC_CAP_VCS 0x00000008 | ||
120 | #define GC_CAP_CBM 0x00000010 | ||
121 | #define GC_CAP_CBOA 0x00000014 | ||
122 | #define GC_CAP_CBLA 0x00000018 | ||
123 | #define GC_CAP_IMG_START 0x0000001C | ||
124 | #define GC_CAP_IMG_END 0x00000020 | ||
125 | #define GC_CAP_CMSS 0x00000048 | ||
126 | #define GC_CAP_CMDS 0x0000004C | ||
127 | |||
128 | #define GC_VCM_VIE 0x80000000 | ||
129 | #define GC_VCM_CM 0x03000000 | ||
130 | #define GC_VCM_VS_PAL 0x00000002 | ||
131 | #define GC_CBM_OO 0x80000000 | ||
132 | #define GC_CBM_HRV 0x00000010 | ||
133 | #define GC_CBM_CBST 0x00000001 | ||
134 | |||
85 | /* Carmine specific */ | 135 | /* Carmine specific */ |
86 | #define MB86297_DRAW_BASE 0x00020000 | 136 | #define MB86297_DRAW_BASE 0x00020000 |
87 | #define MB86297_DISP0_BASE 0x00100000 | 137 | #define MB86297_DISP0_BASE 0x00100000 |
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h index d7e7cb76bbf2..8550630c1e01 100644 --- a/drivers/video/mb862xx/mb862xxfb.h +++ b/drivers/video/mb862xx/mb862xxfb.h | |||
@@ -1,6 +1,26 @@ | |||
1 | #ifndef __MB862XX_H__ | 1 | #ifndef __MB862XX_H__ |
2 | #define __MB862XX_H__ | 2 | #define __MB862XX_H__ |
3 | 3 | ||
4 | struct mb862xx_l1_cfg { | ||
5 | unsigned short sx; | ||
6 | unsigned short sy; | ||
7 | unsigned short sw; | ||
8 | unsigned short sh; | ||
9 | unsigned short dx; | ||
10 | unsigned short dy; | ||
11 | unsigned short dw; | ||
12 | unsigned short dh; | ||
13 | int mirror; | ||
14 | }; | ||
15 | |||
16 | #define MB862XX_BASE 'M' | ||
17 | #define MB862XX_L1_GET_CFG _IOR(MB862XX_BASE, 0, struct mb862xx_l1_cfg*) | ||
18 | #define MB862XX_L1_SET_CFG _IOW(MB862XX_BASE, 1, struct mb862xx_l1_cfg*) | ||
19 | #define MB862XX_L1_ENABLE _IOW(MB862XX_BASE, 2, int) | ||
20 | #define MB862XX_L1_CAP_CTL _IOW(MB862XX_BASE, 3, int) | ||
21 | |||
22 | #ifdef __KERNEL__ | ||
23 | |||
4 | #define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf | 24 | #define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf |
5 | #define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019 | 25 | #define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019 |
6 | #define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e | 26 | #define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e |
@@ -38,6 +58,8 @@ struct mb862xxfb_par { | |||
38 | void __iomem *mmio_base; /* remapped registers */ | 58 | void __iomem *mmio_base; /* remapped registers */ |
39 | size_t mapped_vram; /* length of remapped vram */ | 59 | size_t mapped_vram; /* length of remapped vram */ |
40 | size_t mmio_len; /* length of register region */ | 60 | size_t mmio_len; /* length of register region */ |
61 | unsigned long cap_buf; /* capture buffers offset */ | ||
62 | size_t cap_len; /* length of capture buffers */ | ||
41 | 63 | ||
42 | void __iomem *host; /* relocatable reg. bases */ | 64 | void __iomem *host; /* relocatable reg. bases */ |
43 | void __iomem *i2c; | 65 | void __iomem *i2c; |
@@ -57,11 +79,23 @@ struct mb862xxfb_par { | |||
57 | unsigned int refclk; /* disp. reference clock */ | 79 | unsigned int refclk; /* disp. reference clock */ |
58 | struct mb862xx_gc_mode *gc_mode; /* GDC mode init data */ | 80 | struct mb862xx_gc_mode *gc_mode; /* GDC mode init data */ |
59 | int pre_init; /* don't init display if 1 */ | 81 | int pre_init; /* don't init display if 1 */ |
82 | struct i2c_adapter *adap; /* GDC I2C bus adapter */ | ||
83 | int i2c_rs; | ||
84 | |||
85 | struct mb862xx_l1_cfg l1_cfg; | ||
86 | int l1_stride; | ||
60 | 87 | ||
61 | u32 pseudo_palette[16]; | 88 | u32 pseudo_palette[16]; |
62 | }; | 89 | }; |
63 | 90 | ||
64 | extern void mb862xxfb_init_accel(struct fb_info *info, int xres); | 91 | extern void mb862xxfb_init_accel(struct fb_info *info, int xres); |
92 | #ifdef CONFIG_FB_MB862XX_I2C | ||
93 | extern int mb862xx_i2c_init(struct mb862xxfb_par *par); | ||
94 | extern void mb862xx_i2c_exit(struct mb862xxfb_par *par); | ||
95 | #else | ||
96 | static inline int mb862xx_i2c_init(struct mb862xxfb_par *par) { return 0; } | ||
97 | static inline void mb862xx_i2c_exit(struct mb862xxfb_par *par) { } | ||
98 | #endif | ||
65 | 99 | ||
66 | #if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC) | 100 | #if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC) |
67 | #error "Select Lime GDC or CoralP/Carmine support, but not both together" | 101 | #error "Select Lime GDC or CoralP/Carmine support, but not both together" |
@@ -82,4 +116,6 @@ extern void mb862xxfb_init_accel(struct fb_info *info, int xres); | |||
82 | 116 | ||
83 | #define pack(a, b) (((a) << 16) | (b)) | 117 | #define pack(a, b) (((a) << 16) | (b)) |
84 | 118 | ||
119 | #endif /* __KERNEL__ */ | ||
120 | |||
85 | #endif | 121 | #endif |
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfbdrv.c index c76e663a6cd4..ea39336addfb 100644 --- a/drivers/video/mb862xx/mb862xxfb.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | #define NR_PALETTE 256 | 28 | #define NR_PALETTE 256 |
29 | #define MB862XX_MEM_SIZE 0x1000000 | 29 | #define MB862XX_MEM_SIZE 0x1000000 |
30 | #define CORALP_MEM_SIZE 0x4000000 | 30 | #define CORALP_MEM_SIZE 0x2000000 |
31 | #define CARMINE_MEM_SIZE 0x8000000 | 31 | #define CARMINE_MEM_SIZE 0x8000000 |
32 | #define DRV_NAME "mb862xxfb" | 32 | #define DRV_NAME "mb862xxfb" |
33 | 33 | ||
@@ -309,6 +309,97 @@ static int mb862xxfb_blank(int mode, struct fb_info *fbi) | |||
309 | return 0; | 309 | return 0; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd, | ||
313 | unsigned long arg) | ||
314 | { | ||
315 | struct mb862xxfb_par *par = fbi->par; | ||
316 | struct mb862xx_l1_cfg *l1_cfg = &par->l1_cfg; | ||
317 | void __user *argp = (void __user *)arg; | ||
318 | int *enable; | ||
319 | u32 l1em = 0; | ||
320 | |||
321 | switch (cmd) { | ||
322 | case MB862XX_L1_GET_CFG: | ||
323 | if (copy_to_user(argp, l1_cfg, sizeof(*l1_cfg))) | ||
324 | return -EFAULT; | ||
325 | break; | ||
326 | case MB862XX_L1_SET_CFG: | ||
327 | if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg))) | ||
328 | return -EFAULT; | ||
329 | if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) { | ||
330 | /* downscaling */ | ||
331 | outreg(cap, GC_CAP_CSC, | ||
332 | pack((l1_cfg->sh << 11) / l1_cfg->dh, | ||
333 | (l1_cfg->sw << 11) / l1_cfg->dw)); | ||
334 | l1em = inreg(disp, GC_L1EM); | ||
335 | l1em &= ~GC_L1EM_DM; | ||
336 | } else if ((l1_cfg->sw <= l1_cfg->dw) && | ||
337 | (l1_cfg->sh <= l1_cfg->dh)) { | ||
338 | /* upscaling */ | ||
339 | outreg(cap, GC_CAP_CSC, | ||
340 | pack((l1_cfg->sh << 11) / l1_cfg->dh, | ||
341 | (l1_cfg->sw << 11) / l1_cfg->dw)); | ||
342 | outreg(cap, GC_CAP_CMSS, | ||
343 | pack(l1_cfg->sw >> 1, l1_cfg->sh)); | ||
344 | outreg(cap, GC_CAP_CMDS, | ||
345 | pack(l1_cfg->dw >> 1, l1_cfg->dh)); | ||
346 | l1em = inreg(disp, GC_L1EM); | ||
347 | l1em |= GC_L1EM_DM; | ||
348 | } | ||
349 | |||
350 | if (l1_cfg->mirror) { | ||
351 | outreg(cap, GC_CAP_CBM, | ||
352 | inreg(cap, GC_CAP_CBM) | GC_CBM_HRV); | ||
353 | l1em |= l1_cfg->dw * 2 - 8; | ||
354 | } else { | ||
355 | outreg(cap, GC_CAP_CBM, | ||
356 | inreg(cap, GC_CAP_CBM) & ~GC_CBM_HRV); | ||
357 | l1em &= 0xffff0000; | ||
358 | } | ||
359 | outreg(disp, GC_L1EM, l1em); | ||
360 | break; | ||
361 | case MB862XX_L1_ENABLE: | ||
362 | enable = (int *)arg; | ||
363 | if (*enable) { | ||
364 | outreg(disp, GC_L1DA, par->cap_buf); | ||
365 | outreg(cap, GC_CAP_IMG_START, | ||
366 | pack(l1_cfg->sy >> 1, l1_cfg->sx)); | ||
367 | outreg(cap, GC_CAP_IMG_END, | ||
368 | pack(l1_cfg->sh, l1_cfg->sw)); | ||
369 | outreg(disp, GC_L1M, GC_L1M_16 | GC_L1M_YC | GC_L1M_CS | | ||
370 | (par->l1_stride << 16)); | ||
371 | outreg(disp, GC_L1WY_L1WX, | ||
372 | pack(l1_cfg->dy, l1_cfg->dx)); | ||
373 | outreg(disp, GC_L1WH_L1WW, | ||
374 | pack(l1_cfg->dh - 1, l1_cfg->dw)); | ||
375 | outreg(disp, GC_DLS, 1); | ||
376 | outreg(cap, GC_CAP_VCM, | ||
377 | GC_VCM_VIE | GC_VCM_CM | GC_VCM_VS_PAL); | ||
378 | outreg(disp, GC_DCM1, inreg(disp, GC_DCM1) | | ||
379 | GC_DCM1_DEN | GC_DCM1_L1E); | ||
380 | } else { | ||
381 | outreg(cap, GC_CAP_VCM, | ||
382 | inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE); | ||
383 | outreg(disp, GC_DCM1, | ||
384 | inreg(disp, GC_DCM1) & ~GC_DCM1_L1E); | ||
385 | } | ||
386 | break; | ||
387 | case MB862XX_L1_CAP_CTL: | ||
388 | enable = (int *)arg; | ||
389 | if (*enable) { | ||
390 | outreg(cap, GC_CAP_VCM, | ||
391 | inreg(cap, GC_CAP_VCM) | GC_VCM_VIE); | ||
392 | } else { | ||
393 | outreg(cap, GC_CAP_VCM, | ||
394 | inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE); | ||
395 | } | ||
396 | break; | ||
397 | default: | ||
398 | return -EINVAL; | ||
399 | } | ||
400 | return 0; | ||
401 | } | ||
402 | |||
312 | /* framebuffer ops */ | 403 | /* framebuffer ops */ |
313 | static struct fb_ops mb862xxfb_ops = { | 404 | static struct fb_ops mb862xxfb_ops = { |
314 | .owner = THIS_MODULE, | 405 | .owner = THIS_MODULE, |
@@ -320,6 +411,7 @@ static struct fb_ops mb862xxfb_ops = { | |||
320 | .fb_fillrect = cfb_fillrect, | 411 | .fb_fillrect = cfb_fillrect, |
321 | .fb_copyarea = cfb_copyarea, | 412 | .fb_copyarea = cfb_copyarea, |
322 | .fb_imageblit = cfb_imageblit, | 413 | .fb_imageblit = cfb_imageblit, |
414 | .fb_ioctl = mb862xxfb_ioctl, | ||
323 | }; | 415 | }; |
324 | 416 | ||
325 | /* initialize fb_info data */ | 417 | /* initialize fb_info data */ |
@@ -328,6 +420,7 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi) | |||
328 | struct mb862xxfb_par *par = fbi->par; | 420 | struct mb862xxfb_par *par = fbi->par; |
329 | struct mb862xx_gc_mode *mode = par->gc_mode; | 421 | struct mb862xx_gc_mode *mode = par->gc_mode; |
330 | unsigned long reg; | 422 | unsigned long reg; |
423 | int stride; | ||
331 | 424 | ||
332 | fbi->fbops = &mb862xxfb_ops; | 425 | fbi->fbops = &mb862xxfb_ops; |
333 | fbi->pseudo_palette = par->pseudo_palette; | 426 | fbi->pseudo_palette = par->pseudo_palette; |
@@ -336,7 +429,6 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi) | |||
336 | 429 | ||
337 | strcpy(fbi->fix.id, DRV_NAME); | 430 | strcpy(fbi->fix.id, DRV_NAME); |
338 | fbi->fix.smem_start = (unsigned long)par->fb_base_phys; | 431 | fbi->fix.smem_start = (unsigned long)par->fb_base_phys; |
339 | fbi->fix.smem_len = par->mapped_vram; | ||
340 | fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys; | 432 | fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys; |
341 | fbi->fix.mmio_len = par->mmio_len; | 433 | fbi->fix.mmio_len = par->mmio_len; |
342 | fbi->fix.accel = FB_ACCEL_NONE; | 434 | fbi->fix.accel = FB_ACCEL_NONE; |
@@ -420,6 +512,28 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi) | |||
420 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 512 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
421 | fbi->fix.line_length = (fbi->var.xres_virtual * | 513 | fbi->fix.line_length = (fbi->var.xres_virtual * |
422 | fbi->var.bits_per_pixel) / 8; | 514 | fbi->var.bits_per_pixel) / 8; |
515 | fbi->fix.smem_len = fbi->fix.line_length * fbi->var.yres_virtual; | ||
516 | |||
517 | /* | ||
518 | * reserve space for capture buffers and two cursors | ||
519 | * at the end of vram: 720x576 * 2 * 2.2 + 64x64 * 16. | ||
520 | */ | ||
521 | par->cap_buf = par->mapped_vram - 0x1bd800 - 0x10000; | ||
522 | par->cap_len = 0x1bd800; | ||
523 | par->l1_cfg.sx = 0; | ||
524 | par->l1_cfg.sy = 0; | ||
525 | par->l1_cfg.sw = 720; | ||
526 | par->l1_cfg.sh = 576; | ||
527 | par->l1_cfg.dx = 0; | ||
528 | par->l1_cfg.dy = 0; | ||
529 | par->l1_cfg.dw = 720; | ||
530 | par->l1_cfg.dh = 576; | ||
531 | stride = par->l1_cfg.sw * (fbi->var.bits_per_pixel / 8); | ||
532 | par->l1_stride = stride / 64 + ((stride % 64) ? 1 : 0); | ||
533 | outreg(cap, GC_CAP_CBM, GC_CBM_OO | GC_CBM_CBST | | ||
534 | (par->l1_stride << 16)); | ||
535 | outreg(cap, GC_CAP_CBOA, par->cap_buf); | ||
536 | outreg(cap, GC_CAP_CBLA, par->cap_buf + par->cap_len); | ||
423 | return 0; | 537 | return 0; |
424 | } | 538 | } |
425 | 539 | ||
@@ -742,22 +856,38 @@ static int coralp_init(struct mb862xxfb_par *par) | |||
742 | 856 | ||
743 | par->refclk = GC_DISP_REFCLK_400; | 857 | par->refclk = GC_DISP_REFCLK_400; |
744 | 858 | ||
859 | if (par->mapped_vram >= 0x2000000) { | ||
860 | /* relocate gdc registers space */ | ||
861 | writel(1, par->fb_base + MB862XX_MMIO_BASE + GC_RSW); | ||
862 | udelay(1); /* wait at least 20 bus cycles */ | ||
863 | } | ||
864 | |||
745 | ver = inreg(host, GC_CID); | 865 | ver = inreg(host, GC_CID); |
746 | cn = (ver & GC_CID_CNAME_MSK) >> 8; | 866 | cn = (ver & GC_CID_CNAME_MSK) >> 8; |
747 | ver = ver & GC_CID_VERSION_MSK; | 867 | ver = ver & GC_CID_VERSION_MSK; |
748 | if (cn == 3) { | 868 | if (cn == 3) { |
869 | unsigned long reg; | ||
870 | |||
749 | dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\ | 871 | dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\ |
750 | (ver == 6) ? "P" : (ver == 8) ? "PA" : "?", | 872 | (ver == 6) ? "P" : (ver == 8) ? "PA" : "?", |
751 | par->pdev->revision); | 873 | par->pdev->revision); |
752 | outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133); | 874 | reg = inreg(disp, GC_DCM1); |
753 | udelay(200); | 875 | if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E) |
754 | outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL); | 876 | par->pre_init = 1; |
755 | udelay(10); | 877 | |
878 | if (!par->pre_init) { | ||
879 | outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133); | ||
880 | udelay(200); | ||
881 | outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL); | ||
882 | udelay(10); | ||
883 | } | ||
756 | /* Clear interrupt status */ | 884 | /* Clear interrupt status */ |
757 | outreg(host, GC_IST, 0); | 885 | outreg(host, GC_IST, 0); |
758 | } else { | 886 | } else { |
759 | return -ENODEV; | 887 | return -ENODEV; |
760 | } | 888 | } |
889 | |||
890 | mb862xx_i2c_init(par); | ||
761 | return 0; | 891 | return 0; |
762 | } | 892 | } |
763 | 893 | ||
@@ -899,7 +1029,13 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev, | |||
899 | case PCI_DEVICE_ID_FUJITSU_CORALPA: | 1029 | case PCI_DEVICE_ID_FUJITSU_CORALPA: |
900 | par->fb_base_phys = pci_resource_start(par->pdev, 0); | 1030 | par->fb_base_phys = pci_resource_start(par->pdev, 0); |
901 | par->mapped_vram = CORALP_MEM_SIZE; | 1031 | par->mapped_vram = CORALP_MEM_SIZE; |
902 | par->mmio_base_phys = par->fb_base_phys + MB862XX_MMIO_BASE; | 1032 | if (par->mapped_vram >= 0x2000000) { |
1033 | par->mmio_base_phys = par->fb_base_phys + | ||
1034 | MB862XX_MMIO_HIGH_BASE; | ||
1035 | } else { | ||
1036 | par->mmio_base_phys = par->fb_base_phys + | ||
1037 | MB862XX_MMIO_BASE; | ||
1038 | } | ||
903 | par->mmio_len = MB862XX_MMIO_SIZE; | 1039 | par->mmio_len = MB862XX_MMIO_SIZE; |
904 | par->type = BT_CORALP; | 1040 | par->type = BT_CORALP; |
905 | break; | 1041 | break; |
@@ -1009,6 +1145,8 @@ static void __devexit mb862xx_pci_remove(struct pci_dev *pdev) | |||
1009 | outreg(host, GC_IMASK, 0); | 1145 | outreg(host, GC_IMASK, 0); |
1010 | } | 1146 | } |
1011 | 1147 | ||
1148 | mb862xx_i2c_exit(par); | ||
1149 | |||
1012 | device_remove_file(&pdev->dev, &dev_attr_dispregs); | 1150 | device_remove_file(&pdev->dev, &dev_attr_dispregs); |
1013 | 1151 | ||
1014 | pci_set_drvdata(pdev, NULL); | 1152 | pci_set_drvdata(pdev, NULL); |
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c index 529483467abf..0ccd7adf47bb 100644 --- a/drivers/video/omap/dispc.c +++ b/drivers/video/omap/dispc.c | |||
@@ -922,14 +922,14 @@ static int get_dss_clocks(void) | |||
922 | return PTR_ERR(dispc.dss_ick); | 922 | return PTR_ERR(dispc.dss_ick); |
923 | } | 923 | } |
924 | 924 | ||
925 | dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck"); | 925 | dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "fck"); |
926 | if (IS_ERR(dispc.dss1_fck)) { | 926 | if (IS_ERR(dispc.dss1_fck)) { |
927 | dev_err(dispc.fbdev->dev, "can't get dss1_fck\n"); | 927 | dev_err(dispc.fbdev->dev, "can't get dss1_fck\n"); |
928 | clk_put(dispc.dss_ick); | 928 | clk_put(dispc.dss_ick); |
929 | return PTR_ERR(dispc.dss1_fck); | 929 | return PTR_ERR(dispc.dss1_fck); |
930 | } | 930 | } |
931 | 931 | ||
932 | dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_fck"); | 932 | dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_clk"); |
933 | if (IS_ERR(dispc.dss_54m_fck)) { | 933 | if (IS_ERR(dispc.dss_54m_fck)) { |
934 | dev_err(dispc.fbdev->dev, "can't get tv_fck\n"); | 934 | dev_err(dispc.fbdev->dev, "can't get tv_fck\n"); |
935 | clk_put(dispc.dss_ick); | 935 | clk_put(dispc.dss_ick); |
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index e264efd0278f..b3ddd743d8a6 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
@@ -90,7 +90,7 @@ static void omapdss_release(struct device *dev) | |||
90 | 90 | ||
91 | /* dummy device for clocks */ | 91 | /* dummy device for clocks */ |
92 | static struct platform_device omapdss_device = { | 92 | static struct platform_device omapdss_device = { |
93 | .name = "omapdss", | 93 | .name = "omapdss_dss", |
94 | .id = -1, | 94 | .id = -1, |
95 | .dev = { | 95 | .dev = { |
96 | .release = omapdss_release, | 96 | .release = omapdss_release, |
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c index eada9f12efc7..0c6981f1a4a3 100644 --- a/drivers/video/omap/rfbi.c +++ b/drivers/video/omap/rfbi.c | |||
@@ -90,7 +90,7 @@ static int rfbi_get_clocks(void) | |||
90 | return PTR_ERR(rfbi.dss_ick); | 90 | return PTR_ERR(rfbi.dss_ick); |
91 | } | 91 | } |
92 | 92 | ||
93 | rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "dss1_fck"); | 93 | rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "fck"); |
94 | if (IS_ERR(rfbi.dss1_fck)) { | 94 | if (IS_ERR(rfbi.dss1_fck)) { |
95 | dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n"); | 95 | dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n"); |
96 | clk_put(rfbi.dss_ick); | 96 | clk_put(rfbi.dss_ick); |
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile index d853d05dad31..5ddef129f798 100644 --- a/drivers/video/omap2/Makefile +++ b/drivers/video/omap2/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | obj-$(CONFIG_OMAP2_VRAM) += vram.o | 1 | obj-$(CONFIG_OMAP2_VRAM) += vram.o |
2 | obj-$(CONFIG_OMAP2_VRFB) += vrfb.o | 2 | obj-$(CONFIG_OMAP2_VRFB) += vrfb.o |
3 | 3 | ||
4 | obj-y += dss/ | 4 | obj-$(CONFIG_OMAP2_DSS) += dss/ |
5 | obj-y += omapfb/ | 5 | obj-$(CONFIG_FB_OMAP2) += omapfb/ |
6 | obj-y += displays/ | 6 | obj-y += displays/ |
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index d18ad6b2372a..609a28073178 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig | |||
@@ -3,6 +3,7 @@ menu "OMAP2/3 Display Device Drivers" | |||
3 | 3 | ||
4 | config PANEL_GENERIC_DPI | 4 | config PANEL_GENERIC_DPI |
5 | tristate "Generic DPI Panel" | 5 | tristate "Generic DPI Panel" |
6 | depends on OMAP2_DSS_DPI | ||
6 | help | 7 | help |
7 | Generic DPI panel driver. | 8 | Generic DPI panel driver. |
8 | Supports DVI output for Beagle and OMAP3 SDP. | 9 | Supports DVI output for Beagle and OMAP3 SDP. |
@@ -11,20 +12,20 @@ config PANEL_GENERIC_DPI | |||
11 | 12 | ||
12 | config PANEL_LGPHILIPS_LB035Q02 | 13 | config PANEL_LGPHILIPS_LB035Q02 |
13 | tristate "LG.Philips LB035Q02 LCD Panel" | 14 | tristate "LG.Philips LB035Q02 LCD Panel" |
14 | depends on OMAP2_DSS && SPI | 15 | depends on OMAP2_DSS_DPI && SPI |
15 | help | 16 | help |
16 | LCD Panel used on the Gumstix Overo Palo35 | 17 | LCD Panel used on the Gumstix Overo Palo35 |
17 | 18 | ||
18 | config PANEL_SHARP_LS037V7DW01 | 19 | config PANEL_SHARP_LS037V7DW01 |
19 | tristate "Sharp LS037V7DW01 LCD Panel" | 20 | tristate "Sharp LS037V7DW01 LCD Panel" |
20 | depends on OMAP2_DSS | 21 | depends on OMAP2_DSS_DPI |
21 | select BACKLIGHT_CLASS_DEVICE | 22 | select BACKLIGHT_CLASS_DEVICE |
22 | help | 23 | help |
23 | LCD Panel used in TI's SDP3430 and EVM boards | 24 | LCD Panel used in TI's SDP3430 and EVM boards |
24 | 25 | ||
25 | config PANEL_NEC_NL8048HL11_01B | 26 | config PANEL_NEC_NL8048HL11_01B |
26 | tristate "NEC NL8048HL11-01B Panel" | 27 | tristate "NEC NL8048HL11-01B Panel" |
27 | depends on OMAP2_DSS | 28 | depends on OMAP2_DSS_DPI |
28 | help | 29 | help |
29 | This NEC NL8048HL11-01B panel is TFT LCD | 30 | This NEC NL8048HL11-01B panel is TFT LCD |
30 | used in the Zoom2/3/3630 sdp boards. | 31 | used in the Zoom2/3/3630 sdp boards. |
@@ -37,7 +38,7 @@ config PANEL_TAAL | |||
37 | 38 | ||
38 | config PANEL_TPO_TD043MTEA1 | 39 | config PANEL_TPO_TD043MTEA1 |
39 | tristate "TPO TD043MTEA1 LCD Panel" | 40 | tristate "TPO TD043MTEA1 LCD Panel" |
40 | depends on OMAP2_DSS && SPI | 41 | depends on OMAP2_DSS_DPI && SPI |
41 | help | 42 | help |
42 | LCD Panel used in OMAP3 Pandora | 43 | LCD Panel used in OMAP3 Pandora |
43 | 44 | ||
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c index 7e04c921aa2a..dbd59b8e5b36 100644 --- a/drivers/video/omap2/displays/panel-acx565akm.c +++ b/drivers/video/omap2/displays/panel-acx565akm.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/backlight.h> | 30 | #include <linux/backlight.h> |
31 | #include <linux/fb.h> | 31 | #include <linux/fb.h> |
32 | 32 | ||
33 | #include <plat/display.h> | 33 | #include <video/omapdss.h> |
34 | 34 | ||
35 | #define MIPID_CMD_READ_DISP_ID 0x04 | 35 | #define MIPID_CMD_READ_DISP_ID 0x04 |
36 | #define MIPID_CMD_READ_RED 0x06 | 36 | #define MIPID_CMD_READ_RED 0x06 |
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 4a9b9ff59467..9c90f75653fb 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c | |||
@@ -33,8 +33,9 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <video/omapdss.h> | ||
36 | 37 | ||
37 | #include <plat/panel-generic-dpi.h> | 38 | #include <video/omap-panel-generic-dpi.h> |
38 | 39 | ||
39 | struct panel_config { | 40 | struct panel_config { |
40 | struct omap_video_timings timings; | 41 | struct omap_video_timings timings; |
@@ -181,6 +182,56 @@ static struct panel_config generic_dpi_panels[] = { | |||
181 | .power_off_delay = 0, | 182 | .power_off_delay = 0, |
182 | .name = "samsung_lte430wq_f0c", | 183 | .name = "samsung_lte430wq_f0c", |
183 | }, | 184 | }, |
185 | |||
186 | /* Seiko 70WVW1TZ3Z3 */ | ||
187 | { | ||
188 | { | ||
189 | .x_res = 800, | ||
190 | .y_res = 480, | ||
191 | |||
192 | .pixel_clock = 33000, | ||
193 | |||
194 | .hsw = 128, | ||
195 | .hfp = 10, | ||
196 | .hbp = 10, | ||
197 | |||
198 | .vsw = 2, | ||
199 | .vfp = 4, | ||
200 | .vbp = 11, | ||
201 | }, | ||
202 | .acbi = 0x0, | ||
203 | .acb = 0x0, | ||
204 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
205 | OMAP_DSS_LCD_IHS, | ||
206 | .power_on_delay = 0, | ||
207 | .power_off_delay = 0, | ||
208 | .name = "seiko_70wvw1tz3", | ||
209 | }, | ||
210 | |||
211 | /* Powertip PH480272T */ | ||
212 | { | ||
213 | { | ||
214 | .x_res = 480, | ||
215 | .y_res = 272, | ||
216 | |||
217 | .pixel_clock = 9000, | ||
218 | |||
219 | .hsw = 40, | ||
220 | .hfp = 2, | ||
221 | .hbp = 2, | ||
222 | |||
223 | .vsw = 10, | ||
224 | .vfp = 2, | ||
225 | .vbp = 2, | ||
226 | }, | ||
227 | .acbi = 0x0, | ||
228 | .acb = 0x0, | ||
229 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
230 | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO, | ||
231 | .power_on_delay = 0, | ||
232 | .power_off_delay = 0, | ||
233 | .name = "powertip_ph480272t", | ||
234 | }, | ||
184 | }; | 235 | }; |
185 | 236 | ||
186 | struct panel_drv_data { | 237 | struct panel_drv_data { |
@@ -285,7 +336,7 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev) | |||
285 | return 0; | 336 | return 0; |
286 | } | 337 | } |
287 | 338 | ||
288 | static void generic_dpi_panel_remove(struct omap_dss_device *dssdev) | 339 | static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev) |
289 | { | 340 | { |
290 | struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); | 341 | struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); |
291 | 342 | ||
@@ -358,7 +409,7 @@ static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, | |||
358 | 409 | ||
359 | static struct omap_dss_driver dpi_driver = { | 410 | static struct omap_dss_driver dpi_driver = { |
360 | .probe = generic_dpi_panel_probe, | 411 | .probe = generic_dpi_panel_probe, |
361 | .remove = generic_dpi_panel_remove, | 412 | .remove = __exit_p(generic_dpi_panel_remove), |
362 | 413 | ||
363 | .enable = generic_dpi_panel_enable, | 414 | .enable = generic_dpi_panel_enable, |
364 | .disable = generic_dpi_panel_disable, | 415 | .disable = generic_dpi_panel_disable, |
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c index 271324db2436..e0eb35be303e 100644 --- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c +++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | 23 | ||
24 | #include <plat/display.h> | 24 | #include <video/omapdss.h> |
25 | 25 | ||
26 | struct lb035q02_data { | 26 | struct lb035q02_data { |
27 | struct mutex lock; | 27 | struct mutex lock; |
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c index 925e0fadff54..2ba9d0ca187c 100644 --- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c +++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/backlight.h> | 22 | #include <linux/backlight.h> |
23 | #include <linux/fb.h> | 23 | #include <linux/fb.h> |
24 | 24 | ||
25 | #include <plat/display.h> | 25 | #include <video/omapdss.h> |
26 | 26 | ||
27 | #define LCD_XRES 800 | 27 | #define LCD_XRES 800 |
28 | #define LCD_YRES 480 | 28 | #define LCD_YRES 480 |
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c index d2b35d2df2a6..ba38b3ad17d6 100644 --- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/err.h> | 25 | #include <linux/err.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | 27 | ||
28 | #include <plat/display.h> | 28 | #include <video/omapdss.h> |
29 | 29 | ||
30 | struct sharp_data { | 30 | struct sharp_data { |
31 | struct backlight_device *bl; | 31 | struct backlight_device *bl; |
@@ -120,7 +120,7 @@ static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) | |||
120 | return 0; | 120 | return 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | static void sharp_ls_panel_remove(struct omap_dss_device *dssdev) | 123 | static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev) |
124 | { | 124 | { |
125 | struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); | 125 | struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); |
126 | struct backlight_device *bl = sd->bl; | 126 | struct backlight_device *bl = sd->bl; |
@@ -205,7 +205,7 @@ static int sharp_ls_panel_resume(struct omap_dss_device *dssdev) | |||
205 | 205 | ||
206 | static struct omap_dss_driver sharp_ls_driver = { | 206 | static struct omap_dss_driver sharp_ls_driver = { |
207 | .probe = sharp_ls_panel_probe, | 207 | .probe = sharp_ls_panel_probe, |
208 | .remove = sharp_ls_panel_remove, | 208 | .remove = __exit_p(sharp_ls_panel_remove), |
209 | 209 | ||
210 | .enable = sharp_ls_panel_enable, | 210 | .enable = sharp_ls_panel_enable, |
211 | .disable = sharp_ls_panel_disable, | 211 | .disable = sharp_ls_panel_disable, |
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index adc9900458e1..fdd5d4ae437d 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -33,8 +33,8 @@ | |||
33 | #include <linux/regulator/consumer.h> | 33 | #include <linux/regulator/consumer.h> |
34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
35 | 35 | ||
36 | #include <plat/display.h> | 36 | #include <video/omapdss.h> |
37 | #include <plat/nokia-dsi-panel.h> | 37 | #include <video/omap-panel-nokia-dsi.h> |
38 | 38 | ||
39 | /* DSI Virtual channel. Hardcoded for now. */ | 39 | /* DSI Virtual channel. Hardcoded for now. */ |
40 | #define TCH 0 | 40 | #define TCH 0 |
@@ -63,12 +63,12 @@ | |||
63 | #define DCS_GET_ID2 0xdb | 63 | #define DCS_GET_ID2 0xdb |
64 | #define DCS_GET_ID3 0xdc | 64 | #define DCS_GET_ID3 0xdc |
65 | 65 | ||
66 | #define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000) | ||
67 | |||
68 | static irqreturn_t taal_te_isr(int irq, void *data); | 66 | static irqreturn_t taal_te_isr(int irq, void *data); |
69 | static void taal_te_timeout_work_callback(struct work_struct *work); | 67 | static void taal_te_timeout_work_callback(struct work_struct *work); |
70 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); | 68 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); |
71 | 69 | ||
70 | static int taal_panel_reset(struct omap_dss_device *dssdev); | ||
71 | |||
72 | struct panel_regulator { | 72 | struct panel_regulator { |
73 | struct regulator *regulator; | 73 | struct regulator *regulator; |
74 | const char *name; | 74 | const char *name; |
@@ -229,8 +229,14 @@ struct taal_data { | |||
229 | 229 | ||
230 | bool intro_printed; | 230 | bool intro_printed; |
231 | 231 | ||
232 | struct workqueue_struct *esd_wq; | 232 | struct workqueue_struct *workqueue; |
233 | |||
233 | struct delayed_work esd_work; | 234 | struct delayed_work esd_work; |
235 | unsigned esd_interval; | ||
236 | |||
237 | bool ulps_enabled; | ||
238 | unsigned ulps_timeout; | ||
239 | struct delayed_work ulps_work; | ||
234 | 240 | ||
235 | struct panel_config *panel_config; | 241 | struct panel_config *panel_config; |
236 | }; | 242 | }; |
@@ -242,6 +248,7 @@ static inline struct nokia_dsi_panel_data | |||
242 | } | 248 | } |
243 | 249 | ||
244 | static void taal_esd_work(struct work_struct *work); | 250 | static void taal_esd_work(struct work_struct *work); |
251 | static void taal_ulps_work(struct work_struct *work); | ||
245 | 252 | ||
246 | static void hw_guard_start(struct taal_data *td, int guard_msec) | 253 | static void hw_guard_start(struct taal_data *td, int guard_msec) |
247 | { | 254 | { |
@@ -264,7 +271,7 @@ static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data) | |||
264 | int r; | 271 | int r; |
265 | u8 buf[1]; | 272 | u8 buf[1]; |
266 | 273 | ||
267 | r = dsi_vc_dcs_read(td->channel, dcs_cmd, buf, 1); | 274 | r = dsi_vc_dcs_read(td->dssdev, td->channel, dcs_cmd, buf, 1); |
268 | 275 | ||
269 | if (r < 0) | 276 | if (r < 0) |
270 | return r; | 277 | return r; |
@@ -276,7 +283,7 @@ static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data) | |||
276 | 283 | ||
277 | static int taal_dcs_write_0(struct taal_data *td, u8 dcs_cmd) | 284 | static int taal_dcs_write_0(struct taal_data *td, u8 dcs_cmd) |
278 | { | 285 | { |
279 | return dsi_vc_dcs_write(td->channel, &dcs_cmd, 1); | 286 | return dsi_vc_dcs_write(td->dssdev, td->channel, &dcs_cmd, 1); |
280 | } | 287 | } |
281 | 288 | ||
282 | static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param) | 289 | static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param) |
@@ -284,7 +291,7 @@ static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param) | |||
284 | u8 buf[2]; | 291 | u8 buf[2]; |
285 | buf[0] = dcs_cmd; | 292 | buf[0] = dcs_cmd; |
286 | buf[1] = param; | 293 | buf[1] = param; |
287 | return dsi_vc_dcs_write(td->channel, buf, 2); | 294 | return dsi_vc_dcs_write(td->dssdev, td->channel, buf, 2); |
288 | } | 295 | } |
289 | 296 | ||
290 | static int taal_sleep_in(struct taal_data *td) | 297 | static int taal_sleep_in(struct taal_data *td) |
@@ -296,7 +303,7 @@ static int taal_sleep_in(struct taal_data *td) | |||
296 | hw_guard_wait(td); | 303 | hw_guard_wait(td); |
297 | 304 | ||
298 | cmd = DCS_SLEEP_IN; | 305 | cmd = DCS_SLEEP_IN; |
299 | r = dsi_vc_dcs_write_nosync(td->channel, &cmd, 1); | 306 | r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1); |
300 | if (r) | 307 | if (r) |
301 | return r; | 308 | return r; |
302 | 309 | ||
@@ -402,7 +409,7 @@ static int taal_set_update_window(struct taal_data *td, | |||
402 | buf[3] = (x2 >> 8) & 0xff; | 409 | buf[3] = (x2 >> 8) & 0xff; |
403 | buf[4] = (x2 >> 0) & 0xff; | 410 | buf[4] = (x2 >> 0) & 0xff; |
404 | 411 | ||
405 | r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf)); | 412 | r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, buf, sizeof(buf)); |
406 | if (r) | 413 | if (r) |
407 | return r; | 414 | return r; |
408 | 415 | ||
@@ -412,15 +419,132 @@ static int taal_set_update_window(struct taal_data *td, | |||
412 | buf[3] = (y2 >> 8) & 0xff; | 419 | buf[3] = (y2 >> 8) & 0xff; |
413 | buf[4] = (y2 >> 0) & 0xff; | 420 | buf[4] = (y2 >> 0) & 0xff; |
414 | 421 | ||
415 | r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf)); | 422 | r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, buf, sizeof(buf)); |
416 | if (r) | 423 | if (r) |
417 | return r; | 424 | return r; |
418 | 425 | ||
419 | dsi_vc_send_bta_sync(td->channel); | 426 | dsi_vc_send_bta_sync(td->dssdev, td->channel); |
420 | 427 | ||
421 | return r; | 428 | return r; |
422 | } | 429 | } |
423 | 430 | ||
431 | static void taal_queue_esd_work(struct omap_dss_device *dssdev) | ||
432 | { | ||
433 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
434 | |||
435 | if (td->esd_interval > 0) | ||
436 | queue_delayed_work(td->workqueue, &td->esd_work, | ||
437 | msecs_to_jiffies(td->esd_interval)); | ||
438 | } | ||
439 | |||
440 | static void taal_cancel_esd_work(struct omap_dss_device *dssdev) | ||
441 | { | ||
442 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
443 | |||
444 | cancel_delayed_work(&td->esd_work); | ||
445 | } | ||
446 | |||
447 | static void taal_queue_ulps_work(struct omap_dss_device *dssdev) | ||
448 | { | ||
449 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
450 | |||
451 | if (td->ulps_timeout > 0) | ||
452 | queue_delayed_work(td->workqueue, &td->ulps_work, | ||
453 | msecs_to_jiffies(td->ulps_timeout)); | ||
454 | } | ||
455 | |||
456 | static void taal_cancel_ulps_work(struct omap_dss_device *dssdev) | ||
457 | { | ||
458 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
459 | |||
460 | cancel_delayed_work(&td->ulps_work); | ||
461 | } | ||
462 | |||
463 | static int taal_enter_ulps(struct omap_dss_device *dssdev) | ||
464 | { | ||
465 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
466 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
467 | int r; | ||
468 | |||
469 | if (td->ulps_enabled) | ||
470 | return 0; | ||
471 | |||
472 | taal_cancel_ulps_work(dssdev); | ||
473 | |||
474 | r = _taal_enable_te(dssdev, false); | ||
475 | if (r) | ||
476 | goto err; | ||
477 | |||
478 | disable_irq(gpio_to_irq(panel_data->ext_te_gpio)); | ||
479 | |||
480 | omapdss_dsi_display_disable(dssdev, false, true); | ||
481 | |||
482 | td->ulps_enabled = true; | ||
483 | |||
484 | return 0; | ||
485 | |||
486 | err: | ||
487 | dev_err(&dssdev->dev, "enter ULPS failed"); | ||
488 | taal_panel_reset(dssdev); | ||
489 | |||
490 | td->ulps_enabled = false; | ||
491 | |||
492 | taal_queue_ulps_work(dssdev); | ||
493 | |||
494 | return r; | ||
495 | } | ||
496 | |||
497 | static int taal_exit_ulps(struct omap_dss_device *dssdev) | ||
498 | { | ||
499 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
500 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
501 | int r; | ||
502 | |||
503 | if (!td->ulps_enabled) | ||
504 | return 0; | ||
505 | |||
506 | r = omapdss_dsi_display_enable(dssdev); | ||
507 | if (r) | ||
508 | goto err; | ||
509 | |||
510 | omapdss_dsi_vc_enable_hs(dssdev, td->channel, true); | ||
511 | |||
512 | r = _taal_enable_te(dssdev, true); | ||
513 | if (r) | ||
514 | goto err; | ||
515 | |||
516 | enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); | ||
517 | |||
518 | taal_queue_ulps_work(dssdev); | ||
519 | |||
520 | td->ulps_enabled = false; | ||
521 | |||
522 | return 0; | ||
523 | |||
524 | err: | ||
525 | dev_err(&dssdev->dev, "exit ULPS failed"); | ||
526 | r = taal_panel_reset(dssdev); | ||
527 | |||
528 | enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); | ||
529 | td->ulps_enabled = false; | ||
530 | |||
531 | taal_queue_ulps_work(dssdev); | ||
532 | |||
533 | return r; | ||
534 | } | ||
535 | |||
536 | static int taal_wake_up(struct omap_dss_device *dssdev) | ||
537 | { | ||
538 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
539 | |||
540 | if (td->ulps_enabled) | ||
541 | return taal_exit_ulps(dssdev); | ||
542 | |||
543 | taal_cancel_ulps_work(dssdev); | ||
544 | taal_queue_ulps_work(dssdev); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
424 | static int taal_bl_update_status(struct backlight_device *dev) | 548 | static int taal_bl_update_status(struct backlight_device *dev) |
425 | { | 549 | { |
426 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); | 550 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); |
@@ -441,9 +565,13 @@ static int taal_bl_update_status(struct backlight_device *dev) | |||
441 | 565 | ||
442 | if (td->use_dsi_bl) { | 566 | if (td->use_dsi_bl) { |
443 | if (td->enabled) { | 567 | if (td->enabled) { |
444 | dsi_bus_lock(); | 568 | dsi_bus_lock(dssdev); |
445 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); | 569 | |
446 | dsi_bus_unlock(); | 570 | r = taal_wake_up(dssdev); |
571 | if (!r) | ||
572 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); | ||
573 | |||
574 | dsi_bus_unlock(dssdev); | ||
447 | } else { | 575 | } else { |
448 | r = 0; | 576 | r = 0; |
449 | } | 577 | } |
@@ -504,9 +632,13 @@ static ssize_t taal_num_errors_show(struct device *dev, | |||
504 | mutex_lock(&td->lock); | 632 | mutex_lock(&td->lock); |
505 | 633 | ||
506 | if (td->enabled) { | 634 | if (td->enabled) { |
507 | dsi_bus_lock(); | 635 | dsi_bus_lock(dssdev); |
508 | r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors); | 636 | |
509 | dsi_bus_unlock(); | 637 | r = taal_wake_up(dssdev); |
638 | if (!r) | ||
639 | r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors); | ||
640 | |||
641 | dsi_bus_unlock(dssdev); | ||
510 | } else { | 642 | } else { |
511 | r = -ENODEV; | 643 | r = -ENODEV; |
512 | } | 644 | } |
@@ -530,9 +662,13 @@ static ssize_t taal_hw_revision_show(struct device *dev, | |||
530 | mutex_lock(&td->lock); | 662 | mutex_lock(&td->lock); |
531 | 663 | ||
532 | if (td->enabled) { | 664 | if (td->enabled) { |
533 | dsi_bus_lock(); | 665 | dsi_bus_lock(dssdev); |
534 | r = taal_get_id(td, &id1, &id2, &id3); | 666 | |
535 | dsi_bus_unlock(); | 667 | r = taal_wake_up(dssdev); |
668 | if (!r) | ||
669 | r = taal_get_id(td, &id1, &id2, &id3); | ||
670 | |||
671 | dsi_bus_unlock(dssdev); | ||
536 | } else { | 672 | } else { |
537 | r = -ENODEV; | 673 | r = -ENODEV; |
538 | } | 674 | } |
@@ -579,6 +715,7 @@ static ssize_t store_cabc_mode(struct device *dev, | |||
579 | struct omap_dss_device *dssdev = to_dss_device(dev); | 715 | struct omap_dss_device *dssdev = to_dss_device(dev); |
580 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 716 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
581 | int i; | 717 | int i; |
718 | int r; | ||
582 | 719 | ||
583 | for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { | 720 | for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { |
584 | if (sysfs_streq(cabc_modes[i], buf)) | 721 | if (sysfs_streq(cabc_modes[i], buf)) |
@@ -591,10 +728,19 @@ static ssize_t store_cabc_mode(struct device *dev, | |||
591 | mutex_lock(&td->lock); | 728 | mutex_lock(&td->lock); |
592 | 729 | ||
593 | if (td->enabled) { | 730 | if (td->enabled) { |
594 | dsi_bus_lock(); | 731 | dsi_bus_lock(dssdev); |
595 | if (!td->cabc_broken) | 732 | |
596 | taal_dcs_write_1(td, DCS_WRITE_CABC, i); | 733 | if (!td->cabc_broken) { |
597 | dsi_bus_unlock(); | 734 | r = taal_wake_up(dssdev); |
735 | if (r) | ||
736 | goto err; | ||
737 | |||
738 | r = taal_dcs_write_1(td, DCS_WRITE_CABC, i); | ||
739 | if (r) | ||
740 | goto err; | ||
741 | } | ||
742 | |||
743 | dsi_bus_unlock(dssdev); | ||
598 | } | 744 | } |
599 | 745 | ||
600 | td->cabc_mode = i; | 746 | td->cabc_mode = i; |
@@ -602,6 +748,10 @@ static ssize_t store_cabc_mode(struct device *dev, | |||
602 | mutex_unlock(&td->lock); | 748 | mutex_unlock(&td->lock); |
603 | 749 | ||
604 | return count; | 750 | return count; |
751 | err: | ||
752 | dsi_bus_unlock(dssdev); | ||
753 | mutex_unlock(&td->lock); | ||
754 | return r; | ||
605 | } | 755 | } |
606 | 756 | ||
607 | static ssize_t show_cabc_available_modes(struct device *dev, | 757 | static ssize_t show_cabc_available_modes(struct device *dev, |
@@ -620,18 +770,161 @@ static ssize_t show_cabc_available_modes(struct device *dev, | |||
620 | return len < PAGE_SIZE ? len : PAGE_SIZE - 1; | 770 | return len < PAGE_SIZE ? len : PAGE_SIZE - 1; |
621 | } | 771 | } |
622 | 772 | ||
773 | static ssize_t taal_store_esd_interval(struct device *dev, | ||
774 | struct device_attribute *attr, | ||
775 | const char *buf, size_t count) | ||
776 | { | ||
777 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
778 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
779 | |||
780 | unsigned long t; | ||
781 | int r; | ||
782 | |||
783 | r = strict_strtoul(buf, 10, &t); | ||
784 | if (r) | ||
785 | return r; | ||
786 | |||
787 | mutex_lock(&td->lock); | ||
788 | taal_cancel_esd_work(dssdev); | ||
789 | td->esd_interval = t; | ||
790 | if (td->enabled) | ||
791 | taal_queue_esd_work(dssdev); | ||
792 | mutex_unlock(&td->lock); | ||
793 | |||
794 | return count; | ||
795 | } | ||
796 | |||
797 | static ssize_t taal_show_esd_interval(struct device *dev, | ||
798 | struct device_attribute *attr, | ||
799 | char *buf) | ||
800 | { | ||
801 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
802 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
803 | unsigned t; | ||
804 | |||
805 | mutex_lock(&td->lock); | ||
806 | t = td->esd_interval; | ||
807 | mutex_unlock(&td->lock); | ||
808 | |||
809 | return snprintf(buf, PAGE_SIZE, "%u\n", t); | ||
810 | } | ||
811 | |||
812 | static ssize_t taal_store_ulps(struct device *dev, | ||
813 | struct device_attribute *attr, | ||
814 | const char *buf, size_t count) | ||
815 | { | ||
816 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
817 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
818 | unsigned long t; | ||
819 | int r; | ||
820 | |||
821 | r = strict_strtoul(buf, 10, &t); | ||
822 | if (r) | ||
823 | return r; | ||
824 | |||
825 | mutex_lock(&td->lock); | ||
826 | |||
827 | if (td->enabled) { | ||
828 | dsi_bus_lock(dssdev); | ||
829 | |||
830 | if (t) | ||
831 | r = taal_enter_ulps(dssdev); | ||
832 | else | ||
833 | r = taal_wake_up(dssdev); | ||
834 | |||
835 | dsi_bus_unlock(dssdev); | ||
836 | } | ||
837 | |||
838 | mutex_unlock(&td->lock); | ||
839 | |||
840 | if (r) | ||
841 | return r; | ||
842 | |||
843 | return count; | ||
844 | } | ||
845 | |||
846 | static ssize_t taal_show_ulps(struct device *dev, | ||
847 | struct device_attribute *attr, | ||
848 | char *buf) | ||
849 | { | ||
850 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
851 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
852 | unsigned t; | ||
853 | |||
854 | mutex_lock(&td->lock); | ||
855 | t = td->ulps_enabled; | ||
856 | mutex_unlock(&td->lock); | ||
857 | |||
858 | return snprintf(buf, PAGE_SIZE, "%u\n", t); | ||
859 | } | ||
860 | |||
861 | static ssize_t taal_store_ulps_timeout(struct device *dev, | ||
862 | struct device_attribute *attr, | ||
863 | const char *buf, size_t count) | ||
864 | { | ||
865 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
866 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
867 | unsigned long t; | ||
868 | int r; | ||
869 | |||
870 | r = strict_strtoul(buf, 10, &t); | ||
871 | if (r) | ||
872 | return r; | ||
873 | |||
874 | mutex_lock(&td->lock); | ||
875 | td->ulps_timeout = t; | ||
876 | |||
877 | if (td->enabled) { | ||
878 | /* taal_wake_up will restart the timer */ | ||
879 | dsi_bus_lock(dssdev); | ||
880 | r = taal_wake_up(dssdev); | ||
881 | dsi_bus_unlock(dssdev); | ||
882 | } | ||
883 | |||
884 | mutex_unlock(&td->lock); | ||
885 | |||
886 | if (r) | ||
887 | return r; | ||
888 | |||
889 | return count; | ||
890 | } | ||
891 | |||
892 | static ssize_t taal_show_ulps_timeout(struct device *dev, | ||
893 | struct device_attribute *attr, | ||
894 | char *buf) | ||
895 | { | ||
896 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
897 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
898 | unsigned t; | ||
899 | |||
900 | mutex_lock(&td->lock); | ||
901 | t = td->ulps_timeout; | ||
902 | mutex_unlock(&td->lock); | ||
903 | |||
904 | return snprintf(buf, PAGE_SIZE, "%u\n", t); | ||
905 | } | ||
906 | |||
623 | static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); | 907 | static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); |
624 | static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); | 908 | static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); |
625 | static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, | 909 | static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, |
626 | show_cabc_mode, store_cabc_mode); | 910 | show_cabc_mode, store_cabc_mode); |
627 | static DEVICE_ATTR(cabc_available_modes, S_IRUGO, | 911 | static DEVICE_ATTR(cabc_available_modes, S_IRUGO, |
628 | show_cabc_available_modes, NULL); | 912 | show_cabc_available_modes, NULL); |
913 | static DEVICE_ATTR(esd_interval, S_IRUGO | S_IWUSR, | ||
914 | taal_show_esd_interval, taal_store_esd_interval); | ||
915 | static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR, | ||
916 | taal_show_ulps, taal_store_ulps); | ||
917 | static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR, | ||
918 | taal_show_ulps_timeout, taal_store_ulps_timeout); | ||
629 | 919 | ||
630 | static struct attribute *taal_attrs[] = { | 920 | static struct attribute *taal_attrs[] = { |
631 | &dev_attr_num_dsi_errors.attr, | 921 | &dev_attr_num_dsi_errors.attr, |
632 | &dev_attr_hw_revision.attr, | 922 | &dev_attr_hw_revision.attr, |
633 | &dev_attr_cabc_mode.attr, | 923 | &dev_attr_cabc_mode.attr, |
634 | &dev_attr_cabc_available_modes.attr, | 924 | &dev_attr_cabc_available_modes.attr, |
925 | &dev_attr_esd_interval.attr, | ||
926 | &dev_attr_ulps.attr, | ||
927 | &dev_attr_ulps_timeout.attr, | ||
635 | NULL, | 928 | NULL, |
636 | }; | 929 | }; |
637 | 930 | ||
@@ -700,6 +993,9 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
700 | } | 993 | } |
701 | td->dssdev = dssdev; | 994 | td->dssdev = dssdev; |
702 | td->panel_config = panel_config; | 995 | td->panel_config = panel_config; |
996 | td->esd_interval = panel_data->esd_interval; | ||
997 | td->ulps_enabled = false; | ||
998 | td->ulps_timeout = panel_data->ulps_timeout; | ||
703 | 999 | ||
704 | mutex_init(&td->lock); | 1000 | mutex_init(&td->lock); |
705 | 1001 | ||
@@ -710,13 +1006,14 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
710 | if (r) | 1006 | if (r) |
711 | goto err_reg; | 1007 | goto err_reg; |
712 | 1008 | ||
713 | td->esd_wq = create_singlethread_workqueue("taal_esd"); | 1009 | td->workqueue = create_singlethread_workqueue("taal_esd"); |
714 | if (td->esd_wq == NULL) { | 1010 | if (td->workqueue == NULL) { |
715 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); | 1011 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); |
716 | r = -ENOMEM; | 1012 | r = -ENOMEM; |
717 | goto err_wq; | 1013 | goto err_wq; |
718 | } | 1014 | } |
719 | INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); | 1015 | INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); |
1016 | INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work); | ||
720 | 1017 | ||
721 | dev_set_drvdata(&dssdev->dev, td); | 1018 | dev_set_drvdata(&dssdev->dev, td); |
722 | 1019 | ||
@@ -734,8 +1031,8 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
734 | props.max_brightness = 127; | 1031 | props.max_brightness = 127; |
735 | 1032 | ||
736 | props.type = BACKLIGHT_RAW; | 1033 | props.type = BACKLIGHT_RAW; |
737 | bldev = backlight_device_register("taal", &dssdev->dev, dssdev, | 1034 | bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, |
738 | &taal_bl_ops, &props); | 1035 | dssdev, &taal_bl_ops, &props); |
739 | if (IS_ERR(bldev)) { | 1036 | if (IS_ERR(bldev)) { |
740 | r = PTR_ERR(bldev); | 1037 | r = PTR_ERR(bldev); |
741 | goto err_bl; | 1038 | goto err_bl; |
@@ -810,7 +1107,7 @@ err_irq: | |||
810 | err_gpio: | 1107 | err_gpio: |
811 | backlight_device_unregister(bldev); | 1108 | backlight_device_unregister(bldev); |
812 | err_bl: | 1109 | err_bl: |
813 | destroy_workqueue(td->esd_wq); | 1110 | destroy_workqueue(td->workqueue); |
814 | err_wq: | 1111 | err_wq: |
815 | free_regulators(panel_config->regulators, panel_config->num_regulators); | 1112 | free_regulators(panel_config->regulators, panel_config->num_regulators); |
816 | err_reg: | 1113 | err_reg: |
@@ -819,7 +1116,7 @@ err: | |||
819 | return r; | 1116 | return r; |
820 | } | 1117 | } |
821 | 1118 | ||
822 | static void taal_remove(struct omap_dss_device *dssdev) | 1119 | static void __exit taal_remove(struct omap_dss_device *dssdev) |
823 | { | 1120 | { |
824 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1121 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
825 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 1122 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); |
@@ -841,8 +1138,9 @@ static void taal_remove(struct omap_dss_device *dssdev) | |||
841 | taal_bl_update_status(bldev); | 1138 | taal_bl_update_status(bldev); |
842 | backlight_device_unregister(bldev); | 1139 | backlight_device_unregister(bldev); |
843 | 1140 | ||
844 | cancel_delayed_work(&td->esd_work); | 1141 | taal_cancel_ulps_work(dssdev); |
845 | destroy_workqueue(td->esd_wq); | 1142 | taal_cancel_esd_work(dssdev); |
1143 | destroy_workqueue(td->workqueue); | ||
846 | 1144 | ||
847 | /* reset, to be sure that the panel is in a valid state */ | 1145 | /* reset, to be sure that the panel is in a valid state */ |
848 | taal_hw_reset(dssdev); | 1146 | taal_hw_reset(dssdev); |
@@ -867,7 +1165,7 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
867 | 1165 | ||
868 | taal_hw_reset(dssdev); | 1166 | taal_hw_reset(dssdev); |
869 | 1167 | ||
870 | omapdss_dsi_vc_enable_hs(td->channel, false); | 1168 | omapdss_dsi_vc_enable_hs(dssdev, td->channel, false); |
871 | 1169 | ||
872 | r = taal_sleep_out(td); | 1170 | r = taal_sleep_out(td); |
873 | if (r) | 1171 | if (r) |
@@ -924,7 +1222,7 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
924 | td->intro_printed = true; | 1222 | td->intro_printed = true; |
925 | } | 1223 | } |
926 | 1224 | ||
927 | omapdss_dsi_vc_enable_hs(td->channel, true); | 1225 | omapdss_dsi_vc_enable_hs(dssdev, td->channel, true); |
928 | 1226 | ||
929 | return 0; | 1227 | return 0; |
930 | err: | 1228 | err: |
@@ -932,7 +1230,7 @@ err: | |||
932 | 1230 | ||
933 | taal_hw_reset(dssdev); | 1231 | taal_hw_reset(dssdev); |
934 | 1232 | ||
935 | omapdss_dsi_display_disable(dssdev); | 1233 | omapdss_dsi_display_disable(dssdev, true, false); |
936 | err0: | 1234 | err0: |
937 | return r; | 1235 | return r; |
938 | } | 1236 | } |
@@ -955,15 +1253,23 @@ static void taal_power_off(struct omap_dss_device *dssdev) | |||
955 | taal_hw_reset(dssdev); | 1253 | taal_hw_reset(dssdev); |
956 | } | 1254 | } |
957 | 1255 | ||
958 | omapdss_dsi_display_disable(dssdev); | 1256 | omapdss_dsi_display_disable(dssdev, true, false); |
959 | 1257 | ||
960 | td->enabled = 0; | 1258 | td->enabled = 0; |
961 | } | 1259 | } |
962 | 1260 | ||
1261 | static int taal_panel_reset(struct omap_dss_device *dssdev) | ||
1262 | { | ||
1263 | dev_err(&dssdev->dev, "performing LCD reset\n"); | ||
1264 | |||
1265 | taal_power_off(dssdev); | ||
1266 | taal_hw_reset(dssdev); | ||
1267 | return taal_power_on(dssdev); | ||
1268 | } | ||
1269 | |||
963 | static int taal_enable(struct omap_dss_device *dssdev) | 1270 | static int taal_enable(struct omap_dss_device *dssdev) |
964 | { | 1271 | { |
965 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1272 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
966 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
967 | int r; | 1273 | int r; |
968 | 1274 | ||
969 | dev_dbg(&dssdev->dev, "enable\n"); | 1275 | dev_dbg(&dssdev->dev, "enable\n"); |
@@ -975,18 +1281,16 @@ static int taal_enable(struct omap_dss_device *dssdev) | |||
975 | goto err; | 1281 | goto err; |
976 | } | 1282 | } |
977 | 1283 | ||
978 | dsi_bus_lock(); | 1284 | dsi_bus_lock(dssdev); |
979 | 1285 | ||
980 | r = taal_power_on(dssdev); | 1286 | r = taal_power_on(dssdev); |
981 | 1287 | ||
982 | dsi_bus_unlock(); | 1288 | dsi_bus_unlock(dssdev); |
983 | 1289 | ||
984 | if (r) | 1290 | if (r) |
985 | goto err; | 1291 | goto err; |
986 | 1292 | ||
987 | if (panel_data->use_esd_check) | 1293 | taal_queue_esd_work(dssdev); |
988 | queue_delayed_work(td->esd_wq, &td->esd_work, | ||
989 | TAAL_ESD_CHECK_PERIOD); | ||
990 | 1294 | ||
991 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 1295 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
992 | 1296 | ||
@@ -1007,14 +1311,17 @@ static void taal_disable(struct omap_dss_device *dssdev) | |||
1007 | 1311 | ||
1008 | mutex_lock(&td->lock); | 1312 | mutex_lock(&td->lock); |
1009 | 1313 | ||
1010 | cancel_delayed_work(&td->esd_work); | 1314 | taal_cancel_ulps_work(dssdev); |
1315 | taal_cancel_esd_work(dssdev); | ||
1011 | 1316 | ||
1012 | dsi_bus_lock(); | 1317 | dsi_bus_lock(dssdev); |
1013 | 1318 | ||
1014 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | 1319 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { |
1320 | taal_wake_up(dssdev); | ||
1015 | taal_power_off(dssdev); | 1321 | taal_power_off(dssdev); |
1322 | } | ||
1016 | 1323 | ||
1017 | dsi_bus_unlock(); | 1324 | dsi_bus_unlock(dssdev); |
1018 | 1325 | ||
1019 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 1326 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; |
1020 | 1327 | ||
@@ -1035,13 +1342,16 @@ static int taal_suspend(struct omap_dss_device *dssdev) | |||
1035 | goto err; | 1342 | goto err; |
1036 | } | 1343 | } |
1037 | 1344 | ||
1038 | cancel_delayed_work(&td->esd_work); | 1345 | taal_cancel_ulps_work(dssdev); |
1346 | taal_cancel_esd_work(dssdev); | ||
1039 | 1347 | ||
1040 | dsi_bus_lock(); | 1348 | dsi_bus_lock(dssdev); |
1041 | 1349 | ||
1042 | taal_power_off(dssdev); | 1350 | r = taal_wake_up(dssdev); |
1351 | if (!r) | ||
1352 | taal_power_off(dssdev); | ||
1043 | 1353 | ||
1044 | dsi_bus_unlock(); | 1354 | dsi_bus_unlock(dssdev); |
1045 | 1355 | ||
1046 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | 1356 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; |
1047 | 1357 | ||
@@ -1056,7 +1366,6 @@ err: | |||
1056 | static int taal_resume(struct omap_dss_device *dssdev) | 1366 | static int taal_resume(struct omap_dss_device *dssdev) |
1057 | { | 1367 | { |
1058 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1368 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
1059 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
1060 | int r; | 1369 | int r; |
1061 | 1370 | ||
1062 | dev_dbg(&dssdev->dev, "resume\n"); | 1371 | dev_dbg(&dssdev->dev, "resume\n"); |
@@ -1068,19 +1377,17 @@ static int taal_resume(struct omap_dss_device *dssdev) | |||
1068 | goto err; | 1377 | goto err; |
1069 | } | 1378 | } |
1070 | 1379 | ||
1071 | dsi_bus_lock(); | 1380 | dsi_bus_lock(dssdev); |
1072 | 1381 | ||
1073 | r = taal_power_on(dssdev); | 1382 | r = taal_power_on(dssdev); |
1074 | 1383 | ||
1075 | dsi_bus_unlock(); | 1384 | dsi_bus_unlock(dssdev); |
1076 | 1385 | ||
1077 | if (r) { | 1386 | if (r) { |
1078 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 1387 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; |
1079 | } else { | 1388 | } else { |
1080 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 1389 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
1081 | if (panel_data->use_esd_check) | 1390 | taal_queue_esd_work(dssdev); |
1082 | queue_delayed_work(td->esd_wq, &td->esd_work, | ||
1083 | TAAL_ESD_CHECK_PERIOD); | ||
1084 | } | 1391 | } |
1085 | 1392 | ||
1086 | mutex_unlock(&td->lock); | 1393 | mutex_unlock(&td->lock); |
@@ -1095,7 +1402,7 @@ static void taal_framedone_cb(int err, void *data) | |||
1095 | { | 1402 | { |
1096 | struct omap_dss_device *dssdev = data; | 1403 | struct omap_dss_device *dssdev = data; |
1097 | dev_dbg(&dssdev->dev, "framedone, err %d\n", err); | 1404 | dev_dbg(&dssdev->dev, "framedone, err %d\n", err); |
1098 | dsi_bus_unlock(); | 1405 | dsi_bus_unlock(dssdev); |
1099 | } | 1406 | } |
1100 | 1407 | ||
1101 | static irqreturn_t taal_te_isr(int irq, void *data) | 1408 | static irqreturn_t taal_te_isr(int irq, void *data) |
@@ -1123,7 +1430,7 @@ static irqreturn_t taal_te_isr(int irq, void *data) | |||
1123 | return IRQ_HANDLED; | 1430 | return IRQ_HANDLED; |
1124 | err: | 1431 | err: |
1125 | dev_err(&dssdev->dev, "start update failed\n"); | 1432 | dev_err(&dssdev->dev, "start update failed\n"); |
1126 | dsi_bus_unlock(); | 1433 | dsi_bus_unlock(dssdev); |
1127 | return IRQ_HANDLED; | 1434 | return IRQ_HANDLED; |
1128 | } | 1435 | } |
1129 | 1436 | ||
@@ -1136,7 +1443,7 @@ static void taal_te_timeout_work_callback(struct work_struct *work) | |||
1136 | dev_err(&dssdev->dev, "TE not received for 250ms!\n"); | 1443 | dev_err(&dssdev->dev, "TE not received for 250ms!\n"); |
1137 | 1444 | ||
1138 | atomic_set(&td->do_update, 0); | 1445 | atomic_set(&td->do_update, 0); |
1139 | dsi_bus_unlock(); | 1446 | dsi_bus_unlock(dssdev); |
1140 | } | 1447 | } |
1141 | 1448 | ||
1142 | static int taal_update(struct omap_dss_device *dssdev, | 1449 | static int taal_update(struct omap_dss_device *dssdev, |
@@ -1149,7 +1456,11 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1149 | dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); | 1456 | dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); |
1150 | 1457 | ||
1151 | mutex_lock(&td->lock); | 1458 | mutex_lock(&td->lock); |
1152 | dsi_bus_lock(); | 1459 | dsi_bus_lock(dssdev); |
1460 | |||
1461 | r = taal_wake_up(dssdev); | ||
1462 | if (r) | ||
1463 | goto err; | ||
1153 | 1464 | ||
1154 | if (!td->enabled) { | 1465 | if (!td->enabled) { |
1155 | r = 0; | 1466 | r = 0; |
@@ -1184,7 +1495,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1184 | mutex_unlock(&td->lock); | 1495 | mutex_unlock(&td->lock); |
1185 | return 0; | 1496 | return 0; |
1186 | err: | 1497 | err: |
1187 | dsi_bus_unlock(); | 1498 | dsi_bus_unlock(dssdev); |
1188 | mutex_unlock(&td->lock); | 1499 | mutex_unlock(&td->lock); |
1189 | return r; | 1500 | return r; |
1190 | } | 1501 | } |
@@ -1196,8 +1507,8 @@ static int taal_sync(struct omap_dss_device *dssdev) | |||
1196 | dev_dbg(&dssdev->dev, "sync\n"); | 1507 | dev_dbg(&dssdev->dev, "sync\n"); |
1197 | 1508 | ||
1198 | mutex_lock(&td->lock); | 1509 | mutex_lock(&td->lock); |
1199 | dsi_bus_lock(); | 1510 | dsi_bus_lock(dssdev); |
1200 | dsi_bus_unlock(); | 1511 | dsi_bus_unlock(dssdev); |
1201 | mutex_unlock(&td->lock); | 1512 | mutex_unlock(&td->lock); |
1202 | 1513 | ||
1203 | dev_dbg(&dssdev->dev, "sync done\n"); | 1514 | dev_dbg(&dssdev->dev, "sync done\n"); |
@@ -1235,9 +1546,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1235 | if (td->te_enabled == enable) | 1546 | if (td->te_enabled == enable) |
1236 | goto end; | 1547 | goto end; |
1237 | 1548 | ||
1238 | dsi_bus_lock(); | 1549 | dsi_bus_lock(dssdev); |
1239 | 1550 | ||
1240 | if (td->enabled) { | 1551 | if (td->enabled) { |
1552 | r = taal_wake_up(dssdev); | ||
1553 | if (r) | ||
1554 | goto err; | ||
1555 | |||
1241 | r = _taal_enable_te(dssdev, enable); | 1556 | r = _taal_enable_te(dssdev, enable); |
1242 | if (r) | 1557 | if (r) |
1243 | goto err; | 1558 | goto err; |
@@ -1245,13 +1560,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1245 | 1560 | ||
1246 | td->te_enabled = enable; | 1561 | td->te_enabled = enable; |
1247 | 1562 | ||
1248 | dsi_bus_unlock(); | 1563 | dsi_bus_unlock(dssdev); |
1249 | end: | 1564 | end: |
1250 | mutex_unlock(&td->lock); | 1565 | mutex_unlock(&td->lock); |
1251 | 1566 | ||
1252 | return 0; | 1567 | return 0; |
1253 | err: | 1568 | err: |
1254 | dsi_bus_unlock(); | 1569 | dsi_bus_unlock(dssdev); |
1255 | mutex_unlock(&td->lock); | 1570 | mutex_unlock(&td->lock); |
1256 | 1571 | ||
1257 | return r; | 1572 | return r; |
@@ -1281,9 +1596,13 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | |||
1281 | if (td->rotate == rotate) | 1596 | if (td->rotate == rotate) |
1282 | goto end; | 1597 | goto end; |
1283 | 1598 | ||
1284 | dsi_bus_lock(); | 1599 | dsi_bus_lock(dssdev); |
1285 | 1600 | ||
1286 | if (td->enabled) { | 1601 | if (td->enabled) { |
1602 | r = taal_wake_up(dssdev); | ||
1603 | if (r) | ||
1604 | goto err; | ||
1605 | |||
1287 | r = taal_set_addr_mode(td, rotate, td->mirror); | 1606 | r = taal_set_addr_mode(td, rotate, td->mirror); |
1288 | if (r) | 1607 | if (r) |
1289 | goto err; | 1608 | goto err; |
@@ -1291,12 +1610,12 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | |||
1291 | 1610 | ||
1292 | td->rotate = rotate; | 1611 | td->rotate = rotate; |
1293 | 1612 | ||
1294 | dsi_bus_unlock(); | 1613 | dsi_bus_unlock(dssdev); |
1295 | end: | 1614 | end: |
1296 | mutex_unlock(&td->lock); | 1615 | mutex_unlock(&td->lock); |
1297 | return 0; | 1616 | return 0; |
1298 | err: | 1617 | err: |
1299 | dsi_bus_unlock(); | 1618 | dsi_bus_unlock(dssdev); |
1300 | mutex_unlock(&td->lock); | 1619 | mutex_unlock(&td->lock); |
1301 | return r; | 1620 | return r; |
1302 | } | 1621 | } |
@@ -1325,8 +1644,12 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | |||
1325 | if (td->mirror == enable) | 1644 | if (td->mirror == enable) |
1326 | goto end; | 1645 | goto end; |
1327 | 1646 | ||
1328 | dsi_bus_lock(); | 1647 | dsi_bus_lock(dssdev); |
1329 | if (td->enabled) { | 1648 | if (td->enabled) { |
1649 | r = taal_wake_up(dssdev); | ||
1650 | if (r) | ||
1651 | goto err; | ||
1652 | |||
1330 | r = taal_set_addr_mode(td, td->rotate, enable); | 1653 | r = taal_set_addr_mode(td, td->rotate, enable); |
1331 | if (r) | 1654 | if (r) |
1332 | goto err; | 1655 | goto err; |
@@ -1334,12 +1657,12 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | |||
1334 | 1657 | ||
1335 | td->mirror = enable; | 1658 | td->mirror = enable; |
1336 | 1659 | ||
1337 | dsi_bus_unlock(); | 1660 | dsi_bus_unlock(dssdev); |
1338 | end: | 1661 | end: |
1339 | mutex_unlock(&td->lock); | 1662 | mutex_unlock(&td->lock); |
1340 | return 0; | 1663 | return 0; |
1341 | err: | 1664 | err: |
1342 | dsi_bus_unlock(); | 1665 | dsi_bus_unlock(dssdev); |
1343 | mutex_unlock(&td->lock); | 1666 | mutex_unlock(&td->lock); |
1344 | return r; | 1667 | return r; |
1345 | } | 1668 | } |
@@ -1369,7 +1692,11 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | |||
1369 | goto err1; | 1692 | goto err1; |
1370 | } | 1693 | } |
1371 | 1694 | ||
1372 | dsi_bus_lock(); | 1695 | dsi_bus_lock(dssdev); |
1696 | |||
1697 | r = taal_wake_up(dssdev); | ||
1698 | if (r) | ||
1699 | goto err2; | ||
1373 | 1700 | ||
1374 | r = taal_dcs_read_1(td, DCS_GET_ID1, &id1); | 1701 | r = taal_dcs_read_1(td, DCS_GET_ID1, &id1); |
1375 | if (r) | 1702 | if (r) |
@@ -1381,11 +1708,11 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | |||
1381 | if (r) | 1708 | if (r) |
1382 | goto err2; | 1709 | goto err2; |
1383 | 1710 | ||
1384 | dsi_bus_unlock(); | 1711 | dsi_bus_unlock(dssdev); |
1385 | mutex_unlock(&td->lock); | 1712 | mutex_unlock(&td->lock); |
1386 | return 0; | 1713 | return 0; |
1387 | err2: | 1714 | err2: |
1388 | dsi_bus_unlock(); | 1715 | dsi_bus_unlock(dssdev); |
1389 | err1: | 1716 | err1: |
1390 | mutex_unlock(&td->lock); | 1717 | mutex_unlock(&td->lock); |
1391 | return r; | 1718 | return r; |
@@ -1415,7 +1742,11 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1415 | dssdev->panel.timings.x_res * | 1742 | dssdev->panel.timings.x_res * |
1416 | dssdev->panel.timings.y_res * 3); | 1743 | dssdev->panel.timings.y_res * 3); |
1417 | 1744 | ||
1418 | dsi_bus_lock(); | 1745 | dsi_bus_lock(dssdev); |
1746 | |||
1747 | r = taal_wake_up(dssdev); | ||
1748 | if (r) | ||
1749 | goto err2; | ||
1419 | 1750 | ||
1420 | /* plen 1 or 2 goes into short packet. until checksum error is fixed, | 1751 | /* plen 1 or 2 goes into short packet. until checksum error is fixed, |
1421 | * use short packets. plen 32 works, but bigger packets seem to cause | 1752 | * use short packets. plen 32 works, but bigger packets seem to cause |
@@ -1427,7 +1758,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1427 | 1758 | ||
1428 | taal_set_update_window(td, x, y, w, h); | 1759 | taal_set_update_window(td, x, y, w, h); |
1429 | 1760 | ||
1430 | r = dsi_vc_set_max_rx_packet_size(td->channel, plen); | 1761 | r = dsi_vc_set_max_rx_packet_size(dssdev, td->channel, plen); |
1431 | if (r) | 1762 | if (r) |
1432 | goto err2; | 1763 | goto err2; |
1433 | 1764 | ||
@@ -1435,7 +1766,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1435 | u8 dcs_cmd = first ? 0x2e : 0x3e; | 1766 | u8 dcs_cmd = first ? 0x2e : 0x3e; |
1436 | first = 0; | 1767 | first = 0; |
1437 | 1768 | ||
1438 | r = dsi_vc_dcs_read(td->channel, dcs_cmd, | 1769 | r = dsi_vc_dcs_read(dssdev, td->channel, dcs_cmd, |
1439 | buf + buf_used, size - buf_used); | 1770 | buf + buf_used, size - buf_used); |
1440 | 1771 | ||
1441 | if (r < 0) { | 1772 | if (r < 0) { |
@@ -1461,14 +1792,35 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1461 | r = buf_used; | 1792 | r = buf_used; |
1462 | 1793 | ||
1463 | err3: | 1794 | err3: |
1464 | dsi_vc_set_max_rx_packet_size(td->channel, 1); | 1795 | dsi_vc_set_max_rx_packet_size(dssdev, td->channel, 1); |
1465 | err2: | 1796 | err2: |
1466 | dsi_bus_unlock(); | 1797 | dsi_bus_unlock(dssdev); |
1467 | err1: | 1798 | err1: |
1468 | mutex_unlock(&td->lock); | 1799 | mutex_unlock(&td->lock); |
1469 | return r; | 1800 | return r; |
1470 | } | 1801 | } |
1471 | 1802 | ||
1803 | static void taal_ulps_work(struct work_struct *work) | ||
1804 | { | ||
1805 | struct taal_data *td = container_of(work, struct taal_data, | ||
1806 | ulps_work.work); | ||
1807 | struct omap_dss_device *dssdev = td->dssdev; | ||
1808 | |||
1809 | mutex_lock(&td->lock); | ||
1810 | |||
1811 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !td->enabled) { | ||
1812 | mutex_unlock(&td->lock); | ||
1813 | return; | ||
1814 | } | ||
1815 | |||
1816 | dsi_bus_lock(dssdev); | ||
1817 | |||
1818 | taal_enter_ulps(dssdev); | ||
1819 | |||
1820 | dsi_bus_unlock(dssdev); | ||
1821 | mutex_unlock(&td->lock); | ||
1822 | } | ||
1823 | |||
1472 | static void taal_esd_work(struct work_struct *work) | 1824 | static void taal_esd_work(struct work_struct *work) |
1473 | { | 1825 | { |
1474 | struct taal_data *td = container_of(work, struct taal_data, | 1826 | struct taal_data *td = container_of(work, struct taal_data, |
@@ -1485,7 +1837,13 @@ static void taal_esd_work(struct work_struct *work) | |||
1485 | return; | 1837 | return; |
1486 | } | 1838 | } |
1487 | 1839 | ||
1488 | dsi_bus_lock(); | 1840 | dsi_bus_lock(dssdev); |
1841 | |||
1842 | r = taal_wake_up(dssdev); | ||
1843 | if (r) { | ||
1844 | dev_err(&dssdev->dev, "failed to exit ULPS\n"); | ||
1845 | goto err; | ||
1846 | } | ||
1489 | 1847 | ||
1490 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); | 1848 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); |
1491 | if (r) { | 1849 | if (r) { |
@@ -1521,22 +1879,20 @@ static void taal_esd_work(struct work_struct *work) | |||
1521 | goto err; | 1879 | goto err; |
1522 | } | 1880 | } |
1523 | 1881 | ||
1524 | dsi_bus_unlock(); | 1882 | dsi_bus_unlock(dssdev); |
1525 | 1883 | ||
1526 | queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); | 1884 | taal_queue_esd_work(dssdev); |
1527 | 1885 | ||
1528 | mutex_unlock(&td->lock); | 1886 | mutex_unlock(&td->lock); |
1529 | return; | 1887 | return; |
1530 | err: | 1888 | err: |
1531 | dev_err(&dssdev->dev, "performing LCD reset\n"); | 1889 | dev_err(&dssdev->dev, "performing LCD reset\n"); |
1532 | 1890 | ||
1533 | taal_power_off(dssdev); | 1891 | taal_panel_reset(dssdev); |
1534 | taal_hw_reset(dssdev); | ||
1535 | taal_power_on(dssdev); | ||
1536 | 1892 | ||
1537 | dsi_bus_unlock(); | 1893 | dsi_bus_unlock(dssdev); |
1538 | 1894 | ||
1539 | queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); | 1895 | taal_queue_esd_work(dssdev); |
1540 | 1896 | ||
1541 | mutex_unlock(&td->lock); | 1897 | mutex_unlock(&td->lock); |
1542 | } | 1898 | } |
@@ -1557,7 +1913,7 @@ static enum omap_dss_update_mode taal_get_update_mode( | |||
1557 | 1913 | ||
1558 | static struct omap_dss_driver taal_driver = { | 1914 | static struct omap_dss_driver taal_driver = { |
1559 | .probe = taal_probe, | 1915 | .probe = taal_probe, |
1560 | .remove = taal_remove, | 1916 | .remove = __exit_p(taal_remove), |
1561 | 1917 | ||
1562 | .enable = taal_enable, | 1918 | .enable = taal_enable, |
1563 | .disable = taal_disable, | 1919 | .disable = taal_disable, |
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c index dbe9d43b4850..2462b9ec6662 100644 --- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | 19 | ||
20 | #include <plat/display.h> | 20 | #include <video/omapdss.h> |
21 | 21 | ||
22 | #define TPO_R02_MODE(x) ((x) & 7) | 22 | #define TPO_R02_MODE(x) ((x) & 7) |
23 | #define TPO_R02_MODE_800x480 7 | 23 | #define TPO_R02_MODE_800x480 7 |
@@ -144,13 +144,15 @@ static ssize_t tpo_td043_vmirror_store(struct device *dev, | |||
144 | struct device_attribute *attr, const char *buf, size_t count) | 144 | struct device_attribute *attr, const char *buf, size_t count) |
145 | { | 145 | { |
146 | struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev); | 146 | struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev); |
147 | long val; | 147 | int val; |
148 | int ret; | 148 | int ret; |
149 | 149 | ||
150 | ret = strict_strtol(buf, 0, &val); | 150 | ret = kstrtoint(buf, 0, &val); |
151 | if (ret < 0) | 151 | if (ret < 0) |
152 | return ret; | 152 | return ret; |
153 | 153 | ||
154 | val = !!val; | ||
155 | |||
154 | ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val); | 156 | ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val); |
155 | if (ret < 0) | 157 | if (ret < 0) |
156 | return ret; | 158 | return ret; |
@@ -175,7 +177,7 @@ static ssize_t tpo_td043_mode_store(struct device *dev, | |||
175 | long val; | 177 | long val; |
176 | int ret; | 178 | int ret; |
177 | 179 | ||
178 | ret = strict_strtol(buf, 0, &val); | 180 | ret = kstrtol(buf, 0, &val); |
179 | if (ret != 0 || val & ~7) | 181 | if (ret != 0 || val & ~7) |
180 | return -EINVAL; | 182 | return -EINVAL; |
181 | 183 | ||
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index bfc5da0e9700..6b3e2da11419 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig | |||
@@ -80,7 +80,7 @@ config OMAP2_DSS_SDI | |||
80 | 80 | ||
81 | config OMAP2_DSS_DSI | 81 | config OMAP2_DSS_DSI |
82 | bool "DSI support" | 82 | bool "DSI support" |
83 | depends on ARCH_OMAP3 | 83 | depends on ARCH_OMAP3 || ARCH_OMAP4 |
84 | default n | 84 | default n |
85 | help | 85 | help |
86 | MIPI DSI (Display Serial Interface) support. | 86 | MIPI DSI (Display Serial Interface) support. |
@@ -90,14 +90,6 @@ config OMAP2_DSS_DSI | |||
90 | 90 | ||
91 | See http://www.mipi.org/ for DSI spesifications. | 91 | See http://www.mipi.org/ for DSI spesifications. |
92 | 92 | ||
93 | config OMAP2_DSS_USE_DSI_PLL | ||
94 | bool "Use DSI PLL for PCLK (EXPERIMENTAL)" | ||
95 | default n | ||
96 | depends on OMAP2_DSS_DSI | ||
97 | help | ||
98 | Use DSI PLL to generate pixel clock. Currently only for DPI output. | ||
99 | DSI PLL can be used to generate higher and more precise pixel clocks. | ||
100 | |||
101 | config OMAP2_DSS_FAKE_VSYNC | 93 | config OMAP2_DSS_FAKE_VSYNC |
102 | bool "Fake VSYNC irq from manual update displays" | 94 | bool "Fake VSYNC irq from manual update displays" |
103 | default n | 95 | default n |
@@ -125,4 +117,27 @@ config OMAP2_DSS_MIN_FCK_PER_PCK | |||
125 | Max FCK is 173MHz, so this doesn't work if your PCK | 117 | Max FCK is 173MHz, so this doesn't work if your PCK |
126 | is very high. | 118 | is very high. |
127 | 119 | ||
120 | config OMAP2_DSS_SLEEP_BEFORE_RESET | ||
121 | bool "Sleep 50ms before DSS reset" | ||
122 | default y | ||
123 | help | ||
124 | For some unknown reason we may get SYNC_LOST errors from the display | ||
125 | subsystem at initialization time if we don't sleep before resetting | ||
126 | the DSS. See the source (dss.c) for more comments. | ||
127 | |||
128 | However, 50ms is quite long time to sleep, and with some | ||
129 | configurations the SYNC_LOST may never happen, so the sleep can | ||
130 | be disabled here. | ||
131 | |||
132 | config OMAP2_DSS_SLEEP_AFTER_VENC_RESET | ||
133 | bool "Sleep 20ms after VENC reset" | ||
134 | default y | ||
135 | help | ||
136 | There is a 20ms sleep after VENC reset which seemed to fix the | ||
137 | reset. The reason for the bug is unclear, and it's also unclear | ||
138 | on what platforms this happens. | ||
139 | |||
140 | This option enables the sleep, and is enabled by default. You can | ||
141 | disable the sleep if it doesn't cause problems on your platform. | ||
142 | |||
128 | endif | 143 | endif |
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 1aa2ed1e786e..3da426719dd6 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/device.h> | 33 | #include <linux/device.h> |
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | 35 | ||
36 | #include <plat/display.h> | 36 | #include <video/omapdss.h> |
37 | 37 | ||
38 | #include "dss.h" | 38 | #include "dss.h" |
39 | #include "dss_features.h" | 39 | #include "dss_features.h" |
@@ -54,6 +54,9 @@ unsigned int dss_debug; | |||
54 | module_param_named(debug, dss_debug, bool, 0644); | 54 | module_param_named(debug, dss_debug, bool, 0644); |
55 | #endif | 55 | #endif |
56 | 56 | ||
57 | static int omap_dss_register_device(struct omap_dss_device *); | ||
58 | static void omap_dss_unregister_device(struct omap_dss_device *); | ||
59 | |||
57 | /* REGULATORS */ | 60 | /* REGULATORS */ |
58 | 61 | ||
59 | struct regulator *dss_get_vdds_dsi(void) | 62 | struct regulator *dss_get_vdds_dsi(void) |
@@ -124,8 +127,7 @@ static int dss_initialize_debugfs(void) | |||
124 | #endif | 127 | #endif |
125 | 128 | ||
126 | #if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS) | 129 | #if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS) |
127 | debugfs_create_file("dsi_irq", S_IRUGO, dss_debugfs_dir, | 130 | dsi_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops); |
128 | &dsi_dump_irqs, &dss_debug_fops); | ||
129 | #endif | 131 | #endif |
130 | 132 | ||
131 | debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, | 133 | debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, |
@@ -137,8 +139,7 @@ static int dss_initialize_debugfs(void) | |||
137 | &rfbi_dump_regs, &dss_debug_fops); | 139 | &rfbi_dump_regs, &dss_debug_fops); |
138 | #endif | 140 | #endif |
139 | #ifdef CONFIG_OMAP2_DSS_DSI | 141 | #ifdef CONFIG_OMAP2_DSS_DSI |
140 | debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir, | 142 | dsi_create_debugfs_files_reg(dss_debugfs_dir, &dss_debug_fops); |
141 | &dsi_dump_regs, &dss_debug_fops); | ||
142 | #endif | 143 | #endif |
143 | #ifdef CONFIG_OMAP2_DSS_VENC | 144 | #ifdef CONFIG_OMAP2_DSS_VENC |
144 | debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, | 145 | debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, |
@@ -480,7 +481,7 @@ static void omap_dss_dev_release(struct device *dev) | |||
480 | reset_device(dev, 0); | 481 | reset_device(dev, 0); |
481 | } | 482 | } |
482 | 483 | ||
483 | int omap_dss_register_device(struct omap_dss_device *dssdev) | 484 | static int omap_dss_register_device(struct omap_dss_device *dssdev) |
484 | { | 485 | { |
485 | static int dev_num; | 486 | static int dev_num; |
486 | 487 | ||
@@ -494,7 +495,7 @@ int omap_dss_register_device(struct omap_dss_device *dssdev) | |||
494 | return device_register(&dssdev->dev); | 495 | return device_register(&dssdev->dev); |
495 | } | 496 | } |
496 | 497 | ||
497 | void omap_dss_unregister_device(struct omap_dss_device *dssdev) | 498 | static void omap_dss_unregister_device(struct omap_dss_device *dssdev) |
498 | { | 499 | { |
499 | device_unregister(&dssdev->dev); | 500 | device_unregister(&dssdev->dev); |
500 | } | 501 | } |
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 7804779c9da1..7a9a2e7d9685 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -37,99 +37,15 @@ | |||
37 | #include <plat/sram.h> | 37 | #include <plat/sram.h> |
38 | #include <plat/clock.h> | 38 | #include <plat/clock.h> |
39 | 39 | ||
40 | #include <plat/display.h> | 40 | #include <video/omapdss.h> |
41 | 41 | ||
42 | #include "dss.h" | 42 | #include "dss.h" |
43 | #include "dss_features.h" | 43 | #include "dss_features.h" |
44 | #include "dispc.h" | ||
44 | 45 | ||
45 | /* DISPC */ | 46 | /* DISPC */ |
46 | #define DISPC_SZ_REGS SZ_4K | 47 | #define DISPC_SZ_REGS SZ_4K |
47 | 48 | ||
48 | struct dispc_reg { u16 idx; }; | ||
49 | |||
50 | #define DISPC_REG(idx) ((const struct dispc_reg) { idx }) | ||
51 | |||
52 | /* | ||
53 | * DISPC common registers and | ||
54 | * DISPC channel registers , ch = 0 for LCD, ch = 1 for | ||
55 | * DIGIT, and ch = 2 for LCD2 | ||
56 | */ | ||
57 | #define DISPC_REVISION DISPC_REG(0x0000) | ||
58 | #define DISPC_SYSCONFIG DISPC_REG(0x0010) | ||
59 | #define DISPC_SYSSTATUS DISPC_REG(0x0014) | ||
60 | #define DISPC_IRQSTATUS DISPC_REG(0x0018) | ||
61 | #define DISPC_IRQENABLE DISPC_REG(0x001C) | ||
62 | #define DISPC_CONTROL DISPC_REG(0x0040) | ||
63 | #define DISPC_CONTROL2 DISPC_REG(0x0238) | ||
64 | #define DISPC_CONFIG DISPC_REG(0x0044) | ||
65 | #define DISPC_CONFIG2 DISPC_REG(0x0620) | ||
66 | #define DISPC_CAPABLE DISPC_REG(0x0048) | ||
67 | #define DISPC_DEFAULT_COLOR(ch) DISPC_REG(ch == 0 ? 0x004C : \ | ||
68 | (ch == 1 ? 0x0050 : 0x03AC)) | ||
69 | #define DISPC_TRANS_COLOR(ch) DISPC_REG(ch == 0 ? 0x0054 : \ | ||
70 | (ch == 1 ? 0x0058 : 0x03B0)) | ||
71 | #define DISPC_LINE_STATUS DISPC_REG(0x005C) | ||
72 | #define DISPC_LINE_NUMBER DISPC_REG(0x0060) | ||
73 | #define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400) | ||
74 | #define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404) | ||
75 | #define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408) | ||
76 | #define DISPC_DIVISORo(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C) | ||
77 | #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) | ||
78 | #define DISPC_SIZE_DIG DISPC_REG(0x0078) | ||
79 | #define DISPC_SIZE_LCD(ch) DISPC_REG(ch != 2 ? 0x007C : 0x03CC) | ||
80 | |||
81 | /* DISPC GFX plane */ | ||
82 | #define DISPC_GFX_BA0 DISPC_REG(0x0080) | ||
83 | #define DISPC_GFX_BA1 DISPC_REG(0x0084) | ||
84 | #define DISPC_GFX_POSITION DISPC_REG(0x0088) | ||
85 | #define DISPC_GFX_SIZE DISPC_REG(0x008C) | ||
86 | #define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0) | ||
87 | #define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4) | ||
88 | #define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8) | ||
89 | #define DISPC_GFX_ROW_INC DISPC_REG(0x00AC) | ||
90 | #define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0) | ||
91 | #define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4) | ||
92 | #define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8) | ||
93 | |||
94 | #define DISPC_DATA_CYCLE1(ch) DISPC_REG(ch != 2 ? 0x01D4 : 0x03C0) | ||
95 | #define DISPC_DATA_CYCLE2(ch) DISPC_REG(ch != 2 ? 0x01D8 : 0x03C4) | ||
96 | #define DISPC_DATA_CYCLE3(ch) DISPC_REG(ch != 2 ? 0x01DC : 0x03C8) | ||
97 | #define DISPC_CPR_COEF_R(ch) DISPC_REG(ch != 2 ? 0x0220 : 0x03BC) | ||
98 | #define DISPC_CPR_COEF_G(ch) DISPC_REG(ch != 2 ? 0x0224 : 0x03B8) | ||
99 | #define DISPC_CPR_COEF_B(ch) DISPC_REG(ch != 2 ? 0x0228 : 0x03B4) | ||
100 | |||
101 | #define DISPC_GFX_PRELOAD DISPC_REG(0x022C) | ||
102 | |||
103 | /* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */ | ||
104 | #define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx) | ||
105 | |||
106 | #define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000) | ||
107 | #define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004) | ||
108 | #define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008) | ||
109 | #define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C) | ||
110 | #define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010) | ||
111 | #define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014) | ||
112 | #define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018) | ||
113 | #define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C) | ||
114 | #define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020) | ||
115 | #define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024) | ||
116 | #define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028) | ||
117 | #define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C) | ||
118 | #define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030) | ||
119 | |||
120 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
121 | #define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8) | ||
122 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
123 | #define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8) | ||
124 | /* coef index i = {0, 1, 2, 3, 4} */ | ||
125 | #define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4) | ||
126 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
127 | #define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4) | ||
128 | |||
129 | #define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) | ||
130 | |||
131 | #define DISPC_DIVISOR DISPC_REG(0x0804) | ||
132 | |||
133 | #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ | 49 | #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ |
134 | DISPC_IRQ_OCP_ERR | \ | 50 | DISPC_IRQ_OCP_ERR | \ |
135 | DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ | 51 | DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ |
@@ -167,10 +83,6 @@ struct dispc_v_coef { | |||
167 | #define REG_FLD_MOD(idx, val, start, end) \ | 83 | #define REG_FLD_MOD(idx, val, start, end) \ |
168 | dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) | 84 | dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) |
169 | 85 | ||
170 | static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES, | ||
171 | DISPC_VID_ATTRIBUTES(0), | ||
172 | DISPC_VID_ATTRIBUTES(1) }; | ||
173 | |||
174 | struct dispc_irq_stats { | 86 | struct dispc_irq_stats { |
175 | unsigned long last_reset; | 87 | unsigned long last_reset; |
176 | unsigned irq_count; | 88 | unsigned irq_count; |
@@ -198,25 +110,38 @@ static struct { | |||
198 | #endif | 110 | #endif |
199 | } dispc; | 111 | } dispc; |
200 | 112 | ||
113 | enum omap_color_component { | ||
114 | /* used for all color formats for OMAP3 and earlier | ||
115 | * and for RGB and Y color component on OMAP4 | ||
116 | */ | ||
117 | DISPC_COLOR_COMPONENT_RGB_Y = 1 << 0, | ||
118 | /* used for UV component for | ||
119 | * OMAP_DSS_COLOR_YUV2, OMAP_DSS_COLOR_UYVY, OMAP_DSS_COLOR_NV12 | ||
120 | * color formats on OMAP4 | ||
121 | */ | ||
122 | DISPC_COLOR_COMPONENT_UV = 1 << 1, | ||
123 | }; | ||
124 | |||
201 | static void _omap_dispc_set_irqs(void); | 125 | static void _omap_dispc_set_irqs(void); |
202 | 126 | ||
203 | static inline void dispc_write_reg(const struct dispc_reg idx, u32 val) | 127 | static inline void dispc_write_reg(const u16 idx, u32 val) |
204 | { | 128 | { |
205 | __raw_writel(val, dispc.base + idx.idx); | 129 | __raw_writel(val, dispc.base + idx); |
206 | } | 130 | } |
207 | 131 | ||
208 | static inline u32 dispc_read_reg(const struct dispc_reg idx) | 132 | static inline u32 dispc_read_reg(const u16 idx) |
209 | { | 133 | { |
210 | return __raw_readl(dispc.base + idx.idx); | 134 | return __raw_readl(dispc.base + idx); |
211 | } | 135 | } |
212 | 136 | ||
213 | #define SR(reg) \ | 137 | #define SR(reg) \ |
214 | dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg) | 138 | dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) |
215 | #define RR(reg) \ | 139 | #define RR(reg) \ |
216 | dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)]) | 140 | dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)]) |
217 | 141 | ||
218 | void dispc_save_context(void) | 142 | void dispc_save_context(void) |
219 | { | 143 | { |
144 | int i; | ||
220 | if (cpu_is_omap24xx()) | 145 | if (cpu_is_omap24xx()) |
221 | return; | 146 | return; |
222 | 147 | ||
@@ -224,157 +149,153 @@ void dispc_save_context(void) | |||
224 | SR(IRQENABLE); | 149 | SR(IRQENABLE); |
225 | SR(CONTROL); | 150 | SR(CONTROL); |
226 | SR(CONFIG); | 151 | SR(CONFIG); |
227 | SR(DEFAULT_COLOR(0)); | 152 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); |
228 | SR(DEFAULT_COLOR(1)); | 153 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
229 | SR(TRANS_COLOR(0)); | 154 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); |
230 | SR(TRANS_COLOR(1)); | 155 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
231 | SR(LINE_NUMBER); | 156 | SR(LINE_NUMBER); |
232 | SR(TIMING_H(0)); | 157 | SR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); |
233 | SR(TIMING_V(0)); | 158 | SR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); |
234 | SR(POL_FREQ(0)); | 159 | SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); |
235 | SR(DIVISORo(0)); | 160 | SR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); |
236 | SR(GLOBAL_ALPHA); | 161 | SR(GLOBAL_ALPHA); |
237 | SR(SIZE_DIG); | 162 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); |
238 | SR(SIZE_LCD(0)); | 163 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); |
239 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 164 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
240 | SR(CONTROL2); | 165 | SR(CONTROL2); |
241 | SR(DEFAULT_COLOR(2)); | 166 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
242 | SR(TRANS_COLOR(2)); | 167 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
243 | SR(SIZE_LCD(2)); | 168 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); |
244 | SR(TIMING_H(2)); | 169 | SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2)); |
245 | SR(TIMING_V(2)); | 170 | SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2)); |
246 | SR(POL_FREQ(2)); | 171 | SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); |
247 | SR(DIVISORo(2)); | 172 | SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2)); |
248 | SR(CONFIG2); | 173 | SR(CONFIG2); |
249 | } | 174 | } |
250 | 175 | ||
251 | SR(GFX_BA0); | 176 | SR(OVL_BA0(OMAP_DSS_GFX)); |
252 | SR(GFX_BA1); | 177 | SR(OVL_BA1(OMAP_DSS_GFX)); |
253 | SR(GFX_POSITION); | 178 | SR(OVL_POSITION(OMAP_DSS_GFX)); |
254 | SR(GFX_SIZE); | 179 | SR(OVL_SIZE(OMAP_DSS_GFX)); |
255 | SR(GFX_ATTRIBUTES); | 180 | SR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); |
256 | SR(GFX_FIFO_THRESHOLD); | 181 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); |
257 | SR(GFX_ROW_INC); | 182 | SR(OVL_ROW_INC(OMAP_DSS_GFX)); |
258 | SR(GFX_PIXEL_INC); | 183 | SR(OVL_PIXEL_INC(OMAP_DSS_GFX)); |
259 | SR(GFX_WINDOW_SKIP); | 184 | SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); |
260 | SR(GFX_TABLE_BA); | 185 | SR(OVL_TABLE_BA(OMAP_DSS_GFX)); |
261 | 186 | ||
262 | SR(DATA_CYCLE1(0)); | 187 | SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); |
263 | SR(DATA_CYCLE2(0)); | 188 | SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); |
264 | SR(DATA_CYCLE3(0)); | 189 | SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); |
265 | 190 | ||
266 | SR(CPR_COEF_R(0)); | 191 | SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); |
267 | SR(CPR_COEF_G(0)); | 192 | SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); |
268 | SR(CPR_COEF_B(0)); | 193 | SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); |
269 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 194 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
270 | SR(CPR_COEF_B(2)); | 195 | SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); |
271 | SR(CPR_COEF_G(2)); | 196 | SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); |
272 | SR(CPR_COEF_R(2)); | 197 | SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); |
273 | 198 | ||
274 | SR(DATA_CYCLE1(2)); | 199 | SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); |
275 | SR(DATA_CYCLE2(2)); | 200 | SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); |
276 | SR(DATA_CYCLE3(2)); | 201 | SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); |
277 | } | 202 | } |
278 | 203 | ||
279 | SR(GFX_PRELOAD); | 204 | SR(OVL_PRELOAD(OMAP_DSS_GFX)); |
280 | 205 | ||
281 | /* VID1 */ | 206 | /* VID1 */ |
282 | SR(VID_BA0(0)); | 207 | SR(OVL_BA0(OMAP_DSS_VIDEO1)); |
283 | SR(VID_BA1(0)); | 208 | SR(OVL_BA1(OMAP_DSS_VIDEO1)); |
284 | SR(VID_POSITION(0)); | 209 | SR(OVL_POSITION(OMAP_DSS_VIDEO1)); |
285 | SR(VID_SIZE(0)); | 210 | SR(OVL_SIZE(OMAP_DSS_VIDEO1)); |
286 | SR(VID_ATTRIBUTES(0)); | 211 | SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); |
287 | SR(VID_FIFO_THRESHOLD(0)); | 212 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); |
288 | SR(VID_ROW_INC(0)); | 213 | SR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); |
289 | SR(VID_PIXEL_INC(0)); | 214 | SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); |
290 | SR(VID_FIR(0)); | 215 | SR(OVL_FIR(OMAP_DSS_VIDEO1)); |
291 | SR(VID_PICTURE_SIZE(0)); | 216 | SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); |
292 | SR(VID_ACCU0(0)); | 217 | SR(OVL_ACCU0(OMAP_DSS_VIDEO1)); |
293 | SR(VID_ACCU1(0)); | 218 | SR(OVL_ACCU1(OMAP_DSS_VIDEO1)); |
294 | 219 | ||
295 | SR(VID_FIR_COEF_H(0, 0)); | 220 | for (i = 0; i < 8; i++) |
296 | SR(VID_FIR_COEF_H(0, 1)); | 221 | SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); |
297 | SR(VID_FIR_COEF_H(0, 2)); | 222 | |
298 | SR(VID_FIR_COEF_H(0, 3)); | 223 | for (i = 0; i < 8; i++) |
299 | SR(VID_FIR_COEF_H(0, 4)); | 224 | SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i)); |
300 | SR(VID_FIR_COEF_H(0, 5)); | 225 | |
301 | SR(VID_FIR_COEF_H(0, 6)); | 226 | for (i = 0; i < 5; i++) |
302 | SR(VID_FIR_COEF_H(0, 7)); | 227 | SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); |
303 | 228 | ||
304 | SR(VID_FIR_COEF_HV(0, 0)); | 229 | for (i = 0; i < 8; i++) |
305 | SR(VID_FIR_COEF_HV(0, 1)); | 230 | SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); |
306 | SR(VID_FIR_COEF_HV(0, 2)); | 231 | |
307 | SR(VID_FIR_COEF_HV(0, 3)); | 232 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
308 | SR(VID_FIR_COEF_HV(0, 4)); | 233 | SR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); |
309 | SR(VID_FIR_COEF_HV(0, 5)); | 234 | SR(OVL_BA1_UV(OMAP_DSS_VIDEO1)); |
310 | SR(VID_FIR_COEF_HV(0, 6)); | 235 | SR(OVL_FIR2(OMAP_DSS_VIDEO1)); |
311 | SR(VID_FIR_COEF_HV(0, 7)); | 236 | SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1)); |
312 | 237 | SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1)); | |
313 | SR(VID_CONV_COEF(0, 0)); | 238 | |
314 | SR(VID_CONV_COEF(0, 1)); | 239 | for (i = 0; i < 8; i++) |
315 | SR(VID_CONV_COEF(0, 2)); | 240 | SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i)); |
316 | SR(VID_CONV_COEF(0, 3)); | 241 | |
317 | SR(VID_CONV_COEF(0, 4)); | 242 | for (i = 0; i < 8; i++) |
318 | 243 | SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i)); | |
319 | SR(VID_FIR_COEF_V(0, 0)); | 244 | |
320 | SR(VID_FIR_COEF_V(0, 1)); | 245 | for (i = 0; i < 8; i++) |
321 | SR(VID_FIR_COEF_V(0, 2)); | 246 | SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i)); |
322 | SR(VID_FIR_COEF_V(0, 3)); | 247 | } |
323 | SR(VID_FIR_COEF_V(0, 4)); | 248 | if (dss_has_feature(FEAT_ATTR2)) |
324 | SR(VID_FIR_COEF_V(0, 5)); | 249 | SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); |
325 | SR(VID_FIR_COEF_V(0, 6)); | 250 | |
326 | SR(VID_FIR_COEF_V(0, 7)); | 251 | SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); |
327 | |||
328 | SR(VID_PRELOAD(0)); | ||
329 | 252 | ||
330 | /* VID2 */ | 253 | /* VID2 */ |
331 | SR(VID_BA0(1)); | 254 | SR(OVL_BA0(OMAP_DSS_VIDEO2)); |
332 | SR(VID_BA1(1)); | 255 | SR(OVL_BA1(OMAP_DSS_VIDEO2)); |
333 | SR(VID_POSITION(1)); | 256 | SR(OVL_POSITION(OMAP_DSS_VIDEO2)); |
334 | SR(VID_SIZE(1)); | 257 | SR(OVL_SIZE(OMAP_DSS_VIDEO2)); |
335 | SR(VID_ATTRIBUTES(1)); | 258 | SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); |
336 | SR(VID_FIFO_THRESHOLD(1)); | 259 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); |
337 | SR(VID_ROW_INC(1)); | 260 | SR(OVL_ROW_INC(OMAP_DSS_VIDEO2)); |
338 | SR(VID_PIXEL_INC(1)); | 261 | SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); |
339 | SR(VID_FIR(1)); | 262 | SR(OVL_FIR(OMAP_DSS_VIDEO2)); |
340 | SR(VID_PICTURE_SIZE(1)); | 263 | SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); |
341 | SR(VID_ACCU0(1)); | 264 | SR(OVL_ACCU0(OMAP_DSS_VIDEO2)); |
342 | SR(VID_ACCU1(1)); | 265 | SR(OVL_ACCU1(OMAP_DSS_VIDEO2)); |
343 | 266 | ||
344 | SR(VID_FIR_COEF_H(1, 0)); | 267 | for (i = 0; i < 8; i++) |
345 | SR(VID_FIR_COEF_H(1, 1)); | 268 | SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); |
346 | SR(VID_FIR_COEF_H(1, 2)); | 269 | |
347 | SR(VID_FIR_COEF_H(1, 3)); | 270 | for (i = 0; i < 8; i++) |
348 | SR(VID_FIR_COEF_H(1, 4)); | 271 | SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); |
349 | SR(VID_FIR_COEF_H(1, 5)); | 272 | |
350 | SR(VID_FIR_COEF_H(1, 6)); | 273 | for (i = 0; i < 5; i++) |
351 | SR(VID_FIR_COEF_H(1, 7)); | 274 | SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); |
352 | 275 | ||
353 | SR(VID_FIR_COEF_HV(1, 0)); | 276 | for (i = 0; i < 8; i++) |
354 | SR(VID_FIR_COEF_HV(1, 1)); | 277 | SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); |
355 | SR(VID_FIR_COEF_HV(1, 2)); | 278 | |
356 | SR(VID_FIR_COEF_HV(1, 3)); | 279 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
357 | SR(VID_FIR_COEF_HV(1, 4)); | 280 | SR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); |
358 | SR(VID_FIR_COEF_HV(1, 5)); | 281 | SR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); |
359 | SR(VID_FIR_COEF_HV(1, 6)); | 282 | SR(OVL_FIR2(OMAP_DSS_VIDEO2)); |
360 | SR(VID_FIR_COEF_HV(1, 7)); | 283 | SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); |
361 | 284 | SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | |
362 | SR(VID_CONV_COEF(1, 0)); | 285 | |
363 | SR(VID_CONV_COEF(1, 1)); | 286 | for (i = 0; i < 8; i++) |
364 | SR(VID_CONV_COEF(1, 2)); | 287 | SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); |
365 | SR(VID_CONV_COEF(1, 3)); | 288 | |
366 | SR(VID_CONV_COEF(1, 4)); | 289 | for (i = 0; i < 8; i++) |
367 | 290 | SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); | |
368 | SR(VID_FIR_COEF_V(1, 0)); | 291 | |
369 | SR(VID_FIR_COEF_V(1, 1)); | 292 | for (i = 0; i < 8; i++) |
370 | SR(VID_FIR_COEF_V(1, 2)); | 293 | SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); |
371 | SR(VID_FIR_COEF_V(1, 3)); | 294 | } |
372 | SR(VID_FIR_COEF_V(1, 4)); | 295 | if (dss_has_feature(FEAT_ATTR2)) |
373 | SR(VID_FIR_COEF_V(1, 5)); | 296 | SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); |
374 | SR(VID_FIR_COEF_V(1, 6)); | 297 | |
375 | SR(VID_FIR_COEF_V(1, 7)); | 298 | SR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); |
376 | |||
377 | SR(VID_PRELOAD(1)); | ||
378 | 299 | ||
379 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | 300 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
380 | SR(DIVISOR); | 301 | SR(DIVISOR); |
@@ -382,160 +303,158 @@ void dispc_save_context(void) | |||
382 | 303 | ||
383 | void dispc_restore_context(void) | 304 | void dispc_restore_context(void) |
384 | { | 305 | { |
306 | int i; | ||
385 | RR(SYSCONFIG); | 307 | RR(SYSCONFIG); |
386 | /*RR(IRQENABLE);*/ | 308 | /*RR(IRQENABLE);*/ |
387 | /*RR(CONTROL);*/ | 309 | /*RR(CONTROL);*/ |
388 | RR(CONFIG); | 310 | RR(CONFIG); |
389 | RR(DEFAULT_COLOR(0)); | 311 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); |
390 | RR(DEFAULT_COLOR(1)); | 312 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
391 | RR(TRANS_COLOR(0)); | 313 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); |
392 | RR(TRANS_COLOR(1)); | 314 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
393 | RR(LINE_NUMBER); | 315 | RR(LINE_NUMBER); |
394 | RR(TIMING_H(0)); | 316 | RR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); |
395 | RR(TIMING_V(0)); | 317 | RR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); |
396 | RR(POL_FREQ(0)); | 318 | RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); |
397 | RR(DIVISORo(0)); | 319 | RR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); |
398 | RR(GLOBAL_ALPHA); | 320 | RR(GLOBAL_ALPHA); |
399 | RR(SIZE_DIG); | 321 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); |
400 | RR(SIZE_LCD(0)); | 322 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); |
401 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 323 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
402 | RR(DEFAULT_COLOR(2)); | 324 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
403 | RR(TRANS_COLOR(2)); | 325 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
404 | RR(SIZE_LCD(2)); | 326 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); |
405 | RR(TIMING_H(2)); | 327 | RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2)); |
406 | RR(TIMING_V(2)); | 328 | RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2)); |
407 | RR(POL_FREQ(2)); | 329 | RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); |
408 | RR(DIVISORo(2)); | 330 | RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2)); |
409 | RR(CONFIG2); | 331 | RR(CONFIG2); |
410 | } | 332 | } |
411 | 333 | ||
412 | RR(GFX_BA0); | 334 | RR(OVL_BA0(OMAP_DSS_GFX)); |
413 | RR(GFX_BA1); | 335 | RR(OVL_BA1(OMAP_DSS_GFX)); |
414 | RR(GFX_POSITION); | 336 | RR(OVL_POSITION(OMAP_DSS_GFX)); |
415 | RR(GFX_SIZE); | 337 | RR(OVL_SIZE(OMAP_DSS_GFX)); |
416 | RR(GFX_ATTRIBUTES); | 338 | RR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); |
417 | RR(GFX_FIFO_THRESHOLD); | 339 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); |
418 | RR(GFX_ROW_INC); | 340 | RR(OVL_ROW_INC(OMAP_DSS_GFX)); |
419 | RR(GFX_PIXEL_INC); | 341 | RR(OVL_PIXEL_INC(OMAP_DSS_GFX)); |
420 | RR(GFX_WINDOW_SKIP); | 342 | RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); |
421 | RR(GFX_TABLE_BA); | 343 | RR(OVL_TABLE_BA(OMAP_DSS_GFX)); |
422 | 344 | ||
423 | RR(DATA_CYCLE1(0)); | 345 | |
424 | RR(DATA_CYCLE2(0)); | 346 | RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); |
425 | RR(DATA_CYCLE3(0)); | 347 | RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); |
426 | 348 | RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); | |
427 | RR(CPR_COEF_R(0)); | 349 | |
428 | RR(CPR_COEF_G(0)); | 350 | RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); |
429 | RR(CPR_COEF_B(0)); | 351 | RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); |
352 | RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); | ||
430 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 353 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
431 | RR(DATA_CYCLE1(2)); | 354 | RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); |
432 | RR(DATA_CYCLE2(2)); | 355 | RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); |
433 | RR(DATA_CYCLE3(2)); | 356 | RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); |
434 | 357 | ||
435 | RR(CPR_COEF_B(2)); | 358 | RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); |
436 | RR(CPR_COEF_G(2)); | 359 | RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); |
437 | RR(CPR_COEF_R(2)); | 360 | RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); |
438 | } | 361 | } |
439 | 362 | ||
440 | RR(GFX_PRELOAD); | 363 | RR(OVL_PRELOAD(OMAP_DSS_GFX)); |
441 | 364 | ||
442 | /* VID1 */ | 365 | /* VID1 */ |
443 | RR(VID_BA0(0)); | 366 | RR(OVL_BA0(OMAP_DSS_VIDEO1)); |
444 | RR(VID_BA1(0)); | 367 | RR(OVL_BA1(OMAP_DSS_VIDEO1)); |
445 | RR(VID_POSITION(0)); | 368 | RR(OVL_POSITION(OMAP_DSS_VIDEO1)); |
446 | RR(VID_SIZE(0)); | 369 | RR(OVL_SIZE(OMAP_DSS_VIDEO1)); |
447 | RR(VID_ATTRIBUTES(0)); | 370 | RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); |
448 | RR(VID_FIFO_THRESHOLD(0)); | 371 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); |
449 | RR(VID_ROW_INC(0)); | 372 | RR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); |
450 | RR(VID_PIXEL_INC(0)); | 373 | RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); |
451 | RR(VID_FIR(0)); | 374 | RR(OVL_FIR(OMAP_DSS_VIDEO1)); |
452 | RR(VID_PICTURE_SIZE(0)); | 375 | RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); |
453 | RR(VID_ACCU0(0)); | 376 | RR(OVL_ACCU0(OMAP_DSS_VIDEO1)); |
454 | RR(VID_ACCU1(0)); | 377 | RR(OVL_ACCU1(OMAP_DSS_VIDEO1)); |
455 | 378 | ||
456 | RR(VID_FIR_COEF_H(0, 0)); | 379 | for (i = 0; i < 8; i++) |
457 | RR(VID_FIR_COEF_H(0, 1)); | 380 | RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); |
458 | RR(VID_FIR_COEF_H(0, 2)); | 381 | |
459 | RR(VID_FIR_COEF_H(0, 3)); | 382 | for (i = 0; i < 8; i++) |
460 | RR(VID_FIR_COEF_H(0, 4)); | 383 | RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i)); |
461 | RR(VID_FIR_COEF_H(0, 5)); | 384 | |
462 | RR(VID_FIR_COEF_H(0, 6)); | 385 | for (i = 0; i < 5; i++) |
463 | RR(VID_FIR_COEF_H(0, 7)); | 386 | RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); |
464 | 387 | ||
465 | RR(VID_FIR_COEF_HV(0, 0)); | 388 | for (i = 0; i < 8; i++) |
466 | RR(VID_FIR_COEF_HV(0, 1)); | 389 | RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); |
467 | RR(VID_FIR_COEF_HV(0, 2)); | 390 | |
468 | RR(VID_FIR_COEF_HV(0, 3)); | 391 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
469 | RR(VID_FIR_COEF_HV(0, 4)); | 392 | RR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); |
470 | RR(VID_FIR_COEF_HV(0, 5)); | 393 | RR(OVL_BA1_UV(OMAP_DSS_VIDEO1)); |
471 | RR(VID_FIR_COEF_HV(0, 6)); | 394 | RR(OVL_FIR2(OMAP_DSS_VIDEO1)); |
472 | RR(VID_FIR_COEF_HV(0, 7)); | 395 | RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1)); |
473 | 396 | RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1)); | |
474 | RR(VID_CONV_COEF(0, 0)); | 397 | |
475 | RR(VID_CONV_COEF(0, 1)); | 398 | for (i = 0; i < 8; i++) |
476 | RR(VID_CONV_COEF(0, 2)); | 399 | RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i)); |
477 | RR(VID_CONV_COEF(0, 3)); | 400 | |
478 | RR(VID_CONV_COEF(0, 4)); | 401 | for (i = 0; i < 8; i++) |
479 | 402 | RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i)); | |
480 | RR(VID_FIR_COEF_V(0, 0)); | 403 | |
481 | RR(VID_FIR_COEF_V(0, 1)); | 404 | for (i = 0; i < 8; i++) |
482 | RR(VID_FIR_COEF_V(0, 2)); | 405 | RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i)); |
483 | RR(VID_FIR_COEF_V(0, 3)); | 406 | } |
484 | RR(VID_FIR_COEF_V(0, 4)); | 407 | if (dss_has_feature(FEAT_ATTR2)) |
485 | RR(VID_FIR_COEF_V(0, 5)); | 408 | RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); |
486 | RR(VID_FIR_COEF_V(0, 6)); | 409 | |
487 | RR(VID_FIR_COEF_V(0, 7)); | 410 | RR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); |
488 | |||
489 | RR(VID_PRELOAD(0)); | ||
490 | 411 | ||
491 | /* VID2 */ | 412 | /* VID2 */ |
492 | RR(VID_BA0(1)); | 413 | RR(OVL_BA0(OMAP_DSS_VIDEO2)); |
493 | RR(VID_BA1(1)); | 414 | RR(OVL_BA1(OMAP_DSS_VIDEO2)); |
494 | RR(VID_POSITION(1)); | 415 | RR(OVL_POSITION(OMAP_DSS_VIDEO2)); |
495 | RR(VID_SIZE(1)); | 416 | RR(OVL_SIZE(OMAP_DSS_VIDEO2)); |
496 | RR(VID_ATTRIBUTES(1)); | 417 | RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); |
497 | RR(VID_FIFO_THRESHOLD(1)); | 418 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); |
498 | RR(VID_ROW_INC(1)); | 419 | RR(OVL_ROW_INC(OMAP_DSS_VIDEO2)); |
499 | RR(VID_PIXEL_INC(1)); | 420 | RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); |
500 | RR(VID_FIR(1)); | 421 | RR(OVL_FIR(OMAP_DSS_VIDEO2)); |
501 | RR(VID_PICTURE_SIZE(1)); | 422 | RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); |
502 | RR(VID_ACCU0(1)); | 423 | RR(OVL_ACCU0(OMAP_DSS_VIDEO2)); |
503 | RR(VID_ACCU1(1)); | 424 | RR(OVL_ACCU1(OMAP_DSS_VIDEO2)); |
504 | 425 | ||
505 | RR(VID_FIR_COEF_H(1, 0)); | 426 | for (i = 0; i < 8; i++) |
506 | RR(VID_FIR_COEF_H(1, 1)); | 427 | RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); |
507 | RR(VID_FIR_COEF_H(1, 2)); | 428 | |
508 | RR(VID_FIR_COEF_H(1, 3)); | 429 | for (i = 0; i < 8; i++) |
509 | RR(VID_FIR_COEF_H(1, 4)); | 430 | RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); |
510 | RR(VID_FIR_COEF_H(1, 5)); | 431 | |
511 | RR(VID_FIR_COEF_H(1, 6)); | 432 | for (i = 0; i < 5; i++) |
512 | RR(VID_FIR_COEF_H(1, 7)); | 433 | RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); |
513 | 434 | ||
514 | RR(VID_FIR_COEF_HV(1, 0)); | 435 | for (i = 0; i < 8; i++) |
515 | RR(VID_FIR_COEF_HV(1, 1)); | 436 | RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); |
516 | RR(VID_FIR_COEF_HV(1, 2)); | 437 | |
517 | RR(VID_FIR_COEF_HV(1, 3)); | 438 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
518 | RR(VID_FIR_COEF_HV(1, 4)); | 439 | RR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); |
519 | RR(VID_FIR_COEF_HV(1, 5)); | 440 | RR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); |
520 | RR(VID_FIR_COEF_HV(1, 6)); | 441 | RR(OVL_FIR2(OMAP_DSS_VIDEO2)); |
521 | RR(VID_FIR_COEF_HV(1, 7)); | 442 | RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); |
522 | 443 | RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | |
523 | RR(VID_CONV_COEF(1, 0)); | 444 | |
524 | RR(VID_CONV_COEF(1, 1)); | 445 | for (i = 0; i < 8; i++) |
525 | RR(VID_CONV_COEF(1, 2)); | 446 | RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); |
526 | RR(VID_CONV_COEF(1, 3)); | 447 | |
527 | RR(VID_CONV_COEF(1, 4)); | 448 | for (i = 0; i < 8; i++) |
528 | 449 | RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); | |
529 | RR(VID_FIR_COEF_V(1, 0)); | 450 | |
530 | RR(VID_FIR_COEF_V(1, 1)); | 451 | for (i = 0; i < 8; i++) |
531 | RR(VID_FIR_COEF_V(1, 2)); | 452 | RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); |
532 | RR(VID_FIR_COEF_V(1, 3)); | 453 | } |
533 | RR(VID_FIR_COEF_V(1, 4)); | 454 | if (dss_has_feature(FEAT_ATTR2)) |
534 | RR(VID_FIR_COEF_V(1, 5)); | 455 | RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); |
535 | RR(VID_FIR_COEF_V(1, 6)); | 456 | |
536 | RR(VID_FIR_COEF_V(1, 7)); | 457 | RR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); |
537 | |||
538 | RR(VID_PRELOAD(1)); | ||
539 | 458 | ||
540 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | 459 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
541 | RR(DIVISOR); | 460 | RR(DIVISOR); |
@@ -632,27 +551,43 @@ end: | |||
632 | 551 | ||
633 | static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) | 552 | static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) |
634 | { | 553 | { |
554 | dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); | ||
555 | } | ||
556 | |||
557 | static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) | ||
558 | { | ||
559 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value); | ||
560 | } | ||
561 | |||
562 | static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) | ||
563 | { | ||
564 | dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value); | ||
565 | } | ||
566 | |||
567 | static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value) | ||
568 | { | ||
635 | BUG_ON(plane == OMAP_DSS_GFX); | 569 | BUG_ON(plane == OMAP_DSS_GFX); |
636 | 570 | ||
637 | dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value); | 571 | dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value); |
638 | } | 572 | } |
639 | 573 | ||
640 | static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) | 574 | static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value) |
641 | { | 575 | { |
642 | BUG_ON(plane == OMAP_DSS_GFX); | 576 | BUG_ON(plane == OMAP_DSS_GFX); |
643 | 577 | ||
644 | dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value); | 578 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value); |
645 | } | 579 | } |
646 | 580 | ||
647 | static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) | 581 | static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value) |
648 | { | 582 | { |
649 | BUG_ON(plane == OMAP_DSS_GFX); | 583 | BUG_ON(plane == OMAP_DSS_GFX); |
650 | 584 | ||
651 | dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value); | 585 | dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); |
652 | } | 586 | } |
653 | 587 | ||
654 | static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | 588 | static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, |
655 | int vscaleup, int five_taps) | 589 | int vscaleup, int five_taps, |
590 | enum omap_color_component color_comp) | ||
656 | { | 591 | { |
657 | /* Coefficients for horizontal up-sampling */ | 592 | /* Coefficients for horizontal up-sampling */ |
658 | static const struct dispc_h_coef coef_hup[8] = { | 593 | static const struct dispc_h_coef coef_hup[8] = { |
@@ -750,8 +685,14 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | |||
750 | | FLD_VAL(v_coef[i].vc1, 23, 16) | 685 | | FLD_VAL(v_coef[i].vc1, 23, 16) |
751 | | FLD_VAL(v_coef[i].vc2, 31, 24); | 686 | | FLD_VAL(v_coef[i].vc2, 31, 24); |
752 | 687 | ||
753 | _dispc_write_firh_reg(plane, i, h); | 688 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { |
754 | _dispc_write_firhv_reg(plane, i, hv); | 689 | _dispc_write_firh_reg(plane, i, h); |
690 | _dispc_write_firhv_reg(plane, i, hv); | ||
691 | } else { | ||
692 | _dispc_write_firh2_reg(plane, i, h); | ||
693 | _dispc_write_firhv2_reg(plane, i, hv); | ||
694 | } | ||
695 | |||
755 | } | 696 | } |
756 | 697 | ||
757 | if (five_taps) { | 698 | if (five_taps) { |
@@ -759,7 +700,10 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | |||
759 | u32 v; | 700 | u32 v; |
760 | v = FLD_VAL(v_coef[i].vc00, 7, 0) | 701 | v = FLD_VAL(v_coef[i].vc00, 7, 0) |
761 | | FLD_VAL(v_coef[i].vc22, 15, 8); | 702 | | FLD_VAL(v_coef[i].vc22, 15, 8); |
762 | _dispc_write_firv_reg(plane, i, v); | 703 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) |
704 | _dispc_write_firv_reg(plane, i, v); | ||
705 | else | ||
706 | _dispc_write_firv2_reg(plane, i, v); | ||
763 | } | 707 | } |
764 | } | 708 | } |
765 | } | 709 | } |
@@ -779,72 +723,83 @@ static void _dispc_setup_color_conv_coef(void) | |||
779 | 723 | ||
780 | ct = &ctbl_bt601_5; | 724 | ct = &ctbl_bt601_5; |
781 | 725 | ||
782 | dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry)); | 726 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0), |
783 | dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb)); | 727 | CVAL(ct->rcr, ct->ry)); |
784 | dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr)); | 728 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1), |
785 | dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by)); | 729 | CVAL(ct->gy, ct->rcb)); |
786 | dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb)); | 730 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2), |
787 | 731 | CVAL(ct->gcb, ct->gcr)); | |
788 | dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry)); | 732 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3), |
789 | dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb)); | 733 | CVAL(ct->bcr, ct->by)); |
790 | dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr)); | 734 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4), |
791 | dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by)); | 735 | CVAL(0, ct->bcb)); |
792 | dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb)); | 736 | |
737 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0), | ||
738 | CVAL(ct->rcr, ct->ry)); | ||
739 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1), | ||
740 | CVAL(ct->gy, ct->rcb)); | ||
741 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2), | ||
742 | CVAL(ct->gcb, ct->gcr)); | ||
743 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3), | ||
744 | CVAL(ct->bcr, ct->by)); | ||
745 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4), | ||
746 | CVAL(0, ct->bcb)); | ||
793 | 747 | ||
794 | #undef CVAL | 748 | #undef CVAL |
795 | 749 | ||
796 | REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); | 750 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1), |
797 | REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); | 751 | ct->full_range, 11, 11); |
752 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2), | ||
753 | ct->full_range, 11, 11); | ||
798 | } | 754 | } |
799 | 755 | ||
800 | 756 | ||
801 | static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) | 757 | static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) |
802 | { | 758 | { |
803 | const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0, | 759 | dispc_write_reg(DISPC_OVL_BA0(plane), paddr); |
804 | DISPC_VID_BA0(0), | ||
805 | DISPC_VID_BA0(1) }; | ||
806 | |||
807 | dispc_write_reg(ba0_reg[plane], paddr); | ||
808 | } | 760 | } |
809 | 761 | ||
810 | static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) | 762 | static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) |
811 | { | 763 | { |
812 | const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1, | 764 | dispc_write_reg(DISPC_OVL_BA1(plane), paddr); |
813 | DISPC_VID_BA1(0), | 765 | } |
814 | DISPC_VID_BA1(1) }; | ||
815 | 766 | ||
816 | dispc_write_reg(ba1_reg[plane], paddr); | 767 | static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr) |
768 | { | ||
769 | dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr); | ||
817 | } | 770 | } |
818 | 771 | ||
819 | static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) | 772 | static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr) |
820 | { | 773 | { |
821 | const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION, | 774 | dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); |
822 | DISPC_VID_POSITION(0), | 775 | } |
823 | DISPC_VID_POSITION(1) }; | ||
824 | 776 | ||
777 | static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) | ||
778 | { | ||
825 | u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); | 779 | u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); |
826 | dispc_write_reg(pos_reg[plane], val); | 780 | |
781 | dispc_write_reg(DISPC_OVL_POSITION(plane), val); | ||
827 | } | 782 | } |
828 | 783 | ||
829 | static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) | 784 | static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) |
830 | { | 785 | { |
831 | const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE, | ||
832 | DISPC_VID_PICTURE_SIZE(0), | ||
833 | DISPC_VID_PICTURE_SIZE(1) }; | ||
834 | u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 786 | u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
835 | dispc_write_reg(siz_reg[plane], val); | 787 | |
788 | if (plane == OMAP_DSS_GFX) | ||
789 | dispc_write_reg(DISPC_OVL_SIZE(plane), val); | ||
790 | else | ||
791 | dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); | ||
836 | } | 792 | } |
837 | 793 | ||
838 | static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) | 794 | static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) |
839 | { | 795 | { |
840 | u32 val; | 796 | u32 val; |
841 | const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0), | ||
842 | DISPC_VID_SIZE(1) }; | ||
843 | 797 | ||
844 | BUG_ON(plane == OMAP_DSS_GFX); | 798 | BUG_ON(plane == OMAP_DSS_GFX); |
845 | 799 | ||
846 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 800 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
847 | dispc_write_reg(vsi_reg[plane-1], val); | 801 | |
802 | dispc_write_reg(DISPC_OVL_SIZE(plane), val); | ||
848 | } | 803 | } |
849 | 804 | ||
850 | static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable) | 805 | static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable) |
@@ -856,7 +811,7 @@ static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable) | |||
856 | plane == OMAP_DSS_VIDEO1) | 811 | plane == OMAP_DSS_VIDEO1) |
857 | return; | 812 | return; |
858 | 813 | ||
859 | REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 28, 28); | 814 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); |
860 | } | 815 | } |
861 | 816 | ||
862 | static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | 817 | static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) |
@@ -876,61 +831,93 @@ static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | |||
876 | 831 | ||
877 | static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) | 832 | static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) |
878 | { | 833 | { |
879 | const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC, | 834 | dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc); |
880 | DISPC_VID_PIXEL_INC(0), | ||
881 | DISPC_VID_PIXEL_INC(1) }; | ||
882 | |||
883 | dispc_write_reg(ri_reg[plane], inc); | ||
884 | } | 835 | } |
885 | 836 | ||
886 | static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) | 837 | static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) |
887 | { | 838 | { |
888 | const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC, | 839 | dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc); |
889 | DISPC_VID_ROW_INC(0), | ||
890 | DISPC_VID_ROW_INC(1) }; | ||
891 | |||
892 | dispc_write_reg(ri_reg[plane], inc); | ||
893 | } | 840 | } |
894 | 841 | ||
895 | static void _dispc_set_color_mode(enum omap_plane plane, | 842 | static void _dispc_set_color_mode(enum omap_plane plane, |
896 | enum omap_color_mode color_mode) | 843 | enum omap_color_mode color_mode) |
897 | { | 844 | { |
898 | u32 m = 0; | 845 | u32 m = 0; |
899 | 846 | if (plane != OMAP_DSS_GFX) { | |
900 | switch (color_mode) { | 847 | switch (color_mode) { |
901 | case OMAP_DSS_COLOR_CLUT1: | 848 | case OMAP_DSS_COLOR_NV12: |
902 | m = 0x0; break; | 849 | m = 0x0; break; |
903 | case OMAP_DSS_COLOR_CLUT2: | 850 | case OMAP_DSS_COLOR_RGB12U: |
904 | m = 0x1; break; | 851 | m = 0x1; break; |
905 | case OMAP_DSS_COLOR_CLUT4: | 852 | case OMAP_DSS_COLOR_RGBA16: |
906 | m = 0x2; break; | 853 | m = 0x2; break; |
907 | case OMAP_DSS_COLOR_CLUT8: | 854 | case OMAP_DSS_COLOR_RGBX16: |
908 | m = 0x3; break; | 855 | m = 0x4; break; |
909 | case OMAP_DSS_COLOR_RGB12U: | 856 | case OMAP_DSS_COLOR_ARGB16: |
910 | m = 0x4; break; | 857 | m = 0x5; break; |
911 | case OMAP_DSS_COLOR_ARGB16: | 858 | case OMAP_DSS_COLOR_RGB16: |
912 | m = 0x5; break; | 859 | m = 0x6; break; |
913 | case OMAP_DSS_COLOR_RGB16: | 860 | case OMAP_DSS_COLOR_ARGB16_1555: |
914 | m = 0x6; break; | 861 | m = 0x7; break; |
915 | case OMAP_DSS_COLOR_RGB24U: | 862 | case OMAP_DSS_COLOR_RGB24U: |
916 | m = 0x8; break; | 863 | m = 0x8; break; |
917 | case OMAP_DSS_COLOR_RGB24P: | 864 | case OMAP_DSS_COLOR_RGB24P: |
918 | m = 0x9; break; | 865 | m = 0x9; break; |
919 | case OMAP_DSS_COLOR_YUV2: | 866 | case OMAP_DSS_COLOR_YUV2: |
920 | m = 0xa; break; | 867 | m = 0xa; break; |
921 | case OMAP_DSS_COLOR_UYVY: | 868 | case OMAP_DSS_COLOR_UYVY: |
922 | m = 0xb; break; | 869 | m = 0xb; break; |
923 | case OMAP_DSS_COLOR_ARGB32: | 870 | case OMAP_DSS_COLOR_ARGB32: |
924 | m = 0xc; break; | 871 | m = 0xc; break; |
925 | case OMAP_DSS_COLOR_RGBA32: | 872 | case OMAP_DSS_COLOR_RGBA32: |
926 | m = 0xd; break; | 873 | m = 0xd; break; |
927 | case OMAP_DSS_COLOR_RGBX32: | 874 | case OMAP_DSS_COLOR_RGBX32: |
928 | m = 0xe; break; | 875 | m = 0xe; break; |
929 | default: | 876 | case OMAP_DSS_COLOR_XRGB16_1555: |
930 | BUG(); break; | 877 | m = 0xf; break; |
878 | default: | ||
879 | BUG(); break; | ||
880 | } | ||
881 | } else { | ||
882 | switch (color_mode) { | ||
883 | case OMAP_DSS_COLOR_CLUT1: | ||
884 | m = 0x0; break; | ||
885 | case OMAP_DSS_COLOR_CLUT2: | ||
886 | m = 0x1; break; | ||
887 | case OMAP_DSS_COLOR_CLUT4: | ||
888 | m = 0x2; break; | ||
889 | case OMAP_DSS_COLOR_CLUT8: | ||
890 | m = 0x3; break; | ||
891 | case OMAP_DSS_COLOR_RGB12U: | ||
892 | m = 0x4; break; | ||
893 | case OMAP_DSS_COLOR_ARGB16: | ||
894 | m = 0x5; break; | ||
895 | case OMAP_DSS_COLOR_RGB16: | ||
896 | m = 0x6; break; | ||
897 | case OMAP_DSS_COLOR_ARGB16_1555: | ||
898 | m = 0x7; break; | ||
899 | case OMAP_DSS_COLOR_RGB24U: | ||
900 | m = 0x8; break; | ||
901 | case OMAP_DSS_COLOR_RGB24P: | ||
902 | m = 0x9; break; | ||
903 | case OMAP_DSS_COLOR_YUV2: | ||
904 | m = 0xa; break; | ||
905 | case OMAP_DSS_COLOR_UYVY: | ||
906 | m = 0xb; break; | ||
907 | case OMAP_DSS_COLOR_ARGB32: | ||
908 | m = 0xc; break; | ||
909 | case OMAP_DSS_COLOR_RGBA32: | ||
910 | m = 0xd; break; | ||
911 | case OMAP_DSS_COLOR_RGBX32: | ||
912 | m = 0xe; break; | ||
913 | case OMAP_DSS_COLOR_XRGB16_1555: | ||
914 | m = 0xf; break; | ||
915 | default: | ||
916 | BUG(); break; | ||
917 | } | ||
931 | } | 918 | } |
932 | 919 | ||
933 | REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1); | 920 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); |
934 | } | 921 | } |
935 | 922 | ||
936 | static void _dispc_set_channel_out(enum omap_plane plane, | 923 | static void _dispc_set_channel_out(enum omap_plane plane, |
@@ -953,7 +940,7 @@ static void _dispc_set_channel_out(enum omap_plane plane, | |||
953 | return; | 940 | return; |
954 | } | 941 | } |
955 | 942 | ||
956 | val = dispc_read_reg(dispc_reg_att[plane]); | 943 | val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); |
957 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 944 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
958 | switch (channel) { | 945 | switch (channel) { |
959 | case OMAP_DSS_CHANNEL_LCD: | 946 | case OMAP_DSS_CHANNEL_LCD: |
@@ -977,7 +964,7 @@ static void _dispc_set_channel_out(enum omap_plane plane, | |||
977 | } else { | 964 | } else { |
978 | val = FLD_MOD(val, channel, shift, shift); | 965 | val = FLD_MOD(val, channel, shift, shift); |
979 | } | 966 | } |
980 | dispc_write_reg(dispc_reg_att[plane], val); | 967 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); |
981 | } | 968 | } |
982 | 969 | ||
983 | void dispc_set_burst_size(enum omap_plane plane, | 970 | void dispc_set_burst_size(enum omap_plane plane, |
@@ -1001,9 +988,9 @@ void dispc_set_burst_size(enum omap_plane plane, | |||
1001 | return; | 988 | return; |
1002 | } | 989 | } |
1003 | 990 | ||
1004 | val = dispc_read_reg(dispc_reg_att[plane]); | 991 | val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); |
1005 | val = FLD_MOD(val, burst_size, shift+1, shift); | 992 | val = FLD_MOD(val, burst_size, shift+1, shift); |
1006 | dispc_write_reg(dispc_reg_att[plane], val); | 993 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); |
1007 | 994 | ||
1008 | enable_clocks(0); | 995 | enable_clocks(0); |
1009 | } | 996 | } |
@@ -1028,9 +1015,9 @@ static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) | |||
1028 | 1015 | ||
1029 | BUG_ON(plane == OMAP_DSS_GFX); | 1016 | BUG_ON(plane == OMAP_DSS_GFX); |
1030 | 1017 | ||
1031 | val = dispc_read_reg(dispc_reg_att[plane]); | 1018 | val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); |
1032 | val = FLD_MOD(val, enable, 9, 9); | 1019 | val = FLD_MOD(val, enable, 9, 9); |
1033 | dispc_write_reg(dispc_reg_att[plane], val); | 1020 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); |
1034 | } | 1021 | } |
1035 | 1022 | ||
1036 | void dispc_enable_replication(enum omap_plane plane, bool enable) | 1023 | void dispc_enable_replication(enum omap_plane plane, bool enable) |
@@ -1043,7 +1030,7 @@ void dispc_enable_replication(enum omap_plane plane, bool enable) | |||
1043 | bit = 10; | 1030 | bit = 10; |
1044 | 1031 | ||
1045 | enable_clocks(1); | 1032 | enable_clocks(1); |
1046 | REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit); | 1033 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); |
1047 | enable_clocks(0); | 1034 | enable_clocks(0); |
1048 | } | 1035 | } |
1049 | 1036 | ||
@@ -1053,7 +1040,7 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) | |||
1053 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | 1040 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); |
1054 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 1041 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
1055 | enable_clocks(1); | 1042 | enable_clocks(1); |
1056 | dispc_write_reg(DISPC_SIZE_LCD(channel), val); | 1043 | dispc_write_reg(DISPC_SIZE_MGR(channel), val); |
1057 | enable_clocks(0); | 1044 | enable_clocks(0); |
1058 | } | 1045 | } |
1059 | 1046 | ||
@@ -1063,15 +1050,12 @@ void dispc_set_digit_size(u16 width, u16 height) | |||
1063 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | 1050 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); |
1064 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 1051 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
1065 | enable_clocks(1); | 1052 | enable_clocks(1); |
1066 | dispc_write_reg(DISPC_SIZE_DIG, val); | 1053 | dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); |
1067 | enable_clocks(0); | 1054 | enable_clocks(0); |
1068 | } | 1055 | } |
1069 | 1056 | ||
1070 | static void dispc_read_plane_fifo_sizes(void) | 1057 | static void dispc_read_plane_fifo_sizes(void) |
1071 | { | 1058 | { |
1072 | const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, | ||
1073 | DISPC_VID_FIFO_SIZE_STATUS(0), | ||
1074 | DISPC_VID_FIFO_SIZE_STATUS(1) }; | ||
1075 | u32 size; | 1059 | u32 size; |
1076 | int plane; | 1060 | int plane; |
1077 | u8 start, end; | 1061 | u8 start, end; |
@@ -1081,7 +1065,8 @@ static void dispc_read_plane_fifo_sizes(void) | |||
1081 | dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); | 1065 | dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); |
1082 | 1066 | ||
1083 | for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { | 1067 | for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { |
1084 | size = FLD_GET(dispc_read_reg(fsz_reg[plane]), start, end); | 1068 | size = FLD_GET(dispc_read_reg(DISPC_OVL_FIFO_SIZE_STATUS(plane)), |
1069 | start, end); | ||
1085 | dispc.fifo_size[plane] = size; | 1070 | dispc.fifo_size[plane] = size; |
1086 | } | 1071 | } |
1087 | 1072 | ||
@@ -1095,23 +1080,22 @@ u32 dispc_get_plane_fifo_size(enum omap_plane plane) | |||
1095 | 1080 | ||
1096 | void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) | 1081 | void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) |
1097 | { | 1082 | { |
1098 | const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, | ||
1099 | DISPC_VID_FIFO_THRESHOLD(0), | ||
1100 | DISPC_VID_FIFO_THRESHOLD(1) }; | ||
1101 | u8 hi_start, hi_end, lo_start, lo_end; | 1083 | u8 hi_start, hi_end, lo_start, lo_end; |
1102 | 1084 | ||
1085 | dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); | ||
1086 | dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); | ||
1087 | |||
1103 | enable_clocks(1); | 1088 | enable_clocks(1); |
1104 | 1089 | ||
1105 | DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", | 1090 | DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", |
1106 | plane, | 1091 | plane, |
1107 | REG_GET(ftrs_reg[plane], 11, 0), | 1092 | REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), |
1108 | REG_GET(ftrs_reg[plane], 27, 16), | 1093 | lo_start, lo_end), |
1094 | REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), | ||
1095 | hi_start, hi_end), | ||
1109 | low, high); | 1096 | low, high); |
1110 | 1097 | ||
1111 | dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); | 1098 | dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane), |
1112 | dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); | ||
1113 | |||
1114 | dispc_write_reg(ftrs_reg[plane], | ||
1115 | FLD_VAL(high, hi_start, hi_end) | | 1099 | FLD_VAL(high, hi_start, hi_end) | |
1116 | FLD_VAL(low, lo_start, lo_end)); | 1100 | FLD_VAL(low, lo_start, lo_end)); |
1117 | 1101 | ||
@@ -1128,106 +1112,120 @@ void dispc_enable_fifomerge(bool enable) | |||
1128 | enable_clocks(0); | 1112 | enable_clocks(0); |
1129 | } | 1113 | } |
1130 | 1114 | ||
1131 | static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc) | 1115 | static void _dispc_set_fir(enum omap_plane plane, |
1116 | int hinc, int vinc, | ||
1117 | enum omap_color_component color_comp) | ||
1132 | { | 1118 | { |
1133 | u32 val; | 1119 | u32 val; |
1134 | const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0), | ||
1135 | DISPC_VID_FIR(1) }; | ||
1136 | u8 hinc_start, hinc_end, vinc_start, vinc_end; | ||
1137 | |||
1138 | BUG_ON(plane == OMAP_DSS_GFX); | ||
1139 | 1120 | ||
1140 | dss_feat_get_reg_field(FEAT_REG_FIRHINC, &hinc_start, &hinc_end); | 1121 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { |
1141 | dss_feat_get_reg_field(FEAT_REG_FIRVINC, &vinc_start, &vinc_end); | 1122 | u8 hinc_start, hinc_end, vinc_start, vinc_end; |
1142 | 1123 | ||
1143 | val = FLD_VAL(vinc, vinc_start, vinc_end) | | 1124 | dss_feat_get_reg_field(FEAT_REG_FIRHINC, |
1144 | FLD_VAL(hinc, hinc_start, hinc_end); | 1125 | &hinc_start, &hinc_end); |
1126 | dss_feat_get_reg_field(FEAT_REG_FIRVINC, | ||
1127 | &vinc_start, &vinc_end); | ||
1128 | val = FLD_VAL(vinc, vinc_start, vinc_end) | | ||
1129 | FLD_VAL(hinc, hinc_start, hinc_end); | ||
1145 | 1130 | ||
1146 | dispc_write_reg(fir_reg[plane-1], val); | 1131 | dispc_write_reg(DISPC_OVL_FIR(plane), val); |
1132 | } else { | ||
1133 | val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0); | ||
1134 | dispc_write_reg(DISPC_OVL_FIR2(plane), val); | ||
1135 | } | ||
1147 | } | 1136 | } |
1148 | 1137 | ||
1149 | static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) | 1138 | static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) |
1150 | { | 1139 | { |
1151 | u32 val; | 1140 | u32 val; |
1152 | const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), | ||
1153 | DISPC_VID_ACCU0(1) }; | ||
1154 | u8 hor_start, hor_end, vert_start, vert_end; | 1141 | u8 hor_start, hor_end, vert_start, vert_end; |
1155 | 1142 | ||
1156 | BUG_ON(plane == OMAP_DSS_GFX); | ||
1157 | |||
1158 | dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); | 1143 | dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); |
1159 | dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); | 1144 | dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); |
1160 | 1145 | ||
1161 | val = FLD_VAL(vaccu, vert_start, vert_end) | | 1146 | val = FLD_VAL(vaccu, vert_start, vert_end) | |
1162 | FLD_VAL(haccu, hor_start, hor_end); | 1147 | FLD_VAL(haccu, hor_start, hor_end); |
1163 | 1148 | ||
1164 | dispc_write_reg(ac0_reg[plane-1], val); | 1149 | dispc_write_reg(DISPC_OVL_ACCU0(plane), val); |
1165 | } | 1150 | } |
1166 | 1151 | ||
1167 | static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) | 1152 | static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) |
1168 | { | 1153 | { |
1169 | u32 val; | 1154 | u32 val; |
1170 | const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), | ||
1171 | DISPC_VID_ACCU1(1) }; | ||
1172 | u8 hor_start, hor_end, vert_start, vert_end; | 1155 | u8 hor_start, hor_end, vert_start, vert_end; |
1173 | 1156 | ||
1174 | BUG_ON(plane == OMAP_DSS_GFX); | ||
1175 | |||
1176 | dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); | 1157 | dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); |
1177 | dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); | 1158 | dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); |
1178 | 1159 | ||
1179 | val = FLD_VAL(vaccu, vert_start, vert_end) | | 1160 | val = FLD_VAL(vaccu, vert_start, vert_end) | |
1180 | FLD_VAL(haccu, hor_start, hor_end); | 1161 | FLD_VAL(haccu, hor_start, hor_end); |
1181 | 1162 | ||
1182 | dispc_write_reg(ac1_reg[plane-1], val); | 1163 | dispc_write_reg(DISPC_OVL_ACCU1(plane), val); |
1164 | } | ||
1165 | |||
1166 | static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu) | ||
1167 | { | ||
1168 | u32 val; | ||
1169 | |||
1170 | val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0); | ||
1171 | dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val); | ||
1183 | } | 1172 | } |
1184 | 1173 | ||
1174 | static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu) | ||
1175 | { | ||
1176 | u32 val; | ||
1185 | 1177 | ||
1186 | static void _dispc_set_scaling(enum omap_plane plane, | 1178 | val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0); |
1179 | dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val); | ||
1180 | } | ||
1181 | |||
1182 | static void _dispc_set_scale_param(enum omap_plane plane, | ||
1187 | u16 orig_width, u16 orig_height, | 1183 | u16 orig_width, u16 orig_height, |
1188 | u16 out_width, u16 out_height, | 1184 | u16 out_width, u16 out_height, |
1189 | bool ilace, bool five_taps, | 1185 | bool five_taps, u8 rotation, |
1190 | bool fieldmode) | 1186 | enum omap_color_component color_comp) |
1191 | { | 1187 | { |
1192 | int fir_hinc; | 1188 | int fir_hinc, fir_vinc; |
1193 | int fir_vinc; | ||
1194 | int hscaleup, vscaleup; | 1189 | int hscaleup, vscaleup; |
1195 | int accu0 = 0; | ||
1196 | int accu1 = 0; | ||
1197 | u32 l; | ||
1198 | |||
1199 | BUG_ON(plane == OMAP_DSS_GFX); | ||
1200 | 1190 | ||
1201 | hscaleup = orig_width <= out_width; | 1191 | hscaleup = orig_width <= out_width; |
1202 | vscaleup = orig_height <= out_height; | 1192 | vscaleup = orig_height <= out_height; |
1203 | 1193 | ||
1204 | _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps); | 1194 | _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp); |
1205 | 1195 | ||
1206 | if (!orig_width || orig_width == out_width) | 1196 | fir_hinc = 1024 * orig_width / out_width; |
1207 | fir_hinc = 0; | 1197 | fir_vinc = 1024 * orig_height / out_height; |
1208 | else | ||
1209 | fir_hinc = 1024 * orig_width / out_width; | ||
1210 | 1198 | ||
1211 | if (!orig_height || orig_height == out_height) | 1199 | _dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp); |
1212 | fir_vinc = 0; | 1200 | } |
1213 | else | ||
1214 | fir_vinc = 1024 * orig_height / out_height; | ||
1215 | 1201 | ||
1216 | _dispc_set_fir(plane, fir_hinc, fir_vinc); | 1202 | static void _dispc_set_scaling_common(enum omap_plane plane, |
1203 | u16 orig_width, u16 orig_height, | ||
1204 | u16 out_width, u16 out_height, | ||
1205 | bool ilace, bool five_taps, | ||
1206 | bool fieldmode, enum omap_color_mode color_mode, | ||
1207 | u8 rotation) | ||
1208 | { | ||
1209 | int accu0 = 0; | ||
1210 | int accu1 = 0; | ||
1211 | u32 l; | ||
1217 | 1212 | ||
1218 | l = dispc_read_reg(dispc_reg_att[plane]); | 1213 | _dispc_set_scale_param(plane, orig_width, orig_height, |
1214 | out_width, out_height, five_taps, | ||
1215 | rotation, DISPC_COLOR_COMPONENT_RGB_Y); | ||
1216 | l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); | ||
1219 | 1217 | ||
1220 | /* RESIZEENABLE and VERTICALTAPS */ | 1218 | /* RESIZEENABLE and VERTICALTAPS */ |
1221 | l &= ~((0x3 << 5) | (0x1 << 21)); | 1219 | l &= ~((0x3 << 5) | (0x1 << 21)); |
1222 | l |= fir_hinc ? (1 << 5) : 0; | 1220 | l |= (orig_width != out_width) ? (1 << 5) : 0; |
1223 | l |= fir_vinc ? (1 << 6) : 0; | 1221 | l |= (orig_height != out_height) ? (1 << 6) : 0; |
1224 | l |= five_taps ? (1 << 21) : 0; | 1222 | l |= five_taps ? (1 << 21) : 0; |
1225 | 1223 | ||
1226 | /* VRESIZECONF and HRESIZECONF */ | 1224 | /* VRESIZECONF and HRESIZECONF */ |
1227 | if (dss_has_feature(FEAT_RESIZECONF)) { | 1225 | if (dss_has_feature(FEAT_RESIZECONF)) { |
1228 | l &= ~(0x3 << 7); | 1226 | l &= ~(0x3 << 7); |
1229 | l |= hscaleup ? 0 : (1 << 7); | 1227 | l |= (orig_width <= out_width) ? 0 : (1 << 7); |
1230 | l |= vscaleup ? 0 : (1 << 8); | 1228 | l |= (orig_height <= out_height) ? 0 : (1 << 8); |
1231 | } | 1229 | } |
1232 | 1230 | ||
1233 | /* LINEBUFFERSPLIT */ | 1231 | /* LINEBUFFERSPLIT */ |
@@ -1236,7 +1234,7 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1236 | l |= five_taps ? (1 << 22) : 0; | 1234 | l |= five_taps ? (1 << 22) : 0; |
1237 | } | 1235 | } |
1238 | 1236 | ||
1239 | dispc_write_reg(dispc_reg_att[plane], l); | 1237 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l); |
1240 | 1238 | ||
1241 | /* | 1239 | /* |
1242 | * field 0 = even field = bottom field | 1240 | * field 0 = even field = bottom field |
@@ -1244,7 +1242,7 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1244 | */ | 1242 | */ |
1245 | if (ilace && !fieldmode) { | 1243 | if (ilace && !fieldmode) { |
1246 | accu1 = 0; | 1244 | accu1 = 0; |
1247 | accu0 = (fir_vinc / 2) & 0x3ff; | 1245 | accu0 = ((1024 * orig_height / out_height) / 2) & 0x3ff; |
1248 | if (accu0 >= 1024/2) { | 1246 | if (accu0 >= 1024/2) { |
1249 | accu1 = 1024/2; | 1247 | accu1 = 1024/2; |
1250 | accu0 -= accu1; | 1248 | accu0 -= accu1; |
@@ -1255,6 +1253,93 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1255 | _dispc_set_vid_accu1(plane, 0, accu1); | 1253 | _dispc_set_vid_accu1(plane, 0, accu1); |
1256 | } | 1254 | } |
1257 | 1255 | ||
1256 | static void _dispc_set_scaling_uv(enum omap_plane plane, | ||
1257 | u16 orig_width, u16 orig_height, | ||
1258 | u16 out_width, u16 out_height, | ||
1259 | bool ilace, bool five_taps, | ||
1260 | bool fieldmode, enum omap_color_mode color_mode, | ||
1261 | u8 rotation) | ||
1262 | { | ||
1263 | int scale_x = out_width != orig_width; | ||
1264 | int scale_y = out_height != orig_height; | ||
1265 | |||
1266 | if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) | ||
1267 | return; | ||
1268 | if ((color_mode != OMAP_DSS_COLOR_YUV2 && | ||
1269 | color_mode != OMAP_DSS_COLOR_UYVY && | ||
1270 | color_mode != OMAP_DSS_COLOR_NV12)) { | ||
1271 | /* reset chroma resampling for RGB formats */ | ||
1272 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); | ||
1273 | return; | ||
1274 | } | ||
1275 | switch (color_mode) { | ||
1276 | case OMAP_DSS_COLOR_NV12: | ||
1277 | /* UV is subsampled by 2 vertically*/ | ||
1278 | orig_height >>= 1; | ||
1279 | /* UV is subsampled by 2 horz.*/ | ||
1280 | orig_width >>= 1; | ||
1281 | break; | ||
1282 | case OMAP_DSS_COLOR_YUV2: | ||
1283 | case OMAP_DSS_COLOR_UYVY: | ||
1284 | /*For YUV422 with 90/270 rotation, | ||
1285 | *we don't upsample chroma | ||
1286 | */ | ||
1287 | if (rotation == OMAP_DSS_ROT_0 || | ||
1288 | rotation == OMAP_DSS_ROT_180) | ||
1289 | /* UV is subsampled by 2 hrz*/ | ||
1290 | orig_width >>= 1; | ||
1291 | /* must use FIR for YUV422 if rotated */ | ||
1292 | if (rotation != OMAP_DSS_ROT_0) | ||
1293 | scale_x = scale_y = true; | ||
1294 | break; | ||
1295 | default: | ||
1296 | BUG(); | ||
1297 | } | ||
1298 | |||
1299 | if (out_width != orig_width) | ||
1300 | scale_x = true; | ||
1301 | if (out_height != orig_height) | ||
1302 | scale_y = true; | ||
1303 | |||
1304 | _dispc_set_scale_param(plane, orig_width, orig_height, | ||
1305 | out_width, out_height, five_taps, | ||
1306 | rotation, DISPC_COLOR_COMPONENT_UV); | ||
1307 | |||
1308 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), | ||
1309 | (scale_x || scale_y) ? 1 : 0, 8, 8); | ||
1310 | /* set H scaling */ | ||
1311 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); | ||
1312 | /* set V scaling */ | ||
1313 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); | ||
1314 | |||
1315 | _dispc_set_vid_accu2_0(plane, 0x80, 0); | ||
1316 | _dispc_set_vid_accu2_1(plane, 0x80, 0); | ||
1317 | } | ||
1318 | |||
1319 | static void _dispc_set_scaling(enum omap_plane plane, | ||
1320 | u16 orig_width, u16 orig_height, | ||
1321 | u16 out_width, u16 out_height, | ||
1322 | bool ilace, bool five_taps, | ||
1323 | bool fieldmode, enum omap_color_mode color_mode, | ||
1324 | u8 rotation) | ||
1325 | { | ||
1326 | BUG_ON(plane == OMAP_DSS_GFX); | ||
1327 | |||
1328 | _dispc_set_scaling_common(plane, | ||
1329 | orig_width, orig_height, | ||
1330 | out_width, out_height, | ||
1331 | ilace, five_taps, | ||
1332 | fieldmode, color_mode, | ||
1333 | rotation); | ||
1334 | |||
1335 | _dispc_set_scaling_uv(plane, | ||
1336 | orig_width, orig_height, | ||
1337 | out_width, out_height, | ||
1338 | ilace, five_taps, | ||
1339 | fieldmode, color_mode, | ||
1340 | rotation); | ||
1341 | } | ||
1342 | |||
1258 | static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, | 1343 | static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, |
1259 | bool mirroring, enum omap_color_mode color_mode) | 1344 | bool mirroring, enum omap_color_mode color_mode) |
1260 | { | 1345 | { |
@@ -1302,9 +1387,10 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, | |||
1302 | row_repeat = false; | 1387 | row_repeat = false; |
1303 | } | 1388 | } |
1304 | 1389 | ||
1305 | REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); | 1390 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12); |
1306 | if (dss_has_feature(FEAT_ROWREPEATENABLE)) | 1391 | if (dss_has_feature(FEAT_ROWREPEATENABLE)) |
1307 | REG_FLD_MOD(dispc_reg_att[plane], row_repeat ? 1 : 0, 18, 18); | 1392 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), |
1393 | row_repeat ? 1 : 0, 18, 18); | ||
1308 | } | 1394 | } |
1309 | 1395 | ||
1310 | static int color_mode_to_bpp(enum omap_color_mode color_mode) | 1396 | static int color_mode_to_bpp(enum omap_color_mode color_mode) |
@@ -1317,12 +1403,17 @@ static int color_mode_to_bpp(enum omap_color_mode color_mode) | |||
1317 | case OMAP_DSS_COLOR_CLUT4: | 1403 | case OMAP_DSS_COLOR_CLUT4: |
1318 | return 4; | 1404 | return 4; |
1319 | case OMAP_DSS_COLOR_CLUT8: | 1405 | case OMAP_DSS_COLOR_CLUT8: |
1406 | case OMAP_DSS_COLOR_NV12: | ||
1320 | return 8; | 1407 | return 8; |
1321 | case OMAP_DSS_COLOR_RGB12U: | 1408 | case OMAP_DSS_COLOR_RGB12U: |
1322 | case OMAP_DSS_COLOR_RGB16: | 1409 | case OMAP_DSS_COLOR_RGB16: |
1323 | case OMAP_DSS_COLOR_ARGB16: | 1410 | case OMAP_DSS_COLOR_ARGB16: |
1324 | case OMAP_DSS_COLOR_YUV2: | 1411 | case OMAP_DSS_COLOR_YUV2: |
1325 | case OMAP_DSS_COLOR_UYVY: | 1412 | case OMAP_DSS_COLOR_UYVY: |
1413 | case OMAP_DSS_COLOR_RGBA16: | ||
1414 | case OMAP_DSS_COLOR_RGBX16: | ||
1415 | case OMAP_DSS_COLOR_ARGB16_1555: | ||
1416 | case OMAP_DSS_COLOR_XRGB16_1555: | ||
1326 | return 16; | 1417 | return 16; |
1327 | case OMAP_DSS_COLOR_RGB24P: | 1418 | case OMAP_DSS_COLOR_RGB24P: |
1328 | return 24; | 1419 | return 24; |
@@ -1655,7 +1746,7 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1655 | enum omap_dss_rotation_type rotation_type, | 1746 | enum omap_dss_rotation_type rotation_type, |
1656 | u8 rotation, int mirror, | 1747 | u8 rotation, int mirror, |
1657 | u8 global_alpha, u8 pre_mult_alpha, | 1748 | u8 global_alpha, u8 pre_mult_alpha, |
1658 | enum omap_channel channel) | 1749 | enum omap_channel channel, u32 puv_addr) |
1659 | { | 1750 | { |
1660 | const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; | 1751 | const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; |
1661 | bool five_taps = 0; | 1752 | bool five_taps = 0; |
@@ -1704,7 +1795,8 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1704 | return -EINVAL; | 1795 | return -EINVAL; |
1705 | 1796 | ||
1706 | if (color_mode == OMAP_DSS_COLOR_YUV2 || | 1797 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
1707 | color_mode == OMAP_DSS_COLOR_UYVY) | 1798 | color_mode == OMAP_DSS_COLOR_UYVY || |
1799 | color_mode == OMAP_DSS_COLOR_NV12) | ||
1708 | cconv = 1; | 1800 | cconv = 1; |
1709 | 1801 | ||
1710 | /* Must use 5-tap filter? */ | 1802 | /* Must use 5-tap filter? */ |
@@ -1778,6 +1870,12 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1778 | _dispc_set_plane_ba0(plane, paddr + offset0); | 1870 | _dispc_set_plane_ba0(plane, paddr + offset0); |
1779 | _dispc_set_plane_ba1(plane, paddr + offset1); | 1871 | _dispc_set_plane_ba1(plane, paddr + offset1); |
1780 | 1872 | ||
1873 | if (OMAP_DSS_COLOR_NV12 == color_mode) { | ||
1874 | _dispc_set_plane_ba0_uv(plane, puv_addr + offset0); | ||
1875 | _dispc_set_plane_ba1_uv(plane, puv_addr + offset1); | ||
1876 | } | ||
1877 | |||
1878 | |||
1781 | _dispc_set_row_inc(plane, row_inc); | 1879 | _dispc_set_row_inc(plane, row_inc); |
1782 | _dispc_set_pix_inc(plane, pix_inc); | 1880 | _dispc_set_pix_inc(plane, pix_inc); |
1783 | 1881 | ||
@@ -1791,7 +1889,8 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1791 | if (plane != OMAP_DSS_GFX) { | 1889 | if (plane != OMAP_DSS_GFX) { |
1792 | _dispc_set_scaling(plane, width, height, | 1890 | _dispc_set_scaling(plane, width, height, |
1793 | out_width, out_height, | 1891 | out_width, out_height, |
1794 | ilace, five_taps, fieldmode); | 1892 | ilace, five_taps, fieldmode, |
1893 | color_mode, rotation); | ||
1795 | _dispc_set_vid_size(plane, out_width, out_height); | 1894 | _dispc_set_vid_size(plane, out_width, out_height); |
1796 | _dispc_set_vid_color_conv(plane, cconv); | 1895 | _dispc_set_vid_color_conv(plane, cconv); |
1797 | } | 1896 | } |
@@ -1806,7 +1905,7 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1806 | 1905 | ||
1807 | static void _dispc_enable_plane(enum omap_plane plane, bool enable) | 1906 | static void _dispc_enable_plane(enum omap_plane plane, bool enable) |
1808 | { | 1907 | { |
1809 | REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0); | 1908 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0); |
1810 | } | 1909 | } |
1811 | 1910 | ||
1812 | static void dispc_disable_isr(void *data, u32 mask) | 1911 | static void dispc_disable_isr(void *data, u32 mask) |
@@ -2353,14 +2452,20 @@ static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, | |||
2353 | 2452 | ||
2354 | unsigned long dispc_fclk_rate(void) | 2453 | unsigned long dispc_fclk_rate(void) |
2355 | { | 2454 | { |
2455 | struct platform_device *dsidev; | ||
2356 | unsigned long r = 0; | 2456 | unsigned long r = 0; |
2357 | 2457 | ||
2358 | switch (dss_get_dispc_clk_source()) { | 2458 | switch (dss_get_dispc_clk_source()) { |
2359 | case DSS_CLK_SRC_FCK: | 2459 | case OMAP_DSS_CLK_SRC_FCK: |
2360 | r = dss_clk_get_rate(DSS_CLK_FCK); | 2460 | r = dss_clk_get_rate(DSS_CLK_FCK); |
2361 | break; | 2461 | break; |
2362 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | 2462 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
2363 | r = dsi_get_pll_hsdiv_dispc_rate(); | 2463 | dsidev = dsi_get_dsidev_from_id(0); |
2464 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); | ||
2465 | break; | ||
2466 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | ||
2467 | dsidev = dsi_get_dsidev_from_id(1); | ||
2468 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); | ||
2364 | break; | 2469 | break; |
2365 | default: | 2470 | default: |
2366 | BUG(); | 2471 | BUG(); |
@@ -2371,6 +2476,7 @@ unsigned long dispc_fclk_rate(void) | |||
2371 | 2476 | ||
2372 | unsigned long dispc_lclk_rate(enum omap_channel channel) | 2477 | unsigned long dispc_lclk_rate(enum omap_channel channel) |
2373 | { | 2478 | { |
2479 | struct platform_device *dsidev; | ||
2374 | int lcd; | 2480 | int lcd; |
2375 | unsigned long r; | 2481 | unsigned long r; |
2376 | u32 l; | 2482 | u32 l; |
@@ -2380,11 +2486,16 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) | |||
2380 | lcd = FLD_GET(l, 23, 16); | 2486 | lcd = FLD_GET(l, 23, 16); |
2381 | 2487 | ||
2382 | switch (dss_get_lcd_clk_source(channel)) { | 2488 | switch (dss_get_lcd_clk_source(channel)) { |
2383 | case DSS_CLK_SRC_FCK: | 2489 | case OMAP_DSS_CLK_SRC_FCK: |
2384 | r = dss_clk_get_rate(DSS_CLK_FCK); | 2490 | r = dss_clk_get_rate(DSS_CLK_FCK); |
2385 | break; | 2491 | break; |
2386 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | 2492 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
2387 | r = dsi_get_pll_hsdiv_dispc_rate(); | 2493 | dsidev = dsi_get_dsidev_from_id(0); |
2494 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); | ||
2495 | break; | ||
2496 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | ||
2497 | dsidev = dsi_get_dsidev_from_id(1); | ||
2498 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); | ||
2388 | break; | 2499 | break; |
2389 | default: | 2500 | default: |
2390 | BUG(); | 2501 | BUG(); |
@@ -2412,8 +2523,8 @@ void dispc_dump_clocks(struct seq_file *s) | |||
2412 | { | 2523 | { |
2413 | int lcd, pcd; | 2524 | int lcd, pcd; |
2414 | u32 l; | 2525 | u32 l; |
2415 | enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); | 2526 | enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); |
2416 | enum dss_clk_source lcd_clk_src; | 2527 | enum omap_dss_clk_source lcd_clk_src; |
2417 | 2528 | ||
2418 | enable_clocks(1); | 2529 | enable_clocks(1); |
2419 | 2530 | ||
@@ -2516,7 +2627,7 @@ void dispc_dump_irqs(struct seq_file *s) | |||
2516 | 2627 | ||
2517 | void dispc_dump_regs(struct seq_file *s) | 2628 | void dispc_dump_regs(struct seq_file *s) |
2518 | { | 2629 | { |
2519 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) | 2630 | #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) |
2520 | 2631 | ||
2521 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); | 2632 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
2522 | 2633 | ||
@@ -2528,152 +2639,227 @@ void dispc_dump_regs(struct seq_file *s) | |||
2528 | DUMPREG(DISPC_CONTROL); | 2639 | DUMPREG(DISPC_CONTROL); |
2529 | DUMPREG(DISPC_CONFIG); | 2640 | DUMPREG(DISPC_CONFIG); |
2530 | DUMPREG(DISPC_CAPABLE); | 2641 | DUMPREG(DISPC_CAPABLE); |
2531 | DUMPREG(DISPC_DEFAULT_COLOR(0)); | 2642 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); |
2532 | DUMPREG(DISPC_DEFAULT_COLOR(1)); | 2643 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
2533 | DUMPREG(DISPC_TRANS_COLOR(0)); | 2644 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); |
2534 | DUMPREG(DISPC_TRANS_COLOR(1)); | 2645 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
2535 | DUMPREG(DISPC_LINE_STATUS); | 2646 | DUMPREG(DISPC_LINE_STATUS); |
2536 | DUMPREG(DISPC_LINE_NUMBER); | 2647 | DUMPREG(DISPC_LINE_NUMBER); |
2537 | DUMPREG(DISPC_TIMING_H(0)); | 2648 | DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD)); |
2538 | DUMPREG(DISPC_TIMING_V(0)); | 2649 | DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD)); |
2539 | DUMPREG(DISPC_POL_FREQ(0)); | 2650 | DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD)); |
2540 | DUMPREG(DISPC_DIVISORo(0)); | 2651 | DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD)); |
2541 | DUMPREG(DISPC_GLOBAL_ALPHA); | 2652 | DUMPREG(DISPC_GLOBAL_ALPHA); |
2542 | DUMPREG(DISPC_SIZE_DIG); | 2653 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); |
2543 | DUMPREG(DISPC_SIZE_LCD(0)); | 2654 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); |
2544 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 2655 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
2545 | DUMPREG(DISPC_CONTROL2); | 2656 | DUMPREG(DISPC_CONTROL2); |
2546 | DUMPREG(DISPC_CONFIG2); | 2657 | DUMPREG(DISPC_CONFIG2); |
2547 | DUMPREG(DISPC_DEFAULT_COLOR(2)); | 2658 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
2548 | DUMPREG(DISPC_TRANS_COLOR(2)); | 2659 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
2549 | DUMPREG(DISPC_TIMING_H(2)); | 2660 | DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2)); |
2550 | DUMPREG(DISPC_TIMING_V(2)); | 2661 | DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2)); |
2551 | DUMPREG(DISPC_POL_FREQ(2)); | 2662 | DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); |
2552 | DUMPREG(DISPC_DIVISORo(2)); | 2663 | DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2)); |
2553 | DUMPREG(DISPC_SIZE_LCD(2)); | 2664 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); |
2554 | } | 2665 | } |
2555 | 2666 | ||
2556 | DUMPREG(DISPC_GFX_BA0); | 2667 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX)); |
2557 | DUMPREG(DISPC_GFX_BA1); | 2668 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX)); |
2558 | DUMPREG(DISPC_GFX_POSITION); | 2669 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX)); |
2559 | DUMPREG(DISPC_GFX_SIZE); | 2670 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX)); |
2560 | DUMPREG(DISPC_GFX_ATTRIBUTES); | 2671 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX)); |
2561 | DUMPREG(DISPC_GFX_FIFO_THRESHOLD); | 2672 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); |
2562 | DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS); | 2673 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX)); |
2563 | DUMPREG(DISPC_GFX_ROW_INC); | 2674 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX)); |
2564 | DUMPREG(DISPC_GFX_PIXEL_INC); | 2675 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX)); |
2565 | DUMPREG(DISPC_GFX_WINDOW_SKIP); | 2676 | DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX)); |
2566 | DUMPREG(DISPC_GFX_TABLE_BA); | 2677 | DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX)); |
2567 | 2678 | ||
2568 | DUMPREG(DISPC_DATA_CYCLE1(0)); | 2679 | DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); |
2569 | DUMPREG(DISPC_DATA_CYCLE2(0)); | 2680 | DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); |
2570 | DUMPREG(DISPC_DATA_CYCLE3(0)); | 2681 | DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); |
2571 | 2682 | ||
2572 | DUMPREG(DISPC_CPR_COEF_R(0)); | 2683 | DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); |
2573 | DUMPREG(DISPC_CPR_COEF_G(0)); | 2684 | DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); |
2574 | DUMPREG(DISPC_CPR_COEF_B(0)); | 2685 | DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); |
2575 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 2686 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
2576 | DUMPREG(DISPC_DATA_CYCLE1(2)); | 2687 | DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); |
2577 | DUMPREG(DISPC_DATA_CYCLE2(2)); | 2688 | DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); |
2578 | DUMPREG(DISPC_DATA_CYCLE3(2)); | 2689 | DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); |
2579 | 2690 | ||
2580 | DUMPREG(DISPC_CPR_COEF_R(2)); | 2691 | DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); |
2581 | DUMPREG(DISPC_CPR_COEF_G(2)); | 2692 | DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); |
2582 | DUMPREG(DISPC_CPR_COEF_B(2)); | 2693 | DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); |
2583 | } | 2694 | } |
2584 | 2695 | ||
2585 | DUMPREG(DISPC_GFX_PRELOAD); | 2696 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX)); |
2586 | 2697 | ||
2587 | DUMPREG(DISPC_VID_BA0(0)); | 2698 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1)); |
2588 | DUMPREG(DISPC_VID_BA1(0)); | 2699 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1)); |
2589 | DUMPREG(DISPC_VID_POSITION(0)); | 2700 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1)); |
2590 | DUMPREG(DISPC_VID_SIZE(0)); | 2701 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1)); |
2591 | DUMPREG(DISPC_VID_ATTRIBUTES(0)); | 2702 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); |
2592 | DUMPREG(DISPC_VID_FIFO_THRESHOLD(0)); | 2703 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); |
2593 | DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0)); | 2704 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1)); |
2594 | DUMPREG(DISPC_VID_ROW_INC(0)); | 2705 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1)); |
2595 | DUMPREG(DISPC_VID_PIXEL_INC(0)); | 2706 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); |
2596 | DUMPREG(DISPC_VID_FIR(0)); | 2707 | DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1)); |
2597 | DUMPREG(DISPC_VID_PICTURE_SIZE(0)); | 2708 | DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); |
2598 | DUMPREG(DISPC_VID_ACCU0(0)); | 2709 | DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1)); |
2599 | DUMPREG(DISPC_VID_ACCU1(0)); | 2710 | DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1)); |
2600 | 2711 | ||
2601 | DUMPREG(DISPC_VID_BA0(1)); | 2712 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2)); |
2602 | DUMPREG(DISPC_VID_BA1(1)); | 2713 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2)); |
2603 | DUMPREG(DISPC_VID_POSITION(1)); | 2714 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2)); |
2604 | DUMPREG(DISPC_VID_SIZE(1)); | 2715 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2)); |
2605 | DUMPREG(DISPC_VID_ATTRIBUTES(1)); | 2716 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); |
2606 | DUMPREG(DISPC_VID_FIFO_THRESHOLD(1)); | 2717 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); |
2607 | DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1)); | 2718 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2)); |
2608 | DUMPREG(DISPC_VID_ROW_INC(1)); | 2719 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2)); |
2609 | DUMPREG(DISPC_VID_PIXEL_INC(1)); | 2720 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); |
2610 | DUMPREG(DISPC_VID_FIR(1)); | 2721 | DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2)); |
2611 | DUMPREG(DISPC_VID_PICTURE_SIZE(1)); | 2722 | DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); |
2612 | DUMPREG(DISPC_VID_ACCU0(1)); | 2723 | DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2)); |
2613 | DUMPREG(DISPC_VID_ACCU1(1)); | 2724 | DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2)); |
2614 | 2725 | ||
2615 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 0)); | 2726 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0)); |
2616 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 1)); | 2727 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1)); |
2617 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 2)); | 2728 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2)); |
2618 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 3)); | 2729 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3)); |
2619 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 4)); | 2730 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4)); |
2620 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 5)); | 2731 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5)); |
2621 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 6)); | 2732 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6)); |
2622 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 7)); | 2733 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7)); |
2623 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0)); | 2734 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0)); |
2624 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1)); | 2735 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1)); |
2625 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2)); | 2736 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2)); |
2626 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3)); | 2737 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3)); |
2627 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4)); | 2738 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4)); |
2628 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5)); | 2739 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5)); |
2629 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6)); | 2740 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6)); |
2630 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7)); | 2741 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7)); |
2631 | DUMPREG(DISPC_VID_CONV_COEF(0, 0)); | 2742 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0)); |
2632 | DUMPREG(DISPC_VID_CONV_COEF(0, 1)); | 2743 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1)); |
2633 | DUMPREG(DISPC_VID_CONV_COEF(0, 2)); | 2744 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2)); |
2634 | DUMPREG(DISPC_VID_CONV_COEF(0, 3)); | 2745 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3)); |
2635 | DUMPREG(DISPC_VID_CONV_COEF(0, 4)); | 2746 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4)); |
2636 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 0)); | 2747 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0)); |
2637 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 1)); | 2748 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1)); |
2638 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 2)); | 2749 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2)); |
2639 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 3)); | 2750 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3)); |
2640 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 4)); | 2751 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4)); |
2641 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 5)); | 2752 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5)); |
2642 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 6)); | 2753 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6)); |
2643 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 7)); | 2754 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7)); |
2644 | 2755 | ||
2645 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 0)); | 2756 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
2646 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 1)); | 2757 | DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1)); |
2647 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 2)); | 2758 | DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO1)); |
2648 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 3)); | 2759 | DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO1)); |
2649 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 4)); | 2760 | DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO1)); |
2650 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 5)); | 2761 | DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO1)); |
2651 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 6)); | 2762 | |
2652 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 7)); | 2763 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 0)); |
2653 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0)); | 2764 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 1)); |
2654 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1)); | 2765 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 2)); |
2655 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2)); | 2766 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 3)); |
2656 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3)); | 2767 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 4)); |
2657 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4)); | 2768 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 5)); |
2658 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5)); | 2769 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 6)); |
2659 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6)); | 2770 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 7)); |
2660 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7)); | 2771 | |
2661 | DUMPREG(DISPC_VID_CONV_COEF(1, 0)); | 2772 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 0)); |
2662 | DUMPREG(DISPC_VID_CONV_COEF(1, 1)); | 2773 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 1)); |
2663 | DUMPREG(DISPC_VID_CONV_COEF(1, 2)); | 2774 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 2)); |
2664 | DUMPREG(DISPC_VID_CONV_COEF(1, 3)); | 2775 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 3)); |
2665 | DUMPREG(DISPC_VID_CONV_COEF(1, 4)); | 2776 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 4)); |
2666 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 0)); | 2777 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 5)); |
2667 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 1)); | 2778 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 6)); |
2668 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 2)); | 2779 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 7)); |
2669 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 3)); | 2780 | |
2670 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 4)); | 2781 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 0)); |
2671 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 5)); | 2782 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 1)); |
2672 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 6)); | 2783 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 2)); |
2673 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 7)); | 2784 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 3)); |
2674 | 2785 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 4)); | |
2675 | DUMPREG(DISPC_VID_PRELOAD(0)); | 2786 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 5)); |
2676 | DUMPREG(DISPC_VID_PRELOAD(1)); | 2787 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 6)); |
2788 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 7)); | ||
2789 | } | ||
2790 | if (dss_has_feature(FEAT_ATTR2)) | ||
2791 | DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); | ||
2792 | |||
2793 | |||
2794 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0)); | ||
2795 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1)); | ||
2796 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2)); | ||
2797 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3)); | ||
2798 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4)); | ||
2799 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5)); | ||
2800 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6)); | ||
2801 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7)); | ||
2802 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0)); | ||
2803 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1)); | ||
2804 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2)); | ||
2805 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3)); | ||
2806 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4)); | ||
2807 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5)); | ||
2808 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6)); | ||
2809 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7)); | ||
2810 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0)); | ||
2811 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1)); | ||
2812 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2)); | ||
2813 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3)); | ||
2814 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4)); | ||
2815 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0)); | ||
2816 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1)); | ||
2817 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2)); | ||
2818 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3)); | ||
2819 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4)); | ||
2820 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5)); | ||
2821 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6)); | ||
2822 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7)); | ||
2823 | |||
2824 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
2825 | DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2)); | ||
2826 | DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO2)); | ||
2827 | DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO2)); | ||
2828 | DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO2)); | ||
2829 | DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | ||
2830 | |||
2831 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 0)); | ||
2832 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 1)); | ||
2833 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 2)); | ||
2834 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 3)); | ||
2835 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 4)); | ||
2836 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 5)); | ||
2837 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 6)); | ||
2838 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 7)); | ||
2839 | |||
2840 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 0)); | ||
2841 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 1)); | ||
2842 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 2)); | ||
2843 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 3)); | ||
2844 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 4)); | ||
2845 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 5)); | ||
2846 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 6)); | ||
2847 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 7)); | ||
2848 | |||
2849 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 0)); | ||
2850 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 1)); | ||
2851 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 2)); | ||
2852 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 3)); | ||
2853 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 4)); | ||
2854 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 5)); | ||
2855 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 6)); | ||
2856 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 7)); | ||
2857 | } | ||
2858 | if (dss_has_feature(FEAT_ATTR2)) | ||
2859 | DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); | ||
2860 | |||
2861 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1)); | ||
2862 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); | ||
2677 | 2863 | ||
2678 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | 2864 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
2679 | #undef DUMPREG | 2865 | #undef DUMPREG |
@@ -3388,11 +3574,12 @@ int dispc_setup_plane(enum omap_plane plane, | |||
3388 | bool ilace, | 3574 | bool ilace, |
3389 | enum omap_dss_rotation_type rotation_type, | 3575 | enum omap_dss_rotation_type rotation_type, |
3390 | u8 rotation, bool mirror, u8 global_alpha, | 3576 | u8 rotation, bool mirror, u8 global_alpha, |
3391 | u8 pre_mult_alpha, enum omap_channel channel) | 3577 | u8 pre_mult_alpha, enum omap_channel channel, |
3578 | u32 puv_addr) | ||
3392 | { | 3579 | { |
3393 | int r = 0; | 3580 | int r = 0; |
3394 | 3581 | ||
3395 | DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " | 3582 | DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> " |
3396 | "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", | 3583 | "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", |
3397 | plane, paddr, screen_width, pos_x, pos_y, | 3584 | plane, paddr, screen_width, pos_x, pos_y, |
3398 | width, height, | 3585 | width, height, |
@@ -3411,7 +3598,8 @@ int dispc_setup_plane(enum omap_plane plane, | |||
3411 | rotation_type, | 3598 | rotation_type, |
3412 | rotation, mirror, | 3599 | rotation, mirror, |
3413 | global_alpha, | 3600 | global_alpha, |
3414 | pre_mult_alpha, channel); | 3601 | pre_mult_alpha, |
3602 | channel, puv_addr); | ||
3415 | 3603 | ||
3416 | enable_clocks(0); | 3604 | enable_clocks(0); |
3417 | 3605 | ||
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h new file mode 100644 index 000000000000..6c9ee0a0efb3 --- /dev/null +++ b/drivers/video/omap2/dss/dispc.h | |||
@@ -0,0 +1,691 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/omap2/dss/dispc.h | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments | ||
5 | * Author: Archit Taneja <archit@ti.com> | ||
6 | * | ||
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 __OMAP2_DISPC_REG_H | ||
22 | #define __OMAP2_DISPC_REG_H | ||
23 | |||
24 | /* DISPC common registers */ | ||
25 | #define DISPC_REVISION 0x0000 | ||
26 | #define DISPC_SYSCONFIG 0x0010 | ||
27 | #define DISPC_SYSSTATUS 0x0014 | ||
28 | #define DISPC_IRQSTATUS 0x0018 | ||
29 | #define DISPC_IRQENABLE 0x001C | ||
30 | #define DISPC_CONTROL 0x0040 | ||
31 | #define DISPC_CONFIG 0x0044 | ||
32 | #define DISPC_CAPABLE 0x0048 | ||
33 | #define DISPC_LINE_STATUS 0x005C | ||
34 | #define DISPC_LINE_NUMBER 0x0060 | ||
35 | #define DISPC_GLOBAL_ALPHA 0x0074 | ||
36 | #define DISPC_CONTROL2 0x0238 | ||
37 | #define DISPC_CONFIG2 0x0620 | ||
38 | #define DISPC_DIVISOR 0x0804 | ||
39 | |||
40 | /* DISPC overlay registers */ | ||
41 | #define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \ | ||
42 | DISPC_BA0_OFFSET(n)) | ||
43 | #define DISPC_OVL_BA1(n) (DISPC_OVL_BASE(n) + \ | ||
44 | DISPC_BA1_OFFSET(n)) | ||
45 | #define DISPC_OVL_BA0_UV(n) (DISPC_OVL_BASE(n) + \ | ||
46 | DISPC_BA0_UV_OFFSET(n)) | ||
47 | #define DISPC_OVL_BA1_UV(n) (DISPC_OVL_BASE(n) + \ | ||
48 | DISPC_BA1_UV_OFFSET(n)) | ||
49 | #define DISPC_OVL_POSITION(n) (DISPC_OVL_BASE(n) + \ | ||
50 | DISPC_POS_OFFSET(n)) | ||
51 | #define DISPC_OVL_SIZE(n) (DISPC_OVL_BASE(n) + \ | ||
52 | DISPC_SIZE_OFFSET(n)) | ||
53 | #define DISPC_OVL_ATTRIBUTES(n) (DISPC_OVL_BASE(n) + \ | ||
54 | DISPC_ATTR_OFFSET(n)) | ||
55 | #define DISPC_OVL_ATTRIBUTES2(n) (DISPC_OVL_BASE(n) + \ | ||
56 | DISPC_ATTR2_OFFSET(n)) | ||
57 | #define DISPC_OVL_FIFO_THRESHOLD(n) (DISPC_OVL_BASE(n) + \ | ||
58 | DISPC_FIFO_THRESH_OFFSET(n)) | ||
59 | #define DISPC_OVL_FIFO_SIZE_STATUS(n) (DISPC_OVL_BASE(n) + \ | ||
60 | DISPC_FIFO_SIZE_STATUS_OFFSET(n)) | ||
61 | #define DISPC_OVL_ROW_INC(n) (DISPC_OVL_BASE(n) + \ | ||
62 | DISPC_ROW_INC_OFFSET(n)) | ||
63 | #define DISPC_OVL_PIXEL_INC(n) (DISPC_OVL_BASE(n) + \ | ||
64 | DISPC_PIX_INC_OFFSET(n)) | ||
65 | #define DISPC_OVL_WINDOW_SKIP(n) (DISPC_OVL_BASE(n) + \ | ||
66 | DISPC_WINDOW_SKIP_OFFSET(n)) | ||
67 | #define DISPC_OVL_TABLE_BA(n) (DISPC_OVL_BASE(n) + \ | ||
68 | DISPC_TABLE_BA_OFFSET(n)) | ||
69 | #define DISPC_OVL_FIR(n) (DISPC_OVL_BASE(n) + \ | ||
70 | DISPC_FIR_OFFSET(n)) | ||
71 | #define DISPC_OVL_FIR2(n) (DISPC_OVL_BASE(n) + \ | ||
72 | DISPC_FIR2_OFFSET(n)) | ||
73 | #define DISPC_OVL_PICTURE_SIZE(n) (DISPC_OVL_BASE(n) + \ | ||
74 | DISPC_PIC_SIZE_OFFSET(n)) | ||
75 | #define DISPC_OVL_ACCU0(n) (DISPC_OVL_BASE(n) + \ | ||
76 | DISPC_ACCU0_OFFSET(n)) | ||
77 | #define DISPC_OVL_ACCU1(n) (DISPC_OVL_BASE(n) + \ | ||
78 | DISPC_ACCU1_OFFSET(n)) | ||
79 | #define DISPC_OVL_ACCU2_0(n) (DISPC_OVL_BASE(n) + \ | ||
80 | DISPC_ACCU2_0_OFFSET(n)) | ||
81 | #define DISPC_OVL_ACCU2_1(n) (DISPC_OVL_BASE(n) + \ | ||
82 | DISPC_ACCU2_1_OFFSET(n)) | ||
83 | #define DISPC_OVL_FIR_COEF_H(n, i) (DISPC_OVL_BASE(n) + \ | ||
84 | DISPC_FIR_COEF_H_OFFSET(n, i)) | ||
85 | #define DISPC_OVL_FIR_COEF_HV(n, i) (DISPC_OVL_BASE(n) + \ | ||
86 | DISPC_FIR_COEF_HV_OFFSET(n, i)) | ||
87 | #define DISPC_OVL_FIR_COEF_H2(n, i) (DISPC_OVL_BASE(n) + \ | ||
88 | DISPC_FIR_COEF_H2_OFFSET(n, i)) | ||
89 | #define DISPC_OVL_FIR_COEF_HV2(n, i) (DISPC_OVL_BASE(n) + \ | ||
90 | DISPC_FIR_COEF_HV2_OFFSET(n, i)) | ||
91 | #define DISPC_OVL_CONV_COEF(n, i) (DISPC_OVL_BASE(n) + \ | ||
92 | DISPC_CONV_COEF_OFFSET(n, i)) | ||
93 | #define DISPC_OVL_FIR_COEF_V(n, i) (DISPC_OVL_BASE(n) + \ | ||
94 | DISPC_FIR_COEF_V_OFFSET(n, i)) | ||
95 | #define DISPC_OVL_FIR_COEF_V2(n, i) (DISPC_OVL_BASE(n) + \ | ||
96 | DISPC_FIR_COEF_V2_OFFSET(n, i)) | ||
97 | #define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \ | ||
98 | DISPC_PRELOAD_OFFSET(n)) | ||
99 | |||
100 | /* DISPC manager/channel specific registers */ | ||
101 | static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel) | ||
102 | { | ||
103 | switch (channel) { | ||
104 | case OMAP_DSS_CHANNEL_LCD: | ||
105 | return 0x004C; | ||
106 | case OMAP_DSS_CHANNEL_DIGIT: | ||
107 | return 0x0050; | ||
108 | case OMAP_DSS_CHANNEL_LCD2: | ||
109 | return 0x03AC; | ||
110 | default: | ||
111 | BUG(); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel) | ||
116 | { | ||
117 | switch (channel) { | ||
118 | case OMAP_DSS_CHANNEL_LCD: | ||
119 | return 0x0054; | ||
120 | case OMAP_DSS_CHANNEL_DIGIT: | ||
121 | return 0x0058; | ||
122 | case OMAP_DSS_CHANNEL_LCD2: | ||
123 | return 0x03B0; | ||
124 | default: | ||
125 | BUG(); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static inline u16 DISPC_TIMING_H(enum omap_channel channel) | ||
130 | { | ||
131 | switch (channel) { | ||
132 | case OMAP_DSS_CHANNEL_LCD: | ||
133 | return 0x0064; | ||
134 | case OMAP_DSS_CHANNEL_DIGIT: | ||
135 | BUG(); | ||
136 | case OMAP_DSS_CHANNEL_LCD2: | ||
137 | return 0x0400; | ||
138 | default: | ||
139 | BUG(); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static inline u16 DISPC_TIMING_V(enum omap_channel channel) | ||
144 | { | ||
145 | switch (channel) { | ||
146 | case OMAP_DSS_CHANNEL_LCD: | ||
147 | return 0x0068; | ||
148 | case OMAP_DSS_CHANNEL_DIGIT: | ||
149 | BUG(); | ||
150 | case OMAP_DSS_CHANNEL_LCD2: | ||
151 | return 0x0404; | ||
152 | default: | ||
153 | BUG(); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | static inline u16 DISPC_POL_FREQ(enum omap_channel channel) | ||
158 | { | ||
159 | switch (channel) { | ||
160 | case OMAP_DSS_CHANNEL_LCD: | ||
161 | return 0x006C; | ||
162 | case OMAP_DSS_CHANNEL_DIGIT: | ||
163 | BUG(); | ||
164 | case OMAP_DSS_CHANNEL_LCD2: | ||
165 | return 0x0408; | ||
166 | default: | ||
167 | BUG(); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static inline u16 DISPC_DIVISORo(enum omap_channel channel) | ||
172 | { | ||
173 | switch (channel) { | ||
174 | case OMAP_DSS_CHANNEL_LCD: | ||
175 | return 0x0070; | ||
176 | case OMAP_DSS_CHANNEL_DIGIT: | ||
177 | BUG(); | ||
178 | case OMAP_DSS_CHANNEL_LCD2: | ||
179 | return 0x040C; | ||
180 | default: | ||
181 | BUG(); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* Named as DISPC_SIZE_LCD, DISPC_SIZE_DIGIT and DISPC_SIZE_LCD2 in TRM */ | ||
186 | static inline u16 DISPC_SIZE_MGR(enum omap_channel channel) | ||
187 | { | ||
188 | switch (channel) { | ||
189 | case OMAP_DSS_CHANNEL_LCD: | ||
190 | return 0x007C; | ||
191 | case OMAP_DSS_CHANNEL_DIGIT: | ||
192 | return 0x0078; | ||
193 | case OMAP_DSS_CHANNEL_LCD2: | ||
194 | return 0x03CC; | ||
195 | default: | ||
196 | BUG(); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel) | ||
201 | { | ||
202 | switch (channel) { | ||
203 | case OMAP_DSS_CHANNEL_LCD: | ||
204 | return 0x01D4; | ||
205 | case OMAP_DSS_CHANNEL_DIGIT: | ||
206 | BUG(); | ||
207 | case OMAP_DSS_CHANNEL_LCD2: | ||
208 | return 0x03C0; | ||
209 | default: | ||
210 | BUG(); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel) | ||
215 | { | ||
216 | switch (channel) { | ||
217 | case OMAP_DSS_CHANNEL_LCD: | ||
218 | return 0x01D8; | ||
219 | case OMAP_DSS_CHANNEL_DIGIT: | ||
220 | BUG(); | ||
221 | case OMAP_DSS_CHANNEL_LCD2: | ||
222 | return 0x03C4; | ||
223 | default: | ||
224 | BUG(); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel) | ||
229 | { | ||
230 | switch (channel) { | ||
231 | case OMAP_DSS_CHANNEL_LCD: | ||
232 | return 0x01DC; | ||
233 | case OMAP_DSS_CHANNEL_DIGIT: | ||
234 | BUG(); | ||
235 | case OMAP_DSS_CHANNEL_LCD2: | ||
236 | return 0x03C8; | ||
237 | default: | ||
238 | BUG(); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel) | ||
243 | { | ||
244 | switch (channel) { | ||
245 | case OMAP_DSS_CHANNEL_LCD: | ||
246 | return 0x0220; | ||
247 | case OMAP_DSS_CHANNEL_DIGIT: | ||
248 | BUG(); | ||
249 | case OMAP_DSS_CHANNEL_LCD2: | ||
250 | return 0x03BC; | ||
251 | default: | ||
252 | BUG(); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel) | ||
257 | { | ||
258 | switch (channel) { | ||
259 | case OMAP_DSS_CHANNEL_LCD: | ||
260 | return 0x0224; | ||
261 | case OMAP_DSS_CHANNEL_DIGIT: | ||
262 | BUG(); | ||
263 | case OMAP_DSS_CHANNEL_LCD2: | ||
264 | return 0x03B8; | ||
265 | default: | ||
266 | BUG(); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel) | ||
271 | { | ||
272 | switch (channel) { | ||
273 | case OMAP_DSS_CHANNEL_LCD: | ||
274 | return 0x0228; | ||
275 | case OMAP_DSS_CHANNEL_DIGIT: | ||
276 | BUG(); | ||
277 | case OMAP_DSS_CHANNEL_LCD2: | ||
278 | return 0x03B4; | ||
279 | default: | ||
280 | BUG(); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | /* DISPC overlay register base addresses */ | ||
285 | static inline u16 DISPC_OVL_BASE(enum omap_plane plane) | ||
286 | { | ||
287 | switch (plane) { | ||
288 | case OMAP_DSS_GFX: | ||
289 | return 0x0080; | ||
290 | case OMAP_DSS_VIDEO1: | ||
291 | return 0x00BC; | ||
292 | case OMAP_DSS_VIDEO2: | ||
293 | return 0x014C; | ||
294 | default: | ||
295 | BUG(); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | /* DISPC overlay register offsets */ | ||
300 | static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane) | ||
301 | { | ||
302 | switch (plane) { | ||
303 | case OMAP_DSS_GFX: | ||
304 | case OMAP_DSS_VIDEO1: | ||
305 | case OMAP_DSS_VIDEO2: | ||
306 | return 0x0000; | ||
307 | default: | ||
308 | BUG(); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane) | ||
313 | { | ||
314 | switch (plane) { | ||
315 | case OMAP_DSS_GFX: | ||
316 | case OMAP_DSS_VIDEO1: | ||
317 | case OMAP_DSS_VIDEO2: | ||
318 | return 0x0004; | ||
319 | default: | ||
320 | BUG(); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane) | ||
325 | { | ||
326 | switch (plane) { | ||
327 | case OMAP_DSS_GFX: | ||
328 | BUG(); | ||
329 | case OMAP_DSS_VIDEO1: | ||
330 | return 0x0544; | ||
331 | case OMAP_DSS_VIDEO2: | ||
332 | return 0x04BC; | ||
333 | default: | ||
334 | BUG(); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane) | ||
339 | { | ||
340 | switch (plane) { | ||
341 | case OMAP_DSS_GFX: | ||
342 | BUG(); | ||
343 | case OMAP_DSS_VIDEO1: | ||
344 | return 0x0548; | ||
345 | case OMAP_DSS_VIDEO2: | ||
346 | return 0x04C0; | ||
347 | default: | ||
348 | BUG(); | ||
349 | } | ||
350 | } | ||
351 | |||
352 | static inline u16 DISPC_POS_OFFSET(enum omap_plane plane) | ||
353 | { | ||
354 | switch (plane) { | ||
355 | case OMAP_DSS_GFX: | ||
356 | case OMAP_DSS_VIDEO1: | ||
357 | case OMAP_DSS_VIDEO2: | ||
358 | return 0x0008; | ||
359 | default: | ||
360 | BUG(); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane) | ||
365 | { | ||
366 | switch (plane) { | ||
367 | case OMAP_DSS_GFX: | ||
368 | case OMAP_DSS_VIDEO1: | ||
369 | case OMAP_DSS_VIDEO2: | ||
370 | return 0x000C; | ||
371 | default: | ||
372 | BUG(); | ||
373 | } | ||
374 | } | ||
375 | |||
376 | static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane) | ||
377 | { | ||
378 | switch (plane) { | ||
379 | case OMAP_DSS_GFX: | ||
380 | return 0x0020; | ||
381 | case OMAP_DSS_VIDEO1: | ||
382 | case OMAP_DSS_VIDEO2: | ||
383 | return 0x0010; | ||
384 | default: | ||
385 | BUG(); | ||
386 | } | ||
387 | } | ||
388 | |||
389 | static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane) | ||
390 | { | ||
391 | switch (plane) { | ||
392 | case OMAP_DSS_GFX: | ||
393 | BUG(); | ||
394 | case OMAP_DSS_VIDEO1: | ||
395 | return 0x0568; | ||
396 | case OMAP_DSS_VIDEO2: | ||
397 | return 0x04DC; | ||
398 | default: | ||
399 | BUG(); | ||
400 | } | ||
401 | } | ||
402 | |||
403 | static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane) | ||
404 | { | ||
405 | switch (plane) { | ||
406 | case OMAP_DSS_GFX: | ||
407 | return 0x0024; | ||
408 | case OMAP_DSS_VIDEO1: | ||
409 | case OMAP_DSS_VIDEO2: | ||
410 | return 0x0014; | ||
411 | default: | ||
412 | BUG(); | ||
413 | } | ||
414 | } | ||
415 | |||
416 | static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane) | ||
417 | { | ||
418 | switch (plane) { | ||
419 | case OMAP_DSS_GFX: | ||
420 | return 0x0028; | ||
421 | case OMAP_DSS_VIDEO1: | ||
422 | case OMAP_DSS_VIDEO2: | ||
423 | return 0x0018; | ||
424 | default: | ||
425 | BUG(); | ||
426 | } | ||
427 | } | ||
428 | |||
429 | static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane) | ||
430 | { | ||
431 | switch (plane) { | ||
432 | case OMAP_DSS_GFX: | ||
433 | return 0x002C; | ||
434 | case OMAP_DSS_VIDEO1: | ||
435 | case OMAP_DSS_VIDEO2: | ||
436 | return 0x001C; | ||
437 | default: | ||
438 | BUG(); | ||
439 | } | ||
440 | } | ||
441 | |||
442 | static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane) | ||
443 | { | ||
444 | switch (plane) { | ||
445 | case OMAP_DSS_GFX: | ||
446 | return 0x0030; | ||
447 | case OMAP_DSS_VIDEO1: | ||
448 | case OMAP_DSS_VIDEO2: | ||
449 | return 0x0020; | ||
450 | default: | ||
451 | BUG(); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane) | ||
456 | { | ||
457 | switch (plane) { | ||
458 | case OMAP_DSS_GFX: | ||
459 | return 0x0034; | ||
460 | case OMAP_DSS_VIDEO1: | ||
461 | case OMAP_DSS_VIDEO2: | ||
462 | BUG(); | ||
463 | default: | ||
464 | BUG(); | ||
465 | } | ||
466 | } | ||
467 | |||
468 | static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane) | ||
469 | { | ||
470 | switch (plane) { | ||
471 | case OMAP_DSS_GFX: | ||
472 | return 0x0038; | ||
473 | case OMAP_DSS_VIDEO1: | ||
474 | case OMAP_DSS_VIDEO2: | ||
475 | BUG(); | ||
476 | default: | ||
477 | BUG(); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane) | ||
482 | { | ||
483 | switch (plane) { | ||
484 | case OMAP_DSS_GFX: | ||
485 | BUG(); | ||
486 | case OMAP_DSS_VIDEO1: | ||
487 | case OMAP_DSS_VIDEO2: | ||
488 | return 0x0024; | ||
489 | default: | ||
490 | BUG(); | ||
491 | } | ||
492 | } | ||
493 | |||
494 | static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane) | ||
495 | { | ||
496 | switch (plane) { | ||
497 | case OMAP_DSS_GFX: | ||
498 | BUG(); | ||
499 | case OMAP_DSS_VIDEO1: | ||
500 | return 0x0580; | ||
501 | case OMAP_DSS_VIDEO2: | ||
502 | return 0x055C; | ||
503 | default: | ||
504 | BUG(); | ||
505 | } | ||
506 | } | ||
507 | |||
508 | static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane) | ||
509 | { | ||
510 | switch (plane) { | ||
511 | case OMAP_DSS_GFX: | ||
512 | BUG(); | ||
513 | case OMAP_DSS_VIDEO1: | ||
514 | case OMAP_DSS_VIDEO2: | ||
515 | return 0x0028; | ||
516 | default: | ||
517 | BUG(); | ||
518 | } | ||
519 | } | ||
520 | |||
521 | |||
522 | static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane) | ||
523 | { | ||
524 | switch (plane) { | ||
525 | case OMAP_DSS_GFX: | ||
526 | BUG(); | ||
527 | case OMAP_DSS_VIDEO1: | ||
528 | case OMAP_DSS_VIDEO2: | ||
529 | return 0x002C; | ||
530 | default: | ||
531 | BUG(); | ||
532 | } | ||
533 | } | ||
534 | |||
535 | static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane) | ||
536 | { | ||
537 | switch (plane) { | ||
538 | case OMAP_DSS_GFX: | ||
539 | BUG(); | ||
540 | case OMAP_DSS_VIDEO1: | ||
541 | return 0x0584; | ||
542 | case OMAP_DSS_VIDEO2: | ||
543 | return 0x0560; | ||
544 | default: | ||
545 | BUG(); | ||
546 | } | ||
547 | } | ||
548 | |||
549 | static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane) | ||
550 | { | ||
551 | switch (plane) { | ||
552 | case OMAP_DSS_GFX: | ||
553 | BUG(); | ||
554 | case OMAP_DSS_VIDEO1: | ||
555 | case OMAP_DSS_VIDEO2: | ||
556 | return 0x0030; | ||
557 | default: | ||
558 | BUG(); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane) | ||
563 | { | ||
564 | switch (plane) { | ||
565 | case OMAP_DSS_GFX: | ||
566 | BUG(); | ||
567 | case OMAP_DSS_VIDEO1: | ||
568 | return 0x0588; | ||
569 | case OMAP_DSS_VIDEO2: | ||
570 | return 0x0564; | ||
571 | default: | ||
572 | BUG(); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
577 | static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i) | ||
578 | { | ||
579 | switch (plane) { | ||
580 | case OMAP_DSS_GFX: | ||
581 | BUG(); | ||
582 | case OMAP_DSS_VIDEO1: | ||
583 | case OMAP_DSS_VIDEO2: | ||
584 | return 0x0034 + i * 0x8; | ||
585 | default: | ||
586 | BUG(); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
591 | static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i) | ||
592 | { | ||
593 | switch (plane) { | ||
594 | case OMAP_DSS_GFX: | ||
595 | BUG(); | ||
596 | case OMAP_DSS_VIDEO1: | ||
597 | return 0x058C + i * 0x8; | ||
598 | case OMAP_DSS_VIDEO2: | ||
599 | return 0x0568 + i * 0x8; | ||
600 | default: | ||
601 | BUG(); | ||
602 | } | ||
603 | } | ||
604 | |||
605 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
606 | static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i) | ||
607 | { | ||
608 | switch (plane) { | ||
609 | case OMAP_DSS_GFX: | ||
610 | BUG(); | ||
611 | case OMAP_DSS_VIDEO1: | ||
612 | case OMAP_DSS_VIDEO2: | ||
613 | return 0x0038 + i * 0x8; | ||
614 | default: | ||
615 | BUG(); | ||
616 | } | ||
617 | } | ||
618 | |||
619 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
620 | static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i) | ||
621 | { | ||
622 | switch (plane) { | ||
623 | case OMAP_DSS_GFX: | ||
624 | BUG(); | ||
625 | case OMAP_DSS_VIDEO1: | ||
626 | return 0x0590 + i * 8; | ||
627 | case OMAP_DSS_VIDEO2: | ||
628 | return 0x056C + i * 0x8; | ||
629 | default: | ||
630 | BUG(); | ||
631 | } | ||
632 | } | ||
633 | |||
634 | /* coef index i = {0, 1, 2, 3, 4,} */ | ||
635 | static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i) | ||
636 | { | ||
637 | switch (plane) { | ||
638 | case OMAP_DSS_GFX: | ||
639 | BUG(); | ||
640 | case OMAP_DSS_VIDEO1: | ||
641 | case OMAP_DSS_VIDEO2: | ||
642 | return 0x0074 + i * 0x4; | ||
643 | default: | ||
644 | BUG(); | ||
645 | } | ||
646 | } | ||
647 | |||
648 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
649 | static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i) | ||
650 | { | ||
651 | switch (plane) { | ||
652 | case OMAP_DSS_GFX: | ||
653 | BUG(); | ||
654 | case OMAP_DSS_VIDEO1: | ||
655 | return 0x0124 + i * 0x4; | ||
656 | case OMAP_DSS_VIDEO2: | ||
657 | return 0x00B4 + i * 0x4; | ||
658 | default: | ||
659 | BUG(); | ||
660 | } | ||
661 | } | ||
662 | |||
663 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
664 | static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i) | ||
665 | { | ||
666 | switch (plane) { | ||
667 | case OMAP_DSS_GFX: | ||
668 | BUG(); | ||
669 | case OMAP_DSS_VIDEO1: | ||
670 | return 0x05CC + i * 0x4; | ||
671 | case OMAP_DSS_VIDEO2: | ||
672 | return 0x05A8 + i * 0x4; | ||
673 | default: | ||
674 | BUG(); | ||
675 | } | ||
676 | } | ||
677 | |||
678 | static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane) | ||
679 | { | ||
680 | switch (plane) { | ||
681 | case OMAP_DSS_GFX: | ||
682 | return 0x01AC; | ||
683 | case OMAP_DSS_VIDEO1: | ||
684 | return 0x0174; | ||
685 | case OMAP_DSS_VIDEO2: | ||
686 | return 0x00E8; | ||
687 | default: | ||
688 | BUG(); | ||
689 | } | ||
690 | } | ||
691 | #endif | ||
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index a85a6f38b40c..c2dfc8c50057 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | 29 | ||
30 | #include <plat/display.h> | 30 | #include <video/omapdss.h> |
31 | #include "dss.h" | 31 | #include "dss.h" |
32 | 32 | ||
33 | static ssize_t display_enabled_show(struct device *dev, | 33 | static ssize_t display_enabled_show(struct device *dev, |
@@ -44,9 +44,13 @@ static ssize_t display_enabled_store(struct device *dev, | |||
44 | const char *buf, size_t size) | 44 | const char *buf, size_t size) |
45 | { | 45 | { |
46 | struct omap_dss_device *dssdev = to_dss_device(dev); | 46 | struct omap_dss_device *dssdev = to_dss_device(dev); |
47 | bool enabled, r; | 47 | int r, enabled; |
48 | 48 | ||
49 | enabled = simple_strtoul(buf, NULL, 10); | 49 | r = kstrtoint(buf, 0, &enabled); |
50 | if (r) | ||
51 | return r; | ||
52 | |||
53 | enabled = !!enabled; | ||
50 | 54 | ||
51 | if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { | 55 | if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { |
52 | if (enabled) { | 56 | if (enabled) { |
@@ -82,7 +86,9 @@ static ssize_t display_upd_mode_store(struct device *dev, | |||
82 | if (!dssdev->driver->set_update_mode) | 86 | if (!dssdev->driver->set_update_mode) |
83 | return -EINVAL; | 87 | return -EINVAL; |
84 | 88 | ||
85 | val = simple_strtoul(buf, NULL, 10); | 89 | r = kstrtoint(buf, 0, &val); |
90 | if (r) | ||
91 | return r; | ||
86 | 92 | ||
87 | switch (val) { | 93 | switch (val) { |
88 | case OMAP_DSS_UPDATE_DISABLED: | 94 | case OMAP_DSS_UPDATE_DISABLED: |
@@ -114,13 +120,16 @@ static ssize_t display_tear_store(struct device *dev, | |||
114 | struct device_attribute *attr, const char *buf, size_t size) | 120 | struct device_attribute *attr, const char *buf, size_t size) |
115 | { | 121 | { |
116 | struct omap_dss_device *dssdev = to_dss_device(dev); | 122 | struct omap_dss_device *dssdev = to_dss_device(dev); |
117 | unsigned long te; | 123 | int te, r; |
118 | int r; | ||
119 | 124 | ||
120 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) | 125 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) |
121 | return -ENOENT; | 126 | return -ENOENT; |
122 | 127 | ||
123 | te = simple_strtoul(buf, NULL, 0); | 128 | r = kstrtoint(buf, 0, &te); |
129 | if (r) | ||
130 | return r; | ||
131 | |||
132 | te = !!te; | ||
124 | 133 | ||
125 | r = dssdev->driver->enable_te(dssdev, te); | 134 | r = dssdev->driver->enable_te(dssdev, te); |
126 | if (r) | 135 | if (r) |
@@ -196,13 +205,14 @@ static ssize_t display_rotate_store(struct device *dev, | |||
196 | struct device_attribute *attr, const char *buf, size_t size) | 205 | struct device_attribute *attr, const char *buf, size_t size) |
197 | { | 206 | { |
198 | struct omap_dss_device *dssdev = to_dss_device(dev); | 207 | struct omap_dss_device *dssdev = to_dss_device(dev); |
199 | unsigned long rot; | 208 | int rot, r; |
200 | int r; | ||
201 | 209 | ||
202 | if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) | 210 | if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) |
203 | return -ENOENT; | 211 | return -ENOENT; |
204 | 212 | ||
205 | rot = simple_strtoul(buf, NULL, 0); | 213 | r = kstrtoint(buf, 0, &rot); |
214 | if (r) | ||
215 | return r; | ||
206 | 216 | ||
207 | r = dssdev->driver->set_rotate(dssdev, rot); | 217 | r = dssdev->driver->set_rotate(dssdev, rot); |
208 | if (r) | 218 | if (r) |
@@ -226,13 +236,16 @@ static ssize_t display_mirror_store(struct device *dev, | |||
226 | struct device_attribute *attr, const char *buf, size_t size) | 236 | struct device_attribute *attr, const char *buf, size_t size) |
227 | { | 237 | { |
228 | struct omap_dss_device *dssdev = to_dss_device(dev); | 238 | struct omap_dss_device *dssdev = to_dss_device(dev); |
229 | unsigned long mirror; | 239 | int mirror, r; |
230 | int r; | ||
231 | 240 | ||
232 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) | 241 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) |
233 | return -ENOENT; | 242 | return -ENOENT; |
234 | 243 | ||
235 | mirror = simple_strtoul(buf, NULL, 0); | 244 | r = kstrtoint(buf, 0, &mirror); |
245 | if (r) | ||
246 | return r; | ||
247 | |||
248 | mirror = !!mirror; | ||
236 | 249 | ||
237 | r = dssdev->driver->set_mirror(dssdev, mirror); | 250 | r = dssdev->driver->set_mirror(dssdev, mirror); |
238 | if (r) | 251 | if (r) |
@@ -259,14 +272,15 @@ static ssize_t display_wss_store(struct device *dev, | |||
259 | struct device_attribute *attr, const char *buf, size_t size) | 272 | struct device_attribute *attr, const char *buf, size_t size) |
260 | { | 273 | { |
261 | struct omap_dss_device *dssdev = to_dss_device(dev); | 274 | struct omap_dss_device *dssdev = to_dss_device(dev); |
262 | unsigned long wss; | 275 | u32 wss; |
263 | int r; | 276 | int r; |
264 | 277 | ||
265 | if (!dssdev->driver->get_wss || !dssdev->driver->set_wss) | 278 | if (!dssdev->driver->get_wss || !dssdev->driver->set_wss) |
266 | return -ENOENT; | 279 | return -ENOENT; |
267 | 280 | ||
268 | if (strict_strtoul(buf, 0, &wss)) | 281 | r = kstrtou32(buf, 0, &wss); |
269 | return -EINVAL; | 282 | if (r) |
283 | return r; | ||
270 | 284 | ||
271 | if (wss > 0xfffff) | 285 | if (wss > 0xfffff) |
272 | return -EINVAL; | 286 | return -EINVAL; |
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 2d3ca4ca4a05..ff6bd30132df 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
@@ -30,16 +30,40 @@ | |||
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/regulator/consumer.h> | 31 | #include <linux/regulator/consumer.h> |
32 | 32 | ||
33 | #include <plat/display.h> | 33 | #include <video/omapdss.h> |
34 | #include <plat/cpu.h> | 34 | #include <plat/cpu.h> |
35 | 35 | ||
36 | #include "dss.h" | 36 | #include "dss.h" |
37 | 37 | ||
38 | static struct { | 38 | static struct { |
39 | struct regulator *vdds_dsi_reg; | 39 | struct regulator *vdds_dsi_reg; |
40 | struct platform_device *dsidev; | ||
40 | } dpi; | 41 | } dpi; |
41 | 42 | ||
42 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 43 | static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) |
44 | { | ||
45 | int dsi_module; | ||
46 | |||
47 | dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1; | ||
48 | |||
49 | return dsi_get_dsidev_from_id(dsi_module); | ||
50 | } | ||
51 | |||
52 | static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev) | ||
53 | { | ||
54 | if (dssdev->clocks.dispc.dispc_fclk_src == | ||
55 | OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || | ||
56 | dssdev->clocks.dispc.dispc_fclk_src == | ||
57 | OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC || | ||
58 | dssdev->clocks.dispc.channel.lcd_clk_src == | ||
59 | OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || | ||
60 | dssdev->clocks.dispc.channel.lcd_clk_src == | ||
61 | OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC) | ||
62 | return true; | ||
63 | else | ||
64 | return false; | ||
65 | } | ||
66 | |||
43 | static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, | 67 | static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, |
44 | unsigned long pck_req, unsigned long *fck, int *lck_div, | 68 | unsigned long pck_req, unsigned long *fck, int *lck_div, |
45 | int *pck_div) | 69 | int *pck_div) |
@@ -48,16 +72,16 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, | |||
48 | struct dispc_clock_info dispc_cinfo; | 72 | struct dispc_clock_info dispc_cinfo; |
49 | int r; | 73 | int r; |
50 | 74 | ||
51 | r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo, | 75 | r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, pck_req, |
52 | &dispc_cinfo); | 76 | &dsi_cinfo, &dispc_cinfo); |
53 | if (r) | 77 | if (r) |
54 | return r; | 78 | return r; |
55 | 79 | ||
56 | r = dsi_pll_set_clock_div(&dsi_cinfo); | 80 | r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo); |
57 | if (r) | 81 | if (r) |
58 | return r; | 82 | return r; |
59 | 83 | ||
60 | dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); | 84 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
61 | 85 | ||
62 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 86 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
63 | if (r) | 87 | if (r) |
@@ -69,7 +93,7 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, | |||
69 | 93 | ||
70 | return 0; | 94 | return 0; |
71 | } | 95 | } |
72 | #else | 96 | |
73 | static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, | 97 | static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, |
74 | unsigned long pck_req, unsigned long *fck, int *lck_div, | 98 | unsigned long pck_req, unsigned long *fck, int *lck_div, |
75 | int *pck_div) | 99 | int *pck_div) |
@@ -96,13 +120,12 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, | |||
96 | 120 | ||
97 | return 0; | 121 | return 0; |
98 | } | 122 | } |
99 | #endif | ||
100 | 123 | ||
101 | static int dpi_set_mode(struct omap_dss_device *dssdev) | 124 | static int dpi_set_mode(struct omap_dss_device *dssdev) |
102 | { | 125 | { |
103 | struct omap_video_timings *t = &dssdev->panel.timings; | 126 | struct omap_video_timings *t = &dssdev->panel.timings; |
104 | int lck_div, pck_div; | 127 | int lck_div = 0, pck_div = 0; |
105 | unsigned long fck; | 128 | unsigned long fck = 0; |
106 | unsigned long pck; | 129 | unsigned long pck; |
107 | bool is_tft; | 130 | bool is_tft; |
108 | int r = 0; | 131 | int r = 0; |
@@ -114,13 +137,12 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
114 | 137 | ||
115 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 138 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
116 | 139 | ||
117 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 140 | if (dpi_use_dsi_pll(dssdev)) |
118 | r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck, | 141 | r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000, |
119 | &lck_div, &pck_div); | 142 | &fck, &lck_div, &pck_div); |
120 | #else | 143 | else |
121 | r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck, | 144 | r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, |
122 | &lck_div, &pck_div); | 145 | &fck, &lck_div, &pck_div); |
123 | #endif | ||
124 | if (r) | 146 | if (r) |
125 | goto err0; | 147 | goto err0; |
126 | 148 | ||
@@ -179,12 +201,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
179 | if (r) | 201 | if (r) |
180 | goto err2; | 202 | goto err2; |
181 | 203 | ||
182 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 204 | if (dpi_use_dsi_pll(dssdev)) { |
183 | dss_clk_enable(DSS_CLK_SYSCK); | 205 | dss_clk_enable(DSS_CLK_SYSCK); |
184 | r = dsi_pll_init(dssdev, 0, 1); | 206 | r = dsi_pll_init(dpi.dsidev, 0, 1); |
185 | if (r) | 207 | if (r) |
186 | goto err3; | 208 | goto err3; |
187 | #endif | 209 | } |
210 | |||
188 | r = dpi_set_mode(dssdev); | 211 | r = dpi_set_mode(dssdev); |
189 | if (r) | 212 | if (r) |
190 | goto err4; | 213 | goto err4; |
@@ -196,11 +219,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
196 | return 0; | 219 | return 0; |
197 | 220 | ||
198 | err4: | 221 | err4: |
199 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 222 | if (dpi_use_dsi_pll(dssdev)) |
200 | dsi_pll_uninit(); | 223 | dsi_pll_uninit(dpi.dsidev, true); |
201 | err3: | 224 | err3: |
202 | dss_clk_disable(DSS_CLK_SYSCK); | 225 | if (dpi_use_dsi_pll(dssdev)) |
203 | #endif | 226 | dss_clk_disable(DSS_CLK_SYSCK); |
204 | err2: | 227 | err2: |
205 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | 228 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
206 | if (cpu_is_omap34xx()) | 229 | if (cpu_is_omap34xx()) |
@@ -216,11 +239,11 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) | |||
216 | { | 239 | { |
217 | dssdev->manager->disable(dssdev->manager); | 240 | dssdev->manager->disable(dssdev->manager); |
218 | 241 | ||
219 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 242 | if (dpi_use_dsi_pll(dssdev)) { |
220 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); | 243 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
221 | dsi_pll_uninit(); | 244 | dsi_pll_uninit(dpi.dsidev, true); |
222 | dss_clk_disable(DSS_CLK_SYSCK); | 245 | dss_clk_disable(DSS_CLK_SYSCK); |
223 | #endif | 246 | } |
224 | 247 | ||
225 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | 248 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
226 | 249 | ||
@@ -251,6 +274,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
251 | int lck_div, pck_div; | 274 | int lck_div, pck_div; |
252 | unsigned long fck; | 275 | unsigned long fck; |
253 | unsigned long pck; | 276 | unsigned long pck; |
277 | struct dispc_clock_info dispc_cinfo; | ||
254 | 278 | ||
255 | if (!dispc_lcd_timings_ok(timings)) | 279 | if (!dispc_lcd_timings_ok(timings)) |
256 | return -EINVAL; | 280 | return -EINVAL; |
@@ -260,11 +284,9 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
260 | 284 | ||
261 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 285 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
262 | 286 | ||
263 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 287 | if (dpi_use_dsi_pll(dssdev)) { |
264 | { | ||
265 | struct dsi_clock_info dsi_cinfo; | 288 | struct dsi_clock_info dsi_cinfo; |
266 | struct dispc_clock_info dispc_cinfo; | 289 | r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, |
267 | r = dsi_pll_calc_clock_div_pck(is_tft, | ||
268 | timings->pixel_clock * 1000, | 290 | timings->pixel_clock * 1000, |
269 | &dsi_cinfo, &dispc_cinfo); | 291 | &dsi_cinfo, &dispc_cinfo); |
270 | 292 | ||
@@ -272,13 +294,8 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
272 | return r; | 294 | return r; |
273 | 295 | ||
274 | fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; | 296 | fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
275 | lck_div = dispc_cinfo.lck_div; | 297 | } else { |
276 | pck_div = dispc_cinfo.pck_div; | ||
277 | } | ||
278 | #else | ||
279 | { | ||
280 | struct dss_clock_info dss_cinfo; | 298 | struct dss_clock_info dss_cinfo; |
281 | struct dispc_clock_info dispc_cinfo; | ||
282 | r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000, | 299 | r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000, |
283 | &dss_cinfo, &dispc_cinfo); | 300 | &dss_cinfo, &dispc_cinfo); |
284 | 301 | ||
@@ -286,10 +303,10 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
286 | return r; | 303 | return r; |
287 | 304 | ||
288 | fck = dss_cinfo.fck; | 305 | fck = dss_cinfo.fck; |
289 | lck_div = dispc_cinfo.lck_div; | ||
290 | pck_div = dispc_cinfo.pck_div; | ||
291 | } | 306 | } |
292 | #endif | 307 | |
308 | lck_div = dispc_cinfo.lck_div; | ||
309 | pck_div = dispc_cinfo.pck_div; | ||
293 | 310 | ||
294 | pck = fck / lck_div / pck_div / 1000; | 311 | pck = fck / lck_div / pck_div / 1000; |
295 | 312 | ||
@@ -316,6 +333,12 @@ int dpi_init_display(struct omap_dss_device *dssdev) | |||
316 | dpi.vdds_dsi_reg = vdds_dsi; | 333 | dpi.vdds_dsi_reg = vdds_dsi; |
317 | } | 334 | } |
318 | 335 | ||
336 | if (dpi_use_dsi_pll(dssdev)) { | ||
337 | enum omap_dss_clk_source dispc_fclk_src = | ||
338 | dssdev->clocks.dispc.dispc_fclk_src; | ||
339 | dpi.dsidev = dpi_get_dsidev(dispc_fclk_src); | ||
340 | } | ||
341 | |||
319 | return 0; | 342 | return 0; |
320 | } | 343 | } |
321 | 344 | ||
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 0a7f1a47f8e3..345757cfcbee 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -33,8 +33,11 @@ | |||
33 | #include <linux/regulator/consumer.h> | 33 | #include <linux/regulator/consumer.h> |
34 | #include <linux/wait.h> | 34 | #include <linux/wait.h> |
35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
36 | #include <linux/sched.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/debugfs.h> | ||
36 | 39 | ||
37 | #include <plat/display.h> | 40 | #include <video/omapdss.h> |
38 | #include <plat/clock.h> | 41 | #include <plat/clock.h> |
39 | 42 | ||
40 | #include "dss.h" | 43 | #include "dss.h" |
@@ -56,6 +59,7 @@ struct dsi_reg { u16 idx; }; | |||
56 | #define DSI_IRQSTATUS DSI_REG(0x0018) | 59 | #define DSI_IRQSTATUS DSI_REG(0x0018) |
57 | #define DSI_IRQENABLE DSI_REG(0x001C) | 60 | #define DSI_IRQENABLE DSI_REG(0x001C) |
58 | #define DSI_CTRL DSI_REG(0x0040) | 61 | #define DSI_CTRL DSI_REG(0x0040) |
62 | #define DSI_GNQ DSI_REG(0x0044) | ||
59 | #define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) | 63 | #define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) |
60 | #define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) | 64 | #define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) |
61 | #define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) | 65 | #define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) |
@@ -90,6 +94,7 @@ struct dsi_reg { u16 idx; }; | |||
90 | #define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) | 94 | #define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) |
91 | #define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) | 95 | #define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) |
92 | #define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014) | 96 | #define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014) |
97 | #define DSI_DSIPHY_CFG10 DSI_REG(0x200 + 0x0028) | ||
93 | 98 | ||
94 | /* DSI_PLL_CTRL_SCP */ | 99 | /* DSI_PLL_CTRL_SCP */ |
95 | 100 | ||
@@ -99,11 +104,11 @@ struct dsi_reg { u16 idx; }; | |||
99 | #define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C) | 104 | #define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C) |
100 | #define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010) | 105 | #define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010) |
101 | 106 | ||
102 | #define REG_GET(idx, start, end) \ | 107 | #define REG_GET(dsidev, idx, start, end) \ |
103 | FLD_GET(dsi_read_reg(idx), start, end) | 108 | FLD_GET(dsi_read_reg(dsidev, idx), start, end) |
104 | 109 | ||
105 | #define REG_FLD_MOD(idx, val, start, end) \ | 110 | #define REG_FLD_MOD(dsidev, idx, val, start, end) \ |
106 | dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end)) | 111 | dsi_write_reg(dsidev, idx, FLD_MOD(dsi_read_reg(dsidev, idx), val, start, end)) |
107 | 112 | ||
108 | /* Global interrupts */ | 113 | /* Global interrupts */ |
109 | #define DSI_IRQ_VC0 (1 << 0) | 114 | #define DSI_IRQ_VC0 (1 << 0) |
@@ -147,31 +152,50 @@ struct dsi_reg { u16 idx; }; | |||
147 | #define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0) | 152 | #define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0) |
148 | #define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1) | 153 | #define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1) |
149 | #define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2) | 154 | #define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2) |
155 | #define DSI_CIO_IRQ_ERRSYNCESC4 (1 << 3) | ||
156 | #define DSI_CIO_IRQ_ERRSYNCESC5 (1 << 4) | ||
150 | #define DSI_CIO_IRQ_ERRESC1 (1 << 5) | 157 | #define DSI_CIO_IRQ_ERRESC1 (1 << 5) |
151 | #define DSI_CIO_IRQ_ERRESC2 (1 << 6) | 158 | #define DSI_CIO_IRQ_ERRESC2 (1 << 6) |
152 | #define DSI_CIO_IRQ_ERRESC3 (1 << 7) | 159 | #define DSI_CIO_IRQ_ERRESC3 (1 << 7) |
160 | #define DSI_CIO_IRQ_ERRESC4 (1 << 8) | ||
161 | #define DSI_CIO_IRQ_ERRESC5 (1 << 9) | ||
153 | #define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10) | 162 | #define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10) |
154 | #define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11) | 163 | #define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11) |
155 | #define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12) | 164 | #define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12) |
165 | #define DSI_CIO_IRQ_ERRCONTROL4 (1 << 13) | ||
166 | #define DSI_CIO_IRQ_ERRCONTROL5 (1 << 14) | ||
156 | #define DSI_CIO_IRQ_STATEULPS1 (1 << 15) | 167 | #define DSI_CIO_IRQ_STATEULPS1 (1 << 15) |
157 | #define DSI_CIO_IRQ_STATEULPS2 (1 << 16) | 168 | #define DSI_CIO_IRQ_STATEULPS2 (1 << 16) |
158 | #define DSI_CIO_IRQ_STATEULPS3 (1 << 17) | 169 | #define DSI_CIO_IRQ_STATEULPS3 (1 << 17) |
170 | #define DSI_CIO_IRQ_STATEULPS4 (1 << 18) | ||
171 | #define DSI_CIO_IRQ_STATEULPS5 (1 << 19) | ||
159 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20) | 172 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20) |
160 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21) | 173 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21) |
161 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22) | 174 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22) |
162 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23) | 175 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23) |
163 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24) | 176 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24) |
164 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) | 177 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) |
178 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_4 (1 << 26) | ||
179 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_4 (1 << 27) | ||
180 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_5 (1 << 28) | ||
181 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_5 (1 << 29) | ||
165 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) | 182 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) |
166 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) | 183 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) |
167 | #define DSI_CIO_IRQ_ERROR_MASK \ | 184 | #define DSI_CIO_IRQ_ERROR_MASK \ |
168 | (DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \ | 185 | (DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \ |
169 | DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \ | 186 | DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRSYNCESC4 | \ |
170 | DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRCONTROL1 | \ | 187 | DSI_CIO_IRQ_ERRSYNCESC5 | \ |
171 | DSI_CIO_IRQ_ERRCONTROL2 | DSI_CIO_IRQ_ERRCONTROL3 | \ | 188 | DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \ |
189 | DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRESC4 | \ | ||
190 | DSI_CIO_IRQ_ERRESC5 | \ | ||
191 | DSI_CIO_IRQ_ERRCONTROL1 | DSI_CIO_IRQ_ERRCONTROL2 | \ | ||
192 | DSI_CIO_IRQ_ERRCONTROL3 | DSI_CIO_IRQ_ERRCONTROL4 | \ | ||
193 | DSI_CIO_IRQ_ERRCONTROL5 | \ | ||
172 | DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \ | 194 | DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \ |
173 | DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \ | 195 | DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \ |
174 | DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3) | 196 | DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3 | \ |
197 | DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \ | ||
198 | DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5) | ||
175 | 199 | ||
176 | #define DSI_DT_DCS_SHORT_WRITE_0 0x05 | 200 | #define DSI_DT_DCS_SHORT_WRITE_0 0x05 |
177 | #define DSI_DT_DCS_SHORT_WRITE_1 0x15 | 201 | #define DSI_DT_DCS_SHORT_WRITE_1 0x15 |
@@ -208,6 +232,19 @@ enum dsi_vc_mode { | |||
208 | DSI_VC_MODE_VP, | 232 | DSI_VC_MODE_VP, |
209 | }; | 233 | }; |
210 | 234 | ||
235 | enum dsi_lane { | ||
236 | DSI_CLK_P = 1 << 0, | ||
237 | DSI_CLK_N = 1 << 1, | ||
238 | DSI_DATA1_P = 1 << 2, | ||
239 | DSI_DATA1_N = 1 << 3, | ||
240 | DSI_DATA2_P = 1 << 4, | ||
241 | DSI_DATA2_N = 1 << 5, | ||
242 | DSI_DATA3_P = 1 << 6, | ||
243 | DSI_DATA3_N = 1 << 7, | ||
244 | DSI_DATA4_P = 1 << 8, | ||
245 | DSI_DATA4_N = 1 << 9, | ||
246 | }; | ||
247 | |||
211 | struct dsi_update_region { | 248 | struct dsi_update_region { |
212 | u16 x, y, w, h; | 249 | u16 x, y, w, h; |
213 | struct omap_dss_device *device; | 250 | struct omap_dss_device *device; |
@@ -227,14 +264,16 @@ struct dsi_isr_tables { | |||
227 | struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; | 264 | struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; |
228 | }; | 265 | }; |
229 | 266 | ||
230 | static struct | 267 | struct dsi_data { |
231 | { | ||
232 | struct platform_device *pdev; | 268 | struct platform_device *pdev; |
233 | void __iomem *base; | 269 | void __iomem *base; |
234 | int irq; | 270 | int irq; |
235 | 271 | ||
272 | void (*dsi_mux_pads)(bool enable); | ||
273 | |||
236 | struct dsi_clock_info current_cinfo; | 274 | struct dsi_clock_info current_cinfo; |
237 | 275 | ||
276 | bool vdds_dsi_enabled; | ||
238 | struct regulator *vdds_dsi_reg; | 277 | struct regulator *vdds_dsi_reg; |
239 | 278 | ||
240 | struct { | 279 | struct { |
@@ -258,8 +297,7 @@ static struct | |||
258 | struct dsi_update_region update_region; | 297 | struct dsi_update_region update_region; |
259 | 298 | ||
260 | bool te_enabled; | 299 | bool te_enabled; |
261 | 300 | bool ulps_enabled; | |
262 | struct workqueue_struct *workqueue; | ||
263 | 301 | ||
264 | void (*framedone_callback)(int, void *); | 302 | void (*framedone_callback)(int, void *); |
265 | void *framedone_data; | 303 | void *framedone_data; |
@@ -292,21 +330,63 @@ static struct | |||
292 | unsigned long regm_dispc_max, regm_dsi_max; | 330 | unsigned long regm_dispc_max, regm_dsi_max; |
293 | unsigned long fint_min, fint_max; | 331 | unsigned long fint_min, fint_max; |
294 | unsigned long lpdiv_max; | 332 | unsigned long lpdiv_max; |
295 | } dsi; | 333 | |
334 | int num_data_lanes; | ||
335 | |||
336 | unsigned scp_clk_refcount; | ||
337 | }; | ||
338 | |||
339 | struct dsi_packet_sent_handler_data { | ||
340 | struct platform_device *dsidev; | ||
341 | struct completion *completion; | ||
342 | }; | ||
343 | |||
344 | static struct platform_device *dsi_pdev_map[MAX_NUM_DSI]; | ||
296 | 345 | ||
297 | #ifdef DEBUG | 346 | #ifdef DEBUG |
298 | static unsigned int dsi_perf; | 347 | static unsigned int dsi_perf; |
299 | module_param_named(dsi_perf, dsi_perf, bool, 0644); | 348 | module_param_named(dsi_perf, dsi_perf, bool, 0644); |
300 | #endif | 349 | #endif |
301 | 350 | ||
302 | static inline void dsi_write_reg(const struct dsi_reg idx, u32 val) | 351 | static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dsidev) |
303 | { | 352 | { |
304 | __raw_writel(val, dsi.base + idx.idx); | 353 | return dev_get_drvdata(&dsidev->dev); |
305 | } | 354 | } |
306 | 355 | ||
307 | static inline u32 dsi_read_reg(const struct dsi_reg idx) | 356 | static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev) |
308 | { | 357 | { |
309 | return __raw_readl(dsi.base + idx.idx); | 358 | return dsi_pdev_map[dssdev->phy.dsi.module]; |
359 | } | ||
360 | |||
361 | struct platform_device *dsi_get_dsidev_from_id(int module) | ||
362 | { | ||
363 | return dsi_pdev_map[module]; | ||
364 | } | ||
365 | |||
366 | static int dsi_get_dsidev_id(struct platform_device *dsidev) | ||
367 | { | ||
368 | /* TEMP: Pass 0 as the dsi module index till the time the dsi platform | ||
369 | * device names aren't changed to the form "omapdss_dsi.0", | ||
370 | * "omapdss_dsi.1" and so on */ | ||
371 | BUG_ON(dsidev->id != -1); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static inline void dsi_write_reg(struct platform_device *dsidev, | ||
377 | const struct dsi_reg idx, u32 val) | ||
378 | { | ||
379 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
380 | |||
381 | __raw_writel(val, dsi->base + idx.idx); | ||
382 | } | ||
383 | |||
384 | static inline u32 dsi_read_reg(struct platform_device *dsidev, | ||
385 | const struct dsi_reg idx) | ||
386 | { | ||
387 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
388 | |||
389 | return __raw_readl(dsi->base + idx.idx); | ||
310 | } | 390 | } |
311 | 391 | ||
312 | 392 | ||
@@ -318,21 +398,29 @@ void dsi_restore_context(void) | |||
318 | { | 398 | { |
319 | } | 399 | } |
320 | 400 | ||
321 | void dsi_bus_lock(void) | 401 | void dsi_bus_lock(struct omap_dss_device *dssdev) |
322 | { | 402 | { |
323 | down(&dsi.bus_lock); | 403 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
404 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
405 | |||
406 | down(&dsi->bus_lock); | ||
324 | } | 407 | } |
325 | EXPORT_SYMBOL(dsi_bus_lock); | 408 | EXPORT_SYMBOL(dsi_bus_lock); |
326 | 409 | ||
327 | void dsi_bus_unlock(void) | 410 | void dsi_bus_unlock(struct omap_dss_device *dssdev) |
328 | { | 411 | { |
329 | up(&dsi.bus_lock); | 412 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
413 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
414 | |||
415 | up(&dsi->bus_lock); | ||
330 | } | 416 | } |
331 | EXPORT_SYMBOL(dsi_bus_unlock); | 417 | EXPORT_SYMBOL(dsi_bus_unlock); |
332 | 418 | ||
333 | static bool dsi_bus_is_locked(void) | 419 | static bool dsi_bus_is_locked(struct platform_device *dsidev) |
334 | { | 420 | { |
335 | return dsi.bus_lock.count == 0; | 421 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
422 | |||
423 | return dsi->bus_lock.count == 0; | ||
336 | } | 424 | } |
337 | 425 | ||
338 | static void dsi_completion_handler(void *data, u32 mask) | 426 | static void dsi_completion_handler(void *data, u32 mask) |
@@ -340,12 +428,12 @@ static void dsi_completion_handler(void *data, u32 mask) | |||
340 | complete((struct completion *)data); | 428 | complete((struct completion *)data); |
341 | } | 429 | } |
342 | 430 | ||
343 | static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, | 431 | static inline int wait_for_bit_change(struct platform_device *dsidev, |
344 | int value) | 432 | const struct dsi_reg idx, int bitnum, int value) |
345 | { | 433 | { |
346 | int t = 100000; | 434 | int t = 100000; |
347 | 435 | ||
348 | while (REG_GET(idx, bitnum, bitnum) != value) { | 436 | while (REG_GET(dsidev, idx, bitnum, bitnum) != value) { |
349 | if (--t == 0) | 437 | if (--t == 0) |
350 | return !value; | 438 | return !value; |
351 | } | 439 | } |
@@ -354,18 +442,21 @@ static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, | |||
354 | } | 442 | } |
355 | 443 | ||
356 | #ifdef DEBUG | 444 | #ifdef DEBUG |
357 | static void dsi_perf_mark_setup(void) | 445 | static void dsi_perf_mark_setup(struct platform_device *dsidev) |
358 | { | 446 | { |
359 | dsi.perf_setup_time = ktime_get(); | 447 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
448 | dsi->perf_setup_time = ktime_get(); | ||
360 | } | 449 | } |
361 | 450 | ||
362 | static void dsi_perf_mark_start(void) | 451 | static void dsi_perf_mark_start(struct platform_device *dsidev) |
363 | { | 452 | { |
364 | dsi.perf_start_time = ktime_get(); | 453 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
454 | dsi->perf_start_time = ktime_get(); | ||
365 | } | 455 | } |
366 | 456 | ||
367 | static void dsi_perf_show(const char *name) | 457 | static void dsi_perf_show(struct platform_device *dsidev, const char *name) |
368 | { | 458 | { |
459 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
369 | ktime_t t, setup_time, trans_time; | 460 | ktime_t t, setup_time, trans_time; |
370 | u32 total_bytes; | 461 | u32 total_bytes; |
371 | u32 setup_us, trans_us, total_us; | 462 | u32 setup_us, trans_us, total_us; |
@@ -375,21 +466,21 @@ static void dsi_perf_show(const char *name) | |||
375 | 466 | ||
376 | t = ktime_get(); | 467 | t = ktime_get(); |
377 | 468 | ||
378 | setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time); | 469 | setup_time = ktime_sub(dsi->perf_start_time, dsi->perf_setup_time); |
379 | setup_us = (u32)ktime_to_us(setup_time); | 470 | setup_us = (u32)ktime_to_us(setup_time); |
380 | if (setup_us == 0) | 471 | if (setup_us == 0) |
381 | setup_us = 1; | 472 | setup_us = 1; |
382 | 473 | ||
383 | trans_time = ktime_sub(t, dsi.perf_start_time); | 474 | trans_time = ktime_sub(t, dsi->perf_start_time); |
384 | trans_us = (u32)ktime_to_us(trans_time); | 475 | trans_us = (u32)ktime_to_us(trans_time); |
385 | if (trans_us == 0) | 476 | if (trans_us == 0) |
386 | trans_us = 1; | 477 | trans_us = 1; |
387 | 478 | ||
388 | total_us = setup_us + trans_us; | 479 | total_us = setup_us + trans_us; |
389 | 480 | ||
390 | total_bytes = dsi.update_region.w * | 481 | total_bytes = dsi->update_region.w * |
391 | dsi.update_region.h * | 482 | dsi->update_region.h * |
392 | dsi.update_region.device->ctrl.pixel_size / 8; | 483 | dsi->update_region.device->ctrl.pixel_size / 8; |
393 | 484 | ||
394 | printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " | 485 | printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " |
395 | "%u bytes, %u kbytes/sec\n", | 486 | "%u bytes, %u kbytes/sec\n", |
@@ -402,9 +493,9 @@ static void dsi_perf_show(const char *name) | |||
402 | total_bytes * 1000 / total_us); | 493 | total_bytes * 1000 / total_us); |
403 | } | 494 | } |
404 | #else | 495 | #else |
405 | #define dsi_perf_mark_setup() | 496 | #define dsi_perf_mark_setup(x) |
406 | #define dsi_perf_mark_start() | 497 | #define dsi_perf_mark_start(x) |
407 | #define dsi_perf_show(x) | 498 | #define dsi_perf_show(x, y) |
408 | #endif | 499 | #endif |
409 | 500 | ||
410 | static void print_irq_status(u32 status) | 501 | static void print_irq_status(u32 status) |
@@ -510,38 +601,42 @@ static void print_irq_status_cio(u32 status) | |||
510 | } | 601 | } |
511 | 602 | ||
512 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 603 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
513 | static void dsi_collect_irq_stats(u32 irqstatus, u32 *vcstatus, u32 ciostatus) | 604 | static void dsi_collect_irq_stats(struct platform_device *dsidev, u32 irqstatus, |
605 | u32 *vcstatus, u32 ciostatus) | ||
514 | { | 606 | { |
607 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
515 | int i; | 608 | int i; |
516 | 609 | ||
517 | spin_lock(&dsi.irq_stats_lock); | 610 | spin_lock(&dsi->irq_stats_lock); |
518 | 611 | ||
519 | dsi.irq_stats.irq_count++; | 612 | dsi->irq_stats.irq_count++; |
520 | dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); | 613 | dss_collect_irq_stats(irqstatus, dsi->irq_stats.dsi_irqs); |
521 | 614 | ||
522 | for (i = 0; i < 4; ++i) | 615 | for (i = 0; i < 4; ++i) |
523 | dss_collect_irq_stats(vcstatus[i], dsi.irq_stats.vc_irqs[i]); | 616 | dss_collect_irq_stats(vcstatus[i], dsi->irq_stats.vc_irqs[i]); |
524 | 617 | ||
525 | dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); | 618 | dss_collect_irq_stats(ciostatus, dsi->irq_stats.cio_irqs); |
526 | 619 | ||
527 | spin_unlock(&dsi.irq_stats_lock); | 620 | spin_unlock(&dsi->irq_stats_lock); |
528 | } | 621 | } |
529 | #else | 622 | #else |
530 | #define dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus) | 623 | #define dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus) |
531 | #endif | 624 | #endif |
532 | 625 | ||
533 | static int debug_irq; | 626 | static int debug_irq; |
534 | 627 | ||
535 | static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus) | 628 | static void dsi_handle_irq_errors(struct platform_device *dsidev, u32 irqstatus, |
629 | u32 *vcstatus, u32 ciostatus) | ||
536 | { | 630 | { |
631 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
537 | int i; | 632 | int i; |
538 | 633 | ||
539 | if (irqstatus & DSI_IRQ_ERROR_MASK) { | 634 | if (irqstatus & DSI_IRQ_ERROR_MASK) { |
540 | DSSERR("DSI error, irqstatus %x\n", irqstatus); | 635 | DSSERR("DSI error, irqstatus %x\n", irqstatus); |
541 | print_irq_status(irqstatus); | 636 | print_irq_status(irqstatus); |
542 | spin_lock(&dsi.errors_lock); | 637 | spin_lock(&dsi->errors_lock); |
543 | dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK; | 638 | dsi->errors |= irqstatus & DSI_IRQ_ERROR_MASK; |
544 | spin_unlock(&dsi.errors_lock); | 639 | spin_unlock(&dsi->errors_lock); |
545 | } else if (debug_irq) { | 640 | } else if (debug_irq) { |
546 | print_irq_status(irqstatus); | 641 | print_irq_status(irqstatus); |
547 | } | 642 | } |
@@ -602,22 +697,27 @@ static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables, | |||
602 | 697 | ||
603 | static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) | 698 | static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) |
604 | { | 699 | { |
700 | struct platform_device *dsidev; | ||
701 | struct dsi_data *dsi; | ||
605 | u32 irqstatus, vcstatus[4], ciostatus; | 702 | u32 irqstatus, vcstatus[4], ciostatus; |
606 | int i; | 703 | int i; |
607 | 704 | ||
608 | spin_lock(&dsi.irq_lock); | 705 | dsidev = (struct platform_device *) arg; |
706 | dsi = dsi_get_dsidrv_data(dsidev); | ||
707 | |||
708 | spin_lock(&dsi->irq_lock); | ||
609 | 709 | ||
610 | irqstatus = dsi_read_reg(DSI_IRQSTATUS); | 710 | irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS); |
611 | 711 | ||
612 | /* IRQ is not for us */ | 712 | /* IRQ is not for us */ |
613 | if (!irqstatus) { | 713 | if (!irqstatus) { |
614 | spin_unlock(&dsi.irq_lock); | 714 | spin_unlock(&dsi->irq_lock); |
615 | return IRQ_NONE; | 715 | return IRQ_NONE; |
616 | } | 716 | } |
617 | 717 | ||
618 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | 718 | dsi_write_reg(dsidev, DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); |
619 | /* flush posted write */ | 719 | /* flush posted write */ |
620 | dsi_read_reg(DSI_IRQSTATUS); | 720 | dsi_read_reg(dsidev, DSI_IRQSTATUS); |
621 | 721 | ||
622 | for (i = 0; i < 4; ++i) { | 722 | for (i = 0; i < 4; ++i) { |
623 | if ((irqstatus & (1 << i)) == 0) { | 723 | if ((irqstatus & (1 << i)) == 0) { |
@@ -625,45 +725,47 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) | |||
625 | continue; | 725 | continue; |
626 | } | 726 | } |
627 | 727 | ||
628 | vcstatus[i] = dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 728 | vcstatus[i] = dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i)); |
629 | 729 | ||
630 | dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus[i]); | 730 | dsi_write_reg(dsidev, DSI_VC_IRQSTATUS(i), vcstatus[i]); |
631 | /* flush posted write */ | 731 | /* flush posted write */ |
632 | dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 732 | dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i)); |
633 | } | 733 | } |
634 | 734 | ||
635 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { | 735 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { |
636 | ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 736 | ciostatus = dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS); |
637 | 737 | ||
638 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); | 738 | dsi_write_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS, ciostatus); |
639 | /* flush posted write */ | 739 | /* flush posted write */ |
640 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 740 | dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS); |
641 | } else { | 741 | } else { |
642 | ciostatus = 0; | 742 | ciostatus = 0; |
643 | } | 743 | } |
644 | 744 | ||
645 | #ifdef DSI_CATCH_MISSING_TE | 745 | #ifdef DSI_CATCH_MISSING_TE |
646 | if (irqstatus & DSI_IRQ_TE_TRIGGER) | 746 | if (irqstatus & DSI_IRQ_TE_TRIGGER) |
647 | del_timer(&dsi.te_timer); | 747 | del_timer(&dsi->te_timer); |
648 | #endif | 748 | #endif |
649 | 749 | ||
650 | /* make a copy and unlock, so that isrs can unregister | 750 | /* make a copy and unlock, so that isrs can unregister |
651 | * themselves */ | 751 | * themselves */ |
652 | memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables)); | 752 | memcpy(&dsi->isr_tables_copy, &dsi->isr_tables, |
753 | sizeof(dsi->isr_tables)); | ||
653 | 754 | ||
654 | spin_unlock(&dsi.irq_lock); | 755 | spin_unlock(&dsi->irq_lock); |
655 | 756 | ||
656 | dsi_handle_isrs(&dsi.isr_tables_copy, irqstatus, vcstatus, ciostatus); | 757 | dsi_handle_isrs(&dsi->isr_tables_copy, irqstatus, vcstatus, ciostatus); |
657 | 758 | ||
658 | dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus); | 759 | dsi_handle_irq_errors(dsidev, irqstatus, vcstatus, ciostatus); |
659 | 760 | ||
660 | dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus); | 761 | dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus); |
661 | 762 | ||
662 | return IRQ_HANDLED; | 763 | return IRQ_HANDLED; |
663 | } | 764 | } |
664 | 765 | ||
665 | /* dsi.irq_lock has to be locked by the caller */ | 766 | /* dsi->irq_lock has to be locked by the caller */ |
666 | static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array, | 767 | static void _omap_dsi_configure_irqs(struct platform_device *dsidev, |
768 | struct dsi_isr_data *isr_array, | ||
667 | unsigned isr_array_size, u32 default_mask, | 769 | unsigned isr_array_size, u32 default_mask, |
668 | const struct dsi_reg enable_reg, | 770 | const struct dsi_reg enable_reg, |
669 | const struct dsi_reg status_reg) | 771 | const struct dsi_reg status_reg) |
@@ -684,61 +786,67 @@ static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array, | |||
684 | mask |= isr_data->mask; | 786 | mask |= isr_data->mask; |
685 | } | 787 | } |
686 | 788 | ||
687 | old_mask = dsi_read_reg(enable_reg); | 789 | old_mask = dsi_read_reg(dsidev, enable_reg); |
688 | /* clear the irqstatus for newly enabled irqs */ | 790 | /* clear the irqstatus for newly enabled irqs */ |
689 | dsi_write_reg(status_reg, (mask ^ old_mask) & mask); | 791 | dsi_write_reg(dsidev, status_reg, (mask ^ old_mask) & mask); |
690 | dsi_write_reg(enable_reg, mask); | 792 | dsi_write_reg(dsidev, enable_reg, mask); |
691 | 793 | ||
692 | /* flush posted writes */ | 794 | /* flush posted writes */ |
693 | dsi_read_reg(enable_reg); | 795 | dsi_read_reg(dsidev, enable_reg); |
694 | dsi_read_reg(status_reg); | 796 | dsi_read_reg(dsidev, status_reg); |
695 | } | 797 | } |
696 | 798 | ||
697 | /* dsi.irq_lock has to be locked by the caller */ | 799 | /* dsi->irq_lock has to be locked by the caller */ |
698 | static void _omap_dsi_set_irqs(void) | 800 | static void _omap_dsi_set_irqs(struct platform_device *dsidev) |
699 | { | 801 | { |
802 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
700 | u32 mask = DSI_IRQ_ERROR_MASK; | 803 | u32 mask = DSI_IRQ_ERROR_MASK; |
701 | #ifdef DSI_CATCH_MISSING_TE | 804 | #ifdef DSI_CATCH_MISSING_TE |
702 | mask |= DSI_IRQ_TE_TRIGGER; | 805 | mask |= DSI_IRQ_TE_TRIGGER; |
703 | #endif | 806 | #endif |
704 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table, | 807 | _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table, |
705 | ARRAY_SIZE(dsi.isr_tables.isr_table), mask, | 808 | ARRAY_SIZE(dsi->isr_tables.isr_table), mask, |
706 | DSI_IRQENABLE, DSI_IRQSTATUS); | 809 | DSI_IRQENABLE, DSI_IRQSTATUS); |
707 | } | 810 | } |
708 | 811 | ||
709 | /* dsi.irq_lock has to be locked by the caller */ | 812 | /* dsi->irq_lock has to be locked by the caller */ |
710 | static void _omap_dsi_set_irqs_vc(int vc) | 813 | static void _omap_dsi_set_irqs_vc(struct platform_device *dsidev, int vc) |
711 | { | 814 | { |
712 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_vc[vc], | 815 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
713 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[vc]), | 816 | |
817 | _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_vc[vc], | ||
818 | ARRAY_SIZE(dsi->isr_tables.isr_table_vc[vc]), | ||
714 | DSI_VC_IRQ_ERROR_MASK, | 819 | DSI_VC_IRQ_ERROR_MASK, |
715 | DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc)); | 820 | DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc)); |
716 | } | 821 | } |
717 | 822 | ||
718 | /* dsi.irq_lock has to be locked by the caller */ | 823 | /* dsi->irq_lock has to be locked by the caller */ |
719 | static void _omap_dsi_set_irqs_cio(void) | 824 | static void _omap_dsi_set_irqs_cio(struct platform_device *dsidev) |
720 | { | 825 | { |
721 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_cio, | 826 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
722 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio), | 827 | |
828 | _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_cio, | ||
829 | ARRAY_SIZE(dsi->isr_tables.isr_table_cio), | ||
723 | DSI_CIO_IRQ_ERROR_MASK, | 830 | DSI_CIO_IRQ_ERROR_MASK, |
724 | DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS); | 831 | DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS); |
725 | } | 832 | } |
726 | 833 | ||
727 | static void _dsi_initialize_irq(void) | 834 | static void _dsi_initialize_irq(struct platform_device *dsidev) |
728 | { | 835 | { |
836 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
729 | unsigned long flags; | 837 | unsigned long flags; |
730 | int vc; | 838 | int vc; |
731 | 839 | ||
732 | spin_lock_irqsave(&dsi.irq_lock, flags); | 840 | spin_lock_irqsave(&dsi->irq_lock, flags); |
733 | 841 | ||
734 | memset(&dsi.isr_tables, 0, sizeof(dsi.isr_tables)); | 842 | memset(&dsi->isr_tables, 0, sizeof(dsi->isr_tables)); |
735 | 843 | ||
736 | _omap_dsi_set_irqs(); | 844 | _omap_dsi_set_irqs(dsidev); |
737 | for (vc = 0; vc < 4; ++vc) | 845 | for (vc = 0; vc < 4; ++vc) |
738 | _omap_dsi_set_irqs_vc(vc); | 846 | _omap_dsi_set_irqs_vc(dsidev, vc); |
739 | _omap_dsi_set_irqs_cio(); | 847 | _omap_dsi_set_irqs_cio(dsidev); |
740 | 848 | ||
741 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | 849 | spin_unlock_irqrestore(&dsi->irq_lock, flags); |
742 | } | 850 | } |
743 | 851 | ||
744 | static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask, | 852 | static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask, |
@@ -797,126 +905,137 @@ static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask, | |||
797 | return -EINVAL; | 905 | return -EINVAL; |
798 | } | 906 | } |
799 | 907 | ||
800 | static int dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask) | 908 | static int dsi_register_isr(struct platform_device *dsidev, omap_dsi_isr_t isr, |
909 | void *arg, u32 mask) | ||
801 | { | 910 | { |
911 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
802 | unsigned long flags; | 912 | unsigned long flags; |
803 | int r; | 913 | int r; |
804 | 914 | ||
805 | spin_lock_irqsave(&dsi.irq_lock, flags); | 915 | spin_lock_irqsave(&dsi->irq_lock, flags); |
806 | 916 | ||
807 | r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table, | 917 | r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table, |
808 | ARRAY_SIZE(dsi.isr_tables.isr_table)); | 918 | ARRAY_SIZE(dsi->isr_tables.isr_table)); |
809 | 919 | ||
810 | if (r == 0) | 920 | if (r == 0) |
811 | _omap_dsi_set_irqs(); | 921 | _omap_dsi_set_irqs(dsidev); |
812 | 922 | ||
813 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | 923 | spin_unlock_irqrestore(&dsi->irq_lock, flags); |
814 | 924 | ||
815 | return r; | 925 | return r; |
816 | } | 926 | } |
817 | 927 | ||
818 | static int dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask) | 928 | static int dsi_unregister_isr(struct platform_device *dsidev, |
929 | omap_dsi_isr_t isr, void *arg, u32 mask) | ||
819 | { | 930 | { |
931 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
820 | unsigned long flags; | 932 | unsigned long flags; |
821 | int r; | 933 | int r; |
822 | 934 | ||
823 | spin_lock_irqsave(&dsi.irq_lock, flags); | 935 | spin_lock_irqsave(&dsi->irq_lock, flags); |
824 | 936 | ||
825 | r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table, | 937 | r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table, |
826 | ARRAY_SIZE(dsi.isr_tables.isr_table)); | 938 | ARRAY_SIZE(dsi->isr_tables.isr_table)); |
827 | 939 | ||
828 | if (r == 0) | 940 | if (r == 0) |
829 | _omap_dsi_set_irqs(); | 941 | _omap_dsi_set_irqs(dsidev); |
830 | 942 | ||
831 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | 943 | spin_unlock_irqrestore(&dsi->irq_lock, flags); |
832 | 944 | ||
833 | return r; | 945 | return r; |
834 | } | 946 | } |
835 | 947 | ||
836 | static int dsi_register_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, | 948 | static int dsi_register_isr_vc(struct platform_device *dsidev, int channel, |
837 | u32 mask) | 949 | omap_dsi_isr_t isr, void *arg, u32 mask) |
838 | { | 950 | { |
951 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
839 | unsigned long flags; | 952 | unsigned long flags; |
840 | int r; | 953 | int r; |
841 | 954 | ||
842 | spin_lock_irqsave(&dsi.irq_lock, flags); | 955 | spin_lock_irqsave(&dsi->irq_lock, flags); |
843 | 956 | ||
844 | r = _dsi_register_isr(isr, arg, mask, | 957 | r = _dsi_register_isr(isr, arg, mask, |
845 | dsi.isr_tables.isr_table_vc[channel], | 958 | dsi->isr_tables.isr_table_vc[channel], |
846 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); | 959 | ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel])); |
847 | 960 | ||
848 | if (r == 0) | 961 | if (r == 0) |
849 | _omap_dsi_set_irqs_vc(channel); | 962 | _omap_dsi_set_irqs_vc(dsidev, channel); |
850 | 963 | ||
851 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | 964 | spin_unlock_irqrestore(&dsi->irq_lock, flags); |
852 | 965 | ||
853 | return r; | 966 | return r; |
854 | } | 967 | } |
855 | 968 | ||
856 | static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, | 969 | static int dsi_unregister_isr_vc(struct platform_device *dsidev, int channel, |
857 | u32 mask) | 970 | omap_dsi_isr_t isr, void *arg, u32 mask) |
858 | { | 971 | { |
972 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
859 | unsigned long flags; | 973 | unsigned long flags; |
860 | int r; | 974 | int r; |
861 | 975 | ||
862 | spin_lock_irqsave(&dsi.irq_lock, flags); | 976 | spin_lock_irqsave(&dsi->irq_lock, flags); |
863 | 977 | ||
864 | r = _dsi_unregister_isr(isr, arg, mask, | 978 | r = _dsi_unregister_isr(isr, arg, mask, |
865 | dsi.isr_tables.isr_table_vc[channel], | 979 | dsi->isr_tables.isr_table_vc[channel], |
866 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); | 980 | ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel])); |
867 | 981 | ||
868 | if (r == 0) | 982 | if (r == 0) |
869 | _omap_dsi_set_irqs_vc(channel); | 983 | _omap_dsi_set_irqs_vc(dsidev, channel); |
870 | 984 | ||
871 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | 985 | spin_unlock_irqrestore(&dsi->irq_lock, flags); |
872 | 986 | ||
873 | return r; | 987 | return r; |
874 | } | 988 | } |
875 | 989 | ||
876 | static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) | 990 | static int dsi_register_isr_cio(struct platform_device *dsidev, |
991 | omap_dsi_isr_t isr, void *arg, u32 mask) | ||
877 | { | 992 | { |
993 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
878 | unsigned long flags; | 994 | unsigned long flags; |
879 | int r; | 995 | int r; |
880 | 996 | ||
881 | spin_lock_irqsave(&dsi.irq_lock, flags); | 997 | spin_lock_irqsave(&dsi->irq_lock, flags); |
882 | 998 | ||
883 | r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio, | 999 | r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio, |
884 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio)); | 1000 | ARRAY_SIZE(dsi->isr_tables.isr_table_cio)); |
885 | 1001 | ||
886 | if (r == 0) | 1002 | if (r == 0) |
887 | _omap_dsi_set_irqs_cio(); | 1003 | _omap_dsi_set_irqs_cio(dsidev); |
888 | 1004 | ||
889 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | 1005 | spin_unlock_irqrestore(&dsi->irq_lock, flags); |
890 | 1006 | ||
891 | return r; | 1007 | return r; |
892 | } | 1008 | } |
893 | 1009 | ||
894 | static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) | 1010 | static int dsi_unregister_isr_cio(struct platform_device *dsidev, |
1011 | omap_dsi_isr_t isr, void *arg, u32 mask) | ||
895 | { | 1012 | { |
1013 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
896 | unsigned long flags; | 1014 | unsigned long flags; |
897 | int r; | 1015 | int r; |
898 | 1016 | ||
899 | spin_lock_irqsave(&dsi.irq_lock, flags); | 1017 | spin_lock_irqsave(&dsi->irq_lock, flags); |
900 | 1018 | ||
901 | r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio, | 1019 | r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio, |
902 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio)); | 1020 | ARRAY_SIZE(dsi->isr_tables.isr_table_cio)); |
903 | 1021 | ||
904 | if (r == 0) | 1022 | if (r == 0) |
905 | _omap_dsi_set_irqs_cio(); | 1023 | _omap_dsi_set_irqs_cio(dsidev); |
906 | 1024 | ||
907 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | 1025 | spin_unlock_irqrestore(&dsi->irq_lock, flags); |
908 | 1026 | ||
909 | return r; | 1027 | return r; |
910 | } | 1028 | } |
911 | 1029 | ||
912 | static u32 dsi_get_errors(void) | 1030 | static u32 dsi_get_errors(struct platform_device *dsidev) |
913 | { | 1031 | { |
1032 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
914 | unsigned long flags; | 1033 | unsigned long flags; |
915 | u32 e; | 1034 | u32 e; |
916 | spin_lock_irqsave(&dsi.errors_lock, flags); | 1035 | spin_lock_irqsave(&dsi->errors_lock, flags); |
917 | e = dsi.errors; | 1036 | e = dsi->errors; |
918 | dsi.errors = 0; | 1037 | dsi->errors = 0; |
919 | spin_unlock_irqrestore(&dsi.errors_lock, flags); | 1038 | spin_unlock_irqrestore(&dsi->errors_lock, flags); |
920 | return e; | 1039 | return e; |
921 | } | 1040 | } |
922 | 1041 | ||
@@ -930,23 +1049,27 @@ static inline void enable_clocks(bool enable) | |||
930 | } | 1049 | } |
931 | 1050 | ||
932 | /* source clock for DSI PLL. this could also be PCLKFREE */ | 1051 | /* source clock for DSI PLL. this could also be PCLKFREE */ |
933 | static inline void dsi_enable_pll_clock(bool enable) | 1052 | static inline void dsi_enable_pll_clock(struct platform_device *dsidev, |
1053 | bool enable) | ||
934 | { | 1054 | { |
1055 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1056 | |||
935 | if (enable) | 1057 | if (enable) |
936 | dss_clk_enable(DSS_CLK_SYSCK); | 1058 | dss_clk_enable(DSS_CLK_SYSCK); |
937 | else | 1059 | else |
938 | dss_clk_disable(DSS_CLK_SYSCK); | 1060 | dss_clk_disable(DSS_CLK_SYSCK); |
939 | 1061 | ||
940 | if (enable && dsi.pll_locked) { | 1062 | if (enable && dsi->pll_locked) { |
941 | if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) | 1063 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) |
942 | DSSERR("cannot lock PLL when enabling clocks\n"); | 1064 | DSSERR("cannot lock PLL when enabling clocks\n"); |
943 | } | 1065 | } |
944 | } | 1066 | } |
945 | 1067 | ||
946 | #ifdef DEBUG | 1068 | #ifdef DEBUG |
947 | static void _dsi_print_reset_status(void) | 1069 | static void _dsi_print_reset_status(struct platform_device *dsidev) |
948 | { | 1070 | { |
949 | u32 l; | 1071 | u32 l; |
1072 | int b0, b1, b2; | ||
950 | 1073 | ||
951 | if (!dss_debug) | 1074 | if (!dss_debug) |
952 | return; | 1075 | return; |
@@ -954,35 +1077,47 @@ static void _dsi_print_reset_status(void) | |||
954 | /* A dummy read using the SCP interface to any DSIPHY register is | 1077 | /* A dummy read using the SCP interface to any DSIPHY register is |
955 | * required after DSIPHY reset to complete the reset of the DSI complex | 1078 | * required after DSIPHY reset to complete the reset of the DSI complex |
956 | * I/O. */ | 1079 | * I/O. */ |
957 | l = dsi_read_reg(DSI_DSIPHY_CFG5); | 1080 | l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); |
958 | 1081 | ||
959 | printk(KERN_DEBUG "DSI resets: "); | 1082 | printk(KERN_DEBUG "DSI resets: "); |
960 | 1083 | ||
961 | l = dsi_read_reg(DSI_PLL_STATUS); | 1084 | l = dsi_read_reg(dsidev, DSI_PLL_STATUS); |
962 | printk("PLL (%d) ", FLD_GET(l, 0, 0)); | 1085 | printk("PLL (%d) ", FLD_GET(l, 0, 0)); |
963 | 1086 | ||
964 | l = dsi_read_reg(DSI_COMPLEXIO_CFG1); | 1087 | l = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1); |
965 | printk("CIO (%d) ", FLD_GET(l, 29, 29)); | 1088 | printk("CIO (%d) ", FLD_GET(l, 29, 29)); |
966 | 1089 | ||
967 | l = dsi_read_reg(DSI_DSIPHY_CFG5); | 1090 | if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) { |
968 | printk("PHY (%x, %d, %d, %d)\n", | 1091 | b0 = 28; |
969 | FLD_GET(l, 28, 26), | 1092 | b1 = 27; |
1093 | b2 = 26; | ||
1094 | } else { | ||
1095 | b0 = 24; | ||
1096 | b1 = 25; | ||
1097 | b2 = 26; | ||
1098 | } | ||
1099 | |||
1100 | l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); | ||
1101 | printk("PHY (%x%x%x, %d, %d, %d)\n", | ||
1102 | FLD_GET(l, b0, b0), | ||
1103 | FLD_GET(l, b1, b1), | ||
1104 | FLD_GET(l, b2, b2), | ||
970 | FLD_GET(l, 29, 29), | 1105 | FLD_GET(l, 29, 29), |
971 | FLD_GET(l, 30, 30), | 1106 | FLD_GET(l, 30, 30), |
972 | FLD_GET(l, 31, 31)); | 1107 | FLD_GET(l, 31, 31)); |
973 | } | 1108 | } |
974 | #else | 1109 | #else |
975 | #define _dsi_print_reset_status() | 1110 | #define _dsi_print_reset_status(x) |
976 | #endif | 1111 | #endif |
977 | 1112 | ||
978 | static inline int dsi_if_enable(bool enable) | 1113 | static inline int dsi_if_enable(struct platform_device *dsidev, bool enable) |
979 | { | 1114 | { |
980 | DSSDBG("dsi_if_enable(%d)\n", enable); | 1115 | DSSDBG("dsi_if_enable(%d)\n", enable); |
981 | 1116 | ||
982 | enable = enable ? 1 : 0; | 1117 | enable = enable ? 1 : 0; |
983 | REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */ | 1118 | REG_FLD_MOD(dsidev, DSI_CTRL, enable, 0, 0); /* IF_EN */ |
984 | 1119 | ||
985 | if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) { | 1120 | if (wait_for_bit_change(dsidev, DSI_CTRL, 0, enable) != enable) { |
986 | DSSERR("Failed to set dsi_if_enable to %d\n", enable); | 1121 | DSSERR("Failed to set dsi_if_enable to %d\n", enable); |
987 | return -EIO; | 1122 | return -EIO; |
988 | } | 1123 | } |
@@ -990,31 +1125,38 @@ static inline int dsi_if_enable(bool enable) | |||
990 | return 0; | 1125 | return 0; |
991 | } | 1126 | } |
992 | 1127 | ||
993 | unsigned long dsi_get_pll_hsdiv_dispc_rate(void) | 1128 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) |
994 | { | 1129 | { |
995 | return dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk; | 1130 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1131 | |||
1132 | return dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk; | ||
996 | } | 1133 | } |
997 | 1134 | ||
998 | static unsigned long dsi_get_pll_hsdiv_dsi_rate(void) | 1135 | static unsigned long dsi_get_pll_hsdiv_dsi_rate(struct platform_device *dsidev) |
999 | { | 1136 | { |
1000 | return dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk; | 1137 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1138 | |||
1139 | return dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk; | ||
1001 | } | 1140 | } |
1002 | 1141 | ||
1003 | static unsigned long dsi_get_txbyteclkhs(void) | 1142 | static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev) |
1004 | { | 1143 | { |
1005 | return dsi.current_cinfo.clkin4ddr / 16; | 1144 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1145 | |||
1146 | return dsi->current_cinfo.clkin4ddr / 16; | ||
1006 | } | 1147 | } |
1007 | 1148 | ||
1008 | static unsigned long dsi_fclk_rate(void) | 1149 | static unsigned long dsi_fclk_rate(struct platform_device *dsidev) |
1009 | { | 1150 | { |
1010 | unsigned long r; | 1151 | unsigned long r; |
1152 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
1011 | 1153 | ||
1012 | if (dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK) { | 1154 | if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { |
1013 | /* DSI FCLK source is DSS_CLK_FCK */ | 1155 | /* DSI FCLK source is DSS_CLK_FCK */ |
1014 | r = dss_clk_get_rate(DSS_CLK_FCK); | 1156 | r = dss_clk_get_rate(DSS_CLK_FCK); |
1015 | } else { | 1157 | } else { |
1016 | /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ | 1158 | /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ |
1017 | r = dsi_get_pll_hsdiv_dsi_rate(); | 1159 | r = dsi_get_pll_hsdiv_dsi_rate(dsidev); |
1018 | } | 1160 | } |
1019 | 1161 | ||
1020 | return r; | 1162 | return r; |
@@ -1022,31 +1164,50 @@ static unsigned long dsi_fclk_rate(void) | |||
1022 | 1164 | ||
1023 | static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) | 1165 | static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) |
1024 | { | 1166 | { |
1167 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
1168 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1025 | unsigned long dsi_fclk; | 1169 | unsigned long dsi_fclk; |
1026 | unsigned lp_clk_div; | 1170 | unsigned lp_clk_div; |
1027 | unsigned long lp_clk; | 1171 | unsigned long lp_clk; |
1028 | 1172 | ||
1029 | lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; | 1173 | lp_clk_div = dssdev->clocks.dsi.lp_clk_div; |
1030 | 1174 | ||
1031 | if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max) | 1175 | if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max) |
1032 | return -EINVAL; | 1176 | return -EINVAL; |
1033 | 1177 | ||
1034 | dsi_fclk = dsi_fclk_rate(); | 1178 | dsi_fclk = dsi_fclk_rate(dsidev); |
1035 | 1179 | ||
1036 | lp_clk = dsi_fclk / 2 / lp_clk_div; | 1180 | lp_clk = dsi_fclk / 2 / lp_clk_div; |
1037 | 1181 | ||
1038 | DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk); | 1182 | DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk); |
1039 | dsi.current_cinfo.lp_clk = lp_clk; | 1183 | dsi->current_cinfo.lp_clk = lp_clk; |
1040 | dsi.current_cinfo.lp_clk_div = lp_clk_div; | 1184 | dsi->current_cinfo.lp_clk_div = lp_clk_div; |
1041 | 1185 | ||
1042 | REG_FLD_MOD(DSI_CLK_CTRL, lp_clk_div, 12, 0); /* LP_CLK_DIVISOR */ | 1186 | /* LP_CLK_DIVISOR */ |
1187 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, lp_clk_div, 12, 0); | ||
1043 | 1188 | ||
1044 | REG_FLD_MOD(DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0, | 1189 | /* LP_RX_SYNCHRO_ENABLE */ |
1045 | 21, 21); /* LP_RX_SYNCHRO_ENABLE */ | 1190 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0, 21, 21); |
1046 | 1191 | ||
1047 | return 0; | 1192 | return 0; |
1048 | } | 1193 | } |
1049 | 1194 | ||
1195 | static void dsi_enable_scp_clk(struct platform_device *dsidev) | ||
1196 | { | ||
1197 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1198 | |||
1199 | if (dsi->scp_clk_refcount++ == 0) | ||
1200 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 14, 14); /* CIO_CLK_ICG */ | ||
1201 | } | ||
1202 | |||
1203 | static void dsi_disable_scp_clk(struct platform_device *dsidev) | ||
1204 | { | ||
1205 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1206 | |||
1207 | WARN_ON(dsi->scp_clk_refcount == 0); | ||
1208 | if (--dsi->scp_clk_refcount == 0) | ||
1209 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 14, 14); /* CIO_CLK_ICG */ | ||
1210 | } | ||
1050 | 1211 | ||
1051 | enum dsi_pll_power_state { | 1212 | enum dsi_pll_power_state { |
1052 | DSI_PLL_POWER_OFF = 0x0, | 1213 | DSI_PLL_POWER_OFF = 0x0, |
@@ -1055,14 +1216,21 @@ enum dsi_pll_power_state { | |||
1055 | DSI_PLL_POWER_ON_DIV = 0x3, | 1216 | DSI_PLL_POWER_ON_DIV = 0x3, |
1056 | }; | 1217 | }; |
1057 | 1218 | ||
1058 | static int dsi_pll_power(enum dsi_pll_power_state state) | 1219 | static int dsi_pll_power(struct platform_device *dsidev, |
1220 | enum dsi_pll_power_state state) | ||
1059 | { | 1221 | { |
1060 | int t = 0; | 1222 | int t = 0; |
1061 | 1223 | ||
1062 | REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */ | 1224 | /* DSI-PLL power command 0x3 is not working */ |
1225 | if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) && | ||
1226 | state == DSI_PLL_POWER_ON_DIV) | ||
1227 | state = DSI_PLL_POWER_ON_ALL; | ||
1228 | |||
1229 | /* PLL_PWR_CMD */ | ||
1230 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, state, 31, 30); | ||
1063 | 1231 | ||
1064 | /* PLL_PWR_STATUS */ | 1232 | /* PLL_PWR_STATUS */ |
1065 | while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) { | 1233 | while (FLD_GET(dsi_read_reg(dsidev, DSI_CLK_CTRL), 29, 28) != state) { |
1066 | if (++t > 1000) { | 1234 | if (++t > 1000) { |
1067 | DSSERR("Failed to set DSI PLL power mode to %d\n", | 1235 | DSSERR("Failed to set DSI PLL power mode to %d\n", |
1068 | state); | 1236 | state); |
@@ -1078,16 +1246,19 @@ static int dsi_pll_power(enum dsi_pll_power_state state) | |||
1078 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | 1246 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, |
1079 | struct dsi_clock_info *cinfo) | 1247 | struct dsi_clock_info *cinfo) |
1080 | { | 1248 | { |
1081 | if (cinfo->regn == 0 || cinfo->regn > dsi.regn_max) | 1249 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
1250 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1251 | |||
1252 | if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) | ||
1082 | return -EINVAL; | 1253 | return -EINVAL; |
1083 | 1254 | ||
1084 | if (cinfo->regm == 0 || cinfo->regm > dsi.regm_max) | 1255 | if (cinfo->regm == 0 || cinfo->regm > dsi->regm_max) |
1085 | return -EINVAL; | 1256 | return -EINVAL; |
1086 | 1257 | ||
1087 | if (cinfo->regm_dispc > dsi.regm_dispc_max) | 1258 | if (cinfo->regm_dispc > dsi->regm_dispc_max) |
1088 | return -EINVAL; | 1259 | return -EINVAL; |
1089 | 1260 | ||
1090 | if (cinfo->regm_dsi > dsi.regm_dsi_max) | 1261 | if (cinfo->regm_dsi > dsi->regm_dsi_max) |
1091 | return -EINVAL; | 1262 | return -EINVAL; |
1092 | 1263 | ||
1093 | if (cinfo->use_sys_clk) { | 1264 | if (cinfo->use_sys_clk) { |
@@ -1106,7 +1277,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
1106 | 1277 | ||
1107 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); | 1278 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); |
1108 | 1279 | ||
1109 | if (cinfo->fint > dsi.fint_max || cinfo->fint < dsi.fint_min) | 1280 | if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min) |
1110 | return -EINVAL; | 1281 | return -EINVAL; |
1111 | 1282 | ||
1112 | cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; | 1283 | cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; |
@@ -1129,10 +1300,11 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
1129 | return 0; | 1300 | return 0; |
1130 | } | 1301 | } |
1131 | 1302 | ||
1132 | int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, | 1303 | int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft, |
1133 | struct dsi_clock_info *dsi_cinfo, | 1304 | unsigned long req_pck, struct dsi_clock_info *dsi_cinfo, |
1134 | struct dispc_clock_info *dispc_cinfo) | 1305 | struct dispc_clock_info *dispc_cinfo) |
1135 | { | 1306 | { |
1307 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1136 | struct dsi_clock_info cur, best; | 1308 | struct dsi_clock_info cur, best; |
1137 | struct dispc_clock_info best_dispc; | 1309 | struct dispc_clock_info best_dispc; |
1138 | int min_fck_per_pck; | 1310 | int min_fck_per_pck; |
@@ -1143,10 +1315,10 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, | |||
1143 | 1315 | ||
1144 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); | 1316 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); |
1145 | 1317 | ||
1146 | if (req_pck == dsi.cache_req_pck && | 1318 | if (req_pck == dsi->cache_req_pck && |
1147 | dsi.cache_cinfo.clkin == dss_sys_clk) { | 1319 | dsi->cache_cinfo.clkin == dss_sys_clk) { |
1148 | DSSDBG("DSI clock info found from cache\n"); | 1320 | DSSDBG("DSI clock info found from cache\n"); |
1149 | *dsi_cinfo = dsi.cache_cinfo; | 1321 | *dsi_cinfo = dsi->cache_cinfo; |
1150 | dispc_find_clk_divs(is_tft, req_pck, | 1322 | dispc_find_clk_divs(is_tft, req_pck, |
1151 | dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo); | 1323 | dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo); |
1152 | return 0; | 1324 | return 0; |
@@ -1176,17 +1348,17 @@ retry: | |||
1176 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ | 1348 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ |
1177 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ | 1349 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ |
1178 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ | 1350 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ |
1179 | for (cur.regn = 1; cur.regn < dsi.regn_max; ++cur.regn) { | 1351 | for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { |
1180 | if (cur.highfreq == 0) | 1352 | if (cur.highfreq == 0) |
1181 | cur.fint = cur.clkin / cur.regn; | 1353 | cur.fint = cur.clkin / cur.regn; |
1182 | else | 1354 | else |
1183 | cur.fint = cur.clkin / (2 * cur.regn); | 1355 | cur.fint = cur.clkin / (2 * cur.regn); |
1184 | 1356 | ||
1185 | if (cur.fint > dsi.fint_max || cur.fint < dsi.fint_min) | 1357 | if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) |
1186 | continue; | 1358 | continue; |
1187 | 1359 | ||
1188 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ | 1360 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ |
1189 | for (cur.regm = 1; cur.regm < dsi.regm_max; ++cur.regm) { | 1361 | for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { |
1190 | unsigned long a, b; | 1362 | unsigned long a, b; |
1191 | 1363 | ||
1192 | a = 2 * cur.regm * (cur.clkin/1000); | 1364 | a = 2 * cur.regm * (cur.clkin/1000); |
@@ -1198,8 +1370,8 @@ retry: | |||
1198 | 1370 | ||
1199 | /* dsi_pll_hsdiv_dispc_clk(MHz) = | 1371 | /* dsi_pll_hsdiv_dispc_clk(MHz) = |
1200 | * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ | 1372 | * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ |
1201 | for (cur.regm_dispc = 1; cur.regm_dispc < dsi.regm_dispc_max; | 1373 | for (cur.regm_dispc = 1; cur.regm_dispc < |
1202 | ++cur.regm_dispc) { | 1374 | dsi->regm_dispc_max; ++cur.regm_dispc) { |
1203 | struct dispc_clock_info cur_dispc; | 1375 | struct dispc_clock_info cur_dispc; |
1204 | cur.dsi_pll_hsdiv_dispc_clk = | 1376 | cur.dsi_pll_hsdiv_dispc_clk = |
1205 | cur.clkin4ddr / cur.regm_dispc; | 1377 | cur.clkin4ddr / cur.regm_dispc; |
@@ -1259,34 +1431,39 @@ found: | |||
1259 | if (dispc_cinfo) | 1431 | if (dispc_cinfo) |
1260 | *dispc_cinfo = best_dispc; | 1432 | *dispc_cinfo = best_dispc; |
1261 | 1433 | ||
1262 | dsi.cache_req_pck = req_pck; | 1434 | dsi->cache_req_pck = req_pck; |
1263 | dsi.cache_clk_freq = 0; | 1435 | dsi->cache_clk_freq = 0; |
1264 | dsi.cache_cinfo = best; | 1436 | dsi->cache_cinfo = best; |
1265 | 1437 | ||
1266 | return 0; | 1438 | return 0; |
1267 | } | 1439 | } |
1268 | 1440 | ||
1269 | int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | 1441 | int dsi_pll_set_clock_div(struct platform_device *dsidev, |
1442 | struct dsi_clock_info *cinfo) | ||
1270 | { | 1443 | { |
1444 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1271 | int r = 0; | 1445 | int r = 0; |
1272 | u32 l; | 1446 | u32 l; |
1273 | int f; | 1447 | int f = 0; |
1274 | u8 regn_start, regn_end, regm_start, regm_end; | 1448 | u8 regn_start, regn_end, regm_start, regm_end; |
1275 | u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; | 1449 | u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; |
1276 | 1450 | ||
1277 | DSSDBGF(); | 1451 | DSSDBGF(); |
1278 | 1452 | ||
1279 | dsi.current_cinfo.fint = cinfo->fint; | 1453 | dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk; |
1280 | dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; | 1454 | dsi->current_cinfo.highfreq = cinfo->highfreq; |
1281 | dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk = | 1455 | |
1456 | dsi->current_cinfo.fint = cinfo->fint; | ||
1457 | dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr; | ||
1458 | dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = | ||
1282 | cinfo->dsi_pll_hsdiv_dispc_clk; | 1459 | cinfo->dsi_pll_hsdiv_dispc_clk; |
1283 | dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk = | 1460 | dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk = |
1284 | cinfo->dsi_pll_hsdiv_dsi_clk; | 1461 | cinfo->dsi_pll_hsdiv_dsi_clk; |
1285 | 1462 | ||
1286 | dsi.current_cinfo.regn = cinfo->regn; | 1463 | dsi->current_cinfo.regn = cinfo->regn; |
1287 | dsi.current_cinfo.regm = cinfo->regm; | 1464 | dsi->current_cinfo.regm = cinfo->regm; |
1288 | dsi.current_cinfo.regm_dispc = cinfo->regm_dispc; | 1465 | dsi->current_cinfo.regm_dispc = cinfo->regm_dispc; |
1289 | dsi.current_cinfo.regm_dsi = cinfo->regm_dsi; | 1466 | dsi->current_cinfo.regm_dsi = cinfo->regm_dsi; |
1290 | 1467 | ||
1291 | DSSDBG("DSI Fint %ld\n", cinfo->fint); | 1468 | DSSDBG("DSI Fint %ld\n", cinfo->fint); |
1292 | 1469 | ||
@@ -1309,12 +1486,12 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1309 | DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); | 1486 | DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); |
1310 | 1487 | ||
1311 | DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc, | 1488 | DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc, |
1312 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), | 1489 | dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
1313 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), | 1490 | dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
1314 | cinfo->dsi_pll_hsdiv_dispc_clk); | 1491 | cinfo->dsi_pll_hsdiv_dispc_clk); |
1315 | DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi, | 1492 | DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi, |
1316 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | 1493 | dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), |
1317 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | 1494 | dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), |
1318 | cinfo->dsi_pll_hsdiv_dsi_clk); | 1495 | cinfo->dsi_pll_hsdiv_dsi_clk); |
1319 | 1496 | ||
1320 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end); | 1497 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end); |
@@ -1324,9 +1501,10 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1324 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, ®m_dsi_start, | 1501 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, ®m_dsi_start, |
1325 | ®m_dsi_end); | 1502 | ®m_dsi_end); |
1326 | 1503 | ||
1327 | REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ | 1504 | /* DSI_PLL_AUTOMODE = manual */ |
1505 | REG_FLD_MOD(dsidev, DSI_PLL_CONTROL, 0, 0, 0); | ||
1328 | 1506 | ||
1329 | l = dsi_read_reg(DSI_PLL_CONFIGURATION1); | 1507 | l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION1); |
1330 | l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ | 1508 | l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ |
1331 | /* DSI_PLL_REGN */ | 1509 | /* DSI_PLL_REGN */ |
1332 | l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end); | 1510 | l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end); |
@@ -1338,22 +1516,22 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1338 | /* DSIPROTO_CLOCK_DIV */ | 1516 | /* DSIPROTO_CLOCK_DIV */ |
1339 | l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0, | 1517 | l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0, |
1340 | regm_dsi_start, regm_dsi_end); | 1518 | regm_dsi_start, regm_dsi_end); |
1341 | dsi_write_reg(DSI_PLL_CONFIGURATION1, l); | 1519 | dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION1, l); |
1342 | 1520 | ||
1343 | BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max); | 1521 | BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max); |
1344 | if (cinfo->fint < 1000000) | 1522 | |
1345 | f = 0x3; | 1523 | if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) { |
1346 | else if (cinfo->fint < 1250000) | 1524 | f = cinfo->fint < 1000000 ? 0x3 : |
1347 | f = 0x4; | 1525 | cinfo->fint < 1250000 ? 0x4 : |
1348 | else if (cinfo->fint < 1500000) | 1526 | cinfo->fint < 1500000 ? 0x5 : |
1349 | f = 0x5; | 1527 | cinfo->fint < 1750000 ? 0x6 : |
1350 | else if (cinfo->fint < 1750000) | 1528 | 0x7; |
1351 | f = 0x6; | 1529 | } |
1352 | else | 1530 | |
1353 | f = 0x7; | 1531 | l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2); |
1354 | 1532 | ||
1355 | l = dsi_read_reg(DSI_PLL_CONFIGURATION2); | 1533 | if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) |
1356 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ | 1534 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ |
1357 | l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, | 1535 | l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, |
1358 | 11, 11); /* DSI_PLL_CLKSEL */ | 1536 | 11, 11); /* DSI_PLL_CLKSEL */ |
1359 | l = FLD_MOD(l, cinfo->highfreq, | 1537 | l = FLD_MOD(l, cinfo->highfreq, |
@@ -1361,25 +1539,25 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1361 | l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ | 1539 | l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ |
1362 | l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ | 1540 | l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ |
1363 | l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ | 1541 | l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ |
1364 | dsi_write_reg(DSI_PLL_CONFIGURATION2, l); | 1542 | dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l); |
1365 | 1543 | ||
1366 | REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ | 1544 | REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ |
1367 | 1545 | ||
1368 | if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) { | 1546 | if (wait_for_bit_change(dsidev, DSI_PLL_GO, 0, 0) != 0) { |
1369 | DSSERR("dsi pll go bit not going down.\n"); | 1547 | DSSERR("dsi pll go bit not going down.\n"); |
1370 | r = -EIO; | 1548 | r = -EIO; |
1371 | goto err; | 1549 | goto err; |
1372 | } | 1550 | } |
1373 | 1551 | ||
1374 | if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) { | 1552 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) { |
1375 | DSSERR("cannot lock PLL\n"); | 1553 | DSSERR("cannot lock PLL\n"); |
1376 | r = -EIO; | 1554 | r = -EIO; |
1377 | goto err; | 1555 | goto err; |
1378 | } | 1556 | } |
1379 | 1557 | ||
1380 | dsi.pll_locked = 1; | 1558 | dsi->pll_locked = 1; |
1381 | 1559 | ||
1382 | l = dsi_read_reg(DSI_PLL_CONFIGURATION2); | 1560 | l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2); |
1383 | l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */ | 1561 | l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */ |
1384 | l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */ | 1562 | l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */ |
1385 | l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */ | 1563 | l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */ |
@@ -1394,52 +1572,53 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1394 | l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */ | 1572 | l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */ |
1395 | l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */ | 1573 | l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */ |
1396 | l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */ | 1574 | l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */ |
1397 | dsi_write_reg(DSI_PLL_CONFIGURATION2, l); | 1575 | dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l); |
1398 | 1576 | ||
1399 | DSSDBG("PLL config done\n"); | 1577 | DSSDBG("PLL config done\n"); |
1400 | err: | 1578 | err: |
1401 | return r; | 1579 | return r; |
1402 | } | 1580 | } |
1403 | 1581 | ||
1404 | int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | 1582 | int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, |
1405 | bool enable_hsdiv) | 1583 | bool enable_hsdiv) |
1406 | { | 1584 | { |
1585 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1407 | int r = 0; | 1586 | int r = 0; |
1408 | enum dsi_pll_power_state pwstate; | 1587 | enum dsi_pll_power_state pwstate; |
1409 | 1588 | ||
1410 | DSSDBG("PLL init\n"); | 1589 | DSSDBG("PLL init\n"); |
1411 | 1590 | ||
1412 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 1591 | if (dsi->vdds_dsi_reg == NULL) { |
1413 | /* | ||
1414 | * HACK: this is just a quick hack to get the USE_DSI_PLL | ||
1415 | * option working. USE_DSI_PLL is itself a big hack, and | ||
1416 | * should be removed. | ||
1417 | */ | ||
1418 | if (dsi.vdds_dsi_reg == NULL) { | ||
1419 | struct regulator *vdds_dsi; | 1592 | struct regulator *vdds_dsi; |
1420 | 1593 | ||
1421 | vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi"); | 1594 | vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi"); |
1422 | 1595 | ||
1423 | if (IS_ERR(vdds_dsi)) { | 1596 | if (IS_ERR(vdds_dsi)) { |
1424 | DSSERR("can't get VDDS_DSI regulator\n"); | 1597 | DSSERR("can't get VDDS_DSI regulator\n"); |
1425 | return PTR_ERR(vdds_dsi); | 1598 | return PTR_ERR(vdds_dsi); |
1426 | } | 1599 | } |
1427 | 1600 | ||
1428 | dsi.vdds_dsi_reg = vdds_dsi; | 1601 | dsi->vdds_dsi_reg = vdds_dsi; |
1429 | } | 1602 | } |
1430 | #endif | ||
1431 | 1603 | ||
1432 | enable_clocks(1); | 1604 | enable_clocks(1); |
1433 | dsi_enable_pll_clock(1); | 1605 | dsi_enable_pll_clock(dsidev, 1); |
1606 | /* | ||
1607 | * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4. | ||
1608 | */ | ||
1609 | dsi_enable_scp_clk(dsidev); | ||
1434 | 1610 | ||
1435 | r = regulator_enable(dsi.vdds_dsi_reg); | 1611 | if (!dsi->vdds_dsi_enabled) { |
1436 | if (r) | 1612 | r = regulator_enable(dsi->vdds_dsi_reg); |
1437 | goto err0; | 1613 | if (r) |
1614 | goto err0; | ||
1615 | dsi->vdds_dsi_enabled = true; | ||
1616 | } | ||
1438 | 1617 | ||
1439 | /* XXX PLL does not come out of reset without this... */ | 1618 | /* XXX PLL does not come out of reset without this... */ |
1440 | dispc_pck_free_enable(1); | 1619 | dispc_pck_free_enable(1); |
1441 | 1620 | ||
1442 | if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) { | 1621 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 0, 1) != 1) { |
1443 | DSSERR("PLL not coming out of reset.\n"); | 1622 | DSSERR("PLL not coming out of reset.\n"); |
1444 | r = -ENODEV; | 1623 | r = -ENODEV; |
1445 | dispc_pck_free_enable(0); | 1624 | dispc_pck_free_enable(0); |
@@ -1459,7 +1638,7 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | |||
1459 | else | 1638 | else |
1460 | pwstate = DSI_PLL_POWER_OFF; | 1639 | pwstate = DSI_PLL_POWER_OFF; |
1461 | 1640 | ||
1462 | r = dsi_pll_power(pwstate); | 1641 | r = dsi_pll_power(dsidev, pwstate); |
1463 | 1642 | ||
1464 | if (r) | 1643 | if (r) |
1465 | goto err1; | 1644 | goto err1; |
@@ -1468,42 +1647,53 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | |||
1468 | 1647 | ||
1469 | return 0; | 1648 | return 0; |
1470 | err1: | 1649 | err1: |
1471 | regulator_disable(dsi.vdds_dsi_reg); | 1650 | if (dsi->vdds_dsi_enabled) { |
1651 | regulator_disable(dsi->vdds_dsi_reg); | ||
1652 | dsi->vdds_dsi_enabled = false; | ||
1653 | } | ||
1472 | err0: | 1654 | err0: |
1655 | dsi_disable_scp_clk(dsidev); | ||
1473 | enable_clocks(0); | 1656 | enable_clocks(0); |
1474 | dsi_enable_pll_clock(0); | 1657 | dsi_enable_pll_clock(dsidev, 0); |
1475 | return r; | 1658 | return r; |
1476 | } | 1659 | } |
1477 | 1660 | ||
1478 | void dsi_pll_uninit(void) | 1661 | void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes) |
1479 | { | 1662 | { |
1663 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1664 | |||
1665 | dsi->pll_locked = 0; | ||
1666 | dsi_pll_power(dsidev, DSI_PLL_POWER_OFF); | ||
1667 | if (disconnect_lanes) { | ||
1668 | WARN_ON(!dsi->vdds_dsi_enabled); | ||
1669 | regulator_disable(dsi->vdds_dsi_reg); | ||
1670 | dsi->vdds_dsi_enabled = false; | ||
1671 | } | ||
1672 | |||
1673 | dsi_disable_scp_clk(dsidev); | ||
1480 | enable_clocks(0); | 1674 | enable_clocks(0); |
1481 | dsi_enable_pll_clock(0); | 1675 | dsi_enable_pll_clock(dsidev, 0); |
1482 | 1676 | ||
1483 | dsi.pll_locked = 0; | ||
1484 | dsi_pll_power(DSI_PLL_POWER_OFF); | ||
1485 | regulator_disable(dsi.vdds_dsi_reg); | ||
1486 | DSSDBG("PLL uninit done\n"); | 1677 | DSSDBG("PLL uninit done\n"); |
1487 | } | 1678 | } |
1488 | 1679 | ||
1489 | void dsi_dump_clocks(struct seq_file *s) | 1680 | static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, |
1681 | struct seq_file *s) | ||
1490 | { | 1682 | { |
1491 | int clksel; | 1683 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1492 | struct dsi_clock_info *cinfo = &dsi.current_cinfo; | 1684 | struct dsi_clock_info *cinfo = &dsi->current_cinfo; |
1493 | enum dss_clk_source dispc_clk_src, dsi_clk_src; | 1685 | enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; |
1686 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
1494 | 1687 | ||
1495 | dispc_clk_src = dss_get_dispc_clk_source(); | 1688 | dispc_clk_src = dss_get_dispc_clk_source(); |
1496 | dsi_clk_src = dss_get_dsi_clk_source(); | 1689 | dsi_clk_src = dss_get_dsi_clk_source(dsi_module); |
1497 | 1690 | ||
1498 | enable_clocks(1); | 1691 | enable_clocks(1); |
1499 | 1692 | ||
1500 | clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11); | 1693 | seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); |
1501 | |||
1502 | seq_printf(s, "- DSI PLL -\n"); | ||
1503 | 1694 | ||
1504 | seq_printf(s, "dsi pll source = %s\n", | 1695 | seq_printf(s, "dsi pll source = %s\n", |
1505 | clksel == 0 ? | 1696 | cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree"); |
1506 | "dss_sys_clk" : "pclkfree"); | ||
1507 | 1697 | ||
1508 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); | 1698 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); |
1509 | 1699 | ||
@@ -1515,7 +1705,7 @@ void dsi_dump_clocks(struct seq_file *s) | |||
1515 | dss_feat_get_clk_source_name(dispc_clk_src), | 1705 | dss_feat_get_clk_source_name(dispc_clk_src), |
1516 | cinfo->dsi_pll_hsdiv_dispc_clk, | 1706 | cinfo->dsi_pll_hsdiv_dispc_clk, |
1517 | cinfo->regm_dispc, | 1707 | cinfo->regm_dispc, |
1518 | dispc_clk_src == DSS_CLK_SRC_FCK ? | 1708 | dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ? |
1519 | "off" : "on"); | 1709 | "off" : "on"); |
1520 | 1710 | ||
1521 | seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n", | 1711 | seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n", |
@@ -1523,45 +1713,55 @@ void dsi_dump_clocks(struct seq_file *s) | |||
1523 | dss_feat_get_clk_source_name(dsi_clk_src), | 1713 | dss_feat_get_clk_source_name(dsi_clk_src), |
1524 | cinfo->dsi_pll_hsdiv_dsi_clk, | 1714 | cinfo->dsi_pll_hsdiv_dsi_clk, |
1525 | cinfo->regm_dsi, | 1715 | cinfo->regm_dsi, |
1526 | dsi_clk_src == DSS_CLK_SRC_FCK ? | 1716 | dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ? |
1527 | "off" : "on"); | 1717 | "off" : "on"); |
1528 | 1718 | ||
1529 | seq_printf(s, "- DSI -\n"); | 1719 | seq_printf(s, "- DSI%d -\n", dsi_module + 1); |
1530 | 1720 | ||
1531 | seq_printf(s, "dsi fclk source = %s (%s)\n", | 1721 | seq_printf(s, "dsi fclk source = %s (%s)\n", |
1532 | dss_get_generic_clk_source_name(dsi_clk_src), | 1722 | dss_get_generic_clk_source_name(dsi_clk_src), |
1533 | dss_feat_get_clk_source_name(dsi_clk_src)); | 1723 | dss_feat_get_clk_source_name(dsi_clk_src)); |
1534 | 1724 | ||
1535 | seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); | 1725 | seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev)); |
1536 | 1726 | ||
1537 | seq_printf(s, "DDR_CLK\t\t%lu\n", | 1727 | seq_printf(s, "DDR_CLK\t\t%lu\n", |
1538 | cinfo->clkin4ddr / 4); | 1728 | cinfo->clkin4ddr / 4); |
1539 | 1729 | ||
1540 | seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs()); | 1730 | seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs(dsidev)); |
1541 | 1731 | ||
1542 | seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); | 1732 | seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); |
1543 | 1733 | ||
1544 | seq_printf(s, "VP_CLK\t\t%lu\n" | ||
1545 | "VP_PCLK\t\t%lu\n", | ||
1546 | dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), | ||
1547 | dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD)); | ||
1548 | |||
1549 | enable_clocks(0); | 1734 | enable_clocks(0); |
1550 | } | 1735 | } |
1551 | 1736 | ||
1737 | void dsi_dump_clocks(struct seq_file *s) | ||
1738 | { | ||
1739 | struct platform_device *dsidev; | ||
1740 | int i; | ||
1741 | |||
1742 | for (i = 0; i < MAX_NUM_DSI; i++) { | ||
1743 | dsidev = dsi_get_dsidev_from_id(i); | ||
1744 | if (dsidev) | ||
1745 | dsi_dump_dsidev_clocks(dsidev, s); | ||
1746 | } | ||
1747 | } | ||
1748 | |||
1552 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 1749 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
1553 | void dsi_dump_irqs(struct seq_file *s) | 1750 | static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, |
1751 | struct seq_file *s) | ||
1554 | { | 1752 | { |
1753 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1555 | unsigned long flags; | 1754 | unsigned long flags; |
1556 | struct dsi_irq_stats stats; | 1755 | struct dsi_irq_stats stats; |
1756 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
1557 | 1757 | ||
1558 | spin_lock_irqsave(&dsi.irq_stats_lock, flags); | 1758 | spin_lock_irqsave(&dsi->irq_stats_lock, flags); |
1559 | 1759 | ||
1560 | stats = dsi.irq_stats; | 1760 | stats = dsi->irq_stats; |
1561 | memset(&dsi.irq_stats, 0, sizeof(dsi.irq_stats)); | 1761 | memset(&dsi->irq_stats, 0, sizeof(dsi->irq_stats)); |
1562 | dsi.irq_stats.last_reset = jiffies; | 1762 | dsi->irq_stats.last_reset = jiffies; |
1563 | 1763 | ||
1564 | spin_unlock_irqrestore(&dsi.irq_stats_lock, flags); | 1764 | spin_unlock_irqrestore(&dsi->irq_stats_lock, flags); |
1565 | 1765 | ||
1566 | seq_printf(s, "period %u ms\n", | 1766 | seq_printf(s, "period %u ms\n", |
1567 | jiffies_to_msecs(jiffies - stats.last_reset)); | 1767 | jiffies_to_msecs(jiffies - stats.last_reset)); |
@@ -1570,7 +1770,7 @@ void dsi_dump_irqs(struct seq_file *s) | |||
1570 | #define PIS(x) \ | 1770 | #define PIS(x) \ |
1571 | seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); | 1771 | seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); |
1572 | 1772 | ||
1573 | seq_printf(s, "-- DSI interrupts --\n"); | 1773 | seq_printf(s, "-- DSI%d interrupts --\n", dsi_module + 1); |
1574 | PIS(VC0); | 1774 | PIS(VC0); |
1575 | PIS(VC1); | 1775 | PIS(VC1); |
1576 | PIS(VC2); | 1776 | PIS(VC2); |
@@ -1636,13 +1836,45 @@ void dsi_dump_irqs(struct seq_file *s) | |||
1636 | PIS(ULPSACTIVENOT_ALL1); | 1836 | PIS(ULPSACTIVENOT_ALL1); |
1637 | #undef PIS | 1837 | #undef PIS |
1638 | } | 1838 | } |
1839 | |||
1840 | static void dsi1_dump_irqs(struct seq_file *s) | ||
1841 | { | ||
1842 | struct platform_device *dsidev = dsi_get_dsidev_from_id(0); | ||
1843 | |||
1844 | dsi_dump_dsidev_irqs(dsidev, s); | ||
1845 | } | ||
1846 | |||
1847 | static void dsi2_dump_irqs(struct seq_file *s) | ||
1848 | { | ||
1849 | struct platform_device *dsidev = dsi_get_dsidev_from_id(1); | ||
1850 | |||
1851 | dsi_dump_dsidev_irqs(dsidev, s); | ||
1852 | } | ||
1853 | |||
1854 | void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir, | ||
1855 | const struct file_operations *debug_fops) | ||
1856 | { | ||
1857 | struct platform_device *dsidev; | ||
1858 | |||
1859 | dsidev = dsi_get_dsidev_from_id(0); | ||
1860 | if (dsidev) | ||
1861 | debugfs_create_file("dsi1_irqs", S_IRUGO, debugfs_dir, | ||
1862 | &dsi1_dump_irqs, debug_fops); | ||
1863 | |||
1864 | dsidev = dsi_get_dsidev_from_id(1); | ||
1865 | if (dsidev) | ||
1866 | debugfs_create_file("dsi2_irqs", S_IRUGO, debugfs_dir, | ||
1867 | &dsi2_dump_irqs, debug_fops); | ||
1868 | } | ||
1639 | #endif | 1869 | #endif |
1640 | 1870 | ||
1641 | void dsi_dump_regs(struct seq_file *s) | 1871 | static void dsi_dump_dsidev_regs(struct platform_device *dsidev, |
1872 | struct seq_file *s) | ||
1642 | { | 1873 | { |
1643 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) | 1874 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r)) |
1644 | 1875 | ||
1645 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); | 1876 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
1877 | dsi_enable_scp_clk(dsidev); | ||
1646 | 1878 | ||
1647 | DUMPREG(DSI_REVISION); | 1879 | DUMPREG(DSI_REVISION); |
1648 | DUMPREG(DSI_SYSCONFIG); | 1880 | DUMPREG(DSI_SYSCONFIG); |
@@ -1714,25 +1946,57 @@ void dsi_dump_regs(struct seq_file *s) | |||
1714 | DUMPREG(DSI_PLL_CONFIGURATION1); | 1946 | DUMPREG(DSI_PLL_CONFIGURATION1); |
1715 | DUMPREG(DSI_PLL_CONFIGURATION2); | 1947 | DUMPREG(DSI_PLL_CONFIGURATION2); |
1716 | 1948 | ||
1949 | dsi_disable_scp_clk(dsidev); | ||
1717 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | 1950 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
1718 | #undef DUMPREG | 1951 | #undef DUMPREG |
1719 | } | 1952 | } |
1720 | 1953 | ||
1721 | enum dsi_complexio_power_state { | 1954 | static void dsi1_dump_regs(struct seq_file *s) |
1955 | { | ||
1956 | struct platform_device *dsidev = dsi_get_dsidev_from_id(0); | ||
1957 | |||
1958 | dsi_dump_dsidev_regs(dsidev, s); | ||
1959 | } | ||
1960 | |||
1961 | static void dsi2_dump_regs(struct seq_file *s) | ||
1962 | { | ||
1963 | struct platform_device *dsidev = dsi_get_dsidev_from_id(1); | ||
1964 | |||
1965 | dsi_dump_dsidev_regs(dsidev, s); | ||
1966 | } | ||
1967 | |||
1968 | void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, | ||
1969 | const struct file_operations *debug_fops) | ||
1970 | { | ||
1971 | struct platform_device *dsidev; | ||
1972 | |||
1973 | dsidev = dsi_get_dsidev_from_id(0); | ||
1974 | if (dsidev) | ||
1975 | debugfs_create_file("dsi1_regs", S_IRUGO, debugfs_dir, | ||
1976 | &dsi1_dump_regs, debug_fops); | ||
1977 | |||
1978 | dsidev = dsi_get_dsidev_from_id(1); | ||
1979 | if (dsidev) | ||
1980 | debugfs_create_file("dsi2_regs", S_IRUGO, debugfs_dir, | ||
1981 | &dsi2_dump_regs, debug_fops); | ||
1982 | } | ||
1983 | enum dsi_cio_power_state { | ||
1722 | DSI_COMPLEXIO_POWER_OFF = 0x0, | 1984 | DSI_COMPLEXIO_POWER_OFF = 0x0, |
1723 | DSI_COMPLEXIO_POWER_ON = 0x1, | 1985 | DSI_COMPLEXIO_POWER_ON = 0x1, |
1724 | DSI_COMPLEXIO_POWER_ULPS = 0x2, | 1986 | DSI_COMPLEXIO_POWER_ULPS = 0x2, |
1725 | }; | 1987 | }; |
1726 | 1988 | ||
1727 | static int dsi_complexio_power(enum dsi_complexio_power_state state) | 1989 | static int dsi_cio_power(struct platform_device *dsidev, |
1990 | enum dsi_cio_power_state state) | ||
1728 | { | 1991 | { |
1729 | int t = 0; | 1992 | int t = 0; |
1730 | 1993 | ||
1731 | /* PWR_CMD */ | 1994 | /* PWR_CMD */ |
1732 | REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27); | 1995 | REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG1, state, 28, 27); |
1733 | 1996 | ||
1734 | /* PWR_STATUS */ | 1997 | /* PWR_STATUS */ |
1735 | while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) { | 1998 | while (FLD_GET(dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1), |
1999 | 26, 25) != state) { | ||
1736 | if (++t > 1000) { | 2000 | if (++t > 1000) { |
1737 | DSSERR("failed to set complexio power state to " | 2001 | DSSERR("failed to set complexio power state to " |
1738 | "%d\n", state); | 2002 | "%d\n", state); |
@@ -1744,9 +2008,70 @@ static int dsi_complexio_power(enum dsi_complexio_power_state state) | |||
1744 | return 0; | 2008 | return 0; |
1745 | } | 2009 | } |
1746 | 2010 | ||
1747 | static void dsi_complexio_config(struct omap_dss_device *dssdev) | 2011 | /* Number of data lanes present on DSI interface */ |
2012 | static inline int dsi_get_num_data_lanes(struct platform_device *dsidev) | ||
1748 | { | 2013 | { |
2014 | /* DSI on OMAP3 doesn't have register DSI_GNQ, set number | ||
2015 | * of data lanes as 2 by default */ | ||
2016 | if (dss_has_feature(FEAT_DSI_GNQ)) | ||
2017 | return REG_GET(dsidev, DSI_GNQ, 11, 9); /* NB_DATA_LANES */ | ||
2018 | else | ||
2019 | return 2; | ||
2020 | } | ||
2021 | |||
2022 | /* Number of data lanes used by the dss device */ | ||
2023 | static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev) | ||
2024 | { | ||
2025 | int num_data_lanes = 0; | ||
2026 | |||
2027 | if (dssdev->phy.dsi.data1_lane != 0) | ||
2028 | num_data_lanes++; | ||
2029 | if (dssdev->phy.dsi.data2_lane != 0) | ||
2030 | num_data_lanes++; | ||
2031 | if (dssdev->phy.dsi.data3_lane != 0) | ||
2032 | num_data_lanes++; | ||
2033 | if (dssdev->phy.dsi.data4_lane != 0) | ||
2034 | num_data_lanes++; | ||
2035 | |||
2036 | return num_data_lanes; | ||
2037 | } | ||
2038 | |||
2039 | static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) | ||
2040 | { | ||
2041 | int val; | ||
2042 | |||
2043 | /* line buffer on OMAP3 is 1024 x 24bits */ | ||
2044 | /* XXX: for some reason using full buffer size causes | ||
2045 | * considerable TX slowdown with update sizes that fill the | ||
2046 | * whole buffer */ | ||
2047 | if (!dss_has_feature(FEAT_DSI_GNQ)) | ||
2048 | return 1023 * 3; | ||
2049 | |||
2050 | val = REG_GET(dsidev, DSI_GNQ, 14, 12); /* VP1_LINE_BUFFER_SIZE */ | ||
2051 | |||
2052 | switch (val) { | ||
2053 | case 1: | ||
2054 | return 512 * 3; /* 512x24 bits */ | ||
2055 | case 2: | ||
2056 | return 682 * 3; /* 682x24 bits */ | ||
2057 | case 3: | ||
2058 | return 853 * 3; /* 853x24 bits */ | ||
2059 | case 4: | ||
2060 | return 1024 * 3; /* 1024x24 bits */ | ||
2061 | case 5: | ||
2062 | return 1194 * 3; /* 1194x24 bits */ | ||
2063 | case 6: | ||
2064 | return 1365 * 3; /* 1365x24 bits */ | ||
2065 | default: | ||
2066 | BUG(); | ||
2067 | } | ||
2068 | } | ||
2069 | |||
2070 | static void dsi_set_lane_config(struct omap_dss_device *dssdev) | ||
2071 | { | ||
2072 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
1749 | u32 r; | 2073 | u32 r; |
2074 | int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); | ||
1750 | 2075 | ||
1751 | int clk_lane = dssdev->phy.dsi.clk_lane; | 2076 | int clk_lane = dssdev->phy.dsi.clk_lane; |
1752 | int data1_lane = dssdev->phy.dsi.data1_lane; | 2077 | int data1_lane = dssdev->phy.dsi.data1_lane; |
@@ -1755,14 +2080,28 @@ static void dsi_complexio_config(struct omap_dss_device *dssdev) | |||
1755 | int data1_pol = dssdev->phy.dsi.data1_pol; | 2080 | int data1_pol = dssdev->phy.dsi.data1_pol; |
1756 | int data2_pol = dssdev->phy.dsi.data2_pol; | 2081 | int data2_pol = dssdev->phy.dsi.data2_pol; |
1757 | 2082 | ||
1758 | r = dsi_read_reg(DSI_COMPLEXIO_CFG1); | 2083 | r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1); |
1759 | r = FLD_MOD(r, clk_lane, 2, 0); | 2084 | r = FLD_MOD(r, clk_lane, 2, 0); |
1760 | r = FLD_MOD(r, clk_pol, 3, 3); | 2085 | r = FLD_MOD(r, clk_pol, 3, 3); |
1761 | r = FLD_MOD(r, data1_lane, 6, 4); | 2086 | r = FLD_MOD(r, data1_lane, 6, 4); |
1762 | r = FLD_MOD(r, data1_pol, 7, 7); | 2087 | r = FLD_MOD(r, data1_pol, 7, 7); |
1763 | r = FLD_MOD(r, data2_lane, 10, 8); | 2088 | r = FLD_MOD(r, data2_lane, 10, 8); |
1764 | r = FLD_MOD(r, data2_pol, 11, 11); | 2089 | r = FLD_MOD(r, data2_pol, 11, 11); |
1765 | dsi_write_reg(DSI_COMPLEXIO_CFG1, r); | 2090 | if (num_data_lanes_dssdev > 2) { |
2091 | int data3_lane = dssdev->phy.dsi.data3_lane; | ||
2092 | int data3_pol = dssdev->phy.dsi.data3_pol; | ||
2093 | |||
2094 | r = FLD_MOD(r, data3_lane, 14, 12); | ||
2095 | r = FLD_MOD(r, data3_pol, 15, 15); | ||
2096 | } | ||
2097 | if (num_data_lanes_dssdev > 3) { | ||
2098 | int data4_lane = dssdev->phy.dsi.data4_lane; | ||
2099 | int data4_pol = dssdev->phy.dsi.data4_pol; | ||
2100 | |||
2101 | r = FLD_MOD(r, data4_lane, 18, 16); | ||
2102 | r = FLD_MOD(r, data4_pol, 19, 19); | ||
2103 | } | ||
2104 | dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r); | ||
1766 | 2105 | ||
1767 | /* The configuration of the DSI complex I/O (number of data lanes, | 2106 | /* The configuration of the DSI complex I/O (number of data lanes, |
1768 | position, differential order) should not be changed while | 2107 | position, differential order) should not be changed while |
@@ -1776,27 +2115,31 @@ static void dsi_complexio_config(struct omap_dss_device *dssdev) | |||
1776 | DSI complex I/O configuration is unknown. */ | 2115 | DSI complex I/O configuration is unknown. */ |
1777 | 2116 | ||
1778 | /* | 2117 | /* |
1779 | REG_FLD_MOD(DSI_CTRL, 1, 0, 0); | 2118 | REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0); |
1780 | REG_FLD_MOD(DSI_CTRL, 0, 0, 0); | 2119 | REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0); |
1781 | REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); | 2120 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); |
1782 | REG_FLD_MOD(DSI_CTRL, 1, 0, 0); | 2121 | REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0); |
1783 | */ | 2122 | */ |
1784 | } | 2123 | } |
1785 | 2124 | ||
1786 | static inline unsigned ns2ddr(unsigned ns) | 2125 | static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns) |
1787 | { | 2126 | { |
2127 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2128 | |||
1788 | /* convert time in ns to ddr ticks, rounding up */ | 2129 | /* convert time in ns to ddr ticks, rounding up */ |
1789 | unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4; | 2130 | unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4; |
1790 | return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000; | 2131 | return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000; |
1791 | } | 2132 | } |
1792 | 2133 | ||
1793 | static inline unsigned ddr2ns(unsigned ddr) | 2134 | static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr) |
1794 | { | 2135 | { |
1795 | unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4; | 2136 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2137 | |||
2138 | unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4; | ||
1796 | return ddr * 1000 * 1000 / (ddr_clk / 1000); | 2139 | return ddr * 1000 * 1000 / (ddr_clk / 1000); |
1797 | } | 2140 | } |
1798 | 2141 | ||
1799 | static void dsi_complexio_timings(void) | 2142 | static void dsi_cio_timings(struct platform_device *dsidev) |
1800 | { | 2143 | { |
1801 | u32 r; | 2144 | u32 r; |
1802 | u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; | 2145 | u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; |
@@ -1808,139 +2151,323 @@ static void dsi_complexio_timings(void) | |||
1808 | /* 1 * DDR_CLK = 2 * UI */ | 2151 | /* 1 * DDR_CLK = 2 * UI */ |
1809 | 2152 | ||
1810 | /* min 40ns + 4*UI max 85ns + 6*UI */ | 2153 | /* min 40ns + 4*UI max 85ns + 6*UI */ |
1811 | ths_prepare = ns2ddr(70) + 2; | 2154 | ths_prepare = ns2ddr(dsidev, 70) + 2; |
1812 | 2155 | ||
1813 | /* min 145ns + 10*UI */ | 2156 | /* min 145ns + 10*UI */ |
1814 | ths_prepare_ths_zero = ns2ddr(175) + 2; | 2157 | ths_prepare_ths_zero = ns2ddr(dsidev, 175) + 2; |
1815 | 2158 | ||
1816 | /* min max(8*UI, 60ns+4*UI) */ | 2159 | /* min max(8*UI, 60ns+4*UI) */ |
1817 | ths_trail = ns2ddr(60) + 5; | 2160 | ths_trail = ns2ddr(dsidev, 60) + 5; |
1818 | 2161 | ||
1819 | /* min 100ns */ | 2162 | /* min 100ns */ |
1820 | ths_exit = ns2ddr(145); | 2163 | ths_exit = ns2ddr(dsidev, 145); |
1821 | 2164 | ||
1822 | /* tlpx min 50n */ | 2165 | /* tlpx min 50n */ |
1823 | tlpx_half = ns2ddr(25); | 2166 | tlpx_half = ns2ddr(dsidev, 25); |
1824 | 2167 | ||
1825 | /* min 60ns */ | 2168 | /* min 60ns */ |
1826 | tclk_trail = ns2ddr(60) + 2; | 2169 | tclk_trail = ns2ddr(dsidev, 60) + 2; |
1827 | 2170 | ||
1828 | /* min 38ns, max 95ns */ | 2171 | /* min 38ns, max 95ns */ |
1829 | tclk_prepare = ns2ddr(65); | 2172 | tclk_prepare = ns2ddr(dsidev, 65); |
1830 | 2173 | ||
1831 | /* min tclk-prepare + tclk-zero = 300ns */ | 2174 | /* min tclk-prepare + tclk-zero = 300ns */ |
1832 | tclk_zero = ns2ddr(260); | 2175 | tclk_zero = ns2ddr(dsidev, 260); |
1833 | 2176 | ||
1834 | DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n", | 2177 | DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n", |
1835 | ths_prepare, ddr2ns(ths_prepare), | 2178 | ths_prepare, ddr2ns(dsidev, ths_prepare), |
1836 | ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero)); | 2179 | ths_prepare_ths_zero, ddr2ns(dsidev, ths_prepare_ths_zero)); |
1837 | DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n", | 2180 | DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n", |
1838 | ths_trail, ddr2ns(ths_trail), | 2181 | ths_trail, ddr2ns(dsidev, ths_trail), |
1839 | ths_exit, ddr2ns(ths_exit)); | 2182 | ths_exit, ddr2ns(dsidev, ths_exit)); |
1840 | 2183 | ||
1841 | DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), " | 2184 | DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), " |
1842 | "tclk_zero %u (%uns)\n", | 2185 | "tclk_zero %u (%uns)\n", |
1843 | tlpx_half, ddr2ns(tlpx_half), | 2186 | tlpx_half, ddr2ns(dsidev, tlpx_half), |
1844 | tclk_trail, ddr2ns(tclk_trail), | 2187 | tclk_trail, ddr2ns(dsidev, tclk_trail), |
1845 | tclk_zero, ddr2ns(tclk_zero)); | 2188 | tclk_zero, ddr2ns(dsidev, tclk_zero)); |
1846 | DSSDBG("tclk_prepare %u (%uns)\n", | 2189 | DSSDBG("tclk_prepare %u (%uns)\n", |
1847 | tclk_prepare, ddr2ns(tclk_prepare)); | 2190 | tclk_prepare, ddr2ns(dsidev, tclk_prepare)); |
1848 | 2191 | ||
1849 | /* program timings */ | 2192 | /* program timings */ |
1850 | 2193 | ||
1851 | r = dsi_read_reg(DSI_DSIPHY_CFG0); | 2194 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); |
1852 | r = FLD_MOD(r, ths_prepare, 31, 24); | 2195 | r = FLD_MOD(r, ths_prepare, 31, 24); |
1853 | r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16); | 2196 | r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16); |
1854 | r = FLD_MOD(r, ths_trail, 15, 8); | 2197 | r = FLD_MOD(r, ths_trail, 15, 8); |
1855 | r = FLD_MOD(r, ths_exit, 7, 0); | 2198 | r = FLD_MOD(r, ths_exit, 7, 0); |
1856 | dsi_write_reg(DSI_DSIPHY_CFG0, r); | 2199 | dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r); |
1857 | 2200 | ||
1858 | r = dsi_read_reg(DSI_DSIPHY_CFG1); | 2201 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); |
1859 | r = FLD_MOD(r, tlpx_half, 22, 16); | 2202 | r = FLD_MOD(r, tlpx_half, 22, 16); |
1860 | r = FLD_MOD(r, tclk_trail, 15, 8); | 2203 | r = FLD_MOD(r, tclk_trail, 15, 8); |
1861 | r = FLD_MOD(r, tclk_zero, 7, 0); | 2204 | r = FLD_MOD(r, tclk_zero, 7, 0); |
1862 | dsi_write_reg(DSI_DSIPHY_CFG1, r); | 2205 | dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r); |
1863 | 2206 | ||
1864 | r = dsi_read_reg(DSI_DSIPHY_CFG2); | 2207 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); |
1865 | r = FLD_MOD(r, tclk_prepare, 7, 0); | 2208 | r = FLD_MOD(r, tclk_prepare, 7, 0); |
1866 | dsi_write_reg(DSI_DSIPHY_CFG2, r); | 2209 | dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r); |
1867 | } | 2210 | } |
1868 | 2211 | ||
2212 | static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, | ||
2213 | enum dsi_lane lanes) | ||
2214 | { | ||
2215 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2216 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2217 | int clk_lane = dssdev->phy.dsi.clk_lane; | ||
2218 | int data1_lane = dssdev->phy.dsi.data1_lane; | ||
2219 | int data2_lane = dssdev->phy.dsi.data2_lane; | ||
2220 | int data3_lane = dssdev->phy.dsi.data3_lane; | ||
2221 | int data4_lane = dssdev->phy.dsi.data4_lane; | ||
2222 | int clk_pol = dssdev->phy.dsi.clk_pol; | ||
2223 | int data1_pol = dssdev->phy.dsi.data1_pol; | ||
2224 | int data2_pol = dssdev->phy.dsi.data2_pol; | ||
2225 | int data3_pol = dssdev->phy.dsi.data3_pol; | ||
2226 | int data4_pol = dssdev->phy.dsi.data4_pol; | ||
2227 | |||
2228 | u32 l = 0; | ||
2229 | u8 lptxscp_start = dsi->num_data_lanes == 2 ? 22 : 26; | ||
2230 | |||
2231 | if (lanes & DSI_CLK_P) | ||
2232 | l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1)); | ||
2233 | if (lanes & DSI_CLK_N) | ||
2234 | l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0)); | ||
2235 | |||
2236 | if (lanes & DSI_DATA1_P) | ||
2237 | l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1)); | ||
2238 | if (lanes & DSI_DATA1_N) | ||
2239 | l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0)); | ||
2240 | |||
2241 | if (lanes & DSI_DATA2_P) | ||
2242 | l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1)); | ||
2243 | if (lanes & DSI_DATA2_N) | ||
2244 | l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0)); | ||
2245 | |||
2246 | if (lanes & DSI_DATA3_P) | ||
2247 | l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1)); | ||
2248 | if (lanes & DSI_DATA3_N) | ||
2249 | l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0)); | ||
2250 | |||
2251 | if (lanes & DSI_DATA4_P) | ||
2252 | l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1)); | ||
2253 | if (lanes & DSI_DATA4_N) | ||
2254 | l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0)); | ||
2255 | /* | ||
2256 | * Bits in REGLPTXSCPDAT4TO0DXDY: | ||
2257 | * 17: DY0 18: DX0 | ||
2258 | * 19: DY1 20: DX1 | ||
2259 | * 21: DY2 22: DX2 | ||
2260 | * 23: DY3 24: DX3 | ||
2261 | * 25: DY4 26: DX4 | ||
2262 | */ | ||
2263 | |||
2264 | /* Set the lane override configuration */ | ||
2265 | |||
2266 | /* REGLPTXSCPDAT4TO0DXDY */ | ||
2267 | REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, l, lptxscp_start, 17); | ||
1869 | 2268 | ||
1870 | static int dsi_complexio_init(struct omap_dss_device *dssdev) | 2269 | /* Enable lane override */ |
2270 | |||
2271 | /* ENLPTXSCPDAT */ | ||
2272 | REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 1, 27, 27); | ||
2273 | } | ||
2274 | |||
2275 | static void dsi_cio_disable_lane_override(struct platform_device *dsidev) | ||
1871 | { | 2276 | { |
1872 | int r = 0; | 2277 | /* Disable lane override */ |
2278 | REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 27, 27); /* ENLPTXSCPDAT */ | ||
2279 | /* Reset the lane override configuration */ | ||
2280 | /* REGLPTXSCPDAT4TO0DXDY */ | ||
2281 | REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17); | ||
2282 | } | ||
2283 | |||
2284 | static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) | ||
2285 | { | ||
2286 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2287 | int t; | ||
2288 | int bits[3]; | ||
2289 | bool in_use[3]; | ||
2290 | |||
2291 | if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) { | ||
2292 | bits[0] = 28; | ||
2293 | bits[1] = 27; | ||
2294 | bits[2] = 26; | ||
2295 | } else { | ||
2296 | bits[0] = 24; | ||
2297 | bits[1] = 25; | ||
2298 | bits[2] = 26; | ||
2299 | } | ||
2300 | |||
2301 | in_use[0] = false; | ||
2302 | in_use[1] = false; | ||
2303 | in_use[2] = false; | ||
2304 | |||
2305 | if (dssdev->phy.dsi.clk_lane != 0) | ||
2306 | in_use[dssdev->phy.dsi.clk_lane - 1] = true; | ||
2307 | if (dssdev->phy.dsi.data1_lane != 0) | ||
2308 | in_use[dssdev->phy.dsi.data1_lane - 1] = true; | ||
2309 | if (dssdev->phy.dsi.data2_lane != 0) | ||
2310 | in_use[dssdev->phy.dsi.data2_lane - 1] = true; | ||
2311 | |||
2312 | t = 100000; | ||
2313 | while (true) { | ||
2314 | u32 l; | ||
2315 | int i; | ||
2316 | int ok; | ||
2317 | |||
2318 | l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); | ||
2319 | |||
2320 | ok = 0; | ||
2321 | for (i = 0; i < 3; ++i) { | ||
2322 | if (!in_use[i] || (l & (1 << bits[i]))) | ||
2323 | ok++; | ||
2324 | } | ||
2325 | |||
2326 | if (ok == 3) | ||
2327 | break; | ||
2328 | |||
2329 | if (--t == 0) { | ||
2330 | for (i = 0; i < 3; ++i) { | ||
2331 | if (!in_use[i] || (l & (1 << bits[i]))) | ||
2332 | continue; | ||
2333 | |||
2334 | DSSERR("CIO TXCLKESC%d domain not coming " \ | ||
2335 | "out of reset\n", i); | ||
2336 | } | ||
2337 | return -EIO; | ||
2338 | } | ||
2339 | } | ||
2340 | |||
2341 | return 0; | ||
2342 | } | ||
2343 | |||
2344 | static int dsi_cio_init(struct omap_dss_device *dssdev) | ||
2345 | { | ||
2346 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2347 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2348 | int r; | ||
2349 | int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); | ||
2350 | u32 l; | ||
1873 | 2351 | ||
1874 | DSSDBG("dsi_complexio_init\n"); | 2352 | DSSDBGF(); |
1875 | 2353 | ||
1876 | /* CIO_CLK_ICG, enable L3 clk to CIO */ | 2354 | if (dsi->dsi_mux_pads) |
1877 | REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14); | 2355 | dsi->dsi_mux_pads(true); |
2356 | |||
2357 | dsi_enable_scp_clk(dsidev); | ||
1878 | 2358 | ||
1879 | /* A dummy read using the SCP interface to any DSIPHY register is | 2359 | /* A dummy read using the SCP interface to any DSIPHY register is |
1880 | * required after DSIPHY reset to complete the reset of the DSI complex | 2360 | * required after DSIPHY reset to complete the reset of the DSI complex |
1881 | * I/O. */ | 2361 | * I/O. */ |
1882 | dsi_read_reg(DSI_DSIPHY_CFG5); | 2362 | dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); |
1883 | 2363 | ||
1884 | if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) { | 2364 | if (wait_for_bit_change(dsidev, DSI_DSIPHY_CFG5, 30, 1) != 1) { |
1885 | DSSERR("ComplexIO PHY not coming out of reset.\n"); | 2365 | DSSERR("CIO SCP Clock domain not coming out of reset.\n"); |
1886 | r = -ENODEV; | 2366 | r = -EIO; |
1887 | goto err; | 2367 | goto err_scp_clk_dom; |
1888 | } | 2368 | } |
1889 | 2369 | ||
1890 | dsi_complexio_config(dssdev); | 2370 | dsi_set_lane_config(dssdev); |
2371 | |||
2372 | /* set TX STOP MODE timer to maximum for this operation */ | ||
2373 | l = dsi_read_reg(dsidev, DSI_TIMING1); | ||
2374 | l = FLD_MOD(l, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ | ||
2375 | l = FLD_MOD(l, 1, 14, 14); /* STOP_STATE_X16_IO */ | ||
2376 | l = FLD_MOD(l, 1, 13, 13); /* STOP_STATE_X4_IO */ | ||
2377 | l = FLD_MOD(l, 0x1fff, 12, 0); /* STOP_STATE_COUNTER_IO */ | ||
2378 | dsi_write_reg(dsidev, DSI_TIMING1, l); | ||
1891 | 2379 | ||
1892 | r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON); | 2380 | if (dsi->ulps_enabled) { |
2381 | u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P; | ||
1893 | 2382 | ||
2383 | DSSDBG("manual ulps exit\n"); | ||
2384 | |||
2385 | /* ULPS is exited by Mark-1 state for 1ms, followed by | ||
2386 | * stop state. DSS HW cannot do this via the normal | ||
2387 | * ULPS exit sequence, as after reset the DSS HW thinks | ||
2388 | * that we are not in ULPS mode, and refuses to send the | ||
2389 | * sequence. So we need to send the ULPS exit sequence | ||
2390 | * manually. | ||
2391 | */ | ||
2392 | |||
2393 | if (num_data_lanes_dssdev > 2) | ||
2394 | lane_mask |= DSI_DATA3_P; | ||
2395 | |||
2396 | if (num_data_lanes_dssdev > 3) | ||
2397 | lane_mask |= DSI_DATA4_P; | ||
2398 | |||
2399 | dsi_cio_enable_lane_override(dssdev, lane_mask); | ||
2400 | } | ||
2401 | |||
2402 | r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); | ||
1894 | if (r) | 2403 | if (r) |
1895 | goto err; | 2404 | goto err_cio_pwr; |
1896 | 2405 | ||
1897 | if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) { | 2406 | if (wait_for_bit_change(dsidev, DSI_COMPLEXIO_CFG1, 29, 1) != 1) { |
1898 | DSSERR("ComplexIO not coming out of reset.\n"); | 2407 | DSSERR("CIO PWR clock domain not coming out of reset.\n"); |
1899 | r = -ENODEV; | 2408 | r = -ENODEV; |
1900 | goto err; | 2409 | goto err_cio_pwr_dom; |
1901 | } | 2410 | } |
1902 | 2411 | ||
1903 | if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { | 2412 | dsi_if_enable(dsidev, true); |
1904 | DSSERR("ComplexIO LDO power down.\n"); | 2413 | dsi_if_enable(dsidev, false); |
1905 | r = -ENODEV; | 2414 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ |
1906 | goto err; | 2415 | |
2416 | r = dsi_cio_wait_tx_clk_esc_reset(dssdev); | ||
2417 | if (r) | ||
2418 | goto err_tx_clk_esc_rst; | ||
2419 | |||
2420 | if (dsi->ulps_enabled) { | ||
2421 | /* Keep Mark-1 state for 1ms (as per DSI spec) */ | ||
2422 | ktime_t wait = ns_to_ktime(1000 * 1000); | ||
2423 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2424 | schedule_hrtimeout(&wait, HRTIMER_MODE_REL); | ||
2425 | |||
2426 | /* Disable the override. The lanes should be set to Mark-11 | ||
2427 | * state by the HW */ | ||
2428 | dsi_cio_disable_lane_override(dsidev); | ||
1907 | } | 2429 | } |
1908 | 2430 | ||
1909 | dsi_complexio_timings(); | 2431 | /* FORCE_TX_STOP_MODE_IO */ |
2432 | REG_FLD_MOD(dsidev, DSI_TIMING1, 0, 15, 15); | ||
1910 | 2433 | ||
1911 | /* | 2434 | dsi_cio_timings(dsidev); |
1912 | The configuration of the DSI complex I/O (number of data lanes, | 2435 | |
1913 | position, differential order) should not be changed while | 2436 | dsi->ulps_enabled = false; |
1914 | DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the | ||
1915 | hardware to recognize a new configuration of the complex I/O (done | ||
1916 | in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow | ||
1917 | this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next | ||
1918 | reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20] | ||
1919 | LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN | ||
1920 | bit to 1. If the sequence is not followed, the DSi complex I/O | ||
1921 | configuration is undetermined. | ||
1922 | */ | ||
1923 | dsi_if_enable(1); | ||
1924 | dsi_if_enable(0); | ||
1925 | REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ | ||
1926 | dsi_if_enable(1); | ||
1927 | dsi_if_enable(0); | ||
1928 | 2437 | ||
1929 | DSSDBG("CIO init done\n"); | 2438 | DSSDBG("CIO init done\n"); |
1930 | err: | 2439 | |
2440 | return 0; | ||
2441 | |||
2442 | err_tx_clk_esc_rst: | ||
2443 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 20, 20); /* LP_CLK_ENABLE */ | ||
2444 | err_cio_pwr_dom: | ||
2445 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); | ||
2446 | err_cio_pwr: | ||
2447 | if (dsi->ulps_enabled) | ||
2448 | dsi_cio_disable_lane_override(dsidev); | ||
2449 | err_scp_clk_dom: | ||
2450 | dsi_disable_scp_clk(dsidev); | ||
2451 | if (dsi->dsi_mux_pads) | ||
2452 | dsi->dsi_mux_pads(false); | ||
1931 | return r; | 2453 | return r; |
1932 | } | 2454 | } |
1933 | 2455 | ||
1934 | static void dsi_complexio_uninit(void) | 2456 | static void dsi_cio_uninit(struct platform_device *dsidev) |
1935 | { | 2457 | { |
1936 | dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF); | 2458 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2459 | |||
2460 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); | ||
2461 | dsi_disable_scp_clk(dsidev); | ||
2462 | if (dsi->dsi_mux_pads) | ||
2463 | dsi->dsi_mux_pads(false); | ||
1937 | } | 2464 | } |
1938 | 2465 | ||
1939 | static int _dsi_wait_reset(void) | 2466 | static int _dsi_wait_reset(struct platform_device *dsidev) |
1940 | { | 2467 | { |
1941 | int t = 0; | 2468 | int t = 0; |
1942 | 2469 | ||
1943 | while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) { | 2470 | while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) { |
1944 | if (++t > 5) { | 2471 | if (++t > 5) { |
1945 | DSSERR("soft reset failed\n"); | 2472 | DSSERR("soft reset failed\n"); |
1946 | return -ENODEV; | 2473 | return -ENODEV; |
@@ -1951,28 +2478,30 @@ static int _dsi_wait_reset(void) | |||
1951 | return 0; | 2478 | return 0; |
1952 | } | 2479 | } |
1953 | 2480 | ||
1954 | static int _dsi_reset(void) | 2481 | static int _dsi_reset(struct platform_device *dsidev) |
1955 | { | 2482 | { |
1956 | /* Soft reset */ | 2483 | /* Soft reset */ |
1957 | REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1); | 2484 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1); |
1958 | return _dsi_wait_reset(); | 2485 | return _dsi_wait_reset(dsidev); |
1959 | } | 2486 | } |
1960 | 2487 | ||
1961 | static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, | 2488 | static void dsi_config_tx_fifo(struct platform_device *dsidev, |
2489 | enum fifo_size size1, enum fifo_size size2, | ||
1962 | enum fifo_size size3, enum fifo_size size4) | 2490 | enum fifo_size size3, enum fifo_size size4) |
1963 | { | 2491 | { |
2492 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1964 | u32 r = 0; | 2493 | u32 r = 0; |
1965 | int add = 0; | 2494 | int add = 0; |
1966 | int i; | 2495 | int i; |
1967 | 2496 | ||
1968 | dsi.vc[0].fifo_size = size1; | 2497 | dsi->vc[0].fifo_size = size1; |
1969 | dsi.vc[1].fifo_size = size2; | 2498 | dsi->vc[1].fifo_size = size2; |
1970 | dsi.vc[2].fifo_size = size3; | 2499 | dsi->vc[2].fifo_size = size3; |
1971 | dsi.vc[3].fifo_size = size4; | 2500 | dsi->vc[3].fifo_size = size4; |
1972 | 2501 | ||
1973 | for (i = 0; i < 4; i++) { | 2502 | for (i = 0; i < 4; i++) { |
1974 | u8 v; | 2503 | u8 v; |
1975 | int size = dsi.vc[i].fifo_size; | 2504 | int size = dsi->vc[i].fifo_size; |
1976 | 2505 | ||
1977 | if (add + size > 4) { | 2506 | if (add + size > 4) { |
1978 | DSSERR("Illegal FIFO configuration\n"); | 2507 | DSSERR("Illegal FIFO configuration\n"); |
@@ -1985,24 +2514,26 @@ static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, | |||
1985 | add += size; | 2514 | add += size; |
1986 | } | 2515 | } |
1987 | 2516 | ||
1988 | dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r); | 2517 | dsi_write_reg(dsidev, DSI_TX_FIFO_VC_SIZE, r); |
1989 | } | 2518 | } |
1990 | 2519 | ||
1991 | static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2, | 2520 | static void dsi_config_rx_fifo(struct platform_device *dsidev, |
2521 | enum fifo_size size1, enum fifo_size size2, | ||
1992 | enum fifo_size size3, enum fifo_size size4) | 2522 | enum fifo_size size3, enum fifo_size size4) |
1993 | { | 2523 | { |
2524 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1994 | u32 r = 0; | 2525 | u32 r = 0; |
1995 | int add = 0; | 2526 | int add = 0; |
1996 | int i; | 2527 | int i; |
1997 | 2528 | ||
1998 | dsi.vc[0].fifo_size = size1; | 2529 | dsi->vc[0].fifo_size = size1; |
1999 | dsi.vc[1].fifo_size = size2; | 2530 | dsi->vc[1].fifo_size = size2; |
2000 | dsi.vc[2].fifo_size = size3; | 2531 | dsi->vc[2].fifo_size = size3; |
2001 | dsi.vc[3].fifo_size = size4; | 2532 | dsi->vc[3].fifo_size = size4; |
2002 | 2533 | ||
2003 | for (i = 0; i < 4; i++) { | 2534 | for (i = 0; i < 4; i++) { |
2004 | u8 v; | 2535 | u8 v; |
2005 | int size = dsi.vc[i].fifo_size; | 2536 | int size = dsi->vc[i].fifo_size; |
2006 | 2537 | ||
2007 | if (add + size > 4) { | 2538 | if (add + size > 4) { |
2008 | DSSERR("Illegal FIFO configuration\n"); | 2539 | DSSERR("Illegal FIFO configuration\n"); |
@@ -2015,18 +2546,18 @@ static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2, | |||
2015 | add += size; | 2546 | add += size; |
2016 | } | 2547 | } |
2017 | 2548 | ||
2018 | dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r); | 2549 | dsi_write_reg(dsidev, DSI_RX_FIFO_VC_SIZE, r); |
2019 | } | 2550 | } |
2020 | 2551 | ||
2021 | static int dsi_force_tx_stop_mode_io(void) | 2552 | static int dsi_force_tx_stop_mode_io(struct platform_device *dsidev) |
2022 | { | 2553 | { |
2023 | u32 r; | 2554 | u32 r; |
2024 | 2555 | ||
2025 | r = dsi_read_reg(DSI_TIMING1); | 2556 | r = dsi_read_reg(dsidev, DSI_TIMING1); |
2026 | r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ | 2557 | r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ |
2027 | dsi_write_reg(DSI_TIMING1, r); | 2558 | dsi_write_reg(dsidev, DSI_TIMING1, r); |
2028 | 2559 | ||
2029 | if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) { | 2560 | if (wait_for_bit_change(dsidev, DSI_TIMING1, 15, 0) != 0) { |
2030 | DSSERR("TX_STOP bit not going down\n"); | 2561 | DSSERR("TX_STOP bit not going down\n"); |
2031 | return -EIO; | 2562 | return -EIO; |
2032 | } | 2563 | } |
@@ -2034,16 +2565,135 @@ static int dsi_force_tx_stop_mode_io(void) | |||
2034 | return 0; | 2565 | return 0; |
2035 | } | 2566 | } |
2036 | 2567 | ||
2037 | static int dsi_vc_enable(int channel, bool enable) | 2568 | static bool dsi_vc_is_enabled(struct platform_device *dsidev, int channel) |
2569 | { | ||
2570 | return REG_GET(dsidev, DSI_VC_CTRL(channel), 0, 0); | ||
2571 | } | ||
2572 | |||
2573 | static void dsi_packet_sent_handler_vp(void *data, u32 mask) | ||
2574 | { | ||
2575 | struct dsi_packet_sent_handler_data *vp_data = | ||
2576 | (struct dsi_packet_sent_handler_data *) data; | ||
2577 | struct dsi_data *dsi = dsi_get_dsidrv_data(vp_data->dsidev); | ||
2578 | const int channel = dsi->update_channel; | ||
2579 | u8 bit = dsi->te_enabled ? 30 : 31; | ||
2580 | |||
2581 | if (REG_GET(vp_data->dsidev, DSI_VC_TE(channel), bit, bit) == 0) | ||
2582 | complete(vp_data->completion); | ||
2583 | } | ||
2584 | |||
2585 | static int dsi_sync_vc_vp(struct platform_device *dsidev, int channel) | ||
2586 | { | ||
2587 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2588 | DECLARE_COMPLETION_ONSTACK(completion); | ||
2589 | struct dsi_packet_sent_handler_data vp_data = { dsidev, &completion }; | ||
2590 | int r = 0; | ||
2591 | u8 bit; | ||
2592 | |||
2593 | bit = dsi->te_enabled ? 30 : 31; | ||
2594 | |||
2595 | r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp, | ||
2596 | &vp_data, DSI_VC_IRQ_PACKET_SENT); | ||
2597 | if (r) | ||
2598 | goto err0; | ||
2599 | |||
2600 | /* Wait for completion only if TE_EN/TE_START is still set */ | ||
2601 | if (REG_GET(dsidev, DSI_VC_TE(channel), bit, bit)) { | ||
2602 | if (wait_for_completion_timeout(&completion, | ||
2603 | msecs_to_jiffies(10)) == 0) { | ||
2604 | DSSERR("Failed to complete previous frame transfer\n"); | ||
2605 | r = -EIO; | ||
2606 | goto err1; | ||
2607 | } | ||
2608 | } | ||
2609 | |||
2610 | dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp, | ||
2611 | &vp_data, DSI_VC_IRQ_PACKET_SENT); | ||
2612 | |||
2613 | return 0; | ||
2614 | err1: | ||
2615 | dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp, | ||
2616 | &vp_data, DSI_VC_IRQ_PACKET_SENT); | ||
2617 | err0: | ||
2618 | return r; | ||
2619 | } | ||
2620 | |||
2621 | static void dsi_packet_sent_handler_l4(void *data, u32 mask) | ||
2622 | { | ||
2623 | struct dsi_packet_sent_handler_data *l4_data = | ||
2624 | (struct dsi_packet_sent_handler_data *) data; | ||
2625 | struct dsi_data *dsi = dsi_get_dsidrv_data(l4_data->dsidev); | ||
2626 | const int channel = dsi->update_channel; | ||
2627 | |||
2628 | if (REG_GET(l4_data->dsidev, DSI_VC_CTRL(channel), 5, 5) == 0) | ||
2629 | complete(l4_data->completion); | ||
2630 | } | ||
2631 | |||
2632 | static int dsi_sync_vc_l4(struct platform_device *dsidev, int channel) | ||
2633 | { | ||
2634 | DECLARE_COMPLETION_ONSTACK(completion); | ||
2635 | struct dsi_packet_sent_handler_data l4_data = { dsidev, &completion }; | ||
2636 | int r = 0; | ||
2637 | |||
2638 | r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4, | ||
2639 | &l4_data, DSI_VC_IRQ_PACKET_SENT); | ||
2640 | if (r) | ||
2641 | goto err0; | ||
2642 | |||
2643 | /* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */ | ||
2644 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 5, 5)) { | ||
2645 | if (wait_for_completion_timeout(&completion, | ||
2646 | msecs_to_jiffies(10)) == 0) { | ||
2647 | DSSERR("Failed to complete previous l4 transfer\n"); | ||
2648 | r = -EIO; | ||
2649 | goto err1; | ||
2650 | } | ||
2651 | } | ||
2652 | |||
2653 | dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4, | ||
2654 | &l4_data, DSI_VC_IRQ_PACKET_SENT); | ||
2655 | |||
2656 | return 0; | ||
2657 | err1: | ||
2658 | dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4, | ||
2659 | &l4_data, DSI_VC_IRQ_PACKET_SENT); | ||
2660 | err0: | ||
2661 | return r; | ||
2662 | } | ||
2663 | |||
2664 | static int dsi_sync_vc(struct platform_device *dsidev, int channel) | ||
2665 | { | ||
2666 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2667 | |||
2668 | WARN_ON(!dsi_bus_is_locked(dsidev)); | ||
2669 | |||
2670 | WARN_ON(in_interrupt()); | ||
2671 | |||
2672 | if (!dsi_vc_is_enabled(dsidev, channel)) | ||
2673 | return 0; | ||
2674 | |||
2675 | switch (dsi->vc[channel].mode) { | ||
2676 | case DSI_VC_MODE_VP: | ||
2677 | return dsi_sync_vc_vp(dsidev, channel); | ||
2678 | case DSI_VC_MODE_L4: | ||
2679 | return dsi_sync_vc_l4(dsidev, channel); | ||
2680 | default: | ||
2681 | BUG(); | ||
2682 | } | ||
2683 | } | ||
2684 | |||
2685 | static int dsi_vc_enable(struct platform_device *dsidev, int channel, | ||
2686 | bool enable) | ||
2038 | { | 2687 | { |
2039 | DSSDBG("dsi_vc_enable channel %d, enable %d\n", | 2688 | DSSDBG("dsi_vc_enable channel %d, enable %d\n", |
2040 | channel, enable); | 2689 | channel, enable); |
2041 | 2690 | ||
2042 | enable = enable ? 1 : 0; | 2691 | enable = enable ? 1 : 0; |
2043 | 2692 | ||
2044 | REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0); | 2693 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 0, 0); |
2045 | 2694 | ||
2046 | if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) { | 2695 | if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), |
2696 | 0, enable) != enable) { | ||
2047 | DSSERR("Failed to set dsi_vc_enable to %d\n", enable); | 2697 | DSSERR("Failed to set dsi_vc_enable to %d\n", enable); |
2048 | return -EIO; | 2698 | return -EIO; |
2049 | } | 2699 | } |
@@ -2051,13 +2701,13 @@ static int dsi_vc_enable(int channel, bool enable) | |||
2051 | return 0; | 2701 | return 0; |
2052 | } | 2702 | } |
2053 | 2703 | ||
2054 | static void dsi_vc_initial_config(int channel) | 2704 | static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) |
2055 | { | 2705 | { |
2056 | u32 r; | 2706 | u32 r; |
2057 | 2707 | ||
2058 | DSSDBGF("%d", channel); | 2708 | DSSDBGF("%d", channel); |
2059 | 2709 | ||
2060 | r = dsi_read_reg(DSI_VC_CTRL(channel)); | 2710 | r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel)); |
2061 | 2711 | ||
2062 | if (FLD_GET(r, 15, 15)) /* VC_BUSY */ | 2712 | if (FLD_GET(r, 15, 15)) /* VC_BUSY */ |
2063 | DSSERR("VC(%d) busy when trying to configure it!\n", | 2713 | DSSERR("VC(%d) busy when trying to configure it!\n", |
@@ -2070,85 +2720,107 @@ static void dsi_vc_initial_config(int channel) | |||
2070 | r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ | 2720 | r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ |
2071 | r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ | 2721 | r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ |
2072 | r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */ | 2722 | r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */ |
2723 | if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH)) | ||
2724 | r = FLD_MOD(r, 3, 11, 10); /* OCP_WIDTH = 32 bit */ | ||
2073 | 2725 | ||
2074 | r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ | 2726 | r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ |
2075 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ | 2727 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ |
2076 | 2728 | ||
2077 | dsi_write_reg(DSI_VC_CTRL(channel), r); | 2729 | dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); |
2078 | } | 2730 | } |
2079 | 2731 | ||
2080 | static int dsi_vc_config_l4(int channel) | 2732 | static int dsi_vc_config_l4(struct platform_device *dsidev, int channel) |
2081 | { | 2733 | { |
2082 | if (dsi.vc[channel].mode == DSI_VC_MODE_L4) | 2734 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2735 | |||
2736 | if (dsi->vc[channel].mode == DSI_VC_MODE_L4) | ||
2083 | return 0; | 2737 | return 0; |
2084 | 2738 | ||
2085 | DSSDBGF("%d", channel); | 2739 | DSSDBGF("%d", channel); |
2086 | 2740 | ||
2087 | dsi_vc_enable(channel, 0); | 2741 | dsi_sync_vc(dsidev, channel); |
2742 | |||
2743 | dsi_vc_enable(dsidev, channel, 0); | ||
2088 | 2744 | ||
2089 | /* VC_BUSY */ | 2745 | /* VC_BUSY */ |
2090 | if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) { | 2746 | if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) { |
2091 | DSSERR("vc(%d) busy when trying to config for L4\n", channel); | 2747 | DSSERR("vc(%d) busy when trying to config for L4\n", channel); |
2092 | return -EIO; | 2748 | return -EIO; |
2093 | } | 2749 | } |
2094 | 2750 | ||
2095 | REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ | 2751 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ |
2752 | |||
2753 | /* DCS_CMD_ENABLE */ | ||
2754 | if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) | ||
2755 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 30, 30); | ||
2096 | 2756 | ||
2097 | dsi_vc_enable(channel, 1); | 2757 | dsi_vc_enable(dsidev, channel, 1); |
2098 | 2758 | ||
2099 | dsi.vc[channel].mode = DSI_VC_MODE_L4; | 2759 | dsi->vc[channel].mode = DSI_VC_MODE_L4; |
2100 | 2760 | ||
2101 | return 0; | 2761 | return 0; |
2102 | } | 2762 | } |
2103 | 2763 | ||
2104 | static int dsi_vc_config_vp(int channel) | 2764 | static int dsi_vc_config_vp(struct platform_device *dsidev, int channel) |
2105 | { | 2765 | { |
2106 | if (dsi.vc[channel].mode == DSI_VC_MODE_VP) | 2766 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2767 | |||
2768 | if (dsi->vc[channel].mode == DSI_VC_MODE_VP) | ||
2107 | return 0; | 2769 | return 0; |
2108 | 2770 | ||
2109 | DSSDBGF("%d", channel); | 2771 | DSSDBGF("%d", channel); |
2110 | 2772 | ||
2111 | dsi_vc_enable(channel, 0); | 2773 | dsi_sync_vc(dsidev, channel); |
2774 | |||
2775 | dsi_vc_enable(dsidev, channel, 0); | ||
2112 | 2776 | ||
2113 | /* VC_BUSY */ | 2777 | /* VC_BUSY */ |
2114 | if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) { | 2778 | if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) { |
2115 | DSSERR("vc(%d) busy when trying to config for VP\n", channel); | 2779 | DSSERR("vc(%d) busy when trying to config for VP\n", channel); |
2116 | return -EIO; | 2780 | return -EIO; |
2117 | } | 2781 | } |
2118 | 2782 | ||
2119 | REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ | 2783 | /* SOURCE, 1 = video port */ |
2784 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 1, 1); | ||
2785 | |||
2786 | /* DCS_CMD_ENABLE */ | ||
2787 | if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) | ||
2788 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 30, 30); | ||
2120 | 2789 | ||
2121 | dsi_vc_enable(channel, 1); | 2790 | dsi_vc_enable(dsidev, channel, 1); |
2122 | 2791 | ||
2123 | dsi.vc[channel].mode = DSI_VC_MODE_VP; | 2792 | dsi->vc[channel].mode = DSI_VC_MODE_VP; |
2124 | 2793 | ||
2125 | return 0; | 2794 | return 0; |
2126 | } | 2795 | } |
2127 | 2796 | ||
2128 | 2797 | ||
2129 | void omapdss_dsi_vc_enable_hs(int channel, bool enable) | 2798 | void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, |
2799 | bool enable) | ||
2130 | { | 2800 | { |
2801 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2802 | |||
2131 | DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); | 2803 | DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); |
2132 | 2804 | ||
2133 | WARN_ON(!dsi_bus_is_locked()); | 2805 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
2134 | 2806 | ||
2135 | dsi_vc_enable(channel, 0); | 2807 | dsi_vc_enable(dsidev, channel, 0); |
2136 | dsi_if_enable(0); | 2808 | dsi_if_enable(dsidev, 0); |
2137 | 2809 | ||
2138 | REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9); | 2810 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 9, 9); |
2139 | 2811 | ||
2140 | dsi_vc_enable(channel, 1); | 2812 | dsi_vc_enable(dsidev, channel, 1); |
2141 | dsi_if_enable(1); | 2813 | dsi_if_enable(dsidev, 1); |
2142 | 2814 | ||
2143 | dsi_force_tx_stop_mode_io(); | 2815 | dsi_force_tx_stop_mode_io(dsidev); |
2144 | } | 2816 | } |
2145 | EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); | 2817 | EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); |
2146 | 2818 | ||
2147 | static void dsi_vc_flush_long_data(int channel) | 2819 | static void dsi_vc_flush_long_data(struct platform_device *dsidev, int channel) |
2148 | { | 2820 | { |
2149 | while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { | 2821 | while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) { |
2150 | u32 val; | 2822 | u32 val; |
2151 | val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); | 2823 | val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); |
2152 | DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n", | 2824 | DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n", |
2153 | (val >> 0) & 0xff, | 2825 | (val >> 0) & 0xff, |
2154 | (val >> 8) & 0xff, | 2826 | (val >> 8) & 0xff, |
@@ -2194,13 +2866,14 @@ static void dsi_show_rx_ack_with_err(u16 err) | |||
2194 | DSSERR("\t\tDSI Protocol Violation\n"); | 2866 | DSSERR("\t\tDSI Protocol Violation\n"); |
2195 | } | 2867 | } |
2196 | 2868 | ||
2197 | static u16 dsi_vc_flush_receive_data(int channel) | 2869 | static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev, |
2870 | int channel) | ||
2198 | { | 2871 | { |
2199 | /* RX_FIFO_NOT_EMPTY */ | 2872 | /* RX_FIFO_NOT_EMPTY */ |
2200 | while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { | 2873 | while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) { |
2201 | u32 val; | 2874 | u32 val; |
2202 | u8 dt; | 2875 | u8 dt; |
2203 | val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); | 2876 | val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); |
2204 | DSSERR("\trawval %#08x\n", val); | 2877 | DSSERR("\trawval %#08x\n", val); |
2205 | dt = FLD_GET(val, 5, 0); | 2878 | dt = FLD_GET(val, 5, 0); |
2206 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { | 2879 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { |
@@ -2215,7 +2888,7 @@ static u16 dsi_vc_flush_receive_data(int channel) | |||
2215 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { | 2888 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { |
2216 | DSSERR("\tDCS long response, len %d\n", | 2889 | DSSERR("\tDCS long response, len %d\n", |
2217 | FLD_GET(val, 23, 8)); | 2890 | FLD_GET(val, 23, 8)); |
2218 | dsi_vc_flush_long_data(channel); | 2891 | dsi_vc_flush_long_data(dsidev, channel); |
2219 | } else { | 2892 | } else { |
2220 | DSSERR("\tunknown datatype 0x%02x\n", dt); | 2893 | DSSERR("\tunknown datatype 0x%02x\n", dt); |
2221 | } | 2894 | } |
@@ -2223,40 +2896,44 @@ static u16 dsi_vc_flush_receive_data(int channel) | |||
2223 | return 0; | 2896 | return 0; |
2224 | } | 2897 | } |
2225 | 2898 | ||
2226 | static int dsi_vc_send_bta(int channel) | 2899 | static int dsi_vc_send_bta(struct platform_device *dsidev, int channel) |
2227 | { | 2900 | { |
2228 | if (dsi.debug_write || dsi.debug_read) | 2901 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2902 | |||
2903 | if (dsi->debug_write || dsi->debug_read) | ||
2229 | DSSDBG("dsi_vc_send_bta %d\n", channel); | 2904 | DSSDBG("dsi_vc_send_bta %d\n", channel); |
2230 | 2905 | ||
2231 | WARN_ON(!dsi_bus_is_locked()); | 2906 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
2232 | 2907 | ||
2233 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */ | 2908 | /* RX_FIFO_NOT_EMPTY */ |
2909 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) { | ||
2234 | DSSERR("rx fifo not empty when sending BTA, dumping data:\n"); | 2910 | DSSERR("rx fifo not empty when sending BTA, dumping data:\n"); |
2235 | dsi_vc_flush_receive_data(channel); | 2911 | dsi_vc_flush_receive_data(dsidev, channel); |
2236 | } | 2912 | } |
2237 | 2913 | ||
2238 | REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ | 2914 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ |
2239 | 2915 | ||
2240 | return 0; | 2916 | return 0; |
2241 | } | 2917 | } |
2242 | 2918 | ||
2243 | int dsi_vc_send_bta_sync(int channel) | 2919 | int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel) |
2244 | { | 2920 | { |
2921 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2245 | DECLARE_COMPLETION_ONSTACK(completion); | 2922 | DECLARE_COMPLETION_ONSTACK(completion); |
2246 | int r = 0; | 2923 | int r = 0; |
2247 | u32 err; | 2924 | u32 err; |
2248 | 2925 | ||
2249 | r = dsi_register_isr_vc(channel, dsi_completion_handler, | 2926 | r = dsi_register_isr_vc(dsidev, channel, dsi_completion_handler, |
2250 | &completion, DSI_VC_IRQ_BTA); | 2927 | &completion, DSI_VC_IRQ_BTA); |
2251 | if (r) | 2928 | if (r) |
2252 | goto err0; | 2929 | goto err0; |
2253 | 2930 | ||
2254 | r = dsi_register_isr(dsi_completion_handler, &completion, | 2931 | r = dsi_register_isr(dsidev, dsi_completion_handler, &completion, |
2255 | DSI_IRQ_ERROR_MASK); | 2932 | DSI_IRQ_ERROR_MASK); |
2256 | if (r) | 2933 | if (r) |
2257 | goto err1; | 2934 | goto err1; |
2258 | 2935 | ||
2259 | r = dsi_vc_send_bta(channel); | 2936 | r = dsi_vc_send_bta(dsidev, channel); |
2260 | if (r) | 2937 | if (r) |
2261 | goto err2; | 2938 | goto err2; |
2262 | 2939 | ||
@@ -2267,41 +2944,42 @@ int dsi_vc_send_bta_sync(int channel) | |||
2267 | goto err2; | 2944 | goto err2; |
2268 | } | 2945 | } |
2269 | 2946 | ||
2270 | err = dsi_get_errors(); | 2947 | err = dsi_get_errors(dsidev); |
2271 | if (err) { | 2948 | if (err) { |
2272 | DSSERR("Error while sending BTA: %x\n", err); | 2949 | DSSERR("Error while sending BTA: %x\n", err); |
2273 | r = -EIO; | 2950 | r = -EIO; |
2274 | goto err2; | 2951 | goto err2; |
2275 | } | 2952 | } |
2276 | err2: | 2953 | err2: |
2277 | dsi_unregister_isr(dsi_completion_handler, &completion, | 2954 | dsi_unregister_isr(dsidev, dsi_completion_handler, &completion, |
2278 | DSI_IRQ_ERROR_MASK); | 2955 | DSI_IRQ_ERROR_MASK); |
2279 | err1: | 2956 | err1: |
2280 | dsi_unregister_isr_vc(channel, dsi_completion_handler, | 2957 | dsi_unregister_isr_vc(dsidev, channel, dsi_completion_handler, |
2281 | &completion, DSI_VC_IRQ_BTA); | 2958 | &completion, DSI_VC_IRQ_BTA); |
2282 | err0: | 2959 | err0: |
2283 | return r; | 2960 | return r; |
2284 | } | 2961 | } |
2285 | EXPORT_SYMBOL(dsi_vc_send_bta_sync); | 2962 | EXPORT_SYMBOL(dsi_vc_send_bta_sync); |
2286 | 2963 | ||
2287 | static inline void dsi_vc_write_long_header(int channel, u8 data_type, | 2964 | static inline void dsi_vc_write_long_header(struct platform_device *dsidev, |
2288 | u16 len, u8 ecc) | 2965 | int channel, u8 data_type, u16 len, u8 ecc) |
2289 | { | 2966 | { |
2967 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2290 | u32 val; | 2968 | u32 val; |
2291 | u8 data_id; | 2969 | u8 data_id; |
2292 | 2970 | ||
2293 | WARN_ON(!dsi_bus_is_locked()); | 2971 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
2294 | 2972 | ||
2295 | data_id = data_type | dsi.vc[channel].vc_id << 6; | 2973 | data_id = data_type | dsi->vc[channel].vc_id << 6; |
2296 | 2974 | ||
2297 | val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | | 2975 | val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | |
2298 | FLD_VAL(ecc, 31, 24); | 2976 | FLD_VAL(ecc, 31, 24); |
2299 | 2977 | ||
2300 | dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val); | 2978 | dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_HEADER(channel), val); |
2301 | } | 2979 | } |
2302 | 2980 | ||
2303 | static inline void dsi_vc_write_long_payload(int channel, | 2981 | static inline void dsi_vc_write_long_payload(struct platform_device *dsidev, |
2304 | u8 b1, u8 b2, u8 b3, u8 b4) | 2982 | int channel, u8 b1, u8 b2, u8 b3, u8 b4) |
2305 | { | 2983 | { |
2306 | u32 val; | 2984 | u32 val; |
2307 | 2985 | ||
@@ -2310,34 +2988,35 @@ static inline void dsi_vc_write_long_payload(int channel, | |||
2310 | /* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n", | 2988 | /* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n", |
2311 | b1, b2, b3, b4, val); */ | 2989 | b1, b2, b3, b4, val); */ |
2312 | 2990 | ||
2313 | dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val); | 2991 | dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(channel), val); |
2314 | } | 2992 | } |
2315 | 2993 | ||
2316 | static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len, | 2994 | static int dsi_vc_send_long(struct platform_device *dsidev, int channel, |
2317 | u8 ecc) | 2995 | u8 data_type, u8 *data, u16 len, u8 ecc) |
2318 | { | 2996 | { |
2319 | /*u32 val; */ | 2997 | /*u32 val; */ |
2998 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2320 | int i; | 2999 | int i; |
2321 | u8 *p; | 3000 | u8 *p; |
2322 | int r = 0; | 3001 | int r = 0; |
2323 | u8 b1, b2, b3, b4; | 3002 | u8 b1, b2, b3, b4; |
2324 | 3003 | ||
2325 | if (dsi.debug_write) | 3004 | if (dsi->debug_write) |
2326 | DSSDBG("dsi_vc_send_long, %d bytes\n", len); | 3005 | DSSDBG("dsi_vc_send_long, %d bytes\n", len); |
2327 | 3006 | ||
2328 | /* len + header */ | 3007 | /* len + header */ |
2329 | if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) { | 3008 | if (dsi->vc[channel].fifo_size * 32 * 4 < len + 4) { |
2330 | DSSERR("unable to send long packet: packet too long.\n"); | 3009 | DSSERR("unable to send long packet: packet too long.\n"); |
2331 | return -EINVAL; | 3010 | return -EINVAL; |
2332 | } | 3011 | } |
2333 | 3012 | ||
2334 | dsi_vc_config_l4(channel); | 3013 | dsi_vc_config_l4(dsidev, channel); |
2335 | 3014 | ||
2336 | dsi_vc_write_long_header(channel, data_type, len, ecc); | 3015 | dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc); |
2337 | 3016 | ||
2338 | p = data; | 3017 | p = data; |
2339 | for (i = 0; i < len >> 2; i++) { | 3018 | for (i = 0; i < len >> 2; i++) { |
2340 | if (dsi.debug_write) | 3019 | if (dsi->debug_write) |
2341 | DSSDBG("\tsending full packet %d\n", i); | 3020 | DSSDBG("\tsending full packet %d\n", i); |
2342 | 3021 | ||
2343 | b1 = *p++; | 3022 | b1 = *p++; |
@@ -2345,14 +3024,14 @@ static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len, | |||
2345 | b3 = *p++; | 3024 | b3 = *p++; |
2346 | b4 = *p++; | 3025 | b4 = *p++; |
2347 | 3026 | ||
2348 | dsi_vc_write_long_payload(channel, b1, b2, b3, b4); | 3027 | dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, b4); |
2349 | } | 3028 | } |
2350 | 3029 | ||
2351 | i = len % 4; | 3030 | i = len % 4; |
2352 | if (i) { | 3031 | if (i) { |
2353 | b1 = 0; b2 = 0; b3 = 0; | 3032 | b1 = 0; b2 = 0; b3 = 0; |
2354 | 3033 | ||
2355 | if (dsi.debug_write) | 3034 | if (dsi->debug_write) |
2356 | DSSDBG("\tsending remainder bytes %d\n", i); | 3035 | DSSDBG("\tsending remainder bytes %d\n", i); |
2357 | 3036 | ||
2358 | switch (i) { | 3037 | switch (i) { |
@@ -2370,62 +3049,69 @@ static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len, | |||
2370 | break; | 3049 | break; |
2371 | } | 3050 | } |
2372 | 3051 | ||
2373 | dsi_vc_write_long_payload(channel, b1, b2, b3, 0); | 3052 | dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, 0); |
2374 | } | 3053 | } |
2375 | 3054 | ||
2376 | return r; | 3055 | return r; |
2377 | } | 3056 | } |
2378 | 3057 | ||
2379 | static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) | 3058 | static int dsi_vc_send_short(struct platform_device *dsidev, int channel, |
3059 | u8 data_type, u16 data, u8 ecc) | ||
2380 | { | 3060 | { |
3061 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2381 | u32 r; | 3062 | u32 r; |
2382 | u8 data_id; | 3063 | u8 data_id; |
2383 | 3064 | ||
2384 | WARN_ON(!dsi_bus_is_locked()); | 3065 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
2385 | 3066 | ||
2386 | if (dsi.debug_write) | 3067 | if (dsi->debug_write) |
2387 | DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n", | 3068 | DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n", |
2388 | channel, | 3069 | channel, |
2389 | data_type, data & 0xff, (data >> 8) & 0xff); | 3070 | data_type, data & 0xff, (data >> 8) & 0xff); |
2390 | 3071 | ||
2391 | dsi_vc_config_l4(channel); | 3072 | dsi_vc_config_l4(dsidev, channel); |
2392 | 3073 | ||
2393 | if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) { | 3074 | if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) { |
2394 | DSSERR("ERROR FIFO FULL, aborting transfer\n"); | 3075 | DSSERR("ERROR FIFO FULL, aborting transfer\n"); |
2395 | return -EINVAL; | 3076 | return -EINVAL; |
2396 | } | 3077 | } |
2397 | 3078 | ||
2398 | data_id = data_type | dsi.vc[channel].vc_id << 6; | 3079 | data_id = data_type | dsi->vc[channel].vc_id << 6; |
2399 | 3080 | ||
2400 | r = (data_id << 0) | (data << 8) | (ecc << 24); | 3081 | r = (data_id << 0) | (data << 8) | (ecc << 24); |
2401 | 3082 | ||
2402 | dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r); | 3083 | dsi_write_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel), r); |
2403 | 3084 | ||
2404 | return 0; | 3085 | return 0; |
2405 | } | 3086 | } |
2406 | 3087 | ||
2407 | int dsi_vc_send_null(int channel) | 3088 | int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) |
2408 | { | 3089 | { |
3090 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2409 | u8 nullpkg[] = {0, 0, 0, 0}; | 3091 | u8 nullpkg[] = {0, 0, 0, 0}; |
2410 | return dsi_vc_send_long(channel, DSI_DT_NULL_PACKET, nullpkg, 4, 0); | 3092 | |
3093 | return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg, | ||
3094 | 4, 0); | ||
2411 | } | 3095 | } |
2412 | EXPORT_SYMBOL(dsi_vc_send_null); | 3096 | EXPORT_SYMBOL(dsi_vc_send_null); |
2413 | 3097 | ||
2414 | int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len) | 3098 | int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, |
3099 | u8 *data, int len) | ||
2415 | { | 3100 | { |
3101 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2416 | int r; | 3102 | int r; |
2417 | 3103 | ||
2418 | BUG_ON(len == 0); | 3104 | BUG_ON(len == 0); |
2419 | 3105 | ||
2420 | if (len == 1) { | 3106 | if (len == 1) { |
2421 | r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0, | 3107 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0, |
2422 | data[0], 0); | 3108 | data[0], 0); |
2423 | } else if (len == 2) { | 3109 | } else if (len == 2) { |
2424 | r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1, | 3110 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1, |
2425 | data[0] | (data[1] << 8), 0); | 3111 | data[0] | (data[1] << 8), 0); |
2426 | } else { | 3112 | } else { |
2427 | /* 0x39 = DCS Long Write */ | 3113 | /* 0x39 = DCS Long Write */ |
2428 | r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE, | 3114 | r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE, |
2429 | data, len, 0); | 3115 | data, len, 0); |
2430 | } | 3116 | } |
2431 | 3117 | ||
@@ -2433,21 +3119,24 @@ int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len) | |||
2433 | } | 3119 | } |
2434 | EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); | 3120 | EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); |
2435 | 3121 | ||
2436 | int dsi_vc_dcs_write(int channel, u8 *data, int len) | 3122 | int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, |
3123 | int len) | ||
2437 | { | 3124 | { |
3125 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2438 | int r; | 3126 | int r; |
2439 | 3127 | ||
2440 | r = dsi_vc_dcs_write_nosync(channel, data, len); | 3128 | r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len); |
2441 | if (r) | 3129 | if (r) |
2442 | goto err; | 3130 | goto err; |
2443 | 3131 | ||
2444 | r = dsi_vc_send_bta_sync(channel); | 3132 | r = dsi_vc_send_bta_sync(dssdev, channel); |
2445 | if (r) | 3133 | if (r) |
2446 | goto err; | 3134 | goto err; |
2447 | 3135 | ||
2448 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */ | 3136 | /* RX_FIFO_NOT_EMPTY */ |
3137 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) { | ||
2449 | DSSERR("rx fifo not empty after write, dumping data:\n"); | 3138 | DSSERR("rx fifo not empty after write, dumping data:\n"); |
2450 | dsi_vc_flush_receive_data(channel); | 3139 | dsi_vc_flush_receive_data(dsidev, channel); |
2451 | r = -EIO; | 3140 | r = -EIO; |
2452 | goto err; | 3141 | goto err; |
2453 | } | 3142 | } |
@@ -2460,47 +3149,51 @@ err: | |||
2460 | } | 3149 | } |
2461 | EXPORT_SYMBOL(dsi_vc_dcs_write); | 3150 | EXPORT_SYMBOL(dsi_vc_dcs_write); |
2462 | 3151 | ||
2463 | int dsi_vc_dcs_write_0(int channel, u8 dcs_cmd) | 3152 | int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd) |
2464 | { | 3153 | { |
2465 | return dsi_vc_dcs_write(channel, &dcs_cmd, 1); | 3154 | return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1); |
2466 | } | 3155 | } |
2467 | EXPORT_SYMBOL(dsi_vc_dcs_write_0); | 3156 | EXPORT_SYMBOL(dsi_vc_dcs_write_0); |
2468 | 3157 | ||
2469 | int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param) | 3158 | int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
3159 | u8 param) | ||
2470 | { | 3160 | { |
2471 | u8 buf[2]; | 3161 | u8 buf[2]; |
2472 | buf[0] = dcs_cmd; | 3162 | buf[0] = dcs_cmd; |
2473 | buf[1] = param; | 3163 | buf[1] = param; |
2474 | return dsi_vc_dcs_write(channel, buf, 2); | 3164 | return dsi_vc_dcs_write(dssdev, channel, buf, 2); |
2475 | } | 3165 | } |
2476 | EXPORT_SYMBOL(dsi_vc_dcs_write_1); | 3166 | EXPORT_SYMBOL(dsi_vc_dcs_write_1); |
2477 | 3167 | ||
2478 | int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | 3168 | int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
3169 | u8 *buf, int buflen) | ||
2479 | { | 3170 | { |
3171 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3172 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2480 | u32 val; | 3173 | u32 val; |
2481 | u8 dt; | 3174 | u8 dt; |
2482 | int r; | 3175 | int r; |
2483 | 3176 | ||
2484 | if (dsi.debug_read) | 3177 | if (dsi->debug_read) |
2485 | DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); | 3178 | DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); |
2486 | 3179 | ||
2487 | r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0); | 3180 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0); |
2488 | if (r) | 3181 | if (r) |
2489 | goto err; | 3182 | goto err; |
2490 | 3183 | ||
2491 | r = dsi_vc_send_bta_sync(channel); | 3184 | r = dsi_vc_send_bta_sync(dssdev, channel); |
2492 | if (r) | 3185 | if (r) |
2493 | goto err; | 3186 | goto err; |
2494 | 3187 | ||
2495 | /* RX_FIFO_NOT_EMPTY */ | 3188 | /* RX_FIFO_NOT_EMPTY */ |
2496 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) { | 3189 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) { |
2497 | DSSERR("RX fifo empty when trying to read.\n"); | 3190 | DSSERR("RX fifo empty when trying to read.\n"); |
2498 | r = -EIO; | 3191 | r = -EIO; |
2499 | goto err; | 3192 | goto err; |
2500 | } | 3193 | } |
2501 | 3194 | ||
2502 | val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); | 3195 | val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); |
2503 | if (dsi.debug_read) | 3196 | if (dsi->debug_read) |
2504 | DSSDBG("\theader: %08x\n", val); | 3197 | DSSDBG("\theader: %08x\n", val); |
2505 | dt = FLD_GET(val, 5, 0); | 3198 | dt = FLD_GET(val, 5, 0); |
2506 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { | 3199 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { |
@@ -2511,7 +3204,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | |||
2511 | 3204 | ||
2512 | } else if (dt == DSI_DT_RX_SHORT_READ_1) { | 3205 | } else if (dt == DSI_DT_RX_SHORT_READ_1) { |
2513 | u8 data = FLD_GET(val, 15, 8); | 3206 | u8 data = FLD_GET(val, 15, 8); |
2514 | if (dsi.debug_read) | 3207 | if (dsi->debug_read) |
2515 | DSSDBG("\tDCS short response, 1 byte: %02x\n", data); | 3208 | DSSDBG("\tDCS short response, 1 byte: %02x\n", data); |
2516 | 3209 | ||
2517 | if (buflen < 1) { | 3210 | if (buflen < 1) { |
@@ -2524,7 +3217,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | |||
2524 | return 1; | 3217 | return 1; |
2525 | } else if (dt == DSI_DT_RX_SHORT_READ_2) { | 3218 | } else if (dt == DSI_DT_RX_SHORT_READ_2) { |
2526 | u16 data = FLD_GET(val, 23, 8); | 3219 | u16 data = FLD_GET(val, 23, 8); |
2527 | if (dsi.debug_read) | 3220 | if (dsi->debug_read) |
2528 | DSSDBG("\tDCS short response, 2 byte: %04x\n", data); | 3221 | DSSDBG("\tDCS short response, 2 byte: %04x\n", data); |
2529 | 3222 | ||
2530 | if (buflen < 2) { | 3223 | if (buflen < 2) { |
@@ -2539,7 +3232,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | |||
2539 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { | 3232 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { |
2540 | int w; | 3233 | int w; |
2541 | int len = FLD_GET(val, 23, 8); | 3234 | int len = FLD_GET(val, 23, 8); |
2542 | if (dsi.debug_read) | 3235 | if (dsi->debug_read) |
2543 | DSSDBG("\tDCS long response, len %d\n", len); | 3236 | DSSDBG("\tDCS long response, len %d\n", len); |
2544 | 3237 | ||
2545 | if (len > buflen) { | 3238 | if (len > buflen) { |
@@ -2550,8 +3243,9 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | |||
2550 | /* two byte checksum ends the packet, not included in len */ | 3243 | /* two byte checksum ends the packet, not included in len */ |
2551 | for (w = 0; w < len + 2;) { | 3244 | for (w = 0; w < len + 2;) { |
2552 | int b; | 3245 | int b; |
2553 | val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); | 3246 | val = dsi_read_reg(dsidev, |
2554 | if (dsi.debug_read) | 3247 | DSI_VC_SHORT_PACKET_HEADER(channel)); |
3248 | if (dsi->debug_read) | ||
2555 | DSSDBG("\t\t%02x %02x %02x %02x\n", | 3249 | DSSDBG("\t\t%02x %02x %02x %02x\n", |
2556 | (val >> 0) & 0xff, | 3250 | (val >> 0) & 0xff, |
2557 | (val >> 8) & 0xff, | 3251 | (val >> 8) & 0xff, |
@@ -2582,11 +3276,12 @@ err: | |||
2582 | } | 3276 | } |
2583 | EXPORT_SYMBOL(dsi_vc_dcs_read); | 3277 | EXPORT_SYMBOL(dsi_vc_dcs_read); |
2584 | 3278 | ||
2585 | int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data) | 3279 | int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
3280 | u8 *data) | ||
2586 | { | 3281 | { |
2587 | int r; | 3282 | int r; |
2588 | 3283 | ||
2589 | r = dsi_vc_dcs_read(channel, dcs_cmd, data, 1); | 3284 | r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1); |
2590 | 3285 | ||
2591 | if (r < 0) | 3286 | if (r < 0) |
2592 | return r; | 3287 | return r; |
@@ -2598,12 +3293,13 @@ int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data) | |||
2598 | } | 3293 | } |
2599 | EXPORT_SYMBOL(dsi_vc_dcs_read_1); | 3294 | EXPORT_SYMBOL(dsi_vc_dcs_read_1); |
2600 | 3295 | ||
2601 | int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2) | 3296 | int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
3297 | u8 *data1, u8 *data2) | ||
2602 | { | 3298 | { |
2603 | u8 buf[2]; | 3299 | u8 buf[2]; |
2604 | int r; | 3300 | int r; |
2605 | 3301 | ||
2606 | r = dsi_vc_dcs_read(channel, dcs_cmd, buf, 2); | 3302 | r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2); |
2607 | 3303 | ||
2608 | if (r < 0) | 3304 | if (r < 0) |
2609 | return r; | 3305 | return r; |
@@ -2618,14 +3314,94 @@ int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2) | |||
2618 | } | 3314 | } |
2619 | EXPORT_SYMBOL(dsi_vc_dcs_read_2); | 3315 | EXPORT_SYMBOL(dsi_vc_dcs_read_2); |
2620 | 3316 | ||
2621 | int dsi_vc_set_max_rx_packet_size(int channel, u16 len) | 3317 | int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, |
3318 | u16 len) | ||
2622 | { | 3319 | { |
2623 | return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE, | 3320 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3321 | |||
3322 | return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE, | ||
2624 | len, 0); | 3323 | len, 0); |
2625 | } | 3324 | } |
2626 | EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); | 3325 | EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); |
2627 | 3326 | ||
2628 | static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16) | 3327 | static int dsi_enter_ulps(struct platform_device *dsidev) |
3328 | { | ||
3329 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3330 | DECLARE_COMPLETION_ONSTACK(completion); | ||
3331 | int r; | ||
3332 | |||
3333 | DSSDBGF(); | ||
3334 | |||
3335 | WARN_ON(!dsi_bus_is_locked(dsidev)); | ||
3336 | |||
3337 | WARN_ON(dsi->ulps_enabled); | ||
3338 | |||
3339 | if (dsi->ulps_enabled) | ||
3340 | return 0; | ||
3341 | |||
3342 | if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) { | ||
3343 | DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n"); | ||
3344 | return -EIO; | ||
3345 | } | ||
3346 | |||
3347 | dsi_sync_vc(dsidev, 0); | ||
3348 | dsi_sync_vc(dsidev, 1); | ||
3349 | dsi_sync_vc(dsidev, 2); | ||
3350 | dsi_sync_vc(dsidev, 3); | ||
3351 | |||
3352 | dsi_force_tx_stop_mode_io(dsidev); | ||
3353 | |||
3354 | dsi_vc_enable(dsidev, 0, false); | ||
3355 | dsi_vc_enable(dsidev, 1, false); | ||
3356 | dsi_vc_enable(dsidev, 2, false); | ||
3357 | dsi_vc_enable(dsidev, 3, false); | ||
3358 | |||
3359 | if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 16, 16)) { /* HS_BUSY */ | ||
3360 | DSSERR("HS busy when enabling ULPS\n"); | ||
3361 | return -EIO; | ||
3362 | } | ||
3363 | |||
3364 | if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 17, 17)) { /* LP_BUSY */ | ||
3365 | DSSERR("LP busy when enabling ULPS\n"); | ||
3366 | return -EIO; | ||
3367 | } | ||
3368 | |||
3369 | r = dsi_register_isr_cio(dsidev, dsi_completion_handler, &completion, | ||
3370 | DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); | ||
3371 | if (r) | ||
3372 | return r; | ||
3373 | |||
3374 | /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */ | ||
3375 | /* LANEx_ULPS_SIG2 */ | ||
3376 | REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2), | ||
3377 | 7, 5); | ||
3378 | |||
3379 | if (wait_for_completion_timeout(&completion, | ||
3380 | msecs_to_jiffies(1000)) == 0) { | ||
3381 | DSSERR("ULPS enable timeout\n"); | ||
3382 | r = -EIO; | ||
3383 | goto err; | ||
3384 | } | ||
3385 | |||
3386 | dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion, | ||
3387 | DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); | ||
3388 | |||
3389 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); | ||
3390 | |||
3391 | dsi_if_enable(dsidev, false); | ||
3392 | |||
3393 | dsi->ulps_enabled = true; | ||
3394 | |||
3395 | return 0; | ||
3396 | |||
3397 | err: | ||
3398 | dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion, | ||
3399 | DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); | ||
3400 | return r; | ||
3401 | } | ||
3402 | |||
3403 | static void dsi_set_lp_rx_timeout(struct platform_device *dsidev, | ||
3404 | unsigned ticks, bool x4, bool x16) | ||
2629 | { | 3405 | { |
2630 | unsigned long fck; | 3406 | unsigned long fck; |
2631 | unsigned long total_ticks; | 3407 | unsigned long total_ticks; |
@@ -2634,14 +3410,14 @@ static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16) | |||
2634 | BUG_ON(ticks > 0x1fff); | 3410 | BUG_ON(ticks > 0x1fff); |
2635 | 3411 | ||
2636 | /* ticks in DSI_FCK */ | 3412 | /* ticks in DSI_FCK */ |
2637 | fck = dsi_fclk_rate(); | 3413 | fck = dsi_fclk_rate(dsidev); |
2638 | 3414 | ||
2639 | r = dsi_read_reg(DSI_TIMING2); | 3415 | r = dsi_read_reg(dsidev, DSI_TIMING2); |
2640 | r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ | 3416 | r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ |
2641 | r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */ | 3417 | r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */ |
2642 | r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */ | 3418 | r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */ |
2643 | r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ | 3419 | r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ |
2644 | dsi_write_reg(DSI_TIMING2, r); | 3420 | dsi_write_reg(dsidev, DSI_TIMING2, r); |
2645 | 3421 | ||
2646 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); | 3422 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); |
2647 | 3423 | ||
@@ -2651,7 +3427,8 @@ static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16) | |||
2651 | (total_ticks * 1000) / (fck / 1000 / 1000)); | 3427 | (total_ticks * 1000) / (fck / 1000 / 1000)); |
2652 | } | 3428 | } |
2653 | 3429 | ||
2654 | static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16) | 3430 | static void dsi_set_ta_timeout(struct platform_device *dsidev, unsigned ticks, |
3431 | bool x8, bool x16) | ||
2655 | { | 3432 | { |
2656 | unsigned long fck; | 3433 | unsigned long fck; |
2657 | unsigned long total_ticks; | 3434 | unsigned long total_ticks; |
@@ -2660,14 +3437,14 @@ static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16) | |||
2660 | BUG_ON(ticks > 0x1fff); | 3437 | BUG_ON(ticks > 0x1fff); |
2661 | 3438 | ||
2662 | /* ticks in DSI_FCK */ | 3439 | /* ticks in DSI_FCK */ |
2663 | fck = dsi_fclk_rate(); | 3440 | fck = dsi_fclk_rate(dsidev); |
2664 | 3441 | ||
2665 | r = dsi_read_reg(DSI_TIMING1); | 3442 | r = dsi_read_reg(dsidev, DSI_TIMING1); |
2666 | r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ | 3443 | r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ |
2667 | r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */ | 3444 | r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */ |
2668 | r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */ | 3445 | r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */ |
2669 | r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ | 3446 | r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ |
2670 | dsi_write_reg(DSI_TIMING1, r); | 3447 | dsi_write_reg(dsidev, DSI_TIMING1, r); |
2671 | 3448 | ||
2672 | total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1); | 3449 | total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1); |
2673 | 3450 | ||
@@ -2677,7 +3454,8 @@ static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16) | |||
2677 | (total_ticks * 1000) / (fck / 1000 / 1000)); | 3454 | (total_ticks * 1000) / (fck / 1000 / 1000)); |
2678 | } | 3455 | } |
2679 | 3456 | ||
2680 | static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16) | 3457 | static void dsi_set_stop_state_counter(struct platform_device *dsidev, |
3458 | unsigned ticks, bool x4, bool x16) | ||
2681 | { | 3459 | { |
2682 | unsigned long fck; | 3460 | unsigned long fck; |
2683 | unsigned long total_ticks; | 3461 | unsigned long total_ticks; |
@@ -2686,14 +3464,14 @@ static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16) | |||
2686 | BUG_ON(ticks > 0x1fff); | 3464 | BUG_ON(ticks > 0x1fff); |
2687 | 3465 | ||
2688 | /* ticks in DSI_FCK */ | 3466 | /* ticks in DSI_FCK */ |
2689 | fck = dsi_fclk_rate(); | 3467 | fck = dsi_fclk_rate(dsidev); |
2690 | 3468 | ||
2691 | r = dsi_read_reg(DSI_TIMING1); | 3469 | r = dsi_read_reg(dsidev, DSI_TIMING1); |
2692 | r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ | 3470 | r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ |
2693 | r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */ | 3471 | r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */ |
2694 | r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */ | 3472 | r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */ |
2695 | r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ | 3473 | r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ |
2696 | dsi_write_reg(DSI_TIMING1, r); | 3474 | dsi_write_reg(dsidev, DSI_TIMING1, r); |
2697 | 3475 | ||
2698 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); | 3476 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); |
2699 | 3477 | ||
@@ -2703,7 +3481,8 @@ static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16) | |||
2703 | (total_ticks * 1000) / (fck / 1000 / 1000)); | 3481 | (total_ticks * 1000) / (fck / 1000 / 1000)); |
2704 | } | 3482 | } |
2705 | 3483 | ||
2706 | static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16) | 3484 | static void dsi_set_hs_tx_timeout(struct platform_device *dsidev, |
3485 | unsigned ticks, bool x4, bool x16) | ||
2707 | { | 3486 | { |
2708 | unsigned long fck; | 3487 | unsigned long fck; |
2709 | unsigned long total_ticks; | 3488 | unsigned long total_ticks; |
@@ -2712,14 +3491,14 @@ static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16) | |||
2712 | BUG_ON(ticks > 0x1fff); | 3491 | BUG_ON(ticks > 0x1fff); |
2713 | 3492 | ||
2714 | /* ticks in TxByteClkHS */ | 3493 | /* ticks in TxByteClkHS */ |
2715 | fck = dsi_get_txbyteclkhs(); | 3494 | fck = dsi_get_txbyteclkhs(dsidev); |
2716 | 3495 | ||
2717 | r = dsi_read_reg(DSI_TIMING2); | 3496 | r = dsi_read_reg(dsidev, DSI_TIMING2); |
2718 | r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ | 3497 | r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ |
2719 | r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */ | 3498 | r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */ |
2720 | r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */ | 3499 | r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */ |
2721 | r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ | 3500 | r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ |
2722 | dsi_write_reg(DSI_TIMING2, r); | 3501 | dsi_write_reg(dsidev, DSI_TIMING2, r); |
2723 | 3502 | ||
2724 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); | 3503 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); |
2725 | 3504 | ||
@@ -2730,24 +3509,25 @@ static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16) | |||
2730 | } | 3509 | } |
2731 | static int dsi_proto_config(struct omap_dss_device *dssdev) | 3510 | static int dsi_proto_config(struct omap_dss_device *dssdev) |
2732 | { | 3511 | { |
3512 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2733 | u32 r; | 3513 | u32 r; |
2734 | int buswidth = 0; | 3514 | int buswidth = 0; |
2735 | 3515 | ||
2736 | dsi_config_tx_fifo(DSI_FIFO_SIZE_32, | 3516 | dsi_config_tx_fifo(dsidev, DSI_FIFO_SIZE_32, |
2737 | DSI_FIFO_SIZE_32, | 3517 | DSI_FIFO_SIZE_32, |
2738 | DSI_FIFO_SIZE_32, | 3518 | DSI_FIFO_SIZE_32, |
2739 | DSI_FIFO_SIZE_32); | 3519 | DSI_FIFO_SIZE_32); |
2740 | 3520 | ||
2741 | dsi_config_rx_fifo(DSI_FIFO_SIZE_32, | 3521 | dsi_config_rx_fifo(dsidev, DSI_FIFO_SIZE_32, |
2742 | DSI_FIFO_SIZE_32, | 3522 | DSI_FIFO_SIZE_32, |
2743 | DSI_FIFO_SIZE_32, | 3523 | DSI_FIFO_SIZE_32, |
2744 | DSI_FIFO_SIZE_32); | 3524 | DSI_FIFO_SIZE_32); |
2745 | 3525 | ||
2746 | /* XXX what values for the timeouts? */ | 3526 | /* XXX what values for the timeouts? */ |
2747 | dsi_set_stop_state_counter(0x1000, false, false); | 3527 | dsi_set_stop_state_counter(dsidev, 0x1000, false, false); |
2748 | dsi_set_ta_timeout(0x1fff, true, true); | 3528 | dsi_set_ta_timeout(dsidev, 0x1fff, true, true); |
2749 | dsi_set_lp_rx_timeout(0x1fff, true, true); | 3529 | dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); |
2750 | dsi_set_hs_tx_timeout(0x1fff, true, true); | 3530 | dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); |
2751 | 3531 | ||
2752 | switch (dssdev->ctrl.pixel_size) { | 3532 | switch (dssdev->ctrl.pixel_size) { |
2753 | case 16: | 3533 | case 16: |
@@ -2763,7 +3543,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
2763 | BUG(); | 3543 | BUG(); |
2764 | } | 3544 | } |
2765 | 3545 | ||
2766 | r = dsi_read_reg(DSI_CTRL); | 3546 | r = dsi_read_reg(dsidev, DSI_CTRL); |
2767 | r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */ | 3547 | r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */ |
2768 | r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */ | 3548 | r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */ |
2769 | r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */ | 3549 | r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */ |
@@ -2773,21 +3553,25 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
2773 | r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ | 3553 | r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ |
2774 | r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ | 3554 | r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ |
2775 | r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ | 3555 | r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ |
2776 | r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ | 3556 | if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { |
2777 | r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */ | 3557 | r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ |
3558 | /* DCS_CMD_CODE, 1=start, 0=continue */ | ||
3559 | r = FLD_MOD(r, 0, 25, 25); | ||
3560 | } | ||
2778 | 3561 | ||
2779 | dsi_write_reg(DSI_CTRL, r); | 3562 | dsi_write_reg(dsidev, DSI_CTRL, r); |
2780 | 3563 | ||
2781 | dsi_vc_initial_config(0); | 3564 | dsi_vc_initial_config(dsidev, 0); |
2782 | dsi_vc_initial_config(1); | 3565 | dsi_vc_initial_config(dsidev, 1); |
2783 | dsi_vc_initial_config(2); | 3566 | dsi_vc_initial_config(dsidev, 2); |
2784 | dsi_vc_initial_config(3); | 3567 | dsi_vc_initial_config(dsidev, 3); |
2785 | 3568 | ||
2786 | return 0; | 3569 | return 0; |
2787 | } | 3570 | } |
2788 | 3571 | ||
2789 | static void dsi_proto_timings(struct omap_dss_device *dssdev) | 3572 | static void dsi_proto_timings(struct omap_dss_device *dssdev) |
2790 | { | 3573 | { |
3574 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2791 | unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; | 3575 | unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; |
2792 | unsigned tclk_pre, tclk_post; | 3576 | unsigned tclk_pre, tclk_post; |
2793 | unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; | 3577 | unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; |
@@ -2797,32 +3581,27 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
2797 | unsigned ths_eot; | 3581 | unsigned ths_eot; |
2798 | u32 r; | 3582 | u32 r; |
2799 | 3583 | ||
2800 | r = dsi_read_reg(DSI_DSIPHY_CFG0); | 3584 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); |
2801 | ths_prepare = FLD_GET(r, 31, 24); | 3585 | ths_prepare = FLD_GET(r, 31, 24); |
2802 | ths_prepare_ths_zero = FLD_GET(r, 23, 16); | 3586 | ths_prepare_ths_zero = FLD_GET(r, 23, 16); |
2803 | ths_zero = ths_prepare_ths_zero - ths_prepare; | 3587 | ths_zero = ths_prepare_ths_zero - ths_prepare; |
2804 | ths_trail = FLD_GET(r, 15, 8); | 3588 | ths_trail = FLD_GET(r, 15, 8); |
2805 | ths_exit = FLD_GET(r, 7, 0); | 3589 | ths_exit = FLD_GET(r, 7, 0); |
2806 | 3590 | ||
2807 | r = dsi_read_reg(DSI_DSIPHY_CFG1); | 3591 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); |
2808 | tlpx = FLD_GET(r, 22, 16) * 2; | 3592 | tlpx = FLD_GET(r, 22, 16) * 2; |
2809 | tclk_trail = FLD_GET(r, 15, 8); | 3593 | tclk_trail = FLD_GET(r, 15, 8); |
2810 | tclk_zero = FLD_GET(r, 7, 0); | 3594 | tclk_zero = FLD_GET(r, 7, 0); |
2811 | 3595 | ||
2812 | r = dsi_read_reg(DSI_DSIPHY_CFG2); | 3596 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); |
2813 | tclk_prepare = FLD_GET(r, 7, 0); | 3597 | tclk_prepare = FLD_GET(r, 7, 0); |
2814 | 3598 | ||
2815 | /* min 8*UI */ | 3599 | /* min 8*UI */ |
2816 | tclk_pre = 20; | 3600 | tclk_pre = 20; |
2817 | /* min 60ns + 52*UI */ | 3601 | /* min 60ns + 52*UI */ |
2818 | tclk_post = ns2ddr(60) + 26; | 3602 | tclk_post = ns2ddr(dsidev, 60) + 26; |
2819 | 3603 | ||
2820 | /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */ | 3604 | ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev)); |
2821 | if (dssdev->phy.dsi.data1_lane != 0 && | ||
2822 | dssdev->phy.dsi.data2_lane != 0) | ||
2823 | ths_eot = 2; | ||
2824 | else | ||
2825 | ths_eot = 4; | ||
2826 | 3605 | ||
2827 | ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, | 3606 | ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, |
2828 | 4); | 3607 | 4); |
@@ -2831,10 +3610,10 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
2831 | BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255); | 3610 | BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255); |
2832 | BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255); | 3611 | BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255); |
2833 | 3612 | ||
2834 | r = dsi_read_reg(DSI_CLK_TIMING); | 3613 | r = dsi_read_reg(dsidev, DSI_CLK_TIMING); |
2835 | r = FLD_MOD(r, ddr_clk_pre, 15, 8); | 3614 | r = FLD_MOD(r, ddr_clk_pre, 15, 8); |
2836 | r = FLD_MOD(r, ddr_clk_post, 7, 0); | 3615 | r = FLD_MOD(r, ddr_clk_post, 7, 0); |
2837 | dsi_write_reg(DSI_CLK_TIMING, r); | 3616 | dsi_write_reg(dsidev, DSI_CLK_TIMING, r); |
2838 | 3617 | ||
2839 | DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n", | 3618 | DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n", |
2840 | ddr_clk_pre, | 3619 | ddr_clk_pre, |
@@ -2848,7 +3627,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
2848 | 3627 | ||
2849 | r = FLD_VAL(enter_hs_mode_lat, 31, 16) | | 3628 | r = FLD_VAL(enter_hs_mode_lat, 31, 16) | |
2850 | FLD_VAL(exit_hs_mode_lat, 15, 0); | 3629 | FLD_VAL(exit_hs_mode_lat, 15, 0); |
2851 | dsi_write_reg(DSI_VM_TIMING7, r); | 3630 | dsi_write_reg(dsidev, DSI_VM_TIMING7, r); |
2852 | 3631 | ||
2853 | DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", | 3632 | DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", |
2854 | enter_hs_mode_lat, exit_hs_mode_lat); | 3633 | enter_hs_mode_lat, exit_hs_mode_lat); |
@@ -2858,25 +3637,27 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
2858 | #define DSI_DECL_VARS \ | 3637 | #define DSI_DECL_VARS \ |
2859 | int __dsi_cb = 0; u32 __dsi_cv = 0; | 3638 | int __dsi_cb = 0; u32 __dsi_cv = 0; |
2860 | 3639 | ||
2861 | #define DSI_FLUSH(ch) \ | 3640 | #define DSI_FLUSH(dsidev, ch) \ |
2862 | if (__dsi_cb > 0) { \ | 3641 | if (__dsi_cb > 0) { \ |
2863 | /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ | 3642 | /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ |
2864 | dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ | 3643 | dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ |
2865 | __dsi_cb = __dsi_cv = 0; \ | 3644 | __dsi_cb = __dsi_cv = 0; \ |
2866 | } | 3645 | } |
2867 | 3646 | ||
2868 | #define DSI_PUSH(ch, data) \ | 3647 | #define DSI_PUSH(dsidev, ch, data) \ |
2869 | do { \ | 3648 | do { \ |
2870 | __dsi_cv |= (data) << (__dsi_cb * 8); \ | 3649 | __dsi_cv |= (data) << (__dsi_cb * 8); \ |
2871 | /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ | 3650 | /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ |
2872 | if (++__dsi_cb > 3) \ | 3651 | if (++__dsi_cb > 3) \ |
2873 | DSI_FLUSH(ch); \ | 3652 | DSI_FLUSH(dsidev, ch); \ |
2874 | } while (0) | 3653 | } while (0) |
2875 | 3654 | ||
2876 | static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | 3655 | static int dsi_update_screen_l4(struct omap_dss_device *dssdev, |
2877 | int x, int y, int w, int h) | 3656 | int x, int y, int w, int h) |
2878 | { | 3657 | { |
2879 | /* Note: supports only 24bit colors in 32bit container */ | 3658 | /* Note: supports only 24bit colors in 32bit container */ |
3659 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3660 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2880 | int first = 1; | 3661 | int first = 1; |
2881 | int fifo_stalls = 0; | 3662 | int fifo_stalls = 0; |
2882 | int max_dsi_packet_size; | 3663 | int max_dsi_packet_size; |
@@ -2915,7 +3696,7 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
2915 | * in fifo */ | 3696 | * in fifo */ |
2916 | 3697 | ||
2917 | /* When using CPU, max long packet size is TX buffer size */ | 3698 | /* When using CPU, max long packet size is TX buffer size */ |
2918 | max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4; | 3699 | max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4; |
2919 | 3700 | ||
2920 | /* we seem to get better perf if we divide the tx fifo to half, | 3701 | /* we seem to get better perf if we divide the tx fifo to half, |
2921 | and while the other half is being sent, we fill the other half | 3702 | and while the other half is being sent, we fill the other half |
@@ -2944,35 +3725,36 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
2944 | #if 1 | 3725 | #if 1 |
2945 | /* using fifo not empty */ | 3726 | /* using fifo not empty */ |
2946 | /* TX_FIFO_NOT_EMPTY */ | 3727 | /* TX_FIFO_NOT_EMPTY */ |
2947 | while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) { | 3728 | while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) { |
2948 | fifo_stalls++; | 3729 | fifo_stalls++; |
2949 | if (fifo_stalls > 0xfffff) { | 3730 | if (fifo_stalls > 0xfffff) { |
2950 | DSSERR("fifo stalls overflow, pixels left %d\n", | 3731 | DSSERR("fifo stalls overflow, pixels left %d\n", |
2951 | pixels_left); | 3732 | pixels_left); |
2952 | dsi_if_enable(0); | 3733 | dsi_if_enable(dsidev, 0); |
2953 | return -EIO; | 3734 | return -EIO; |
2954 | } | 3735 | } |
2955 | udelay(1); | 3736 | udelay(1); |
2956 | } | 3737 | } |
2957 | #elif 1 | 3738 | #elif 1 |
2958 | /* using fifo emptiness */ | 3739 | /* using fifo emptiness */ |
2959 | while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < | 3740 | while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < |
2960 | max_dsi_packet_size) { | 3741 | max_dsi_packet_size) { |
2961 | fifo_stalls++; | 3742 | fifo_stalls++; |
2962 | if (fifo_stalls > 0xfffff) { | 3743 | if (fifo_stalls > 0xfffff) { |
2963 | DSSERR("fifo stalls overflow, pixels left %d\n", | 3744 | DSSERR("fifo stalls overflow, pixels left %d\n", |
2964 | pixels_left); | 3745 | pixels_left); |
2965 | dsi_if_enable(0); | 3746 | dsi_if_enable(dsidev, 0); |
2966 | return -EIO; | 3747 | return -EIO; |
2967 | } | 3748 | } |
2968 | } | 3749 | } |
2969 | #else | 3750 | #else |
2970 | while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) { | 3751 | while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, |
3752 | 7, 0) + 1) * 4 == 0) { | ||
2971 | fifo_stalls++; | 3753 | fifo_stalls++; |
2972 | if (fifo_stalls > 0xfffff) { | 3754 | if (fifo_stalls > 0xfffff) { |
2973 | DSSERR("fifo stalls overflow, pixels left %d\n", | 3755 | DSSERR("fifo stalls overflow, pixels left %d\n", |
2974 | pixels_left); | 3756 | pixels_left); |
2975 | dsi_if_enable(0); | 3757 | dsi_if_enable(dsidev, 0); |
2976 | return -EIO; | 3758 | return -EIO; |
2977 | } | 3759 | } |
2978 | } | 3760 | } |
@@ -2981,17 +3763,17 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
2981 | 3763 | ||
2982 | pixels_left -= pixels; | 3764 | pixels_left -= pixels; |
2983 | 3765 | ||
2984 | dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE, | 3766 | dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE, |
2985 | 1 + pixels * bytespp, 0); | 3767 | 1 + pixels * bytespp, 0); |
2986 | 3768 | ||
2987 | DSI_PUSH(0, dcs_cmd); | 3769 | DSI_PUSH(dsidev, 0, dcs_cmd); |
2988 | 3770 | ||
2989 | while (pixels-- > 0) { | 3771 | while (pixels-- > 0) { |
2990 | u32 pix = __raw_readl(data++); | 3772 | u32 pix = __raw_readl(data++); |
2991 | 3773 | ||
2992 | DSI_PUSH(0, (pix >> 16) & 0xff); | 3774 | DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff); |
2993 | DSI_PUSH(0, (pix >> 8) & 0xff); | 3775 | DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff); |
2994 | DSI_PUSH(0, (pix >> 0) & 0xff); | 3776 | DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff); |
2995 | 3777 | ||
2996 | current_x++; | 3778 | current_x++; |
2997 | if (current_x == x+w) { | 3779 | if (current_x == x+w) { |
@@ -3000,7 +3782,7 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
3000 | } | 3782 | } |
3001 | } | 3783 | } |
3002 | 3784 | ||
3003 | DSI_FLUSH(0); | 3785 | DSI_FLUSH(dsidev, 0); |
3004 | } | 3786 | } |
3005 | 3787 | ||
3006 | return 0; | 3788 | return 0; |
@@ -3009,6 +3791,8 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
3009 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | 3791 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, |
3010 | u16 x, u16 y, u16 w, u16 h) | 3792 | u16 x, u16 y, u16 w, u16 h) |
3011 | { | 3793 | { |
3794 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3795 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3012 | unsigned bytespp; | 3796 | unsigned bytespp; |
3013 | unsigned bytespl; | 3797 | unsigned bytespl; |
3014 | unsigned bytespf; | 3798 | unsigned bytespf; |
@@ -3017,16 +3801,13 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
3017 | unsigned packet_len; | 3801 | unsigned packet_len; |
3018 | u32 l; | 3802 | u32 l; |
3019 | int r; | 3803 | int r; |
3020 | const unsigned channel = dsi.update_channel; | 3804 | const unsigned channel = dsi->update_channel; |
3021 | /* line buffer is 1024 x 24bits */ | 3805 | const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); |
3022 | /* XXX: for some reason using full buffer size causes considerable TX | ||
3023 | * slowdown with update sizes that fill the whole buffer */ | ||
3024 | const unsigned line_buf_size = 1023 * 3; | ||
3025 | 3806 | ||
3026 | DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", | 3807 | DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", |
3027 | x, y, w, h); | 3808 | x, y, w, h); |
3028 | 3809 | ||
3029 | dsi_vc_config_vp(channel); | 3810 | dsi_vc_config_vp(dsidev, channel); |
3030 | 3811 | ||
3031 | bytespp = dssdev->ctrl.pixel_size / 8; | 3812 | bytespp = dssdev->ctrl.pixel_size / 8; |
3032 | bytespl = w * bytespp; | 3813 | bytespl = w * bytespp; |
@@ -3047,15 +3828,16 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
3047 | total_len += (bytespf % packet_payload) + 1; | 3828 | total_len += (bytespf % packet_payload) + 1; |
3048 | 3829 | ||
3049 | l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ | 3830 | l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ |
3050 | dsi_write_reg(DSI_VC_TE(channel), l); | 3831 | dsi_write_reg(dsidev, DSI_VC_TE(channel), l); |
3051 | 3832 | ||
3052 | dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0); | 3833 | dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE, |
3834 | packet_len, 0); | ||
3053 | 3835 | ||
3054 | if (dsi.te_enabled) | 3836 | if (dsi->te_enabled) |
3055 | l = FLD_MOD(l, 1, 30, 30); /* TE_EN */ | 3837 | l = FLD_MOD(l, 1, 30, 30); /* TE_EN */ |
3056 | else | 3838 | else |
3057 | l = FLD_MOD(l, 1, 31, 31); /* TE_START */ | 3839 | l = FLD_MOD(l, 1, 31, 31); /* TE_START */ |
3058 | dsi_write_reg(DSI_VC_TE(channel), l); | 3840 | dsi_write_reg(dsidev, DSI_VC_TE(channel), l); |
3059 | 3841 | ||
3060 | /* We put SIDLEMODE to no-idle for the duration of the transfer, | 3842 | /* We put SIDLEMODE to no-idle for the duration of the transfer, |
3061 | * because DSS interrupts are not capable of waking up the CPU and the | 3843 | * because DSS interrupts are not capable of waking up the CPU and the |
@@ -3065,23 +3847,23 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
3065 | */ | 3847 | */ |
3066 | dispc_disable_sidle(); | 3848 | dispc_disable_sidle(); |
3067 | 3849 | ||
3068 | dsi_perf_mark_start(); | 3850 | dsi_perf_mark_start(dsidev); |
3069 | 3851 | ||
3070 | r = queue_delayed_work(dsi.workqueue, &dsi.framedone_timeout_work, | 3852 | r = schedule_delayed_work(&dsi->framedone_timeout_work, |
3071 | msecs_to_jiffies(250)); | 3853 | msecs_to_jiffies(250)); |
3072 | BUG_ON(r == 0); | 3854 | BUG_ON(r == 0); |
3073 | 3855 | ||
3074 | dss_start_update(dssdev); | 3856 | dss_start_update(dssdev); |
3075 | 3857 | ||
3076 | if (dsi.te_enabled) { | 3858 | if (dsi->te_enabled) { |
3077 | /* disable LP_RX_TO, so that we can receive TE. Time to wait | 3859 | /* disable LP_RX_TO, so that we can receive TE. Time to wait |
3078 | * for TE is longer than the timer allows */ | 3860 | * for TE is longer than the timer allows */ |
3079 | REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */ | 3861 | REG_FLD_MOD(dsidev, DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */ |
3080 | 3862 | ||
3081 | dsi_vc_send_bta(channel); | 3863 | dsi_vc_send_bta(dsidev, channel); |
3082 | 3864 | ||
3083 | #ifdef DSI_CATCH_MISSING_TE | 3865 | #ifdef DSI_CATCH_MISSING_TE |
3084 | mod_timer(&dsi.te_timer, jiffies + msecs_to_jiffies(250)); | 3866 | mod_timer(&dsi->te_timer, jiffies + msecs_to_jiffies(250)); |
3085 | #endif | 3867 | #endif |
3086 | } | 3868 | } |
3087 | } | 3869 | } |
@@ -3093,41 +3875,28 @@ static void dsi_te_timeout(unsigned long arg) | |||
3093 | } | 3875 | } |
3094 | #endif | 3876 | #endif |
3095 | 3877 | ||
3096 | static void dsi_framedone_bta_callback(void *data, u32 mask); | 3878 | static void dsi_handle_framedone(struct platform_device *dsidev, int error) |
3097 | |||
3098 | static void dsi_handle_framedone(int error) | ||
3099 | { | 3879 | { |
3100 | const int channel = dsi.update_channel; | 3880 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
3101 | |||
3102 | dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, | ||
3103 | NULL, DSI_VC_IRQ_BTA); | ||
3104 | |||
3105 | cancel_delayed_work(&dsi.framedone_timeout_work); | ||
3106 | 3881 | ||
3107 | /* SIDLEMODE back to smart-idle */ | 3882 | /* SIDLEMODE back to smart-idle */ |
3108 | dispc_enable_sidle(); | 3883 | dispc_enable_sidle(); |
3109 | 3884 | ||
3110 | if (dsi.te_enabled) { | 3885 | if (dsi->te_enabled) { |
3111 | /* enable LP_RX_TO again after the TE */ | 3886 | /* enable LP_RX_TO again after the TE */ |
3112 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ | 3887 | REG_FLD_MOD(dsidev, DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ |
3113 | } | 3888 | } |
3114 | 3889 | ||
3115 | /* RX_FIFO_NOT_EMPTY */ | 3890 | dsi->framedone_callback(error, dsi->framedone_data); |
3116 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { | ||
3117 | DSSERR("Received error during frame transfer:\n"); | ||
3118 | dsi_vc_flush_receive_data(channel); | ||
3119 | if (!error) | ||
3120 | error = -EIO; | ||
3121 | } | ||
3122 | |||
3123 | dsi.framedone_callback(error, dsi.framedone_data); | ||
3124 | 3891 | ||
3125 | if (!error) | 3892 | if (!error) |
3126 | dsi_perf_show("DISPC"); | 3893 | dsi_perf_show(dsidev, "DISPC"); |
3127 | } | 3894 | } |
3128 | 3895 | ||
3129 | static void dsi_framedone_timeout_work_callback(struct work_struct *work) | 3896 | static void dsi_framedone_timeout_work_callback(struct work_struct *work) |
3130 | { | 3897 | { |
3898 | struct dsi_data *dsi = container_of(work, struct dsi_data, | ||
3899 | framedone_timeout_work.work); | ||
3131 | /* XXX While extremely unlikely, we could get FRAMEDONE interrupt after | 3900 | /* XXX While extremely unlikely, we could get FRAMEDONE interrupt after |
3132 | * 250ms which would conflict with this timeout work. What should be | 3901 | * 250ms which would conflict with this timeout work. What should be |
3133 | * done is first cancel the transfer on the HW, and then cancel the | 3902 | * done is first cancel the transfer on the HW, and then cancel the |
@@ -3137,70 +3906,34 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work) | |||
3137 | 3906 | ||
3138 | DSSERR("Framedone not received for 250ms!\n"); | 3907 | DSSERR("Framedone not received for 250ms!\n"); |
3139 | 3908 | ||
3140 | dsi_handle_framedone(-ETIMEDOUT); | 3909 | dsi_handle_framedone(dsi->pdev, -ETIMEDOUT); |
3141 | } | ||
3142 | |||
3143 | static void dsi_framedone_bta_callback(void *data, u32 mask) | ||
3144 | { | ||
3145 | dsi_handle_framedone(0); | ||
3146 | |||
3147 | #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC | ||
3148 | dispc_fake_vsync_irq(); | ||
3149 | #endif | ||
3150 | } | 3910 | } |
3151 | 3911 | ||
3152 | static void dsi_framedone_irq_callback(void *data, u32 mask) | 3912 | static void dsi_framedone_irq_callback(void *data, u32 mask) |
3153 | { | 3913 | { |
3154 | const int channel = dsi.update_channel; | 3914 | struct omap_dss_device *dssdev = (struct omap_dss_device *) data; |
3155 | int r; | 3915 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3916 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3156 | 3917 | ||
3157 | /* Note: We get FRAMEDONE when DISPC has finished sending pixels and | 3918 | /* Note: We get FRAMEDONE when DISPC has finished sending pixels and |
3158 | * turns itself off. However, DSI still has the pixels in its buffers, | 3919 | * turns itself off. However, DSI still has the pixels in its buffers, |
3159 | * and is sending the data. | 3920 | * and is sending the data. |
3160 | */ | 3921 | */ |
3161 | 3922 | ||
3162 | if (dsi.te_enabled) { | 3923 | __cancel_delayed_work(&dsi->framedone_timeout_work); |
3163 | /* enable LP_RX_TO again after the TE */ | ||
3164 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ | ||
3165 | } | ||
3166 | |||
3167 | /* Send BTA after the frame. We need this for the TE to work, as TE | ||
3168 | * trigger is only sent for BTAs without preceding packet. Thus we need | ||
3169 | * to BTA after the pixel packets so that next BTA will cause TE | ||
3170 | * trigger. | ||
3171 | * | ||
3172 | * This is not needed when TE is not in use, but we do it anyway to | ||
3173 | * make sure that the transfer has been completed. It would be more | ||
3174 | * optimal, but more complex, to wait only just before starting next | ||
3175 | * transfer. | ||
3176 | * | ||
3177 | * Also, as there's no interrupt telling when the transfer has been | ||
3178 | * done and the channel could be reconfigured, the only way is to | ||
3179 | * busyloop until TE_SIZE is zero. With BTA we can do this | ||
3180 | * asynchronously. | ||
3181 | * */ | ||
3182 | |||
3183 | r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback, | ||
3184 | NULL, DSI_VC_IRQ_BTA); | ||
3185 | if (r) { | ||
3186 | DSSERR("Failed to register BTA ISR\n"); | ||
3187 | dsi_handle_framedone(-EIO); | ||
3188 | return; | ||
3189 | } | ||
3190 | 3924 | ||
3191 | r = dsi_vc_send_bta(channel); | 3925 | dsi_handle_framedone(dsidev, 0); |
3192 | if (r) { | 3926 | |
3193 | DSSERR("BTA after framedone failed\n"); | 3927 | #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC |
3194 | dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, | 3928 | dispc_fake_vsync_irq(); |
3195 | NULL, DSI_VC_IRQ_BTA); | 3929 | #endif |
3196 | dsi_handle_framedone(-EIO); | ||
3197 | } | ||
3198 | } | 3930 | } |
3199 | 3931 | ||
3200 | int omap_dsi_prepare_update(struct omap_dss_device *dssdev, | 3932 | int omap_dsi_prepare_update(struct omap_dss_device *dssdev, |
3201 | u16 *x, u16 *y, u16 *w, u16 *h, | 3933 | u16 *x, u16 *y, u16 *w, u16 *h, |
3202 | bool enlarge_update_area) | 3934 | bool enlarge_update_area) |
3203 | { | 3935 | { |
3936 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3204 | u16 dw, dh; | 3937 | u16 dw, dh; |
3205 | 3938 | ||
3206 | dssdev->driver->get_resolution(dssdev, &dw, &dh); | 3939 | dssdev->driver->get_resolution(dssdev, &dw, &dh); |
@@ -3220,7 +3953,7 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev, | |||
3220 | if (*w == 0 || *h == 0) | 3953 | if (*w == 0 || *h == 0) |
3221 | return -EINVAL; | 3954 | return -EINVAL; |
3222 | 3955 | ||
3223 | dsi_perf_mark_setup(); | 3956 | dsi_perf_mark_setup(dsidev); |
3224 | 3957 | ||
3225 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 3958 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
3226 | dss_setup_partial_planes(dssdev, x, y, w, h, | 3959 | dss_setup_partial_planes(dssdev, x, y, w, h, |
@@ -3237,7 +3970,10 @@ int omap_dsi_update(struct omap_dss_device *dssdev, | |||
3237 | u16 x, u16 y, u16 w, u16 h, | 3970 | u16 x, u16 y, u16 w, u16 h, |
3238 | void (*callback)(int, void *), void *data) | 3971 | void (*callback)(int, void *), void *data) |
3239 | { | 3972 | { |
3240 | dsi.update_channel = channel; | 3973 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3974 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3975 | |||
3976 | dsi->update_channel = channel; | ||
3241 | 3977 | ||
3242 | /* OMAP DSS cannot send updates of odd widths. | 3978 | /* OMAP DSS cannot send updates of odd widths. |
3243 | * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON | 3979 | * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON |
@@ -3246,14 +3982,14 @@ int omap_dsi_update(struct omap_dss_device *dssdev, | |||
3246 | BUG_ON(x % 2 == 1); | 3982 | BUG_ON(x % 2 == 1); |
3247 | 3983 | ||
3248 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 3984 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
3249 | dsi.framedone_callback = callback; | 3985 | dsi->framedone_callback = callback; |
3250 | dsi.framedone_data = data; | 3986 | dsi->framedone_data = data; |
3251 | 3987 | ||
3252 | dsi.update_region.x = x; | 3988 | dsi->update_region.x = x; |
3253 | dsi.update_region.y = y; | 3989 | dsi->update_region.y = y; |
3254 | dsi.update_region.w = w; | 3990 | dsi->update_region.w = w; |
3255 | dsi.update_region.h = h; | 3991 | dsi->update_region.h = h; |
3256 | dsi.update_region.device = dssdev; | 3992 | dsi->update_region.device = dssdev; |
3257 | 3993 | ||
3258 | dsi_update_screen_dispc(dssdev, x, y, w, h); | 3994 | dsi_update_screen_dispc(dssdev, x, y, w, h); |
3259 | } else { | 3995 | } else { |
@@ -3263,7 +3999,7 @@ int omap_dsi_update(struct omap_dss_device *dssdev, | |||
3263 | if (r) | 3999 | if (r) |
3264 | return r; | 4000 | return r; |
3265 | 4001 | ||
3266 | dsi_perf_show("L4"); | 4002 | dsi_perf_show(dsidev, "L4"); |
3267 | callback(0, data); | 4003 | callback(0, data); |
3268 | } | 4004 | } |
3269 | 4005 | ||
@@ -3276,9 +4012,13 @@ EXPORT_SYMBOL(omap_dsi_update); | |||
3276 | static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | 4012 | static int dsi_display_init_dispc(struct omap_dss_device *dssdev) |
3277 | { | 4013 | { |
3278 | int r; | 4014 | int r; |
4015 | u32 irq; | ||
4016 | |||
4017 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? | ||
4018 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; | ||
3279 | 4019 | ||
3280 | r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL, | 4020 | r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev, |
3281 | DISPC_IRQ_FRAMEDONE); | 4021 | irq); |
3282 | if (r) { | 4022 | if (r) { |
3283 | DSSERR("can't get FRAMEDONE irq\n"); | 4023 | DSSERR("can't get FRAMEDONE irq\n"); |
3284 | return r; | 4024 | return r; |
@@ -3311,28 +4051,34 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | |||
3311 | 4051 | ||
3312 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) | 4052 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) |
3313 | { | 4053 | { |
3314 | omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL, | 4054 | u32 irq; |
3315 | DISPC_IRQ_FRAMEDONE); | 4055 | |
4056 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? | ||
4057 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; | ||
4058 | |||
4059 | omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev, | ||
4060 | irq); | ||
3316 | } | 4061 | } |
3317 | 4062 | ||
3318 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | 4063 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) |
3319 | { | 4064 | { |
4065 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3320 | struct dsi_clock_info cinfo; | 4066 | struct dsi_clock_info cinfo; |
3321 | int r; | 4067 | int r; |
3322 | 4068 | ||
3323 | /* we always use DSS_CLK_SYSCK as input clock */ | 4069 | /* we always use DSS_CLK_SYSCK as input clock */ |
3324 | cinfo.use_sys_clk = true; | 4070 | cinfo.use_sys_clk = true; |
3325 | cinfo.regn = dssdev->phy.dsi.div.regn; | 4071 | cinfo.regn = dssdev->clocks.dsi.regn; |
3326 | cinfo.regm = dssdev->phy.dsi.div.regm; | 4072 | cinfo.regm = dssdev->clocks.dsi.regm; |
3327 | cinfo.regm_dispc = dssdev->phy.dsi.div.regm_dispc; | 4073 | cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; |
3328 | cinfo.regm_dsi = dssdev->phy.dsi.div.regm_dsi; | 4074 | cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; |
3329 | r = dsi_calc_clock_rates(dssdev, &cinfo); | 4075 | r = dsi_calc_clock_rates(dssdev, &cinfo); |
3330 | if (r) { | 4076 | if (r) { |
3331 | DSSERR("Failed to calc dsi clocks\n"); | 4077 | DSSERR("Failed to calc dsi clocks\n"); |
3332 | return r; | 4078 | return r; |
3333 | } | 4079 | } |
3334 | 4080 | ||
3335 | r = dsi_pll_set_clock_div(&cinfo); | 4081 | r = dsi_pll_set_clock_div(dsidev, &cinfo); |
3336 | if (r) { | 4082 | if (r) { |
3337 | DSSERR("Failed to set dsi clocks\n"); | 4083 | DSSERR("Failed to set dsi clocks\n"); |
3338 | return r; | 4084 | return r; |
@@ -3343,14 +4089,15 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | |||
3343 | 4089 | ||
3344 | static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | 4090 | static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) |
3345 | { | 4091 | { |
4092 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3346 | struct dispc_clock_info dispc_cinfo; | 4093 | struct dispc_clock_info dispc_cinfo; |
3347 | int r; | 4094 | int r; |
3348 | unsigned long long fck; | 4095 | unsigned long long fck; |
3349 | 4096 | ||
3350 | fck = dsi_get_pll_hsdiv_dispc_rate(); | 4097 | fck = dsi_get_pll_hsdiv_dispc_rate(dsidev); |
3351 | 4098 | ||
3352 | dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; | 4099 | dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div; |
3353 | dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; | 4100 | dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div; |
3354 | 4101 | ||
3355 | r = dispc_calc_clock_rates(fck, &dispc_cinfo); | 4102 | r = dispc_calc_clock_rates(fck, &dispc_cinfo); |
3356 | if (r) { | 4103 | if (r) { |
@@ -3369,11 +4116,11 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
3369 | 4116 | ||
3370 | static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | 4117 | static int dsi_display_init_dsi(struct omap_dss_device *dssdev) |
3371 | { | 4118 | { |
4119 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4120 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
3372 | int r; | 4121 | int r; |
3373 | 4122 | ||
3374 | _dsi_print_reset_status(); | 4123 | r = dsi_pll_init(dsidev, true, true); |
3375 | |||
3376 | r = dsi_pll_init(dssdev, true, true); | ||
3377 | if (r) | 4124 | if (r) |
3378 | goto err0; | 4125 | goto err0; |
3379 | 4126 | ||
@@ -3381,8 +4128,10 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
3381 | if (r) | 4128 | if (r) |
3382 | goto err1; | 4129 | goto err1; |
3383 | 4130 | ||
3384 | dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); | 4131 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
3385 | dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI); | 4132 | dss_select_dsi_clk_source(dsi_module, dssdev->clocks.dsi.dsi_fclk_src); |
4133 | dss_select_lcd_clk_source(dssdev->manager->id, | ||
4134 | dssdev->clocks.dispc.channel.lcd_clk_src); | ||
3386 | 4135 | ||
3387 | DSSDBG("PLL OK\n"); | 4136 | DSSDBG("PLL OK\n"); |
3388 | 4137 | ||
@@ -3390,82 +4139,92 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
3390 | if (r) | 4139 | if (r) |
3391 | goto err2; | 4140 | goto err2; |
3392 | 4141 | ||
3393 | r = dsi_complexio_init(dssdev); | 4142 | r = dsi_cio_init(dssdev); |
3394 | if (r) | 4143 | if (r) |
3395 | goto err2; | 4144 | goto err2; |
3396 | 4145 | ||
3397 | _dsi_print_reset_status(); | 4146 | _dsi_print_reset_status(dsidev); |
3398 | 4147 | ||
3399 | dsi_proto_timings(dssdev); | 4148 | dsi_proto_timings(dssdev); |
3400 | dsi_set_lp_clk_divisor(dssdev); | 4149 | dsi_set_lp_clk_divisor(dssdev); |
3401 | 4150 | ||
3402 | if (1) | 4151 | if (1) |
3403 | _dsi_print_reset_status(); | 4152 | _dsi_print_reset_status(dsidev); |
3404 | 4153 | ||
3405 | r = dsi_proto_config(dssdev); | 4154 | r = dsi_proto_config(dssdev); |
3406 | if (r) | 4155 | if (r) |
3407 | goto err3; | 4156 | goto err3; |
3408 | 4157 | ||
3409 | /* enable interface */ | 4158 | /* enable interface */ |
3410 | dsi_vc_enable(0, 1); | 4159 | dsi_vc_enable(dsidev, 0, 1); |
3411 | dsi_vc_enable(1, 1); | 4160 | dsi_vc_enable(dsidev, 1, 1); |
3412 | dsi_vc_enable(2, 1); | 4161 | dsi_vc_enable(dsidev, 2, 1); |
3413 | dsi_vc_enable(3, 1); | 4162 | dsi_vc_enable(dsidev, 3, 1); |
3414 | dsi_if_enable(1); | 4163 | dsi_if_enable(dsidev, 1); |
3415 | dsi_force_tx_stop_mode_io(); | 4164 | dsi_force_tx_stop_mode_io(dsidev); |
3416 | 4165 | ||
3417 | return 0; | 4166 | return 0; |
3418 | err3: | 4167 | err3: |
3419 | dsi_complexio_uninit(); | 4168 | dsi_cio_uninit(dsidev); |
3420 | err2: | 4169 | err2: |
3421 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); | 4170 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
3422 | dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); | 4171 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); |
3423 | err1: | 4172 | err1: |
3424 | dsi_pll_uninit(); | 4173 | dsi_pll_uninit(dsidev, true); |
3425 | err0: | 4174 | err0: |
3426 | return r; | 4175 | return r; |
3427 | } | 4176 | } |
3428 | 4177 | ||
3429 | static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) | 4178 | static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, |
4179 | bool disconnect_lanes, bool enter_ulps) | ||
3430 | { | 4180 | { |
3431 | /* disable interface */ | 4181 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3432 | dsi_if_enable(0); | 4182 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
3433 | dsi_vc_enable(0, 0); | 4183 | int dsi_module = dsi_get_dsidev_id(dsidev); |
3434 | dsi_vc_enable(1, 0); | ||
3435 | dsi_vc_enable(2, 0); | ||
3436 | dsi_vc_enable(3, 0); | ||
3437 | 4184 | ||
3438 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); | 4185 | if (enter_ulps && !dsi->ulps_enabled) |
3439 | dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); | 4186 | dsi_enter_ulps(dsidev); |
3440 | dsi_complexio_uninit(); | 4187 | |
3441 | dsi_pll_uninit(); | 4188 | /* disable interface */ |
4189 | dsi_if_enable(dsidev, 0); | ||
4190 | dsi_vc_enable(dsidev, 0, 0); | ||
4191 | dsi_vc_enable(dsidev, 1, 0); | ||
4192 | dsi_vc_enable(dsidev, 2, 0); | ||
4193 | dsi_vc_enable(dsidev, 3, 0); | ||
4194 | |||
4195 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | ||
4196 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); | ||
4197 | dsi_cio_uninit(dsidev); | ||
4198 | dsi_pll_uninit(dsidev, disconnect_lanes); | ||
3442 | } | 4199 | } |
3443 | 4200 | ||
3444 | static int dsi_core_init(void) | 4201 | static int dsi_core_init(struct platform_device *dsidev) |
3445 | { | 4202 | { |
3446 | /* Autoidle */ | 4203 | /* Autoidle */ |
3447 | REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0); | 4204 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0); |
3448 | 4205 | ||
3449 | /* ENWAKEUP */ | 4206 | /* ENWAKEUP */ |
3450 | REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2); | 4207 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2); |
3451 | 4208 | ||
3452 | /* SIDLEMODE smart-idle */ | 4209 | /* SIDLEMODE smart-idle */ |
3453 | REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3); | 4210 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3); |
3454 | 4211 | ||
3455 | _dsi_initialize_irq(); | 4212 | _dsi_initialize_irq(dsidev); |
3456 | 4213 | ||
3457 | return 0; | 4214 | return 0; |
3458 | } | 4215 | } |
3459 | 4216 | ||
3460 | int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | 4217 | int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) |
3461 | { | 4218 | { |
4219 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4220 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3462 | int r = 0; | 4221 | int r = 0; |
3463 | 4222 | ||
3464 | DSSDBG("dsi_display_enable\n"); | 4223 | DSSDBG("dsi_display_enable\n"); |
3465 | 4224 | ||
3466 | WARN_ON(!dsi_bus_is_locked()); | 4225 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
3467 | 4226 | ||
3468 | mutex_lock(&dsi.lock); | 4227 | mutex_lock(&dsi->lock); |
3469 | 4228 | ||
3470 | r = omap_dss_start_device(dssdev); | 4229 | r = omap_dss_start_device(dssdev); |
3471 | if (r) { | 4230 | if (r) { |
@@ -3474,13 +4233,13 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
3474 | } | 4233 | } |
3475 | 4234 | ||
3476 | enable_clocks(1); | 4235 | enable_clocks(1); |
3477 | dsi_enable_pll_clock(1); | 4236 | dsi_enable_pll_clock(dsidev, 1); |
3478 | 4237 | ||
3479 | r = _dsi_reset(); | 4238 | r = _dsi_reset(dsidev); |
3480 | if (r) | 4239 | if (r) |
3481 | goto err1; | 4240 | goto err1; |
3482 | 4241 | ||
3483 | dsi_core_init(); | 4242 | dsi_core_init(dsidev); |
3484 | 4243 | ||
3485 | r = dsi_display_init_dispc(dssdev); | 4244 | r = dsi_display_init_dispc(dssdev); |
3486 | if (r) | 4245 | if (r) |
@@ -3490,7 +4249,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
3490 | if (r) | 4249 | if (r) |
3491 | goto err2; | 4250 | goto err2; |
3492 | 4251 | ||
3493 | mutex_unlock(&dsi.lock); | 4252 | mutex_unlock(&dsi->lock); |
3494 | 4253 | ||
3495 | return 0; | 4254 | return 0; |
3496 | 4255 | ||
@@ -3498,39 +4257,46 @@ err2: | |||
3498 | dsi_display_uninit_dispc(dssdev); | 4257 | dsi_display_uninit_dispc(dssdev); |
3499 | err1: | 4258 | err1: |
3500 | enable_clocks(0); | 4259 | enable_clocks(0); |
3501 | dsi_enable_pll_clock(0); | 4260 | dsi_enable_pll_clock(dsidev, 0); |
3502 | omap_dss_stop_device(dssdev); | 4261 | omap_dss_stop_device(dssdev); |
3503 | err0: | 4262 | err0: |
3504 | mutex_unlock(&dsi.lock); | 4263 | mutex_unlock(&dsi->lock); |
3505 | DSSDBG("dsi_display_enable FAILED\n"); | 4264 | DSSDBG("dsi_display_enable FAILED\n"); |
3506 | return r; | 4265 | return r; |
3507 | } | 4266 | } |
3508 | EXPORT_SYMBOL(omapdss_dsi_display_enable); | 4267 | EXPORT_SYMBOL(omapdss_dsi_display_enable); |
3509 | 4268 | ||
3510 | void omapdss_dsi_display_disable(struct omap_dss_device *dssdev) | 4269 | void omapdss_dsi_display_disable(struct omap_dss_device *dssdev, |
4270 | bool disconnect_lanes, bool enter_ulps) | ||
3511 | { | 4271 | { |
4272 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4273 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4274 | |||
3512 | DSSDBG("dsi_display_disable\n"); | 4275 | DSSDBG("dsi_display_disable\n"); |
3513 | 4276 | ||
3514 | WARN_ON(!dsi_bus_is_locked()); | 4277 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
3515 | 4278 | ||
3516 | mutex_lock(&dsi.lock); | 4279 | mutex_lock(&dsi->lock); |
3517 | 4280 | ||
3518 | dsi_display_uninit_dispc(dssdev); | 4281 | dsi_display_uninit_dispc(dssdev); |
3519 | 4282 | ||
3520 | dsi_display_uninit_dsi(dssdev); | 4283 | dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps); |
3521 | 4284 | ||
3522 | enable_clocks(0); | 4285 | enable_clocks(0); |
3523 | dsi_enable_pll_clock(0); | 4286 | dsi_enable_pll_clock(dsidev, 0); |
3524 | 4287 | ||
3525 | omap_dss_stop_device(dssdev); | 4288 | omap_dss_stop_device(dssdev); |
3526 | 4289 | ||
3527 | mutex_unlock(&dsi.lock); | 4290 | mutex_unlock(&dsi->lock); |
3528 | } | 4291 | } |
3529 | EXPORT_SYMBOL(omapdss_dsi_display_disable); | 4292 | EXPORT_SYMBOL(omapdss_dsi_display_disable); |
3530 | 4293 | ||
3531 | int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) | 4294 | int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) |
3532 | { | 4295 | { |
3533 | dsi.te_enabled = enable; | 4296 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
4297 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4298 | |||
4299 | dsi->te_enabled = enable; | ||
3534 | return 0; | 4300 | return 0; |
3535 | } | 4301 | } |
3536 | EXPORT_SYMBOL(omapdss_dsi_enable_te); | 4302 | EXPORT_SYMBOL(omapdss_dsi_enable_te); |
@@ -3550,23 +4316,33 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, | |||
3550 | 4316 | ||
3551 | int dsi_init_display(struct omap_dss_device *dssdev) | 4317 | int dsi_init_display(struct omap_dss_device *dssdev) |
3552 | { | 4318 | { |
4319 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4320 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4321 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
4322 | |||
3553 | DSSDBG("DSI init\n"); | 4323 | DSSDBG("DSI init\n"); |
3554 | 4324 | ||
3555 | /* XXX these should be figured out dynamically */ | 4325 | /* XXX these should be figured out dynamically */ |
3556 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | | 4326 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | |
3557 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; | 4327 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; |
3558 | 4328 | ||
3559 | if (dsi.vdds_dsi_reg == NULL) { | 4329 | if (dsi->vdds_dsi_reg == NULL) { |
3560 | struct regulator *vdds_dsi; | 4330 | struct regulator *vdds_dsi; |
3561 | 4331 | ||
3562 | vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi"); | 4332 | vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi"); |
3563 | 4333 | ||
3564 | if (IS_ERR(vdds_dsi)) { | 4334 | if (IS_ERR(vdds_dsi)) { |
3565 | DSSERR("can't get VDDS_DSI regulator\n"); | 4335 | DSSERR("can't get VDDS_DSI regulator\n"); |
3566 | return PTR_ERR(vdds_dsi); | 4336 | return PTR_ERR(vdds_dsi); |
3567 | } | 4337 | } |
3568 | 4338 | ||
3569 | dsi.vdds_dsi_reg = vdds_dsi; | 4339 | dsi->vdds_dsi_reg = vdds_dsi; |
4340 | } | ||
4341 | |||
4342 | if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) { | ||
4343 | DSSERR("DSI%d can't support more than %d data lanes\n", | ||
4344 | dsi_module + 1, dsi->num_data_lanes); | ||
4345 | return -EINVAL; | ||
3570 | } | 4346 | } |
3571 | 4347 | ||
3572 | return 0; | 4348 | return 0; |
@@ -3574,11 +4350,13 @@ int dsi_init_display(struct omap_dss_device *dssdev) | |||
3574 | 4350 | ||
3575 | int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel) | 4351 | int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel) |
3576 | { | 4352 | { |
4353 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4354 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3577 | int i; | 4355 | int i; |
3578 | 4356 | ||
3579 | for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { | 4357 | for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { |
3580 | if (!dsi.vc[i].dssdev) { | 4358 | if (!dsi->vc[i].dssdev) { |
3581 | dsi.vc[i].dssdev = dssdev; | 4359 | dsi->vc[i].dssdev = dssdev; |
3582 | *channel = i; | 4360 | *channel = i; |
3583 | return 0; | 4361 | return 0; |
3584 | } | 4362 | } |
@@ -3591,6 +4369,9 @@ EXPORT_SYMBOL(omap_dsi_request_vc); | |||
3591 | 4369 | ||
3592 | int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id) | 4370 | int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id) |
3593 | { | 4371 | { |
4372 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4373 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4374 | |||
3594 | if (vc_id < 0 || vc_id > 3) { | 4375 | if (vc_id < 0 || vc_id > 3) { |
3595 | DSSERR("VC ID out of range\n"); | 4376 | DSSERR("VC ID out of range\n"); |
3596 | return -EINVAL; | 4377 | return -EINVAL; |
@@ -3601,13 +4382,13 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id) | |||
3601 | return -EINVAL; | 4382 | return -EINVAL; |
3602 | } | 4383 | } |
3603 | 4384 | ||
3604 | if (dsi.vc[channel].dssdev != dssdev) { | 4385 | if (dsi->vc[channel].dssdev != dssdev) { |
3605 | DSSERR("Virtual Channel not allocated to display %s\n", | 4386 | DSSERR("Virtual Channel not allocated to display %s\n", |
3606 | dssdev->name); | 4387 | dssdev->name); |
3607 | return -EINVAL; | 4388 | return -EINVAL; |
3608 | } | 4389 | } |
3609 | 4390 | ||
3610 | dsi.vc[channel].vc_id = vc_id; | 4391 | dsi->vc[channel].vc_id = vc_id; |
3611 | 4392 | ||
3612 | return 0; | 4393 | return 0; |
3613 | } | 4394 | } |
@@ -3615,143 +4396,172 @@ EXPORT_SYMBOL(omap_dsi_set_vc_id); | |||
3615 | 4396 | ||
3616 | void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel) | 4397 | void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel) |
3617 | { | 4398 | { |
4399 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4400 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4401 | |||
3618 | if ((channel >= 0 && channel <= 3) && | 4402 | if ((channel >= 0 && channel <= 3) && |
3619 | dsi.vc[channel].dssdev == dssdev) { | 4403 | dsi->vc[channel].dssdev == dssdev) { |
3620 | dsi.vc[channel].dssdev = NULL; | 4404 | dsi->vc[channel].dssdev = NULL; |
3621 | dsi.vc[channel].vc_id = 0; | 4405 | dsi->vc[channel].vc_id = 0; |
3622 | } | 4406 | } |
3623 | } | 4407 | } |
3624 | EXPORT_SYMBOL(omap_dsi_release_vc); | 4408 | EXPORT_SYMBOL(omap_dsi_release_vc); |
3625 | 4409 | ||
3626 | void dsi_wait_pll_hsdiv_dispc_active(void) | 4410 | void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev) |
3627 | { | 4411 | { |
3628 | if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) | 4412 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 7, 1) != 1) |
3629 | DSSERR("%s (%s) not active\n", | 4413 | DSSERR("%s (%s) not active\n", |
3630 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), | 4414 | dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
3631 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)); | 4415 | dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)); |
3632 | } | 4416 | } |
3633 | 4417 | ||
3634 | void dsi_wait_pll_hsdiv_dsi_active(void) | 4418 | void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev) |
3635 | { | 4419 | { |
3636 | if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) | 4420 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 8, 1) != 1) |
3637 | DSSERR("%s (%s) not active\n", | 4421 | DSSERR("%s (%s) not active\n", |
3638 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | 4422 | dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), |
3639 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); | 4423 | dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); |
3640 | } | 4424 | } |
3641 | 4425 | ||
3642 | static void dsi_calc_clock_param_ranges(void) | 4426 | static void dsi_calc_clock_param_ranges(struct platform_device *dsidev) |
3643 | { | 4427 | { |
3644 | dsi.regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN); | 4428 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
3645 | dsi.regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM); | 4429 | |
3646 | dsi.regm_dispc_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC); | 4430 | dsi->regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN); |
3647 | dsi.regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI); | 4431 | dsi->regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM); |
3648 | dsi.fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT); | 4432 | dsi->regm_dispc_max = |
3649 | dsi.fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT); | 4433 | dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC); |
3650 | dsi.lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); | 4434 | dsi->regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI); |
4435 | dsi->fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT); | ||
4436 | dsi->fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT); | ||
4437 | dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); | ||
3651 | } | 4438 | } |
3652 | 4439 | ||
3653 | static int dsi_init(struct platform_device *pdev) | 4440 | static int dsi_init(struct platform_device *dsidev) |
3654 | { | 4441 | { |
4442 | struct omap_display_platform_data *dss_plat_data; | ||
4443 | struct omap_dss_board_info *board_info; | ||
3655 | u32 rev; | 4444 | u32 rev; |
3656 | int r, i; | 4445 | int r, i, dsi_module = dsi_get_dsidev_id(dsidev); |
3657 | struct resource *dsi_mem; | 4446 | struct resource *dsi_mem; |
4447 | struct dsi_data *dsi; | ||
4448 | |||
4449 | dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); | ||
4450 | if (!dsi) { | ||
4451 | r = -ENOMEM; | ||
4452 | goto err0; | ||
4453 | } | ||
4454 | |||
4455 | dsi->pdev = dsidev; | ||
4456 | dsi_pdev_map[dsi_module] = dsidev; | ||
4457 | dev_set_drvdata(&dsidev->dev, dsi); | ||
4458 | |||
4459 | dss_plat_data = dsidev->dev.platform_data; | ||
4460 | board_info = dss_plat_data->board_data; | ||
4461 | dsi->dsi_mux_pads = board_info->dsi_mux_pads; | ||
3658 | 4462 | ||
3659 | spin_lock_init(&dsi.irq_lock); | 4463 | spin_lock_init(&dsi->irq_lock); |
3660 | spin_lock_init(&dsi.errors_lock); | 4464 | spin_lock_init(&dsi->errors_lock); |
3661 | dsi.errors = 0; | 4465 | dsi->errors = 0; |
3662 | 4466 | ||
3663 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 4467 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
3664 | spin_lock_init(&dsi.irq_stats_lock); | 4468 | spin_lock_init(&dsi->irq_stats_lock); |
3665 | dsi.irq_stats.last_reset = jiffies; | 4469 | dsi->irq_stats.last_reset = jiffies; |
3666 | #endif | 4470 | #endif |
3667 | 4471 | ||
3668 | mutex_init(&dsi.lock); | 4472 | mutex_init(&dsi->lock); |
3669 | sema_init(&dsi.bus_lock, 1); | 4473 | sema_init(&dsi->bus_lock, 1); |
3670 | 4474 | ||
3671 | dsi.workqueue = create_singlethread_workqueue("dsi"); | 4475 | INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work, |
3672 | if (dsi.workqueue == NULL) | ||
3673 | return -ENOMEM; | ||
3674 | |||
3675 | INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work, | ||
3676 | dsi_framedone_timeout_work_callback); | 4476 | dsi_framedone_timeout_work_callback); |
3677 | 4477 | ||
3678 | #ifdef DSI_CATCH_MISSING_TE | 4478 | #ifdef DSI_CATCH_MISSING_TE |
3679 | init_timer(&dsi.te_timer); | 4479 | init_timer(&dsi->te_timer); |
3680 | dsi.te_timer.function = dsi_te_timeout; | 4480 | dsi->te_timer.function = dsi_te_timeout; |
3681 | dsi.te_timer.data = 0; | 4481 | dsi->te_timer.data = 0; |
3682 | #endif | 4482 | #endif |
3683 | dsi_mem = platform_get_resource(dsi.pdev, IORESOURCE_MEM, 0); | 4483 | dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0); |
3684 | if (!dsi_mem) { | 4484 | if (!dsi_mem) { |
3685 | DSSERR("can't get IORESOURCE_MEM DSI\n"); | 4485 | DSSERR("can't get IORESOURCE_MEM DSI\n"); |
3686 | r = -EINVAL; | 4486 | r = -EINVAL; |
3687 | goto err1; | 4487 | goto err1; |
3688 | } | 4488 | } |
3689 | dsi.base = ioremap(dsi_mem->start, resource_size(dsi_mem)); | 4489 | dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem)); |
3690 | if (!dsi.base) { | 4490 | if (!dsi->base) { |
3691 | DSSERR("can't ioremap DSI\n"); | 4491 | DSSERR("can't ioremap DSI\n"); |
3692 | r = -ENOMEM; | 4492 | r = -ENOMEM; |
3693 | goto err1; | 4493 | goto err1; |
3694 | } | 4494 | } |
3695 | dsi.irq = platform_get_irq(dsi.pdev, 0); | 4495 | dsi->irq = platform_get_irq(dsi->pdev, 0); |
3696 | if (dsi.irq < 0) { | 4496 | if (dsi->irq < 0) { |
3697 | DSSERR("platform_get_irq failed\n"); | 4497 | DSSERR("platform_get_irq failed\n"); |
3698 | r = -ENODEV; | 4498 | r = -ENODEV; |
3699 | goto err2; | 4499 | goto err2; |
3700 | } | 4500 | } |
3701 | 4501 | ||
3702 | r = request_irq(dsi.irq, omap_dsi_irq_handler, IRQF_SHARED, | 4502 | r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED, |
3703 | "OMAP DSI1", dsi.pdev); | 4503 | dev_name(&dsidev->dev), dsi->pdev); |
3704 | if (r < 0) { | 4504 | if (r < 0) { |
3705 | DSSERR("request_irq failed\n"); | 4505 | DSSERR("request_irq failed\n"); |
3706 | goto err2; | 4506 | goto err2; |
3707 | } | 4507 | } |
3708 | 4508 | ||
3709 | /* DSI VCs initialization */ | 4509 | /* DSI VCs initialization */ |
3710 | for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { | 4510 | for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { |
3711 | dsi.vc[i].mode = DSI_VC_MODE_L4; | 4511 | dsi->vc[i].mode = DSI_VC_MODE_L4; |
3712 | dsi.vc[i].dssdev = NULL; | 4512 | dsi->vc[i].dssdev = NULL; |
3713 | dsi.vc[i].vc_id = 0; | 4513 | dsi->vc[i].vc_id = 0; |
3714 | } | 4514 | } |
3715 | 4515 | ||
3716 | dsi_calc_clock_param_ranges(); | 4516 | dsi_calc_clock_param_ranges(dsidev); |
3717 | 4517 | ||
3718 | enable_clocks(1); | 4518 | enable_clocks(1); |
3719 | 4519 | ||
3720 | rev = dsi_read_reg(DSI_REVISION); | 4520 | rev = dsi_read_reg(dsidev, DSI_REVISION); |
3721 | dev_dbg(&pdev->dev, "OMAP DSI rev %d.%d\n", | 4521 | dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", |
3722 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 4522 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
3723 | 4523 | ||
4524 | dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); | ||
4525 | |||
3724 | enable_clocks(0); | 4526 | enable_clocks(0); |
3725 | 4527 | ||
3726 | return 0; | 4528 | return 0; |
3727 | err2: | 4529 | err2: |
3728 | iounmap(dsi.base); | 4530 | iounmap(dsi->base); |
3729 | err1: | 4531 | err1: |
3730 | destroy_workqueue(dsi.workqueue); | 4532 | kfree(dsi); |
4533 | err0: | ||
3731 | return r; | 4534 | return r; |
3732 | } | 4535 | } |
3733 | 4536 | ||
3734 | static void dsi_exit(void) | 4537 | static void dsi_exit(struct platform_device *dsidev) |
3735 | { | 4538 | { |
3736 | if (dsi.vdds_dsi_reg != NULL) { | 4539 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
3737 | regulator_put(dsi.vdds_dsi_reg); | 4540 | |
3738 | dsi.vdds_dsi_reg = NULL; | 4541 | if (dsi->vdds_dsi_reg != NULL) { |
4542 | if (dsi->vdds_dsi_enabled) { | ||
4543 | regulator_disable(dsi->vdds_dsi_reg); | ||
4544 | dsi->vdds_dsi_enabled = false; | ||
4545 | } | ||
4546 | |||
4547 | regulator_put(dsi->vdds_dsi_reg); | ||
4548 | dsi->vdds_dsi_reg = NULL; | ||
3739 | } | 4549 | } |
3740 | 4550 | ||
3741 | free_irq(dsi.irq, dsi.pdev); | 4551 | free_irq(dsi->irq, dsi->pdev); |
3742 | iounmap(dsi.base); | 4552 | iounmap(dsi->base); |
3743 | 4553 | ||
3744 | destroy_workqueue(dsi.workqueue); | 4554 | kfree(dsi); |
3745 | 4555 | ||
3746 | DSSDBG("omap_dsi_exit\n"); | 4556 | DSSDBG("omap_dsi_exit\n"); |
3747 | } | 4557 | } |
3748 | 4558 | ||
3749 | /* DSI1 HW IP initialisation */ | 4559 | /* DSI1 HW IP initialisation */ |
3750 | static int omap_dsi1hw_probe(struct platform_device *pdev) | 4560 | static int omap_dsi1hw_probe(struct platform_device *dsidev) |
3751 | { | 4561 | { |
3752 | int r; | 4562 | int r; |
3753 | dsi.pdev = pdev; | 4563 | |
3754 | r = dsi_init(pdev); | 4564 | r = dsi_init(dsidev); |
3755 | if (r) { | 4565 | if (r) { |
3756 | DSSERR("Failed to initialize DSI\n"); | 4566 | DSSERR("Failed to initialize DSI\n"); |
3757 | goto err_dsi; | 4567 | goto err_dsi; |
@@ -3760,9 +4570,12 @@ err_dsi: | |||
3760 | return r; | 4570 | return r; |
3761 | } | 4571 | } |
3762 | 4572 | ||
3763 | static int omap_dsi1hw_remove(struct platform_device *pdev) | 4573 | static int omap_dsi1hw_remove(struct platform_device *dsidev) |
3764 | { | 4574 | { |
3765 | dsi_exit(); | 4575 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4576 | |||
4577 | dsi_exit(dsidev); | ||
4578 | WARN_ON(dsi->scp_clk_refcount > 0); | ||
3766 | return 0; | 4579 | return 0; |
3767 | } | 4580 | } |
3768 | 4581 | ||
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 3f1fee63c678..d9489d5c4f08 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | 31 | ||
32 | #include <plat/display.h> | 32 | #include <video/omapdss.h> |
33 | #include <plat/clock.h> | 33 | #include <plat/clock.h> |
34 | #include "dss.h" | 34 | #include "dss.h" |
35 | #include "dss_features.h" | 35 | #include "dss_features.h" |
@@ -45,7 +45,6 @@ struct dss_reg { | |||
45 | #define DSS_REVISION DSS_REG(0x0000) | 45 | #define DSS_REVISION DSS_REG(0x0000) |
46 | #define DSS_SYSCONFIG DSS_REG(0x0010) | 46 | #define DSS_SYSCONFIG DSS_REG(0x0010) |
47 | #define DSS_SYSSTATUS DSS_REG(0x0014) | 47 | #define DSS_SYSSTATUS DSS_REG(0x0014) |
48 | #define DSS_IRQSTATUS DSS_REG(0x0018) | ||
49 | #define DSS_CONTROL DSS_REG(0x0040) | 48 | #define DSS_CONTROL DSS_REG(0x0040) |
50 | #define DSS_SDI_CONTROL DSS_REG(0x0044) | 49 | #define DSS_SDI_CONTROL DSS_REG(0x0044) |
51 | #define DSS_PLL_CONTROL DSS_REG(0x0048) | 50 | #define DSS_PLL_CONTROL DSS_REG(0x0048) |
@@ -75,17 +74,17 @@ static struct { | |||
75 | struct dss_clock_info cache_dss_cinfo; | 74 | struct dss_clock_info cache_dss_cinfo; |
76 | struct dispc_clock_info cache_dispc_cinfo; | 75 | struct dispc_clock_info cache_dispc_cinfo; |
77 | 76 | ||
78 | enum dss_clk_source dsi_clk_source; | 77 | enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI]; |
79 | enum dss_clk_source dispc_clk_source; | 78 | enum omap_dss_clk_source dispc_clk_source; |
80 | enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; | 79 | enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; |
81 | 80 | ||
82 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; | 81 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; |
83 | } dss; | 82 | } dss; |
84 | 83 | ||
85 | static const char * const dss_generic_clk_source_names[] = { | 84 | static const char * const dss_generic_clk_source_names[] = { |
86 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", | 85 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", |
87 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", | 86 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", |
88 | [DSS_CLK_SRC_FCK] = "DSS_FCK", | 87 | [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", |
89 | }; | 88 | }; |
90 | 89 | ||
91 | static void dss_clk_enable_all_no_ctx(void); | 90 | static void dss_clk_enable_all_no_ctx(void); |
@@ -230,7 +229,7 @@ void dss_sdi_disable(void) | |||
230 | REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ | 229 | REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ |
231 | } | 230 | } |
232 | 231 | ||
233 | const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src) | 232 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src) |
234 | { | 233 | { |
235 | return dss_generic_clk_source_names[clk_src]; | 234 | return dss_generic_clk_source_names[clk_src]; |
236 | } | 235 | } |
@@ -246,8 +245,8 @@ void dss_dump_clocks(struct seq_file *s) | |||
246 | 245 | ||
247 | seq_printf(s, "- DSS -\n"); | 246 | seq_printf(s, "- DSS -\n"); |
248 | 247 | ||
249 | fclk_name = dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK); | 248 | fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK); |
250 | fclk_real_name = dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK); | 249 | fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK); |
251 | fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); | 250 | fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); |
252 | 251 | ||
253 | if (dss.dpll4_m4_ck) { | 252 | if (dss.dpll4_m4_ck) { |
@@ -286,7 +285,6 @@ void dss_dump_regs(struct seq_file *s) | |||
286 | DUMPREG(DSS_REVISION); | 285 | DUMPREG(DSS_REVISION); |
287 | DUMPREG(DSS_SYSCONFIG); | 286 | DUMPREG(DSS_SYSCONFIG); |
288 | DUMPREG(DSS_SYSSTATUS); | 287 | DUMPREG(DSS_SYSSTATUS); |
289 | DUMPREG(DSS_IRQSTATUS); | ||
290 | DUMPREG(DSS_CONTROL); | 288 | DUMPREG(DSS_CONTROL); |
291 | 289 | ||
292 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & | 290 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & |
@@ -300,18 +298,25 @@ void dss_dump_regs(struct seq_file *s) | |||
300 | #undef DUMPREG | 298 | #undef DUMPREG |
301 | } | 299 | } |
302 | 300 | ||
303 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src) | 301 | void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) |
304 | { | 302 | { |
303 | struct platform_device *dsidev; | ||
305 | int b; | 304 | int b; |
306 | u8 start, end; | 305 | u8 start, end; |
307 | 306 | ||
308 | switch (clk_src) { | 307 | switch (clk_src) { |
309 | case DSS_CLK_SRC_FCK: | 308 | case OMAP_DSS_CLK_SRC_FCK: |
310 | b = 0; | 309 | b = 0; |
311 | break; | 310 | break; |
312 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | 311 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
313 | b = 1; | 312 | b = 1; |
314 | dsi_wait_pll_hsdiv_dispc_active(); | 313 | dsidev = dsi_get_dsidev_from_id(0); |
314 | dsi_wait_pll_hsdiv_dispc_active(dsidev); | ||
315 | break; | ||
316 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | ||
317 | b = 2; | ||
318 | dsidev = dsi_get_dsidev_from_id(1); | ||
319 | dsi_wait_pll_hsdiv_dispc_active(dsidev); | ||
315 | break; | 320 | break; |
316 | default: | 321 | default: |
317 | BUG(); | 322 | BUG(); |
@@ -324,17 +329,27 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src) | |||
324 | dss.dispc_clk_source = clk_src; | 329 | dss.dispc_clk_source = clk_src; |
325 | } | 330 | } |
326 | 331 | ||
327 | void dss_select_dsi_clk_source(enum dss_clk_source clk_src) | 332 | void dss_select_dsi_clk_source(int dsi_module, |
333 | enum omap_dss_clk_source clk_src) | ||
328 | { | 334 | { |
335 | struct platform_device *dsidev; | ||
329 | int b; | 336 | int b; |
330 | 337 | ||
331 | switch (clk_src) { | 338 | switch (clk_src) { |
332 | case DSS_CLK_SRC_FCK: | 339 | case OMAP_DSS_CLK_SRC_FCK: |
333 | b = 0; | 340 | b = 0; |
334 | break; | 341 | break; |
335 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: | 342 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: |
343 | BUG_ON(dsi_module != 0); | ||
344 | b = 1; | ||
345 | dsidev = dsi_get_dsidev_from_id(0); | ||
346 | dsi_wait_pll_hsdiv_dsi_active(dsidev); | ||
347 | break; | ||
348 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI: | ||
349 | BUG_ON(dsi_module != 1); | ||
336 | b = 1; | 350 | b = 1; |
337 | dsi_wait_pll_hsdiv_dsi_active(); | 351 | dsidev = dsi_get_dsidev_from_id(1); |
352 | dsi_wait_pll_hsdiv_dsi_active(dsidev); | ||
338 | break; | 353 | break; |
339 | default: | 354 | default: |
340 | BUG(); | 355 | BUG(); |
@@ -342,25 +357,33 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src) | |||
342 | 357 | ||
343 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ | 358 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ |
344 | 359 | ||
345 | dss.dsi_clk_source = clk_src; | 360 | dss.dsi_clk_source[dsi_module] = clk_src; |
346 | } | 361 | } |
347 | 362 | ||
348 | void dss_select_lcd_clk_source(enum omap_channel channel, | 363 | void dss_select_lcd_clk_source(enum omap_channel channel, |
349 | enum dss_clk_source clk_src) | 364 | enum omap_dss_clk_source clk_src) |
350 | { | 365 | { |
366 | struct platform_device *dsidev; | ||
351 | int b, ix, pos; | 367 | int b, ix, pos; |
352 | 368 | ||
353 | if (!dss_has_feature(FEAT_LCD_CLK_SRC)) | 369 | if (!dss_has_feature(FEAT_LCD_CLK_SRC)) |
354 | return; | 370 | return; |
355 | 371 | ||
356 | switch (clk_src) { | 372 | switch (clk_src) { |
357 | case DSS_CLK_SRC_FCK: | 373 | case OMAP_DSS_CLK_SRC_FCK: |
358 | b = 0; | 374 | b = 0; |
359 | break; | 375 | break; |
360 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | 376 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
361 | BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); | 377 | BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); |
362 | b = 1; | 378 | b = 1; |
363 | dsi_wait_pll_hsdiv_dispc_active(); | 379 | dsidev = dsi_get_dsidev_from_id(0); |
380 | dsi_wait_pll_hsdiv_dispc_active(dsidev); | ||
381 | break; | ||
382 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | ||
383 | BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2); | ||
384 | b = 1; | ||
385 | dsidev = dsi_get_dsidev_from_id(1); | ||
386 | dsi_wait_pll_hsdiv_dispc_active(dsidev); | ||
364 | break; | 387 | break; |
365 | default: | 388 | default: |
366 | BUG(); | 389 | BUG(); |
@@ -373,20 +396,26 @@ void dss_select_lcd_clk_source(enum omap_channel channel, | |||
373 | dss.lcd_clk_source[ix] = clk_src; | 396 | dss.lcd_clk_source[ix] = clk_src; |
374 | } | 397 | } |
375 | 398 | ||
376 | enum dss_clk_source dss_get_dispc_clk_source(void) | 399 | enum omap_dss_clk_source dss_get_dispc_clk_source(void) |
377 | { | 400 | { |
378 | return dss.dispc_clk_source; | 401 | return dss.dispc_clk_source; |
379 | } | 402 | } |
380 | 403 | ||
381 | enum dss_clk_source dss_get_dsi_clk_source(void) | 404 | enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module) |
382 | { | 405 | { |
383 | return dss.dsi_clk_source; | 406 | return dss.dsi_clk_source[dsi_module]; |
384 | } | 407 | } |
385 | 408 | ||
386 | enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) | 409 | enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) |
387 | { | 410 | { |
388 | int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; | 411 | if (dss_has_feature(FEAT_LCD_CLK_SRC)) { |
389 | return dss.lcd_clk_source[ix]; | 412 | int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; |
413 | return dss.lcd_clk_source[ix]; | ||
414 | } else { | ||
415 | /* LCD_CLK source is the same as DISPC_FCLK source for | ||
416 | * OMAP2 and OMAP3 */ | ||
417 | return dss.dispc_clk_source; | ||
418 | } | ||
390 | } | 419 | } |
391 | 420 | ||
392 | /* calculate clock rates using dividers in cinfo */ | 421 | /* calculate clock rates using dividers in cinfo */ |
@@ -659,13 +688,18 @@ static int dss_init(void) | |||
659 | * the kernel resets it */ | 688 | * the kernel resets it */ |
660 | omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); | 689 | omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); |
661 | 690 | ||
691 | #ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET | ||
662 | /* We need to wait here a bit, otherwise we sometimes start to | 692 | /* We need to wait here a bit, otherwise we sometimes start to |
663 | * get synclost errors, and after that only power cycle will | 693 | * get synclost errors, and after that only power cycle will |
664 | * restore DSS functionality. I have no idea why this happens. | 694 | * restore DSS functionality. I have no idea why this happens. |
665 | * And we have to wait _before_ resetting the DSS, but after | 695 | * And we have to wait _before_ resetting the DSS, but after |
666 | * enabling clocks. | 696 | * enabling clocks. |
697 | * | ||
698 | * This bug was at least present on OMAP3430. It's unknown | ||
699 | * if it happens on OMAP2 or OMAP3630. | ||
667 | */ | 700 | */ |
668 | msleep(50); | 701 | msleep(50); |
702 | #endif | ||
669 | 703 | ||
670 | _omap_dss_reset(); | 704 | _omap_dss_reset(); |
671 | 705 | ||
@@ -700,10 +734,11 @@ static int dss_init(void) | |||
700 | 734 | ||
701 | dss.dpll4_m4_ck = dpll4_m4_ck; | 735 | dss.dpll4_m4_ck = dpll4_m4_ck; |
702 | 736 | ||
703 | dss.dsi_clk_source = DSS_CLK_SRC_FCK; | 737 | dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; |
704 | dss.dispc_clk_source = DSS_CLK_SRC_FCK; | 738 | dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; |
705 | dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK; | 739 | dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; |
706 | dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK; | 740 | dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; |
741 | dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; | ||
707 | 742 | ||
708 | dss_save_context(); | 743 | dss_save_context(); |
709 | 744 | ||
@@ -1015,6 +1050,14 @@ static void core_dump_clocks(struct seq_file *s) | |||
1015 | dss.dss_video_fck | 1050 | dss.dss_video_fck |
1016 | }; | 1051 | }; |
1017 | 1052 | ||
1053 | const char *names[5] = { | ||
1054 | "ick", | ||
1055 | "fck", | ||
1056 | "sys_clk", | ||
1057 | "tv_fck", | ||
1058 | "video_fck" | ||
1059 | }; | ||
1060 | |||
1018 | seq_printf(s, "- CORE -\n"); | 1061 | seq_printf(s, "- CORE -\n"); |
1019 | 1062 | ||
1020 | seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); | 1063 | seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); |
@@ -1022,8 +1065,11 @@ static void core_dump_clocks(struct seq_file *s) | |||
1022 | for (i = 0; i < 5; i++) { | 1065 | for (i = 0; i < 5; i++) { |
1023 | if (!clocks[i]) | 1066 | if (!clocks[i]) |
1024 | continue; | 1067 | continue; |
1025 | seq_printf(s, "%-15s\t%lu\t%d\n", | 1068 | seq_printf(s, "%s (%s)%*s\t%lu\t%d\n", |
1069 | names[i], | ||
1026 | clocks[i]->name, | 1070 | clocks[i]->name, |
1071 | 24 - strlen(names[i]) - strlen(clocks[i]->name), | ||
1072 | "", | ||
1027 | clk_get_rate(clocks[i]), | 1073 | clk_get_rate(clocks[i]), |
1028 | clocks[i]->usecount); | 1074 | clocks[i]->usecount); |
1029 | } | 1075 | } |
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index c2f582bb19c0..8ab6d43329bb 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -117,15 +117,6 @@ enum dss_clock { | |||
117 | DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/ | 117 | DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/ |
118 | }; | 118 | }; |
119 | 119 | ||
120 | enum dss_clk_source { | ||
121 | DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK | ||
122 | * OMAP4: PLL1_CLK1 */ | ||
123 | DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK | ||
124 | * OMAP4: PLL1_CLK2 */ | ||
125 | DSS_CLK_SRC_FCK, /* OMAP2/3: DSS1_ALWON_FCLK | ||
126 | * OMAP4: DSS_FCLK */ | ||
127 | }; | ||
128 | |||
129 | enum dss_hdmi_venc_clk_source_select { | 120 | enum dss_hdmi_venc_clk_source_select { |
130 | DSS_VENC_TV_CLK = 0, | 121 | DSS_VENC_TV_CLK = 0, |
131 | DSS_HDMI_M_PCLK = 1, | 122 | DSS_HDMI_M_PCLK = 1, |
@@ -236,7 +227,7 @@ void dss_clk_enable(enum dss_clock clks); | |||
236 | void dss_clk_disable(enum dss_clock clks); | 227 | void dss_clk_disable(enum dss_clock clks); |
237 | unsigned long dss_clk_get_rate(enum dss_clock clk); | 228 | unsigned long dss_clk_get_rate(enum dss_clock clk); |
238 | int dss_need_ctx_restore(void); | 229 | int dss_need_ctx_restore(void); |
239 | const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src); | 230 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); |
240 | void dss_dump_clocks(struct seq_file *s); | 231 | void dss_dump_clocks(struct seq_file *s); |
241 | 232 | ||
242 | void dss_dump_regs(struct seq_file *s); | 233 | void dss_dump_regs(struct seq_file *s); |
@@ -248,13 +239,14 @@ void dss_sdi_init(u8 datapairs); | |||
248 | int dss_sdi_enable(void); | 239 | int dss_sdi_enable(void); |
249 | void dss_sdi_disable(void); | 240 | void dss_sdi_disable(void); |
250 | 241 | ||
251 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src); | 242 | void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src); |
252 | void dss_select_dsi_clk_source(enum dss_clk_source clk_src); | 243 | void dss_select_dsi_clk_source(int dsi_module, |
244 | enum omap_dss_clk_source clk_src); | ||
253 | void dss_select_lcd_clk_source(enum omap_channel channel, | 245 | void dss_select_lcd_clk_source(enum omap_channel channel, |
254 | enum dss_clk_source clk_src); | 246 | enum omap_dss_clk_source clk_src); |
255 | enum dss_clk_source dss_get_dispc_clk_source(void); | 247 | enum omap_dss_clk_source dss_get_dispc_clk_source(void); |
256 | enum dss_clk_source dss_get_dsi_clk_source(void); | 248 | enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module); |
257 | enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); | 249 | enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); |
258 | 250 | ||
259 | void dss_set_venc_output(enum omap_dss_venc_type type); | 251 | void dss_set_venc_output(enum omap_dss_venc_type type); |
260 | void dss_set_dac_pwrdn_bgz(bool enable); | 252 | void dss_set_dac_pwrdn_bgz(bool enable); |
@@ -284,31 +276,39 @@ static inline void sdi_exit(void) | |||
284 | 276 | ||
285 | /* DSI */ | 277 | /* DSI */ |
286 | #ifdef CONFIG_OMAP2_DSS_DSI | 278 | #ifdef CONFIG_OMAP2_DSS_DSI |
279 | |||
280 | struct dentry; | ||
281 | struct file_operations; | ||
282 | |||
287 | int dsi_init_platform_driver(void); | 283 | int dsi_init_platform_driver(void); |
288 | void dsi_uninit_platform_driver(void); | 284 | void dsi_uninit_platform_driver(void); |
289 | 285 | ||
290 | void dsi_dump_clocks(struct seq_file *s); | 286 | void dsi_dump_clocks(struct seq_file *s); |
291 | void dsi_dump_irqs(struct seq_file *s); | 287 | void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir, |
292 | void dsi_dump_regs(struct seq_file *s); | 288 | const struct file_operations *debug_fops); |
289 | void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, | ||
290 | const struct file_operations *debug_fops); | ||
293 | 291 | ||
294 | void dsi_save_context(void); | 292 | void dsi_save_context(void); |
295 | void dsi_restore_context(void); | 293 | void dsi_restore_context(void); |
296 | 294 | ||
297 | int dsi_init_display(struct omap_dss_device *display); | 295 | int dsi_init_display(struct omap_dss_device *display); |
298 | void dsi_irq_handler(void); | 296 | void dsi_irq_handler(void); |
299 | unsigned long dsi_get_pll_hsdiv_dispc_rate(void); | 297 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); |
300 | int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo); | 298 | int dsi_pll_set_clock_div(struct platform_device *dsidev, |
301 | int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, | 299 | struct dsi_clock_info *cinfo); |
302 | struct dsi_clock_info *cinfo, | 300 | int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft, |
301 | unsigned long req_pck, struct dsi_clock_info *cinfo, | ||
303 | struct dispc_clock_info *dispc_cinfo); | 302 | struct dispc_clock_info *dispc_cinfo); |
304 | int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | 303 | int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, |
305 | bool enable_hsdiv); | 304 | bool enable_hsdiv); |
306 | void dsi_pll_uninit(void); | 305 | void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); |
307 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, | 306 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, |
308 | u32 fifo_size, enum omap_burst_size *burst_size, | 307 | u32 fifo_size, enum omap_burst_size *burst_size, |
309 | u32 *fifo_low, u32 *fifo_high); | 308 | u32 *fifo_low, u32 *fifo_high); |
310 | void dsi_wait_pll_hsdiv_dispc_active(void); | 309 | void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev); |
311 | void dsi_wait_pll_hsdiv_dsi_active(void); | 310 | void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev); |
311 | struct platform_device *dsi_get_dsidev_from_id(int module); | ||
312 | #else | 312 | #else |
313 | static inline int dsi_init_platform_driver(void) | 313 | static inline int dsi_init_platform_driver(void) |
314 | { | 314 | { |
@@ -317,17 +317,47 @@ static inline int dsi_init_platform_driver(void) | |||
317 | static inline void dsi_uninit_platform_driver(void) | 317 | static inline void dsi_uninit_platform_driver(void) |
318 | { | 318 | { |
319 | } | 319 | } |
320 | static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(void) | 320 | static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) |
321 | { | 321 | { |
322 | WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); | 322 | WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); |
323 | return 0; | 323 | return 0; |
324 | } | 324 | } |
325 | static inline void dsi_wait_pll_hsdiv_dispc_active(void) | 325 | static inline int dsi_pll_set_clock_div(struct platform_device *dsidev, |
326 | struct dsi_clock_info *cinfo) | ||
327 | { | ||
328 | WARN("%s: DSI not compiled in\n", __func__); | ||
329 | return -ENODEV; | ||
330 | } | ||
331 | static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, | ||
332 | bool is_tft, unsigned long req_pck, | ||
333 | struct dsi_clock_info *dsi_cinfo, | ||
334 | struct dispc_clock_info *dispc_cinfo) | ||
335 | { | ||
336 | WARN("%s: DSI not compiled in\n", __func__); | ||
337 | return -ENODEV; | ||
338 | } | ||
339 | static inline int dsi_pll_init(struct platform_device *dsidev, | ||
340 | bool enable_hsclk, bool enable_hsdiv) | ||
326 | { | 341 | { |
342 | WARN("%s: DSI not compiled in\n", __func__); | ||
343 | return -ENODEV; | ||
327 | } | 344 | } |
328 | static inline void dsi_wait_pll_hsdiv_dsi_active(void) | 345 | static inline void dsi_pll_uninit(struct platform_device *dsidev, |
346 | bool disconnect_lanes) | ||
329 | { | 347 | { |
330 | } | 348 | } |
349 | static inline void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev) | ||
350 | { | ||
351 | } | ||
352 | static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev) | ||
353 | { | ||
354 | } | ||
355 | static inline struct platform_device *dsi_get_dsidev_from_id(int module) | ||
356 | { | ||
357 | WARN("%s: DSI not compiled in, returning platform device as NULL\n", | ||
358 | __func__); | ||
359 | return NULL; | ||
360 | } | ||
331 | #endif | 361 | #endif |
332 | 362 | ||
333 | /* DPI */ | 363 | /* DPI */ |
@@ -391,7 +421,8 @@ int dispc_setup_plane(enum omap_plane plane, | |||
391 | enum omap_dss_rotation_type rotation_type, | 421 | enum omap_dss_rotation_type rotation_type, |
392 | u8 rotation, bool mirror, | 422 | u8 rotation, bool mirror, |
393 | u8 global_alpha, u8 pre_mult_alpha, | 423 | u8 global_alpha, u8 pre_mult_alpha, |
394 | enum omap_channel channel); | 424 | enum omap_channel channel, |
425 | u32 puv_addr); | ||
395 | 426 | ||
396 | bool dispc_go_busy(enum omap_channel channel); | 427 | bool dispc_go_busy(enum omap_channel channel); |
397 | void dispc_go(enum omap_channel channel); | 428 | void dispc_go(enum omap_channel channel); |
@@ -485,13 +516,6 @@ void hdmi_panel_exit(void); | |||
485 | int rfbi_init_platform_driver(void); | 516 | int rfbi_init_platform_driver(void); |
486 | void rfbi_uninit_platform_driver(void); | 517 | void rfbi_uninit_platform_driver(void); |
487 | void rfbi_dump_regs(struct seq_file *s); | 518 | void rfbi_dump_regs(struct seq_file *s); |
488 | |||
489 | int rfbi_configure(int rfbi_module, int bpp, int lines); | ||
490 | void rfbi_enable_rfbi(bool enable); | ||
491 | void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, | ||
492 | u16 height, void (callback)(void *data), void *data); | ||
493 | void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); | ||
494 | unsigned long rfbi_get_max_tx_rate(void); | ||
495 | int rfbi_init_display(struct omap_dss_device *display); | 519 | int rfbi_init_display(struct omap_dss_device *display); |
496 | #else | 520 | #else |
497 | static inline int rfbi_init_platform_driver(void) | 521 | static inline int rfbi_init_platform_driver(void) |
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index aa1622241d0d..1c18888e5df3 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/err.h> | 22 | #include <linux/err.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | 24 | ||
25 | #include <plat/display.h> | 25 | #include <video/omapdss.h> |
26 | #include <plat/cpu.h> | 26 | #include <plat/cpu.h> |
27 | 27 | ||
28 | #include "dss.h" | 28 | #include "dss.h" |
@@ -52,7 +52,7 @@ struct omap_dss_features { | |||
52 | }; | 52 | }; |
53 | 53 | ||
54 | /* This struct is assigned to one of the below during initialization */ | 54 | /* This struct is assigned to one of the below during initialization */ |
55 | static struct omap_dss_features *omap_current_dss_features; | 55 | static const struct omap_dss_features *omap_current_dss_features; |
56 | 56 | ||
57 | static const struct dss_reg_field omap2_dss_reg_fields[] = { | 57 | static const struct dss_reg_field omap2_dss_reg_fields[] = { |
58 | [FEAT_REG_FIRHINC] = { 11, 0 }, | 58 | [FEAT_REG_FIRHINC] = { 11, 0 }, |
@@ -177,22 +177,55 @@ static const enum omap_color_mode omap3_dss_supported_color_modes[] = { | |||
177 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, | 177 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, |
178 | }; | 178 | }; |
179 | 179 | ||
180 | static const enum omap_color_mode omap4_dss_supported_color_modes[] = { | ||
181 | /* OMAP_DSS_GFX */ | ||
182 | OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | | ||
183 | OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 | | ||
184 | OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | | ||
185 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | | ||
186 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | | ||
187 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 | | ||
188 | OMAP_DSS_COLOR_ARGB16_1555, | ||
189 | |||
190 | /* OMAP_DSS_VIDEO1 */ | ||
191 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U | | ||
192 | OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 | | ||
193 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 | | ||
194 | OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U | | ||
195 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY | | ||
196 | OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | | ||
197 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | | ||
198 | OMAP_DSS_COLOR_RGBX32, | ||
199 | |||
200 | /* OMAP_DSS_VIDEO2 */ | ||
201 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U | | ||
202 | OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 | | ||
203 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 | | ||
204 | OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U | | ||
205 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY | | ||
206 | OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | | ||
207 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | | ||
208 | OMAP_DSS_COLOR_RGBX32, | ||
209 | }; | ||
210 | |||
180 | static const char * const omap2_dss_clk_source_names[] = { | 211 | static const char * const omap2_dss_clk_source_names[] = { |
181 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A", | 212 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A", |
182 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A", | 213 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A", |
183 | [DSS_CLK_SRC_FCK] = "DSS_FCLK1", | 214 | [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK1", |
184 | }; | 215 | }; |
185 | 216 | ||
186 | static const char * const omap3_dss_clk_source_names[] = { | 217 | static const char * const omap3_dss_clk_source_names[] = { |
187 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK", | 218 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK", |
188 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK", | 219 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK", |
189 | [DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK", | 220 | [OMAP_DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK", |
190 | }; | 221 | }; |
191 | 222 | ||
192 | static const char * const omap4_dss_clk_source_names[] = { | 223 | static const char * const omap4_dss_clk_source_names[] = { |
193 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1", | 224 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1", |
194 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2", | 225 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2", |
195 | [DSS_CLK_SRC_FCK] = "DSS_FCLK", | 226 | [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK", |
227 | [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "PLL2_CLK1", | ||
228 | [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2", | ||
196 | }; | 229 | }; |
197 | 230 | ||
198 | static const struct dss_param_range omap2_dss_param_range[] = { | 231 | static const struct dss_param_range omap2_dss_param_range[] = { |
@@ -226,7 +259,7 @@ static const struct dss_param_range omap4_dss_param_range[] = { | |||
226 | }; | 259 | }; |
227 | 260 | ||
228 | /* OMAP2 DSS Features */ | 261 | /* OMAP2 DSS Features */ |
229 | static struct omap_dss_features omap2_dss_features = { | 262 | static const struct omap_dss_features omap2_dss_features = { |
230 | .reg_fields = omap2_dss_reg_fields, | 263 | .reg_fields = omap2_dss_reg_fields, |
231 | .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields), | 264 | .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields), |
232 | 265 | ||
@@ -244,7 +277,7 @@ static struct omap_dss_features omap2_dss_features = { | |||
244 | }; | 277 | }; |
245 | 278 | ||
246 | /* OMAP3 DSS Features */ | 279 | /* OMAP3 DSS Features */ |
247 | static struct omap_dss_features omap3430_dss_features = { | 280 | static const struct omap_dss_features omap3430_dss_features = { |
248 | .reg_fields = omap3_dss_reg_fields, | 281 | .reg_fields = omap3_dss_reg_fields, |
249 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | 282 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), |
250 | 283 | ||
@@ -252,7 +285,8 @@ static struct omap_dss_features omap3430_dss_features = { | |||
252 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | 285 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | |
253 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | 286 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | |
254 | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | | 287 | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | |
255 | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF, | 288 | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | |
289 | FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC, | ||
256 | 290 | ||
257 | .num_mgrs = 2, | 291 | .num_mgrs = 2, |
258 | .num_ovls = 3, | 292 | .num_ovls = 3, |
@@ -262,7 +296,7 @@ static struct omap_dss_features omap3430_dss_features = { | |||
262 | .dss_params = omap3_dss_param_range, | 296 | .dss_params = omap3_dss_param_range, |
263 | }; | 297 | }; |
264 | 298 | ||
265 | static struct omap_dss_features omap3630_dss_features = { | 299 | static const struct omap_dss_features omap3630_dss_features = { |
266 | .reg_fields = omap3_dss_reg_fields, | 300 | .reg_fields = omap3_dss_reg_fields, |
267 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | 301 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), |
268 | 302 | ||
@@ -271,7 +305,8 @@ static struct omap_dss_features omap3630_dss_features = { | |||
271 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | 305 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | |
272 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | | 306 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | |
273 | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | | 307 | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | |
274 | FEAT_RESIZECONF, | 308 | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | |
309 | FEAT_DSI_PLL_FREQSEL, | ||
275 | 310 | ||
276 | .num_mgrs = 2, | 311 | .num_mgrs = 2, |
277 | .num_ovls = 3, | 312 | .num_ovls = 3, |
@@ -282,19 +317,43 @@ static struct omap_dss_features omap3630_dss_features = { | |||
282 | }; | 317 | }; |
283 | 318 | ||
284 | /* OMAP4 DSS Features */ | 319 | /* OMAP4 DSS Features */ |
285 | static struct omap_dss_features omap4_dss_features = { | 320 | /* For OMAP4430 ES 1.0 revision */ |
321 | static const struct omap_dss_features omap4430_es1_0_dss_features = { | ||
286 | .reg_fields = omap4_dss_reg_fields, | 322 | .reg_fields = omap4_dss_reg_fields, |
287 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), | 323 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), |
288 | 324 | ||
289 | .has_feature = | 325 | .has_feature = |
290 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | 326 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | |
291 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | | 327 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | |
292 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC, | 328 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | |
329 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | | ||
330 | FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2, | ||
293 | 331 | ||
294 | .num_mgrs = 3, | 332 | .num_mgrs = 3, |
295 | .num_ovls = 3, | 333 | .num_ovls = 3, |
296 | .supported_displays = omap4_dss_supported_displays, | 334 | .supported_displays = omap4_dss_supported_displays, |
297 | .supported_color_modes = omap3_dss_supported_color_modes, | 335 | .supported_color_modes = omap4_dss_supported_color_modes, |
336 | .clksrc_names = omap4_dss_clk_source_names, | ||
337 | .dss_params = omap4_dss_param_range, | ||
338 | }; | ||
339 | |||
340 | /* For all the other OMAP4 versions */ | ||
341 | static const struct omap_dss_features omap4_dss_features = { | ||
342 | .reg_fields = omap4_dss_reg_fields, | ||
343 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), | ||
344 | |||
345 | .has_feature = | ||
346 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | ||
347 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | | ||
348 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | | ||
349 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | | ||
350 | FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | | ||
351 | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2, | ||
352 | |||
353 | .num_mgrs = 3, | ||
354 | .num_ovls = 3, | ||
355 | .supported_displays = omap4_dss_supported_displays, | ||
356 | .supported_color_modes = omap4_dss_supported_color_modes, | ||
298 | .clksrc_names = omap4_dss_clk_source_names, | 357 | .clksrc_names = omap4_dss_clk_source_names, |
299 | .dss_params = omap4_dss_param_range, | 358 | .dss_params = omap4_dss_param_range, |
300 | }; | 359 | }; |
@@ -337,7 +396,7 @@ bool dss_feat_color_mode_supported(enum omap_plane plane, | |||
337 | color_mode; | 396 | color_mode; |
338 | } | 397 | } |
339 | 398 | ||
340 | const char *dss_feat_get_clk_source_name(enum dss_clk_source id) | 399 | const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id) |
341 | { | 400 | { |
342 | return omap_current_dss_features->clksrc_names[id]; | 401 | return omap_current_dss_features->clksrc_names[id]; |
343 | } | 402 | } |
@@ -365,6 +424,10 @@ void dss_features_init(void) | |||
365 | omap_current_dss_features = &omap3630_dss_features; | 424 | omap_current_dss_features = &omap3630_dss_features; |
366 | else if (cpu_is_omap34xx()) | 425 | else if (cpu_is_omap34xx()) |
367 | omap_current_dss_features = &omap3430_dss_features; | 426 | omap_current_dss_features = &omap3430_dss_features; |
368 | else | 427 | else if (omap_rev() == OMAP4430_REV_ES1_0) |
428 | omap_current_dss_features = &omap4430_es1_0_dss_features; | ||
429 | else if (cpu_is_omap44xx()) | ||
369 | omap_current_dss_features = &omap4_dss_features; | 430 | omap_current_dss_features = &omap4_dss_features; |
431 | else | ||
432 | DSSWARN("Unsupported OMAP version"); | ||
370 | } | 433 | } |
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 12e9c4ef0dec..07b346f7d916 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h | |||
@@ -23,23 +23,34 @@ | |||
23 | #define MAX_DSS_MANAGERS 3 | 23 | #define MAX_DSS_MANAGERS 3 |
24 | #define MAX_DSS_OVERLAYS 3 | 24 | #define MAX_DSS_OVERLAYS 3 |
25 | #define MAX_DSS_LCD_MANAGERS 2 | 25 | #define MAX_DSS_LCD_MANAGERS 2 |
26 | #define MAX_NUM_DSI 2 | ||
26 | 27 | ||
27 | /* DSS has feature id */ | 28 | /* DSS has feature id */ |
28 | enum dss_feat_id { | 29 | enum dss_feat_id { |
29 | FEAT_GLOBAL_ALPHA = 1 << 0, | 30 | FEAT_GLOBAL_ALPHA = 1 << 0, |
30 | FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, | 31 | FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, |
31 | FEAT_PRE_MULT_ALPHA = 1 << 2, | 32 | FEAT_PRE_MULT_ALPHA = 1 << 2, |
32 | FEAT_LCDENABLEPOL = 1 << 3, | 33 | FEAT_LCDENABLEPOL = 1 << 3, |
33 | FEAT_LCDENABLESIGNAL = 1 << 4, | 34 | FEAT_LCDENABLESIGNAL = 1 << 4, |
34 | FEAT_PCKFREEENABLE = 1 << 5, | 35 | FEAT_PCKFREEENABLE = 1 << 5, |
35 | FEAT_FUNCGATED = 1 << 6, | 36 | FEAT_FUNCGATED = 1 << 6, |
36 | FEAT_MGR_LCD2 = 1 << 7, | 37 | FEAT_MGR_LCD2 = 1 << 7, |
37 | FEAT_LINEBUFFERSPLIT = 1 << 8, | 38 | FEAT_LINEBUFFERSPLIT = 1 << 8, |
38 | FEAT_ROWREPEATENABLE = 1 << 9, | 39 | FEAT_ROWREPEATENABLE = 1 << 9, |
39 | FEAT_RESIZECONF = 1 << 10, | 40 | FEAT_RESIZECONF = 1 << 10, |
40 | /* Independent core clk divider */ | 41 | /* Independent core clk divider */ |
41 | FEAT_CORE_CLK_DIV = 1 << 11, | 42 | FEAT_CORE_CLK_DIV = 1 << 11, |
42 | FEAT_LCD_CLK_SRC = 1 << 12, | 43 | FEAT_LCD_CLK_SRC = 1 << 12, |
44 | /* DSI-PLL power command 0x3 is not working */ | ||
45 | FEAT_DSI_PLL_PWR_BUG = 1 << 13, | ||
46 | FEAT_DSI_PLL_FREQSEL = 1 << 14, | ||
47 | FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15, | ||
48 | FEAT_DSI_VC_OCP_WIDTH = 1 << 16, | ||
49 | FEAT_DSI_REVERSE_TXCLKESC = 1 << 17, | ||
50 | FEAT_DSI_GNQ = 1 << 18, | ||
51 | FEAT_HDMI_CTS_SWMODE = 1 << 19, | ||
52 | FEAT_HANDLE_UV_SEPARATE = 1 << 20, | ||
53 | FEAT_ATTR2 = 1 << 21, | ||
43 | }; | 54 | }; |
44 | 55 | ||
45 | /* DSS register field id */ | 56 | /* DSS register field id */ |
@@ -77,7 +88,7 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel | |||
77 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); | 88 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); |
78 | bool dss_feat_color_mode_supported(enum omap_plane plane, | 89 | bool dss_feat_color_mode_supported(enum omap_plane plane, |
79 | enum omap_color_mode color_mode); | 90 | enum omap_color_mode color_mode); |
80 | const char *dss_feat_get_clk_source_name(enum dss_clk_source id); | 91 | const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); |
81 | 92 | ||
82 | bool dss_has_feature(enum dss_feat_id id); | 93 | bool dss_has_feature(enum dss_feat_id id); |
83 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); | 94 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); |
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index a981def8099a..b0555f4f0a78 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c | |||
@@ -29,10 +29,16 @@ | |||
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
32 | #include <plat/display.h> | 32 | #include <video/omapdss.h> |
33 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
34 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
35 | #include <sound/soc.h> | ||
36 | #include <sound/pcm_params.h> | ||
37 | #endif | ||
33 | 38 | ||
34 | #include "dss.h" | 39 | #include "dss.h" |
35 | #include "hdmi.h" | 40 | #include "hdmi.h" |
41 | #include "dss_features.h" | ||
36 | 42 | ||
37 | static struct { | 43 | static struct { |
38 | struct mutex lock; | 44 | struct mutex lock; |
@@ -1052,25 +1058,26 @@ static void update_hdmi_timings(struct hdmi_config *cfg, | |||
1052 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; | 1058 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; |
1053 | } | 1059 | } |
1054 | 1060 | ||
1055 | static void hdmi_compute_pll(unsigned long clkin, int phy, | 1061 | static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, |
1056 | int n, struct hdmi_pll_info *pi) | 1062 | struct hdmi_pll_info *pi) |
1057 | { | 1063 | { |
1058 | unsigned long refclk; | 1064 | unsigned long clkin, refclk; |
1059 | u32 mf; | 1065 | u32 mf; |
1060 | 1066 | ||
1067 | clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000; | ||
1061 | /* | 1068 | /* |
1062 | * Input clock is predivided by N + 1 | 1069 | * Input clock is predivided by N + 1 |
1063 | * out put of which is reference clk | 1070 | * out put of which is reference clk |
1064 | */ | 1071 | */ |
1065 | refclk = clkin / (n + 1); | 1072 | pi->regn = dssdev->clocks.hdmi.regn; |
1066 | pi->regn = n; | 1073 | refclk = clkin / (pi->regn + 1); |
1067 | 1074 | ||
1068 | /* | 1075 | /* |
1069 | * multiplier is pixel_clk/ref_clk | 1076 | * multiplier is pixel_clk/ref_clk |
1070 | * Multiplying by 100 to avoid fractional part removal | 1077 | * Multiplying by 100 to avoid fractional part removal |
1071 | */ | 1078 | */ |
1072 | pi->regm = (phy * 100/(refclk))/100; | 1079 | pi->regm = (phy * 100 / (refclk)) / 100; |
1073 | pi->regm2 = 1; | 1080 | pi->regm2 = dssdev->clocks.hdmi.regm2; |
1074 | 1081 | ||
1075 | /* | 1082 | /* |
1076 | * fractional multiplier is remainder of the difference between | 1083 | * fractional multiplier is remainder of the difference between |
@@ -1078,14 +1085,14 @@ static void hdmi_compute_pll(unsigned long clkin, int phy, | |||
1078 | * multiplied by 2^18(262144) divided by the reference clock | 1085 | * multiplied by 2^18(262144) divided by the reference clock |
1079 | */ | 1086 | */ |
1080 | mf = (phy - pi->regm * refclk) * 262144; | 1087 | mf = (phy - pi->regm * refclk) * 262144; |
1081 | pi->regmf = mf/(refclk); | 1088 | pi->regmf = mf / (refclk); |
1082 | 1089 | ||
1083 | /* | 1090 | /* |
1084 | * Dcofreq should be set to 1 if required pixel clock | 1091 | * Dcofreq should be set to 1 if required pixel clock |
1085 | * is greater than 1000MHz | 1092 | * is greater than 1000MHz |
1086 | */ | 1093 | */ |
1087 | pi->dcofreq = phy > 1000 * 100; | 1094 | pi->dcofreq = phy > 1000 * 100; |
1088 | pi->regsd = ((pi->regm * clkin / 10) / ((n + 1) * 250) + 5) / 10; | 1095 | pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10; |
1089 | 1096 | ||
1090 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); | 1097 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); |
1091 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); | 1098 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); |
@@ -1106,7 +1113,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1106 | int r, code = 0; | 1113 | int r, code = 0; |
1107 | struct hdmi_pll_info pll_data; | 1114 | struct hdmi_pll_info pll_data; |
1108 | struct omap_video_timings *p; | 1115 | struct omap_video_timings *p; |
1109 | int clkin, n, phy; | 1116 | unsigned long phy; |
1110 | 1117 | ||
1111 | hdmi_enable_clocks(1); | 1118 | hdmi_enable_clocks(1); |
1112 | 1119 | ||
@@ -1126,11 +1133,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1126 | dssdev->panel.timings = cea_vesa_timings[code].timings; | 1133 | dssdev->panel.timings = cea_vesa_timings[code].timings; |
1127 | update_hdmi_timings(&hdmi.cfg, p, code); | 1134 | update_hdmi_timings(&hdmi.cfg, p, code); |
1128 | 1135 | ||
1129 | clkin = 3840; /* 38.4 MHz */ | ||
1130 | n = 15; /* this is a constant for our math */ | ||
1131 | phy = p->pixel_clock; | 1136 | phy = p->pixel_clock; |
1132 | 1137 | ||
1133 | hdmi_compute_pll(clkin, phy, n, &pll_data); | 1138 | hdmi_compute_pll(dssdev, phy, &pll_data); |
1134 | 1139 | ||
1135 | hdmi_wp_video_start(0); | 1140 | hdmi_wp_video_start(0); |
1136 | 1141 | ||
@@ -1160,7 +1165,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1160 | * dynamically by user. This can be moved to single location , say | 1165 | * dynamically by user. This can be moved to single location , say |
1161 | * Boardfile. | 1166 | * Boardfile. |
1162 | */ | 1167 | */ |
1163 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); | 1168 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
1164 | 1169 | ||
1165 | /* bypass TV gamma table */ | 1170 | /* bypass TV gamma table */ |
1166 | dispc_enable_gamma_table(0); | 1171 | dispc_enable_gamma_table(0); |
@@ -1275,10 +1280,420 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | |||
1275 | mutex_unlock(&hdmi.lock); | 1280 | mutex_unlock(&hdmi.lock); |
1276 | } | 1281 | } |
1277 | 1282 | ||
1283 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1284 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1285 | static 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 | |||
1304 | static 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 | |||
1321 | static 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 | |||
1391 | static 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 | |||
1432 | checksum = 0x100 - sum; | ||
1433 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum); | ||
1434 | |||
1435 | /* | ||
1436 | * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing | ||
1437 | * is available. | ||
1438 | */ | ||
1439 | } | ||
1440 | |||
1441 | static 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 | |||
1497 | static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | ||
1498 | struct snd_pcm_hw_params *params, | ||
1499 | struct snd_soc_dai *dai) | ||
1500 | { | ||
1501 | struct hdmi_audio_format audio_format; | ||
1502 | struct hdmi_audio_dma audio_dma; | ||
1503 | struct hdmi_core_audio_config core_cfg; | ||
1504 | struct hdmi_core_infoframe_audio aud_if_cfg; | ||
1505 | int err, n, cts; | ||
1506 | enum hdmi_core_audio_sample_freq sample_freq; | ||
1507 | |||
1508 | switch (params_format(params)) { | ||
1509 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1510 | core_cfg.i2s_cfg.word_max_length = | ||
1511 | HDMI_AUDIO_I2S_MAX_WORD_20BITS; | ||
1512 | core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_16_BITS; | ||
1513 | core_cfg.i2s_cfg.in_length_bits = | ||
1514 | HDMI_AUDIO_I2S_INPUT_LENGTH_16; | ||
1515 | core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT; | ||
1516 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES; | ||
1517 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS; | ||
1518 | audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT; | ||
1519 | audio_dma.transfer_size = 0x10; | ||
1520 | break; | ||
1521 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1522 | core_cfg.i2s_cfg.word_max_length = | ||
1523 | HDMI_AUDIO_I2S_MAX_WORD_24BITS; | ||
1524 | core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_24_BITS; | ||
1525 | core_cfg.i2s_cfg.in_length_bits = | ||
1526 | HDMI_AUDIO_I2S_INPUT_LENGTH_24; | ||
1527 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE; | ||
1528 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS; | ||
1529 | audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT; | ||
1530 | core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT; | ||
1531 | audio_dma.transfer_size = 0x20; | ||
1532 | break; | ||
1533 | default: | ||
1534 | return -EINVAL; | ||
1535 | } | ||
1536 | |||
1537 | switch (params_rate(params)) { | ||
1538 | case 32000: | ||
1539 | sample_freq = HDMI_AUDIO_FS_32000; | ||
1540 | break; | ||
1541 | case 44100: | ||
1542 | sample_freq = HDMI_AUDIO_FS_44100; | ||
1543 | break; | ||
1544 | case 48000: | ||
1545 | sample_freq = HDMI_AUDIO_FS_48000; | ||
1546 | break; | ||
1547 | default: | ||
1548 | return -EINVAL; | ||
1549 | } | ||
1550 | |||
1551 | err = hdmi_config_audio_acr(params_rate(params), &n, &cts); | ||
1552 | if (err < 0) | ||
1553 | return err; | ||
1554 | |||
1555 | /* Audio wrapper config */ | ||
1556 | audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; | ||
1557 | audio_format.active_chnnls_msk = 0x03; | ||
1558 | audio_format.type = HDMI_AUDIO_TYPE_LPCM; | ||
1559 | audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST; | ||
1560 | /* Disable start/stop signals of IEC 60958 blocks */ | ||
1561 | audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF; | ||
1562 | |||
1563 | audio_dma.block_size = 0xC0; | ||
1564 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; | ||
1565 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ | ||
1566 | |||
1567 | hdmi_wp_audio_config_dma(&audio_dma); | ||
1568 | hdmi_wp_audio_config_format(&audio_format); | ||
1569 | |||
1570 | /* | ||
1571 | * I2S config | ||
1572 | */ | ||
1573 | core_cfg.i2s_cfg.en_high_bitrate_aud = false; | ||
1574 | /* Only used with high bitrate audio */ | ||
1575 | core_cfg.i2s_cfg.cbit_order = false; | ||
1576 | /* Serial data and word select should change on sck rising edge */ | ||
1577 | core_cfg.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING; | ||
1578 | core_cfg.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM; | ||
1579 | /* Set I2S word select polarity */ | ||
1580 | core_cfg.i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT; | ||
1581 | core_cfg.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST; | ||
1582 | /* Set serial data to word select shift. See Phillips spec. */ | ||
1583 | core_cfg.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT; | ||
1584 | /* Enable one of the four available serial data channels */ | ||
1585 | core_cfg.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN; | ||
1586 | |||
1587 | /* Core audio config */ | ||
1588 | core_cfg.freq_sample = sample_freq; | ||
1589 | core_cfg.n = n; | ||
1590 | core_cfg.cts = cts; | ||
1591 | if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { | ||
1592 | core_cfg.aud_par_busclk = 0; | ||
1593 | core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW; | ||
1594 | core_cfg.use_mclk = false; | ||
1595 | } else { | ||
1596 | core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8); | ||
1597 | core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW; | ||
1598 | core_cfg.use_mclk = true; | ||
1599 | core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS; | ||
1600 | } | ||
1601 | core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH; | ||
1602 | core_cfg.en_spdif = false; | ||
1603 | /* Use sample frequency from channel status word */ | ||
1604 | core_cfg.fs_override = true; | ||
1605 | /* Enable ACR packets */ | ||
1606 | core_cfg.en_acr_pkt = true; | ||
1607 | /* Disable direct streaming digital audio */ | ||
1608 | core_cfg.en_dsd_audio = false; | ||
1609 | /* Use parallel audio interface */ | ||
1610 | core_cfg.en_parallel_aud_input = true; | ||
1611 | |||
1612 | hdmi_core_audio_config(&core_cfg); | ||
1613 | |||
1614 | /* | ||
1615 | * Configure packet | ||
1616 | * info frame audio see doc CEA861-D page 74 | ||
1617 | */ | ||
1618 | aud_if_cfg.db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM; | ||
1619 | aud_if_cfg.db1_channel_count = 2; | ||
1620 | aud_if_cfg.db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM; | ||
1621 | aud_if_cfg.db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM; | ||
1622 | aud_if_cfg.db4_channel_alloc = 0x00; | ||
1623 | aud_if_cfg.db5_downmix_inh = false; | ||
1624 | aud_if_cfg.db5_lsv = 0; | ||
1625 | |||
1626 | hdmi_core_audio_infoframe_config(&aud_if_cfg); | ||
1627 | return 0; | ||
1628 | } | ||
1629 | |||
1630 | static 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 | |||
1656 | static int hdmi_audio_startup(struct snd_pcm_substream *substream, | ||
1657 | struct snd_soc_dai *dai) | ||
1658 | { | ||
1659 | if (!hdmi.mode) { | ||
1660 | pr_err("Current video settings do not support audio.\n"); | ||
1661 | return -EIO; | ||
1662 | } | ||
1663 | return 0; | ||
1664 | } | ||
1665 | |||
1666 | static struct snd_soc_codec_driver hdmi_audio_codec_drv = { | ||
1667 | }; | ||
1668 | |||
1669 | static struct snd_soc_dai_ops hdmi_audio_codec_ops = { | ||
1670 | .hw_params = hdmi_audio_hw_params, | ||
1671 | .trigger = hdmi_audio_trigger, | ||
1672 | .startup = hdmi_audio_startup, | ||
1673 | }; | ||
1674 | |||
1675 | static struct snd_soc_dai_driver hdmi_codec_dai_drv = { | ||
1676 | .name = "hdmi-audio-codec", | ||
1677 | .playback = { | ||
1678 | .channels_min = 2, | ||
1679 | .channels_max = 2, | ||
1680 | .rates = SNDRV_PCM_RATE_32000 | | ||
1681 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, | ||
1682 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
1683 | SNDRV_PCM_FMTBIT_S24_LE, | ||
1684 | }, | ||
1685 | .ops = &hdmi_audio_codec_ops, | ||
1686 | }; | ||
1687 | #endif | ||
1688 | |||
1278 | /* HDMI HW IP initialisation */ | 1689 | /* HDMI HW IP initialisation */ |
1279 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | 1690 | static int omapdss_hdmihw_probe(struct platform_device *pdev) |
1280 | { | 1691 | { |
1281 | struct resource *hdmi_mem; | 1692 | struct resource *hdmi_mem; |
1693 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1694 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1695 | int ret; | ||
1696 | #endif | ||
1282 | 1697 | ||
1283 | hdmi.pdata = pdev->dev.platform_data; | 1698 | hdmi.pdata = pdev->dev.platform_data; |
1284 | hdmi.pdev = pdev; | 1699 | hdmi.pdev = pdev; |
@@ -1300,6 +1715,17 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) | |||
1300 | 1715 | ||
1301 | hdmi_panel_init(); | 1716 | hdmi_panel_init(); |
1302 | 1717 | ||
1718 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1719 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1720 | |||
1721 | /* Register ASoC codec DAI */ | ||
1722 | ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv, | ||
1723 | &hdmi_codec_dai_drv, 1); | ||
1724 | if (ret) { | ||
1725 | DSSERR("can't register ASoC HDMI audio codec\n"); | ||
1726 | return ret; | ||
1727 | } | ||
1728 | #endif | ||
1303 | return 0; | 1729 | return 0; |
1304 | } | 1730 | } |
1305 | 1731 | ||
@@ -1307,6 +1733,11 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev) | |||
1307 | { | 1733 | { |
1308 | hdmi_panel_exit(); | 1734 | hdmi_panel_exit(); |
1309 | 1735 | ||
1736 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1737 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1738 | snd_soc_unregister_codec(&pdev->dev); | ||
1739 | #endif | ||
1740 | |||
1310 | iounmap(hdmi.base_wp); | 1741 | iounmap(hdmi.base_wp); |
1311 | 1742 | ||
1312 | return 0; | 1743 | return 0; |
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h index 9887ab96da3c..c885f9cb0659 100644 --- a/drivers/video/omap2/dss/hdmi.h +++ b/drivers/video/omap2/dss/hdmi.h | |||
@@ -22,7 +22,7 @@ | |||
22 | #define _OMAP4_DSS_HDMI_H_ | 22 | #define _OMAP4_DSS_HDMI_H_ |
23 | 23 | ||
24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
25 | #include <plat/display.h> | 25 | #include <video/omapdss.h> |
26 | 26 | ||
27 | #define HDMI_WP 0x0 | 27 | #define HDMI_WP 0x0 |
28 | #define HDMI_CORE_SYS 0x400 | 28 | #define HDMI_CORE_SYS 0x400 |
@@ -48,6 +48,10 @@ struct hdmi_reg { u16 idx; }; | |||
48 | #define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68) | 48 | #define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68) |
49 | #define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C) | 49 | #define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C) |
50 | #define HDMI_WP_WP_CLK HDMI_WP_REG(0x70) | 50 | #define HDMI_WP_WP_CLK HDMI_WP_REG(0x70) |
51 | #define HDMI_WP_AUDIO_CFG HDMI_WP_REG(0x80) | ||
52 | #define HDMI_WP_AUDIO_CFG2 HDMI_WP_REG(0x84) | ||
53 | #define HDMI_WP_AUDIO_CTRL HDMI_WP_REG(0x88) | ||
54 | #define HDMI_WP_AUDIO_DATA HDMI_WP_REG(0x8C) | ||
51 | 55 | ||
52 | /* HDMI IP Core System */ | 56 | /* HDMI IP Core System */ |
53 | #define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx) | 57 | #define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx) |
@@ -105,6 +109,8 @@ struct hdmi_reg { u16 idx; }; | |||
105 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15) | 109 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15) |
106 | #define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190) | 110 | #define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190) |
107 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | 111 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27) |
112 | #define HDMI_CORE_AV_AUD_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x210) | ||
113 | #define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_CORE_AV_REG(10) | ||
108 | #define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290) | 114 | #define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290) |
109 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | 115 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27) |
110 | #define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300) | 116 | #define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300) |
@@ -153,6 +159,10 @@ struct hdmi_reg { u16 idx; }; | |||
153 | #define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184) | 159 | #define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184) |
154 | #define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188) | 160 | #define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188) |
155 | #define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C) | 161 | #define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C) |
162 | #define HDMI_CORE_AV_AUDIO_TYPE HDMI_CORE_AV_REG(0x200) | ||
163 | #define HDMI_CORE_AV_AUDIO_VERS HDMI_CORE_AV_REG(0x204) | ||
164 | #define HDMI_CORE_AV_AUDIO_LEN HDMI_CORE_AV_REG(0x208) | ||
165 | #define HDMI_CORE_AV_AUDIO_CHSUM HDMI_CORE_AV_REG(0x20C) | ||
156 | #define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280) | 166 | #define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280) |
157 | #define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284) | 167 | #define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284) |
158 | #define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288) | 168 | #define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288) |
@@ -272,7 +282,7 @@ enum hdmi_core_packet_ctrl { | |||
272 | HDMI_PACKETREPEATOFF = 0 | 282 | HDMI_PACKETREPEATOFF = 0 |
273 | }; | 283 | }; |
274 | 284 | ||
275 | /* INFOFRAME_AVI_ definitions */ | 285 | /* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */ |
276 | enum hdmi_core_infoframe { | 286 | enum hdmi_core_infoframe { |
277 | HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, | 287 | HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, |
278 | HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, | 288 | HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, |
@@ -317,7 +327,36 @@ enum hdmi_core_infoframe { | |||
317 | HDMI_INFOFRAME_AVI_DB5PR_7 = 6, | 327 | HDMI_INFOFRAME_AVI_DB5PR_7 = 6, |
318 | HDMI_INFOFRAME_AVI_DB5PR_8 = 7, | 328 | HDMI_INFOFRAME_AVI_DB5PR_8 = 7, |
319 | HDMI_INFOFRAME_AVI_DB5PR_9 = 8, | 329 | HDMI_INFOFRAME_AVI_DB5PR_9 = 8, |
320 | HDMI_INFOFRAME_AVI_DB5PR_10 = 9 | 330 | HDMI_INFOFRAME_AVI_DB5PR_10 = 9, |
331 | HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM = 0, | ||
332 | HDMI_INFOFRAME_AUDIO_DB1CT_IEC60958 = 1, | ||
333 | HDMI_INFOFRAME_AUDIO_DB1CT_AC3 = 2, | ||
334 | HDMI_INFOFRAME_AUDIO_DB1CT_MPEG1 = 3, | ||
335 | HDMI_INFOFRAME_AUDIO_DB1CT_MP3 = 4, | ||
336 | HDMI_INFOFRAME_AUDIO_DB1CT_MPEG2_MULTICH = 5, | ||
337 | HDMI_INFOFRAME_AUDIO_DB1CT_AAC = 6, | ||
338 | HDMI_INFOFRAME_AUDIO_DB1CT_DTS = 7, | ||
339 | HDMI_INFOFRAME_AUDIO_DB1CT_ATRAC = 8, | ||
340 | HDMI_INFOFRAME_AUDIO_DB1CT_ONEBIT = 9, | ||
341 | HDMI_INFOFRAME_AUDIO_DB1CT_DOLBY_DIGITAL_PLUS = 10, | ||
342 | HDMI_INFOFRAME_AUDIO_DB1CT_DTS_HD = 11, | ||
343 | HDMI_INFOFRAME_AUDIO_DB1CT_MAT = 12, | ||
344 | HDMI_INFOFRAME_AUDIO_DB1CT_DST = 13, | ||
345 | HDMI_INFOFRAME_AUDIO_DB1CT_WMA_PRO = 14, | ||
346 | HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM = 0, | ||
347 | HDMI_INFOFRAME_AUDIO_DB2SF_32000 = 1, | ||
348 | HDMI_INFOFRAME_AUDIO_DB2SF_44100 = 2, | ||
349 | HDMI_INFOFRAME_AUDIO_DB2SF_48000 = 3, | ||
350 | HDMI_INFOFRAME_AUDIO_DB2SF_88200 = 4, | ||
351 | HDMI_INFOFRAME_AUDIO_DB2SF_96000 = 5, | ||
352 | HDMI_INFOFRAME_AUDIO_DB2SF_176400 = 6, | ||
353 | HDMI_INFOFRAME_AUDIO_DB2SF_192000 = 7, | ||
354 | HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM = 0, | ||
355 | HDMI_INFOFRAME_AUDIO_DB2SS_16BIT = 1, | ||
356 | HDMI_INFOFRAME_AUDIO_DB2SS_20BIT = 2, | ||
357 | HDMI_INFOFRAME_AUDIO_DB2SS_24BIT = 3, | ||
358 | HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PERMITTED = 0, | ||
359 | HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PROHIBITED = 1 | ||
321 | }; | 360 | }; |
322 | 361 | ||
323 | enum hdmi_packing_mode { | 362 | enum hdmi_packing_mode { |
@@ -327,6 +366,121 @@ enum hdmi_packing_mode { | |||
327 | HDMI_PACK_ALREADYPACKED = 7 | 366 | HDMI_PACK_ALREADYPACKED = 7 |
328 | }; | 367 | }; |
329 | 368 | ||
369 | enum hdmi_core_audio_sample_freq { | ||
370 | HDMI_AUDIO_FS_32000 = 0x3, | ||
371 | HDMI_AUDIO_FS_44100 = 0x0, | ||
372 | HDMI_AUDIO_FS_48000 = 0x2, | ||
373 | HDMI_AUDIO_FS_88200 = 0x8, | ||
374 | HDMI_AUDIO_FS_96000 = 0xA, | ||
375 | HDMI_AUDIO_FS_176400 = 0xC, | ||
376 | HDMI_AUDIO_FS_192000 = 0xE, | ||
377 | HDMI_AUDIO_FS_NOT_INDICATED = 0x1 | ||
378 | }; | ||
379 | |||
380 | enum hdmi_core_audio_layout { | ||
381 | HDMI_AUDIO_LAYOUT_2CH = 0, | ||
382 | HDMI_AUDIO_LAYOUT_8CH = 1 | ||
383 | }; | ||
384 | |||
385 | enum hdmi_core_cts_mode { | ||
386 | HDMI_AUDIO_CTS_MODE_HW = 0, | ||
387 | HDMI_AUDIO_CTS_MODE_SW = 1 | ||
388 | }; | ||
389 | |||
390 | enum hdmi_stereo_channels { | ||
391 | HDMI_AUDIO_STEREO_NOCHANNELS = 0, | ||
392 | HDMI_AUDIO_STEREO_ONECHANNEL = 1, | ||
393 | HDMI_AUDIO_STEREO_TWOCHANNELS = 2, | ||
394 | HDMI_AUDIO_STEREO_THREECHANNELS = 3, | ||
395 | HDMI_AUDIO_STEREO_FOURCHANNELS = 4 | ||
396 | }; | ||
397 | |||
398 | enum hdmi_audio_type { | ||
399 | HDMI_AUDIO_TYPE_LPCM = 0, | ||
400 | HDMI_AUDIO_TYPE_IEC = 1 | ||
401 | }; | ||
402 | |||
403 | enum hdmi_audio_justify { | ||
404 | HDMI_AUDIO_JUSTIFY_LEFT = 0, | ||
405 | HDMI_AUDIO_JUSTIFY_RIGHT = 1 | ||
406 | }; | ||
407 | |||
408 | enum hdmi_audio_sample_order { | ||
409 | HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0, | ||
410 | HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1 | ||
411 | }; | ||
412 | |||
413 | enum hdmi_audio_samples_perword { | ||
414 | HDMI_AUDIO_ONEWORD_ONESAMPLE = 0, | ||
415 | HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1 | ||
416 | }; | ||
417 | |||
418 | enum hdmi_audio_sample_size { | ||
419 | HDMI_AUDIO_SAMPLE_16BITS = 0, | ||
420 | HDMI_AUDIO_SAMPLE_24BITS = 1 | ||
421 | }; | ||
422 | |||
423 | enum hdmi_audio_transf_mode { | ||
424 | HDMI_AUDIO_TRANSF_DMA = 0, | ||
425 | HDMI_AUDIO_TRANSF_IRQ = 1 | ||
426 | }; | ||
427 | |||
428 | enum hdmi_audio_blk_strt_end_sig { | ||
429 | HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0, | ||
430 | HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1 | ||
431 | }; | ||
432 | |||
433 | enum hdmi_audio_i2s_config { | ||
434 | HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT = 0, | ||
435 | HDMI_AUDIO_I2S_WS_POLARIT_YLOW_IS_RIGHT = 1, | ||
436 | HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0, | ||
437 | HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1, | ||
438 | HDMI_AUDIO_I2S_MAX_WORD_20BITS = 0, | ||
439 | HDMI_AUDIO_I2S_MAX_WORD_24BITS = 1, | ||
440 | HDMI_AUDIO_I2S_CHST_WORD_NOT_SPECIFIED = 0, | ||
441 | HDMI_AUDIO_I2S_CHST_WORD_16_BITS = 1, | ||
442 | HDMI_AUDIO_I2S_CHST_WORD_17_BITS = 6, | ||
443 | HDMI_AUDIO_I2S_CHST_WORD_18_BITS = 2, | ||
444 | HDMI_AUDIO_I2S_CHST_WORD_19_BITS = 4, | ||
445 | HDMI_AUDIO_I2S_CHST_WORD_20_BITS_20MAX = 5, | ||
446 | HDMI_AUDIO_I2S_CHST_WORD_20_BITS_24MAX = 1, | ||
447 | HDMI_AUDIO_I2S_CHST_WORD_21_BITS = 6, | ||
448 | HDMI_AUDIO_I2S_CHST_WORD_22_BITS = 2, | ||
449 | HDMI_AUDIO_I2S_CHST_WORD_23_BITS = 4, | ||
450 | HDMI_AUDIO_I2S_CHST_WORD_24_BITS = 5, | ||
451 | HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0, | ||
452 | HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1, | ||
453 | HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0, | ||
454 | HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1, | ||
455 | HDMI_AUDIO_I2S_INPUT_LENGTH_NA = 0, | ||
456 | HDMI_AUDIO_I2S_INPUT_LENGTH_16 = 2, | ||
457 | HDMI_AUDIO_I2S_INPUT_LENGTH_17 = 12, | ||
458 | HDMI_AUDIO_I2S_INPUT_LENGTH_18 = 4, | ||
459 | HDMI_AUDIO_I2S_INPUT_LENGTH_19 = 8, | ||
460 | HDMI_AUDIO_I2S_INPUT_LENGTH_20 = 10, | ||
461 | HDMI_AUDIO_I2S_INPUT_LENGTH_21 = 13, | ||
462 | HDMI_AUDIO_I2S_INPUT_LENGTH_22 = 5, | ||
463 | HDMI_AUDIO_I2S_INPUT_LENGTH_23 = 9, | ||
464 | HDMI_AUDIO_I2S_INPUT_LENGTH_24 = 11, | ||
465 | HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0, | ||
466 | HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1, | ||
467 | HDMI_AUDIO_I2S_SD0_EN = 1, | ||
468 | HDMI_AUDIO_I2S_SD1_EN = 1 << 1, | ||
469 | HDMI_AUDIO_I2S_SD2_EN = 1 << 2, | ||
470 | HDMI_AUDIO_I2S_SD3_EN = 1 << 3, | ||
471 | }; | ||
472 | |||
473 | enum hdmi_audio_mclk_mode { | ||
474 | HDMI_AUDIO_MCLK_128FS = 0, | ||
475 | HDMI_AUDIO_MCLK_256FS = 1, | ||
476 | HDMI_AUDIO_MCLK_384FS = 2, | ||
477 | HDMI_AUDIO_MCLK_512FS = 3, | ||
478 | HDMI_AUDIO_MCLK_768FS = 4, | ||
479 | HDMI_AUDIO_MCLK_1024FS = 5, | ||
480 | HDMI_AUDIO_MCLK_1152FS = 6, | ||
481 | HDMI_AUDIO_MCLK_192FS = 7 | ||
482 | }; | ||
483 | |||
330 | struct hdmi_core_video_config { | 484 | struct hdmi_core_video_config { |
331 | enum hdmi_core_inputbus_width ip_bus_width; | 485 | enum hdmi_core_inputbus_width ip_bus_width; |
332 | enum hdmi_core_dither_trunc op_dither_truc; | 486 | enum hdmi_core_dither_trunc op_dither_truc; |
@@ -376,6 +530,19 @@ struct hdmi_core_infoframe_avi { | |||
376 | u16 db12_13_pixel_sofright; | 530 | u16 db12_13_pixel_sofright; |
377 | /* Pixel number start of right bar */ | 531 | /* Pixel number start of right bar */ |
378 | }; | 532 | }; |
533 | /* | ||
534 | * Refer to section 8.2 in HDMI 1.3 specification for | ||
535 | * details about infoframe databytes | ||
536 | */ | ||
537 | struct hdmi_core_infoframe_audio { | ||
538 | u8 db1_coding_type; | ||
539 | u8 db1_channel_count; | ||
540 | u8 db2_sample_freq; | ||
541 | u8 db2_sample_size; | ||
542 | u8 db4_channel_alloc; | ||
543 | bool db5_downmix_inh; | ||
544 | u8 db5_lsv; /* Level shift values for downmix */ | ||
545 | }; | ||
379 | 546 | ||
380 | struct hdmi_core_packet_enable_repeat { | 547 | struct hdmi_core_packet_enable_repeat { |
381 | u32 audio_pkt; | 548 | u32 audio_pkt; |
@@ -412,4 +579,53 @@ struct hdmi_config { | |||
412 | struct hdmi_cm cm; | 579 | struct hdmi_cm cm; |
413 | }; | 580 | }; |
414 | 581 | ||
582 | struct hdmi_audio_format { | ||
583 | enum hdmi_stereo_channels stereo_channels; | ||
584 | u8 active_chnnls_msk; | ||
585 | enum hdmi_audio_type type; | ||
586 | enum hdmi_audio_justify justification; | ||
587 | enum hdmi_audio_sample_order sample_order; | ||
588 | enum hdmi_audio_samples_perword samples_per_word; | ||
589 | enum hdmi_audio_sample_size sample_size; | ||
590 | enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end; | ||
591 | }; | ||
592 | |||
593 | struct hdmi_audio_dma { | ||
594 | u8 transfer_size; | ||
595 | u8 block_size; | ||
596 | enum hdmi_audio_transf_mode mode; | ||
597 | u16 fifo_threshold; | ||
598 | }; | ||
599 | |||
600 | struct hdmi_core_audio_i2s_config { | ||
601 | u8 word_max_length; | ||
602 | u8 word_length; | ||
603 | u8 in_length_bits; | ||
604 | u8 justification; | ||
605 | u8 en_high_bitrate_aud; | ||
606 | u8 sck_edge_mode; | ||
607 | u8 cbit_order; | ||
608 | u8 vbit; | ||
609 | u8 ws_polarity; | ||
610 | u8 direction; | ||
611 | u8 shift; | ||
612 | u8 active_sds; | ||
613 | }; | ||
614 | |||
615 | struct hdmi_core_audio_config { | ||
616 | struct hdmi_core_audio_i2s_config i2s_cfg; | ||
617 | enum hdmi_core_audio_sample_freq freq_sample; | ||
618 | bool fs_override; | ||
619 | u32 n; | ||
620 | u32 cts; | ||
621 | u32 aud_par_busclk; | ||
622 | enum hdmi_core_audio_layout layout; | ||
623 | enum hdmi_core_cts_mode cts_mode; | ||
624 | bool use_mclk; | ||
625 | enum hdmi_audio_mclk_mode mclk_mode; | ||
626 | bool en_acr_pkt; | ||
627 | bool en_dsd_audio; | ||
628 | bool en_parallel_aud_input; | ||
629 | bool en_spdif; | ||
630 | }; | ||
415 | #endif | 631 | #endif |
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c index ffb5de94131f..7d4f2bd7c506 100644 --- a/drivers/video/omap2/dss/hdmi_omap4_panel.c +++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <plat/display.h> | 27 | #include <video/omapdss.h> |
28 | 28 | ||
29 | #include "dss.h" | 29 | #include "dss.h" |
30 | 30 | ||
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index bcd37ec86952..9aeea50e33ff 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
30 | #include <linux/jiffies.h> | 30 | #include <linux/jiffies.h> |
31 | 31 | ||
32 | #include <plat/display.h> | 32 | #include <video/omapdss.h> |
33 | #include <plat/cpu.h> | 33 | #include <plat/cpu.h> |
34 | 34 | ||
35 | #include "dss.h" | 35 | #include "dss.h" |
@@ -393,6 +393,7 @@ struct overlay_cache_data { | |||
393 | 393 | ||
394 | u32 paddr; | 394 | u32 paddr; |
395 | void __iomem *vaddr; | 395 | void __iomem *vaddr; |
396 | u32 p_uv_addr; /* relevant for NV12 format only */ | ||
396 | u16 screen_width; | 397 | u16 screen_width; |
397 | u16 width; | 398 | u16 width; |
398 | u16 height; | 399 | u16 height; |
@@ -775,10 +776,17 @@ static int configure_overlay(enum omap_plane plane) | |||
775 | } | 776 | } |
776 | 777 | ||
777 | switch (c->color_mode) { | 778 | switch (c->color_mode) { |
779 | case OMAP_DSS_COLOR_NV12: | ||
780 | bpp = 8; | ||
781 | break; | ||
778 | case OMAP_DSS_COLOR_RGB16: | 782 | case OMAP_DSS_COLOR_RGB16: |
779 | case OMAP_DSS_COLOR_ARGB16: | 783 | case OMAP_DSS_COLOR_ARGB16: |
780 | case OMAP_DSS_COLOR_YUV2: | 784 | case OMAP_DSS_COLOR_YUV2: |
781 | case OMAP_DSS_COLOR_UYVY: | 785 | case OMAP_DSS_COLOR_UYVY: |
786 | case OMAP_DSS_COLOR_RGBA16: | ||
787 | case OMAP_DSS_COLOR_RGBX16: | ||
788 | case OMAP_DSS_COLOR_ARGB16_1555: | ||
789 | case OMAP_DSS_COLOR_XRGB16_1555: | ||
782 | bpp = 16; | 790 | bpp = 16; |
783 | break; | 791 | break; |
784 | 792 | ||
@@ -854,7 +862,8 @@ static int configure_overlay(enum omap_plane plane) | |||
854 | c->mirror, | 862 | c->mirror, |
855 | c->global_alpha, | 863 | c->global_alpha, |
856 | c->pre_mult_alpha, | 864 | c->pre_mult_alpha, |
857 | c->channel); | 865 | c->channel, |
866 | c->p_uv_addr); | ||
858 | 867 | ||
859 | if (r) { | 868 | if (r) { |
860 | /* this shouldn't happen */ | 869 | /* this shouldn't happen */ |
@@ -1269,6 +1278,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1269 | 1278 | ||
1270 | oc->paddr = ovl->info.paddr; | 1279 | oc->paddr = ovl->info.paddr; |
1271 | oc->vaddr = ovl->info.vaddr; | 1280 | oc->vaddr = ovl->info.vaddr; |
1281 | oc->p_uv_addr = ovl->info.p_uv_addr; | ||
1272 | oc->screen_width = ovl->info.screen_width; | 1282 | oc->screen_width = ovl->info.screen_width; |
1273 | oc->width = ovl->info.width; | 1283 | oc->width = ovl->info.width; |
1274 | oc->height = ovl->info.height; | 1284 | oc->height = ovl->info.height; |
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index f1aca6d04011..0f08025b1f0e 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | 33 | ||
34 | #include <plat/display.h> | 34 | #include <video/omapdss.h> |
35 | #include <plat/cpu.h> | 35 | #include <plat/cpu.h> |
36 | 36 | ||
37 | #include "dss.h" | 37 | #include "dss.h" |
@@ -201,12 +201,16 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) | |||
201 | static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, | 201 | static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, |
202 | size_t size) | 202 | size_t size) |
203 | { | 203 | { |
204 | int r; | 204 | int r, enable; |
205 | struct omap_overlay_info info; | 205 | struct omap_overlay_info info; |
206 | 206 | ||
207 | ovl->get_overlay_info(ovl, &info); | 207 | ovl->get_overlay_info(ovl, &info); |
208 | 208 | ||
209 | info.enabled = simple_strtoul(buf, NULL, 10); | 209 | r = kstrtoint(buf, 0, &enable); |
210 | if (r) | ||
211 | return r; | ||
212 | |||
213 | info.enabled = !!enable; | ||
210 | 214 | ||
211 | r = ovl->set_overlay_info(ovl, &info); | 215 | r = ovl->set_overlay_info(ovl, &info); |
212 | if (r) | 216 | if (r) |
@@ -231,8 +235,13 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, | |||
231 | const char *buf, size_t size) | 235 | const char *buf, size_t size) |
232 | { | 236 | { |
233 | int r; | 237 | int r; |
238 | u8 alpha; | ||
234 | struct omap_overlay_info info; | 239 | struct omap_overlay_info info; |
235 | 240 | ||
241 | r = kstrtou8(buf, 0, &alpha); | ||
242 | if (r) | ||
243 | return r; | ||
244 | |||
236 | ovl->get_overlay_info(ovl, &info); | 245 | ovl->get_overlay_info(ovl, &info); |
237 | 246 | ||
238 | /* Video1 plane does not support global alpha | 247 | /* Video1 plane does not support global alpha |
@@ -242,7 +251,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, | |||
242 | ovl->id == OMAP_DSS_VIDEO1) | 251 | ovl->id == OMAP_DSS_VIDEO1) |
243 | info.global_alpha = 255; | 252 | info.global_alpha = 255; |
244 | else | 253 | else |
245 | info.global_alpha = simple_strtoul(buf, NULL, 10); | 254 | info.global_alpha = alpha; |
246 | 255 | ||
247 | r = ovl->set_overlay_info(ovl, &info); | 256 | r = ovl->set_overlay_info(ovl, &info); |
248 | if (r) | 257 | if (r) |
@@ -268,8 +277,13 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, | |||
268 | const char *buf, size_t size) | 277 | const char *buf, size_t size) |
269 | { | 278 | { |
270 | int r; | 279 | int r; |
280 | u8 alpha; | ||
271 | struct omap_overlay_info info; | 281 | struct omap_overlay_info info; |
272 | 282 | ||
283 | r = kstrtou8(buf, 0, &alpha); | ||
284 | if (r) | ||
285 | return r; | ||
286 | |||
273 | ovl->get_overlay_info(ovl, &info); | 287 | ovl->get_overlay_info(ovl, &info); |
274 | 288 | ||
275 | /* only GFX and Video2 plane support pre alpha multiplied | 289 | /* only GFX and Video2 plane support pre alpha multiplied |
@@ -279,7 +293,7 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, | |||
279 | ovl->id == OMAP_DSS_VIDEO1) | 293 | ovl->id == OMAP_DSS_VIDEO1) |
280 | info.pre_mult_alpha = 0; | 294 | info.pre_mult_alpha = 0; |
281 | else | 295 | else |
282 | info.pre_mult_alpha = simple_strtoul(buf, NULL, 10); | 296 | info.pre_mult_alpha = alpha; |
283 | 297 | ||
284 | r = ovl->set_overlay_info(ovl, &info); | 298 | r = ovl->set_overlay_info(ovl, &info); |
285 | if (r) | 299 | if (r) |
@@ -491,13 +505,18 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, | |||
491 | ovl->manager = mgr; | 505 | ovl->manager = mgr; |
492 | 506 | ||
493 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); | 507 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
494 | /* XXX: on manual update display, in auto update mode, a bug happens | 508 | /* XXX: When there is an overlay on a DSI manual update display, and |
495 | * here. When an overlay is first enabled on LCD, then it's disabled, | 509 | * the overlay is first disabled, then moved to tv, and enabled, we |
496 | * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT | 510 | * seem to get SYNC_LOST_DIGIT error. |
497 | * errors. Waiting before changing the channel_out fixes it. I'm | 511 | * |
498 | * guessing that the overlay is still somehow being used for the LCD, | 512 | * Waiting doesn't seem to help, but updating the manual update display |
499 | * but I don't understand how or why. */ | 513 | * after disabling the overlay seems to fix this. This hints that the |
500 | msleep(40); | 514 | * overlay is perhaps somehow tied to the LCD output until the output |
515 | * is updated. | ||
516 | * | ||
517 | * Userspace workaround for this is to update the LCD after disabling | ||
518 | * the overlay, but before moving the overlay to TV. | ||
519 | */ | ||
501 | dispc_set_channel_out(ovl->id, mgr->id); | 520 | dispc_set_channel_out(ovl->id, mgr->id); |
502 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | 521 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
503 | 522 | ||
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 5ea17f49c611..c06fbe0bc678 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
@@ -32,8 +32,9 @@ | |||
32 | #include <linux/ktime.h> | 32 | #include <linux/ktime.h> |
33 | #include <linux/hrtimer.h> | 33 | #include <linux/hrtimer.h> |
34 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
35 | #include <linux/semaphore.h> | ||
35 | 36 | ||
36 | #include <plat/display.h> | 37 | #include <video/omapdss.h> |
37 | #include "dss.h" | 38 | #include "dss.h" |
38 | 39 | ||
39 | struct rfbi_reg { u16 idx; }; | 40 | struct rfbi_reg { u16 idx; }; |
@@ -65,9 +66,6 @@ struct rfbi_reg { u16 idx; }; | |||
65 | #define REG_FLD_MOD(idx, val, start, end) \ | 66 | #define REG_FLD_MOD(idx, val, start, end) \ |
66 | rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) | 67 | rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) |
67 | 68 | ||
68 | /* To work around an RFBI transfer rate limitation */ | ||
69 | #define OMAP_RFBI_RATE_LIMIT 1 | ||
70 | |||
71 | enum omap_rfbi_cycleformat { | 69 | enum omap_rfbi_cycleformat { |
72 | OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0, | 70 | OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0, |
73 | OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1, | 71 | OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1, |
@@ -89,11 +87,6 @@ enum omap_rfbi_parallelmode { | |||
89 | OMAP_DSS_RFBI_PARALLELMODE_16 = 3, | 87 | OMAP_DSS_RFBI_PARALLELMODE_16 = 3, |
90 | }; | 88 | }; |
91 | 89 | ||
92 | enum update_cmd { | ||
93 | RFBI_CMD_UPDATE = 0, | ||
94 | RFBI_CMD_SYNC = 1, | ||
95 | }; | ||
96 | |||
97 | static int rfbi_convert_timings(struct rfbi_timings *t); | 90 | static int rfbi_convert_timings(struct rfbi_timings *t); |
98 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); | 91 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); |
99 | 92 | ||
@@ -114,20 +107,9 @@ static struct { | |||
114 | 107 | ||
115 | struct omap_dss_device *dssdev[2]; | 108 | struct omap_dss_device *dssdev[2]; |
116 | 109 | ||
117 | struct kfifo cmd_fifo; | 110 | struct semaphore bus_lock; |
118 | spinlock_t cmd_lock; | ||
119 | struct completion cmd_done; | ||
120 | atomic_t cmd_fifo_full; | ||
121 | atomic_t cmd_pending; | ||
122 | } rfbi; | 111 | } rfbi; |
123 | 112 | ||
124 | struct update_region { | ||
125 | u16 x; | ||
126 | u16 y; | ||
127 | u16 w; | ||
128 | u16 h; | ||
129 | }; | ||
130 | |||
131 | static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) | 113 | static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) |
132 | { | 114 | { |
133 | __raw_writel(val, rfbi.base + idx.idx); | 115 | __raw_writel(val, rfbi.base + idx.idx); |
@@ -146,9 +128,20 @@ static void rfbi_enable_clocks(bool enable) | |||
146 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | 128 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
147 | } | 129 | } |
148 | 130 | ||
131 | void rfbi_bus_lock(void) | ||
132 | { | ||
133 | down(&rfbi.bus_lock); | ||
134 | } | ||
135 | EXPORT_SYMBOL(rfbi_bus_lock); | ||
136 | |||
137 | void rfbi_bus_unlock(void) | ||
138 | { | ||
139 | up(&rfbi.bus_lock); | ||
140 | } | ||
141 | EXPORT_SYMBOL(rfbi_bus_unlock); | ||
142 | |||
149 | void omap_rfbi_write_command(const void *buf, u32 len) | 143 | void omap_rfbi_write_command(const void *buf, u32 len) |
150 | { | 144 | { |
151 | rfbi_enable_clocks(1); | ||
152 | switch (rfbi.parallelmode) { | 145 | switch (rfbi.parallelmode) { |
153 | case OMAP_DSS_RFBI_PARALLELMODE_8: | 146 | case OMAP_DSS_RFBI_PARALLELMODE_8: |
154 | { | 147 | { |
@@ -172,13 +165,11 @@ void omap_rfbi_write_command(const void *buf, u32 len) | |||
172 | default: | 165 | default: |
173 | BUG(); | 166 | BUG(); |
174 | } | 167 | } |
175 | rfbi_enable_clocks(0); | ||
176 | } | 168 | } |
177 | EXPORT_SYMBOL(omap_rfbi_write_command); | 169 | EXPORT_SYMBOL(omap_rfbi_write_command); |
178 | 170 | ||
179 | void omap_rfbi_read_data(void *buf, u32 len) | 171 | void omap_rfbi_read_data(void *buf, u32 len) |
180 | { | 172 | { |
181 | rfbi_enable_clocks(1); | ||
182 | switch (rfbi.parallelmode) { | 173 | switch (rfbi.parallelmode) { |
183 | case OMAP_DSS_RFBI_PARALLELMODE_8: | 174 | case OMAP_DSS_RFBI_PARALLELMODE_8: |
184 | { | 175 | { |
@@ -206,13 +197,11 @@ void omap_rfbi_read_data(void *buf, u32 len) | |||
206 | default: | 197 | default: |
207 | BUG(); | 198 | BUG(); |
208 | } | 199 | } |
209 | rfbi_enable_clocks(0); | ||
210 | } | 200 | } |
211 | EXPORT_SYMBOL(omap_rfbi_read_data); | 201 | EXPORT_SYMBOL(omap_rfbi_read_data); |
212 | 202 | ||
213 | void omap_rfbi_write_data(const void *buf, u32 len) | 203 | void omap_rfbi_write_data(const void *buf, u32 len) |
214 | { | 204 | { |
215 | rfbi_enable_clocks(1); | ||
216 | switch (rfbi.parallelmode) { | 205 | switch (rfbi.parallelmode) { |
217 | case OMAP_DSS_RFBI_PARALLELMODE_8: | 206 | case OMAP_DSS_RFBI_PARALLELMODE_8: |
218 | { | 207 | { |
@@ -237,7 +226,6 @@ void omap_rfbi_write_data(const void *buf, u32 len) | |||
237 | BUG(); | 226 | BUG(); |
238 | 227 | ||
239 | } | 228 | } |
240 | rfbi_enable_clocks(0); | ||
241 | } | 229 | } |
242 | EXPORT_SYMBOL(omap_rfbi_write_data); | 230 | EXPORT_SYMBOL(omap_rfbi_write_data); |
243 | 231 | ||
@@ -249,8 +237,6 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, | |||
249 | int horiz_offset = scr_width - w; | 237 | int horiz_offset = scr_width - w; |
250 | int i; | 238 | int i; |
251 | 239 | ||
252 | rfbi_enable_clocks(1); | ||
253 | |||
254 | if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && | 240 | if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && |
255 | rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { | 241 | rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { |
256 | const u16 __iomem *pd = buf; | 242 | const u16 __iomem *pd = buf; |
@@ -295,12 +281,10 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, | |||
295 | } else { | 281 | } else { |
296 | BUG(); | 282 | BUG(); |
297 | } | 283 | } |
298 | |||
299 | rfbi_enable_clocks(0); | ||
300 | } | 284 | } |
301 | EXPORT_SYMBOL(omap_rfbi_write_pixels); | 285 | EXPORT_SYMBOL(omap_rfbi_write_pixels); |
302 | 286 | ||
303 | void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, | 287 | static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, |
304 | u16 height, void (*callback)(void *data), void *data) | 288 | u16 height, void (*callback)(void *data), void *data) |
305 | { | 289 | { |
306 | u32 l; | 290 | u32 l; |
@@ -317,8 +301,6 @@ void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, | |||
317 | rfbi.framedone_callback = callback; | 301 | rfbi.framedone_callback = callback; |
318 | rfbi.framedone_callback_data = data; | 302 | rfbi.framedone_callback_data = data; |
319 | 303 | ||
320 | rfbi_enable_clocks(1); | ||
321 | |||
322 | rfbi_write_reg(RFBI_PIXEL_CNT, width * height); | 304 | rfbi_write_reg(RFBI_PIXEL_CNT, width * height); |
323 | 305 | ||
324 | l = rfbi_read_reg(RFBI_CONTROL); | 306 | l = rfbi_read_reg(RFBI_CONTROL); |
@@ -337,15 +319,11 @@ static void framedone_callback(void *data, u32 mask) | |||
337 | 319 | ||
338 | REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); | 320 | REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); |
339 | 321 | ||
340 | rfbi_enable_clocks(0); | ||
341 | |||
342 | callback = rfbi.framedone_callback; | 322 | callback = rfbi.framedone_callback; |
343 | rfbi.framedone_callback = NULL; | 323 | rfbi.framedone_callback = NULL; |
344 | 324 | ||
345 | if (callback != NULL) | 325 | if (callback != NULL) |
346 | callback(rfbi.framedone_callback_data); | 326 | callback(rfbi.framedone_callback_data); |
347 | |||
348 | atomic_set(&rfbi.cmd_pending, 0); | ||
349 | } | 327 | } |
350 | 328 | ||
351 | #if 1 /* VERBOSE */ | 329 | #if 1 /* VERBOSE */ |
@@ -435,7 +413,7 @@ static int calc_extif_timings(struct rfbi_timings *t) | |||
435 | } | 413 | } |
436 | 414 | ||
437 | 415 | ||
438 | void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) | 416 | static void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) |
439 | { | 417 | { |
440 | int r; | 418 | int r; |
441 | 419 | ||
@@ -447,7 +425,6 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) | |||
447 | 425 | ||
448 | BUG_ON(!t->converted); | 426 | BUG_ON(!t->converted); |
449 | 427 | ||
450 | rfbi_enable_clocks(1); | ||
451 | rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]); | 428 | rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]); |
452 | rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]); | 429 | rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]); |
453 | 430 | ||
@@ -456,7 +433,6 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) | |||
456 | (t->tim[2] ? 1 : 0), 4, 4); | 433 | (t->tim[2] ? 1 : 0), 4, 4); |
457 | 434 | ||
458 | rfbi_print_timings(); | 435 | rfbi_print_timings(); |
459 | rfbi_enable_clocks(0); | ||
460 | } | 436 | } |
461 | 437 | ||
462 | static int ps_to_rfbi_ticks(int time, int div) | 438 | static int ps_to_rfbi_ticks(int time, int div) |
@@ -472,59 +448,6 @@ static int ps_to_rfbi_ticks(int time, int div) | |||
472 | return ret; | 448 | return ret; |
473 | } | 449 | } |
474 | 450 | ||
475 | #ifdef OMAP_RFBI_RATE_LIMIT | ||
476 | unsigned long rfbi_get_max_tx_rate(void) | ||
477 | { | ||
478 | unsigned long l4_rate, dss1_rate; | ||
479 | int min_l4_ticks = 0; | ||
480 | int i; | ||
481 | |||
482 | /* According to TI this can't be calculated so make the | ||
483 | * adjustments for a couple of known frequencies and warn for | ||
484 | * others. | ||
485 | */ | ||
486 | static const struct { | ||
487 | unsigned long l4_clk; /* HZ */ | ||
488 | unsigned long dss1_clk; /* HZ */ | ||
489 | unsigned long min_l4_ticks; | ||
490 | } ftab[] = { | ||
491 | { 55, 132, 7, }, /* 7.86 MPix/s */ | ||
492 | { 110, 110, 12, }, /* 9.16 MPix/s */ | ||
493 | { 110, 132, 10, }, /* 11 Mpix/s */ | ||
494 | { 120, 120, 10, }, /* 12 Mpix/s */ | ||
495 | { 133, 133, 10, }, /* 13.3 Mpix/s */ | ||
496 | }; | ||
497 | |||
498 | l4_rate = rfbi.l4_khz / 1000; | ||
499 | dss1_rate = dss_clk_get_rate(DSS_CLK_FCK) / 1000000; | ||
500 | |||
501 | for (i = 0; i < ARRAY_SIZE(ftab); i++) { | ||
502 | /* Use a window instead of an exact match, to account | ||
503 | * for different DPLL multiplier / divider pairs. | ||
504 | */ | ||
505 | if (abs(ftab[i].l4_clk - l4_rate) < 3 && | ||
506 | abs(ftab[i].dss1_clk - dss1_rate) < 3) { | ||
507 | min_l4_ticks = ftab[i].min_l4_ticks; | ||
508 | break; | ||
509 | } | ||
510 | } | ||
511 | if (i == ARRAY_SIZE(ftab)) { | ||
512 | /* Can't be sure, return anyway the maximum not | ||
513 | * rate-limited. This might cause a problem only for the | ||
514 | * tearing synchronisation. | ||
515 | */ | ||
516 | DSSERR("can't determine maximum RFBI transfer rate\n"); | ||
517 | return rfbi.l4_khz * 1000; | ||
518 | } | ||
519 | return rfbi.l4_khz * 1000 / min_l4_ticks; | ||
520 | } | ||
521 | #else | ||
522 | int rfbi_get_max_tx_rate(void) | ||
523 | { | ||
524 | return rfbi.l4_khz * 1000; | ||
525 | } | ||
526 | #endif | ||
527 | |||
528 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) | 451 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) |
529 | { | 452 | { |
530 | *clk_period = 1000000000 / rfbi.l4_khz; | 453 | *clk_period = 1000000000 / rfbi.l4_khz; |
@@ -644,7 +567,6 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, | |||
644 | DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n", | 567 | DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n", |
645 | mode, hs, vs, hs_pol_inv, vs_pol_inv); | 568 | mode, hs, vs, hs_pol_inv, vs_pol_inv); |
646 | 569 | ||
647 | rfbi_enable_clocks(1); | ||
648 | rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); | 570 | rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); |
649 | rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); | 571 | rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); |
650 | 572 | ||
@@ -657,7 +579,6 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, | |||
657 | l &= ~(1 << 20); | 579 | l &= ~(1 << 20); |
658 | else | 580 | else |
659 | l |= 1 << 20; | 581 | l |= 1 << 20; |
660 | rfbi_enable_clocks(0); | ||
661 | 582 | ||
662 | return 0; | 583 | return 0; |
663 | } | 584 | } |
@@ -672,7 +593,6 @@ int omap_rfbi_enable_te(bool enable, unsigned line) | |||
672 | if (line > (1 << 11) - 1) | 593 | if (line > (1 << 11) - 1) |
673 | return -EINVAL; | 594 | return -EINVAL; |
674 | 595 | ||
675 | rfbi_enable_clocks(1); | ||
676 | l = rfbi_read_reg(RFBI_CONFIG(0)); | 596 | l = rfbi_read_reg(RFBI_CONFIG(0)); |
677 | l &= ~(0x3 << 2); | 597 | l &= ~(0x3 << 2); |
678 | if (enable) { | 598 | if (enable) { |
@@ -682,50 +602,12 @@ int omap_rfbi_enable_te(bool enable, unsigned line) | |||
682 | rfbi.te_enabled = 0; | 602 | rfbi.te_enabled = 0; |
683 | rfbi_write_reg(RFBI_CONFIG(0), l); | 603 | rfbi_write_reg(RFBI_CONFIG(0), l); |
684 | rfbi_write_reg(RFBI_LINE_NUMBER, line); | 604 | rfbi_write_reg(RFBI_LINE_NUMBER, line); |
685 | rfbi_enable_clocks(0); | ||
686 | 605 | ||
687 | return 0; | 606 | return 0; |
688 | } | 607 | } |
689 | EXPORT_SYMBOL(omap_rfbi_enable_te); | 608 | EXPORT_SYMBOL(omap_rfbi_enable_te); |
690 | 609 | ||
691 | #if 0 | 610 | static int rfbi_configure(int rfbi_module, int bpp, int lines) |
692 | static void rfbi_enable_config(int enable1, int enable2) | ||
693 | { | ||
694 | u32 l; | ||
695 | int cs = 0; | ||
696 | |||
697 | if (enable1) | ||
698 | cs |= 1<<0; | ||
699 | if (enable2) | ||
700 | cs |= 1<<1; | ||
701 | |||
702 | rfbi_enable_clocks(1); | ||
703 | |||
704 | l = rfbi_read_reg(RFBI_CONTROL); | ||
705 | |||
706 | l = FLD_MOD(l, cs, 3, 2); | ||
707 | l = FLD_MOD(l, 0, 1, 1); | ||
708 | |||
709 | rfbi_write_reg(RFBI_CONTROL, l); | ||
710 | |||
711 | |||
712 | l = rfbi_read_reg(RFBI_CONFIG(0)); | ||
713 | l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */ | ||
714 | /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ | ||
715 | /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */ | ||
716 | |||
717 | l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */ | ||
718 | l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */ | ||
719 | l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */ | ||
720 | |||
721 | l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0); | ||
722 | rfbi_write_reg(RFBI_CONFIG(0), l); | ||
723 | |||
724 | rfbi_enable_clocks(0); | ||
725 | } | ||
726 | #endif | ||
727 | |||
728 | int rfbi_configure(int rfbi_module, int bpp, int lines) | ||
729 | { | 611 | { |
730 | u32 l; | 612 | u32 l; |
731 | int cycle1 = 0, cycle2 = 0, cycle3 = 0; | 613 | int cycle1 = 0, cycle2 = 0, cycle3 = 0; |
@@ -821,8 +703,6 @@ int rfbi_configure(int rfbi_module, int bpp, int lines) | |||
821 | break; | 703 | break; |
822 | } | 704 | } |
823 | 705 | ||
824 | rfbi_enable_clocks(1); | ||
825 | |||
826 | REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */ | 706 | REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */ |
827 | 707 | ||
828 | l = 0; | 708 | l = 0; |
@@ -856,11 +736,15 @@ int rfbi_configure(int rfbi_module, int bpp, int lines) | |||
856 | DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n", | 736 | DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n", |
857 | bpp, lines, cycle1, cycle2, cycle3); | 737 | bpp, lines, cycle1, cycle2, cycle3); |
858 | 738 | ||
859 | rfbi_enable_clocks(0); | ||
860 | |||
861 | return 0; | 739 | return 0; |
862 | } | 740 | } |
863 | EXPORT_SYMBOL(rfbi_configure); | 741 | |
742 | int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, | ||
743 | int data_lines) | ||
744 | { | ||
745 | return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines); | ||
746 | } | ||
747 | EXPORT_SYMBOL(omap_rfbi_configure); | ||
864 | 748 | ||
865 | int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | 749 | int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, |
866 | u16 *x, u16 *y, u16 *w, u16 *h) | 750 | u16 *x, u16 *y, u16 *w, u16 *h) |
@@ -960,6 +844,8 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | |||
960 | { | 844 | { |
961 | int r; | 845 | int r; |
962 | 846 | ||
847 | rfbi_enable_clocks(1); | ||
848 | |||
963 | r = omap_dss_start_device(dssdev); | 849 | r = omap_dss_start_device(dssdev); |
964 | if (r) { | 850 | if (r) { |
965 | DSSERR("failed to start device\n"); | 851 | DSSERR("failed to start device\n"); |
@@ -1002,6 +888,8 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) | |||
1002 | omap_dispc_unregister_isr(framedone_callback, NULL, | 888 | omap_dispc_unregister_isr(framedone_callback, NULL, |
1003 | DISPC_IRQ_FRAMEDONE); | 889 | DISPC_IRQ_FRAMEDONE); |
1004 | omap_dss_stop_device(dssdev); | 890 | omap_dss_stop_device(dssdev); |
891 | |||
892 | rfbi_enable_clocks(0); | ||
1005 | } | 893 | } |
1006 | EXPORT_SYMBOL(omapdss_rfbi_display_disable); | 894 | EXPORT_SYMBOL(omapdss_rfbi_display_disable); |
1007 | 895 | ||
@@ -1021,11 +909,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev) | |||
1021 | 909 | ||
1022 | rfbi.pdev = pdev; | 910 | rfbi.pdev = pdev; |
1023 | 911 | ||
1024 | spin_lock_init(&rfbi.cmd_lock); | 912 | sema_init(&rfbi.bus_lock, 1); |
1025 | |||
1026 | init_completion(&rfbi.cmd_done); | ||
1027 | atomic_set(&rfbi.cmd_fifo_full, 0); | ||
1028 | atomic_set(&rfbi.cmd_pending, 0); | ||
1029 | 913 | ||
1030 | rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); | 914 | rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); |
1031 | if (!rfbi_mem) { | 915 | if (!rfbi_mem) { |
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 54a53e648180..0bd4b0350f80 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/err.h> | 25 | #include <linux/err.h> |
26 | #include <linux/regulator/consumer.h> | 26 | #include <linux/regulator/consumer.h> |
27 | 27 | ||
28 | #include <plat/display.h> | 28 | #include <video/omapdss.h> |
29 | #include <plat/cpu.h> | 29 | #include <plat/cpu.h> |
30 | #include "dss.h" | 30 | #include "dss.h" |
31 | 31 | ||
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 8e35a5bae429..980f919ed987 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
35 | #include <linux/regulator/consumer.h> | 35 | #include <linux/regulator/consumer.h> |
36 | 36 | ||
37 | #include <plat/display.h> | 37 | #include <video/omapdss.h> |
38 | #include <plat/cpu.h> | 38 | #include <plat/cpu.h> |
39 | 39 | ||
40 | #include "dss.h" | 40 | #include "dss.h" |
@@ -373,8 +373,11 @@ static void venc_reset(void) | |||
373 | } | 373 | } |
374 | } | 374 | } |
375 | 375 | ||
376 | #ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET | ||
376 | /* the magical sleep that makes things work */ | 377 | /* the magical sleep that makes things work */ |
378 | /* XXX more info? What bug this circumvents? */ | ||
377 | msleep(20); | 379 | msleep(20); |
380 | #endif | ||
378 | } | 381 | } |
379 | 382 | ||
380 | static void venc_enable_clocks(int enable) | 383 | static void venc_enable_clocks(int enable) |
@@ -473,6 +476,12 @@ static int venc_panel_enable(struct omap_dss_device *dssdev) | |||
473 | 476 | ||
474 | mutex_lock(&venc.venc_lock); | 477 | mutex_lock(&venc.venc_lock); |
475 | 478 | ||
479 | r = omap_dss_start_device(dssdev); | ||
480 | if (r) { | ||
481 | DSSERR("failed to start device\n"); | ||
482 | goto err0; | ||
483 | } | ||
484 | |||
476 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | 485 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { |
477 | r = -EINVAL; | 486 | r = -EINVAL; |
478 | goto err1; | 487 | goto err1; |
@@ -484,10 +493,11 @@ static int venc_panel_enable(struct omap_dss_device *dssdev) | |||
484 | 493 | ||
485 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 494 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
486 | 495 | ||
487 | /* wait couple of vsyncs until enabling the LCD */ | 496 | mutex_unlock(&venc.venc_lock); |
488 | msleep(50); | 497 | return 0; |
489 | |||
490 | err1: | 498 | err1: |
499 | omap_dss_stop_device(dssdev); | ||
500 | err0: | ||
491 | mutex_unlock(&venc.venc_lock); | 501 | mutex_unlock(&venc.venc_lock); |
492 | 502 | ||
493 | return r; | 503 | return r; |
@@ -510,10 +520,9 @@ static void venc_panel_disable(struct omap_dss_device *dssdev) | |||
510 | 520 | ||
511 | venc_power_off(dssdev); | 521 | venc_power_off(dssdev); |
512 | 522 | ||
513 | /* wait at least 5 vsyncs after disabling the LCD */ | ||
514 | msleep(100); | ||
515 | |||
516 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 523 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; |
524 | |||
525 | omap_dss_stop_device(dssdev); | ||
517 | end: | 526 | end: |
518 | mutex_unlock(&venc.venc_lock); | 527 | mutex_unlock(&venc.venc_lock); |
519 | } | 528 | } |
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 6f435450987e..cff450392b79 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/omapfb.h> | 28 | #include <linux/omapfb.h> |
29 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
30 | 30 | ||
31 | #include <plat/display.h> | 31 | #include <video/omapdss.h> |
32 | #include <plat/vrfb.h> | 32 | #include <plat/vrfb.h> |
33 | #include <plat/vram.h> | 33 | #include <plat/vram.h> |
34 | 34 | ||
@@ -895,8 +895,16 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) | |||
895 | 895 | ||
896 | p.display_info.xres = xres; | 896 | p.display_info.xres = xres; |
897 | p.display_info.yres = yres; | 897 | p.display_info.yres = yres; |
898 | p.display_info.width = 0; | 898 | |
899 | p.display_info.height = 0; | 899 | if (display->driver->get_dimensions) { |
900 | u32 w, h; | ||
901 | display->driver->get_dimensions(display, &w, &h); | ||
902 | p.display_info.width = w; | ||
903 | p.display_info.height = h; | ||
904 | } else { | ||
905 | p.display_info.width = 0; | ||
906 | p.display_info.height = 0; | ||
907 | } | ||
900 | 908 | ||
901 | if (copy_to_user((void __user *)arg, &p.display_info, | 909 | if (copy_to_user((void __user *)arg, &p.display_info, |
902 | sizeof(p.display_info))) | 910 | sizeof(p.display_info))) |
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 505ec6672049..505bc12a3031 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/omapfb.h> | 31 | #include <linux/omapfb.h> |
32 | 32 | ||
33 | #include <plat/display.h> | 33 | #include <video/omapdss.h> |
34 | #include <plat/vram.h> | 34 | #include <plat/vram.h> |
35 | #include <plat/vrfb.h> | 35 | #include <plat/vrfb.h> |
36 | 36 | ||
@@ -702,8 +702,16 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) | |||
702 | var->xres, var->yres, | 702 | var->xres, var->yres, |
703 | var->xres_virtual, var->yres_virtual); | 703 | var->xres_virtual, var->yres_virtual); |
704 | 704 | ||
705 | var->height = -1; | 705 | if (display && display->driver->get_dimensions) { |
706 | var->width = -1; | 706 | u32 w, h; |
707 | display->driver->get_dimensions(display, &w, &h); | ||
708 | var->width = DIV_ROUND_CLOSEST(w, 1000); | ||
709 | var->height = DIV_ROUND_CLOSEST(h, 1000); | ||
710 | } else { | ||
711 | var->height = -1; | ||
712 | var->width = -1; | ||
713 | } | ||
714 | |||
707 | var->grayscale = 0; | 715 | var->grayscale = 0; |
708 | 716 | ||
709 | if (display && display->driver->get_timings) { | 717 | if (display && display->driver->get_timings) { |
@@ -749,35 +757,6 @@ static int omapfb_open(struct fb_info *fbi, int user) | |||
749 | 757 | ||
750 | static int omapfb_release(struct fb_info *fbi, int user) | 758 | static int omapfb_release(struct fb_info *fbi, int user) |
751 | { | 759 | { |
752 | #if 0 | ||
753 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
754 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
755 | struct omap_dss_device *display = fb2display(fbi); | ||
756 | |||
757 | DBG("Closing fb with plane index %d\n", ofbi->id); | ||
758 | |||
759 | omapfb_lock(fbdev); | ||
760 | |||
761 | if (display && display->get_update_mode && display->update) { | ||
762 | /* XXX this update should be removed, I think. But it's | ||
763 | * good for debugging */ | ||
764 | if (display->get_update_mode(display) == | ||
765 | OMAP_DSS_UPDATE_MANUAL) { | ||
766 | u16 w, h; | ||
767 | |||
768 | if (display->sync) | ||
769 | display->sync(display); | ||
770 | |||
771 | display->get_resolution(display, &w, &h); | ||
772 | display->update(display, 0, 0, w, h); | ||
773 | } | ||
774 | } | ||
775 | |||
776 | if (display && display->sync) | ||
777 | display->sync(display); | ||
778 | |||
779 | omapfb_unlock(fbdev); | ||
780 | #endif | ||
781 | return 0; | 760 | return 0; |
782 | } | 761 | } |
783 | 762 | ||
@@ -1263,7 +1242,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
1263 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1242 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1264 | struct omapfb2_device *fbdev = ofbi->fbdev; | 1243 | struct omapfb2_device *fbdev = ofbi->fbdev; |
1265 | struct omap_dss_device *display = fb2display(fbi); | 1244 | struct omap_dss_device *display = fb2display(fbi); |
1266 | int do_update = 0; | ||
1267 | int r = 0; | 1245 | int r = 0; |
1268 | 1246 | ||
1269 | if (!display) | 1247 | if (!display) |
@@ -1279,11 +1257,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
1279 | if (display->driver->resume) | 1257 | if (display->driver->resume) |
1280 | r = display->driver->resume(display); | 1258 | r = display->driver->resume(display); |
1281 | 1259 | ||
1282 | if (r == 0 && display->driver->get_update_mode && | ||
1283 | display->driver->get_update_mode(display) == | ||
1284 | OMAP_DSS_UPDATE_MANUAL) | ||
1285 | do_update = 1; | ||
1286 | |||
1287 | break; | 1260 | break; |
1288 | 1261 | ||
1289 | case FB_BLANK_NORMAL: | 1262 | case FB_BLANK_NORMAL: |
@@ -1307,13 +1280,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
1307 | exit: | 1280 | exit: |
1308 | omapfb_unlock(fbdev); | 1281 | omapfb_unlock(fbdev); |
1309 | 1282 | ||
1310 | if (r == 0 && do_update && display->driver->update) { | ||
1311 | u16 w, h; | ||
1312 | display->driver->get_resolution(display, &w, &h); | ||
1313 | |||
1314 | r = display->driver->update(display, 0, 0, w, h); | ||
1315 | } | ||
1316 | |||
1317 | return r; | 1283 | return r; |
1318 | } | 1284 | } |
1319 | 1285 | ||
@@ -2030,9 +1996,9 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
2030 | static int omapfb_mode_to_timings(const char *mode_str, | 1996 | static int omapfb_mode_to_timings(const char *mode_str, |
2031 | struct omap_video_timings *timings, u8 *bpp) | 1997 | struct omap_video_timings *timings, u8 *bpp) |
2032 | { | 1998 | { |
2033 | struct fb_info fbi; | 1999 | struct fb_info *fbi; |
2034 | struct fb_var_screeninfo var; | 2000 | struct fb_var_screeninfo *var; |
2035 | struct fb_ops fbops; | 2001 | struct fb_ops *fbops; |
2036 | int r; | 2002 | int r; |
2037 | 2003 | ||
2038 | #ifdef CONFIG_OMAP2_DSS_VENC | 2004 | #ifdef CONFIG_OMAP2_DSS_VENC |
@@ -2050,39 +2016,66 @@ static int omapfb_mode_to_timings(const char *mode_str, | |||
2050 | /* this is quite a hack, but I wanted to use the modedb and for | 2016 | /* this is quite a hack, but I wanted to use the modedb and for |
2051 | * that we need fb_info and var, so we create dummy ones */ | 2017 | * that we need fb_info and var, so we create dummy ones */ |
2052 | 2018 | ||
2053 | memset(&fbi, 0, sizeof(fbi)); | 2019 | *bpp = 0; |
2054 | memset(&var, 0, sizeof(var)); | 2020 | fbi = NULL; |
2055 | memset(&fbops, 0, sizeof(fbops)); | 2021 | var = NULL; |
2056 | fbi.fbops = &fbops; | 2022 | fbops = NULL; |
2057 | |||
2058 | r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24); | ||
2059 | |||
2060 | if (r != 0) { | ||
2061 | timings->pixel_clock = PICOS2KHZ(var.pixclock); | ||
2062 | timings->hbp = var.left_margin; | ||
2063 | timings->hfp = var.right_margin; | ||
2064 | timings->vbp = var.upper_margin; | ||
2065 | timings->vfp = var.lower_margin; | ||
2066 | timings->hsw = var.hsync_len; | ||
2067 | timings->vsw = var.vsync_len; | ||
2068 | timings->x_res = var.xres; | ||
2069 | timings->y_res = var.yres; | ||
2070 | |||
2071 | switch (var.bits_per_pixel) { | ||
2072 | case 16: | ||
2073 | *bpp = 16; | ||
2074 | break; | ||
2075 | case 24: | ||
2076 | case 32: | ||
2077 | default: | ||
2078 | *bpp = 24; | ||
2079 | break; | ||
2080 | } | ||
2081 | 2023 | ||
2082 | return 0; | 2024 | fbi = kzalloc(sizeof(*fbi), GFP_KERNEL); |
2083 | } else { | 2025 | if (fbi == NULL) { |
2084 | return -EINVAL; | 2026 | r = -ENOMEM; |
2027 | goto err; | ||
2028 | } | ||
2029 | |||
2030 | var = kzalloc(sizeof(*var), GFP_KERNEL); | ||
2031 | if (var == NULL) { | ||
2032 | r = -ENOMEM; | ||
2033 | goto err; | ||
2034 | } | ||
2035 | |||
2036 | fbops = kzalloc(sizeof(*fbops), GFP_KERNEL); | ||
2037 | if (fbops == NULL) { | ||
2038 | r = -ENOMEM; | ||
2039 | goto err; | ||
2040 | } | ||
2041 | |||
2042 | fbi->fbops = fbops; | ||
2043 | |||
2044 | r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24); | ||
2045 | if (r == 0) { | ||
2046 | r = -EINVAL; | ||
2047 | goto err; | ||
2048 | } | ||
2049 | |||
2050 | timings->pixel_clock = PICOS2KHZ(var->pixclock); | ||
2051 | timings->hbp = var->left_margin; | ||
2052 | timings->hfp = var->right_margin; | ||
2053 | timings->vbp = var->upper_margin; | ||
2054 | timings->vfp = var->lower_margin; | ||
2055 | timings->hsw = var->hsync_len; | ||
2056 | timings->vsw = var->vsync_len; | ||
2057 | timings->x_res = var->xres; | ||
2058 | timings->y_res = var->yres; | ||
2059 | |||
2060 | switch (var->bits_per_pixel) { | ||
2061 | case 16: | ||
2062 | *bpp = 16; | ||
2063 | break; | ||
2064 | case 24: | ||
2065 | case 32: | ||
2066 | default: | ||
2067 | *bpp = 24; | ||
2068 | break; | ||
2085 | } | 2069 | } |
2070 | |||
2071 | r = 0; | ||
2072 | |||
2073 | err: | ||
2074 | kfree(fbi); | ||
2075 | kfree(var); | ||
2076 | kfree(fbops); | ||
2077 | |||
2078 | return r; | ||
2086 | } | 2079 | } |
2087 | 2080 | ||
2088 | static int omapfb_set_def_mode(struct omapfb2_device *fbdev, | 2081 | static int omapfb_set_def_mode(struct omapfb2_device *fbdev, |
@@ -2185,6 +2178,61 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) | |||
2185 | return r; | 2178 | return r; |
2186 | } | 2179 | } |
2187 | 2180 | ||
2181 | static int omapfb_init_display(struct omapfb2_device *fbdev, | ||
2182 | struct omap_dss_device *dssdev) | ||
2183 | { | ||
2184 | struct omap_dss_driver *dssdrv = dssdev->driver; | ||
2185 | int r; | ||
2186 | |||
2187 | r = dssdrv->enable(dssdev); | ||
2188 | if (r) { | ||
2189 | dev_warn(fbdev->dev, "Failed to enable display '%s'\n", | ||
2190 | dssdev->name); | ||
2191 | return r; | ||
2192 | } | ||
2193 | |||
2194 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | ||
2195 | u16 w, h; | ||
2196 | if (dssdrv->enable_te) { | ||
2197 | r = dssdrv->enable_te(dssdev, 1); | ||
2198 | if (r) { | ||
2199 | dev_err(fbdev->dev, "Failed to set TE\n"); | ||
2200 | return r; | ||
2201 | } | ||
2202 | } | ||
2203 | |||
2204 | if (dssdrv->set_update_mode) { | ||
2205 | r = dssdrv->set_update_mode(dssdev, | ||
2206 | OMAP_DSS_UPDATE_MANUAL); | ||
2207 | if (r) { | ||
2208 | dev_err(fbdev->dev, | ||
2209 | "Failed to set update mode\n"); | ||
2210 | return r; | ||
2211 | } | ||
2212 | } | ||
2213 | |||
2214 | dssdrv->get_resolution(dssdev, &w, &h); | ||
2215 | r = dssdrv->update(dssdev, 0, 0, w, h); | ||
2216 | if (r) { | ||
2217 | dev_err(fbdev->dev, | ||
2218 | "Failed to update display\n"); | ||
2219 | return r; | ||
2220 | } | ||
2221 | } else { | ||
2222 | if (dssdrv->set_update_mode) { | ||
2223 | r = dssdrv->set_update_mode(dssdev, | ||
2224 | OMAP_DSS_UPDATE_AUTO); | ||
2225 | if (r) { | ||
2226 | dev_err(fbdev->dev, | ||
2227 | "Failed to set update mode\n"); | ||
2228 | return r; | ||
2229 | } | ||
2230 | } | ||
2231 | } | ||
2232 | |||
2233 | return 0; | ||
2234 | } | ||
2235 | |||
2188 | static int omapfb_probe(struct platform_device *pdev) | 2236 | static int omapfb_probe(struct platform_device *pdev) |
2189 | { | 2237 | { |
2190 | struct omapfb2_device *fbdev = NULL; | 2238 | struct omapfb2_device *fbdev = NULL; |
@@ -2284,30 +2332,13 @@ static int omapfb_probe(struct platform_device *pdev) | |||
2284 | } | 2332 | } |
2285 | 2333 | ||
2286 | if (def_display) { | 2334 | if (def_display) { |
2287 | struct omap_dss_driver *dssdrv = def_display->driver; | 2335 | r = omapfb_init_display(fbdev, def_display); |
2288 | |||
2289 | r = def_display->driver->enable(def_display); | ||
2290 | if (r) { | 2336 | if (r) { |
2291 | dev_warn(fbdev->dev, "Failed to enable display '%s'\n", | 2337 | dev_err(fbdev->dev, |
2292 | def_display->name); | 2338 | "failed to initialize default " |
2339 | "display\n"); | ||
2293 | goto cleanup; | 2340 | goto cleanup; |
2294 | } | 2341 | } |
2295 | |||
2296 | if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | ||
2297 | u16 w, h; | ||
2298 | if (dssdrv->enable_te) | ||
2299 | dssdrv->enable_te(def_display, 1); | ||
2300 | if (dssdrv->set_update_mode) | ||
2301 | dssdrv->set_update_mode(def_display, | ||
2302 | OMAP_DSS_UPDATE_MANUAL); | ||
2303 | |||
2304 | dssdrv->get_resolution(def_display, &w, &h); | ||
2305 | def_display->driver->update(def_display, 0, 0, w, h); | ||
2306 | } else { | ||
2307 | if (dssdrv->set_update_mode) | ||
2308 | dssdrv->set_update_mode(def_display, | ||
2309 | OMAP_DSS_UPDATE_AUTO); | ||
2310 | } | ||
2311 | } | 2342 | } |
2312 | 2343 | ||
2313 | DBG("create sysfs for fbs\n"); | 2344 | DBG("create sysfs for fbs\n"); |
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index 6f9c72cd6bb0..2f5e817b2a9a 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <linux/omapfb.h> | 30 | #include <linux/omapfb.h> |
31 | 31 | ||
32 | #include <plat/display.h> | 32 | #include <video/omapdss.h> |
33 | #include <plat/vrfb.h> | 33 | #include <plat/vrfb.h> |
34 | 34 | ||
35 | #include "omapfb.h" | 35 | #include "omapfb.h" |
@@ -50,10 +50,12 @@ static ssize_t store_rotate_type(struct device *dev, | |||
50 | struct fb_info *fbi = dev_get_drvdata(dev); | 50 | struct fb_info *fbi = dev_get_drvdata(dev); |
51 | struct omapfb_info *ofbi = FB2OFB(fbi); | 51 | struct omapfb_info *ofbi = FB2OFB(fbi); |
52 | struct omapfb2_mem_region *rg; | 52 | struct omapfb2_mem_region *rg; |
53 | enum omap_dss_rotation_type rot_type; | 53 | int rot_type; |
54 | int r; | 54 | int r; |
55 | 55 | ||
56 | rot_type = simple_strtoul(buf, NULL, 0); | 56 | r = kstrtoint(buf, 0, &rot_type); |
57 | if (r) | ||
58 | return r; | ||
57 | 59 | ||
58 | if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) | 60 | if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) |
59 | return -EINVAL; | 61 | return -EINVAL; |
@@ -102,14 +104,15 @@ static ssize_t store_mirror(struct device *dev, | |||
102 | { | 104 | { |
103 | struct fb_info *fbi = dev_get_drvdata(dev); | 105 | struct fb_info *fbi = dev_get_drvdata(dev); |
104 | struct omapfb_info *ofbi = FB2OFB(fbi); | 106 | struct omapfb_info *ofbi = FB2OFB(fbi); |
105 | unsigned long mirror; | 107 | int mirror; |
106 | int r; | 108 | int r; |
107 | struct fb_var_screeninfo new_var; | 109 | struct fb_var_screeninfo new_var; |
108 | 110 | ||
109 | mirror = simple_strtoul(buf, NULL, 0); | 111 | r = kstrtoint(buf, 0, &mirror); |
112 | if (r) | ||
113 | return r; | ||
110 | 114 | ||
111 | if (mirror != 0 && mirror != 1) | 115 | mirror = !!mirror; |
112 | return -EINVAL; | ||
113 | 116 | ||
114 | if (!lock_fb_info(fbi)) | 117 | if (!lock_fb_info(fbi)) |
115 | return -ENODEV; | 118 | return -ENODEV; |
@@ -445,7 +448,11 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, | |||
445 | int r; | 448 | int r; |
446 | int i; | 449 | int i; |
447 | 450 | ||
448 | size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0)); | 451 | r = kstrtoul(buf, 0, &size); |
452 | if (r) | ||
453 | return r; | ||
454 | |||
455 | size = PAGE_ALIGN(size); | ||
449 | 456 | ||
450 | if (!lock_fb_info(fbi)) | 457 | if (!lock_fb_info(fbi)) |
451 | return -ENODEV; | 458 | return -ENODEV; |
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index 1305fc9880ba..aa1b1d974276 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h | |||
@@ -29,13 +29,15 @@ | |||
29 | 29 | ||
30 | #include <linux/rwsem.h> | 30 | #include <linux/rwsem.h> |
31 | 31 | ||
32 | #include <plat/display.h> | 32 | #include <video/omapdss.h> |
33 | 33 | ||
34 | #ifdef DEBUG | 34 | #ifdef DEBUG |
35 | extern unsigned int omapfb_debug; | 35 | extern unsigned int omapfb_debug; |
36 | #define DBG(format, ...) \ | 36 | #define DBG(format, ...) \ |
37 | if (omapfb_debug) \ | 37 | do { \ |
38 | printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__) | 38 | if (omapfb_debug) \ |
39 | printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__); \ | ||
40 | } while (0) | ||
39 | #else | 41 | #else |
40 | #define DBG(format, ...) | 42 | #define DBG(format, ...) |
41 | #endif | 43 | #endif |
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 3b6cdcac8f1a..0352afa49a39 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
@@ -182,6 +182,7 @@ struct s3c_fb_vsync { | |||
182 | 182 | ||
183 | /** | 183 | /** |
184 | * struct s3c_fb - overall hardware state of the hardware | 184 | * struct s3c_fb - overall hardware state of the hardware |
185 | * @slock: The spinlock protection for this data sturcture. | ||
185 | * @dev: The device that we bound to, for printing, etc. | 186 | * @dev: The device that we bound to, for printing, etc. |
186 | * @regs_res: The resource we claimed for the IO registers. | 187 | * @regs_res: The resource we claimed for the IO registers. |
187 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. | 188 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. |
@@ -195,6 +196,7 @@ struct s3c_fb_vsync { | |||
195 | * @vsync_info: VSYNC-related information (count, queues...) | 196 | * @vsync_info: VSYNC-related information (count, queues...) |
196 | */ | 197 | */ |
197 | struct s3c_fb { | 198 | struct s3c_fb { |
199 | spinlock_t slock; | ||
198 | struct device *dev; | 200 | struct device *dev; |
199 | struct resource *regs_res; | 201 | struct resource *regs_res; |
200 | struct clk *bus_clk; | 202 | struct clk *bus_clk; |
@@ -300,6 +302,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
300 | var->blue.length = 5; | 302 | var->blue.length = 5; |
301 | break; | 303 | break; |
302 | 304 | ||
305 | case 32: | ||
303 | case 28: | 306 | case 28: |
304 | case 25: | 307 | case 25: |
305 | var->transp.length = var->bits_per_pixel - 24; | 308 | var->transp.length = var->bits_per_pixel - 24; |
@@ -308,7 +311,6 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
308 | case 24: | 311 | case 24: |
309 | /* our 24bpp is unpacked, so 32bpp */ | 312 | /* our 24bpp is unpacked, so 32bpp */ |
310 | var->bits_per_pixel = 32; | 313 | var->bits_per_pixel = 32; |
311 | case 32: | ||
312 | var->red.offset = 16; | 314 | var->red.offset = 16; |
313 | var->red.length = 8; | 315 | var->red.length = 8; |
314 | var->green.offset = 8; | 316 | var->green.offset = 8; |
@@ -947,6 +949,8 @@ static irqreturn_t s3c_fb_irq(int irq, void *dev_id) | |||
947 | void __iomem *regs = sfb->regs; | 949 | void __iomem *regs = sfb->regs; |
948 | u32 irq_sts_reg; | 950 | u32 irq_sts_reg; |
949 | 951 | ||
952 | spin_lock(&sfb->slock); | ||
953 | |||
950 | irq_sts_reg = readl(regs + VIDINTCON1); | 954 | irq_sts_reg = readl(regs + VIDINTCON1); |
951 | 955 | ||
952 | if (irq_sts_reg & VIDINTCON1_INT_FRAME) { | 956 | if (irq_sts_reg & VIDINTCON1_INT_FRAME) { |
@@ -963,6 +967,7 @@ static irqreturn_t s3c_fb_irq(int irq, void *dev_id) | |||
963 | */ | 967 | */ |
964 | s3c_fb_disable_irq(sfb); | 968 | s3c_fb_disable_irq(sfb); |
965 | 969 | ||
970 | spin_unlock(&sfb->slock); | ||
966 | return IRQ_HANDLED; | 971 | return IRQ_HANDLED; |
967 | } | 972 | } |
968 | 973 | ||
@@ -1339,6 +1344,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
1339 | sfb->pdata = pd; | 1344 | sfb->pdata = pd; |
1340 | sfb->variant = fbdrv->variant; | 1345 | sfb->variant = fbdrv->variant; |
1341 | 1346 | ||
1347 | spin_lock_init(&sfb->slock); | ||
1348 | |||
1342 | sfb->bus_clk = clk_get(dev, "lcd"); | 1349 | sfb->bus_clk = clk_get(dev, "lcd"); |
1343 | if (IS_ERR(sfb->bus_clk)) { | 1350 | if (IS_ERR(sfb->bus_clk)) { |
1344 | dev_err(dev, "failed to get bus clock\n"); | 1351 | dev_err(dev, "failed to get bus clock\n"); |
@@ -1442,8 +1449,7 @@ err_ioremap: | |||
1442 | iounmap(sfb->regs); | 1449 | iounmap(sfb->regs); |
1443 | 1450 | ||
1444 | err_req_region: | 1451 | err_req_region: |
1445 | release_resource(sfb->regs_res); | 1452 | release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); |
1446 | kfree(sfb->regs_res); | ||
1447 | 1453 | ||
1448 | err_clk: | 1454 | err_clk: |
1449 | clk_disable(sfb->bus_clk); | 1455 | clk_disable(sfb->bus_clk); |
@@ -1479,8 +1485,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) | |||
1479 | clk_disable(sfb->bus_clk); | 1485 | clk_disable(sfb->bus_clk); |
1480 | clk_put(sfb->bus_clk); | 1486 | clk_put(sfb->bus_clk); |
1481 | 1487 | ||
1482 | release_resource(sfb->regs_res); | 1488 | release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); |
1483 | kfree(sfb->regs_res); | ||
1484 | 1489 | ||
1485 | kfree(sfb); | 1490 | kfree(sfb); |
1486 | 1491 | ||
@@ -1521,7 +1526,8 @@ static int s3c_fb_resume(struct device *dev) | |||
1521 | 1526 | ||
1522 | clk_enable(sfb->bus_clk); | 1527 | clk_enable(sfb->bus_clk); |
1523 | 1528 | ||
1524 | /* setup registers */ | 1529 | /* setup gpio and output polarity controls */ |
1530 | pd->setup_gpio(); | ||
1525 | writel(pd->vidcon1, sfb->regs + VIDCON1); | 1531 | writel(pd->vidcon1, sfb->regs + VIDCON1); |
1526 | 1532 | ||
1527 | /* zero all windows before we do anything */ | 1533 | /* zero all windows before we do anything */ |
@@ -1549,7 +1555,7 @@ static int s3c_fb_resume(struct device *dev) | |||
1549 | return 0; | 1555 | return 0; |
1550 | } | 1556 | } |
1551 | 1557 | ||
1552 | int s3c_fb_runtime_suspend(struct device *dev) | 1558 | static int s3c_fb_runtime_suspend(struct device *dev) |
1553 | { | 1559 | { |
1554 | struct platform_device *pdev = to_platform_device(dev); | 1560 | struct platform_device *pdev = to_platform_device(dev); |
1555 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | 1561 | struct s3c_fb *sfb = platform_get_drvdata(pdev); |
@@ -1569,7 +1575,7 @@ int s3c_fb_runtime_suspend(struct device *dev) | |||
1569 | return 0; | 1575 | return 0; |
1570 | } | 1576 | } |
1571 | 1577 | ||
1572 | int s3c_fb_runtime_resume(struct device *dev) | 1578 | static int s3c_fb_runtime_resume(struct device *dev) |
1573 | { | 1579 | { |
1574 | struct platform_device *pdev = to_platform_device(dev); | 1580 | struct platform_device *pdev = to_platform_device(dev); |
1575 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | 1581 | struct s3c_fb *sfb = platform_get_drvdata(pdev); |
@@ -1579,7 +1585,8 @@ int s3c_fb_runtime_resume(struct device *dev) | |||
1579 | 1585 | ||
1580 | clk_enable(sfb->bus_clk); | 1586 | clk_enable(sfb->bus_clk); |
1581 | 1587 | ||
1582 | /* setup registers */ | 1588 | /* setup gpio and output polarity controls */ |
1589 | pd->setup_gpio(); | ||
1583 | writel(pd->vidcon1, sfb->regs + VIDCON1); | 1590 | writel(pd->vidcon1, sfb->regs + VIDCON1); |
1584 | 1591 | ||
1585 | /* zero all windows before we do anything */ | 1592 | /* zero all windows before we do anything */ |
@@ -1623,28 +1630,31 @@ static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = { | |||
1623 | .has_osd_c = 1, | 1630 | .has_osd_c = 1, |
1624 | .osd_size_off = 0x8, | 1631 | .osd_size_off = 0x8, |
1625 | .palette_sz = 256, | 1632 | .palette_sz = 256, |
1626 | .valid_bpp = VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24), | 1633 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | |
1634 | VALID_BPP(18) | VALID_BPP(24)), | ||
1627 | }, | 1635 | }, |
1628 | [1] = { | 1636 | [1] = { |
1629 | .has_osd_c = 1, | 1637 | .has_osd_c = 1, |
1630 | .has_osd_d = 1, | 1638 | .has_osd_d = 1, |
1631 | .osd_size_off = 0x12, | 1639 | .osd_size_off = 0xc, |
1632 | .has_osd_alpha = 1, | 1640 | .has_osd_alpha = 1, |
1633 | .palette_sz = 256, | 1641 | .palette_sz = 256, |
1634 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | | 1642 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | |
1635 | VALID_BPP(18) | VALID_BPP(19) | | 1643 | VALID_BPP(18) | VALID_BPP(19) | |
1636 | VALID_BPP(24) | VALID_BPP(25)), | 1644 | VALID_BPP(24) | VALID_BPP(25) | |
1645 | VALID_BPP(28)), | ||
1637 | }, | 1646 | }, |
1638 | [2] = { | 1647 | [2] = { |
1639 | .has_osd_c = 1, | 1648 | .has_osd_c = 1, |
1640 | .has_osd_d = 1, | 1649 | .has_osd_d = 1, |
1641 | .osd_size_off = 0x12, | 1650 | .osd_size_off = 0xc, |
1642 | .has_osd_alpha = 1, | 1651 | .has_osd_alpha = 1, |
1643 | .palette_sz = 16, | 1652 | .palette_sz = 16, |
1644 | .palette_16bpp = 1, | 1653 | .palette_16bpp = 1, |
1645 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | | 1654 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | |
1646 | VALID_BPP(18) | VALID_BPP(19) | | 1655 | VALID_BPP(18) | VALID_BPP(19) | |
1647 | VALID_BPP(24) | VALID_BPP(25)), | 1656 | VALID_BPP(24) | VALID_BPP(25) | |
1657 | VALID_BPP(28)), | ||
1648 | }, | 1658 | }, |
1649 | [3] = { | 1659 | [3] = { |
1650 | .has_osd_c = 1, | 1660 | .has_osd_c = 1, |
@@ -1653,7 +1663,8 @@ static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = { | |||
1653 | .palette_16bpp = 1, | 1663 | .palette_16bpp = 1, |
1654 | .valid_bpp = (VALID_BPP124 | VALID_BPP(16) | | 1664 | .valid_bpp = (VALID_BPP124 | VALID_BPP(16) | |
1655 | VALID_BPP(18) | VALID_BPP(19) | | 1665 | VALID_BPP(18) | VALID_BPP(19) | |
1656 | VALID_BPP(24) | VALID_BPP(25)), | 1666 | VALID_BPP(24) | VALID_BPP(25) | |
1667 | VALID_BPP(28)), | ||
1657 | }, | 1668 | }, |
1658 | [4] = { | 1669 | [4] = { |
1659 | .has_osd_c = 1, | 1670 | .has_osd_c = 1, |
@@ -1662,7 +1673,65 @@ static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = { | |||
1662 | .palette_16bpp = 1, | 1673 | .palette_16bpp = 1, |
1663 | .valid_bpp = (VALID_BPP(1) | VALID_BPP(2) | | 1674 | .valid_bpp = (VALID_BPP(1) | VALID_BPP(2) | |
1664 | VALID_BPP(16) | VALID_BPP(18) | | 1675 | VALID_BPP(16) | VALID_BPP(18) | |
1665 | VALID_BPP(24) | VALID_BPP(25)), | 1676 | VALID_BPP(19) | VALID_BPP(24) | |
1677 | VALID_BPP(25) | VALID_BPP(28)), | ||
1678 | }, | ||
1679 | }; | ||
1680 | |||
1681 | static struct s3c_fb_win_variant s3c_fb_data_s5p_wins[] = { | ||
1682 | [0] = { | ||
1683 | .has_osd_c = 1, | ||
1684 | .osd_size_off = 0x8, | ||
1685 | .palette_sz = 256, | ||
1686 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) | | ||
1687 | VALID_BPP(15) | VALID_BPP(16) | | ||
1688 | VALID_BPP(18) | VALID_BPP(19) | | ||
1689 | VALID_BPP(24) | VALID_BPP(25) | | ||
1690 | VALID_BPP(32)), | ||
1691 | }, | ||
1692 | [1] = { | ||
1693 | .has_osd_c = 1, | ||
1694 | .has_osd_d = 1, | ||
1695 | .osd_size_off = 0xc, | ||
1696 | .has_osd_alpha = 1, | ||
1697 | .palette_sz = 256, | ||
1698 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) | | ||
1699 | VALID_BPP(15) | VALID_BPP(16) | | ||
1700 | VALID_BPP(18) | VALID_BPP(19) | | ||
1701 | VALID_BPP(24) | VALID_BPP(25) | | ||
1702 | VALID_BPP(32)), | ||
1703 | }, | ||
1704 | [2] = { | ||
1705 | .has_osd_c = 1, | ||
1706 | .has_osd_d = 1, | ||
1707 | .osd_size_off = 0xc, | ||
1708 | .has_osd_alpha = 1, | ||
1709 | .palette_sz = 256, | ||
1710 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) | | ||
1711 | VALID_BPP(15) | VALID_BPP(16) | | ||
1712 | VALID_BPP(18) | VALID_BPP(19) | | ||
1713 | VALID_BPP(24) | VALID_BPP(25) | | ||
1714 | VALID_BPP(32)), | ||
1715 | }, | ||
1716 | [3] = { | ||
1717 | .has_osd_c = 1, | ||
1718 | .has_osd_alpha = 1, | ||
1719 | .palette_sz = 256, | ||
1720 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) | | ||
1721 | VALID_BPP(15) | VALID_BPP(16) | | ||
1722 | VALID_BPP(18) | VALID_BPP(19) | | ||
1723 | VALID_BPP(24) | VALID_BPP(25) | | ||
1724 | VALID_BPP(32)), | ||
1725 | }, | ||
1726 | [4] = { | ||
1727 | .has_osd_c = 1, | ||
1728 | .has_osd_alpha = 1, | ||
1729 | .palette_sz = 256, | ||
1730 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) | | ||
1731 | VALID_BPP(15) | VALID_BPP(16) | | ||
1732 | VALID_BPP(18) | VALID_BPP(19) | | ||
1733 | VALID_BPP(24) | VALID_BPP(25) | | ||
1734 | VALID_BPP(32)), | ||
1666 | }, | 1735 | }, |
1667 | }; | 1736 | }; |
1668 | 1737 | ||
@@ -1719,11 +1788,11 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = { | |||
1719 | 1788 | ||
1720 | .has_prtcon = 1, | 1789 | .has_prtcon = 1, |
1721 | }, | 1790 | }, |
1722 | .win[0] = &s3c_fb_data_64xx_wins[0], | 1791 | .win[0] = &s3c_fb_data_s5p_wins[0], |
1723 | .win[1] = &s3c_fb_data_64xx_wins[1], | 1792 | .win[1] = &s3c_fb_data_s5p_wins[1], |
1724 | .win[2] = &s3c_fb_data_64xx_wins[2], | 1793 | .win[2] = &s3c_fb_data_s5p_wins[2], |
1725 | .win[3] = &s3c_fb_data_64xx_wins[3], | 1794 | .win[3] = &s3c_fb_data_s5p_wins[3], |
1726 | .win[4] = &s3c_fb_data_64xx_wins[4], | 1795 | .win[4] = &s3c_fb_data_s5p_wins[4], |
1727 | }; | 1796 | }; |
1728 | 1797 | ||
1729 | static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = { | 1798 | static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = { |
@@ -1749,11 +1818,11 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = { | |||
1749 | 1818 | ||
1750 | .has_shadowcon = 1, | 1819 | .has_shadowcon = 1, |
1751 | }, | 1820 | }, |
1752 | .win[0] = &s3c_fb_data_64xx_wins[0], | 1821 | .win[0] = &s3c_fb_data_s5p_wins[0], |
1753 | .win[1] = &s3c_fb_data_64xx_wins[1], | 1822 | .win[1] = &s3c_fb_data_s5p_wins[1], |
1754 | .win[2] = &s3c_fb_data_64xx_wins[2], | 1823 | .win[2] = &s3c_fb_data_s5p_wins[2], |
1755 | .win[3] = &s3c_fb_data_64xx_wins[3], | 1824 | .win[3] = &s3c_fb_data_s5p_wins[3], |
1756 | .win[4] = &s3c_fb_data_64xx_wins[4], | 1825 | .win[4] = &s3c_fb_data_s5p_wins[4], |
1757 | }; | 1826 | }; |
1758 | 1827 | ||
1759 | /* S3C2443/S3C2416 style hardware */ | 1828 | /* S3C2443/S3C2416 style hardware */ |
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 61c819e35f7f..0aa13761de6e 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -867,7 +867,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev, | |||
867 | goto dealloc_fb; | 867 | goto dealloc_fb; |
868 | } | 868 | } |
869 | 869 | ||
870 | size = (res->end - res->start) + 1; | 870 | size = resource_size(res); |
871 | info->mem = request_mem_region(res->start, size, pdev->name); | 871 | info->mem = request_mem_region(res->start, size, pdev->name); |
872 | if (info->mem == NULL) { | 872 | if (info->mem == NULL) { |
873 | dev_err(&pdev->dev, "failed to get memory region\n"); | 873 | dev_err(&pdev->dev, "failed to get memory region\n"); |
@@ -997,8 +997,7 @@ release_irq: | |||
997 | release_regs: | 997 | release_regs: |
998 | iounmap(info->io); | 998 | iounmap(info->io); |
999 | release_mem: | 999 | release_mem: |
1000 | release_resource(info->mem); | 1000 | release_mem_region(res->start, size); |
1001 | kfree(info->mem); | ||
1002 | dealloc_fb: | 1001 | dealloc_fb: |
1003 | platform_set_drvdata(pdev, NULL); | 1002 | platform_set_drvdata(pdev, NULL); |
1004 | framebuffer_release(fbinfo); | 1003 | framebuffer_release(fbinfo); |
@@ -1044,8 +1043,7 @@ static int __devexit s3c2410fb_remove(struct platform_device *pdev) | |||
1044 | 1043 | ||
1045 | iounmap(info->io); | 1044 | iounmap(info->io); |
1046 | 1045 | ||
1047 | release_resource(info->mem); | 1046 | release_mem_region(info->mem->start, resource_size(info->mem)); |
1048 | kfree(info->mem); | ||
1049 | 1047 | ||
1050 | platform_set_drvdata(pdev, NULL); | 1048 | platform_set_drvdata(pdev, NULL); |
1051 | framebuffer_release(fbinfo); | 1049 | framebuffer_release(fbinfo); |
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index c4482f2e5799..4ca5d0c8fe84 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
@@ -25,6 +25,9 @@ | |||
25 | #include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */ | 25 | #include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */ |
26 | #include <video/vga.h> | 26 | #include <video/vga.h> |
27 | 27 | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/i2c-algo-bit.h> | ||
30 | |||
28 | #ifdef CONFIG_MTRR | 31 | #ifdef CONFIG_MTRR |
29 | #include <asm/mtrr.h> | 32 | #include <asm/mtrr.h> |
30 | #endif | 33 | #endif |
@@ -36,6 +39,12 @@ struct s3fb_info { | |||
36 | struct mutex open_lock; | 39 | struct mutex open_lock; |
37 | unsigned int ref_count; | 40 | unsigned int ref_count; |
38 | u32 pseudo_palette[16]; | 41 | u32 pseudo_palette[16]; |
42 | #ifdef CONFIG_FB_S3_DDC | ||
43 | u8 __iomem *mmio; | ||
44 | bool ddc_registered; | ||
45 | struct i2c_adapter ddc_adapter; | ||
46 | struct i2c_algo_bit_data ddc_algo; | ||
47 | #endif | ||
39 | }; | 48 | }; |
40 | 49 | ||
41 | 50 | ||
@@ -105,6 +114,9 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
105 | #define CHIP_UNDECIDED_FLAG 0x80 | 114 | #define CHIP_UNDECIDED_FLAG 0x80 |
106 | #define CHIP_MASK 0xFF | 115 | #define CHIP_MASK 0xFF |
107 | 116 | ||
117 | #define MMIO_OFFSET 0x1000000 | ||
118 | #define MMIO_SIZE 0x10000 | ||
119 | |||
108 | /* CRT timing register sets */ | 120 | /* CRT timing register sets */ |
109 | 121 | ||
110 | static const struct vga_regset s3_h_total_regs[] = {{0x00, 0, 7}, {0x5D, 0, 0}, VGA_REGSET_END}; | 122 | static const struct vga_regset s3_h_total_regs[] = {{0x00, 0, 7}, {0x5D, 0, 0}, VGA_REGSET_END}; |
@@ -140,7 +152,7 @@ static const struct svga_timing_regs s3_timing_regs = { | |||
140 | /* Module parameters */ | 152 | /* Module parameters */ |
141 | 153 | ||
142 | 154 | ||
143 | static char *mode_option __devinitdata = "640x480-8@60"; | 155 | static char *mode_option __devinitdata; |
144 | 156 | ||
145 | #ifdef CONFIG_MTRR | 157 | #ifdef CONFIG_MTRR |
146 | static int mtrr __devinitdata = 1; | 158 | static int mtrr __devinitdata = 1; |
@@ -169,6 +181,119 @@ MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, defau | |||
169 | 181 | ||
170 | /* ------------------------------------------------------------------------- */ | 182 | /* ------------------------------------------------------------------------- */ |
171 | 183 | ||
184 | #ifdef CONFIG_FB_S3_DDC | ||
185 | |||
186 | #define DDC_REG 0xaa /* Trio 3D/1X/2X */ | ||
187 | #define DDC_MMIO_REG 0xff20 /* all other chips */ | ||
188 | #define DDC_SCL_OUT (1 << 0) | ||
189 | #define DDC_SDA_OUT (1 << 1) | ||
190 | #define DDC_SCL_IN (1 << 2) | ||
191 | #define DDC_SDA_IN (1 << 3) | ||
192 | #define DDC_DRIVE_EN (1 << 4) | ||
193 | |||
194 | static bool s3fb_ddc_needs_mmio(int chip) | ||
195 | { | ||
196 | return !(chip == CHIP_360_TRIO3D_1X || | ||
197 | chip == CHIP_362_TRIO3D_2X || | ||
198 | chip == CHIP_368_TRIO3D_2X); | ||
199 | } | ||
200 | |||
201 | static u8 s3fb_ddc_read(struct s3fb_info *par) | ||
202 | { | ||
203 | if (s3fb_ddc_needs_mmio(par->chip)) | ||
204 | return readb(par->mmio + DDC_MMIO_REG); | ||
205 | else | ||
206 | return vga_rcrt(par->state.vgabase, DDC_REG); | ||
207 | } | ||
208 | |||
209 | static void s3fb_ddc_write(struct s3fb_info *par, u8 val) | ||
210 | { | ||
211 | if (s3fb_ddc_needs_mmio(par->chip)) | ||
212 | writeb(val, par->mmio + DDC_MMIO_REG); | ||
213 | else | ||
214 | vga_wcrt(par->state.vgabase, DDC_REG, val); | ||
215 | } | ||
216 | |||
217 | static void s3fb_ddc_setscl(void *data, int val) | ||
218 | { | ||
219 | struct s3fb_info *par = data; | ||
220 | unsigned char reg; | ||
221 | |||
222 | reg = s3fb_ddc_read(par) | DDC_DRIVE_EN; | ||
223 | if (val) | ||
224 | reg |= DDC_SCL_OUT; | ||
225 | else | ||
226 | reg &= ~DDC_SCL_OUT; | ||
227 | s3fb_ddc_write(par, reg); | ||
228 | } | ||
229 | |||
230 | static void s3fb_ddc_setsda(void *data, int val) | ||
231 | { | ||
232 | struct s3fb_info *par = data; | ||
233 | unsigned char reg; | ||
234 | |||
235 | reg = s3fb_ddc_read(par) | DDC_DRIVE_EN; | ||
236 | if (val) | ||
237 | reg |= DDC_SDA_OUT; | ||
238 | else | ||
239 | reg &= ~DDC_SDA_OUT; | ||
240 | s3fb_ddc_write(par, reg); | ||
241 | } | ||
242 | |||
243 | static int s3fb_ddc_getscl(void *data) | ||
244 | { | ||
245 | struct s3fb_info *par = data; | ||
246 | |||
247 | return !!(s3fb_ddc_read(par) & DDC_SCL_IN); | ||
248 | } | ||
249 | |||
250 | static int s3fb_ddc_getsda(void *data) | ||
251 | { | ||
252 | struct s3fb_info *par = data; | ||
253 | |||
254 | return !!(s3fb_ddc_read(par) & DDC_SDA_IN); | ||
255 | } | ||
256 | |||
257 | static int __devinit s3fb_setup_ddc_bus(struct fb_info *info) | ||
258 | { | ||
259 | struct s3fb_info *par = info->par; | ||
260 | |||
261 | strlcpy(par->ddc_adapter.name, info->fix.id, | ||
262 | sizeof(par->ddc_adapter.name)); | ||
263 | par->ddc_adapter.owner = THIS_MODULE; | ||
264 | par->ddc_adapter.class = I2C_CLASS_DDC; | ||
265 | par->ddc_adapter.algo_data = &par->ddc_algo; | ||
266 | par->ddc_adapter.dev.parent = info->device; | ||
267 | par->ddc_algo.setsda = s3fb_ddc_setsda; | ||
268 | par->ddc_algo.setscl = s3fb_ddc_setscl; | ||
269 | par->ddc_algo.getsda = s3fb_ddc_getsda; | ||
270 | par->ddc_algo.getscl = s3fb_ddc_getscl; | ||
271 | par->ddc_algo.udelay = 10; | ||
272 | par->ddc_algo.timeout = 20; | ||
273 | par->ddc_algo.data = par; | ||
274 | |||
275 | i2c_set_adapdata(&par->ddc_adapter, par); | ||
276 | |||
277 | /* | ||
278 | * some Virge cards have external MUX to switch chip I2C bus between | ||
279 | * DDC and extension pins - switch it do DDC | ||
280 | */ | ||
281 | /* vga_wseq(par->state.vgabase, 0x08, 0x06); - not needed, already unlocked */ | ||
282 | if (par->chip == CHIP_357_VIRGE_GX2 || | ||
283 | par->chip == CHIP_359_VIRGE_GX2P) | ||
284 | svga_wseq_mask(par->state.vgabase, 0x0d, 0x01, 0x03); | ||
285 | else | ||
286 | svga_wseq_mask(par->state.vgabase, 0x0d, 0x00, 0x03); | ||
287 | /* some Virge need this or the DDC is ignored */ | ||
288 | svga_wcrt_mask(par->state.vgabase, 0x5c, 0x03, 0x03); | ||
289 | |||
290 | return i2c_bit_add_bus(&par->ddc_adapter); | ||
291 | } | ||
292 | #endif /* CONFIG_FB_S3_DDC */ | ||
293 | |||
294 | |||
295 | /* ------------------------------------------------------------------------- */ | ||
296 | |||
172 | /* Set font in S3 fast text mode */ | 297 | /* Set font in S3 fast text mode */ |
173 | 298 | ||
174 | static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) | 299 | static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) |
@@ -994,6 +1119,7 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
994 | struct s3fb_info *par; | 1119 | struct s3fb_info *par; |
995 | int rc; | 1120 | int rc; |
996 | u8 regval, cr38, cr39; | 1121 | u8 regval, cr38, cr39; |
1122 | bool found = false; | ||
997 | 1123 | ||
998 | /* Ignore secondary VGA device because there is no VGA arbitration */ | 1124 | /* Ignore secondary VGA device because there is no VGA arbitration */ |
999 | if (! svga_primary_device(dev)) { | 1125 | if (! svga_primary_device(dev)) { |
@@ -1110,12 +1236,69 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1110 | info->fix.ypanstep = 0; | 1236 | info->fix.ypanstep = 0; |
1111 | info->fix.accel = FB_ACCEL_NONE; | 1237 | info->fix.accel = FB_ACCEL_NONE; |
1112 | info->pseudo_palette = (void*) (par->pseudo_palette); | 1238 | info->pseudo_palette = (void*) (par->pseudo_palette); |
1239 | info->var.bits_per_pixel = 8; | ||
1240 | |||
1241 | #ifdef CONFIG_FB_S3_DDC | ||
1242 | /* Enable MMIO if needed */ | ||
1243 | if (s3fb_ddc_needs_mmio(par->chip)) { | ||
1244 | par->mmio = ioremap(info->fix.smem_start + MMIO_OFFSET, MMIO_SIZE); | ||
1245 | if (par->mmio) | ||
1246 | svga_wcrt_mask(par->state.vgabase, 0x53, 0x08, 0x08); /* enable MMIO */ | ||
1247 | else | ||
1248 | dev_err(info->device, "unable to map MMIO at 0x%lx, disabling DDC", | ||
1249 | info->fix.smem_start + MMIO_OFFSET); | ||
1250 | } | ||
1251 | if (!s3fb_ddc_needs_mmio(par->chip) || par->mmio) | ||
1252 | if (s3fb_setup_ddc_bus(info) == 0) { | ||
1253 | u8 *edid = fb_ddc_read(&par->ddc_adapter); | ||
1254 | par->ddc_registered = true; | ||
1255 | if (edid) { | ||
1256 | fb_edid_to_monspecs(edid, &info->monspecs); | ||
1257 | kfree(edid); | ||
1258 | if (!info->monspecs.modedb) | ||
1259 | dev_err(info->device, "error getting mode database\n"); | ||
1260 | else { | ||
1261 | const struct fb_videomode *m; | ||
1262 | |||
1263 | fb_videomode_to_modelist(info->monspecs.modedb, | ||
1264 | info->monspecs.modedb_len, | ||
1265 | &info->modelist); | ||
1266 | m = fb_find_best_display(&info->monspecs, &info->modelist); | ||
1267 | if (m) { | ||
1268 | fb_videomode_to_var(&info->var, m); | ||
1269 | /* fill all other info->var's fields */ | ||
1270 | if (s3fb_check_var(&info->var, info) == 0) | ||
1271 | found = true; | ||
1272 | } | ||
1273 | } | ||
1274 | } | ||
1275 | } | ||
1276 | #endif | ||
1277 | if (!mode_option && !found) | ||
1278 | mode_option = "640x480-8@60"; | ||
1113 | 1279 | ||
1114 | /* Prepare startup mode */ | 1280 | /* Prepare startup mode */ |
1115 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); | 1281 | if (mode_option) { |
1116 | if (! ((rc == 1) || (rc == 2))) { | 1282 | rc = fb_find_mode(&info->var, info, mode_option, |
1117 | rc = -EINVAL; | 1283 | info->monspecs.modedb, info->monspecs.modedb_len, |
1118 | dev_err(info->device, "mode %s not found\n", mode_option); | 1284 | NULL, info->var.bits_per_pixel); |
1285 | if (!rc || rc == 4) { | ||
1286 | rc = -EINVAL; | ||
1287 | dev_err(info->device, "mode %s not found\n", mode_option); | ||
1288 | fb_destroy_modedb(info->monspecs.modedb); | ||
1289 | info->monspecs.modedb = NULL; | ||
1290 | goto err_find_mode; | ||
1291 | } | ||
1292 | } | ||
1293 | |||
1294 | fb_destroy_modedb(info->monspecs.modedb); | ||
1295 | info->monspecs.modedb = NULL; | ||
1296 | |||
1297 | /* maximize virtual vertical size for fast scrolling */ | ||
1298 | info->var.yres_virtual = info->fix.smem_len * 8 / | ||
1299 | (info->var.bits_per_pixel * info->var.xres_virtual); | ||
1300 | if (info->var.yres_virtual < info->var.yres) { | ||
1301 | dev_err(info->device, "virtual vertical size smaller than real\n"); | ||
1119 | goto err_find_mode; | 1302 | goto err_find_mode; |
1120 | } | 1303 | } |
1121 | 1304 | ||
@@ -1164,6 +1347,12 @@ err_reg_fb: | |||
1164 | fb_dealloc_cmap(&info->cmap); | 1347 | fb_dealloc_cmap(&info->cmap); |
1165 | err_alloc_cmap: | 1348 | err_alloc_cmap: |
1166 | err_find_mode: | 1349 | err_find_mode: |
1350 | #ifdef CONFIG_FB_S3_DDC | ||
1351 | if (par->ddc_registered) | ||
1352 | i2c_del_adapter(&par->ddc_adapter); | ||
1353 | if (par->mmio) | ||
1354 | iounmap(par->mmio); | ||
1355 | #endif | ||
1167 | pci_iounmap(dev, info->screen_base); | 1356 | pci_iounmap(dev, info->screen_base); |
1168 | err_iomap: | 1357 | err_iomap: |
1169 | pci_release_regions(dev); | 1358 | pci_release_regions(dev); |
@@ -1180,12 +1369,11 @@ err_enable_device: | |||
1180 | static void __devexit s3_pci_remove(struct pci_dev *dev) | 1369 | static void __devexit s3_pci_remove(struct pci_dev *dev) |
1181 | { | 1370 | { |
1182 | struct fb_info *info = pci_get_drvdata(dev); | 1371 | struct fb_info *info = pci_get_drvdata(dev); |
1372 | struct s3fb_info __maybe_unused *par = info->par; | ||
1183 | 1373 | ||
1184 | if (info) { | 1374 | if (info) { |
1185 | 1375 | ||
1186 | #ifdef CONFIG_MTRR | 1376 | #ifdef CONFIG_MTRR |
1187 | struct s3fb_info *par = info->par; | ||
1188 | |||
1189 | if (par->mtrr_reg >= 0) { | 1377 | if (par->mtrr_reg >= 0) { |
1190 | mtrr_del(par->mtrr_reg, 0, 0); | 1378 | mtrr_del(par->mtrr_reg, 0, 0); |
1191 | par->mtrr_reg = -1; | 1379 | par->mtrr_reg = -1; |
@@ -1195,6 +1383,13 @@ static void __devexit s3_pci_remove(struct pci_dev *dev) | |||
1195 | unregister_framebuffer(info); | 1383 | unregister_framebuffer(info); |
1196 | fb_dealloc_cmap(&info->cmap); | 1384 | fb_dealloc_cmap(&info->cmap); |
1197 | 1385 | ||
1386 | #ifdef CONFIG_FB_S3_DDC | ||
1387 | if (par->ddc_registered) | ||
1388 | i2c_del_adapter(&par->ddc_adapter); | ||
1389 | if (par->mmio) | ||
1390 | iounmap(par->mmio); | ||
1391 | #endif | ||
1392 | |||
1198 | pci_iounmap(dev, info->screen_base); | 1393 | pci_iounmap(dev, info->screen_base); |
1199 | pci_release_regions(dev); | 1394 | pci_release_regions(dev); |
1200 | /* pci_disable_device(dev); */ | 1395 | /* pci_disable_device(dev); */ |
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index bb71fea07284..80fa87e2ae2f 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c | |||
@@ -171,6 +171,8 @@ void savagefb_create_i2c_busses(struct fb_info *info) | |||
171 | 171 | ||
172 | switch (par->chip) { | 172 | switch (par->chip) { |
173 | case S3_PROSAVAGE: | 173 | case S3_PROSAVAGE: |
174 | case S3_PROSAVAGEDDR: | ||
175 | case S3_TWISTER: | ||
174 | par->chan.reg = CR_SERIAL2; | 176 | par->chan.reg = CR_SERIAL2; |
175 | par->chan.ioaddr = par->mmio.vbase; | 177 | par->chan.ioaddr = par->mmio.vbase; |
176 | par->chan.algo.setsda = prosavage_gpio_setsda; | 178 | par->chan.algo.setsda = prosavage_gpio_setsda; |
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h index 4e9490c19d7d..32549d177b19 100644 --- a/drivers/video/savage/savagefb.h +++ b/drivers/video/savage/savagefb.h | |||
@@ -36,7 +36,6 @@ | |||
36 | #define PCI_CHIP_SAVAGE_IX 0x8c13 | 36 | #define PCI_CHIP_SAVAGE_IX 0x8c13 |
37 | #define PCI_CHIP_PROSAVAGE_PM 0x8a25 | 37 | #define PCI_CHIP_PROSAVAGE_PM 0x8a25 |
38 | #define PCI_CHIP_PROSAVAGE_KM 0x8a26 | 38 | #define PCI_CHIP_PROSAVAGE_KM 0x8a26 |
39 | /* Twister is a code name; hope I get the real name soon. */ | ||
40 | #define PCI_CHIP_S3TWISTER_P 0x8d01 | 39 | #define PCI_CHIP_S3TWISTER_P 0x8d01 |
41 | #define PCI_CHIP_S3TWISTER_K 0x8d02 | 40 | #define PCI_CHIP_S3TWISTER_K 0x8d02 |
42 | #define PCI_CHIP_PROSAVAGE_DDR 0x8d03 | 41 | #define PCI_CHIP_PROSAVAGE_DDR 0x8d03 |
@@ -52,14 +51,15 @@ | |||
52 | #define PCI_CHIP_SUPSAV_IXCDDR 0x8c2f | 51 | #define PCI_CHIP_SUPSAV_IXCDDR 0x8c2f |
53 | 52 | ||
54 | 53 | ||
54 | #define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) | ||
55 | 55 | ||
56 | #define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX)) | 56 | #define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX)) |
57 | 57 | ||
58 | #define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) || (chip==S3_PROSAVAGE)) | 58 | #define S3_SAVAGE4_SERIES(chip) ((chip>=S3_SAVAGE4) || (chip<=S3_PROSAVAGEDDR)) |
59 | 59 | ||
60 | #define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE)) | 60 | #define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE)) |
61 | 61 | ||
62 | #define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) | 62 | #define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip==S3_PROSAVAGEDDR)) |
63 | 63 | ||
64 | /* Chip tags. These are used to group the adapters into | 64 | /* Chip tags. These are used to group the adapters into |
65 | * related families. | 65 | * related families. |
@@ -71,6 +71,8 @@ typedef enum { | |||
71 | S3_SAVAGE_MX, | 71 | S3_SAVAGE_MX, |
72 | S3_SAVAGE4, | 72 | S3_SAVAGE4, |
73 | S3_PROSAVAGE, | 73 | S3_PROSAVAGE, |
74 | S3_TWISTER, | ||
75 | S3_PROSAVAGEDDR, | ||
74 | S3_SUPERSAVAGE, | 76 | S3_SUPERSAVAGE, |
75 | S3_SAVAGE2000, | 77 | S3_SAVAGE2000, |
76 | S3_LAST | 78 | S3_LAST |
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index a2dc1a7ec758..3b7f2f5bae71 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c | |||
@@ -328,7 +328,9 @@ SavageSetup2DEngine(struct savagefb_par *par) | |||
328 | savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par); | 328 | savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par); |
329 | break; | 329 | break; |
330 | case S3_SAVAGE4: | 330 | case S3_SAVAGE4: |
331 | case S3_TWISTER: | ||
331 | case S3_PROSAVAGE: | 332 | case S3_PROSAVAGE: |
333 | case S3_PROSAVAGEDDR: | ||
332 | case S3_SUPERSAVAGE: | 334 | case S3_SUPERSAVAGE: |
333 | /* Disable BCI */ | 335 | /* Disable BCI */ |
334 | savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par); | 336 | savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par); |
@@ -1886,6 +1888,8 @@ static int savage_init_hw(struct savagefb_par *par) | |||
1886 | break; | 1888 | break; |
1887 | 1889 | ||
1888 | case S3_PROSAVAGE: | 1890 | case S3_PROSAVAGE: |
1891 | case S3_PROSAVAGEDDR: | ||
1892 | case S3_TWISTER: | ||
1889 | videoRam = RamSavageNB[(config1 & 0xE0) >> 5] * 1024; | 1893 | videoRam = RamSavageNB[(config1 & 0xE0) >> 5] * 1024; |
1890 | break; | 1894 | break; |
1891 | 1895 | ||
@@ -1963,7 +1967,8 @@ static int savage_init_hw(struct savagefb_par *par) | |||
1963 | } | 1967 | } |
1964 | } | 1968 | } |
1965 | 1969 | ||
1966 | if (S3_SAVAGE_MOBILE_SERIES(par->chip) && !par->crtonly) | 1970 | if ((S3_SAVAGE_MOBILE_SERIES(par->chip) || |
1971 | S3_MOBILE_TWISTER_SERIES(par->chip)) && !par->crtonly) | ||
1967 | par->display_type = DISP_LCD; | 1972 | par->display_type = DISP_LCD; |
1968 | else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi)) | 1973 | else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi)) |
1969 | par->display_type = DISP_DFP; | 1974 | par->display_type = DISP_DFP; |
@@ -2111,19 +2116,19 @@ static int __devinit savage_init_fb_info(struct fb_info *info, | |||
2111 | snprintf(info->fix.id, 16, "ProSavageKM"); | 2116 | snprintf(info->fix.id, 16, "ProSavageKM"); |
2112 | break; | 2117 | break; |
2113 | case FB_ACCEL_S3TWISTER_P: | 2118 | case FB_ACCEL_S3TWISTER_P: |
2114 | par->chip = S3_PROSAVAGE; | 2119 | par->chip = S3_TWISTER; |
2115 | snprintf(info->fix.id, 16, "TwisterP"); | 2120 | snprintf(info->fix.id, 16, "TwisterP"); |
2116 | break; | 2121 | break; |
2117 | case FB_ACCEL_S3TWISTER_K: | 2122 | case FB_ACCEL_S3TWISTER_K: |
2118 | par->chip = S3_PROSAVAGE; | 2123 | par->chip = S3_TWISTER; |
2119 | snprintf(info->fix.id, 16, "TwisterK"); | 2124 | snprintf(info->fix.id, 16, "TwisterK"); |
2120 | break; | 2125 | break; |
2121 | case FB_ACCEL_PROSAVAGE_DDR: | 2126 | case FB_ACCEL_PROSAVAGE_DDR: |
2122 | par->chip = S3_PROSAVAGE; | 2127 | par->chip = S3_PROSAVAGEDDR; |
2123 | snprintf(info->fix.id, 16, "ProSavageDDR"); | 2128 | snprintf(info->fix.id, 16, "ProSavageDDR"); |
2124 | break; | 2129 | break; |
2125 | case FB_ACCEL_PROSAVAGE_DDRK: | 2130 | case FB_ACCEL_PROSAVAGE_DDRK: |
2126 | par->chip = S3_PROSAVAGE; | 2131 | par->chip = S3_PROSAVAGEDDR; |
2127 | snprintf(info->fix.id, 16, "ProSavage8"); | 2132 | snprintf(info->fix.id, 16, "ProSavage8"); |
2128 | break; | 2133 | break; |
2129 | } | 2134 | } |
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c index 8fe19582c460..45e47d847163 100644 --- a/drivers/video/sh7760fb.c +++ b/drivers/video/sh7760fb.c | |||
@@ -551,8 +551,7 @@ out_unmap: | |||
551 | free_irq(par->irq, &par->vsync); | 551 | free_irq(par->irq, &par->vsync); |
552 | iounmap(par->base); | 552 | iounmap(par->base); |
553 | out_res: | 553 | out_res: |
554 | release_resource(par->ioarea); | 554 | release_mem_region(res->start, resource_size(res)); |
555 | kfree(par->ioarea); | ||
556 | out_fb: | 555 | out_fb: |
557 | framebuffer_release(info); | 556 | framebuffer_release(info); |
558 | return ret; | 557 | return ret; |
@@ -570,8 +569,7 @@ static int __devexit sh7760fb_remove(struct platform_device *dev) | |||
570 | if (par->irq >= 0) | 569 | if (par->irq >= 0) |
571 | free_irq(par->irq, par); | 570 | free_irq(par->irq, par); |
572 | iounmap(par->base); | 571 | iounmap(par->base); |
573 | release_resource(par->ioarea); | 572 | release_mem_region(par->ioarea->start, resource_size(par->ioarea)); |
574 | kfree(par->ioarea); | ||
575 | framebuffer_release(info); | 573 | framebuffer_release(info); |
576 | platform_set_drvdata(dev, NULL); | 574 | platform_set_drvdata(dev, NULL); |
577 | 575 | ||
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 2b9e56a6bde4..6ae40b630dc9 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c | |||
@@ -1131,15 +1131,19 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) | |||
1131 | pm_runtime_get_sync(hdmi->dev); | 1131 | pm_runtime_get_sync(hdmi->dev); |
1132 | 1132 | ||
1133 | ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); | 1133 | ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); |
1134 | if (ret < 0) | 1134 | if (ret < 0) { |
1135 | pm_runtime_put(hdmi->dev); | ||
1135 | goto out; | 1136 | goto out; |
1137 | } | ||
1136 | 1138 | ||
1137 | hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE; | 1139 | hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE; |
1138 | 1140 | ||
1139 | /* Reconfigure the clock */ | 1141 | /* Reconfigure the clock */ |
1140 | ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate); | 1142 | ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate); |
1141 | if (ret < 0) | 1143 | if (ret < 0) { |
1144 | pm_runtime_put(hdmi->dev); | ||
1142 | goto out; | 1145 | goto out; |
1146 | } | ||
1143 | 1147 | ||
1144 | msleep(10); | 1148 | msleep(10); |
1145 | sh_hdmi_configure(hdmi); | 1149 | sh_hdmi_configure(hdmi); |
@@ -1336,6 +1340,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
1336 | ecodec: | 1340 | ecodec: |
1337 | free_irq(irq, hdmi); | 1341 | free_irq(irq, hdmi); |
1338 | ereqirq: | 1342 | ereqirq: |
1343 | pm_runtime_suspend(&pdev->dev); | ||
1339 | pm_runtime_disable(&pdev->dev); | 1344 | pm_runtime_disable(&pdev->dev); |
1340 | iounmap(hdmi->base); | 1345 | iounmap(hdmi->base); |
1341 | emap: | 1346 | emap: |
@@ -1372,6 +1377,7 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) | |||
1372 | free_irq(irq, hdmi); | 1377 | free_irq(irq, hdmi); |
1373 | /* Wait for already scheduled work */ | 1378 | /* Wait for already scheduled work */ |
1374 | cancel_delayed_work_sync(&hdmi->edid_work); | 1379 | cancel_delayed_work_sync(&hdmi->edid_work); |
1380 | pm_runtime_suspend(&pdev->dev); | ||
1375 | pm_runtime_disable(&pdev->dev); | 1381 | pm_runtime_disable(&pdev->dev); |
1376 | clk_disable(hdmi->hdmi_clk); | 1382 | clk_disable(hdmi->hdmi_clk); |
1377 | clk_put(hdmi->hdmi_clk); | 1383 | clk_put(hdmi->hdmi_clk); |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 9bcc61b4ef14..404c03b4b7c7 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/atomic.h> | 27 | #include <asm/atomic.h> |
28 | 28 | ||
29 | #include "sh_mobile_lcdcfb.h" | 29 | #include "sh_mobile_lcdcfb.h" |
30 | #include "sh_mobile_meram.h" | ||
30 | 31 | ||
31 | #define SIDE_B_OFFSET 0x1000 | 32 | #define SIDE_B_OFFSET 0x1000 |
32 | #define MIRROR_OFFSET 0x2000 | 33 | #define MIRROR_OFFSET 0x2000 |
@@ -143,6 +144,7 @@ struct sh_mobile_lcdc_priv { | |||
143 | unsigned long saved_shared_regs[NR_SHARED_REGS]; | 144 | unsigned long saved_shared_regs[NR_SHARED_REGS]; |
144 | int started; | 145 | int started; |
145 | int forced_bpp; /* 2 channel LCDC must share bpp setting */ | 146 | int forced_bpp; /* 2 channel LCDC must share bpp setting */ |
147 | struct sh_mobile_meram_info *meram_dev; | ||
146 | }; | 148 | }; |
147 | 149 | ||
148 | static bool banked(int reg_nr) | 150 | static bool banked(int reg_nr) |
@@ -469,7 +471,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
469 | int bpp = 0; | 471 | int bpp = 0; |
470 | unsigned long ldddsr; | 472 | unsigned long ldddsr; |
471 | int k, m; | 473 | int k, m; |
472 | int ret = 0; | ||
473 | 474 | ||
474 | /* enable clocks before accessing the hardware */ | 475 | /* enable clocks before accessing the hardware */ |
475 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 476 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
@@ -538,11 +539,12 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
538 | lcdc_write_chan(ch, LDPMR, 0); | 539 | lcdc_write_chan(ch, LDPMR, 0); |
539 | 540 | ||
540 | board_cfg = &ch->cfg.board_cfg; | 541 | board_cfg = &ch->cfg.board_cfg; |
541 | if (board_cfg->setup_sys) | 542 | if (board_cfg->setup_sys) { |
542 | ret = board_cfg->setup_sys(board_cfg->board_data, ch, | 543 | int ret = board_cfg->setup_sys(board_cfg->board_data, |
543 | &sh_mobile_lcdc_sys_bus_ops); | 544 | ch, &sh_mobile_lcdc_sys_bus_ops); |
544 | if (ret) | 545 | if (ret) |
545 | return ret; | 546 | return ret; |
547 | } | ||
546 | } | 548 | } |
547 | 549 | ||
548 | /* word and long word swap */ | 550 | /* word and long word swap */ |
@@ -564,6 +566,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
564 | } | 566 | } |
565 | 567 | ||
566 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 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; | ||
567 | ch = &priv->ch[k]; | 572 | ch = &priv->ch[k]; |
568 | 573 | ||
569 | if (!priv->ch[k].enabled) | 574 | if (!priv->ch[k].enabled) |
@@ -598,16 +603,68 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
598 | } | 603 | } |
599 | lcdc_write_chan(ch, LDDFR, tmp); | 604 | lcdc_write_chan(ch, LDDFR, tmp); |
600 | 605 | ||
606 | base_addr_y = ch->info->fix.smem_start; | ||
607 | base_addr_c = base_addr_y + | ||
608 | ch->info->var.xres * | ||
609 | ch->info->var.yres_virtual; | ||
610 | pitch = ch->info->fix.line_length; | ||
611 | |||
612 | /* test if we can enable meram */ | ||
613 | if (ch->cfg.meram_cfg && priv->meram_dev && | ||
614 | priv->meram_dev->ops) { | ||
615 | struct sh_mobile_meram_cfg *cfg; | ||
616 | struct sh_mobile_meram_info *mdev; | ||
617 | unsigned long icb_addr_y, icb_addr_c; | ||
618 | int icb_pitch; | ||
619 | int pf; | ||
620 | |||
621 | cfg = ch->cfg.meram_cfg; | ||
622 | mdev = priv->meram_dev; | ||
623 | /* we need to de-init configured ICBs before we | ||
624 | * we can re-initialize them. | ||
625 | */ | ||
626 | if (ch->meram_enabled) | ||
627 | mdev->ops->meram_unregister(mdev, cfg); | ||
628 | |||
629 | ch->meram_enabled = 0; | ||
630 | |||
631 | if (ch->info->var.nonstd) { | ||
632 | if (ch->info->var.bits_per_pixel == 24) | ||
633 | pf = SH_MOBILE_MERAM_PF_NV24; | ||
634 | else | ||
635 | pf = SH_MOBILE_MERAM_PF_NV; | ||
636 | } else { | ||
637 | pf = SH_MOBILE_MERAM_PF_RGB; | ||
638 | } | ||
639 | |||
640 | ret = mdev->ops->meram_register(mdev, cfg, pitch, | ||
641 | ch->info->var.yres, | ||
642 | pf, | ||
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 | |||
601 | /* point out our frame buffer */ | 661 | /* point out our frame buffer */ |
602 | lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start); | 662 | lcdc_write_chan(ch, LDSA1R, base_addr_y); |
603 | if (ch->info->var.nonstd) | 663 | if (ch->info->var.nonstd) |
604 | lcdc_write_chan(ch, LDSA2R, | 664 | lcdc_write_chan(ch, LDSA2R, base_addr_c); |
605 | ch->info->fix.smem_start + | ||
606 | ch->info->var.xres * | ||
607 | ch->info->var.yres_virtual); | ||
608 | 665 | ||
609 | /* set line size */ | 666 | /* set line size */ |
610 | lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length); | 667 | lcdc_write_chan(ch, LDMLSR, pitch); |
611 | 668 | ||
612 | /* setup deferred io if SYS bus */ | 669 | /* setup deferred io if SYS bus */ |
613 | tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; | 670 | tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; |
@@ -692,6 +749,17 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) | |||
692 | board_cfg->display_off(board_cfg->board_data); | 749 | board_cfg->display_off(board_cfg->board_data); |
693 | module_put(board_cfg->owner); | 750 | module_put(board_cfg->owner); |
694 | } | 751 | } |
752 | |||
753 | /* disable the meram */ | ||
754 | if (ch->meram_enabled) { | ||
755 | struct sh_mobile_meram_cfg *cfg; | ||
756 | struct sh_mobile_meram_info *mdev; | ||
757 | cfg = ch->cfg.meram_cfg; | ||
758 | mdev = priv->meram_dev; | ||
759 | mdev->ops->meram_unregister(mdev, cfg); | ||
760 | ch->meram_enabled = 0; | ||
761 | } | ||
762 | |||
695 | } | 763 | } |
696 | 764 | ||
697 | /* stop the lcdc */ | 765 | /* stop the lcdc */ |
@@ -875,9 +943,29 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, | |||
875 | } else | 943 | } else |
876 | base_addr_c = 0; | 944 | base_addr_c = 0; |
877 | 945 | ||
878 | lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); | 946 | if (!ch->meram_enabled) { |
879 | if (base_addr_c) | 947 | lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); |
880 | lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); | 948 | if (base_addr_c) |
949 | lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); | ||
950 | } else { | ||
951 | struct sh_mobile_meram_cfg *cfg; | ||
952 | struct sh_mobile_meram_info *mdev; | ||
953 | unsigned long icb_addr_y, icb_addr_c; | ||
954 | int ret; | ||
955 | |||
956 | cfg = ch->cfg.meram_cfg; | ||
957 | mdev = priv->meram_dev; | ||
958 | ret = mdev->ops->meram_update(mdev, cfg, | ||
959 | base_addr_y, base_addr_c, | ||
960 | &icb_addr_y, &icb_addr_c); | ||
961 | if (ret) | ||
962 | return ret; | ||
963 | |||
964 | lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y); | ||
965 | if (icb_addr_c) | ||
966 | lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c); | ||
967 | |||
968 | } | ||
881 | 969 | ||
882 | if (lcdc_chan_is_sublcd(ch)) | 970 | if (lcdc_chan_is_sublcd(ch)) |
883 | lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); | 971 | lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); |
@@ -1288,7 +1376,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, | |||
1288 | struct fb_info *info = event->info; | 1376 | struct fb_info *info = event->info; |
1289 | struct sh_mobile_lcdc_chan *ch = info->par; | 1377 | struct sh_mobile_lcdc_chan *ch = info->par; |
1290 | struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; | 1378 | struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; |
1291 | int ret; | ||
1292 | 1379 | ||
1293 | if (&ch->lcdc->notifier != nb) | 1380 | if (&ch->lcdc->notifier != nb) |
1294 | return NOTIFY_DONE; | 1381 | return NOTIFY_DONE; |
@@ -1302,7 +1389,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, | |||
1302 | board_cfg->display_off(board_cfg->board_data); | 1389 | board_cfg->display_off(board_cfg->board_data); |
1303 | module_put(board_cfg->owner); | 1390 | module_put(board_cfg->owner); |
1304 | } | 1391 | } |
1305 | pm_runtime_put(info->device); | ||
1306 | sh_mobile_lcdc_stop(ch->lcdc); | 1392 | sh_mobile_lcdc_stop(ch->lcdc); |
1307 | break; | 1393 | break; |
1308 | case FB_EVENT_RESUME: | 1394 | case FB_EVENT_RESUME: |
@@ -1316,9 +1402,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, | |||
1316 | module_put(board_cfg->owner); | 1402 | module_put(board_cfg->owner); |
1317 | } | 1403 | } |
1318 | 1404 | ||
1319 | ret = sh_mobile_lcdc_start(ch->lcdc); | 1405 | sh_mobile_lcdc_start(ch->lcdc); |
1320 | if (!ret) | ||
1321 | pm_runtime_get_sync(info->device); | ||
1322 | } | 1406 | } |
1323 | 1407 | ||
1324 | return NOTIFY_OK; | 1408 | return NOTIFY_OK; |
@@ -1420,6 +1504,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1420 | goto err1; | 1504 | goto err1; |
1421 | } | 1505 | } |
1422 | 1506 | ||
1507 | priv->meram_dev = pdata->meram_dev; | ||
1508 | |||
1423 | for (i = 0; i < j; i++) { | 1509 | for (i = 0; i < j; i++) { |
1424 | struct fb_var_screeninfo *var; | 1510 | struct fb_var_screeninfo *var; |
1425 | const struct fb_videomode *lcd_cfg, *max_cfg = NULL; | 1511 | const struct fb_videomode *lcd_cfg, *max_cfg = NULL; |
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h index f16cb5645a13..aeed6687e6a7 100644 --- a/drivers/video/sh_mobile_lcdcfb.h +++ b/drivers/video/sh_mobile_lcdcfb.h | |||
@@ -39,6 +39,7 @@ struct sh_mobile_lcdc_chan { | |||
39 | int use_count; | 39 | int use_count; |
40 | int blank_status; | 40 | int blank_status; |
41 | struct mutex open_lock; /* protects the use counter */ | 41 | struct mutex open_lock; /* protects the use counter */ |
42 | int meram_enabled; | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | #endif | 45 | #endif |
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c new file mode 100644 index 000000000000..9170c82b495c --- /dev/null +++ b/drivers/video/sh_mobile_meram.c | |||
@@ -0,0 +1,567 @@ | |||
1 | /* | ||
2 | * SuperH Mobile MERAM Driver for SuperH Mobile LCDC Driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Damian Hobson-Garcia <dhobsong@igel.co.jp> | ||
5 | * Takanari Hayama <taki@igel.co.jp> | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file "COPYING" in the main directory of this archive | ||
9 | * for more details. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #include "sh_mobile_meram.h" | ||
20 | |||
21 | /* meram registers */ | ||
22 | #define MExxCTL 0x0 | ||
23 | #define MExxBSIZE 0x4 | ||
24 | #define MExxMNCF 0x8 | ||
25 | #define MExxSARA 0x10 | ||
26 | #define MExxSARB 0x14 | ||
27 | #define MExxSBSIZE 0x18 | ||
28 | |||
29 | #define MERAM_MExxCTL_VAL(ctl, next_icb, addr) \ | ||
30 | ((ctl) | (((next_icb) & 0x1f) << 11) | (((addr) & 0x7ff) << 16)) | ||
31 | #define MERAM_MExxBSIZE_VAL(a, b, c) \ | ||
32 | (((a) << 28) | ((b) << 16) | (c)) | ||
33 | |||
34 | #define MEVCR1 0x4 | ||
35 | #define MEACTS 0x10 | ||
36 | #define MEQSEL1 0x40 | ||
37 | #define MEQSEL2 0x44 | ||
38 | |||
39 | /* settings */ | ||
40 | #define MERAM_SEC_LINE 15 | ||
41 | #define MERAM_LINE_WIDTH 2048 | ||
42 | |||
43 | /* | ||
44 | * MERAM/ICB access functions | ||
45 | */ | ||
46 | |||
47 | #define MERAM_ICB_OFFSET(base, idx, off) \ | ||
48 | ((base) + (0x400 + ((idx) * 0x20) + (off))) | ||
49 | |||
50 | static inline void meram_write_icb(void __iomem *base, int idx, int off, | ||
51 | unsigned long val) | ||
52 | { | ||
53 | iowrite32(val, MERAM_ICB_OFFSET(base, idx, off)); | ||
54 | } | ||
55 | |||
56 | static inline unsigned long meram_read_icb(void __iomem *base, int idx, int off) | ||
57 | { | ||
58 | return ioread32(MERAM_ICB_OFFSET(base, idx, off)); | ||
59 | } | ||
60 | |||
61 | static inline void meram_write_reg(void __iomem *base, int off, | ||
62 | unsigned long val) | ||
63 | { | ||
64 | iowrite32(val, base + off); | ||
65 | } | ||
66 | |||
67 | static inline unsigned long meram_read_reg(void __iomem *base, int off) | ||
68 | { | ||
69 | return ioread32(base + off); | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * register ICB | ||
74 | */ | ||
75 | |||
76 | #define MERAM_CACHE_START(p) ((p) >> 16) | ||
77 | #define MERAM_CACHE_END(p) ((p) & 0xffff) | ||
78 | #define MERAM_CACHE_SET(o, s) ((((o) & 0xffff) << 16) | \ | ||
79 | (((o) + (s) - 1) & 0xffff)) | ||
80 | |||
81 | /* | ||
82 | * check if there's no overlaps in MERAM allocation. | ||
83 | */ | ||
84 | |||
85 | static inline int meram_check_overlap(struct sh_mobile_meram_priv *priv, | ||
86 | struct sh_mobile_meram_icb *new) | ||
87 | { | ||
88 | int i; | ||
89 | int used_start, used_end, meram_start, meram_end; | ||
90 | |||
91 | /* valid ICB? */ | ||
92 | if (new->marker_icb & ~0x1f || new->cache_icb & ~0x1f) | ||
93 | return 1; | ||
94 | |||
95 | if (test_bit(new->marker_icb, &priv->used_icb) || | ||
96 | test_bit(new->cache_icb, &priv->used_icb)) | ||
97 | return 1; | ||
98 | |||
99 | for (i = 0; i < priv->used_meram_cache_regions; i++) { | ||
100 | used_start = MERAM_CACHE_START(priv->used_meram_cache[i]); | ||
101 | used_end = MERAM_CACHE_END(priv->used_meram_cache[i]); | ||
102 | meram_start = new->meram_offset; | ||
103 | meram_end = new->meram_offset + new->meram_size; | ||
104 | |||
105 | if ((meram_start >= used_start && meram_start < used_end) || | ||
106 | (meram_end > used_start && meram_end < used_end)) | ||
107 | return 1; | ||
108 | } | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * mark the specified ICB as used | ||
115 | */ | ||
116 | |||
117 | static inline void meram_mark(struct sh_mobile_meram_priv *priv, | ||
118 | struct sh_mobile_meram_icb *new) | ||
119 | { | ||
120 | int n; | ||
121 | |||
122 | if (new->marker_icb < 0 || new->cache_icb < 0) | ||
123 | return; | ||
124 | |||
125 | __set_bit(new->marker_icb, &priv->used_icb); | ||
126 | __set_bit(new->cache_icb, &priv->used_icb); | ||
127 | |||
128 | n = priv->used_meram_cache_regions; | ||
129 | |||
130 | priv->used_meram_cache[n] = MERAM_CACHE_SET(new->meram_offset, | ||
131 | new->meram_size); | ||
132 | |||
133 | priv->used_meram_cache_regions++; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * unmark the specified ICB as used | ||
138 | */ | ||
139 | |||
140 | static inline void meram_unmark(struct sh_mobile_meram_priv *priv, | ||
141 | struct sh_mobile_meram_icb *icb) | ||
142 | { | ||
143 | int i; | ||
144 | unsigned long pattern; | ||
145 | |||
146 | if (icb->marker_icb < 0 || icb->cache_icb < 0) | ||
147 | return; | ||
148 | |||
149 | __clear_bit(icb->marker_icb, &priv->used_icb); | ||
150 | __clear_bit(icb->cache_icb, &priv->used_icb); | ||
151 | |||
152 | pattern = MERAM_CACHE_SET(icb->meram_offset, icb->meram_size); | ||
153 | for (i = 0; i < priv->used_meram_cache_regions; i++) { | ||
154 | if (priv->used_meram_cache[i] == pattern) { | ||
155 | while (i < priv->used_meram_cache_regions - 1) { | ||
156 | priv->used_meram_cache[i] = | ||
157 | priv->used_meram_cache[i + 1] ; | ||
158 | i++; | ||
159 | } | ||
160 | priv->used_meram_cache[i] = 0; | ||
161 | priv->used_meram_cache_regions--; | ||
162 | break; | ||
163 | } | ||
164 | } | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * is this a YCbCr(NV12, NV16 or NV24) colorspace | ||
169 | */ | ||
170 | static inline int is_nvcolor(int cspace) | ||
171 | { | ||
172 | if (cspace == SH_MOBILE_MERAM_PF_NV || | ||
173 | cspace == SH_MOBILE_MERAM_PF_NV24) | ||
174 | return 1; | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * set the next address to fetch | ||
180 | */ | ||
181 | static inline void meram_set_next_addr(struct sh_mobile_meram_priv *priv, | ||
182 | struct sh_mobile_meram_cfg *cfg, | ||
183 | unsigned long base_addr_y, | ||
184 | unsigned long base_addr_c) | ||
185 | { | ||
186 | unsigned long target; | ||
187 | |||
188 | target = (cfg->current_reg) ? MExxSARA : MExxSARB; | ||
189 | cfg->current_reg ^= 1; | ||
190 | |||
191 | /* set the next address to fetch */ | ||
192 | meram_write_icb(priv->base, cfg->icb[0].cache_icb, target, | ||
193 | base_addr_y); | ||
194 | meram_write_icb(priv->base, cfg->icb[0].marker_icb, target, | ||
195 | base_addr_y + cfg->icb[0].cache_unit); | ||
196 | |||
197 | if (is_nvcolor(cfg->pixelformat)) { | ||
198 | meram_write_icb(priv->base, cfg->icb[1].cache_icb, target, | ||
199 | base_addr_c); | ||
200 | meram_write_icb(priv->base, cfg->icb[1].marker_icb, target, | ||
201 | base_addr_c + cfg->icb[1].cache_unit); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * get the next ICB address | ||
207 | */ | ||
208 | static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, | ||
209 | struct sh_mobile_meram_cfg *cfg, | ||
210 | unsigned long *icb_addr_y, | ||
211 | unsigned long *icb_addr_c) | ||
212 | { | ||
213 | unsigned long icb_offset; | ||
214 | |||
215 | if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0) | ||
216 | icb_offset = 0x80000000 | (cfg->current_reg << 29); | ||
217 | else | ||
218 | icb_offset = 0xc0000000 | (cfg->current_reg << 23); | ||
219 | |||
220 | *icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24); | ||
221 | if ((*icb_addr_c) && is_nvcolor(cfg->pixelformat)) | ||
222 | *icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24); | ||
223 | } | ||
224 | |||
225 | #define MERAM_CALC_BYTECOUNT(x, y) \ | ||
226 | (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1)) | ||
227 | |||
228 | /* | ||
229 | * initialize MERAM | ||
230 | */ | ||
231 | |||
232 | static int meram_init(struct sh_mobile_meram_priv *priv, | ||
233 | struct sh_mobile_meram_icb *icb, | ||
234 | int xres, int yres, int *out_pitch) | ||
235 | { | ||
236 | unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres); | ||
237 | unsigned long bnm; | ||
238 | int lcdc_pitch, xpitch, line_cnt; | ||
239 | int save_lines; | ||
240 | |||
241 | /* adjust pitch to 1024, 2048, 4096 or 8192 */ | ||
242 | lcdc_pitch = (xres - 1) | 1023; | ||
243 | lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 1); | ||
244 | lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 2); | ||
245 | lcdc_pitch += 1; | ||
246 | |||
247 | /* derive settings */ | ||
248 | if (lcdc_pitch == 8192 && yres >= 1024) { | ||
249 | lcdc_pitch = xpitch = MERAM_LINE_WIDTH; | ||
250 | line_cnt = total_byte_count >> 11; | ||
251 | *out_pitch = xres; | ||
252 | save_lines = (icb->meram_size / 16 / MERAM_SEC_LINE); | ||
253 | save_lines *= MERAM_SEC_LINE; | ||
254 | } else { | ||
255 | xpitch = xres; | ||
256 | line_cnt = yres; | ||
257 | *out_pitch = lcdc_pitch; | ||
258 | save_lines = icb->meram_size / (lcdc_pitch >> 10) / 2; | ||
259 | save_lines &= 0xff; | ||
260 | } | ||
261 | bnm = (save_lines - 1) << 16; | ||
262 | |||
263 | /* TODO: we better to check if we have enough MERAM buffer size */ | ||
264 | |||
265 | /* set up ICB */ | ||
266 | meram_write_icb(priv->base, icb->cache_icb, MExxBSIZE, | ||
267 | MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1)); | ||
268 | meram_write_icb(priv->base, icb->marker_icb, MExxBSIZE, | ||
269 | MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1)); | ||
270 | |||
271 | meram_write_icb(priv->base, icb->cache_icb, MExxMNCF, bnm); | ||
272 | meram_write_icb(priv->base, icb->marker_icb, MExxMNCF, bnm); | ||
273 | |||
274 | meram_write_icb(priv->base, icb->cache_icb, MExxSBSIZE, xpitch); | ||
275 | meram_write_icb(priv->base, icb->marker_icb, MExxSBSIZE, xpitch); | ||
276 | |||
277 | /* save a cache unit size */ | ||
278 | icb->cache_unit = xres * save_lines; | ||
279 | |||
280 | /* | ||
281 | * Set MERAM for framebuffer | ||
282 | * | ||
283 | * 0x70f: WD = 0x3, WS=0x1, CM=0x1, MD=FB mode | ||
284 | * we also chain the cache_icb and the marker_icb. | ||
285 | * we also split the allocated MERAM buffer between two ICBs. | ||
286 | */ | ||
287 | meram_write_icb(priv->base, icb->cache_icb, MExxCTL, | ||
288 | MERAM_MExxCTL_VAL(0x70f, icb->marker_icb, | ||
289 | icb->meram_offset)); | ||
290 | meram_write_icb(priv->base, icb->marker_icb, MExxCTL, | ||
291 | MERAM_MExxCTL_VAL(0x70f, icb->cache_icb, | ||
292 | icb->meram_offset + | ||
293 | icb->meram_size / 2)); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static void meram_deinit(struct sh_mobile_meram_priv *priv, | ||
299 | struct sh_mobile_meram_icb *icb) | ||
300 | { | ||
301 | /* disable ICB */ | ||
302 | meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 0); | ||
303 | meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 0); | ||
304 | icb->cache_unit = 0; | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * register the ICB | ||
309 | */ | ||
310 | |||
311 | static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, | ||
312 | struct sh_mobile_meram_cfg *cfg, | ||
313 | int xres, int yres, int pixelformat, | ||
314 | unsigned long base_addr_y, | ||
315 | unsigned long base_addr_c, | ||
316 | unsigned long *icb_addr_y, | ||
317 | unsigned long *icb_addr_c, | ||
318 | int *pitch) | ||
319 | { | ||
320 | struct platform_device *pdev; | ||
321 | struct sh_mobile_meram_priv *priv; | ||
322 | int n, out_pitch; | ||
323 | int error = 0; | ||
324 | |||
325 | if (!pdata || !pdata->priv || !pdata->pdev || !cfg) | ||
326 | return -EINVAL; | ||
327 | |||
328 | if (pixelformat != SH_MOBILE_MERAM_PF_NV && | ||
329 | pixelformat != SH_MOBILE_MERAM_PF_NV24 && | ||
330 | pixelformat != SH_MOBILE_MERAM_PF_RGB) | ||
331 | return -EINVAL; | ||
332 | |||
333 | priv = pdata->priv; | ||
334 | pdev = pdata->pdev; | ||
335 | |||
336 | dev_dbg(&pdev->dev, "registering %dx%d (%s) (y=%08lx, c=%08lx)", | ||
337 | xres, yres, (!pixelformat) ? "yuv" : "rgb", | ||
338 | base_addr_y, base_addr_c); | ||
339 | |||
340 | mutex_lock(&priv->lock); | ||
341 | |||
342 | /* we can't handle wider than 8192px */ | ||
343 | if (xres > 8192) { | ||
344 | dev_err(&pdev->dev, "width exceeding the limit (> 8192)."); | ||
345 | error = -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 | } | ||
354 | |||
355 | /* do we have at least one ICB config? */ | ||
356 | if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) { | ||
357 | dev_err(&pdev->dev, "at least one ICB is required."); | ||
358 | error = -EINVAL; | ||
359 | goto err; | ||
360 | } | ||
361 | |||
362 | /* make sure that there's no overlaps */ | ||
363 | if (meram_check_overlap(priv, &cfg->icb[0])) { | ||
364 | dev_err(&pdev->dev, "conflicting config detected."); | ||
365 | error = -EINVAL; | ||
366 | goto err; | ||
367 | } | ||
368 | n = 1; | ||
369 | |||
370 | /* do the same if we have the second ICB set */ | ||
371 | if (cfg->icb[1].marker_icb >= 0 && cfg->icb[1].cache_icb >= 0) { | ||
372 | if (meram_check_overlap(priv, &cfg->icb[1])) { | ||
373 | dev_err(&pdev->dev, "conflicting config detected."); | ||
374 | error = -EINVAL; | ||
375 | goto err; | ||
376 | } | ||
377 | n = 2; | ||
378 | } | ||
379 | |||
380 | if (is_nvcolor(pixelformat) && n != 2) { | ||
381 | dev_err(&pdev->dev, "requires two ICB sets for planar Y/C."); | ||
382 | error = -EINVAL; | ||
383 | goto err; | ||
384 | } | ||
385 | |||
386 | /* we now register the ICB */ | ||
387 | cfg->pixelformat = pixelformat; | ||
388 | meram_mark(priv, &cfg->icb[0]); | ||
389 | if (is_nvcolor(pixelformat)) | ||
390 | meram_mark(priv, &cfg->icb[1]); | ||
391 | |||
392 | /* initialize MERAM */ | ||
393 | meram_init(priv, &cfg->icb[0], xres, yres, &out_pitch); | ||
394 | *pitch = out_pitch; | ||
395 | if (pixelformat == SH_MOBILE_MERAM_PF_NV) | ||
396 | meram_init(priv, &cfg->icb[1], xres, (yres + 1) / 2, | ||
397 | &out_pitch); | ||
398 | else if (pixelformat == SH_MOBILE_MERAM_PF_NV24) | ||
399 | meram_init(priv, &cfg->icb[1], 2 * xres, (yres + 1) / 2, | ||
400 | &out_pitch); | ||
401 | |||
402 | cfg->current_reg = 1; | ||
403 | meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c); | ||
404 | meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c); | ||
405 | |||
406 | dev_dbg(&pdev->dev, "registered - can access via y=%08lx, c=%08lx", | ||
407 | *icb_addr_y, *icb_addr_c); | ||
408 | |||
409 | err: | ||
410 | mutex_unlock(&priv->lock); | ||
411 | return error; | ||
412 | } | ||
413 | |||
414 | static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, | ||
415 | struct sh_mobile_meram_cfg *cfg) | ||
416 | { | ||
417 | struct sh_mobile_meram_priv *priv; | ||
418 | |||
419 | if (!pdata || !pdata->priv || !cfg) | ||
420 | return -EINVAL; | ||
421 | |||
422 | priv = pdata->priv; | ||
423 | |||
424 | mutex_lock(&priv->lock); | ||
425 | |||
426 | /* deinit & unmark */ | ||
427 | if (is_nvcolor(cfg->pixelformat)) { | ||
428 | meram_deinit(priv, &cfg->icb[1]); | ||
429 | meram_unmark(priv, &cfg->icb[1]); | ||
430 | } | ||
431 | meram_deinit(priv, &cfg->icb[0]); | ||
432 | meram_unmark(priv, &cfg->icb[0]); | ||
433 | |||
434 | mutex_unlock(&priv->lock); | ||
435 | |||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, | ||
440 | struct sh_mobile_meram_cfg *cfg, | ||
441 | unsigned long base_addr_y, | ||
442 | unsigned long base_addr_c, | ||
443 | unsigned long *icb_addr_y, | ||
444 | unsigned long *icb_addr_c) | ||
445 | { | ||
446 | struct sh_mobile_meram_priv *priv; | ||
447 | |||
448 | if (!pdata || !pdata->priv || !cfg) | ||
449 | return -EINVAL; | ||
450 | |||
451 | priv = pdata->priv; | ||
452 | |||
453 | mutex_lock(&priv->lock); | ||
454 | |||
455 | meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c); | ||
456 | meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c); | ||
457 | |||
458 | mutex_unlock(&priv->lock); | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | static struct sh_mobile_meram_ops sh_mobile_meram_ops = { | ||
464 | .module = THIS_MODULE, | ||
465 | .meram_register = sh_mobile_meram_register, | ||
466 | .meram_unregister = sh_mobile_meram_unregister, | ||
467 | .meram_update = sh_mobile_meram_update, | ||
468 | }; | ||
469 | |||
470 | /* | ||
471 | * initialize MERAM | ||
472 | */ | ||
473 | |||
474 | static int sh_mobile_meram_remove(struct platform_device *pdev); | ||
475 | |||
476 | static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) | ||
477 | { | ||
478 | struct sh_mobile_meram_priv *priv; | ||
479 | struct sh_mobile_meram_info *pdata = pdev->dev.platform_data; | ||
480 | struct resource *res; | ||
481 | int error; | ||
482 | |||
483 | if (!pdata) { | ||
484 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | |||
488 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
489 | if (!res) { | ||
490 | dev_err(&pdev->dev, "cannot get platform resources\n"); | ||
491 | return -ENOENT; | ||
492 | } | ||
493 | |||
494 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
495 | if (!priv) { | ||
496 | dev_err(&pdev->dev, "cannot allocate device data\n"); | ||
497 | return -ENOMEM; | ||
498 | } | ||
499 | |||
500 | platform_set_drvdata(pdev, priv); | ||
501 | |||
502 | /* initialize private data */ | ||
503 | mutex_init(&priv->lock); | ||
504 | priv->base = ioremap_nocache(res->start, resource_size(res)); | ||
505 | if (!priv->base) { | ||
506 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
507 | error = -EFAULT; | ||
508 | goto err; | ||
509 | } | ||
510 | pdata->ops = &sh_mobile_meram_ops; | ||
511 | pdata->priv = priv; | ||
512 | pdata->pdev = pdev; | ||
513 | |||
514 | /* initialize ICB addressing mode */ | ||
515 | if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1) | ||
516 | meram_write_reg(priv->base, MEVCR1, 1 << 29); | ||
517 | |||
518 | dev_info(&pdev->dev, "sh_mobile_meram initialized."); | ||
519 | |||
520 | return 0; | ||
521 | |||
522 | err: | ||
523 | sh_mobile_meram_remove(pdev); | ||
524 | |||
525 | return error; | ||
526 | } | ||
527 | |||
528 | |||
529 | static int sh_mobile_meram_remove(struct platform_device *pdev) | ||
530 | { | ||
531 | struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); | ||
532 | |||
533 | if (priv->base) | ||
534 | iounmap(priv->base); | ||
535 | |||
536 | mutex_destroy(&priv->lock); | ||
537 | |||
538 | kfree(priv); | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static struct platform_driver sh_mobile_meram_driver = { | ||
544 | .driver = { | ||
545 | .name = "sh_mobile_meram", | ||
546 | .owner = THIS_MODULE, | ||
547 | }, | ||
548 | .probe = sh_mobile_meram_probe, | ||
549 | .remove = sh_mobile_meram_remove, | ||
550 | }; | ||
551 | |||
552 | static int __init sh_mobile_meram_init(void) | ||
553 | { | ||
554 | return platform_driver_register(&sh_mobile_meram_driver); | ||
555 | } | ||
556 | |||
557 | static void __exit sh_mobile_meram_exit(void) | ||
558 | { | ||
559 | platform_driver_unregister(&sh_mobile_meram_driver); | ||
560 | } | ||
561 | |||
562 | module_init(sh_mobile_meram_init); | ||
563 | module_exit(sh_mobile_meram_exit); | ||
564 | |||
565 | MODULE_DESCRIPTION("SuperH Mobile MERAM driver"); | ||
566 | MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama"); | ||
567 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/sh_mobile_meram.h b/drivers/video/sh_mobile_meram.h new file mode 100644 index 000000000000..82c54fbce8bd --- /dev/null +++ b/drivers/video/sh_mobile_meram.h | |||
@@ -0,0 +1,41 @@ | |||
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 | |||
20 | struct 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 | |||
28 | int 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 | |||
36 | void 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/sm501fb.c b/drivers/video/sm501fb.c index 56ef6b3a9851..87f0be1e78b5 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -1625,22 +1625,22 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
1625 | return 0; /* everything is setup */ | 1625 | return 0; /* everything is setup */ |
1626 | 1626 | ||
1627 | err_mem_res: | 1627 | err_mem_res: |
1628 | release_resource(info->fbmem_res); | 1628 | release_mem_region(info->fbmem_res->start, |
1629 | kfree(info->fbmem_res); | 1629 | resource_size(info->fbmem_res)); |
1630 | 1630 | ||
1631 | err_regs2d_map: | 1631 | err_regs2d_map: |
1632 | iounmap(info->regs2d); | 1632 | iounmap(info->regs2d); |
1633 | 1633 | ||
1634 | err_regs2d_res: | 1634 | err_regs2d_res: |
1635 | release_resource(info->regs2d_res); | 1635 | release_mem_region(info->regs2d_res->start, |
1636 | kfree(info->regs2d_res); | 1636 | resource_size(info->regs2d_res)); |
1637 | 1637 | ||
1638 | err_regs_map: | 1638 | err_regs_map: |
1639 | iounmap(info->regs); | 1639 | iounmap(info->regs); |
1640 | 1640 | ||
1641 | err_regs_res: | 1641 | err_regs_res: |
1642 | release_resource(info->regs_res); | 1642 | release_mem_region(info->regs_res->start, |
1643 | kfree(info->regs_res); | 1643 | resource_size(info->regs_res)); |
1644 | 1644 | ||
1645 | err_release: | 1645 | err_release: |
1646 | return ret; | 1646 | return ret; |
@@ -1652,16 +1652,16 @@ static void sm501fb_stop(struct sm501fb_info *info) | |||
1652 | sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0); | 1652 | sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0); |
1653 | 1653 | ||
1654 | iounmap(info->fbmem); | 1654 | iounmap(info->fbmem); |
1655 | release_resource(info->fbmem_res); | 1655 | release_mem_region(info->fbmem_res->start, |
1656 | kfree(info->fbmem_res); | 1656 | resource_size(info->fbmem_res)); |
1657 | 1657 | ||
1658 | iounmap(info->regs2d); | 1658 | iounmap(info->regs2d); |
1659 | release_resource(info->regs2d_res); | 1659 | release_mem_region(info->regs2d_res->start, |
1660 | kfree(info->regs2d_res); | 1660 | resource_size(info->regs2d_res)); |
1661 | 1661 | ||
1662 | iounmap(info->regs); | 1662 | iounmap(info->regs); |
1663 | release_resource(info->regs_res); | 1663 | release_mem_region(info->regs_res->start, |
1664 | kfree(info->regs_res); | 1664 | resource_size(info->regs_res)); |
1665 | } | 1665 | } |
1666 | 1666 | ||
1667 | static int sm501fb_init_fb(struct fb_info *fb, | 1667 | static int sm501fb_init_fb(struct fb_info *fb, |
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index 695066b5b2e6..52b0f3e8ccac 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/prefetch.h> | 30 | #include <linux/prefetch.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/prefetch.h> | ||
32 | #include <video/udlfb.h> | 33 | #include <video/udlfb.h> |
33 | #include "edid.h" | 34 | #include "edid.h" |
34 | 35 | ||
@@ -1587,10 +1588,19 @@ static int dlfb_usb_probe(struct usb_interface *interface, | |||
1587 | goto error; | 1588 | goto error; |
1588 | } | 1589 | } |
1589 | 1590 | ||
1590 | for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) | 1591 | for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) { |
1591 | device_create_file(info->dev, &fb_device_attrs[i]); | 1592 | retval = device_create_file(info->dev, &fb_device_attrs[i]); |
1593 | if (retval) { | ||
1594 | pr_err("device_create_file failed %d\n", retval); | ||
1595 | goto err_del_attrs; | ||
1596 | } | ||
1597 | } | ||
1592 | 1598 | ||
1593 | device_create_bin_file(info->dev, &edid_attr); | 1599 | retval = device_create_bin_file(info->dev, &edid_attr); |
1600 | if (retval) { | ||
1601 | pr_err("device_create_bin_file failed %d\n", retval); | ||
1602 | goto err_del_attrs; | ||
1603 | } | ||
1594 | 1604 | ||
1595 | pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution." | 1605 | pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution." |
1596 | " Using %dK framebuffer memory\n", info->node, | 1606 | " Using %dK framebuffer memory\n", info->node, |
@@ -1599,6 +1609,10 @@ static int dlfb_usb_probe(struct usb_interface *interface, | |||
1599 | info->fix.smem_len * 2 : info->fix.smem_len) >> 10); | 1609 | info->fix.smem_len * 2 : info->fix.smem_len) >> 10); |
1600 | return 0; | 1610 | return 0; |
1601 | 1611 | ||
1612 | err_del_attrs: | ||
1613 | for (i -= 1; i >= 0; i--) | ||
1614 | device_remove_file(info->dev, &fb_device_attrs[i]); | ||
1615 | |||
1602 | error: | 1616 | error: |
1603 | if (dev) { | 1617 | if (dev) { |
1604 | 1618 | ||