aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig70
-rw-r--r--drivers/video/Makefile9
-rw-r--r--drivers/video/amifb.c16
-rw-r--r--drivers/video/atmel_lcdfb.c133
-rw-r--r--drivers/video/auo_k1900fb.c11
-rw-r--r--drivers/video/auo_k1901fb.c11
-rw-r--r--drivers/video/auo_k190x.c237
-rw-r--r--drivers/video/backlight/Kconfig9
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/adp5520_bl.c28
-rw-r--r--drivers/video/backlight/adp8860_bl.c23
-rw-r--r--drivers/video/backlight/adp8870_bl.c33
-rw-r--r--drivers/video/backlight/ams369fg06.c21
-rw-r--r--drivers/video/backlight/as3711_bl.c118
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c14
-rw-r--r--drivers/video/backlight/corgi_lcd.c18
-rw-r--r--drivers/video/backlight/da903x_bl.c30
-rw-r--r--drivers/video/backlight/ep93xx_bl.c20
-rw-r--r--drivers/video/backlight/generic_bl.c6
-rw-r--r--drivers/video/backlight/hp680_bl.c18
-rw-r--r--drivers/video/backlight/ili922x.c555
-rw-r--r--drivers/video/backlight/ili9320.c26
-rw-r--r--drivers/video/backlight/ili9320.h2
-rw-r--r--drivers/video/backlight/jornada720_bl.c18
-rw-r--r--drivers/video/backlight/jornada720_lcd.c21
-rw-r--r--drivers/video/backlight/kb3886_bl.c18
-rw-r--r--drivers/video/backlight/l4f00242t03.c27
-rw-r--r--drivers/video/backlight/ld9040.c20
-rw-r--r--drivers/video/backlight/lm3533_bl.c22
-rw-r--r--drivers/video/backlight/lms501kf03.c22
-rw-r--r--drivers/video/backlight/locomolcd.c16
-rw-r--r--drivers/video/backlight/lp855x_bl.c105
-rw-r--r--drivers/video/backlight/ltv350qv.c18
-rw-r--r--drivers/video/backlight/omap1_bl.c26
-rw-r--r--drivers/video/backlight/platform_lcd.c12
-rw-r--r--drivers/video/backlight/pwm_bl.c7
-rw-r--r--drivers/video/backlight/s6e63m0.c20
-rw-r--r--drivers/video/backlight/tdo24m.c18
-rw-r--r--drivers/video/backlight/tosa_bl.c18
-rw-r--r--drivers/video/backlight/tosa_lcd.c18
-rw-r--r--drivers/video/backlight/tps65217_bl.c15
-rw-r--r--drivers/video/backlight/vgg2432a4.c18
-rw-r--r--drivers/video/bfin_adv7393fb.c43
-rw-r--r--drivers/video/cirrusfb.c62
-rw-r--r--drivers/video/console/fbcon.c2
-rw-r--r--drivers/video/console/fbcon_cw.c3
-rw-r--r--drivers/video/controlfb.c50
-rw-r--r--drivers/video/ep93xx-fb.c18
-rw-r--r--drivers/video/exynos/exynos_dp_core.c4
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi.c10
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_common.c2
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_lowlevel.c2
-rw-r--r--drivers/video/fb-puv3.c14
-rw-r--r--drivers/video/fbmem.c43
-rw-r--r--drivers/video/fbmon.c16
-rw-r--r--drivers/video/fsl-diu-fb.c157
-rw-r--r--drivers/video/gbefb.c4
-rw-r--r--drivers/video/goldfishfb.c2
-rw-r--r--drivers/video/hdmi.c21
-rw-r--r--drivers/video/hyperv_fb.c829
-rw-r--r--drivers/video/matrox/matroxfb_maven.c16
-rw-r--r--drivers/video/mmp/core.c2
-rw-r--r--drivers/video/mmp/hw/mmp_ctrl.h479
-rw-r--r--drivers/video/of_display_timing.c19
-rw-r--r--drivers/video/of_videomode.c2
-rw-r--r--drivers/video/omap/Kconfig11
-rw-r--r--drivers/video/omap2/Makefile2
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c59
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c39
-rw-r--r--drivers/video/omap2/displays/panel-lgphilips-lb035q02.c58
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c95
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c135
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c49
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c126
-rw-r--r--drivers/video/omap2/displays/panel-taal.c300
-rw-r--r--drivers/video/omap2/displays/panel-tfp410.c4
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c45
-rw-r--r--drivers/video/omap2/dss/apply.c15
-rw-r--r--drivers/video/omap2/dss/core.c5
-rw-r--r--drivers/video/omap2/dss/dispc.c176
-rw-r--r--drivers/video/omap2/dss/dispc.h1
-rw-r--r--drivers/video/omap2/dss/dpi.c351
-rw-r--r--drivers/video/omap2/dss/dsi.c1256
-rw-r--r--drivers/video/omap2/dss/dss.c181
-rw-r--r--drivers/video/omap2/dss/dss.h59
-rw-r--r--drivers/video/omap2/dss/dss_features.c8
-rw-r--r--drivers/video/omap2/dss/hdmi.c68
-rw-r--r--drivers/video/omap2/dss/output.c1
-rw-r--r--drivers/video/omap2/dss/rfbi.c34
-rw-r--r--drivers/video/omap2/dss/sdi.c103
-rw-r--r--drivers/video/omap2/dss/venc.c56
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c62
-rw-r--r--drivers/video/omap2/vrfb.c13
-rw-r--r--drivers/video/ps3fb.c18
-rw-r--r--drivers/video/pxa3xx-gcu.c36
-rw-r--r--drivers/video/s1d13xxxfb.c2
-rw-r--r--drivers/video/s3c-fb.c3
-rw-r--r--drivers/video/sa1100fb.c16
-rw-r--r--drivers/video/sgivwfb.c20
-rw-r--r--drivers/video/sh_mipi_dsi.c12
-rw-r--r--drivers/video/sh_mobile_hdmi.c12
-rw-r--r--drivers/video/smscufx.c6
-rw-r--r--drivers/video/ssd1307fb.c4
-rw-r--r--drivers/video/udlfb.c6
-rw-r--r--drivers/video/uvesafb.c2
-rw-r--r--drivers/video/vermilion/vermilion.c14
-rw-r--r--drivers/video/vfb.c7
-rw-r--r--drivers/video/videomode.c36
-rw-r--r--drivers/video/vt8500lcdfb.c55
-rw-r--r--drivers/video/wm8505fb.c145
-rw-r--r--drivers/video/wmt_ge_rops.h23
111 files changed, 4403 insertions, 2974 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e7718fdad1e1..c04ccdf60eaa 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -21,6 +21,8 @@ source "drivers/gpu/vga/Kconfig"
21 21
22source "drivers/gpu/drm/Kconfig" 22source "drivers/gpu/drm/Kconfig"
23 23
24source "drivers/gpu/host1x/Kconfig"
25
24config VGASTATE 26config VGASTATE
25 tristate 27 tristate
26 default n 28 default n
@@ -31,26 +33,8 @@ config VIDEO_OUTPUT_CONTROL
31 This framework adds support for low-level control of the video 33 This framework adds support for low-level control of the video
32 output switch. 34 output switch.
33 35
34config DISPLAY_TIMING 36config VIDEOMODE_HELPERS
35 bool 37 bool
36
37config VIDEOMODE
38 bool
39
40config OF_DISPLAY_TIMING
41 bool "Enable device tree display timing support"
42 depends on OF
43 select DISPLAY_TIMING
44 help
45 helper to parse display timings from the devicetree
46
47config OF_VIDEOMODE
48 bool "Enable device tree videomode support"
49 depends on OF
50 select VIDEOMODE
51 select OF_DISPLAY_TIMING
52 help
53 helper to get videomodes from the devicetree
54 38
55config HDMI 39config HDMI
56 bool 40 bool
@@ -212,14 +196,6 @@ config FB_SYS_FOPS
212 depends on FB 196 depends on FB
213 default n 197 default n
214 198
215config FB_WMT_GE_ROPS
216 tristate
217 depends on FB
218 default n
219 ---help---
220 Include functions for accelerated rectangle filling and area
221 copying using WonderMedia Graphics Engine operations.
222
223config FB_DEFERRED_IO 199config FB_DEFERRED_IO
224 bool 200 bool
225 depends on FB 201 depends on FB
@@ -1797,22 +1773,37 @@ config FB_AU1200
1797 option au1200fb:panel=<name>. 1773 option au1200fb:panel=<name>.
1798 1774
1799config FB_VT8500 1775config FB_VT8500
1800 bool "VT8500 LCD Driver" 1776 bool "VIA VT8500 framebuffer support"
1801 depends on (FB = y) && ARM && ARCH_VT8500 1777 depends on (FB = y) && ARM && ARCH_VT8500
1802 select FB_WMT_GE_ROPS 1778 select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
1779 select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
1803 select FB_SYS_IMAGEBLIT 1780 select FB_SYS_IMAGEBLIT
1781 select FB_MODE_HELPERS
1782 select VIDEOMODE_HELPERS
1804 help 1783 help
1805 This is the framebuffer driver for VIA VT8500 integrated LCD 1784 This is the framebuffer driver for VIA VT8500 integrated LCD
1806 controller. 1785 controller.
1807 1786
1808config FB_WM8505 1787config FB_WM8505
1809 bool "WM8505 frame buffer support" 1788 bool "Wondermedia WM8xxx-series frame buffer support"
1810 depends on (FB = y) && ARM && ARCH_VT8500 1789 depends on (FB = y) && ARM && ARCH_VT8500
1811 select FB_WMT_GE_ROPS 1790 select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
1791 select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
1812 select FB_SYS_IMAGEBLIT 1792 select FB_SYS_IMAGEBLIT
1793 select FB_MODE_HELPERS
1794 select VIDEOMODE_HELPERS
1813 help 1795 help
1814 This is the framebuffer driver for WonderMedia WM8505/WM8650 1796 This is the framebuffer driver for WonderMedia WM8xxx-series
1815 integrated LCD controller. 1797 integrated LCD controller. This driver covers the WM8505, WM8650
1798 and WM8850 SoCs.
1799
1800config FB_WMT_GE_ROPS
1801 bool "VT8500/WM8xxx accelerated raster ops support"
1802 depends on (FB = y) && (FB_VT8500 || FB_WM8505)
1803 default n
1804 help
1805 This adds support for accelerated raster operations on the
1806 VIA VT8500 and Wondermedia 85xx series SoCs.
1816 1807
1817source "drivers/video/geode/Kconfig" 1808source "drivers/video/geode/Kconfig"
1818 1809
@@ -2277,7 +2268,7 @@ config XEN_FBDEV_FRONTEND
2277 select FB_SYS_IMAGEBLIT 2268 select FB_SYS_IMAGEBLIT
2278 select FB_SYS_FOPS 2269 select FB_SYS_FOPS
2279 select FB_DEFERRED_IO 2270 select FB_DEFERRED_IO
2280 select INPUT_XEN_KBDDEV_FRONTEND 2271 select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC
2281 select XEN_XENBUS_FRONTEND 2272 select XEN_XENBUS_FRONTEND
2282 default y 2273 default y
2283 help 2274 help
@@ -2453,6 +2444,15 @@ config FB_PUV3_UNIGFX
2453 Choose this option if you want to use the Unigfx device as a 2444 Choose this option if you want to use the Unigfx device as a
2454 framebuffer device. Without the support of PCI & AGP. 2445 framebuffer device. Without the support of PCI & AGP.
2455 2446
2447config FB_HYPERV
2448 tristate "Microsoft Hyper-V Synthetic Video support"
2449 depends on FB && HYPERV
2450 select FB_CFB_FILLRECT
2451 select FB_CFB_COPYAREA
2452 select FB_CFB_IMAGEBLIT
2453 help
2454 This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
2455
2456source "drivers/video/omap/Kconfig" 2456source "drivers/video/omap/Kconfig"
2457source "drivers/video/omap2/Kconfig" 2457source "drivers/video/omap2/Kconfig"
2458source "drivers/video/exynos/Kconfig" 2458source "drivers/video/exynos/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9df387334cb7..7234e4a959e8 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -149,6 +149,7 @@ obj-$(CONFIG_FB_MSM) += msm/
149obj-$(CONFIG_FB_NUC900) += nuc900fb.o 149obj-$(CONFIG_FB_NUC900) += nuc900fb.o
150obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o 150obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
151obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o 151obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
152obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
152 153
153# Platform or fallback drivers go here 154# Platform or fallback drivers go here
154obj-$(CONFIG_FB_UVESA) += uvesafb.o 155obj-$(CONFIG_FB_UVESA) += uvesafb.o
@@ -171,7 +172,7 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o
171 172
172#video output switch sysfs driver 173#video output switch sysfs driver
173obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o 174obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
174obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o 175obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o
175obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o 176ifeq ($(CONFIG_OF),y)
176obj-$(CONFIG_VIDEOMODE) += videomode.o 177obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o
177obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o 178endif
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 7fa1bf823729..a6780eecff0e 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -1181,7 +1181,7 @@ static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
1181 } 1181 }
1182 1182
1183 /* 1183 /*
1184 * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing 1184 * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the following
1185 * checks failed and smooth scrolling is not possible 1185 * checks failed and smooth scrolling is not possible
1186 */ 1186 */
1187 1187
@@ -3788,19 +3788,7 @@ static struct platform_driver amifb_driver = {
3788 }, 3788 },
3789}; 3789};
3790 3790
3791static int __init amifb_init(void) 3791module_platform_driver_probe(amifb_driver, amifb_probe);
3792{
3793 return platform_driver_probe(&amifb_driver, amifb_probe);
3794}
3795
3796module_init(amifb_init);
3797
3798static void __exit amifb_exit(void)
3799{
3800 platform_driver_unregister(&amifb_driver);
3801}
3802
3803module_exit(amifb_exit);
3804 3792
3805MODULE_LICENSE("GPL"); 3793MODULE_LICENSE("GPL");
3806MODULE_ALIAS("platform:amiga-video"); 3794MODULE_ALIAS("platform:amiga-video");
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 025428e04c33..540909de6247 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -34,6 +34,77 @@
34#define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */ 34#define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */
35#define ATMEL_LCDC_FIFO_SIZE 512 /* words */ 35#define ATMEL_LCDC_FIFO_SIZE 512 /* words */
36 36
37struct atmel_lcdfb_config {
38 bool have_alt_pixclock;
39 bool have_hozval;
40 bool have_intensity_bit;
41};
42
43static struct atmel_lcdfb_config at91sam9261_config = {
44 .have_hozval = true,
45 .have_intensity_bit = true,
46};
47
48static struct atmel_lcdfb_config at91sam9263_config = {
49 .have_intensity_bit = true,
50};
51
52static struct atmel_lcdfb_config at91sam9g10_config = {
53 .have_hozval = true,
54};
55
56static struct atmel_lcdfb_config at91sam9g45_config = {
57 .have_alt_pixclock = true,
58};
59
60static struct atmel_lcdfb_config at91sam9g45es_config = {
61};
62
63static struct atmel_lcdfb_config at91sam9rl_config = {
64 .have_intensity_bit = true,
65};
66
67static struct atmel_lcdfb_config at32ap_config = {
68 .have_hozval = true,
69};
70
71static const struct platform_device_id atmel_lcdfb_devtypes[] = {
72 {
73 .name = "at91sam9261-lcdfb",
74 .driver_data = (unsigned long)&at91sam9261_config,
75 }, {
76 .name = "at91sam9263-lcdfb",
77 .driver_data = (unsigned long)&at91sam9263_config,
78 }, {
79 .name = "at91sam9g10-lcdfb",
80 .driver_data = (unsigned long)&at91sam9g10_config,
81 }, {
82 .name = "at91sam9g45-lcdfb",
83 .driver_data = (unsigned long)&at91sam9g45_config,
84 }, {
85 .name = "at91sam9g45es-lcdfb",
86 .driver_data = (unsigned long)&at91sam9g45es_config,
87 }, {
88 .name = "at91sam9rl-lcdfb",
89 .driver_data = (unsigned long)&at91sam9rl_config,
90 }, {
91 .name = "at32ap-lcdfb",
92 .driver_data = (unsigned long)&at32ap_config,
93 }, {
94 /* terminator */
95 }
96};
97
98static struct atmel_lcdfb_config *
99atmel_lcdfb_get_config(struct platform_device *pdev)
100{
101 unsigned long data;
102
103 data = platform_get_device_id(pdev)->driver_data;
104
105 return (struct atmel_lcdfb_config *)data;
106}
107
37#if defined(CONFIG_ARCH_AT91) 108#if defined(CONFIG_ARCH_AT91)
38#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ 109#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
39 | FBINFO_PARTIAL_PAN_OK \ 110 | FBINFO_PARTIAL_PAN_OK \
@@ -193,14 +264,16 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
193 .accel = FB_ACCEL_NONE, 264 .accel = FB_ACCEL_NONE,
194}; 265};
195 266
196static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) 267static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo,
268 unsigned long xres)
197{ 269{
270 unsigned long lcdcon2;
198 unsigned long value; 271 unsigned long value;
199 272
200 if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10() 273 if (!sinfo->config->have_hozval)
201 || cpu_is_at32ap7000()))
202 return xres; 274 return xres;
203 275
276 lcdcon2 = lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2);
204 value = xres; 277 value = xres;
205 if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) { 278 if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
206 /* STN display */ 279 /* STN display */
@@ -423,7 +496,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
423 break; 496 break;
424 case 16: 497 case 16:
425 /* Older SOCs use IBGR:555 rather than BGR:565. */ 498 /* Older SOCs use IBGR:555 rather than BGR:565. */
426 if (sinfo->have_intensity_bit) 499 if (sinfo->config->have_intensity_bit)
427 var->green.length = 5; 500 var->green.length = 5;
428 else 501 else
429 var->green.length = 6; 502 var->green.length = 6;
@@ -531,7 +604,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
531 /* Now, the LCDC core... */ 604 /* Now, the LCDC core... */
532 605
533 /* Set pixel clock */ 606 /* Set pixel clock */
534 if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es()) 607 if (sinfo->config->have_alt_pixclock)
535 pix_factor = 1; 608 pix_factor = 1;
536 609
537 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; 610 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
@@ -591,8 +664,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
591 lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); 664 lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
592 665
593 /* Horizontal value (aka line size) */ 666 /* Horizontal value (aka line size) */
594 hozval_linesz = compute_hozval(info->var.xres, 667 hozval_linesz = compute_hozval(sinfo, info->var.xres);
595 lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
596 668
597 /* Display size */ 669 /* Display size */
598 value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET; 670 value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
@@ -684,7 +756,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
684 756
685 case FB_VISUAL_PSEUDOCOLOR: 757 case FB_VISUAL_PSEUDOCOLOR:
686 if (regno < 256) { 758 if (regno < 256) {
687 if (sinfo->have_intensity_bit) { 759 if (sinfo->config->have_intensity_bit) {
688 /* old style I+BGR:555 */ 760 /* old style I+BGR:555 */
689 val = ((red >> 11) & 0x001f); 761 val = ((red >> 11) & 0x001f);
690 val |= ((green >> 6) & 0x03e0); 762 val |= ((green >> 6) & 0x03e0);
@@ -821,15 +893,13 @@ static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
821 893
822static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) 894static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
823{ 895{
824 if (sinfo->bus_clk) 896 clk_enable(sinfo->bus_clk);
825 clk_enable(sinfo->bus_clk);
826 clk_enable(sinfo->lcdc_clk); 897 clk_enable(sinfo->lcdc_clk);
827} 898}
828 899
829static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) 900static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
830{ 901{
831 if (sinfo->bus_clk) 902 clk_disable(sinfo->bus_clk);
832 clk_disable(sinfo->bus_clk);
833 clk_disable(sinfo->lcdc_clk); 903 clk_disable(sinfo->lcdc_clk);
834} 904}
835 905
@@ -874,10 +944,9 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
874 } 944 }
875 sinfo->info = info; 945 sinfo->info = info;
876 sinfo->pdev = pdev; 946 sinfo->pdev = pdev;
877 if (cpu_is_at91sam9261() || cpu_is_at91sam9263() || 947 sinfo->config = atmel_lcdfb_get_config(pdev);
878 cpu_is_at91sam9rl()) { 948 if (!sinfo->config)
879 sinfo->have_intensity_bit = true; 949 goto free_info;
880 }
881 950
882 strcpy(info->fix.id, sinfo->pdev->name); 951 strcpy(info->fix.id, sinfo->pdev->name);
883 info->flags = ATMEL_LCDFB_FBINFO_DEFAULT; 952 info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
@@ -888,13 +957,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
888 info->fix = atmel_lcdfb_fix; 957 info->fix = atmel_lcdfb_fix;
889 958
890 /* Enable LCDC Clocks */ 959 /* Enable LCDC Clocks */
891 if (cpu_is_at91sam9261() || cpu_is_at91sam9g10() 960 sinfo->bus_clk = clk_get(dev, "hclk");
892 || cpu_is_at32ap7000()) { 961 if (IS_ERR(sinfo->bus_clk)) {
893 sinfo->bus_clk = clk_get(dev, "hck1"); 962 ret = PTR_ERR(sinfo->bus_clk);
894 if (IS_ERR(sinfo->bus_clk)) { 963 goto free_info;
895 ret = PTR_ERR(sinfo->bus_clk);
896 goto free_info;
897 }
898 } 964 }
899 sinfo->lcdc_clk = clk_get(dev, "lcdc_clk"); 965 sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
900 if (IS_ERR(sinfo->lcdc_clk)) { 966 if (IS_ERR(sinfo->lcdc_clk)) {
@@ -1055,8 +1121,7 @@ stop_clk:
1055 atmel_lcdfb_stop_clock(sinfo); 1121 atmel_lcdfb_stop_clock(sinfo);
1056 clk_put(sinfo->lcdc_clk); 1122 clk_put(sinfo->lcdc_clk);
1057put_bus_clk: 1123put_bus_clk:
1058 if (sinfo->bus_clk) 1124 clk_put(sinfo->bus_clk);
1059 clk_put(sinfo->bus_clk);
1060free_info: 1125free_info:
1061 framebuffer_release(info); 1126 framebuffer_release(info);
1062out: 1127out:
@@ -1081,8 +1146,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
1081 unregister_framebuffer(info); 1146 unregister_framebuffer(info);
1082 atmel_lcdfb_stop_clock(sinfo); 1147 atmel_lcdfb_stop_clock(sinfo);
1083 clk_put(sinfo->lcdc_clk); 1148 clk_put(sinfo->lcdc_clk);
1084 if (sinfo->bus_clk) 1149 clk_put(sinfo->bus_clk);
1085 clk_put(sinfo->bus_clk);
1086 fb_dealloc_cmap(&info->cmap); 1150 fb_dealloc_cmap(&info->cmap);
1087 free_irq(sinfo->irq_base, info); 1151 free_irq(sinfo->irq_base, info);
1088 iounmap(sinfo->mmio); 1152 iounmap(sinfo->mmio);
@@ -1151,25 +1215,14 @@ static struct platform_driver atmel_lcdfb_driver = {
1151 .remove = __exit_p(atmel_lcdfb_remove), 1215 .remove = __exit_p(atmel_lcdfb_remove),
1152 .suspend = atmel_lcdfb_suspend, 1216 .suspend = atmel_lcdfb_suspend,
1153 .resume = atmel_lcdfb_resume, 1217 .resume = atmel_lcdfb_resume,
1154 1218 .id_table = atmel_lcdfb_devtypes,
1155 .driver = { 1219 .driver = {
1156 .name = "atmel_lcdfb", 1220 .name = "atmel_lcdfb",
1157 .owner = THIS_MODULE, 1221 .owner = THIS_MODULE,
1158 }, 1222 },
1159}; 1223};
1160 1224
1161static int __init atmel_lcdfb_init(void) 1225module_platform_driver_probe(atmel_lcdfb_driver, atmel_lcdfb_probe);
1162{
1163 return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe);
1164}
1165
1166static void __exit atmel_lcdfb_exit(void)
1167{
1168 platform_driver_unregister(&atmel_lcdfb_driver);
1169}
1170
1171module_init(atmel_lcdfb_init);
1172module_exit(atmel_lcdfb_exit);
1173 1226
1174MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); 1227MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
1175MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>"); 1228MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
diff --git a/drivers/video/auo_k1900fb.c b/drivers/video/auo_k1900fb.c
index 1a9ac6e1f4b3..f5b668e77af3 100644
--- a/drivers/video/auo_k1900fb.c
+++ b/drivers/video/auo_k1900fb.c
@@ -60,9 +60,12 @@
60 60
61static void auok1900_init(struct auok190xfb_par *par) 61static void auok1900_init(struct auok190xfb_par *par)
62{ 62{
63 struct device *dev = par->info->device;
63 struct auok190x_board *board = par->board; 64 struct auok190x_board *board = par->board;
64 u16 init_param = 0; 65 u16 init_param = 0;
65 66
67 pm_runtime_get_sync(dev);
68
66 init_param |= AUOK1900_INIT_TEMP_AVERAGE; 69 init_param |= AUOK1900_INIT_TEMP_AVERAGE;
67 init_param |= AUOK1900_INIT_ROTATE(par->rotation); 70 init_param |= AUOK1900_INIT_ROTATE(par->rotation);
68 init_param |= AUOK190X_INIT_INVERSE_WHITE; 71 init_param |= AUOK190X_INIT_INVERSE_WHITE;
@@ -74,6 +77,9 @@ static void auok1900_init(struct auok190xfb_par *par)
74 77
75 /* let the controller finish */ 78 /* let the controller finish */
76 board->wait_for_rdy(par); 79 board->wait_for_rdy(par);
80
81 pm_runtime_mark_last_busy(dev);
82 pm_runtime_put_autosuspend(dev);
77} 83}
78 84
79static void auok1900_update_region(struct auok190xfb_par *par, int mode, 85static void auok1900_update_region(struct auok190xfb_par *par, int mode,
@@ -82,6 +88,7 @@ static void auok1900_update_region(struct auok190xfb_par *par, int mode,
82 struct device *dev = par->info->device; 88 struct device *dev = par->info->device;
83 unsigned char *buf = (unsigned char *)par->info->screen_base; 89 unsigned char *buf = (unsigned char *)par->info->screen_base;
84 int xres = par->info->var.xres; 90 int xres = par->info->var.xres;
91 int line_length = par->info->fix.line_length;
85 u16 args[4]; 92 u16 args[4];
86 93
87 pm_runtime_get_sync(dev); 94 pm_runtime_get_sync(dev);
@@ -100,9 +107,9 @@ static void auok1900_update_region(struct auok190xfb_par *par, int mode,
100 args[1] = y1 + 1; 107 args[1] = y1 + 1;
101 args[2] = xres; 108 args[2] = xres;
102 args[3] = y2 - y1; 109 args[3] = y2 - y1;
103 buf += y1 * xres; 110 buf += y1 * line_length;
104 auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args, 111 auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args,
105 ((y2 - y1) * xres)/2, (u16 *) buf); 112 ((y2 - y1) * line_length)/2, (u16 *) buf);
106 auok190x_send_command(par, AUOK190X_CMD_DATA_STOP); 113 auok190x_send_command(par, AUOK190X_CMD_DATA_STOP);
107 114
108 par->update_cnt++; 115 par->update_cnt++;
diff --git a/drivers/video/auo_k1901fb.c b/drivers/video/auo_k1901fb.c
index d1db1653cd88..12b9adcb75c5 100644
--- a/drivers/video/auo_k1901fb.c
+++ b/drivers/video/auo_k1901fb.c
@@ -101,9 +101,12 @@
101 101
102static void auok1901_init(struct auok190xfb_par *par) 102static void auok1901_init(struct auok190xfb_par *par)
103{ 103{
104 struct device *dev = par->info->device;
104 struct auok190x_board *board = par->board; 105 struct auok190x_board *board = par->board;
105 u16 init_param = 0; 106 u16 init_param = 0;
106 107
108 pm_runtime_get_sync(dev);
109
107 init_param |= AUOK190X_INIT_INVERSE_WHITE; 110 init_param |= AUOK190X_INIT_INVERSE_WHITE;
108 init_param |= AUOK190X_INIT_FORMAT0; 111 init_param |= AUOK190X_INIT_FORMAT0;
109 init_param |= AUOK1901_INIT_RESOLUTION(par->resolution); 112 init_param |= AUOK1901_INIT_RESOLUTION(par->resolution);
@@ -113,6 +116,9 @@ static void auok1901_init(struct auok190xfb_par *par)
113 116
114 /* let the controller finish */ 117 /* let the controller finish */
115 board->wait_for_rdy(par); 118 board->wait_for_rdy(par);
119
120 pm_runtime_mark_last_busy(dev);
121 pm_runtime_put_autosuspend(dev);
116} 122}
117 123
118static void auok1901_update_region(struct auok190xfb_par *par, int mode, 124static void auok1901_update_region(struct auok190xfb_par *par, int mode,
@@ -121,6 +127,7 @@ static void auok1901_update_region(struct auok190xfb_par *par, int mode,
121 struct device *dev = par->info->device; 127 struct device *dev = par->info->device;
122 unsigned char *buf = (unsigned char *)par->info->screen_base; 128 unsigned char *buf = (unsigned char *)par->info->screen_base;
123 int xres = par->info->var.xres; 129 int xres = par->info->var.xres;
130 int line_length = par->info->fix.line_length;
124 u16 args[5]; 131 u16 args[5];
125 132
126 pm_runtime_get_sync(dev); 133 pm_runtime_get_sync(dev);
@@ -139,9 +146,9 @@ static void auok1901_update_region(struct auok190xfb_par *par, int mode,
139 args[1] = y1 + 1; 146 args[1] = y1 + 1;
140 args[2] = xres; 147 args[2] = xres;
141 args[3] = y2 - y1; 148 args[3] = y2 - y1;
142 buf += y1 * xres; 149 buf += y1 * line_length;
143 auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4, 150 auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4,
144 args, ((y2 - y1) * xres)/2, 151 args, ((y2 - y1) * line_length)/2,
145 (u16 *) buf); 152 (u16 *) buf);
146 auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP); 153 auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP);
147 154
diff --git a/drivers/video/auo_k190x.c b/drivers/video/auo_k190x.c
index 53846cb534d4..8d2499d1cafb 100644
--- a/drivers/video/auo_k190x.c
+++ b/drivers/video/auo_k190x.c
@@ -40,6 +40,14 @@ static struct panel_info panel_table[] = {
40 .w = 1024, 40 .w = 1024,
41 .h = 768, 41 .h = 768,
42 }, 42 },
43 [AUOK190X_RESOLUTION_600_800] = {
44 .w = 600,
45 .h = 800,
46 },
47 [AUOK190X_RESOLUTION_768_1024] = {
48 .w = 768,
49 .h = 1024,
50 },
43}; 51};
44 52
45/* 53/*
@@ -60,8 +68,48 @@ static void auok190x_issue_cmd(struct auok190xfb_par *par, u16 data)
60 par->board->set_ctl(par, AUOK190X_I80_DC, 1); 68 par->board->set_ctl(par, AUOK190X_I80_DC, 1);
61} 69}
62 70
63static int auok190x_issue_pixels(struct auok190xfb_par *par, int size, 71/**
64 u16 *data) 72 * Conversion of 16bit color to 4bit grayscale
73 * does roughly (0.3 * R + 0.6 G + 0.1 B) / 2
74 */
75static inline int rgb565_to_gray4(u16 data, struct fb_var_screeninfo *var)
76{
77 return ((((data & 0xF800) >> var->red.offset) * 77 +
78 ((data & 0x07E0) >> (var->green.offset + 1)) * 151 +
79 ((data & 0x1F) >> var->blue.offset) * 28) >> 8 >> 1);
80}
81
82static int auok190x_issue_pixels_rgb565(struct auok190xfb_par *par, int size,
83 u16 *data)
84{
85 struct fb_var_screeninfo *var = &par->info->var;
86 struct device *dev = par->info->device;
87 int i;
88 u16 tmp;
89
90 if (size & 7) {
91 dev_err(dev, "issue_pixels: size %d must be a multiple of 8\n",
92 size);
93 return -EINVAL;
94 }
95
96 for (i = 0; i < (size >> 2); i++) {
97 par->board->set_ctl(par, AUOK190X_I80_WR, 0);
98
99 tmp = (rgb565_to_gray4(data[4*i], var) & 0x000F);
100 tmp |= (rgb565_to_gray4(data[4*i+1], var) << 4) & 0x00F0;
101 tmp |= (rgb565_to_gray4(data[4*i+2], var) << 8) & 0x0F00;
102 tmp |= (rgb565_to_gray4(data[4*i+3], var) << 12) & 0xF000;
103
104 par->board->set_hdb(par, tmp);
105 par->board->set_ctl(par, AUOK190X_I80_WR, 1);
106 }
107
108 return 0;
109}
110
111static int auok190x_issue_pixels_gray8(struct auok190xfb_par *par, int size,
112 u16 *data)
65{ 113{
66 struct device *dev = par->info->device; 114 struct device *dev = par->info->device;
67 int i; 115 int i;
@@ -91,6 +139,23 @@ static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
91 return 0; 139 return 0;
92} 140}
93 141
142static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
143 u16 *data)
144{
145 struct fb_info *info = par->info;
146 struct device *dev = par->info->device;
147
148 if (info->var.bits_per_pixel == 8 && info->var.grayscale)
149 auok190x_issue_pixels_gray8(par, size, data);
150 else if (info->var.bits_per_pixel == 16)
151 auok190x_issue_pixels_rgb565(par, size, data);
152 else
153 dev_err(dev, "unsupported color mode (bits: %d, gray: %d)\n",
154 info->var.bits_per_pixel, info->var.grayscale);
155
156 return 0;
157}
158
94static u16 auok190x_read_data(struct auok190xfb_par *par) 159static u16 auok190x_read_data(struct auok190xfb_par *par)
95{ 160{
96 u16 data; 161 u16 data;
@@ -224,8 +289,8 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
224{ 289{
225 struct fb_deferred_io *fbdefio = info->fbdefio; 290 struct fb_deferred_io *fbdefio = info->fbdefio;
226 struct auok190xfb_par *par = info->par; 291 struct auok190xfb_par *par = info->par;
292 u16 line_length = info->fix.line_length;
227 u16 yres = info->var.yres; 293 u16 yres = info->var.yres;
228 u16 xres = info->var.xres;
229 u16 y1 = 0, h = 0; 294 u16 y1 = 0, h = 0;
230 int prev_index = -1; 295 int prev_index = -1;
231 struct page *cur; 296 struct page *cur;
@@ -254,7 +319,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
254 } 319 }
255 320
256 /* height increment is fixed per page */ 321 /* height increment is fixed per page */
257 h_inc = DIV_ROUND_UP(PAGE_SIZE , xres); 322 h_inc = DIV_ROUND_UP(PAGE_SIZE , line_length);
258 323
259 /* calculate number of pages from pixel height */ 324 /* calculate number of pages from pixel height */
260 threshold = par->consecutive_threshold / h_inc; 325 threshold = par->consecutive_threshold / h_inc;
@@ -265,7 +330,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
265 list_for_each_entry(cur, &fbdefio->pagelist, lru) { 330 list_for_each_entry(cur, &fbdefio->pagelist, lru) {
266 if (prev_index < 0) { 331 if (prev_index < 0) {
267 /* just starting so assign first page */ 332 /* just starting so assign first page */
268 y1 = (cur->index << PAGE_SHIFT) / xres; 333 y1 = (cur->index << PAGE_SHIFT) / line_length;
269 h = h_inc; 334 h = h_inc;
270 } else if ((cur->index - prev_index) <= threshold) { 335 } else if ((cur->index - prev_index) <= threshold) {
271 /* page is within our threshold for single updates */ 336 /* page is within our threshold for single updates */
@@ -275,7 +340,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
275 par->update_partial(par, y1, y1 + h); 340 par->update_partial(par, y1, y1 + h);
276 341
277 /* start over with our non consecutive page */ 342 /* start over with our non consecutive page */
278 y1 = (cur->index << PAGE_SHIFT) / xres; 343 y1 = (cur->index << PAGE_SHIFT) / line_length;
279 h = h_inc; 344 h = h_inc;
280 } 345 }
281 prev_index = cur->index; 346 prev_index = cur->index;
@@ -376,27 +441,127 @@ static void auok190xfb_imageblit(struct fb_info *info,
376static int auok190xfb_check_var(struct fb_var_screeninfo *var, 441static int auok190xfb_check_var(struct fb_var_screeninfo *var,
377 struct fb_info *info) 442 struct fb_info *info)
378{ 443{
379 if (info->var.xres != var->xres || info->var.yres != var->yres || 444 struct device *dev = info->device;
380 info->var.xres_virtual != var->xres_virtual || 445 struct auok190xfb_par *par = info->par;
381 info->var.yres_virtual != var->yres_virtual) { 446 struct panel_info *panel = &panel_table[par->resolution];
382 pr_info("%s: Resolution not supported: X%u x Y%u\n", 447 int size;
383 __func__, var->xres, var->yres); 448
449 /*
450 * Color depth
451 */
452
453 if (var->bits_per_pixel == 8 && var->grayscale == 1) {
454 /*
455 * For 8-bit grayscale, R, G, and B offset are equal.
456 */
457 var->red.length = 8;
458 var->red.offset = 0;
459 var->red.msb_right = 0;
460
461 var->green.length = 8;
462 var->green.offset = 0;
463 var->green.msb_right = 0;
464
465 var->blue.length = 8;
466 var->blue.offset = 0;
467 var->blue.msb_right = 0;
468
469 var->transp.length = 0;
470 var->transp.offset = 0;
471 var->transp.msb_right = 0;
472 } else if (var->bits_per_pixel == 16) {
473 var->red.length = 5;
474 var->red.offset = 11;
475 var->red.msb_right = 0;
476
477 var->green.length = 6;
478 var->green.offset = 5;
479 var->green.msb_right = 0;
480
481 var->blue.length = 5;
482 var->blue.offset = 0;
483 var->blue.msb_right = 0;
484
485 var->transp.length = 0;
486 var->transp.offset = 0;
487 var->transp.msb_right = 0;
488 } else {
489 dev_warn(dev, "unsupported color mode (bits: %d, grayscale: %d)\n",
490 info->var.bits_per_pixel, info->var.grayscale);
384 return -EINVAL; 491 return -EINVAL;
385 } 492 }
386 493
387 /* 494 /*
495 * Dimensions
496 */
497
498 switch (var->rotate) {
499 case FB_ROTATE_UR:
500 case FB_ROTATE_UD:
501 var->xres = panel->w;
502 var->yres = panel->h;
503 break;
504 case FB_ROTATE_CW:
505 case FB_ROTATE_CCW:
506 var->xres = panel->h;
507 var->yres = panel->w;
508 break;
509 default:
510 dev_dbg(dev, "Invalid rotation request\n");
511 return -EINVAL;
512 }
513
514 var->xres_virtual = var->xres;
515 var->yres_virtual = var->yres;
516
517 /*
388 * Memory limit 518 * Memory limit
389 */ 519 */
390 520
391 if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) { 521 size = var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8;
392 pr_info("%s: Memory Limit requested yres_virtual = %u\n", 522 if (size > info->fix.smem_len) {
393 __func__, var->yres_virtual); 523 dev_err(dev, "Memory limit exceeded, requested %dK\n",
524 size >> 10);
394 return -ENOMEM; 525 return -ENOMEM;
395 } 526 }
396 527
397 return 0; 528 return 0;
398} 529}
399 530
531static int auok190xfb_set_fix(struct fb_info *info)
532{
533 struct fb_fix_screeninfo *fix = &info->fix;
534 struct fb_var_screeninfo *var = &info->var;
535
536 fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
537
538 fix->type = FB_TYPE_PACKED_PIXELS;
539 fix->accel = FB_ACCEL_NONE;
540 fix->visual = (var->grayscale) ? FB_VISUAL_STATIC_PSEUDOCOLOR
541 : FB_VISUAL_TRUECOLOR;
542 fix->xpanstep = 0;
543 fix->ypanstep = 0;
544 fix->ywrapstep = 0;
545
546 return 0;
547}
548
549static int auok190xfb_set_par(struct fb_info *info)
550{
551 struct auok190xfb_par *par = info->par;
552
553 par->rotation = info->var.rotate;
554 auok190xfb_set_fix(info);
555
556 /* reinit the controller to honor the rotation */
557 par->init(par);
558
559 /* wait for init to complete */
560 par->board->wait_for_rdy(par);
561
562 return 0;
563}
564
400static struct fb_ops auok190xfb_ops = { 565static struct fb_ops auok190xfb_ops = {
401 .owner = THIS_MODULE, 566 .owner = THIS_MODULE,
402 .fb_read = fb_sys_read, 567 .fb_read = fb_sys_read,
@@ -405,6 +570,7 @@ static struct fb_ops auok190xfb_ops = {
405 .fb_copyarea = auok190xfb_copyarea, 570 .fb_copyarea = auok190xfb_copyarea,
406 .fb_imageblit = auok190xfb_imageblit, 571 .fb_imageblit = auok190xfb_imageblit,
407 .fb_check_var = auok190xfb_check_var, 572 .fb_check_var = auok190xfb_check_var,
573 .fb_set_par = auok190xfb_set_par,
408}; 574};
409 575
410/* 576/*
@@ -588,10 +754,16 @@ static int auok190x_power(struct auok190xfb_par *par, bool on)
588 754
589static void auok190x_recover(struct auok190xfb_par *par) 755static void auok190x_recover(struct auok190xfb_par *par)
590{ 756{
757 struct device *dev = par->info->device;
758
591 auok190x_power(par, 0); 759 auok190x_power(par, 0);
592 msleep(100); 760 msleep(100);
593 auok190x_power(par, 1); 761 auok190x_power(par, 1);
594 762
763 /* after powercycling the device, it's always active */
764 pm_runtime_set_active(dev);
765 par->standby = 0;
766
595 par->init(par); 767 par->init(par);
596 768
597 /* wait for init to complete */ 769 /* wait for init to complete */
@@ -875,42 +1047,17 @@ int auok190x_common_probe(struct platform_device *pdev,
875 /* initialise fix, var, resolution and rotation */ 1047 /* initialise fix, var, resolution and rotation */
876 1048
877 strlcpy(info->fix.id, init->id, 16); 1049 strlcpy(info->fix.id, init->id, 16);
878 info->fix.type = FB_TYPE_PACKED_PIXELS;
879 info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
880 info->fix.xpanstep = 0;
881 info->fix.ypanstep = 0;
882 info->fix.ywrapstep = 0;
883 info->fix.accel = FB_ACCEL_NONE;
884
885 info->var.bits_per_pixel = 8; 1050 info->var.bits_per_pixel = 8;
886 info->var.grayscale = 1; 1051 info->var.grayscale = 1;
887 info->var.red.length = 8;
888 info->var.green.length = 8;
889 info->var.blue.length = 8;
890 1052
891 panel = &panel_table[board->resolution]; 1053 panel = &panel_table[board->resolution];
892 1054
893 /* if 90 degree rotation, switch width and height */
894 if (board->rotation & 1) {
895 info->var.xres = panel->h;
896 info->var.yres = panel->w;
897 info->var.xres_virtual = panel->h;
898 info->var.yres_virtual = panel->w;
899 info->fix.line_length = panel->h;
900 } else {
901 info->var.xres = panel->w;
902 info->var.yres = panel->h;
903 info->var.xres_virtual = panel->w;
904 info->var.yres_virtual = panel->h;
905 info->fix.line_length = panel->w;
906 }
907
908 par->resolution = board->resolution; 1055 par->resolution = board->resolution;
909 par->rotation = board->rotation; 1056 par->rotation = 0;
910 1057
911 /* videomemory handling */ 1058 /* videomemory handling */
912 1059
913 videomemorysize = roundup((panel->w * panel->h), PAGE_SIZE); 1060 videomemorysize = roundup((panel->w * panel->h) * 2, PAGE_SIZE);
914 videomemory = vmalloc(videomemorysize); 1061 videomemory = vmalloc(videomemorysize);
915 if (!videomemory) { 1062 if (!videomemory) {
916 ret = -ENOMEM; 1063 ret = -ENOMEM;
@@ -924,6 +1071,12 @@ int auok190x_common_probe(struct platform_device *pdev,
924 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; 1071 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
925 info->fbops = &auok190xfb_ops; 1072 info->fbops = &auok190xfb_ops;
926 1073
1074 ret = auok190xfb_check_var(&info->var, info);
1075 if (ret)
1076 goto err_defio;
1077
1078 auok190xfb_set_fix(info);
1079
927 /* deferred io init */ 1080 /* deferred io init */
928 1081
929 info->fbdefio = devm_kzalloc(info->device, 1082 info->fbdefio = devm_kzalloc(info->device,
@@ -935,7 +1088,7 @@ int auok190x_common_probe(struct platform_device *pdev,
935 goto err_defio; 1088 goto err_defio;
936 } 1089 }
937 1090
938 dev_dbg(info->device, "targetting %d frames per second\n", board->fps); 1091 dev_dbg(info->device, "targeting %d frames per second\n", board->fps);
939 info->fbdefio->delay = HZ / board->fps; 1092 info->fbdefio->delay = HZ / board->fps;
940 info->fbdefio->first_io = auok190xfb_dpy_first_io, 1093 info->fbdefio->first_io = auok190xfb_dpy_first_io,
941 info->fbdefio->deferred_io = auok190xfb_dpy_deferred_io, 1094 info->fbdefio->deferred_io = auok190xfb_dpy_deferred_io,
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index db10d0120d2b..2e166c3fc4c3 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -59,6 +59,13 @@ config LCD_LTV350QV
59 59
60 The LTV350QV panel is present on all ATSTK1000 boards. 60 The LTV350QV panel is present on all ATSTK1000 boards.
61 61
62config LCD_ILI922X
63 tristate "ILI Technology ILI9221/ILI9222 support"
64 depends on SPI
65 help
66 If you have a panel based on the ILI9221/9222 controller
67 chip then say y to include a driver for it.
68
62config LCD_ILI9320 69config LCD_ILI9320
63 tristate "ILI Technology ILI9320 controller support" 70 tristate "ILI Technology ILI9320 controller support"
64 depends on SPI 71 depends on SPI
@@ -161,7 +168,7 @@ if BACKLIGHT_CLASS_DEVICE
161config BACKLIGHT_ATMEL_LCDC 168config BACKLIGHT_ATMEL_LCDC
162 bool "Atmel LCDC Contrast-as-Backlight control" 169 bool "Atmel LCDC Contrast-as-Backlight control"
163 depends on FB_ATMEL 170 depends on FB_ATMEL
164 default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK 171 default y if MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK || MACH_AT91SAM9263EK
165 help 172 help
166 This provides a backlight control internal to the Atmel LCDC 173 This provides a backlight control internal to the Atmel LCDC
167 driver. If the LCD "contrast control" on your board is wired 174 driver. If the LCD "contrast control" on your board is wired
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 96c4d620c5ce..92711fe60464 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
5obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o 5obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o
6obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o 6obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o
7obj-$(CONFIG_LCD_HX8357) += hx8357.o 7obj-$(CONFIG_LCD_HX8357) += hx8357.o
8obj-$(CONFIG_LCD_ILI922X) += ili922x.o
8obj-$(CONFIG_LCD_ILI9320) += ili9320.o 9obj-$(CONFIG_LCD_ILI9320) += ili9320.o
9obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o 10obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o
10obj-$(CONFIG_LCD_LD9040) += ld9040.o 11obj-$(CONFIG_LCD_LD9040) += ld9040.o
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index a1e41d4faa71..c84701b7ca6e 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -143,13 +143,16 @@ static int adp5520_bl_setup(struct backlight_device *bl)
143static ssize_t adp5520_show(struct device *dev, char *buf, int reg) 143static ssize_t adp5520_show(struct device *dev, char *buf, int reg)
144{ 144{
145 struct adp5520_bl *data = dev_get_drvdata(dev); 145 struct adp5520_bl *data = dev_get_drvdata(dev);
146 int error; 146 int ret;
147 uint8_t reg_val; 147 uint8_t reg_val;
148 148
149 mutex_lock(&data->lock); 149 mutex_lock(&data->lock);
150 error = adp5520_read(data->master, reg, &reg_val); 150 ret = adp5520_read(data->master, reg, &reg_val);
151 mutex_unlock(&data->lock); 151 mutex_unlock(&data->lock);
152 152
153 if (ret < 0)
154 return ret;
155
153 return sprintf(buf, "%u\n", reg_val); 156 return sprintf(buf, "%u\n", reg_val);
154} 157}
155 158
@@ -349,35 +352,34 @@ static int adp5520_bl_remove(struct platform_device *pdev)
349 return 0; 352 return 0;
350} 353}
351 354
352#ifdef CONFIG_PM 355#ifdef CONFIG_PM_SLEEP
353static int adp5520_bl_suspend(struct platform_device *pdev, 356static int adp5520_bl_suspend(struct device *dev)
354 pm_message_t state)
355{ 357{
356 struct backlight_device *bl = platform_get_drvdata(pdev); 358 struct backlight_device *bl = dev_get_drvdata(dev);
359
357 return adp5520_bl_set(bl, 0); 360 return adp5520_bl_set(bl, 0);
358} 361}
359 362
360static int adp5520_bl_resume(struct platform_device *pdev) 363static int adp5520_bl_resume(struct device *dev)
361{ 364{
362 struct backlight_device *bl = platform_get_drvdata(pdev); 365 struct backlight_device *bl = dev_get_drvdata(dev);
363 366
364 backlight_update_status(bl); 367 backlight_update_status(bl);
365 return 0; 368 return 0;
366} 369}
367#else
368#define adp5520_bl_suspend NULL
369#define adp5520_bl_resume NULL
370#endif 370#endif
371 371
372static SIMPLE_DEV_PM_OPS(adp5520_bl_pm_ops, adp5520_bl_suspend,
373 adp5520_bl_resume);
374
372static struct platform_driver adp5520_bl_driver = { 375static struct platform_driver adp5520_bl_driver = {
373 .driver = { 376 .driver = {
374 .name = "adp5520-backlight", 377 .name = "adp5520-backlight",
375 .owner = THIS_MODULE, 378 .owner = THIS_MODULE,
379 .pm = &adp5520_bl_pm_ops,
376 }, 380 },
377 .probe = adp5520_bl_probe, 381 .probe = adp5520_bl_probe,
378 .remove = adp5520_bl_remove, 382 .remove = adp5520_bl_remove,
379 .suspend = adp5520_bl_suspend,
380 .resume = adp5520_bl_resume,
381}; 383};
382 384
383module_platform_driver(adp5520_bl_driver); 385module_platform_driver(adp5520_bl_driver);
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index a77c9cad3320..75b10f876127 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -249,12 +249,14 @@ static int adp8860_led_probe(struct i2c_client *client)
249 if (led_dat->id > 7 || led_dat->id < 1) { 249 if (led_dat->id > 7 || led_dat->id < 1) {
250 dev_err(&client->dev, "Invalid LED ID %d\n", 250 dev_err(&client->dev, "Invalid LED ID %d\n",
251 led_dat->id); 251 led_dat->id);
252 ret = -EINVAL;
252 goto err; 253 goto err;
253 } 254 }
254 255
255 if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) { 256 if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) {
256 dev_err(&client->dev, "LED %d used by Backlight\n", 257 dev_err(&client->dev, "LED %d used by Backlight\n",
257 led_dat->id); 258 led_dat->id);
259 ret = -EBUSY;
258 goto err; 260 goto err;
259 } 261 }
260 262
@@ -773,25 +775,29 @@ static int adp8860_remove(struct i2c_client *client)
773 return 0; 775 return 0;
774} 776}
775 777
776#ifdef CONFIG_PM 778#ifdef CONFIG_PM_SLEEP
777static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message) 779static int adp8860_i2c_suspend(struct device *dev)
778{ 780{
781 struct i2c_client *client = to_i2c_client(dev);
782
779 adp8860_clr_bits(client, ADP8860_MDCR, NSTBY); 783 adp8860_clr_bits(client, ADP8860_MDCR, NSTBY);
780 784
781 return 0; 785 return 0;
782} 786}
783 787
784static int adp8860_i2c_resume(struct i2c_client *client) 788static int adp8860_i2c_resume(struct device *dev)
785{ 789{
790 struct i2c_client *client = to_i2c_client(dev);
791
786 adp8860_set_bits(client, ADP8860_MDCR, NSTBY | BLEN); 792 adp8860_set_bits(client, ADP8860_MDCR, NSTBY | BLEN);
787 793
788 return 0; 794 return 0;
789} 795}
790#else
791#define adp8860_i2c_suspend NULL
792#define adp8860_i2c_resume NULL
793#endif 796#endif
794 797
798static SIMPLE_DEV_PM_OPS(adp8860_i2c_pm_ops, adp8860_i2c_suspend,
799 adp8860_i2c_resume);
800
795static const struct i2c_device_id adp8860_id[] = { 801static const struct i2c_device_id adp8860_id[] = {
796 { "adp8860", adp8860 }, 802 { "adp8860", adp8860 },
797 { "adp8861", adp8861 }, 803 { "adp8861", adp8861 },
@@ -802,12 +808,11 @@ MODULE_DEVICE_TABLE(i2c, adp8860_id);
802 808
803static struct i2c_driver adp8860_driver = { 809static struct i2c_driver adp8860_driver = {
804 .driver = { 810 .driver = {
805 .name = KBUILD_MODNAME, 811 .name = KBUILD_MODNAME,
812 .pm = &adp8860_i2c_pm_ops,
806 }, 813 },
807 .probe = adp8860_probe, 814 .probe = adp8860_probe,
808 .remove = adp8860_remove, 815 .remove = adp8860_remove,
809 .suspend = adp8860_i2c_suspend,
810 .resume = adp8860_i2c_resume,
811 .id_table = adp8860_id, 816 .id_table = adp8860_id,
812}; 817};
813 818
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index 712c25a0d8fe..90049d7b5c60 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -274,12 +274,14 @@ static int adp8870_led_probe(struct i2c_client *client)
274 if (led_dat->id > 7 || led_dat->id < 1) { 274 if (led_dat->id > 7 || led_dat->id < 1) {
275 dev_err(&client->dev, "Invalid LED ID %d\n", 275 dev_err(&client->dev, "Invalid LED ID %d\n",
276 led_dat->id); 276 led_dat->id);
277 ret = -EINVAL;
277 goto err; 278 goto err;
278 } 279 }
279 280
280 if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) { 281 if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) {
281 dev_err(&client->dev, "LED %d used by Backlight\n", 282 dev_err(&client->dev, "LED %d used by Backlight\n",
282 led_dat->id); 283 led_dat->id);
284 ret = -EBUSY;
283 goto err; 285 goto err;
284 } 286 }
285 287
@@ -895,13 +897,13 @@ static int adp8870_probe(struct i2c_client *client,
895 897
896 data->bl = bl; 898 data->bl = bl;
897 899
898 if (pdata->en_ambl_sens) 900 if (pdata->en_ambl_sens) {
899 ret = sysfs_create_group(&bl->dev.kobj, 901 ret = sysfs_create_group(&bl->dev.kobj,
900 &adp8870_bl_attr_group); 902 &adp8870_bl_attr_group);
901 903 if (ret) {
902 if (ret) { 904 dev_err(&client->dev, "failed to register sysfs\n");
903 dev_err(&client->dev, "failed to register sysfs\n"); 905 goto out1;
904 goto out1; 906 }
905 } 907 }
906 908
907 ret = adp8870_bl_setup(bl); 909 ret = adp8870_bl_setup(bl);
@@ -947,25 +949,29 @@ static int adp8870_remove(struct i2c_client *client)
947 return 0; 949 return 0;
948} 950}
949 951
950#ifdef CONFIG_PM 952#ifdef CONFIG_PM_SLEEP
951static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message) 953static int adp8870_i2c_suspend(struct device *dev)
952{ 954{
955 struct i2c_client *client = to_i2c_client(dev);
956
953 adp8870_clr_bits(client, ADP8870_MDCR, NSTBY); 957 adp8870_clr_bits(client, ADP8870_MDCR, NSTBY);
954 958
955 return 0; 959 return 0;
956} 960}
957 961
958static int adp8870_i2c_resume(struct i2c_client *client) 962static int adp8870_i2c_resume(struct device *dev)
959{ 963{
964 struct i2c_client *client = to_i2c_client(dev);
965
960 adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN); 966 adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN);
961 967
962 return 0; 968 return 0;
963} 969}
964#else
965#define adp8870_i2c_suspend NULL
966#define adp8870_i2c_resume NULL
967#endif 970#endif
968 971
972static SIMPLE_DEV_PM_OPS(adp8870_i2c_pm_ops, adp8870_i2c_suspend,
973 adp8870_i2c_resume);
974
969static const struct i2c_device_id adp8870_id[] = { 975static const struct i2c_device_id adp8870_id[] = {
970 { "adp8870", 0 }, 976 { "adp8870", 0 },
971 { } 977 { }
@@ -974,12 +980,11 @@ MODULE_DEVICE_TABLE(i2c, adp8870_id);
974 980
975static struct i2c_driver adp8870_driver = { 981static struct i2c_driver adp8870_driver = {
976 .driver = { 982 .driver = {
977 .name = KBUILD_MODNAME, 983 .name = KBUILD_MODNAME,
984 .pm = &adp8870_i2c_pm_ops,
978 }, 985 },
979 .probe = adp8870_probe, 986 .probe = adp8870_probe,
980 .remove = adp8870_remove, 987 .remove = adp8870_remove,
981 .suspend = adp8870_i2c_suspend,
982 .resume = adp8870_i2c_resume,
983 .id_table = adp8870_id, 988 .id_table = adp8870_id,
984}; 989};
985 990
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
index c02aa2c2575a..319fef6cb422 100644
--- a/drivers/video/backlight/ams369fg06.c
+++ b/drivers/video/backlight/ams369fg06.c
@@ -533,12 +533,12 @@ static int ams369fg06_remove(struct spi_device *spi)
533 return 0; 533 return 0;
534} 534}
535 535
536#if defined(CONFIG_PM) 536#ifdef CONFIG_PM_SLEEP
537static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg) 537static int ams369fg06_suspend(struct device *dev)
538{ 538{
539 struct ams369fg06 *lcd = spi_get_drvdata(spi); 539 struct ams369fg06 *lcd = dev_get_drvdata(dev);
540 540
541 dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); 541 dev_dbg(dev, "lcd->power = %d\n", lcd->power);
542 542
543 /* 543 /*
544 * when lcd panel is suspend, lcd panel becomes off 544 * when lcd panel is suspend, lcd panel becomes off
@@ -547,19 +547,19 @@ static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg)
547 return ams369fg06_power(lcd, FB_BLANK_POWERDOWN); 547 return ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
548} 548}
549 549
550static int ams369fg06_resume(struct spi_device *spi) 550static int ams369fg06_resume(struct device *dev)
551{ 551{
552 struct ams369fg06 *lcd = spi_get_drvdata(spi); 552 struct ams369fg06 *lcd = dev_get_drvdata(dev);
553 553
554 lcd->power = FB_BLANK_POWERDOWN; 554 lcd->power = FB_BLANK_POWERDOWN;
555 555
556 return ams369fg06_power(lcd, FB_BLANK_UNBLANK); 556 return ams369fg06_power(lcd, FB_BLANK_UNBLANK);
557} 557}
558#else
559#define ams369fg06_suspend NULL
560#define ams369fg06_resume NULL
561#endif 558#endif
562 559
560static SIMPLE_DEV_PM_OPS(ams369fg06_pm_ops, ams369fg06_suspend,
561 ams369fg06_resume);
562
563static void ams369fg06_shutdown(struct spi_device *spi) 563static void ams369fg06_shutdown(struct spi_device *spi)
564{ 564{
565 struct ams369fg06 *lcd = spi_get_drvdata(spi); 565 struct ams369fg06 *lcd = spi_get_drvdata(spi);
@@ -571,12 +571,11 @@ static struct spi_driver ams369fg06_driver = {
571 .driver = { 571 .driver = {
572 .name = "ams369fg06", 572 .name = "ams369fg06",
573 .owner = THIS_MODULE, 573 .owner = THIS_MODULE,
574 .pm = &ams369fg06_pm_ops,
574 }, 575 },
575 .probe = ams369fg06_probe, 576 .probe = ams369fg06_probe,
576 .remove = ams369fg06_remove, 577 .remove = ams369fg06_remove,
577 .shutdown = ams369fg06_shutdown, 578 .shutdown = ams369fg06_shutdown,
578 .suspend = ams369fg06_suspend,
579 .resume = ams369fg06_resume,
580}; 579};
581 580
582module_spi_driver(ams369fg06_driver); 581module_spi_driver(ams369fg06_driver);
diff --git a/drivers/video/backlight/as3711_bl.c b/drivers/video/backlight/as3711_bl.c
index 41d52fe52543..123887cd76bd 100644
--- a/drivers/video/backlight/as3711_bl.c
+++ b/drivers/video/backlight/as3711_bl.c
@@ -258,6 +258,109 @@ static int as3711_bl_register(struct platform_device *pdev,
258 return 0; 258 return 0;
259} 259}
260 260
261static int as3711_backlight_parse_dt(struct device *dev)
262{
263 struct as3711_bl_pdata *pdata = dev_get_platdata(dev);
264 struct device_node *bl =
265 of_find_node_by_name(dev->parent->of_node, "backlight"), *fb;
266 int ret;
267
268 if (!bl) {
269 dev_dbg(dev, "backlight node not found\n");
270 return -ENODEV;
271 }
272
273 fb = of_parse_phandle(bl, "su1-dev", 0);
274 if (fb) {
275 pdata->su1_fb = fb->full_name;
276
277 ret = of_property_read_u32(bl, "su1-max-uA", &pdata->su1_max_uA);
278 if (pdata->su1_max_uA <= 0)
279 ret = -EINVAL;
280 if (ret < 0)
281 return ret;
282 }
283
284 fb = of_parse_phandle(bl, "su2-dev", 0);
285 if (fb) {
286 int count = 0;
287
288 pdata->su2_fb = fb->full_name;
289
290 ret = of_property_read_u32(bl, "su2-max-uA", &pdata->su2_max_uA);
291 if (pdata->su2_max_uA <= 0)
292 ret = -EINVAL;
293 if (ret < 0)
294 return ret;
295
296 if (of_find_property(bl, "su2-feedback-voltage", NULL)) {
297 pdata->su2_feedback = AS3711_SU2_VOLTAGE;
298 count++;
299 }
300 if (of_find_property(bl, "su2-feedback-curr1", NULL)) {
301 pdata->su2_feedback = AS3711_SU2_CURR1;
302 count++;
303 }
304 if (of_find_property(bl, "su2-feedback-curr2", NULL)) {
305 pdata->su2_feedback = AS3711_SU2_CURR2;
306 count++;
307 }
308 if (of_find_property(bl, "su2-feedback-curr3", NULL)) {
309 pdata->su2_feedback = AS3711_SU2_CURR3;
310 count++;
311 }
312 if (of_find_property(bl, "su2-feedback-curr-auto", NULL)) {
313 pdata->su2_feedback = AS3711_SU2_CURR_AUTO;
314 count++;
315 }
316 if (count != 1)
317 return -EINVAL;
318
319 count = 0;
320 if (of_find_property(bl, "su2-fbprot-lx-sd4", NULL)) {
321 pdata->su2_fbprot = AS3711_SU2_LX_SD4;
322 count++;
323 }
324 if (of_find_property(bl, "su2-fbprot-gpio2", NULL)) {
325 pdata->su2_fbprot = AS3711_SU2_GPIO2;
326 count++;
327 }
328 if (of_find_property(bl, "su2-fbprot-gpio3", NULL)) {
329 pdata->su2_fbprot = AS3711_SU2_GPIO3;
330 count++;
331 }
332 if (of_find_property(bl, "su2-fbprot-gpio4", NULL)) {
333 pdata->su2_fbprot = AS3711_SU2_GPIO4;
334 count++;
335 }
336 if (count != 1)
337 return -EINVAL;
338
339 count = 0;
340 if (of_find_property(bl, "su2-auto-curr1", NULL)) {
341 pdata->su2_auto_curr1 = true;
342 count++;
343 }
344 if (of_find_property(bl, "su2-auto-curr2", NULL)) {
345 pdata->su2_auto_curr2 = true;
346 count++;
347 }
348 if (of_find_property(bl, "su2-auto-curr3", NULL)) {
349 pdata->su2_auto_curr3 = true;
350 count++;
351 }
352
353 /*
354 * At least one su2-auto-curr* must be specified iff
355 * AS3711_SU2_CURR_AUTO is used
356 */
357 if (!count ^ (pdata->su2_feedback != AS3711_SU2_CURR_AUTO))
358 return -EINVAL;
359 }
360
361 return 0;
362}
363
261static int as3711_backlight_probe(struct platform_device *pdev) 364static int as3711_backlight_probe(struct platform_device *pdev)
262{ 365{
263 struct as3711_bl_pdata *pdata = dev_get_platdata(&pdev->dev); 366 struct as3711_bl_pdata *pdata = dev_get_platdata(&pdev->dev);
@@ -267,11 +370,24 @@ static int as3711_backlight_probe(struct platform_device *pdev)
267 unsigned int max_brightness; 370 unsigned int max_brightness;
268 int ret; 371 int ret;
269 372
270 if (!pdata || (!pdata->su1_fb && !pdata->su2_fb)) { 373 if (!pdata) {
271 dev_err(&pdev->dev, "No platform data, exiting...\n"); 374 dev_err(&pdev->dev, "No platform data, exiting...\n");
272 return -ENODEV; 375 return -ENODEV;
273 } 376 }
274 377
378 if (pdev->dev.parent->of_node) {
379 ret = as3711_backlight_parse_dt(&pdev->dev);
380 if (ret < 0) {
381 dev_err(&pdev->dev, "DT parsing failed: %d\n", ret);
382 return ret;
383 }
384 }
385
386 if (!pdata->su1_fb && !pdata->su2_fb) {
387 dev_err(&pdev->dev, "No framebuffer specified\n");
388 return -EINVAL;
389 }
390
275 /* 391 /*
276 * Due to possible hardware damage I chose to block all modes, 392 * Due to possible hardware damage I chose to block all modes,
277 * unsupported on my hardware. Anyone, wishing to use any of those modes 393 * unsupported on my hardware. Anyone, wishing to use any of those modes
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index de5e5e74e2a7..a60d6afca97c 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -118,7 +118,7 @@ static const struct backlight_ops atmel_pwm_bl_ops = {
118 .update_status = atmel_pwm_bl_set_intensity, 118 .update_status = atmel_pwm_bl_set_intensity,
119}; 119};
120 120
121static int atmel_pwm_bl_probe(struct platform_device *pdev) 121static int __init atmel_pwm_bl_probe(struct platform_device *pdev)
122{ 122{
123 struct backlight_properties props; 123 struct backlight_properties props;
124 const struct atmel_pwm_bl_platform_data *pdata; 124 const struct atmel_pwm_bl_platform_data *pdata;
@@ -225,17 +225,7 @@ static struct platform_driver atmel_pwm_bl_driver = {
225 .remove = __exit_p(atmel_pwm_bl_remove), 225 .remove = __exit_p(atmel_pwm_bl_remove),
226}; 226};
227 227
228static int __init atmel_pwm_bl_init(void) 228module_platform_driver_probe(atmel_pwm_bl_driver, atmel_pwm_bl_probe);
229{
230 return platform_driver_probe(&atmel_pwm_bl_driver, atmel_pwm_bl_probe);
231}
232module_init(atmel_pwm_bl_init);
233
234static void __exit atmel_pwm_bl_exit(void)
235{
236 platform_driver_unregister(&atmel_pwm_bl_driver);
237}
238module_exit(atmel_pwm_bl_exit);
239 229
240MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>"); 230MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
241MODULE_DESCRIPTION("Atmel PWM backlight driver"); 231MODULE_DESCRIPTION("Atmel PWM backlight driver");
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index aa782f302983..c97867a717a7 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -457,10 +457,10 @@ static const struct backlight_ops corgi_bl_ops = {
457 .update_status = corgi_bl_update_status, 457 .update_status = corgi_bl_update_status,
458}; 458};
459 459
460#ifdef CONFIG_PM 460#ifdef CONFIG_PM_SLEEP
461static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state) 461static int corgi_lcd_suspend(struct device *dev)
462{ 462{
463 struct corgi_lcd *lcd = spi_get_drvdata(spi); 463 struct corgi_lcd *lcd = dev_get_drvdata(dev);
464 464
465 corgibl_flags |= CORGIBL_SUSPENDED; 465 corgibl_flags |= CORGIBL_SUSPENDED;
466 corgi_bl_set_intensity(lcd, 0); 466 corgi_bl_set_intensity(lcd, 0);
@@ -468,20 +468,19 @@ static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state)
468 return 0; 468 return 0;
469} 469}
470 470
471static int corgi_lcd_resume(struct spi_device *spi) 471static int corgi_lcd_resume(struct device *dev)
472{ 472{
473 struct corgi_lcd *lcd = spi_get_drvdata(spi); 473 struct corgi_lcd *lcd = dev_get_drvdata(dev);
474 474
475 corgibl_flags &= ~CORGIBL_SUSPENDED; 475 corgibl_flags &= ~CORGIBL_SUSPENDED;
476 corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK); 476 corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK);
477 backlight_update_status(lcd->bl_dev); 477 backlight_update_status(lcd->bl_dev);
478 return 0; 478 return 0;
479} 479}
480#else
481#define corgi_lcd_suspend NULL
482#define corgi_lcd_resume NULL
483#endif 480#endif
484 481
482static SIMPLE_DEV_PM_OPS(corgi_lcd_pm_ops, corgi_lcd_suspend, corgi_lcd_resume);
483
485static int setup_gpio_backlight(struct corgi_lcd *lcd, 484static int setup_gpio_backlight(struct corgi_lcd *lcd,
486 struct corgi_lcd_platform_data *pdata) 485 struct corgi_lcd_platform_data *pdata)
487{ 486{
@@ -611,11 +610,10 @@ static struct spi_driver corgi_lcd_driver = {
611 .driver = { 610 .driver = {
612 .name = "corgi-lcd", 611 .name = "corgi-lcd",
613 .owner = THIS_MODULE, 612 .owner = THIS_MODULE,
613 .pm = &corgi_lcd_pm_ops,
614 }, 614 },
615 .probe = corgi_lcd_probe, 615 .probe = corgi_lcd_probe,
616 .remove = corgi_lcd_remove, 616 .remove = corgi_lcd_remove,
617 .suspend = corgi_lcd_suspend,
618 .resume = corgi_lcd_resume,
619}; 617};
620 618
621module_spi_driver(corgi_lcd_driver); 619module_spi_driver(corgi_lcd_driver);
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index 8179cef0730f..67cadd30e273 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -88,16 +88,21 @@ static int da903x_backlight_update_status(struct backlight_device *bl)
88 if (bl->props.fb_blank != FB_BLANK_UNBLANK) 88 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
89 brightness = 0; 89 brightness = 0;
90 90
91 if (bl->props.state & BL_CORE_SUSPENDED)
92 brightness = 0;
93
91 return da903x_backlight_set(bl, brightness); 94 return da903x_backlight_set(bl, brightness);
92} 95}
93 96
94static int da903x_backlight_get_brightness(struct backlight_device *bl) 97static int da903x_backlight_get_brightness(struct backlight_device *bl)
95{ 98{
96 struct da903x_backlight_data *data = bl_get_data(bl); 99 struct da903x_backlight_data *data = bl_get_data(bl);
100
97 return data->current_brightness; 101 return data->current_brightness;
98} 102}
99 103
100static const struct backlight_ops da903x_backlight_ops = { 104static const struct backlight_ops da903x_backlight_ops = {
105 .options = BL_CORE_SUSPENDRESUME,
101 .update_status = da903x_backlight_update_status, 106 .update_status = da903x_backlight_update_status,
102 .get_brightness = da903x_backlight_get_brightness, 107 .get_brightness = da903x_backlight_get_brightness,
103}; 108};
@@ -161,35 +166,10 @@ static int da903x_backlight_remove(struct platform_device *pdev)
161 return 0; 166 return 0;
162} 167}
163 168
164#ifdef CONFIG_PM
165static int da903x_backlight_suspend(struct device *dev)
166{
167 struct backlight_device *bl = dev_get_drvdata(dev);
168
169 return da903x_backlight_set(bl, 0);
170}
171
172static int da903x_backlight_resume(struct device *dev)
173{
174 struct backlight_device *bl = dev_get_drvdata(dev);
175
176 backlight_update_status(bl);
177 return 0;
178}
179
180static const struct dev_pm_ops da903x_backlight_pm_ops = {
181 .suspend = da903x_backlight_suspend,
182 .resume = da903x_backlight_resume,
183};
184#endif
185
186static struct platform_driver da903x_backlight_driver = { 169static struct platform_driver da903x_backlight_driver = {
187 .driver = { 170 .driver = {
188 .name = "da903x-backlight", 171 .name = "da903x-backlight",
189 .owner = THIS_MODULE, 172 .owner = THIS_MODULE,
190#ifdef CONFIG_PM
191 .pm = &da903x_backlight_pm_ops,
192#endif
193 }, 173 },
194 .probe = da903x_backlight_probe, 174 .probe = da903x_backlight_probe,
195 .remove = da903x_backlight_remove, 175 .remove = da903x_backlight_remove,
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
index ef3e21e8f825..33455821dd31 100644
--- a/drivers/video/backlight/ep93xx_bl.c
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -60,7 +60,7 @@ static const struct backlight_ops ep93xxbl_ops = {
60 .get_brightness = ep93xxbl_get_brightness, 60 .get_brightness = ep93xxbl_get_brightness,
61}; 61};
62 62
63static int __init ep93xxbl_probe(struct platform_device *dev) 63static int ep93xxbl_probe(struct platform_device *dev)
64{ 64{
65 struct ep93xxbl *ep93xxbl; 65 struct ep93xxbl *ep93xxbl;
66 struct backlight_device *bl; 66 struct backlight_device *bl;
@@ -115,35 +115,33 @@ static int ep93xxbl_remove(struct platform_device *dev)
115 return 0; 115 return 0;
116} 116}
117 117
118#ifdef CONFIG_PM 118#ifdef CONFIG_PM_SLEEP
119static int ep93xxbl_suspend(struct platform_device *dev, pm_message_t state) 119static int ep93xxbl_suspend(struct device *dev)
120{ 120{
121 struct backlight_device *bl = platform_get_drvdata(dev); 121 struct backlight_device *bl = dev_get_drvdata(dev);
122 122
123 return ep93xxbl_set(bl, 0); 123 return ep93xxbl_set(bl, 0);
124} 124}
125 125
126static int ep93xxbl_resume(struct platform_device *dev) 126static int ep93xxbl_resume(struct device *dev)
127{ 127{
128 struct backlight_device *bl = platform_get_drvdata(dev); 128 struct backlight_device *bl = dev_get_drvdata(dev);
129 129
130 backlight_update_status(bl); 130 backlight_update_status(bl);
131 return 0; 131 return 0;
132} 132}
133#else
134#define ep93xxbl_suspend NULL
135#define ep93xxbl_resume NULL
136#endif 133#endif
137 134
135static SIMPLE_DEV_PM_OPS(ep93xxbl_pm_ops, ep93xxbl_suspend, ep93xxbl_resume);
136
138static struct platform_driver ep93xxbl_driver = { 137static struct platform_driver ep93xxbl_driver = {
139 .driver = { 138 .driver = {
140 .name = "ep93xx-bl", 139 .name = "ep93xx-bl",
141 .owner = THIS_MODULE, 140 .owner = THIS_MODULE,
141 .pm = &ep93xxbl_pm_ops,
142 }, 142 },
143 .probe = ep93xxbl_probe, 143 .probe = ep93xxbl_probe,
144 .remove = ep93xxbl_remove, 144 .remove = ep93xxbl_remove,
145 .suspend = ep93xxbl_suspend,
146 .resume = ep93xxbl_resume,
147}; 145};
148 146
149module_platform_driver(ep93xxbl_driver); 147module_platform_driver(ep93xxbl_driver);
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 0ae155be9c89..19e393b41438 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -9,8 +9,6 @@
9 * 9 *
10 */ 10 */
11 11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14#include <linux/module.h> 12#include <linux/module.h>
15#include <linux/kernel.h> 13#include <linux/kernel.h>
16#include <linux/init.h> 14#include <linux/init.h>
@@ -108,7 +106,7 @@ static int genericbl_probe(struct platform_device *pdev)
108 106
109 generic_backlight_device = bd; 107 generic_backlight_device = bd;
110 108
111 pr_info("Generic Backlight Driver Initialized.\n"); 109 dev_info(&pdev->dev, "Generic Backlight Driver Initialized.\n");
112 return 0; 110 return 0;
113} 111}
114 112
@@ -122,7 +120,7 @@ static int genericbl_remove(struct platform_device *pdev)
122 120
123 backlight_device_unregister(bd); 121 backlight_device_unregister(bd);
124 122
125 pr_info("Generic Backlight Driver Unloaded\n"); 123 dev_info(&pdev->dev, "Generic Backlight Driver Unloaded\n");
126 return 0; 124 return 0;
127} 125}
128 126
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 5cefd73526f8..00076ecfe9b8 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -64,29 +64,28 @@ static void hp680bl_send_intensity(struct backlight_device *bd)
64} 64}
65 65
66 66
67#ifdef CONFIG_PM 67#ifdef CONFIG_PM_SLEEP
68static int hp680bl_suspend(struct platform_device *pdev, pm_message_t state) 68static int hp680bl_suspend(struct device *dev)
69{ 69{
70 struct backlight_device *bd = platform_get_drvdata(pdev); 70 struct backlight_device *bd = dev_get_drvdata(dev);
71 71
72 hp680bl_suspended = 1; 72 hp680bl_suspended = 1;
73 hp680bl_send_intensity(bd); 73 hp680bl_send_intensity(bd);
74 return 0; 74 return 0;
75} 75}
76 76
77static int hp680bl_resume(struct platform_device *pdev) 77static int hp680bl_resume(struct device *dev)
78{ 78{
79 struct backlight_device *bd = platform_get_drvdata(pdev); 79 struct backlight_device *bd = dev_get_drvdata(dev);
80 80
81 hp680bl_suspended = 0; 81 hp680bl_suspended = 0;
82 hp680bl_send_intensity(bd); 82 hp680bl_send_intensity(bd);
83 return 0; 83 return 0;
84} 84}
85#else
86#define hp680bl_suspend NULL
87#define hp680bl_resume NULL
88#endif 85#endif
89 86
87static SIMPLE_DEV_PM_OPS(hp680bl_pm_ops, hp680bl_suspend, hp680bl_resume);
88
90static int hp680bl_set_intensity(struct backlight_device *bd) 89static int hp680bl_set_intensity(struct backlight_device *bd)
91{ 90{
92 hp680bl_send_intensity(bd); 91 hp680bl_send_intensity(bd);
@@ -140,10 +139,9 @@ static int hp680bl_remove(struct platform_device *pdev)
140static struct platform_driver hp680bl_driver = { 139static struct platform_driver hp680bl_driver = {
141 .probe = hp680bl_probe, 140 .probe = hp680bl_probe,
142 .remove = hp680bl_remove, 141 .remove = hp680bl_remove,
143 .suspend = hp680bl_suspend,
144 .resume = hp680bl_resume,
145 .driver = { 142 .driver = {
146 .name = "hp680-bl", 143 .name = "hp680-bl",
144 .pm = &hp680bl_pm_ops,
147 }, 145 },
148}; 146};
149 147
diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c
new file mode 100644
index 000000000000..d9f65c2d9b01
--- /dev/null
+++ b/drivers/video/backlight/ili922x.c
@@ -0,0 +1,555 @@
1/*
2 * (C) Copyright 2008
3 * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This driver implements a lcd device for the ILITEK 922x display
11 * controller. The interface to the display is SPI and the display's
12 * memory is cyclically updated over the RGB interface.
13 */
14
15#include <linux/fb.h>
16#include <linux/delay.h>
17#include <linux/errno.h>
18#include <linux/init.h>
19#include <linux/kernel.h>
20#include <linux/lcd.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/slab.h>
24#include <linux/spi/spi.h>
25#include <linux/string.h>
26
27/* Register offset, see manual section 8.2 */
28#define REG_START_OSCILLATION 0x00
29#define REG_DRIVER_CODE_READ 0x00
30#define REG_DRIVER_OUTPUT_CONTROL 0x01
31#define REG_LCD_AC_DRIVEING_CONTROL 0x02
32#define REG_ENTRY_MODE 0x03
33#define REG_COMPARE_1 0x04
34#define REG_COMPARE_2 0x05
35#define REG_DISPLAY_CONTROL_1 0x07
36#define REG_DISPLAY_CONTROL_2 0x08
37#define REG_DISPLAY_CONTROL_3 0x09
38#define REG_FRAME_CYCLE_CONTROL 0x0B
39#define REG_EXT_INTF_CONTROL 0x0C
40#define REG_POWER_CONTROL_1 0x10
41#define REG_POWER_CONTROL_2 0x11
42#define REG_POWER_CONTROL_3 0x12
43#define REG_POWER_CONTROL_4 0x13
44#define REG_RAM_ADDRESS_SET 0x21
45#define REG_WRITE_DATA_TO_GRAM 0x22
46#define REG_RAM_WRITE_MASK1 0x23
47#define REG_RAM_WRITE_MASK2 0x24
48#define REG_GAMMA_CONTROL_1 0x30
49#define REG_GAMMA_CONTROL_2 0x31
50#define REG_GAMMA_CONTROL_3 0x32
51#define REG_GAMMA_CONTROL_4 0x33
52#define REG_GAMMA_CONTROL_5 0x34
53#define REG_GAMMA_CONTROL_6 0x35
54#define REG_GAMMA_CONTROL_7 0x36
55#define REG_GAMMA_CONTROL_8 0x37
56#define REG_GAMMA_CONTROL_9 0x38
57#define REG_GAMMA_CONTROL_10 0x39
58#define REG_GATE_SCAN_CONTROL 0x40
59#define REG_VERT_SCROLL_CONTROL 0x41
60#define REG_FIRST_SCREEN_DRIVE_POS 0x42
61#define REG_SECOND_SCREEN_DRIVE_POS 0x43
62#define REG_RAM_ADDR_POS_H 0x44
63#define REG_RAM_ADDR_POS_V 0x45
64#define REG_OSCILLATOR_CONTROL 0x4F
65#define REG_GPIO 0x60
66#define REG_OTP_VCM_PROGRAMMING 0x61
67#define REG_OTP_VCM_STATUS_ENABLE 0x62
68#define REG_OTP_PROGRAMMING_ID_KEY 0x65
69
70/*
71 * maximum frequency for register access
72 * (not for the GRAM access)
73 */
74#define ILITEK_MAX_FREQ_REG 4000000
75
76/*
77 * Device ID as found in the datasheet (supports 9221 and 9222)
78 */
79#define ILITEK_DEVICE_ID 0x9220
80#define ILITEK_DEVICE_ID_MASK 0xFFF0
81
82/* Last two bits in the START BYTE */
83#define START_RS_INDEX 0
84#define START_RS_REG 1
85#define START_RW_WRITE 0
86#define START_RW_READ 1
87
88/**
89 * START_BYTE(id, rs, rw)
90 *
91 * Set the start byte according to the required operation.
92 * The start byte is defined as:
93 * ----------------------------------
94 * | 0 | 1 | 1 | 1 | 0 | ID | RS | RW |
95 * ----------------------------------
96 * @id: display's id as set by the manufacturer
97 * @rs: operation type bit, one of:
98 * - START_RS_INDEX set the index register
99 * - START_RS_REG write/read registers/GRAM
100 * @rw: read/write operation
101 * - START_RW_WRITE write
102 * - START_RW_READ read
103 */
104#define START_BYTE(id, rs, rw) \
105 (0x70 | (((id) & 0x01) << 2) | (((rs) & 0x01) << 1) | ((rw) & 0x01))
106
107/**
108 * CHECK_FREQ_REG(spi_device s, spi_transfer x) - Check the frequency
109 * for the SPI transfer. According to the datasheet, the controller
110 * accept higher frequency for the GRAM transfer, but it requires
111 * lower frequency when the registers are read/written.
112 * The macro sets the frequency in the spi_transfer structure if
113 * the frequency exceeds the maximum value.
114 */
115#define CHECK_FREQ_REG(s, x) \
116 do { \
117 if (s->max_speed_hz > ILITEK_MAX_FREQ_REG) \
118 ((struct spi_transfer *)x)->speed_hz = \
119 ILITEK_MAX_FREQ_REG; \
120 } while (0)
121
122#define CMD_BUFSIZE 16
123
124#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
125
126#define set_tx_byte(b) (tx_invert ? ~(b) : b)
127
128/**
129 * ili922x_id - id as set by manufacturer
130 */
131static int ili922x_id = 1;
132module_param(ili922x_id, int, 0);
133
134static int tx_invert;
135module_param(tx_invert, int, 0);
136
137/**
138 * driver's private structure
139 */
140struct ili922x {
141 struct spi_device *spi;
142 struct lcd_device *ld;
143 int power;
144};
145
146/**
147 * ili922x_read_status - read status register from display
148 * @spi: spi device
149 * @rs: output value
150 */
151static int ili922x_read_status(struct spi_device *spi, u16 *rs)
152{
153 struct spi_message msg;
154 struct spi_transfer xfer;
155 unsigned char tbuf[CMD_BUFSIZE];
156 unsigned char rbuf[CMD_BUFSIZE];
157 int ret, i;
158
159 memset(&xfer, 0, sizeof(struct spi_transfer));
160 spi_message_init(&msg);
161 xfer.tx_buf = tbuf;
162 xfer.rx_buf = rbuf;
163 xfer.cs_change = 1;
164 CHECK_FREQ_REG(spi, &xfer);
165
166 tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX,
167 START_RW_READ));
168 /*
169 * we need 4-byte xfer here due to invalid dummy byte
170 * received after start byte
171 */
172 for (i = 1; i < 4; i++)
173 tbuf[i] = set_tx_byte(0); /* dummy */
174
175 xfer.bits_per_word = 8;
176 xfer.len = 4;
177 spi_message_add_tail(&xfer, &msg);
178 ret = spi_sync(spi, &msg);
179 if (ret < 0) {
180 dev_dbg(&spi->dev, "Error sending SPI message 0x%x", ret);
181 return ret;
182 }
183
184 *rs = (rbuf[2] << 8) + rbuf[3];
185 return 0;
186}
187
188/**
189 * ili922x_read - read register from display
190 * @spi: spi device
191 * @reg: offset of the register to be read
192 * @rx: output value
193 */
194static int ili922x_read(struct spi_device *spi, u8 reg, u16 *rx)
195{
196 struct spi_message msg;
197 struct spi_transfer xfer_regindex, xfer_regvalue;
198 unsigned char tbuf[CMD_BUFSIZE];
199 unsigned char rbuf[CMD_BUFSIZE];
200 int ret, len = 0, send_bytes;
201
202 memset(&xfer_regindex, 0, sizeof(struct spi_transfer));
203 memset(&xfer_regvalue, 0, sizeof(struct spi_transfer));
204 spi_message_init(&msg);
205 xfer_regindex.tx_buf = tbuf;
206 xfer_regindex.rx_buf = rbuf;
207 xfer_regindex.cs_change = 1;
208 CHECK_FREQ_REG(spi, &xfer_regindex);
209
210 tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX,
211 START_RW_WRITE));
212 tbuf[1] = set_tx_byte(0);
213 tbuf[2] = set_tx_byte(reg);
214 xfer_regindex.bits_per_word = 8;
215 len = xfer_regindex.len = 3;
216 spi_message_add_tail(&xfer_regindex, &msg);
217
218 send_bytes = len;
219
220 tbuf[len++] = set_tx_byte(START_BYTE(ili922x_id, START_RS_REG,
221 START_RW_READ));
222 tbuf[len++] = set_tx_byte(0);
223 tbuf[len] = set_tx_byte(0);
224
225 xfer_regvalue.cs_change = 1;
226 xfer_regvalue.len = 3;
227 xfer_regvalue.tx_buf = &tbuf[send_bytes];
228 xfer_regvalue.rx_buf = &rbuf[send_bytes];
229 CHECK_FREQ_REG(spi, &xfer_regvalue);
230
231 spi_message_add_tail(&xfer_regvalue, &msg);
232 ret = spi_sync(spi, &msg);
233 if (ret < 0) {
234 dev_dbg(&spi->dev, "Error sending SPI message 0x%x", ret);
235 return ret;
236 }
237
238 *rx = (rbuf[1 + send_bytes] << 8) + rbuf[2 + send_bytes];
239 return 0;
240}
241
242/**
243 * ili922x_write - write a controller register
244 * @spi: struct spi_device *
245 * @reg: offset of the register to be written
246 * @value: value to be written
247 */
248static int ili922x_write(struct spi_device *spi, u8 reg, u16 value)
249{
250 struct spi_message msg;
251 struct spi_transfer xfer_regindex, xfer_regvalue;
252 unsigned char tbuf[CMD_BUFSIZE];
253 unsigned char rbuf[CMD_BUFSIZE];
254 int ret, len = 0;
255
256 memset(&xfer_regindex, 0, sizeof(struct spi_transfer));
257 memset(&xfer_regvalue, 0, sizeof(struct spi_transfer));
258
259 spi_message_init(&msg);
260 xfer_regindex.tx_buf = tbuf;
261 xfer_regindex.rx_buf = rbuf;
262 xfer_regindex.cs_change = 1;
263 CHECK_FREQ_REG(spi, &xfer_regindex);
264
265 tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX,
266 START_RW_WRITE));
267 tbuf[1] = set_tx_byte(0);
268 tbuf[2] = set_tx_byte(reg);
269 xfer_regindex.bits_per_word = 8;
270 xfer_regindex.len = 3;
271 spi_message_add_tail(&xfer_regindex, &msg);
272
273 ret = spi_sync(spi, &msg);
274
275 spi_message_init(&msg);
276 len = 0;
277 tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_REG,
278 START_RW_WRITE));
279 tbuf[1] = set_tx_byte((value & 0xFF00) >> 8);
280 tbuf[2] = set_tx_byte(value & 0x00FF);
281
282 xfer_regvalue.cs_change = 1;
283 xfer_regvalue.len = 3;
284 xfer_regvalue.tx_buf = tbuf;
285 xfer_regvalue.rx_buf = rbuf;
286 CHECK_FREQ_REG(spi, &xfer_regvalue);
287
288 spi_message_add_tail(&xfer_regvalue, &msg);
289
290 ret = spi_sync(spi, &msg);
291 if (ret < 0) {
292 dev_err(&spi->dev, "Error sending SPI message 0x%x", ret);
293 return ret;
294 }
295 return 0;
296}
297
298#ifdef DEBUG
299/**
300 * ili922x_reg_dump - dump all registers
301 */
302static void ili922x_reg_dump(struct spi_device *spi)
303{
304 u8 reg;
305 u16 rx;
306
307 dev_dbg(&spi->dev, "ILI922x configuration registers:\n");
308 for (reg = REG_START_OSCILLATION;
309 reg <= REG_OTP_PROGRAMMING_ID_KEY; reg++) {
310 ili922x_read(spi, reg, &rx);
311 dev_dbg(&spi->dev, "reg @ 0x%02X: 0x%04X\n", reg, rx);
312 }
313}
314#else
315static inline void ili922x_reg_dump(struct spi_device *spi) {}
316#endif
317
318/**
319 * set_write_to_gram_reg - initialize the display to write the GRAM
320 * @spi: spi device
321 */
322static void set_write_to_gram_reg(struct spi_device *spi)
323{
324 struct spi_message msg;
325 struct spi_transfer xfer;
326 unsigned char tbuf[CMD_BUFSIZE];
327
328 memset(&xfer, 0, sizeof(struct spi_transfer));
329
330 spi_message_init(&msg);
331 xfer.tx_buf = tbuf;
332 xfer.rx_buf = NULL;
333 xfer.cs_change = 1;
334
335 tbuf[0] = START_BYTE(ili922x_id, START_RS_INDEX, START_RW_WRITE);
336 tbuf[1] = 0;
337 tbuf[2] = REG_WRITE_DATA_TO_GRAM;
338
339 xfer.bits_per_word = 8;
340 xfer.len = 3;
341 spi_message_add_tail(&xfer, &msg);
342 spi_sync(spi, &msg);
343}
344
345/**
346 * ili922x_poweron - turn the display on
347 * @spi: spi device
348 *
349 * The sequence to turn on the display is taken from
350 * the datasheet and/or the example code provided by the
351 * manufacturer.
352 */
353static int ili922x_poweron(struct spi_device *spi)
354{
355 int ret;
356
357 /* Power on */
358 ret = ili922x_write(spi, REG_POWER_CONTROL_1, 0x0000);
359 usleep_range(10000, 10500);
360 ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000);
361 ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0000);
362 msleep(40);
363 ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x0000);
364 msleep(40);
365 /* register 0x56 is not documented in the datasheet */
366 ret += ili922x_write(spi, 0x56, 0x080F);
367 ret += ili922x_write(spi, REG_POWER_CONTROL_1, 0x4240);
368 usleep_range(10000, 10500);
369 ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000);
370 ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0014);
371 msleep(40);
372 ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x1319);
373 msleep(40);
374
375 return ret;
376}
377
378/**
379 * ili922x_poweroff - turn the display off
380 * @spi: spi device
381 */
382static int ili922x_poweroff(struct spi_device *spi)
383{
384 int ret;
385
386 /* Power off */
387 ret = ili922x_write(spi, REG_POWER_CONTROL_1, 0x0000);
388 usleep_range(10000, 10500);
389 ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000);
390 ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0000);
391 msleep(40);
392 ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x0000);
393 msleep(40);
394
395 return ret;
396}
397
398/**
399 * ili922x_display_init - initialize the display by setting
400 * the configuration registers
401 * @spi: spi device
402 */
403static void ili922x_display_init(struct spi_device *spi)
404{
405 ili922x_write(spi, REG_START_OSCILLATION, 1);
406 usleep_range(10000, 10500);
407 ili922x_write(spi, REG_DRIVER_OUTPUT_CONTROL, 0x691B);
408 ili922x_write(spi, REG_LCD_AC_DRIVEING_CONTROL, 0x0700);
409 ili922x_write(spi, REG_ENTRY_MODE, 0x1030);
410 ili922x_write(spi, REG_COMPARE_1, 0x0000);
411 ili922x_write(spi, REG_COMPARE_2, 0x0000);
412 ili922x_write(spi, REG_DISPLAY_CONTROL_1, 0x0037);
413 ili922x_write(spi, REG_DISPLAY_CONTROL_2, 0x0202);
414 ili922x_write(spi, REG_DISPLAY_CONTROL_3, 0x0000);
415 ili922x_write(spi, REG_FRAME_CYCLE_CONTROL, 0x0000);
416
417 /* Set RGB interface */
418 ili922x_write(spi, REG_EXT_INTF_CONTROL, 0x0110);
419
420 ili922x_poweron(spi);
421
422 ili922x_write(spi, REG_GAMMA_CONTROL_1, 0x0302);
423 ili922x_write(spi, REG_GAMMA_CONTROL_2, 0x0407);
424 ili922x_write(spi, REG_GAMMA_CONTROL_3, 0x0304);
425 ili922x_write(spi, REG_GAMMA_CONTROL_4, 0x0203);
426 ili922x_write(spi, REG_GAMMA_CONTROL_5, 0x0706);
427 ili922x_write(spi, REG_GAMMA_CONTROL_6, 0x0407);
428 ili922x_write(spi, REG_GAMMA_CONTROL_7, 0x0706);
429 ili922x_write(spi, REG_GAMMA_CONTROL_8, 0x0000);
430 ili922x_write(spi, REG_GAMMA_CONTROL_9, 0x0C06);
431 ili922x_write(spi, REG_GAMMA_CONTROL_10, 0x0F00);
432 ili922x_write(spi, REG_RAM_ADDRESS_SET, 0x0000);
433 ili922x_write(spi, REG_GATE_SCAN_CONTROL, 0x0000);
434 ili922x_write(spi, REG_VERT_SCROLL_CONTROL, 0x0000);
435 ili922x_write(spi, REG_FIRST_SCREEN_DRIVE_POS, 0xDB00);
436 ili922x_write(spi, REG_SECOND_SCREEN_DRIVE_POS, 0xDB00);
437 ili922x_write(spi, REG_RAM_ADDR_POS_H, 0xAF00);
438 ili922x_write(spi, REG_RAM_ADDR_POS_V, 0xDB00);
439 ili922x_reg_dump(spi);
440 set_write_to_gram_reg(spi);
441}
442
443static int ili922x_lcd_power(struct ili922x *lcd, int power)
444{
445 int ret = 0;
446
447 if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
448 ret = ili922x_poweron(lcd->spi);
449 else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
450 ret = ili922x_poweroff(lcd->spi);
451
452 if (!ret)
453 lcd->power = power;
454
455 return ret;
456}
457
458static int ili922x_set_power(struct lcd_device *ld, int power)
459{
460 struct ili922x *ili = lcd_get_data(ld);
461
462 return ili922x_lcd_power(ili, power);
463}
464
465static int ili922x_get_power(struct lcd_device *ld)
466{
467 struct ili922x *ili = lcd_get_data(ld);
468
469 return ili->power;
470}
471
472static struct lcd_ops ili922x_ops = {
473 .get_power = ili922x_get_power,
474 .set_power = ili922x_set_power,
475};
476
477static int ili922x_probe(struct spi_device *spi)
478{
479 struct ili922x *ili;
480 struct lcd_device *lcd;
481 int ret;
482 u16 reg = 0;
483
484 ili = devm_kzalloc(&spi->dev, sizeof(*ili), GFP_KERNEL);
485 if (!ili) {
486 dev_err(&spi->dev, "cannot alloc priv data\n");
487 return -ENOMEM;
488 }
489
490 ili->spi = spi;
491 spi_set_drvdata(spi, ili);
492
493 /* check if the device is connected */
494 ret = ili922x_read(spi, REG_DRIVER_CODE_READ, &reg);
495 if (ret || ((reg & ILITEK_DEVICE_ID_MASK) != ILITEK_DEVICE_ID)) {
496 dev_err(&spi->dev,
497 "no LCD found: Chip ID 0x%x, ret %d\n",
498 reg, ret);
499 return -ENODEV;
500 } else {
501 dev_info(&spi->dev, "ILI%x found, SPI freq %d, mode %d\n",
502 reg, spi->max_speed_hz, spi->mode);
503 }
504
505 ret = ili922x_read_status(spi, &reg);
506 if (ret) {
507 dev_err(&spi->dev, "reading RS failed...\n");
508 return ret;
509 } else
510 dev_dbg(&spi->dev, "status: 0x%x\n", reg);
511
512 ili922x_display_init(spi);
513
514 ili->power = FB_BLANK_POWERDOWN;
515
516 lcd = lcd_device_register("ili922xlcd", &spi->dev, ili,
517 &ili922x_ops);
518 if (IS_ERR(lcd)) {
519 dev_err(&spi->dev, "cannot register LCD\n");
520 return PTR_ERR(lcd);
521 }
522
523 ili->ld = lcd;
524 spi_set_drvdata(spi, ili);
525
526 ili922x_lcd_power(ili, FB_BLANK_UNBLANK);
527
528 return 0;
529}
530
531static int ili922x_remove(struct spi_device *spi)
532{
533 struct ili922x *ili = spi_get_drvdata(spi);
534
535 ili922x_poweroff(spi);
536 lcd_device_unregister(ili->ld);
537 return 0;
538}
539
540static struct spi_driver ili922x_driver = {
541 .driver = {
542 .name = "ili922x",
543 .owner = THIS_MODULE,
544 },
545 .probe = ili922x_probe,
546 .remove = ili922x_remove,
547};
548
549module_spi_driver(ili922x_driver);
550
551MODULE_AUTHOR("Stefano Babic <sbabic@denx.de>");
552MODULE_DESCRIPTION("ILI9221/9222 LCD driver");
553MODULE_LICENSE("GPL");
554MODULE_PARM_DESC(ili922x_id, "set controller identifier (default=1)");
555MODULE_PARM_DESC(tx_invert, "invert bytes before sending");
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
index 1235bf9defc4..f8be90c5dedc 100644
--- a/drivers/video/backlight/ili9320.c
+++ b/drivers/video/backlight/ili9320.c
@@ -231,7 +231,7 @@ int ili9320_probe_spi(struct spi_device *spi,
231 ili->power = FB_BLANK_POWERDOWN; 231 ili->power = FB_BLANK_POWERDOWN;
232 ili->platdata = cfg; 232 ili->platdata = cfg;
233 233
234 dev_set_drvdata(&spi->dev, ili); 234 spi_set_drvdata(spi, ili);
235 235
236 ili9320_setup_spi(ili, spi); 236 ili9320_setup_spi(ili, spi);
237 237
@@ -270,27 +270,21 @@ int ili9320_remove(struct ili9320 *ili)
270} 270}
271EXPORT_SYMBOL_GPL(ili9320_remove); 271EXPORT_SYMBOL_GPL(ili9320_remove);
272 272
273#ifdef CONFIG_PM 273#ifdef CONFIG_PM_SLEEP
274int ili9320_suspend(struct ili9320 *lcd, pm_message_t state) 274int ili9320_suspend(struct ili9320 *lcd)
275{ 275{
276 int ret; 276 int ret;
277 277
278 dev_dbg(lcd->dev, "%s: event %d\n", __func__, state.event); 278 ret = ili9320_power(lcd, FB_BLANK_POWERDOWN);
279 279
280 if (state.event == PM_EVENT_SUSPEND) { 280 if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
281 ret = ili9320_power(lcd, FB_BLANK_POWERDOWN); 281 ili9320_write(lcd, ILI9320_POWER1, lcd->power1 |
282 282 ILI9320_POWER1_SLP |
283 if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) { 283 ILI9320_POWER1_DSTB);
284 ili9320_write(lcd, ILI9320_POWER1, lcd->power1 | 284 lcd->initialised = 0;
285 ILI9320_POWER1_SLP |
286 ILI9320_POWER1_DSTB);
287 lcd->initialised = 0;
288 }
289
290 return ret;
291 } 285 }
292 286
293 return 0; 287 return ret;
294} 288}
295EXPORT_SYMBOL_GPL(ili9320_suspend); 289EXPORT_SYMBOL_GPL(ili9320_suspend);
296 290
diff --git a/drivers/video/backlight/ili9320.h b/drivers/video/backlight/ili9320.h
index e0db738f7bb9..42329e7aa9a8 100644
--- a/drivers/video/backlight/ili9320.h
+++ b/drivers/video/backlight/ili9320.h
@@ -76,5 +76,5 @@ extern void ili9320_shutdown(struct ili9320 *lcd);
76 76
77/* PM */ 77/* PM */
78 78
79extern int ili9320_suspend(struct ili9320 *lcd, pm_message_t state); 79extern int ili9320_suspend(struct ili9320 *lcd);
80extern int ili9320_resume(struct ili9320 *lcd); 80extern int ili9320_resume(struct ili9320 *lcd);
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index fef6ce4fad71..3ccb89340f22 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -9,8 +9,6 @@
9 * 9 *
10 */ 10 */
11 11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14#include <linux/backlight.h> 12#include <linux/backlight.h>
15#include <linux/device.h> 13#include <linux/device.h>
16#include <linux/fb.h> 14#include <linux/fb.h>
@@ -40,11 +38,13 @@ static int jornada_bl_get_brightness(struct backlight_device *bd)
40 ret = jornada_ssp_byte(GETBRIGHTNESS); 38 ret = jornada_ssp_byte(GETBRIGHTNESS);
41 39
42 if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) { 40 if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) {
43 pr_err("get brightness timeout\n"); 41 dev_err(&bd->dev, "get brightness timeout\n");
44 jornada_ssp_end(); 42 jornada_ssp_end();
45 return -ETIMEDOUT; 43 return -ETIMEDOUT;
46 } else /* exchange txdummy for value */ 44 } else {
45 /* exchange txdummy for value */
47 ret = jornada_ssp_byte(TXDUMMY); 46 ret = jornada_ssp_byte(TXDUMMY);
47 }
48 48
49 jornada_ssp_end(); 49 jornada_ssp_end();
50 50
@@ -61,7 +61,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
61 if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) { 61 if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
62 ret = jornada_ssp_byte(BRIGHTNESSOFF); 62 ret = jornada_ssp_byte(BRIGHTNESSOFF);
63 if (ret != TXDUMMY) { 63 if (ret != TXDUMMY) {
64 pr_info("brightness off timeout\n"); 64 dev_info(&bd->dev, "brightness off timeout\n");
65 /* turn off backlight */ 65 /* turn off backlight */
66 PPSR &= ~PPC_LDD1; 66 PPSR &= ~PPC_LDD1;
67 PPDR |= PPC_LDD1; 67 PPDR |= PPC_LDD1;
@@ -72,7 +72,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
72 72
73 /* send command to our mcu */ 73 /* send command to our mcu */
74 if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) { 74 if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
75 pr_info("failed to set brightness\n"); 75 dev_info(&bd->dev, "failed to set brightness\n");
76 ret = -ETIMEDOUT; 76 ret = -ETIMEDOUT;
77 goto out; 77 goto out;
78 } 78 }
@@ -86,7 +86,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
86 */ 86 */
87 if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) 87 if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness)
88 != TXDUMMY) { 88 != TXDUMMY) {
89 pr_err("set brightness failed\n"); 89 dev_err(&bd->dev, "set brightness failed\n");
90 ret = -ETIMEDOUT; 90 ret = -ETIMEDOUT;
91 } 91 }
92 92
@@ -120,7 +120,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
120 120
121 if (IS_ERR(bd)) { 121 if (IS_ERR(bd)) {
122 ret = PTR_ERR(bd); 122 ret = PTR_ERR(bd);
123 pr_err("failed to register device, err=%x\n", ret); 123 dev_err(&pdev->dev, "failed to register device, err=%x\n", ret);
124 return ret; 124 return ret;
125 } 125 }
126 126
@@ -134,7 +134,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
134 jornada_bl_update_status(bd); 134 jornada_bl_update_status(bd);
135 135
136 platform_set_drvdata(pdev, bd); 136 platform_set_drvdata(pdev, bd);
137 pr_info("HP Jornada 700 series backlight driver\n"); 137 dev_info(&pdev->dev, "HP Jornada 700 series backlight driver\n");
138 138
139 return 0; 139 return 0;
140} 140}
diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c
index 635b30523fd5..b061413f1a65 100644
--- a/drivers/video/backlight/jornada720_lcd.c
+++ b/drivers/video/backlight/jornada720_lcd.c
@@ -9,8 +9,6 @@
9 * 9 *
10 */ 10 */
11 11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14#include <linux/device.h> 12#include <linux/device.h>
15#include <linux/fb.h> 13#include <linux/fb.h>
16#include <linux/kernel.h> 14#include <linux/kernel.h>
@@ -27,7 +25,7 @@
27#define LCD_MAX_CONTRAST 0xff 25#define LCD_MAX_CONTRAST 0xff
28#define LCD_DEF_CONTRAST 0x80 26#define LCD_DEF_CONTRAST 0x80
29 27
30static int jornada_lcd_get_power(struct lcd_device *dev) 28static int jornada_lcd_get_power(struct lcd_device *ld)
31{ 29{
32 /* LDD2 in PPC = LCD POWER */ 30 /* LDD2 in PPC = LCD POWER */
33 if (PPSR & PPC_LDD2) 31 if (PPSR & PPC_LDD2)
@@ -36,17 +34,17 @@ static int jornada_lcd_get_power(struct lcd_device *dev)
36 return FB_BLANK_POWERDOWN; /* PW OFF */ 34 return FB_BLANK_POWERDOWN; /* PW OFF */
37} 35}
38 36
39static int jornada_lcd_get_contrast(struct lcd_device *dev) 37static int jornada_lcd_get_contrast(struct lcd_device *ld)
40{ 38{
41 int ret; 39 int ret;
42 40
43 if (jornada_lcd_get_power(dev) != FB_BLANK_UNBLANK) 41 if (jornada_lcd_get_power(ld) != FB_BLANK_UNBLANK)
44 return 0; 42 return 0;
45 43
46 jornada_ssp_start(); 44 jornada_ssp_start();
47 45
48 if (jornada_ssp_byte(GETCONTRAST) != TXDUMMY) { 46 if (jornada_ssp_byte(GETCONTRAST) != TXDUMMY) {
49 pr_err("get contrast failed\n"); 47 dev_err(&ld->dev, "get contrast failed\n");
50 jornada_ssp_end(); 48 jornada_ssp_end();
51 return -ETIMEDOUT; 49 return -ETIMEDOUT;
52 } else { 50 } else {
@@ -56,7 +54,7 @@ static int jornada_lcd_get_contrast(struct lcd_device *dev)
56 } 54 }
57} 55}
58 56
59static int jornada_lcd_set_contrast(struct lcd_device *dev, int value) 57static int jornada_lcd_set_contrast(struct lcd_device *ld, int value)
60{ 58{
61 int ret; 59 int ret;
62 60
@@ -67,7 +65,7 @@ static int jornada_lcd_set_contrast(struct lcd_device *dev, int value)
67 65
68 /* push the new value */ 66 /* push the new value */
69 if (jornada_ssp_byte(value) != TXDUMMY) { 67 if (jornada_ssp_byte(value) != TXDUMMY) {
70 pr_err("set contrast failed\n"); 68 dev_err(&ld->dev, "set contrast failed\n");
71 jornada_ssp_end(); 69 jornada_ssp_end();
72 return -ETIMEDOUT; 70 return -ETIMEDOUT;
73 } 71 }
@@ -78,13 +76,14 @@ static int jornada_lcd_set_contrast(struct lcd_device *dev, int value)
78 return 0; 76 return 0;
79} 77}
80 78
81static int jornada_lcd_set_power(struct lcd_device *dev, int power) 79static int jornada_lcd_set_power(struct lcd_device *ld, int power)
82{ 80{
83 if (power != FB_BLANK_UNBLANK) { 81 if (power != FB_BLANK_UNBLANK) {
84 PPSR &= ~PPC_LDD2; 82 PPSR &= ~PPC_LDD2;
85 PPDR |= PPC_LDD2; 83 PPDR |= PPC_LDD2;
86 } else 84 } else {
87 PPSR |= PPC_LDD2; 85 PPSR |= PPC_LDD2;
86 }
88 87
89 return 0; 88 return 0;
90} 89}
@@ -105,7 +104,7 @@ static int jornada_lcd_probe(struct platform_device *pdev)
105 104
106 if (IS_ERR(lcd_device)) { 105 if (IS_ERR(lcd_device)) {
107 ret = PTR_ERR(lcd_device); 106 ret = PTR_ERR(lcd_device);
108 pr_err("failed to register device\n"); 107 dev_err(&pdev->dev, "failed to register device\n");
109 return ret; 108 return ret;
110 } 109 }
111 110
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c
index 6c5ed6b242cc..bca6ccc74dfb 100644
--- a/drivers/video/backlight/kb3886_bl.c
+++ b/drivers/video/backlight/kb3886_bl.c
@@ -106,29 +106,28 @@ static int kb3886bl_send_intensity(struct backlight_device *bd)
106 return 0; 106 return 0;
107} 107}
108 108
109#ifdef CONFIG_PM 109#ifdef CONFIG_PM_SLEEP
110static int kb3886bl_suspend(struct platform_device *pdev, pm_message_t state) 110static int kb3886bl_suspend(struct device *dev)
111{ 111{
112 struct backlight_device *bd = platform_get_drvdata(pdev); 112 struct backlight_device *bd = dev_get_drvdata(dev);
113 113
114 kb3886bl_flags |= KB3886BL_SUSPENDED; 114 kb3886bl_flags |= KB3886BL_SUSPENDED;
115 backlight_update_status(bd); 115 backlight_update_status(bd);
116 return 0; 116 return 0;
117} 117}
118 118
119static int kb3886bl_resume(struct platform_device *pdev) 119static int kb3886bl_resume(struct device *dev)
120{ 120{
121 struct backlight_device *bd = platform_get_drvdata(pdev); 121 struct backlight_device *bd = dev_get_drvdata(dev);
122 122
123 kb3886bl_flags &= ~KB3886BL_SUSPENDED; 123 kb3886bl_flags &= ~KB3886BL_SUSPENDED;
124 backlight_update_status(bd); 124 backlight_update_status(bd);
125 return 0; 125 return 0;
126} 126}
127#else
128#define kb3886bl_suspend NULL
129#define kb3886bl_resume NULL
130#endif 127#endif
131 128
129static SIMPLE_DEV_PM_OPS(kb3886bl_pm_ops, kb3886bl_suspend, kb3886bl_resume);
130
132static int kb3886bl_get_intensity(struct backlight_device *bd) 131static int kb3886bl_get_intensity(struct backlight_device *bd)
133{ 132{
134 return kb3886bl_intensity; 133 return kb3886bl_intensity;
@@ -179,10 +178,9 @@ static int kb3886bl_remove(struct platform_device *pdev)
179static struct platform_driver kb3886bl_driver = { 178static struct platform_driver kb3886bl_driver = {
180 .probe = kb3886bl_probe, 179 .probe = kb3886bl_probe,
181 .remove = kb3886bl_remove, 180 .remove = kb3886bl_remove,
182 .suspend = kb3886bl_suspend,
183 .resume = kb3886bl_resume,
184 .driver = { 181 .driver = {
185 .name = "kb3886-bl", 182 .name = "kb3886-bl",
183 .pm = &kb3886bl_pm_ops,
186 }, 184 },
187}; 185};
188 186
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index fb6155771326..a35a38c709cf 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -51,14 +51,33 @@ static void l4f00242t03_lcd_init(struct spi_device *spi)
51 struct l4f00242t03_pdata *pdata = spi->dev.platform_data; 51 struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
52 struct l4f00242t03_priv *priv = spi_get_drvdata(spi); 52 struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
53 const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) }; 53 const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) };
54 int ret;
54 55
55 dev_dbg(&spi->dev, "initializing LCD\n"); 56 dev_dbg(&spi->dev, "initializing LCD\n");
56 57
57 regulator_set_voltage(priv->io_reg, 1800000, 1800000); 58 ret = regulator_set_voltage(priv->io_reg, 1800000, 1800000);
58 regulator_enable(priv->io_reg); 59 if (ret) {
60 dev_err(&spi->dev, "failed to set the IO regulator voltage.\n");
61 return;
62 }
63 ret = regulator_enable(priv->io_reg);
64 if (ret) {
65 dev_err(&spi->dev, "failed to enable the IO regulator.\n");
66 return;
67 }
59 68
60 regulator_set_voltage(priv->core_reg, 2800000, 2800000); 69 ret = regulator_set_voltage(priv->core_reg, 2800000, 2800000);
61 regulator_enable(priv->core_reg); 70 if (ret) {
71 dev_err(&spi->dev, "failed to set the core regulator voltage.\n");
72 regulator_disable(priv->io_reg);
73 return;
74 }
75 ret = regulator_enable(priv->core_reg);
76 if (ret) {
77 dev_err(&spi->dev, "failed to enable the core regulator.\n");
78 regulator_disable(priv->io_reg);
79 return;
80 }
62 81
63 l4f00242t03_reset(pdata->reset_gpio); 82 l4f00242t03_reset(pdata->reset_gpio);
64 83
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index 1b642f5f381a..1e0a3093ce50 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -775,12 +775,12 @@ static int ld9040_remove(struct spi_device *spi)
775 return 0; 775 return 0;
776} 776}
777 777
778#if defined(CONFIG_PM) 778#ifdef CONFIG_PM_SLEEP
779static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg) 779static int ld9040_suspend(struct device *dev)
780{ 780{
781 struct ld9040 *lcd = spi_get_drvdata(spi); 781 struct ld9040 *lcd = dev_get_drvdata(dev);
782 782
783 dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); 783 dev_dbg(dev, "lcd->power = %d\n", lcd->power);
784 784
785 /* 785 /*
786 * when lcd panel is suspend, lcd panel becomes off 786 * when lcd panel is suspend, lcd panel becomes off
@@ -789,19 +789,18 @@ static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg)
789 return ld9040_power(lcd, FB_BLANK_POWERDOWN); 789 return ld9040_power(lcd, FB_BLANK_POWERDOWN);
790} 790}
791 791
792static int ld9040_resume(struct spi_device *spi) 792static int ld9040_resume(struct device *dev)
793{ 793{
794 struct ld9040 *lcd = spi_get_drvdata(spi); 794 struct ld9040 *lcd = dev_get_drvdata(dev);
795 795
796 lcd->power = FB_BLANK_POWERDOWN; 796 lcd->power = FB_BLANK_POWERDOWN;
797 797
798 return ld9040_power(lcd, FB_BLANK_UNBLANK); 798 return ld9040_power(lcd, FB_BLANK_UNBLANK);
799} 799}
800#else
801#define ld9040_suspend NULL
802#define ld9040_resume NULL
803#endif 800#endif
804 801
802static SIMPLE_DEV_PM_OPS(ld9040_pm_ops, ld9040_suspend, ld9040_resume);
803
805/* Power down all displays on reboot, poweroff or halt. */ 804/* Power down all displays on reboot, poweroff or halt. */
806static void ld9040_shutdown(struct spi_device *spi) 805static void ld9040_shutdown(struct spi_device *spi)
807{ 806{
@@ -814,12 +813,11 @@ static struct spi_driver ld9040_driver = {
814 .driver = { 813 .driver = {
815 .name = "ld9040", 814 .name = "ld9040",
816 .owner = THIS_MODULE, 815 .owner = THIS_MODULE,
816 .pm = &ld9040_pm_ops,
817 }, 817 },
818 .probe = ld9040_probe, 818 .probe = ld9040_probe,
819 .remove = ld9040_remove, 819 .remove = ld9040_remove,
820 .shutdown = ld9040_shutdown, 820 .shutdown = ld9040_shutdown,
821 .suspend = ld9040_suspend,
822 .resume = ld9040_resume,
823}; 821};
824 822
825module_spi_driver(ld9040_driver); 823module_spi_driver(ld9040_driver);
diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c
index 5d18d4d7f470..1d1dbfb789e3 100644
--- a/drivers/video/backlight/lm3533_bl.c
+++ b/drivers/video/backlight/lm3533_bl.c
@@ -368,29 +368,28 @@ static int lm3533_bl_remove(struct platform_device *pdev)
368 return 0; 368 return 0;
369} 369}
370 370
371#ifdef CONFIG_PM 371#ifdef CONFIG_PM_SLEEP
372static int lm3533_bl_suspend(struct platform_device *pdev, pm_message_t state) 372static int lm3533_bl_suspend(struct device *dev)
373{ 373{
374 struct lm3533_bl *bl = platform_get_drvdata(pdev); 374 struct lm3533_bl *bl = dev_get_drvdata(dev);
375 375
376 dev_dbg(&pdev->dev, "%s\n", __func__); 376 dev_dbg(dev, "%s\n", __func__);
377 377
378 return lm3533_ctrlbank_disable(&bl->cb); 378 return lm3533_ctrlbank_disable(&bl->cb);
379} 379}
380 380
381static int lm3533_bl_resume(struct platform_device *pdev) 381static int lm3533_bl_resume(struct device *dev)
382{ 382{
383 struct lm3533_bl *bl = platform_get_drvdata(pdev); 383 struct lm3533_bl *bl = dev_get_drvdata(dev);
384 384
385 dev_dbg(&pdev->dev, "%s\n", __func__); 385 dev_dbg(dev, "%s\n", __func__);
386 386
387 return lm3533_ctrlbank_enable(&bl->cb); 387 return lm3533_ctrlbank_enable(&bl->cb);
388} 388}
389#else
390#define lm3533_bl_suspend NULL
391#define lm3533_bl_resume NULL
392#endif 389#endif
393 390
391static SIMPLE_DEV_PM_OPS(lm3533_bl_pm_ops, lm3533_bl_suspend, lm3533_bl_resume);
392
394static void lm3533_bl_shutdown(struct platform_device *pdev) 393static void lm3533_bl_shutdown(struct platform_device *pdev)
395{ 394{
396 struct lm3533_bl *bl = platform_get_drvdata(pdev); 395 struct lm3533_bl *bl = platform_get_drvdata(pdev);
@@ -404,12 +403,11 @@ static struct platform_driver lm3533_bl_driver = {
404 .driver = { 403 .driver = {
405 .name = "lm3533-backlight", 404 .name = "lm3533-backlight",
406 .owner = THIS_MODULE, 405 .owner = THIS_MODULE,
406 .pm = &lm3533_bl_pm_ops,
407 }, 407 },
408 .probe = lm3533_bl_probe, 408 .probe = lm3533_bl_probe,
409 .remove = lm3533_bl_remove, 409 .remove = lm3533_bl_remove,
410 .shutdown = lm3533_bl_shutdown, 410 .shutdown = lm3533_bl_shutdown,
411 .suspend = lm3533_bl_suspend,
412 .resume = lm3533_bl_resume,
413}; 411};
414module_platform_driver(lm3533_bl_driver); 412module_platform_driver(lm3533_bl_driver);
415 413
diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c
index b43882abefaf..cf01b9ac8131 100644
--- a/drivers/video/backlight/lms501kf03.c
+++ b/drivers/video/backlight/lms501kf03.c
@@ -387,13 +387,12 @@ static int lms501kf03_remove(struct spi_device *spi)
387 return 0; 387 return 0;
388} 388}
389 389
390#if defined(CONFIG_PM) 390#ifdef CONFIG_PM_SLEEP
391 391static int lms501kf03_suspend(struct device *dev)
392static int lms501kf03_suspend(struct spi_device *spi, pm_message_t mesg)
393{ 392{
394 struct lms501kf03 *lcd = spi_get_drvdata(spi); 393 struct lms501kf03 *lcd = dev_get_drvdata(dev);
395 394
396 dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); 395 dev_dbg(dev, "lcd->power = %d\n", lcd->power);
397 396
398 /* 397 /*
399 * when lcd panel is suspend, lcd panel becomes off 398 * when lcd panel is suspend, lcd panel becomes off
@@ -402,19 +401,19 @@ static int lms501kf03_suspend(struct spi_device *spi, pm_message_t mesg)
402 return lms501kf03_power(lcd, FB_BLANK_POWERDOWN); 401 return lms501kf03_power(lcd, FB_BLANK_POWERDOWN);
403} 402}
404 403
405static int lms501kf03_resume(struct spi_device *spi) 404static int lms501kf03_resume(struct device *dev)
406{ 405{
407 struct lms501kf03 *lcd = spi_get_drvdata(spi); 406 struct lms501kf03 *lcd = dev_get_drvdata(dev);
408 407
409 lcd->power = FB_BLANK_POWERDOWN; 408 lcd->power = FB_BLANK_POWERDOWN;
410 409
411 return lms501kf03_power(lcd, FB_BLANK_UNBLANK); 410 return lms501kf03_power(lcd, FB_BLANK_UNBLANK);
412} 411}
413#else
414#define lms501kf03_suspend NULL
415#define lms501kf03_resume NULL
416#endif 412#endif
417 413
414static SIMPLE_DEV_PM_OPS(lms501kf03_pm_ops, lms501kf03_suspend,
415 lms501kf03_resume);
416
418static void lms501kf03_shutdown(struct spi_device *spi) 417static void lms501kf03_shutdown(struct spi_device *spi)
419{ 418{
420 struct lms501kf03 *lcd = spi_get_drvdata(spi); 419 struct lms501kf03 *lcd = spi_get_drvdata(spi);
@@ -426,12 +425,11 @@ static struct spi_driver lms501kf03_driver = {
426 .driver = { 425 .driver = {
427 .name = "lms501kf03", 426 .name = "lms501kf03",
428 .owner = THIS_MODULE, 427 .owner = THIS_MODULE,
428 .pm = &lms501kf03_pm_ops,
429 }, 429 },
430 .probe = lms501kf03_probe, 430 .probe = lms501kf03_probe,
431 .remove = lms501kf03_remove, 431 .remove = lms501kf03_remove,
432 .shutdown = lms501kf03_shutdown, 432 .shutdown = lms501kf03_shutdown,
433 .suspend = lms501kf03_suspend,
434 .resume = lms501kf03_resume,
435}; 433};
436 434
437module_spi_driver(lms501kf03_driver); 435module_spi_driver(lms501kf03_driver);
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index 146fea8aa431..6c3ec4259a60 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -157,25 +157,24 @@ static const struct backlight_ops locomobl_data = {
157 .update_status = locomolcd_set_intensity, 157 .update_status = locomolcd_set_intensity,
158}; 158};
159 159
160#ifdef CONFIG_PM 160#ifdef CONFIG_PM_SLEEP
161static int locomolcd_suspend(struct locomo_dev *dev, pm_message_t state) 161static int locomolcd_suspend(struct device *dev)
162{ 162{
163 locomolcd_flags |= LOCOMOLCD_SUSPENDED; 163 locomolcd_flags |= LOCOMOLCD_SUSPENDED;
164 locomolcd_set_intensity(locomolcd_bl_device); 164 locomolcd_set_intensity(locomolcd_bl_device);
165 return 0; 165 return 0;
166} 166}
167 167
168static int locomolcd_resume(struct locomo_dev *dev) 168static int locomolcd_resume(struct device *dev)
169{ 169{
170 locomolcd_flags &= ~LOCOMOLCD_SUSPENDED; 170 locomolcd_flags &= ~LOCOMOLCD_SUSPENDED;
171 locomolcd_set_intensity(locomolcd_bl_device); 171 locomolcd_set_intensity(locomolcd_bl_device);
172 return 0; 172 return 0;
173} 173}
174#else
175#define locomolcd_suspend NULL
176#define locomolcd_resume NULL
177#endif 174#endif
178 175
176static SIMPLE_DEV_PM_OPS(locomolcd_pm_ops, locomolcd_suspend, locomolcd_resume);
177
179static int locomolcd_probe(struct locomo_dev *ldev) 178static int locomolcd_probe(struct locomo_dev *ldev)
180{ 179{
181 struct backlight_properties props; 180 struct backlight_properties props;
@@ -230,13 +229,12 @@ static int locomolcd_remove(struct locomo_dev *dev)
230 229
231static struct locomo_driver poodle_lcd_driver = { 230static struct locomo_driver poodle_lcd_driver = {
232 .drv = { 231 .drv = {
233 .name = "locomo-backlight", 232 .name = "locomo-backlight",
233 .pm = &locomolcd_pm_ops,
234 }, 234 },
235 .devid = LOCOMO_DEVID_BACKLIGHT, 235 .devid = LOCOMO_DEVID_BACKLIGHT,
236 .probe = locomolcd_probe, 236 .probe = locomolcd_probe,
237 .remove = locomolcd_remove, 237 .remove = locomolcd_remove,
238 .suspend = locomolcd_suspend,
239 .resume = locomolcd_resume,
240}; 238};
241 239
242static int __init locomolcd_init(void) 240static int __init locomolcd_init(void)
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index 7ae9ae6f4655..a0e1e02bdc2e 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -14,6 +14,7 @@
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/backlight.h> 15#include <linux/backlight.h>
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/of.h>
17#include <linux/platform_data/lp855x.h> 18#include <linux/platform_data/lp855x.h>
18#include <linux/pwm.h> 19#include <linux/pwm.h>
19 20
@@ -35,10 +36,14 @@
35#define LP8557_EPROM_START 0x10 36#define LP8557_EPROM_START 0x10
36#define LP8557_EPROM_END 0x1E 37#define LP8557_EPROM_END 0x1E
37 38
38#define BUF_SIZE 20
39#define DEFAULT_BL_NAME "lcd-backlight" 39#define DEFAULT_BL_NAME "lcd-backlight"
40#define MAX_BRIGHTNESS 255 40#define MAX_BRIGHTNESS 255
41 41
42enum lp855x_brightness_ctrl_mode {
43 PWM_BASED = 1,
44 REGISTER_BASED,
45};
46
42struct lp855x; 47struct lp855x;
43 48
44/* 49/*
@@ -58,6 +63,7 @@ struct lp855x_device_config {
58struct lp855x { 63struct lp855x {
59 const char *chipname; 64 const char *chipname;
60 enum lp855x_chip_id chip_id; 65 enum lp855x_chip_id chip_id;
66 enum lp855x_brightness_ctrl_mode mode;
61 struct lp855x_device_config *cfg; 67 struct lp855x_device_config *cfg;
62 struct i2c_client *client; 68 struct i2c_client *client;
63 struct backlight_device *bl; 69 struct backlight_device *bl;
@@ -187,7 +193,7 @@ static int lp855x_configure(struct lp855x *lp)
187 if (ret) 193 if (ret)
188 goto err; 194 goto err;
189 195
190 if (pd->load_new_rom_data && pd->size_program) { 196 if (pd->size_program > 0) {
191 for (i = 0; i < pd->size_program; i++) { 197 for (i = 0; i < pd->size_program; i++) {
192 addr = pd->rom_data[i].addr; 198 addr = pd->rom_data[i].addr;
193 val = pd->rom_data[i].val; 199 val = pd->rom_data[i].val;
@@ -239,18 +245,17 @@ static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)
239static int lp855x_bl_update_status(struct backlight_device *bl) 245static int lp855x_bl_update_status(struct backlight_device *bl)
240{ 246{
241 struct lp855x *lp = bl_get_data(bl); 247 struct lp855x *lp = bl_get_data(bl);
242 enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode;
243 248
244 if (bl->props.state & BL_CORE_SUSPENDED) 249 if (bl->props.state & BL_CORE_SUSPENDED)
245 bl->props.brightness = 0; 250 bl->props.brightness = 0;
246 251
247 if (mode == PWM_BASED) { 252 if (lp->mode == PWM_BASED) {
248 int br = bl->props.brightness; 253 int br = bl->props.brightness;
249 int max_br = bl->props.max_brightness; 254 int max_br = bl->props.max_brightness;
250 255
251 lp855x_pwm_ctrl(lp, br, max_br); 256 lp855x_pwm_ctrl(lp, br, max_br);
252 257
253 } else if (mode == REGISTER_BASED) { 258 } else if (lp->mode == REGISTER_BASED) {
254 u8 val = bl->props.brightness; 259 u8 val = bl->props.brightness;
255 lp855x_write_byte(lp, lp->cfg->reg_brightness, val); 260 lp855x_write_byte(lp, lp->cfg->reg_brightness, val);
256 } 261 }
@@ -274,7 +279,7 @@ static int lp855x_backlight_register(struct lp855x *lp)
274 struct backlight_device *bl; 279 struct backlight_device *bl;
275 struct backlight_properties props; 280 struct backlight_properties props;
276 struct lp855x_platform_data *pdata = lp->pdata; 281 struct lp855x_platform_data *pdata = lp->pdata;
277 char *name = pdata->name ? : DEFAULT_BL_NAME; 282 const char *name = pdata->name ? : DEFAULT_BL_NAME;
278 283
279 props.type = BACKLIGHT_PLATFORM; 284 props.type = BACKLIGHT_PLATFORM;
280 props.max_brightness = MAX_BRIGHTNESS; 285 props.max_brightness = MAX_BRIGHTNESS;
@@ -304,22 +309,21 @@ static ssize_t lp855x_get_chip_id(struct device *dev,
304 struct device_attribute *attr, char *buf) 309 struct device_attribute *attr, char *buf)
305{ 310{
306 struct lp855x *lp = dev_get_drvdata(dev); 311 struct lp855x *lp = dev_get_drvdata(dev);
307 return scnprintf(buf, BUF_SIZE, "%s\n", lp->chipname); 312 return scnprintf(buf, PAGE_SIZE, "%s\n", lp->chipname);
308} 313}
309 314
310static ssize_t lp855x_get_bl_ctl_mode(struct device *dev, 315static ssize_t lp855x_get_bl_ctl_mode(struct device *dev,
311 struct device_attribute *attr, char *buf) 316 struct device_attribute *attr, char *buf)
312{ 317{
313 struct lp855x *lp = dev_get_drvdata(dev); 318 struct lp855x *lp = dev_get_drvdata(dev);
314 enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode;
315 char *strmode = NULL; 319 char *strmode = NULL;
316 320
317 if (mode == PWM_BASED) 321 if (lp->mode == PWM_BASED)
318 strmode = "pwm based"; 322 strmode = "pwm based";
319 else if (mode == REGISTER_BASED) 323 else if (lp->mode == REGISTER_BASED)
320 strmode = "register based"; 324 strmode = "register based";
321 325
322 return scnprintf(buf, BUF_SIZE, "%s\n", strmode); 326 return scnprintf(buf, PAGE_SIZE, "%s\n", strmode);
323} 327}
324 328
325static DEVICE_ATTR(chip_id, S_IRUGO, lp855x_get_chip_id, NULL); 329static DEVICE_ATTR(chip_id, S_IRUGO, lp855x_get_chip_id, NULL);
@@ -335,16 +339,71 @@ static const struct attribute_group lp855x_attr_group = {
335 .attrs = lp855x_attributes, 339 .attrs = lp855x_attributes,
336}; 340};
337 341
342#ifdef CONFIG_OF
343static int lp855x_parse_dt(struct device *dev, struct device_node *node)
344{
345 struct lp855x_platform_data *pdata;
346 int rom_length;
347
348 if (!node) {
349 dev_err(dev, "no platform data\n");
350 return -EINVAL;
351 }
352
353 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
354 if (!pdata)
355 return -ENOMEM;
356
357 of_property_read_string(node, "bl-name", &pdata->name);
358 of_property_read_u8(node, "dev-ctrl", &pdata->device_control);
359 of_property_read_u8(node, "init-brt", &pdata->initial_brightness);
360 of_property_read_u32(node, "pwm-period", &pdata->period_ns);
361
362 /* Fill ROM platform data if defined */
363 rom_length = of_get_child_count(node);
364 if (rom_length > 0) {
365 struct lp855x_rom_data *rom;
366 struct device_node *child;
367 int i = 0;
368
369 rom = devm_kzalloc(dev, sizeof(*rom) * rom_length, GFP_KERNEL);
370 if (!rom)
371 return -ENOMEM;
372
373 for_each_child_of_node(node, child) {
374 of_property_read_u8(child, "rom-addr", &rom[i].addr);
375 of_property_read_u8(child, "rom-val", &rom[i].val);
376 i++;
377 }
378
379 pdata->size_program = rom_length;
380 pdata->rom_data = &rom[0];
381 }
382
383 dev->platform_data = pdata;
384
385 return 0;
386}
387#else
388static int lp855x_parse_dt(struct device *dev, struct device_node *node)
389{
390 return -EINVAL;
391}
392#endif
393
338static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) 394static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
339{ 395{
340 struct lp855x *lp; 396 struct lp855x *lp;
341 struct lp855x_platform_data *pdata = cl->dev.platform_data; 397 struct lp855x_platform_data *pdata = cl->dev.platform_data;
342 enum lp855x_brightness_ctrl_mode mode; 398 struct device_node *node = cl->dev.of_node;
343 int ret; 399 int ret;
344 400
345 if (!pdata) { 401 if (!pdata) {
346 dev_err(&cl->dev, "no platform data supplied\n"); 402 ret = lp855x_parse_dt(&cl->dev, node);
347 return -EINVAL; 403 if (ret < 0)
404 return ret;
405
406 pdata = cl->dev.platform_data;
348 } 407 }
349 408
350 if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) 409 if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
@@ -354,7 +413,11 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
354 if (!lp) 413 if (!lp)
355 return -ENOMEM; 414 return -ENOMEM;
356 415
357 mode = pdata->mode; 416 if (pdata->period_ns > 0)
417 lp->mode = PWM_BASED;
418 else
419 lp->mode = REGISTER_BASED;
420
358 lp->client = cl; 421 lp->client = cl;
359 lp->dev = &cl->dev; 422 lp->dev = &cl->dev;
360 lp->pdata = pdata; 423 lp->pdata = pdata;
@@ -402,6 +465,17 @@ static int lp855x_remove(struct i2c_client *cl)
402 return 0; 465 return 0;
403} 466}
404 467
468static const struct of_device_id lp855x_dt_ids[] = {
469 { .compatible = "ti,lp8550", },
470 { .compatible = "ti,lp8551", },
471 { .compatible = "ti,lp8552", },
472 { .compatible = "ti,lp8553", },
473 { .compatible = "ti,lp8556", },
474 { .compatible = "ti,lp8557", },
475 { }
476};
477MODULE_DEVICE_TABLE(of, lp855x_dt_ids);
478
405static const struct i2c_device_id lp855x_ids[] = { 479static const struct i2c_device_id lp855x_ids[] = {
406 {"lp8550", LP8550}, 480 {"lp8550", LP8550},
407 {"lp8551", LP8551}, 481 {"lp8551", LP8551},
@@ -416,6 +490,7 @@ MODULE_DEVICE_TABLE(i2c, lp855x_ids);
416static struct i2c_driver lp855x_driver = { 490static struct i2c_driver lp855x_driver = {
417 .driver = { 491 .driver = {
418 .name = "lp855x", 492 .name = "lp855x",
493 .of_match_table = of_match_ptr(lp855x_dt_ids),
419 }, 494 },
420 .probe = lp855x_probe, 495 .probe = lp855x_probe,
421 .remove = lp855x_remove, 496 .remove = lp855x_remove,
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
index c0b4b8f2de98..ed1b39268131 100644
--- a/drivers/video/backlight/ltv350qv.c
+++ b/drivers/video/backlight/ltv350qv.c
@@ -271,25 +271,24 @@ static int ltv350qv_remove(struct spi_device *spi)
271 return 0; 271 return 0;
272} 272}
273 273
274#ifdef CONFIG_PM 274#ifdef CONFIG_PM_SLEEP
275static int ltv350qv_suspend(struct spi_device *spi, pm_message_t state) 275static int ltv350qv_suspend(struct device *dev)
276{ 276{
277 struct ltv350qv *lcd = spi_get_drvdata(spi); 277 struct ltv350qv *lcd = dev_get_drvdata(dev);
278 278
279 return ltv350qv_power(lcd, FB_BLANK_POWERDOWN); 279 return ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
280} 280}
281 281
282static int ltv350qv_resume(struct spi_device *spi) 282static int ltv350qv_resume(struct device *dev)
283{ 283{
284 struct ltv350qv *lcd = spi_get_drvdata(spi); 284 struct ltv350qv *lcd = dev_get_drvdata(dev);
285 285
286 return ltv350qv_power(lcd, FB_BLANK_UNBLANK); 286 return ltv350qv_power(lcd, FB_BLANK_UNBLANK);
287} 287}
288#else
289#define ltv350qv_suspend NULL
290#define ltv350qv_resume NULL
291#endif 288#endif
292 289
290static SIMPLE_DEV_PM_OPS(ltv350qv_pm_ops, ltv350qv_suspend, ltv350qv_resume);
291
293/* Power down all displays on reboot, poweroff or halt */ 292/* Power down all displays on reboot, poweroff or halt */
294static void ltv350qv_shutdown(struct spi_device *spi) 293static void ltv350qv_shutdown(struct spi_device *spi)
295{ 294{
@@ -302,13 +301,12 @@ static struct spi_driver ltv350qv_driver = {
302 .driver = { 301 .driver = {
303 .name = "ltv350qv", 302 .name = "ltv350qv",
304 .owner = THIS_MODULE, 303 .owner = THIS_MODULE,
304 .pm = &ltv350qv_pm_ops,
305 }, 305 },
306 306
307 .probe = ltv350qv_probe, 307 .probe = ltv350qv_probe,
308 .remove = ltv350qv_remove, 308 .remove = ltv350qv_remove,
309 .shutdown = ltv350qv_shutdown, 309 .shutdown = ltv350qv_shutdown,
310 .suspend = ltv350qv_suspend,
311 .resume = ltv350qv_resume,
312}; 310};
313 311
314module_spi_driver(ltv350qv_driver); 312module_spi_driver(ltv350qv_driver);
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index 627110163067..812e22e35cab 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -18,8 +18,6 @@
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */ 19 */
20 20
21#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#include <linux/module.h> 21#include <linux/module.h>
24#include <linux/kernel.h> 22#include <linux/kernel.h>
25#include <linux/init.h> 23#include <linux/init.h>
@@ -73,27 +71,24 @@ static void omapbl_blank(struct omap_backlight *bl, int mode)
73 } 71 }
74} 72}
75 73
76#ifdef CONFIG_PM 74#ifdef CONFIG_PM_SLEEP
77static int omapbl_suspend(struct platform_device *pdev, pm_message_t state) 75static int omapbl_suspend(struct device *dev)
78{ 76{
79 struct backlight_device *dev = platform_get_drvdata(pdev); 77 struct backlight_device *bl_dev = dev_get_drvdata(dev);
80 struct omap_backlight *bl = bl_get_data(dev); 78 struct omap_backlight *bl = bl_get_data(bl_dev);
81 79
82 omapbl_blank(bl, FB_BLANK_POWERDOWN); 80 omapbl_blank(bl, FB_BLANK_POWERDOWN);
83 return 0; 81 return 0;
84} 82}
85 83
86static int omapbl_resume(struct platform_device *pdev) 84static int omapbl_resume(struct device *dev)
87{ 85{
88 struct backlight_device *dev = platform_get_drvdata(pdev); 86 struct backlight_device *bl_dev = dev_get_drvdata(dev);
89 struct omap_backlight *bl = bl_get_data(dev); 87 struct omap_backlight *bl = bl_get_data(bl_dev);
90 88
91 omapbl_blank(bl, bl->powermode); 89 omapbl_blank(bl, bl->powermode);
92 return 0; 90 return 0;
93} 91}
94#else
95#define omapbl_suspend NULL
96#define omapbl_resume NULL
97#endif 92#endif
98 93
99static int omapbl_set_power(struct backlight_device *dev, int state) 94static int omapbl_set_power(struct backlight_device *dev, int state)
@@ -170,7 +165,7 @@ static int omapbl_probe(struct platform_device *pdev)
170 dev->props.brightness = pdata->default_intensity; 165 dev->props.brightness = pdata->default_intensity;
171 omapbl_update_status(dev); 166 omapbl_update_status(dev);
172 167
173 pr_info("OMAP LCD backlight initialised\n"); 168 dev_info(&pdev->dev, "OMAP LCD backlight initialised\n");
174 169
175 return 0; 170 return 0;
176} 171}
@@ -184,13 +179,14 @@ static int omapbl_remove(struct platform_device *pdev)
184 return 0; 179 return 0;
185} 180}
186 181
182static SIMPLE_DEV_PM_OPS(omapbl_pm_ops, omapbl_suspend, omapbl_resume);
183
187static struct platform_driver omapbl_driver = { 184static struct platform_driver omapbl_driver = {
188 .probe = omapbl_probe, 185 .probe = omapbl_probe,
189 .remove = omapbl_remove, 186 .remove = omapbl_remove,
190 .suspend = omapbl_suspend,
191 .resume = omapbl_resume,
192 .driver = { 187 .driver = {
193 .name = "omap-bl", 188 .name = "omap-bl",
189 .pm = &omapbl_pm_ops,
194 }, 190 },
195}; 191};
196 192
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
index 17a6b83f97af..056836706708 100644
--- a/drivers/video/backlight/platform_lcd.c
+++ b/drivers/video/backlight/platform_lcd.c
@@ -86,6 +86,12 @@ static int platform_lcd_probe(struct platform_device *pdev)
86 return -EINVAL; 86 return -EINVAL;
87 } 87 }
88 88
89 if (pdata->probe) {
90 err = pdata->probe(pdata);
91 if (err)
92 return err;
93 }
94
89 plcd = devm_kzalloc(&pdev->dev, sizeof(struct platform_lcd), 95 plcd = devm_kzalloc(&pdev->dev, sizeof(struct platform_lcd),
90 GFP_KERNEL); 96 GFP_KERNEL);
91 if (!plcd) { 97 if (!plcd) {
@@ -121,7 +127,7 @@ static int platform_lcd_remove(struct platform_device *pdev)
121 return 0; 127 return 0;
122} 128}
123 129
124#ifdef CONFIG_PM 130#ifdef CONFIG_PM_SLEEP
125static int platform_lcd_suspend(struct device *dev) 131static int platform_lcd_suspend(struct device *dev)
126{ 132{
127 struct platform_lcd *plcd = dev_get_drvdata(dev); 133 struct platform_lcd *plcd = dev_get_drvdata(dev);
@@ -141,10 +147,10 @@ static int platform_lcd_resume(struct device *dev)
141 147
142 return 0; 148 return 0;
143} 149}
150#endif
144 151
145static SIMPLE_DEV_PM_OPS(platform_lcd_pm_ops, platform_lcd_suspend, 152static SIMPLE_DEV_PM_OPS(platform_lcd_pm_ops, platform_lcd_suspend,
146 platform_lcd_resume); 153 platform_lcd_resume);
147#endif
148 154
149#ifdef CONFIG_OF 155#ifdef CONFIG_OF
150static const struct of_device_id platform_lcd_of_match[] = { 156static const struct of_device_id platform_lcd_of_match[] = {
@@ -158,9 +164,7 @@ static struct platform_driver platform_lcd_driver = {
158 .driver = { 164 .driver = {
159 .name = "platform-lcd", 165 .name = "platform-lcd",
160 .owner = THIS_MODULE, 166 .owner = THIS_MODULE,
161#ifdef CONFIG_PM
162 .pm = &platform_lcd_pm_ops, 167 .pm = &platform_lcd_pm_ops,
163#endif
164 .of_match_table = of_match_ptr(platform_lcd_of_match), 168 .of_match_table = of_match_ptr(platform_lcd_of_match),
165 }, 169 },
166 .probe = platform_lcd_probe, 170 .probe = platform_lcd_probe,
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index fa00304a63d8..1fea627394d7 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -274,7 +274,7 @@ static int pwm_backlight_remove(struct platform_device *pdev)
274 return 0; 274 return 0;
275} 275}
276 276
277#ifdef CONFIG_PM 277#ifdef CONFIG_PM_SLEEP
278static int pwm_backlight_suspend(struct device *dev) 278static int pwm_backlight_suspend(struct device *dev)
279{ 279{
280 struct backlight_device *bl = dev_get_drvdata(dev); 280 struct backlight_device *bl = dev_get_drvdata(dev);
@@ -296,19 +296,16 @@ static int pwm_backlight_resume(struct device *dev)
296 backlight_update_status(bl); 296 backlight_update_status(bl);
297 return 0; 297 return 0;
298} 298}
299#endif
299 300
300static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend, 301static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend,
301 pwm_backlight_resume); 302 pwm_backlight_resume);
302 303
303#endif
304
305static struct platform_driver pwm_backlight_driver = { 304static struct platform_driver pwm_backlight_driver = {
306 .driver = { 305 .driver = {
307 .name = "pwm-backlight", 306 .name = "pwm-backlight",
308 .owner = THIS_MODULE, 307 .owner = THIS_MODULE,
309#ifdef CONFIG_PM
310 .pm = &pwm_backlight_pm_ops, 308 .pm = &pwm_backlight_pm_ops,
311#endif
312 .of_match_table = of_match_ptr(pwm_backlight_of_match), 309 .of_match_table = of_match_ptr(pwm_backlight_of_match),
313 }, 310 },
314 .probe = pwm_backlight_probe, 311 .probe = pwm_backlight_probe,
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index 9c2677f0ef7d..b37bb1854bf4 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -817,12 +817,12 @@ static int s6e63m0_remove(struct spi_device *spi)
817 return 0; 817 return 0;
818} 818}
819 819
820#if defined(CONFIG_PM) 820#ifdef CONFIG_PM_SLEEP
821static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) 821static int s6e63m0_suspend(struct device *dev)
822{ 822{
823 struct s6e63m0 *lcd = spi_get_drvdata(spi); 823 struct s6e63m0 *lcd = dev_get_drvdata(dev);
824 824
825 dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); 825 dev_dbg(dev, "lcd->power = %d\n", lcd->power);
826 826
827 /* 827 /*
828 * when lcd panel is suspend, lcd panel becomes off 828 * when lcd panel is suspend, lcd panel becomes off
@@ -831,19 +831,18 @@ static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg)
831 return s6e63m0_power(lcd, FB_BLANK_POWERDOWN); 831 return s6e63m0_power(lcd, FB_BLANK_POWERDOWN);
832} 832}
833 833
834static int s6e63m0_resume(struct spi_device *spi) 834static int s6e63m0_resume(struct device *dev)
835{ 835{
836 struct s6e63m0 *lcd = spi_get_drvdata(spi); 836 struct s6e63m0 *lcd = dev_get_drvdata(dev);
837 837
838 lcd->power = FB_BLANK_POWERDOWN; 838 lcd->power = FB_BLANK_POWERDOWN;
839 839
840 return s6e63m0_power(lcd, FB_BLANK_UNBLANK); 840 return s6e63m0_power(lcd, FB_BLANK_UNBLANK);
841} 841}
842#else
843#define s6e63m0_suspend NULL
844#define s6e63m0_resume NULL
845#endif 842#endif
846 843
844static SIMPLE_DEV_PM_OPS(s6e63m0_pm_ops, s6e63m0_suspend, s6e63m0_resume);
845
847/* Power down all displays on reboot, poweroff or halt. */ 846/* Power down all displays on reboot, poweroff or halt. */
848static void s6e63m0_shutdown(struct spi_device *spi) 847static void s6e63m0_shutdown(struct spi_device *spi)
849{ 848{
@@ -856,12 +855,11 @@ static struct spi_driver s6e63m0_driver = {
856 .driver = { 855 .driver = {
857 .name = "s6e63m0", 856 .name = "s6e63m0",
858 .owner = THIS_MODULE, 857 .owner = THIS_MODULE,
858 .pm = &s6e63m0_pm_ops,
859 }, 859 },
860 .probe = s6e63m0_probe, 860 .probe = s6e63m0_probe,
861 .remove = s6e63m0_remove, 861 .remove = s6e63m0_remove,
862 .shutdown = s6e63m0_shutdown, 862 .shutdown = s6e63m0_shutdown,
863 .suspend = s6e63m0_suspend,
864 .resume = s6e63m0_resume,
865}; 863};
866 864
867module_spi_driver(s6e63m0_driver); 865module_spi_driver(s6e63m0_driver);
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
index 00162085eec0..18cdf466d50a 100644
--- a/drivers/video/backlight/tdo24m.c
+++ b/drivers/video/backlight/tdo24m.c
@@ -412,25 +412,24 @@ static int tdo24m_remove(struct spi_device *spi)
412 return 0; 412 return 0;
413} 413}
414 414
415#ifdef CONFIG_PM 415#ifdef CONFIG_PM_SLEEP
416static int tdo24m_suspend(struct spi_device *spi, pm_message_t state) 416static int tdo24m_suspend(struct device *dev)
417{ 417{
418 struct tdo24m *lcd = spi_get_drvdata(spi); 418 struct tdo24m *lcd = dev_get_drvdata(dev);
419 419
420 return tdo24m_power(lcd, FB_BLANK_POWERDOWN); 420 return tdo24m_power(lcd, FB_BLANK_POWERDOWN);
421} 421}
422 422
423static int tdo24m_resume(struct spi_device *spi) 423static int tdo24m_resume(struct device *dev)
424{ 424{
425 struct tdo24m *lcd = spi_get_drvdata(spi); 425 struct tdo24m *lcd = dev_get_drvdata(dev);
426 426
427 return tdo24m_power(lcd, FB_BLANK_UNBLANK); 427 return tdo24m_power(lcd, FB_BLANK_UNBLANK);
428} 428}
429#else
430#define tdo24m_suspend NULL
431#define tdo24m_resume NULL
432#endif 429#endif
433 430
431static SIMPLE_DEV_PM_OPS(tdo24m_pm_ops, tdo24m_suspend, tdo24m_resume);
432
434/* Power down all displays on reboot, poweroff or halt */ 433/* Power down all displays on reboot, poweroff or halt */
435static void tdo24m_shutdown(struct spi_device *spi) 434static void tdo24m_shutdown(struct spi_device *spi)
436{ 435{
@@ -443,12 +442,11 @@ static struct spi_driver tdo24m_driver = {
443 .driver = { 442 .driver = {
444 .name = "tdo24m", 443 .name = "tdo24m",
445 .owner = THIS_MODULE, 444 .owner = THIS_MODULE,
445 .pm = &tdo24m_pm_ops,
446 }, 446 },
447 .probe = tdo24m_probe, 447 .probe = tdo24m_probe,
448 .remove = tdo24m_remove, 448 .remove = tdo24m_remove,
449 .shutdown = tdo24m_shutdown, 449 .shutdown = tdo24m_shutdown,
450 .suspend = tdo24m_suspend,
451 .resume = tdo24m_resume,
452}; 450};
453 451
454module_spi_driver(tdo24m_driver); 452module_spi_driver(tdo24m_driver);
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 2326fa810c59..9df66ac68b34 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -134,28 +134,27 @@ static int tosa_bl_remove(struct i2c_client *client)
134 return 0; 134 return 0;
135} 135}
136 136
137#ifdef CONFIG_PM 137#ifdef CONFIG_PM_SLEEP
138static int tosa_bl_suspend(struct i2c_client *client, pm_message_t pm) 138static int tosa_bl_suspend(struct device *dev)
139{ 139{
140 struct tosa_bl_data *data = i2c_get_clientdata(client); 140 struct tosa_bl_data *data = dev_get_drvdata(dev);
141 141
142 tosa_bl_set_backlight(data, 0); 142 tosa_bl_set_backlight(data, 0);
143 143
144 return 0; 144 return 0;
145} 145}
146 146
147static int tosa_bl_resume(struct i2c_client *client) 147static int tosa_bl_resume(struct device *dev)
148{ 148{
149 struct tosa_bl_data *data = i2c_get_clientdata(client); 149 struct tosa_bl_data *data = dev_get_drvdata(dev);
150 150
151 backlight_update_status(data->bl); 151 backlight_update_status(data->bl);
152 return 0; 152 return 0;
153} 153}
154#else
155#define tosa_bl_suspend NULL
156#define tosa_bl_resume NULL
157#endif 154#endif
158 155
156static SIMPLE_DEV_PM_OPS(tosa_bl_pm_ops, tosa_bl_suspend, tosa_bl_resume);
157
159static const struct i2c_device_id tosa_bl_id[] = { 158static const struct i2c_device_id tosa_bl_id[] = {
160 { "tosa-bl", 0 }, 159 { "tosa-bl", 0 },
161 { }, 160 { },
@@ -165,11 +164,10 @@ static struct i2c_driver tosa_bl_driver = {
165 .driver = { 164 .driver = {
166 .name = "tosa-bl", 165 .name = "tosa-bl",
167 .owner = THIS_MODULE, 166 .owner = THIS_MODULE,
167 .pm = &tosa_bl_pm_ops,
168 }, 168 },
169 .probe = tosa_bl_probe, 169 .probe = tosa_bl_probe,
170 .remove = tosa_bl_remove, 170 .remove = tosa_bl_remove,
171 .suspend = tosa_bl_suspend,
172 .resume = tosa_bl_resume,
173 .id_table = tosa_bl_id, 171 .id_table = tosa_bl_id,
174}; 172};
175 173
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
index 666fe2593ea4..bf081573e5b5 100644
--- a/drivers/video/backlight/tosa_lcd.c
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -240,19 +240,19 @@ static int tosa_lcd_remove(struct spi_device *spi)
240 return 0; 240 return 0;
241} 241}
242 242
243#ifdef CONFIG_PM 243#ifdef CONFIG_PM_SLEEP
244static int tosa_lcd_suspend(struct spi_device *spi, pm_message_t state) 244static int tosa_lcd_suspend(struct device *dev)
245{ 245{
246 struct tosa_lcd_data *data = spi_get_drvdata(spi); 246 struct tosa_lcd_data *data = dev_get_drvdata(dev);
247 247
248 tosa_lcd_tg_off(data); 248 tosa_lcd_tg_off(data);
249 249
250 return 0; 250 return 0;
251} 251}
252 252
253static int tosa_lcd_resume(struct spi_device *spi) 253static int tosa_lcd_resume(struct device *dev)
254{ 254{
255 struct tosa_lcd_data *data = spi_get_drvdata(spi); 255 struct tosa_lcd_data *data = dev_get_drvdata(dev);
256 256
257 tosa_lcd_tg_init(data); 257 tosa_lcd_tg_init(data);
258 if (POWER_IS_ON(data->lcd_power)) 258 if (POWER_IS_ON(data->lcd_power))
@@ -262,20 +262,18 @@ static int tosa_lcd_resume(struct spi_device *spi)
262 262
263 return 0; 263 return 0;
264} 264}
265#else
266#define tosa_lcd_suspend NULL
267#define tosa_lcd_resume NULL
268#endif 265#endif
269 266
267static SIMPLE_DEV_PM_OPS(tosa_lcd_pm_ops, tosa_lcd_suspend, tosa_lcd_resume);
268
270static struct spi_driver tosa_lcd_driver = { 269static struct spi_driver tosa_lcd_driver = {
271 .driver = { 270 .driver = {
272 .name = "tosa-lcd", 271 .name = "tosa-lcd",
273 .owner = THIS_MODULE, 272 .owner = THIS_MODULE,
273 .pm = &tosa_lcd_pm_ops,
274 }, 274 },
275 .probe = tosa_lcd_probe, 275 .probe = tosa_lcd_probe,
276 .remove = tosa_lcd_remove, 276 .remove = tosa_lcd_remove,
277 .suspend = tosa_lcd_suspend,
278 .resume = tosa_lcd_resume,
279}; 277};
280 278
281module_spi_driver(tosa_lcd_driver); 279module_spi_driver(tosa_lcd_driver);
diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
index 70881633b45a..05782312aeb3 100644
--- a/drivers/video/backlight/tps65217_bl.c
+++ b/drivers/video/backlight/tps65217_bl.c
@@ -245,6 +245,18 @@ tps65217_bl_parse_dt(struct platform_device *pdev)
245 } 245 }
246 } 246 }
247 247
248 if (!of_property_read_u32(node, "default-brightness", &val)) {
249 if (val < 0 ||
250 val > 100) {
251 dev_err(&pdev->dev,
252 "invalid 'default-brightness' value in the device tree\n");
253 err = ERR_PTR(-EINVAL);
254 goto err;
255 }
256
257 pdata->dft_brightness = val;
258 }
259
248 of_node_put(node); 260 of_node_put(node);
249 261
250 return pdata; 262 return pdata;
@@ -311,7 +323,8 @@ static int tps65217_bl_probe(struct platform_device *pdev)
311 return PTR_ERR(tps65217_bl->bl); 323 return PTR_ERR(tps65217_bl->bl);
312 } 324 }
313 325
314 tps65217_bl->bl->props.brightness = 0; 326 tps65217_bl->bl->props.brightness = pdata->dft_brightness;
327 backlight_update_status(tps65217_bl->bl);
315 platform_set_drvdata(pdev, tps65217_bl); 328 platform_set_drvdata(pdev, tps65217_bl);
316 329
317 return 0; 330 return 0;
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
index 84d582f591dc..d538947a67d3 100644
--- a/drivers/video/backlight/vgg2432a4.c
+++ b/drivers/video/backlight/vgg2432a4.c
@@ -205,18 +205,15 @@ static int vgg2432a4_lcd_init(struct ili9320 *lcd,
205 return ret; 205 return ret;
206} 206}
207 207
208#ifdef CONFIG_PM 208#ifdef CONFIG_PM_SLEEP
209static int vgg2432a4_suspend(struct spi_device *spi, pm_message_t state) 209static int vgg2432a4_suspend(struct device *dev)
210{ 210{
211 return ili9320_suspend(spi_get_drvdata(spi), state); 211 return ili9320_suspend(dev_get_drvdata(dev));
212} 212}
213static int vgg2432a4_resume(struct spi_device *spi) 213static int vgg2432a4_resume(struct device *dev)
214{ 214{
215 return ili9320_resume(spi_get_drvdata(spi)); 215 return ili9320_resume(dev_get_drvdata(dev));
216} 216}
217#else
218#define vgg2432a4_suspend NULL
219#define vgg2432a4_resume NULL
220#endif 217#endif
221 218
222static struct ili9320_client vgg2432a4_client = { 219static struct ili9320_client vgg2432a4_client = {
@@ -249,16 +246,17 @@ static void vgg2432a4_shutdown(struct spi_device *spi)
249 ili9320_shutdown(spi_get_drvdata(spi)); 246 ili9320_shutdown(spi_get_drvdata(spi));
250} 247}
251 248
249static SIMPLE_DEV_PM_OPS(vgg2432a4_pm_ops, vgg2432a4_suspend, vgg2432a4_resume);
250
252static struct spi_driver vgg2432a4_driver = { 251static struct spi_driver vgg2432a4_driver = {
253 .driver = { 252 .driver = {
254 .name = "VGG2432A4", 253 .name = "VGG2432A4",
255 .owner = THIS_MODULE, 254 .owner = THIS_MODULE,
255 .pm = &vgg2432a4_pm_ops,
256 }, 256 },
257 .probe = vgg2432a4_probe, 257 .probe = vgg2432a4_probe,
258 .remove = vgg2432a4_remove, 258 .remove = vgg2432a4_remove,
259 .shutdown = vgg2432a4_shutdown, 259 .shutdown = vgg2432a4_shutdown,
260 .suspend = vgg2432a4_suspend,
261 .resume = vgg2432a4_resume,
262}; 260};
263 261
264module_spi_driver(vgg2432a4_driver); 262module_spi_driver(vgg2432a4_driver);
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
index 8d411a3c9966..a54f7f7d763b 100644
--- a/drivers/video/bfin_adv7393fb.c
+++ b/drivers/video/bfin_adv7393fb.c
@@ -333,29 +333,23 @@ static int proc_output(char *buf)
333 return p - buf; 333 return p - buf;
334} 334}
335 335
336static int 336static ssize_t
337adv7393_read_proc(char *page, char **start, off_t off, 337adv7393_read_proc(struct file *file, char __user *buf,
338 int count, int *eof, void *data) 338 size_t size, loff_t *ppos)
339{ 339{
340 int len; 340 static const char message[] = "Usage:\n"
341 341 "echo 0x[REG][Value] > adv7393\n"
342 len = proc_output(page); 342 "example: echo 0x1234 >adv7393\n"
343 if (len <= off + count) 343 "writes 0x34 into Register 0x12\n";
344 *eof = 1; 344 return simple_read_from_buffer(buf, size, ppos, message,
345 *start = page + off; 345 sizeof(message));
346 len -= off;
347 if (len > count)
348 len = count;
349 if (len < 0)
350 len = 0;
351 return len;
352} 346}
353 347
354static int 348static ssize_t
355adv7393_write_proc(struct file *file, const char __user * buffer, 349adv7393_write_proc(struct file *file, const char __user * buffer,
356 size_t count, void *data) 350 size_t count, loff_t *ppos)
357{ 351{
358 struct adv7393fb_device *fbdev = data; 352 struct adv7393fb_device *fbdev = PDE_DATA(file_inode(file));
359 unsigned int val; 353 unsigned int val;
360 int ret; 354 int ret;
361 355
@@ -368,6 +362,12 @@ adv7393_write_proc(struct file *file, const char __user * buffer,
368 return count; 362 return count;
369} 363}
370 364
365static const struct file_operations fops = {
366 .read = adv7393_read_proc,
367 .write = adv7393_write_proc,
368 .llseek = default_llseek,
369};
370
371static int bfin_adv7393_fb_probe(struct i2c_client *client, 371static int bfin_adv7393_fb_probe(struct i2c_client *client,
372 const struct i2c_device_id *id) 372 const struct i2c_device_id *id)
373{ 373{
@@ -506,17 +506,12 @@ static int bfin_adv7393_fb_probe(struct i2c_client *client,
506 fbdev->info.node, fbdev->info.fix.id); 506 fbdev->info.node, fbdev->info.fix.id);
507 dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem); 507 dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem);
508 508
509 entry = create_proc_entry("driver/adv7393", 0, NULL); 509 entry = proc_create_data("driver/adv7393", 0, NULL, &fops, fbdev);
510 if (!entry) { 510 if (!entry) {
511 dev_err(&client->dev, "unable to create /proc entry\n"); 511 dev_err(&client->dev, "unable to create /proc entry\n");
512 ret = -EFAULT; 512 ret = -EFAULT;
513 goto free_fb; 513 goto free_fb;
514 } 514 }
515
516 entry->read_proc = adv7393_read_proc;
517 entry->write_proc = adv7393_write_proc;
518 entry->data = fbdev;
519
520 return 0; 515 return 0;
521 516
522free_fb: 517free_fb:
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index c3dbbe6e3acf..97db3ba8f237 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -53,12 +53,6 @@
53#ifdef CONFIG_AMIGA 53#ifdef CONFIG_AMIGA
54#include <asm/amigahw.h> 54#include <asm/amigahw.h>
55#endif 55#endif
56#ifdef CONFIG_PPC_PREP
57#include <asm/machdep.h>
58#define isPReP machine_is(prep)
59#else
60#define isPReP 0
61#endif
62 56
63#include <video/vga.h> 57#include <video/vga.h>
64#include <video/cirrus.h> 58#include <video/cirrus.h>
@@ -557,30 +551,18 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
557 break; 551 break;
558 552
559 case 16: 553 case 16:
560 if (isPReP) { 554 var->red.offset = 11;
561 var->red.offset = 2; 555 var->green.offset = 5;
562 var->green.offset = -3; 556 var->blue.offset = 0;
563 var->blue.offset = 8;
564 } else {
565 var->red.offset = 11;
566 var->green.offset = 5;
567 var->blue.offset = 0;
568 }
569 var->red.length = 5; 557 var->red.length = 5;
570 var->green.length = 6; 558 var->green.length = 6;
571 var->blue.length = 5; 559 var->blue.length = 5;
572 break; 560 break;
573 561
574 case 24: 562 case 24:
575 if (isPReP) { 563 var->red.offset = 16;
576 var->red.offset = 0; 564 var->green.offset = 8;
577 var->green.offset = 8; 565 var->blue.offset = 0;
578 var->blue.offset = 16;
579 } else {
580 var->red.offset = 16;
581 var->green.offset = 8;
582 var->blue.offset = 0;
583 }
584 var->red.length = 8; 566 var->red.length = 8;
585 var->green.length = 8; 567 var->green.length = 8;
586 var->blue.length = 8; 568 var->blue.length = 8;
@@ -1874,17 +1856,6 @@ static void cirrusfb_imageblit(struct fb_info *info,
1874 } 1856 }
1875} 1857}
1876 1858
1877#ifdef CONFIG_PPC_PREP
1878#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
1879#define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
1880static void get_prep_addrs(unsigned long *display, unsigned long *registers)
1881{
1882 *display = PREP_VIDEO_BASE;
1883 *registers = (unsigned long) PREP_IO_BASE;
1884}
1885
1886#endif /* CONFIG_PPC_PREP */
1887
1888#ifdef CONFIG_PCI 1859#ifdef CONFIG_PCI
1889static int release_io_ports; 1860static int release_io_ports;
1890 1861
@@ -2139,21 +2110,12 @@ static int cirrusfb_pci_register(struct pci_dev *pdev,
2139 dev_dbg(info->device, " base address 1 is 0x%Lx\n", 2110 dev_dbg(info->device, " base address 1 is 0x%Lx\n",
2140 (unsigned long long)pdev->resource[1].start); 2111 (unsigned long long)pdev->resource[1].start);
2141 2112
2142 if (isPReP) { 2113 dev_dbg(info->device,
2143 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000); 2114 "Attempt to get PCI info for Cirrus Graphics Card\n");
2144#ifdef CONFIG_PPC_PREP 2115 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2145 get_prep_addrs(&board_addr, &info->fix.mmio_start); 2116 /* FIXME: this forces VGA. alternatives? */
2146#endif 2117 cinfo->regbase = NULL;
2147 /* PReP dies if we ioremap the IO registers, but it works w/out... */ 2118 cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000);
2148 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2149 } else {
2150 dev_dbg(info->device,
2151 "Attempt to get PCI info for Cirrus Graphics Card\n");
2152 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2153 /* FIXME: this forces VGA. alternatives? */
2154 cinfo->regbase = NULL;
2155 cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000);
2156 }
2157 2119
2158 dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n", 2120 dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n",
2159 board_addr, info->fix.mmio_start); 2121 board_addr, info->fix.mmio_start);
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 3cd675927826..a92783e480e6 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -1228,6 +1228,8 @@ static void fbcon_deinit(struct vc_data *vc)
1228finished: 1228finished:
1229 1229
1230 fbcon_free_font(p, free_font); 1230 fbcon_free_font(p, free_font);
1231 if (free_font)
1232 vc->vc_font.data = NULL;
1231 1233
1232 if (!con_is_bound(&fb_con)) 1234 if (!con_is_bound(&fb_con))
1233 fbcon_exit(); 1235 fbcon_exit();
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index 6a737827beb1..a93670ef7f89 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -27,7 +27,7 @@ static void cw_update_attr(u8 *dst, u8 *src, int attribute,
27{ 27{
28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; 28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
29 int width = (vc->vc_font.height + 7) >> 3; 29 int width = (vc->vc_font.height + 7) >> 3;
30 u8 c, t = 0, msk = ~(0xff >> offset); 30 u8 c, msk = ~(0xff >> offset);
31 31
32 for (i = 0; i < vc->vc_font.width; i++) { 32 for (i = 0; i < vc->vc_font.width; i++) {
33 for (j = 0; j < width; j++) { 33 for (j = 0; j < width; j++) {
@@ -40,7 +40,6 @@ static void cw_update_attr(u8 *dst, u8 *src, int attribute,
40 c = ~c; 40 c = ~c;
41 src++; 41 src++;
42 *dst++ = c; 42 *dst++ = c;
43 t = c;
44 } 43 }
45 } 44 }
46} 45}
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 0c189b32a4c5..67b77b40aa7f 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -285,36 +285,26 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
285static int controlfb_mmap(struct fb_info *info, 285static int controlfb_mmap(struct fb_info *info,
286 struct vm_area_struct *vma) 286 struct vm_area_struct *vma)
287{ 287{
288 unsigned long off, start; 288 unsigned long mmio_pgoff;
289 u32 len; 289 unsigned long start;
290 290 u32 len;
291 off = vma->vm_pgoff << PAGE_SHIFT; 291
292 292 start = info->fix.smem_start;
293 /* frame buffer memory */ 293 len = info->fix.smem_len;
294 start = info->fix.smem_start; 294 mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
295 len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.smem_len); 295 if (vma->vm_pgoff >= mmio_pgoff) {
296 if (off >= len) { 296 if (info->var.accel_flags)
297 /* memory mapped io */ 297 return -EINVAL;
298 off -= len; 298 vma->vm_pgoff -= mmio_pgoff;
299 if (info->var.accel_flags) 299 start = info->fix.mmio_start;
300 return -EINVAL; 300 len = info->fix.mmio_len;
301 start = info->fix.mmio_start; 301 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
302 len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.mmio_len); 302 } else {
303 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 303 /* framebuffer */
304 } else { 304 vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot);
305 /* framebuffer */ 305 }
306 vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot); 306
307 } 307 return vm_iomap_memory(vma, start, len);
308 start &= PAGE_MASK;
309 if ((vma->vm_end - vma->vm_start + off) > len)
310 return -EINVAL;
311 off += start;
312 vma->vm_pgoff = off >> PAGE_SHIFT;
313 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
314 vma->vm_end - vma->vm_start, vma->vm_page_prot))
315 return -EAGAIN;
316
317 return 0;
318} 308}
319 309
320static int controlfb_blank(int blank_mode, struct fb_info *info) 310static int controlfb_blank(int blank_mode, struct fb_info *info)
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
index e06cd5d90c97..ee1ee5401544 100644
--- a/drivers/video/ep93xx-fb.c
+++ b/drivers/video/ep93xx-fb.c
@@ -419,7 +419,7 @@ static struct fb_ops ep93xxfb_ops = {
419 .fb_mmap = ep93xxfb_mmap, 419 .fb_mmap = ep93xxfb_mmap,
420}; 420};
421 421
422static int __init ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info) 422static int ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info)
423{ 423{
424 int i, fb_size = 0; 424 int i, fb_size = 0;
425 425
@@ -441,7 +441,7 @@ static int __init ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info)
441 return fb_size; 441 return fb_size;
442} 442}
443 443
444static int __init ep93xxfb_alloc_videomem(struct fb_info *info) 444static int ep93xxfb_alloc_videomem(struct fb_info *info)
445{ 445{
446 struct ep93xx_fbi *fbi = info->par; 446 struct ep93xx_fbi *fbi = info->par;
447 char __iomem *virt_addr; 447 char __iomem *virt_addr;
@@ -627,19 +627,7 @@ static struct platform_driver ep93xxfb_driver = {
627 .owner = THIS_MODULE, 627 .owner = THIS_MODULE,
628 }, 628 },
629}; 629};
630 630module_platform_driver(ep93xxfb_driver);
631static int ep93xxfb_init(void)
632{
633 return platform_driver_register(&ep93xxfb_driver);
634}
635
636static void __exit ep93xxfb_exit(void)
637{
638 platform_driver_unregister(&ep93xxfb_driver);
639}
640
641module_init(ep93xxfb_init);
642module_exit(ep93xxfb_exit);
643 631
644MODULE_DESCRIPTION("EP93XX Framebuffer Driver"); 632MODULE_DESCRIPTION("EP93XX Framebuffer Driver");
645MODULE_ALIAS("platform:ep93xx-fb"); 633MODULE_ALIAS("platform:ep93xx-fb");
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index de9d4da0e3da..12bbede3b091 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -976,14 +976,14 @@ static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
976 } 976 }
977 977
978 if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) { 978 if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
979 dev_err(dp->dev, "faild to get reg for dptx-phy\n"); 979 dev_err(dp->dev, "failed to get reg for dptx-phy\n");
980 ret = -EINVAL; 980 ret = -EINVAL;
981 goto err; 981 goto err;
982 } 982 }
983 983
984 if (of_property_read_u32(dp_phy_node, "samsung,enable-mask", 984 if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
985 &dp->enable_mask)) { 985 &dp->enable_mask)) {
986 dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n"); 986 dev_err(dp->dev, "failed to get enable-mask for dptx-phy\n");
987 ret = -EINVAL; 987 ret = -EINVAL;
988 goto err; 988 goto err;
989 } 989 }
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
index fac7df6d1aba..32e540600f99 100644
--- a/drivers/video/exynos/exynos_mipi_dsi.c
+++ b/drivers/video/exynos/exynos_mipi_dsi.c
@@ -32,11 +32,10 @@
32#include <linux/notifier.h> 32#include <linux/notifier.h>
33#include <linux/regulator/consumer.h> 33#include <linux/regulator/consumer.h>
34#include <linux/pm_runtime.h> 34#include <linux/pm_runtime.h>
35#include <linux/err.h>
35 36
36#include <video/exynos_mipi_dsim.h> 37#include <video/exynos_mipi_dsim.h>
37 38
38#include <plat/fb.h>
39
40#include "exynos_mipi_dsi_common.h" 39#include "exynos_mipi_dsi_common.h"
41#include "exynos_mipi_dsi_lowlevel.h" 40#include "exynos_mipi_dsi_lowlevel.h"
42 41
@@ -384,10 +383,9 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
384 383
385 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 384 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
386 385
387 dsim->reg_base = devm_request_and_ioremap(&pdev->dev, res); 386 dsim->reg_base = devm_ioremap_resource(&pdev->dev, res);
388 if (!dsim->reg_base) { 387 if (IS_ERR(dsim->reg_base)) {
389 dev_err(&pdev->dev, "failed to remap io region\n"); 388 ret = PTR_ERR(dsim->reg_base);
390 ret = -ENOMEM;
391 goto error; 389 goto error;
392 } 390 }
393 391
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c
index c70cb8926df6..520fc9bd887b 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_common.c
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
@@ -31,8 +31,6 @@
31#include <video/mipi_display.h> 31#include <video/mipi_display.h>
32#include <video/exynos_mipi_dsim.h> 32#include <video/exynos_mipi_dsim.h>
33 33
34#include <mach/map.h>
35
36#include "exynos_mipi_dsi_regs.h" 34#include "exynos_mipi_dsi_regs.h"
37#include "exynos_mipi_dsi_lowlevel.h" 35#include "exynos_mipi_dsi_lowlevel.h"
38#include "exynos_mipi_dsi_common.h" 36#include "exynos_mipi_dsi_common.h"
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
index 95cb99a1fe2d..15c5abd408dc 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
+++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
@@ -26,8 +26,6 @@
26 26
27#include <video/exynos_mipi_dsim.h> 27#include <video/exynos_mipi_dsim.h>
28 28
29#include <mach/map.h>
30
31#include "exynos_mipi_dsi_regs.h" 29#include "exynos_mipi_dsi_regs.h"
32 30
33void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim) 31void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim)
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
index 7d106f1f4906..27fc956166fa 100644
--- a/drivers/video/fb-puv3.c
+++ b/drivers/video/fb-puv3.c
@@ -640,21 +640,9 @@ static int unifb_pan_display(struct fb_var_screeninfo *var,
640int unifb_mmap(struct fb_info *info, 640int unifb_mmap(struct fb_info *info,
641 struct vm_area_struct *vma) 641 struct vm_area_struct *vma)
642{ 642{
643 unsigned long size = vma->vm_end - vma->vm_start;
644 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
645 unsigned long pos = info->fix.smem_start + offset;
646
647 if (offset + size > info->fix.smem_len)
648 return -EINVAL;
649
650 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 643 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
651 644
652 if (io_remap_pfn_range(vma, vma->vm_start, pos >> PAGE_SHIFT, size, 645 return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
653 vma->vm_page_prot))
654 return -EAGAIN;
655
656 /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
657 return 0;
658} 646}
659 647
660static struct fb_ops unifb_ops = { 648static struct fb_ops unifb_ops = {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 7c254084b6a0..098bfc64cfb9 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1373,15 +1373,12 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
1373{ 1373{
1374 struct fb_info *info = file_fb_info(file); 1374 struct fb_info *info = file_fb_info(file);
1375 struct fb_ops *fb; 1375 struct fb_ops *fb;
1376 unsigned long off; 1376 unsigned long mmio_pgoff;
1377 unsigned long start; 1377 unsigned long start;
1378 u32 len; 1378 u32 len;
1379 1379
1380 if (!info) 1380 if (!info)
1381 return -ENODEV; 1381 return -ENODEV;
1382 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1383 return -EINVAL;
1384 off = vma->vm_pgoff << PAGE_SHIFT;
1385 fb = info->fbops; 1382 fb = info->fbops;
1386 if (!fb) 1383 if (!fb)
1387 return -ENODEV; 1384 return -ENODEV;
@@ -1393,32 +1390,29 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
1393 return res; 1390 return res;
1394 } 1391 }
1395 1392
1396 /* frame buffer memory */ 1393 /*
1394 * Ugh. This can be either the frame buffer mapping, or
1395 * if pgoff points past it, the mmio mapping.
1396 */
1397 start = info->fix.smem_start; 1397 start = info->fix.smem_start;
1398 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); 1398 len = info->fix.smem_len;
1399 if (off >= len) { 1399 mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
1400 /* memory mapped io */ 1400 if (vma->vm_pgoff >= mmio_pgoff) {
1401 off -= len;
1402 if (info->var.accel_flags) { 1401 if (info->var.accel_flags) {
1403 mutex_unlock(&info->mm_lock); 1402 mutex_unlock(&info->mm_lock);
1404 return -EINVAL; 1403 return -EINVAL;
1405 } 1404 }
1405
1406 vma->vm_pgoff -= mmio_pgoff;
1406 start = info->fix.mmio_start; 1407 start = info->fix.mmio_start;
1407 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); 1408 len = info->fix.mmio_len;
1408 } 1409 }
1409 mutex_unlock(&info->mm_lock); 1410 mutex_unlock(&info->mm_lock);
1410 start &= PAGE_MASK; 1411
1411 if ((vma->vm_end - vma->vm_start + off) > len)
1412 return -EINVAL;
1413 off += start;
1414 vma->vm_pgoff = off >> PAGE_SHIFT;
1415 /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by io_remap_pfn_range()*/
1416 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 1412 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
1417 fb_pgprotect(file, vma, off); 1413 fb_pgprotect(file, vma, start);
1418 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, 1414
1419 vma->vm_end - vma->vm_start, vma->vm_page_prot)) 1415 return vm_iomap_memory(vma, start, len);
1420 return -EAGAIN;
1421 return 0;
1422} 1416}
1423 1417
1424static int 1418static int
@@ -1645,6 +1639,11 @@ static int do_register_framebuffer(struct fb_info *fb_info)
1645 if (!fb_info->modelist.prev || !fb_info->modelist.next) 1639 if (!fb_info->modelist.prev || !fb_info->modelist.next)
1646 INIT_LIST_HEAD(&fb_info->modelist); 1640 INIT_LIST_HEAD(&fb_info->modelist);
1647 1641
1642 if (fb_info->skip_vt_switch)
1643 pm_vt_switch_required(fb_info->dev, false);
1644 else
1645 pm_vt_switch_required(fb_info->dev, true);
1646
1648 fb_var_to_videomode(&mode, &fb_info->var); 1647 fb_var_to_videomode(&mode, &fb_info->var);
1649 fb_add_videomode(&mode, &fb_info->modelist); 1648 fb_add_videomode(&mode, &fb_info->modelist);
1650 registered_fb[i] = fb_info; 1649 registered_fb[i] = fb_info;
@@ -1679,6 +1678,8 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
1679 if (ret) 1678 if (ret)
1680 return -EINVAL; 1679 return -EINVAL;
1681 1680
1681 pm_vt_switch_unregister(fb_info->dev);
1682
1682 unlink_framebuffer(fb_info); 1683 unlink_framebuffer(fb_info);
1683 if (fb_info->pixmap.addr && 1684 if (fb_info->pixmap.addr &&
1684 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) 1685 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 7f6709991a5c..6103fa6fb54f 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -1376,7 +1376,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
1376 return err; 1376 return err;
1377} 1377}
1378 1378
1379#if IS_ENABLED(CONFIG_VIDEOMODE) 1379#ifdef CONFIG_VIDEOMODE_HELPERS
1380int fb_videomode_from_videomode(const struct videomode *vm, 1380int fb_videomode_from_videomode(const struct videomode *vm,
1381 struct fb_videomode *fbmode) 1381 struct fb_videomode *fbmode)
1382{ 1382{
@@ -1398,13 +1398,13 @@ int fb_videomode_from_videomode(const struct videomode *vm,
1398 1398
1399 fbmode->sync = 0; 1399 fbmode->sync = 0;
1400 fbmode->vmode = 0; 1400 fbmode->vmode = 0;
1401 if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH) 1401 if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
1402 fbmode->sync |= FB_SYNC_HOR_HIGH_ACT; 1402 fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
1403 if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH) 1403 if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
1404 fbmode->sync |= FB_SYNC_VERT_HIGH_ACT; 1404 fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
1405 if (vm->data_flags & DISPLAY_FLAGS_INTERLACED) 1405 if (vm->flags & DISPLAY_FLAGS_INTERLACED)
1406 fbmode->vmode |= FB_VMODE_INTERLACED; 1406 fbmode->vmode |= FB_VMODE_INTERLACED;
1407 if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN) 1407 if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
1408 fbmode->vmode |= FB_VMODE_DOUBLE; 1408 fbmode->vmode |= FB_VMODE_DOUBLE;
1409 fbmode->flag = 0; 1409 fbmode->flag = 0;
1410 1410
@@ -1424,9 +1424,8 @@ int fb_videomode_from_videomode(const struct videomode *vm,
1424 return 0; 1424 return 0;
1425} 1425}
1426EXPORT_SYMBOL_GPL(fb_videomode_from_videomode); 1426EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
1427#endif
1428 1427
1429#if IS_ENABLED(CONFIG_OF_VIDEOMODE) 1428#ifdef CONFIG_OF
1430static inline void dump_fb_videomode(const struct fb_videomode *m) 1429static inline void dump_fb_videomode(const struct fb_videomode *m)
1431{ 1430{
1432 pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n", 1431 pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
@@ -1465,7 +1464,8 @@ int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb,
1465 return 0; 1464 return 0;
1466} 1465}
1467EXPORT_SYMBOL_GPL(of_get_fb_videomode); 1466EXPORT_SYMBOL_GPL(of_get_fb_videomode);
1468#endif 1467#endif /* CONFIG_OF */
1468#endif /* CONFIG_VIDEOMODE_HELPERS */
1469 1469
1470#else 1470#else
1471int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) 1471int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 41fbd9453c5f..6c278056fc60 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -375,7 +375,10 @@ struct fsl_diu_data {
375 struct diu_ad dummy_ad __aligned(8); 375 struct diu_ad dummy_ad __aligned(8);
376 struct diu_ad ad[NUM_AOIS] __aligned(8); 376 struct diu_ad ad[NUM_AOIS] __aligned(8);
377 u8 gamma[256 * 3] __aligned(32); 377 u8 gamma[256 * 3] __aligned(32);
378 u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32); 378 /* It's easier to parse the cursor data as little-endian */
379 __le16 cursor[MAX_CURS * MAX_CURS] __aligned(32);
380 /* Blank cursor data -- used to hide the cursor */
381 __le16 blank_cursor[MAX_CURS * MAX_CURS] __aligned(32);
379 uint8_t edid_data[EDID_LENGTH]; 382 uint8_t edid_data[EDID_LENGTH];
380 bool has_edid; 383 bool has_edid;
381} __aligned(32); 384} __aligned(32);
@@ -824,7 +827,6 @@ static void update_lcdc(struct fb_info *info)
824 /* Program DIU registers */ 827 /* Program DIU registers */
825 828
826 out_be32(&hw->gamma, DMA_ADDR(data, gamma)); 829 out_be32(&hw->gamma, DMA_ADDR(data, gamma));
827 out_be32(&hw->cursor, DMA_ADDR(data, cursor));
828 830
829 out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */ 831 out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
830 out_be32(&hw->disp_size, (var->yres << 16) | var->xres); 832 out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
@@ -968,6 +970,156 @@ static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel)
968} 970}
969 971
970/* 972/*
973 * Copies a cursor image from user space to the proper place in driver
974 * memory so that the hardware can display the cursor image.
975 *
976 * Cursor data is represented as a sequence of 'width' bits packed into bytes.
977 * That is, the first 8 bits are in the first byte, the second 8 bits in the
978 * second byte, and so on. Therefore, the each row of the cursor is (width +
979 * 7) / 8 bytes of 'data'
980 *
981 * The DIU only supports cursors up to 32x32 (MAX_CURS). We reject cursors
982 * larger than this, so we already know that 'width' <= 32. Therefore, we can
983 * simplify our code by using a 32-bit big-endian integer ("line") to read in
984 * a single line of pixels, and only look at the top 'width' bits of that
985 * integer.
986 *
987 * This could result in an unaligned 32-bit read. For example, if the cursor
988 * is 24x24, then the first three bytes of 'image' contain the pixel data for
989 * the top line of the cursor. We do a 32-bit read of 'image', but we look
990 * only at the top 24 bits. Then we increment 'image' by 3 bytes. The next
991 * read is unaligned. The only problem is that we might read past the end of
992 * 'image' by 1-3 bytes, but that should not cause any problems.
993 */
994static void fsl_diu_load_cursor_image(struct fb_info *info,
995 const void *image, uint16_t bg, uint16_t fg,
996 unsigned int width, unsigned int height)
997{
998 struct mfb_info *mfbi = info->par;
999 struct fsl_diu_data *data = mfbi->parent;
1000 __le16 *cursor = data->cursor;
1001 __le16 _fg = cpu_to_le16(fg);
1002 __le16 _bg = cpu_to_le16(bg);
1003 unsigned int h, w;
1004
1005 for (h = 0; h < height; h++) {
1006 uint32_t mask = 1 << 31;
1007 uint32_t line = be32_to_cpup(image);
1008
1009 for (w = 0; w < width; w++) {
1010 cursor[w] = (line & mask) ? _fg : _bg;
1011 mask >>= 1;
1012 }
1013
1014 cursor += MAX_CURS;
1015 image += DIV_ROUND_UP(width, 8);
1016 }
1017}
1018
1019/*
1020 * Set a hardware cursor. The image data for the cursor is passed via the
1021 * fb_cursor object.
1022 */
1023static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
1024{
1025 struct mfb_info *mfbi = info->par;
1026 struct fsl_diu_data *data = mfbi->parent;
1027 struct diu __iomem *hw = data->diu_reg;
1028
1029 if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
1030 return -EINVAL;
1031
1032 /* The cursor size has changed */
1033 if (cursor->set & FB_CUR_SETSIZE) {
1034 /*
1035 * The DIU cursor is a fixed size, so when we get this
1036 * message, instead of resizing the cursor, we just clear
1037 * all the image data, in expectation of new data. However,
1038 * in tests this control does not appear to be normally
1039 * called.
1040 */
1041 memset(data->cursor, 0, sizeof(data->cursor));
1042 }
1043
1044 /* The cursor position has changed (cursor->image.dx|dy) */
1045 if (cursor->set & FB_CUR_SETPOS) {
1046 uint32_t xx, yy;
1047
1048 yy = (cursor->image.dy - info->var.yoffset) & 0x7ff;
1049 xx = (cursor->image.dx - info->var.xoffset) & 0x7ff;
1050
1051 out_be32(&hw->curs_pos, yy << 16 | xx);
1052 }
1053
1054 /*
1055 * FB_CUR_SETIMAGE - the cursor image has changed
1056 * FB_CUR_SETCMAP - the cursor colors has changed
1057 * FB_CUR_SETSHAPE - the cursor bitmask has changed
1058 */
1059 if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
1060 unsigned int image_size =
1061 DIV_ROUND_UP(cursor->image.width, 8) * cursor->image.height;
1062 unsigned int image_words =
1063 DIV_ROUND_UP(image_size, sizeof(uint32_t));
1064 unsigned int bg_idx = cursor->image.bg_color;
1065 unsigned int fg_idx = cursor->image.fg_color;
1066 uint8_t buffer[image_size];
1067 uint32_t *image, *source, *mask;
1068 uint16_t fg, bg;
1069 unsigned int i;
1070
1071 if (info->state != FBINFO_STATE_RUNNING)
1072 return 0;
1073
1074 /*
1075 * Determine the size of the cursor image data. Normally,
1076 * it's 8x16.
1077 */
1078 image_size = DIV_ROUND_UP(cursor->image.width, 8) *
1079 cursor->image.height;
1080
1081 bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
1082 ((info->cmap.green[bg_idx] & 0xf8) << 2) |
1083 ((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
1084 1 << 15;
1085
1086 fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
1087 ((info->cmap.green[fg_idx] & 0xf8) << 2) |
1088 ((info->cmap.blue[fg_idx] & 0xf8) >> 3) |
1089 1 << 15;
1090
1091 /* Use 32-bit operations on the data to improve performance */
1092 image = (uint32_t *)buffer;
1093 source = (uint32_t *)cursor->image.data;
1094 mask = (uint32_t *)cursor->mask;
1095
1096 if (cursor->rop == ROP_XOR)
1097 for (i = 0; i < image_words; i++)
1098 image[i] = source[i] ^ mask[i];
1099 else
1100 for (i = 0; i < image_words; i++)
1101 image[i] = source[i] & mask[i];
1102
1103 fsl_diu_load_cursor_image(info, image, bg, fg,
1104 cursor->image.width, cursor->image.height);
1105 };
1106
1107 /*
1108 * Show or hide the cursor. The cursor data is always stored in the
1109 * 'cursor' memory block, and the actual cursor position is always in
1110 * the DIU's CURS_POS register. To hide the cursor, we redirect the
1111 * CURSOR register to a blank cursor. The show the cursor, we
1112 * redirect the CURSOR register to the real cursor data.
1113 */
1114 if (cursor->enable)
1115 out_be32(&hw->cursor, DMA_ADDR(data, cursor));
1116 else
1117 out_be32(&hw->cursor, DMA_ADDR(data, blank_cursor));
1118
1119 return 0;
1120}
1121
1122/*
971 * Using the fb_var_screeninfo in fb_info we set the resolution of this 1123 * Using the fb_var_screeninfo in fb_info we set the resolution of this
972 * particular framebuffer. This function alters the fb_fix_screeninfo stored 1124 * particular framebuffer. This function alters the fb_fix_screeninfo stored
973 * in fb_info. It does not alter var in fb_info since we are using that 1125 * in fb_info. It does not alter var in fb_info since we are using that
@@ -1312,6 +1464,7 @@ static struct fb_ops fsl_diu_ops = {
1312 .fb_ioctl = fsl_diu_ioctl, 1464 .fb_ioctl = fsl_diu_ioctl,
1313 .fb_open = fsl_diu_open, 1465 .fb_open = fsl_diu_open,
1314 .fb_release = fsl_diu_release, 1466 .fb_release = fsl_diu_release,
1467 .fb_cursor = fsl_diu_cursor,
1315}; 1468};
1316 1469
1317static int install_fb(struct fb_info *info) 1470static int install_fb(struct fb_info *info)
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index bda5e3941510..ceab37020fff 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -1016,7 +1016,9 @@ static int gbefb_mmap(struct fb_info *info,
1016 /* check range */ 1016 /* check range */
1017 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) 1017 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1018 return -EINVAL; 1018 return -EINVAL;
1019 if (offset + size > gbe_mem_size) 1019 if (size > gbe_mem_size)
1020 return -EINVAL;
1021 if (offset > gbe_mem_size - size)
1020 return -EINVAL; 1022 return -EINVAL;
1021 1023
1022 /* remap using the fastest write-through mode on architecture */ 1024 /* remap using the fastest write-through mode on architecture */
diff --git a/drivers/video/goldfishfb.c b/drivers/video/goldfishfb.c
index 489abb32fc04..7f6c9e6cfc6c 100644
--- a/drivers/video/goldfishfb.c
+++ b/drivers/video/goldfishfb.c
@@ -148,7 +148,7 @@ static int goldfish_fb_pan_display(struct fb_var_screeninfo *var,
148 wait_event_timeout(fb->wait, 148 wait_event_timeout(fb->wait,
149 fb->base_update_count != base_update_count, HZ / 15); 149 fb->base_update_count != base_update_count, HZ / 15);
150 if (fb->base_update_count == base_update_count) 150 if (fb->base_update_count == base_update_count)
151 pr_err("goldfish_fb_pan_display: timeout wating for base update\n"); 151 pr_err("goldfish_fb_pan_display: timeout waiting for base update\n");
152 return 0; 152 return 0;
153} 153}
154 154
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index ab23c9b79143..40178338b619 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -1,9 +1,24 @@
1/* 1/*
2 * Copyright (C) 2012 Avionic Design GmbH 2 * Copyright (C) 2012 Avionic Design GmbH
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * it under the terms of the GNU General Public License version 2 as 5 * copy of this software and associated documentation files (the "Software"),
6 * published by the Free Software Foundation. 6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
7 */ 22 */
8 23
9#include <linux/bitops.h> 24#include <linux/bitops.h>
diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c
new file mode 100644
index 000000000000..d4d2c5fe2488
--- /dev/null
+++ b/drivers/video/hyperv_fb.c
@@ -0,0 +1,829 @@
1/*
2 * Copyright (c) 2012, Microsoft Corporation.
3 *
4 * Author:
5 * Haiyang Zhang <haiyangz@microsoft.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published
9 * by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14 * NON INFRINGEMENT. See the GNU General Public License for more
15 * details.
16 */
17
18/*
19 * Hyper-V Synthetic Video Frame Buffer Driver
20 *
21 * This is the driver for the Hyper-V Synthetic Video, which supports
22 * screen resolution up to Full HD 1920x1080 with 32 bit color on Windows
23 * Server 2012, and 1600x1200 with 16 bit color on Windows Server 2008 R2
24 * or earlier.
25 *
26 * It also solves the double mouse cursor issue of the emulated video mode.
27 *
28 * The default screen resolution is 1152x864, which may be changed by a
29 * kernel parameter:
30 * video=hyperv_fb:<width>x<height>
31 * For example: video=hyperv_fb:1280x1024
32 *
33 * Portrait orientation is also supported:
34 * For example: video=hyperv_fb:864x1152
35 */
36
37#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
38
39#include <linux/module.h>
40#include <linux/kernel.h>
41#include <linux/init.h>
42#include <linux/completion.h>
43#include <linux/fb.h>
44#include <linux/pci.h>
45
46#include <linux/hyperv.h>
47
48
49/* Hyper-V Synthetic Video Protocol definitions and structures */
50#define MAX_VMBUS_PKT_SIZE 0x4000
51
52#define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major))
53#define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0)
54#define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2)
55
56#define SYNTHVID_DEPTH_WIN7 16
57#define SYNTHVID_DEPTH_WIN8 32
58
59#define SYNTHVID_FB_SIZE_WIN7 (4 * 1024 * 1024)
60#define SYNTHVID_WIDTH_MAX_WIN7 1600
61#define SYNTHVID_HEIGHT_MAX_WIN7 1200
62
63#define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024)
64
65#define PCI_VENDOR_ID_MICROSOFT 0x1414
66#define PCI_DEVICE_ID_HYPERV_VIDEO 0x5353
67
68
69enum pipe_msg_type {
70 PIPE_MSG_INVALID,
71 PIPE_MSG_DATA,
72 PIPE_MSG_MAX
73};
74
75struct pipe_msg_hdr {
76 u32 type;
77 u32 size; /* size of message after this field */
78} __packed;
79
80
81enum synthvid_msg_type {
82 SYNTHVID_ERROR = 0,
83 SYNTHVID_VERSION_REQUEST = 1,
84 SYNTHVID_VERSION_RESPONSE = 2,
85 SYNTHVID_VRAM_LOCATION = 3,
86 SYNTHVID_VRAM_LOCATION_ACK = 4,
87 SYNTHVID_SITUATION_UPDATE = 5,
88 SYNTHVID_SITUATION_UPDATE_ACK = 6,
89 SYNTHVID_POINTER_POSITION = 7,
90 SYNTHVID_POINTER_SHAPE = 8,
91 SYNTHVID_FEATURE_CHANGE = 9,
92 SYNTHVID_DIRT = 10,
93
94 SYNTHVID_MAX = 11
95};
96
97struct synthvid_msg_hdr {
98 u32 type;
99 u32 size; /* size of this header + payload after this field*/
100} __packed;
101
102
103struct synthvid_version_req {
104 u32 version;
105} __packed;
106
107struct synthvid_version_resp {
108 u32 version;
109 u8 is_accepted;
110 u8 max_video_outputs;
111} __packed;
112
113struct synthvid_vram_location {
114 u64 user_ctx;
115 u8 is_vram_gpa_specified;
116 u64 vram_gpa;
117} __packed;
118
119struct synthvid_vram_location_ack {
120 u64 user_ctx;
121} __packed;
122
123struct video_output_situation {
124 u8 active;
125 u32 vram_offset;
126 u8 depth_bits;
127 u32 width_pixels;
128 u32 height_pixels;
129 u32 pitch_bytes;
130} __packed;
131
132struct synthvid_situation_update {
133 u64 user_ctx;
134 u8 video_output_count;
135 struct video_output_situation video_output[1];
136} __packed;
137
138struct synthvid_situation_update_ack {
139 u64 user_ctx;
140} __packed;
141
142struct synthvid_pointer_position {
143 u8 is_visible;
144 u8 video_output;
145 s32 image_x;
146 s32 image_y;
147} __packed;
148
149
150#define CURSOR_MAX_X 96
151#define CURSOR_MAX_Y 96
152#define CURSOR_ARGB_PIXEL_SIZE 4
153#define CURSOR_MAX_SIZE (CURSOR_MAX_X * CURSOR_MAX_Y * CURSOR_ARGB_PIXEL_SIZE)
154#define CURSOR_COMPLETE (-1)
155
156struct synthvid_pointer_shape {
157 u8 part_idx;
158 u8 is_argb;
159 u32 width; /* CURSOR_MAX_X at most */
160 u32 height; /* CURSOR_MAX_Y at most */
161 u32 hot_x; /* hotspot relative to upper-left of pointer image */
162 u32 hot_y;
163 u8 data[4];
164} __packed;
165
166struct synthvid_feature_change {
167 u8 is_dirt_needed;
168 u8 is_ptr_pos_needed;
169 u8 is_ptr_shape_needed;
170 u8 is_situ_needed;
171} __packed;
172
173struct rect {
174 s32 x1, y1; /* top left corner */
175 s32 x2, y2; /* bottom right corner, exclusive */
176} __packed;
177
178struct synthvid_dirt {
179 u8 video_output;
180 u8 dirt_count;
181 struct rect rect[1];
182} __packed;
183
184struct synthvid_msg {
185 struct pipe_msg_hdr pipe_hdr;
186 struct synthvid_msg_hdr vid_hdr;
187 union {
188 struct synthvid_version_req ver_req;
189 struct synthvid_version_resp ver_resp;
190 struct synthvid_vram_location vram;
191 struct synthvid_vram_location_ack vram_ack;
192 struct synthvid_situation_update situ;
193 struct synthvid_situation_update_ack situ_ack;
194 struct synthvid_pointer_position ptr_pos;
195 struct synthvid_pointer_shape ptr_shape;
196 struct synthvid_feature_change feature_chg;
197 struct synthvid_dirt dirt;
198 };
199} __packed;
200
201
202
203/* FB driver definitions and structures */
204#define HVFB_WIDTH 1152 /* default screen width */
205#define HVFB_HEIGHT 864 /* default screen height */
206#define HVFB_WIDTH_MIN 640
207#define HVFB_HEIGHT_MIN 480
208
209#define RING_BUFSIZE (256 * 1024)
210#define VSP_TIMEOUT (10 * HZ)
211#define HVFB_UPDATE_DELAY (HZ / 20)
212
213struct hvfb_par {
214 struct fb_info *info;
215 bool fb_ready; /* fb device is ready */
216 struct completion wait;
217 u32 synthvid_version;
218
219 struct delayed_work dwork;
220 bool update;
221
222 u32 pseudo_palette[16];
223 u8 init_buf[MAX_VMBUS_PKT_SIZE];
224 u8 recv_buf[MAX_VMBUS_PKT_SIZE];
225};
226
227static uint screen_width = HVFB_WIDTH;
228static uint screen_height = HVFB_HEIGHT;
229static uint screen_depth;
230static uint screen_fb_size;
231
232/* Send message to Hyper-V host */
233static inline int synthvid_send(struct hv_device *hdev,
234 struct synthvid_msg *msg)
235{
236 static atomic64_t request_id = ATOMIC64_INIT(0);
237 int ret;
238
239 msg->pipe_hdr.type = PIPE_MSG_DATA;
240 msg->pipe_hdr.size = msg->vid_hdr.size;
241
242 ret = vmbus_sendpacket(hdev->channel, msg,
243 msg->vid_hdr.size + sizeof(struct pipe_msg_hdr),
244 atomic64_inc_return(&request_id),
245 VM_PKT_DATA_INBAND, 0);
246
247 if (ret)
248 pr_err("Unable to send packet via vmbus\n");
249
250 return ret;
251}
252
253
254/* Send screen resolution info to host */
255static int synthvid_send_situ(struct hv_device *hdev)
256{
257 struct fb_info *info = hv_get_drvdata(hdev);
258 struct synthvid_msg msg;
259
260 if (!info)
261 return -ENODEV;
262
263 memset(&msg, 0, sizeof(struct synthvid_msg));
264
265 msg.vid_hdr.type = SYNTHVID_SITUATION_UPDATE;
266 msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
267 sizeof(struct synthvid_situation_update);
268 msg.situ.user_ctx = 0;
269 msg.situ.video_output_count = 1;
270 msg.situ.video_output[0].active = 1;
271 msg.situ.video_output[0].vram_offset = 0;
272 msg.situ.video_output[0].depth_bits = info->var.bits_per_pixel;
273 msg.situ.video_output[0].width_pixels = info->var.xres;
274 msg.situ.video_output[0].height_pixels = info->var.yres;
275 msg.situ.video_output[0].pitch_bytes = info->fix.line_length;
276
277 synthvid_send(hdev, &msg);
278
279 return 0;
280}
281
282/* Send mouse pointer info to host */
283static int synthvid_send_ptr(struct hv_device *hdev)
284{
285 struct synthvid_msg msg;
286
287 memset(&msg, 0, sizeof(struct synthvid_msg));
288 msg.vid_hdr.type = SYNTHVID_POINTER_POSITION;
289 msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
290 sizeof(struct synthvid_pointer_position);
291 msg.ptr_pos.is_visible = 1;
292 msg.ptr_pos.video_output = 0;
293 msg.ptr_pos.image_x = 0;
294 msg.ptr_pos.image_y = 0;
295 synthvid_send(hdev, &msg);
296
297 memset(&msg, 0, sizeof(struct synthvid_msg));
298 msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE;
299 msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
300 sizeof(struct synthvid_pointer_shape);
301 msg.ptr_shape.part_idx = CURSOR_COMPLETE;
302 msg.ptr_shape.is_argb = 1;
303 msg.ptr_shape.width = 1;
304 msg.ptr_shape.height = 1;
305 msg.ptr_shape.hot_x = 0;
306 msg.ptr_shape.hot_y = 0;
307 msg.ptr_shape.data[0] = 0;
308 msg.ptr_shape.data[1] = 1;
309 msg.ptr_shape.data[2] = 1;
310 msg.ptr_shape.data[3] = 1;
311 synthvid_send(hdev, &msg);
312
313 return 0;
314}
315
316/* Send updated screen area (dirty rectangle) location to host */
317static int synthvid_update(struct fb_info *info)
318{
319 struct hv_device *hdev = device_to_hv_device(info->device);
320 struct synthvid_msg msg;
321
322 memset(&msg, 0, sizeof(struct synthvid_msg));
323
324 msg.vid_hdr.type = SYNTHVID_DIRT;
325 msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
326 sizeof(struct synthvid_dirt);
327 msg.dirt.video_output = 0;
328 msg.dirt.dirt_count = 1;
329 msg.dirt.rect[0].x1 = 0;
330 msg.dirt.rect[0].y1 = 0;
331 msg.dirt.rect[0].x2 = info->var.xres;
332 msg.dirt.rect[0].y2 = info->var.yres;
333
334 synthvid_send(hdev, &msg);
335
336 return 0;
337}
338
339
340/*
341 * Actions on received messages from host:
342 * Complete the wait event.
343 * Or, reply with screen and cursor info.
344 */
345static void synthvid_recv_sub(struct hv_device *hdev)
346{
347 struct fb_info *info = hv_get_drvdata(hdev);
348 struct hvfb_par *par;
349 struct synthvid_msg *msg;
350
351 if (!info)
352 return;
353
354 par = info->par;
355 msg = (struct synthvid_msg *)par->recv_buf;
356
357 /* Complete the wait event */
358 if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE ||
359 msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) {
360 memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE);
361 complete(&par->wait);
362 return;
363 }
364
365 /* Reply with screen and cursor info */
366 if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) {
367 if (par->fb_ready) {
368 synthvid_send_ptr(hdev);
369 synthvid_send_situ(hdev);
370 }
371
372 par->update = msg->feature_chg.is_dirt_needed;
373 if (par->update)
374 schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
375 }
376}
377
378/* Receive callback for messages from the host */
379static void synthvid_receive(void *ctx)
380{
381 struct hv_device *hdev = ctx;
382 struct fb_info *info = hv_get_drvdata(hdev);
383 struct hvfb_par *par;
384 struct synthvid_msg *recv_buf;
385 u32 bytes_recvd;
386 u64 req_id;
387 int ret;
388
389 if (!info)
390 return;
391
392 par = info->par;
393 recv_buf = (struct synthvid_msg *)par->recv_buf;
394
395 do {
396 ret = vmbus_recvpacket(hdev->channel, recv_buf,
397 MAX_VMBUS_PKT_SIZE,
398 &bytes_recvd, &req_id);
399 if (bytes_recvd > 0 &&
400 recv_buf->pipe_hdr.type == PIPE_MSG_DATA)
401 synthvid_recv_sub(hdev);
402 } while (bytes_recvd > 0 && ret == 0);
403}
404
405/* Check synthetic video protocol version with the host */
406static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver)
407{
408 struct fb_info *info = hv_get_drvdata(hdev);
409 struct hvfb_par *par = info->par;
410 struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
411 int t, ret = 0;
412
413 memset(msg, 0, sizeof(struct synthvid_msg));
414 msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST;
415 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
416 sizeof(struct synthvid_version_req);
417 msg->ver_req.version = ver;
418 synthvid_send(hdev, msg);
419
420 t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
421 if (!t) {
422 pr_err("Time out on waiting version response\n");
423 ret = -ETIMEDOUT;
424 goto out;
425 }
426 if (!msg->ver_resp.is_accepted) {
427 ret = -ENODEV;
428 goto out;
429 }
430
431 par->synthvid_version = ver;
432
433out:
434 return ret;
435}
436
437/* Connect to VSP (Virtual Service Provider) on host */
438static int synthvid_connect_vsp(struct hv_device *hdev)
439{
440 struct fb_info *info = hv_get_drvdata(hdev);
441 struct hvfb_par *par = info->par;
442 int ret;
443
444 ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE,
445 NULL, 0, synthvid_receive, hdev);
446 if (ret) {
447 pr_err("Unable to open vmbus channel\n");
448 return ret;
449 }
450
451 /* Negotiate the protocol version with host */
452 if (vmbus_proto_version == VERSION_WS2008 ||
453 vmbus_proto_version == VERSION_WIN7)
454 ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7);
455 else
456 ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8);
457
458 if (ret) {
459 pr_err("Synthetic video device version not accepted\n");
460 goto error;
461 }
462
463 if (par->synthvid_version == SYNTHVID_VERSION_WIN7) {
464 screen_depth = SYNTHVID_DEPTH_WIN7;
465 screen_fb_size = SYNTHVID_FB_SIZE_WIN7;
466 } else {
467 screen_depth = SYNTHVID_DEPTH_WIN8;
468 screen_fb_size = SYNTHVID_FB_SIZE_WIN8;
469 }
470
471 return 0;
472
473error:
474 vmbus_close(hdev->channel);
475 return ret;
476}
477
478/* Send VRAM and Situation messages to the host */
479static int synthvid_send_config(struct hv_device *hdev)
480{
481 struct fb_info *info = hv_get_drvdata(hdev);
482 struct hvfb_par *par = info->par;
483 struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
484 int t, ret = 0;
485
486 /* Send VRAM location */
487 memset(msg, 0, sizeof(struct synthvid_msg));
488 msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION;
489 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
490 sizeof(struct synthvid_vram_location);
491 msg->vram.user_ctx = msg->vram.vram_gpa = info->fix.smem_start;
492 msg->vram.is_vram_gpa_specified = 1;
493 synthvid_send(hdev, msg);
494
495 t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
496 if (!t) {
497 pr_err("Time out on waiting vram location ack\n");
498 ret = -ETIMEDOUT;
499 goto out;
500 }
501 if (msg->vram_ack.user_ctx != info->fix.smem_start) {
502 pr_err("Unable to set VRAM location\n");
503 ret = -ENODEV;
504 goto out;
505 }
506
507 /* Send pointer and situation update */
508 synthvid_send_ptr(hdev);
509 synthvid_send_situ(hdev);
510
511out:
512 return ret;
513}
514
515
516/*
517 * Delayed work callback:
518 * It is called at HVFB_UPDATE_DELAY or longer time interval to process
519 * screen updates. It is re-scheduled if further update is necessary.
520 */
521static void hvfb_update_work(struct work_struct *w)
522{
523 struct hvfb_par *par = container_of(w, struct hvfb_par, dwork.work);
524 struct fb_info *info = par->info;
525
526 if (par->fb_ready)
527 synthvid_update(info);
528
529 if (par->update)
530 schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
531}
532
533
534/* Framebuffer operation handlers */
535
536static int hvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
537{
538 if (var->xres < HVFB_WIDTH_MIN || var->yres < HVFB_HEIGHT_MIN ||
539 var->xres > screen_width || var->yres > screen_height ||
540 var->bits_per_pixel != screen_depth)
541 return -EINVAL;
542
543 var->xres_virtual = var->xres;
544 var->yres_virtual = var->yres;
545
546 return 0;
547}
548
549static int hvfb_set_par(struct fb_info *info)
550{
551 struct hv_device *hdev = device_to_hv_device(info->device);
552
553 return synthvid_send_situ(hdev);
554}
555
556
557static inline u32 chan_to_field(u32 chan, struct fb_bitfield *bf)
558{
559 return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
560}
561
562static int hvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
563 unsigned blue, unsigned transp, struct fb_info *info)
564{
565 u32 *pal = info->pseudo_palette;
566
567 if (regno > 15)
568 return -EINVAL;
569
570 pal[regno] = chan_to_field(red, &info->var.red)
571 | chan_to_field(green, &info->var.green)
572 | chan_to_field(blue, &info->var.blue)
573 | chan_to_field(transp, &info->var.transp);
574
575 return 0;
576}
577
578
579static struct fb_ops hvfb_ops = {
580 .owner = THIS_MODULE,
581 .fb_check_var = hvfb_check_var,
582 .fb_set_par = hvfb_set_par,
583 .fb_setcolreg = hvfb_setcolreg,
584 .fb_fillrect = cfb_fillrect,
585 .fb_copyarea = cfb_copyarea,
586 .fb_imageblit = cfb_imageblit,
587};
588
589
590/* Get options from kernel paramenter "video=" */
591static void hvfb_get_option(struct fb_info *info)
592{
593 struct hvfb_par *par = info->par;
594 char *opt = NULL, *p;
595 uint x = 0, y = 0;
596
597 if (fb_get_options(KBUILD_MODNAME, &opt) || !opt || !*opt)
598 return;
599
600 p = strsep(&opt, "x");
601 if (!*p || kstrtouint(p, 0, &x) ||
602 !opt || !*opt || kstrtouint(opt, 0, &y)) {
603 pr_err("Screen option is invalid: skipped\n");
604 return;
605 }
606
607 if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN ||
608 (par->synthvid_version == SYNTHVID_VERSION_WIN8 &&
609 x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) ||
610 (par->synthvid_version == SYNTHVID_VERSION_WIN7 &&
611 (x > SYNTHVID_WIDTH_MAX_WIN7 || y > SYNTHVID_HEIGHT_MAX_WIN7))) {
612 pr_err("Screen resolution option is out of range: skipped\n");
613 return;
614 }
615
616 screen_width = x;
617 screen_height = y;
618 return;
619}
620
621
622/* Get framebuffer memory from Hyper-V video pci space */
623static int hvfb_getmem(struct fb_info *info)
624{
625 struct pci_dev *pdev;
626 ulong fb_phys;
627 void __iomem *fb_virt;
628
629 pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
630 PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
631 if (!pdev) {
632 pr_err("Unable to find PCI Hyper-V video\n");
633 return -ENODEV;
634 }
635
636 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
637 pci_resource_len(pdev, 0) < screen_fb_size)
638 goto err1;
639
640 fb_phys = pci_resource_end(pdev, 0) - screen_fb_size + 1;
641 if (!request_mem_region(fb_phys, screen_fb_size, KBUILD_MODNAME))
642 goto err1;
643
644 fb_virt = ioremap(fb_phys, screen_fb_size);
645 if (!fb_virt)
646 goto err2;
647
648 info->apertures = alloc_apertures(1);
649 if (!info->apertures)
650 goto err3;
651
652 info->apertures->ranges[0].base = pci_resource_start(pdev, 0);
653 info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
654 info->fix.smem_start = fb_phys;
655 info->fix.smem_len = screen_fb_size;
656 info->screen_base = fb_virt;
657 info->screen_size = screen_fb_size;
658
659 pci_dev_put(pdev);
660 return 0;
661
662err3:
663 iounmap(fb_virt);
664err2:
665 release_mem_region(fb_phys, screen_fb_size);
666err1:
667 pci_dev_put(pdev);
668 return -ENOMEM;
669}
670
671/* Release the framebuffer */
672static void hvfb_putmem(struct fb_info *info)
673{
674 iounmap(info->screen_base);
675 release_mem_region(info->fix.smem_start, screen_fb_size);
676}
677
678
679static int hvfb_probe(struct hv_device *hdev,
680 const struct hv_vmbus_device_id *dev_id)
681{
682 struct fb_info *info;
683 struct hvfb_par *par;
684 int ret;
685
686 info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device);
687 if (!info) {
688 pr_err("No memory for framebuffer info\n");
689 return -ENOMEM;
690 }
691
692 par = info->par;
693 par->info = info;
694 par->fb_ready = false;
695 init_completion(&par->wait);
696 INIT_DELAYED_WORK(&par->dwork, hvfb_update_work);
697
698 /* Connect to VSP */
699 hv_set_drvdata(hdev, info);
700 ret = synthvid_connect_vsp(hdev);
701 if (ret) {
702 pr_err("Unable to connect to VSP\n");
703 goto error1;
704 }
705
706 ret = hvfb_getmem(info);
707 if (ret) {
708 pr_err("No memory for framebuffer\n");
709 goto error2;
710 }
711
712 hvfb_get_option(info);
713 pr_info("Screen resolution: %dx%d, Color depth: %d\n",
714 screen_width, screen_height, screen_depth);
715
716
717 /* Set up fb_info */
718 info->flags = FBINFO_DEFAULT;
719
720 info->var.xres_virtual = info->var.xres = screen_width;
721 info->var.yres_virtual = info->var.yres = screen_height;
722 info->var.bits_per_pixel = screen_depth;
723
724 if (info->var.bits_per_pixel == 16) {
725 info->var.red = (struct fb_bitfield){11, 5, 0};
726 info->var.green = (struct fb_bitfield){5, 6, 0};
727 info->var.blue = (struct fb_bitfield){0, 5, 0};
728 info->var.transp = (struct fb_bitfield){0, 0, 0};
729 } else {
730 info->var.red = (struct fb_bitfield){16, 8, 0};
731 info->var.green = (struct fb_bitfield){8, 8, 0};
732 info->var.blue = (struct fb_bitfield){0, 8, 0};
733 info->var.transp = (struct fb_bitfield){24, 8, 0};
734 }
735
736 info->var.activate = FB_ACTIVATE_NOW;
737 info->var.height = -1;
738 info->var.width = -1;
739 info->var.vmode = FB_VMODE_NONINTERLACED;
740
741 strcpy(info->fix.id, KBUILD_MODNAME);
742 info->fix.type = FB_TYPE_PACKED_PIXELS;
743 info->fix.visual = FB_VISUAL_TRUECOLOR;
744 info->fix.line_length = screen_width * screen_depth / 8;
745 info->fix.accel = FB_ACCEL_NONE;
746
747 info->fbops = &hvfb_ops;
748 info->pseudo_palette = par->pseudo_palette;
749
750 /* Send config to host */
751 ret = synthvid_send_config(hdev);
752 if (ret)
753 goto error;
754
755 ret = register_framebuffer(info);
756 if (ret) {
757 pr_err("Unable to register framebuffer\n");
758 goto error;
759 }
760
761 par->fb_ready = true;
762
763 return 0;
764
765error:
766 hvfb_putmem(info);
767error2:
768 vmbus_close(hdev->channel);
769error1:
770 cancel_delayed_work_sync(&par->dwork);
771 hv_set_drvdata(hdev, NULL);
772 framebuffer_release(info);
773 return ret;
774}
775
776
777static int hvfb_remove(struct hv_device *hdev)
778{
779 struct fb_info *info = hv_get_drvdata(hdev);
780 struct hvfb_par *par = info->par;
781
782 par->update = false;
783 par->fb_ready = false;
784
785 unregister_framebuffer(info);
786 cancel_delayed_work_sync(&par->dwork);
787
788 vmbus_close(hdev->channel);
789 hv_set_drvdata(hdev, NULL);
790
791 hvfb_putmem(info);
792 framebuffer_release(info);
793
794 return 0;
795}
796
797
798static const struct hv_vmbus_device_id id_table[] = {
799 /* Synthetic Video Device GUID */
800 {HV_SYNTHVID_GUID},
801 {}
802};
803
804MODULE_DEVICE_TABLE(vmbus, id_table);
805
806static struct hv_driver hvfb_drv = {
807 .name = KBUILD_MODNAME,
808 .id_table = id_table,
809 .probe = hvfb_probe,
810 .remove = hvfb_remove,
811};
812
813
814static int __init hvfb_drv_init(void)
815{
816 return vmbus_driver_register(&hvfb_drv);
817}
818
819static void __exit hvfb_drv_exit(void)
820{
821 vmbus_driver_unregister(&hvfb_drv);
822}
823
824module_init(hvfb_drv_init);
825module_exit(hvfb_drv_exit);
826
827MODULE_LICENSE("GPL");
828MODULE_VERSION(HV_DRV_VERSION);
829MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver");
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 217678e0b983..fd2897455696 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -137,8 +137,20 @@ static int* get_ctrl_ptr(struct maven_data* md, int idx) {
137 137
138static int maven_get_reg(struct i2c_client* c, char reg) { 138static int maven_get_reg(struct i2c_client* c, char reg) {
139 char dst; 139 char dst;
140 struct i2c_msg msgs[] = {{ c->addr, I2C_M_REV_DIR_ADDR, sizeof(reg), &reg }, 140 struct i2c_msg msgs[] = {
141 { c->addr, I2C_M_RD | I2C_M_NOSTART, sizeof(dst), &dst }}; 141 {
142 .addr = c->addr,
143 .flags = I2C_M_REV_DIR_ADDR,
144 .len = sizeof(reg),
145 .buf = &reg
146 },
147 {
148 .addr = c->addr,
149 .flags = I2C_M_RD | I2C_M_NOSTART,
150 .len = sizeof(dst),
151 .buf = &dst
152 }
153 };
142 s32 err; 154 s32 err;
143 155
144 err = i2c_transfer(c->adapter, msgs, 2); 156 err = i2c_transfer(c->adapter, msgs, 2);
diff --git a/drivers/video/mmp/core.c b/drivers/video/mmp/core.c
index 9ed83419038b..84de2632857a 100644
--- a/drivers/video/mmp/core.c
+++ b/drivers/video/mmp/core.c
@@ -252,7 +252,5 @@ void mmp_unregister_path(struct mmp_path *path)
252 252
253 kfree(path); 253 kfree(path);
254 mutex_unlock(&disp_lock); 254 mutex_unlock(&disp_lock);
255
256 dev_info(path->dev, "de-register %s\n", path->name);
257} 255}
258EXPORT_SYMBOL_GPL(mmp_unregister_path); 256EXPORT_SYMBOL_GPL(mmp_unregister_path);
diff --git a/drivers/video/mmp/hw/mmp_ctrl.h b/drivers/video/mmp/hw/mmp_ctrl.h
index 6408d8ef3abb..edd2002b0e99 100644
--- a/drivers/video/mmp/hw/mmp_ctrl.h
+++ b/drivers/video/mmp/hw/mmp_ctrl.h
@@ -961,56 +961,7 @@ struct lcd_regs {
961 LCD_TVG_CUTVLN : PN2_LCD_GRA_CUTVLN) : LCD_GRA_CUTVLN) 961 LCD_TVG_CUTVLN : PN2_LCD_GRA_CUTVLN) : LCD_GRA_CUTVLN)
962 962
963/* 963/*
964 * defined Video Memory Color format for DMA control 0 register 964 * defined for Configure Dumb Mode
965 * DMA0 bit[23:20]
966 */
967#define VMODE_RGB565 0x0
968#define VMODE_RGB1555 0x1
969#define VMODE_RGB888PACKED 0x2
970#define VMODE_RGB888UNPACKED 0x3
971#define VMODE_RGBA888 0x4
972#define VMODE_YUV422PACKED 0x5
973#define VMODE_YUV422PLANAR 0x6
974#define VMODE_YUV420PLANAR 0x7
975#define VMODE_SMPNCMD 0x8
976#define VMODE_PALETTE4BIT 0x9
977#define VMODE_PALETTE8BIT 0xa
978#define VMODE_RESERVED 0xb
979
980/*
981 * defined Graphic Memory Color format for DMA control 0 register
982 * DMA0 bit[19:16]
983 */
984#define GMODE_RGB565 0x0
985#define GMODE_RGB1555 0x1
986#define GMODE_RGB888PACKED 0x2
987#define GMODE_RGB888UNPACKED 0x3
988#define GMODE_RGBA888 0x4
989#define GMODE_YUV422PACKED 0x5
990#define GMODE_YUV422PLANAR 0x6
991#define GMODE_YUV420PLANAR 0x7
992#define GMODE_SMPNCMD 0x8
993#define GMODE_PALETTE4BIT 0x9
994#define GMODE_PALETTE8BIT 0xa
995#define GMODE_RESERVED 0xb
996
997/*
998 * define for DMA control 1 register
999 */
1000#define DMA1_FRAME_TRIG 31 /* bit location */
1001#define DMA1_VSYNC_MODE 28
1002#define DMA1_VSYNC_INV 27
1003#define DMA1_CKEY 24
1004#define DMA1_CARRY 23
1005#define DMA1_LNBUF_ENA 22
1006#define DMA1_GATED_ENA 21
1007#define DMA1_PWRDN_ENA 20
1008#define DMA1_DSCALE 18
1009#define DMA1_ALPHA_MODE 16
1010#define DMA1_ALPHA 08
1011#define DMA1_PXLCMD 00
1012
1013/*
1014 * defined for Configure Dumb Mode 965 * defined for Configure Dumb Mode
1015 * DUMB LCD Panel bit[31:28] 966 * DUMB LCD Panel bit[31:28]
1016 */ 967 */
@@ -1050,18 +1001,6 @@ struct lcd_regs {
1050#define CFG_CYC_BURST_LEN16 (1<<4) 1001#define CFG_CYC_BURST_LEN16 (1<<4)
1051#define CFG_CYC_BURST_LEN8 (0<<4) 1002#define CFG_CYC_BURST_LEN8 (0<<4)
1052 1003
1053/*
1054 * defined Dumb Panel Clock Divider register
1055 * SCLK_Source bit[31]
1056 */
1057 /* 0: PLL clock select*/
1058#define AXI_BUS_SEL 0x80000000
1059#define CCD_CLK_SEL 0x40000000
1060#define DCON_CLK_SEL 0x20000000
1061#define ENA_CLK_INT_DIV CONFIG_FB_DOVE_CLCD_SCLK_DIV
1062#define IDLE_CLK_INT_DIV 0x1 /* idle Integer Divider */
1063#define DIS_CLK_INT_DIV 0x0 /* Disable Integer Divider */
1064
1065/* SRAM ID */ 1004/* SRAM ID */
1066#define SRAMID_GAMMA_YR 0x0 1005#define SRAMID_GAMMA_YR 0x0
1067#define SRAMID_GAMMA_UG 0x1 1006#define SRAMID_GAMMA_UG 0x1
@@ -1471,422 +1410,6 @@ struct dsi_regs {
1471#define LVDS_FREQ_OFFSET_MODE_CK_DIV4_OUT (0x1 << 1) 1410#define LVDS_FREQ_OFFSET_MODE_CK_DIV4_OUT (0x1 << 1)
1472#define LVDS_FREQ_OFFSET_MODE_EN (0x1 << 0) 1411#define LVDS_FREQ_OFFSET_MODE_EN (0x1 << 0)
1473 1412
1474/* VDMA */
1475struct vdma_ch_regs {
1476#define VDMA_DC_SADDR_1 0x320
1477#define VDMA_DC_SADDR_2 0x3A0
1478#define VDMA_DC_SZ_1 0x324
1479#define VDMA_DC_SZ_2 0x3A4
1480#define VDMA_CTRL_1 0x328
1481#define VDMA_CTRL_2 0x3A8
1482#define VDMA_SRC_SZ_1 0x32C
1483#define VDMA_SRC_SZ_2 0x3AC
1484#define VDMA_SA_1 0x330
1485#define VDMA_SA_2 0x3B0
1486#define VDMA_DA_1 0x334
1487#define VDMA_DA_2 0x3B4
1488#define VDMA_SZ_1 0x338
1489#define VDMA_SZ_2 0x3B8
1490 u32 dc_saddr;
1491 u32 dc_size;
1492 u32 ctrl;
1493 u32 src_size;
1494 u32 src_addr;
1495 u32 dst_addr;
1496 u32 dst_size;
1497#define VDMA_PITCH_1 0x33C
1498#define VDMA_PITCH_2 0x3BC
1499#define VDMA_ROT_CTRL_1 0x340
1500#define VDMA_ROT_CTRL_2 0x3C0
1501#define VDMA_RAM_CTRL0_1 0x344
1502#define VDMA_RAM_CTRL0_2 0x3C4
1503#define VDMA_RAM_CTRL1_1 0x348
1504#define VDMA_RAM_CTRL1_2 0x3C8
1505 u32 pitch;
1506 u32 rot_ctrl;
1507 u32 ram_ctrl0;
1508 u32 ram_ctrl1;
1509
1510};
1511struct vdma_regs {
1512#define VDMA_ARBR_CTRL 0x300
1513#define VDMA_IRQR 0x304
1514#define VDMA_IRQM 0x308
1515#define VDMA_IRQS 0x30C
1516#define VDMA_MDMA_ARBR_CTRL 0x310
1517 u32 arbr_ctr;
1518 u32 irq_raw;
1519 u32 irq_mask;
1520 u32 irq_status;
1521 u32 mdma_arbr_ctrl;
1522 u32 reserved[3];
1523
1524 struct vdma_ch_regs ch1;
1525 u32 reserved2[21];
1526 struct vdma_ch_regs ch2;
1527};
1528
1529/* CMU */
1530#define CMU_PIP_DE_H_CFG 0x0008
1531#define CMU_PRI1_H_CFG 0x000C
1532#define CMU_PRI2_H_CFG 0x0010
1533#define CMU_ACE_MAIN_DE1_H_CFG 0x0014
1534#define CMU_ACE_MAIN_DE2_H_CFG 0x0018
1535#define CMU_ACE_PIP_DE1_H_CFG 0x001C
1536#define CMU_ACE_PIP_DE2_H_CFG 0x0020
1537#define CMU_PIP_DE_V_CFG 0x0024
1538#define CMU_PRI_V_CFG 0x0028
1539#define CMU_ACE_MAIN_DE_V_CFG 0x002C
1540#define CMU_ACE_PIP_DE_V_CFG 0x0030
1541#define CMU_BAR_0_CFG 0x0034
1542#define CMU_BAR_1_CFG 0x0038
1543#define CMU_BAR_2_CFG 0x003C
1544#define CMU_BAR_3_CFG 0x0040
1545#define CMU_BAR_4_CFG 0x0044
1546#define CMU_BAR_5_CFG 0x0048
1547#define CMU_BAR_6_CFG 0x004C
1548#define CMU_BAR_7_CFG 0x0050
1549#define CMU_BAR_8_CFG 0x0054
1550#define CMU_BAR_9_CFG 0x0058
1551#define CMU_BAR_10_CFG 0x005C
1552#define CMU_BAR_11_CFG 0x0060
1553#define CMU_BAR_12_CFG 0x0064
1554#define CMU_BAR_13_CFG 0x0068
1555#define CMU_BAR_14_CFG 0x006C
1556#define CMU_BAR_15_CFG 0x0070
1557#define CMU_BAR_CTRL 0x0074
1558#define PATTERN_TOTAL 0x0078
1559#define PATTERN_ACTIVE 0x007C
1560#define PATTERN_FRONT_PORCH 0x0080
1561#define PATTERN_BACK_PORCH 0x0084
1562#define CMU_CLK_CTRL 0x0088
1563
1564#define CMU_ICSC_M_C0_L 0x0900
1565#define CMU_ICSC_M_C0_H 0x0901
1566#define CMU_ICSC_M_C1_L 0x0902
1567#define CMU_ICSC_M_C1_H 0x0903
1568#define CMU_ICSC_M_C2_L 0x0904
1569#define CMU_ICSC_M_C2_H 0x0905
1570#define CMU_ICSC_M_C3_L 0x0906
1571#define CMU_ICSC_M_C3_H 0x0907
1572#define CMU_ICSC_M_C4_L 0x0908
1573#define CMU_ICSC_M_C4_H 0x0909
1574#define CMU_ICSC_M_C5_L 0x090A
1575#define CMU_ICSC_M_C5_H 0x090B
1576#define CMU_ICSC_M_C6_L 0x090C
1577#define CMU_ICSC_M_C6_H 0x090D
1578#define CMU_ICSC_M_C7_L 0x090E
1579#define CMU_ICSC_M_C7_H 0x090F
1580#define CMU_ICSC_M_C8_L 0x0910
1581#define CMU_ICSC_M_C8_H 0x0911
1582#define CMU_ICSC_M_O1_0 0x0914
1583#define CMU_ICSC_M_O1_1 0x0915
1584#define CMU_ICSC_M_O1_2 0x0916
1585#define CMU_ICSC_M_O2_0 0x0918
1586#define CMU_ICSC_M_O2_1 0x0919
1587#define CMU_ICSC_M_O2_2 0x091A
1588#define CMU_ICSC_M_O3_0 0x091C
1589#define CMU_ICSC_M_O3_1 0x091D
1590#define CMU_ICSC_M_O3_2 0x091E
1591#define CMU_ICSC_P_C0_L 0x0920
1592#define CMU_ICSC_P_C0_H 0x0921
1593#define CMU_ICSC_P_C1_L 0x0922
1594#define CMU_ICSC_P_C1_H 0x0923
1595#define CMU_ICSC_P_C2_L 0x0924
1596#define CMU_ICSC_P_C2_H 0x0925
1597#define CMU_ICSC_P_C3_L 0x0926
1598#define CMU_ICSC_P_C3_H 0x0927
1599#define CMU_ICSC_P_C4_L 0x0928
1600#define CMU_ICSC_P_C4_H 0x0929
1601#define CMU_ICSC_P_C5_L 0x092A
1602#define CMU_ICSC_P_C5_H 0x092B
1603#define CMU_ICSC_P_C6_L 0x092C
1604#define CMU_ICSC_P_C6_H 0x092D
1605#define CMU_ICSC_P_C7_L 0x092E
1606#define CMU_ICSC_P_C7_H 0x092F
1607#define CMU_ICSC_P_C8_L 0x0930
1608#define CMU_ICSC_P_C8_H 0x0931
1609#define CMU_ICSC_P_O1_0 0x0934
1610#define CMU_ICSC_P_O1_1 0x0935
1611#define CMU_ICSC_P_O1_2 0x0936
1612#define CMU_ICSC_P_O2_0 0x0938
1613#define CMU_ICSC_P_O2_1 0x0939
1614#define CMU_ICSC_P_O2_2 0x093A
1615#define CMU_ICSC_P_O3_0 0x093C
1616#define CMU_ICSC_P_O3_1 0x093D
1617#define CMU_ICSC_P_O3_2 0x093E
1618#define CMU_BR_M_EN 0x0940
1619#define CMU_BR_M_TH1_L 0x0942
1620#define CMU_BR_M_TH1_H 0x0943
1621#define CMU_BR_M_TH2_L 0x0944
1622#define CMU_BR_M_TH2_H 0x0945
1623#define CMU_ACE_M_EN 0x0950
1624#define CMU_ACE_M_WFG1 0x0951
1625#define CMU_ACE_M_WFG2 0x0952
1626#define CMU_ACE_M_WFG3 0x0953
1627#define CMU_ACE_M_TH0 0x0954
1628#define CMU_ACE_M_TH1 0x0955
1629#define CMU_ACE_M_TH2 0x0956
1630#define CMU_ACE_M_TH3 0x0957
1631#define CMU_ACE_M_TH4 0x0958
1632#define CMU_ACE_M_TH5 0x0959
1633#define CMU_ACE_M_OP0_L 0x095A
1634#define CMU_ACE_M_OP0_H 0x095B
1635#define CMU_ACE_M_OP5_L 0x095C
1636#define CMU_ACE_M_OP5_H 0x095D
1637#define CMU_ACE_M_GB2 0x095E
1638#define CMU_ACE_M_GB3 0x095F
1639#define CMU_ACE_M_MS1 0x0960
1640#define CMU_ACE_M_MS2 0x0961
1641#define CMU_ACE_M_MS3 0x0962
1642#define CMU_BR_P_EN 0x0970
1643#define CMU_BR_P_TH1_L 0x0972
1644#define CMU_BR_P_TH1_H 0x0973
1645#define CMU_BR_P_TH2_L 0x0974
1646#define CMU_BR_P_TH2_H 0x0975
1647#define CMU_ACE_P_EN 0x0980
1648#define CMU_ACE_P_WFG1 0x0981
1649#define CMU_ACE_P_WFG2 0x0982
1650#define CMU_ACE_P_WFG3 0x0983
1651#define CMU_ACE_P_TH0 0x0984
1652#define CMU_ACE_P_TH1 0x0985
1653#define CMU_ACE_P_TH2 0x0986
1654#define CMU_ACE_P_TH3 0x0987
1655#define CMU_ACE_P_TH4 0x0988
1656#define CMU_ACE_P_TH5 0x0989
1657#define CMU_ACE_P_OP0_L 0x098A
1658#define CMU_ACE_P_OP0_H 0x098B
1659#define CMU_ACE_P_OP5_L 0x098C
1660#define CMU_ACE_P_OP5_H 0x098D
1661#define CMU_ACE_P_GB2 0x098E
1662#define CMU_ACE_P_GB3 0x098F
1663#define CMU_ACE_P_MS1 0x0990
1664#define CMU_ACE_P_MS2 0x0991
1665#define CMU_ACE_P_MS3 0x0992
1666#define CMU_FTDC_M_EN 0x09A0
1667#define CMU_FTDC_P_EN 0x09A1
1668#define CMU_FTDC_INLOW_L 0x09A2
1669#define CMU_FTDC_INLOW_H 0x09A3
1670#define CMU_FTDC_INHIGH_L 0x09A4
1671#define CMU_FTDC_INHIGH_H 0x09A5
1672#define CMU_FTDC_OUTLOW_L 0x09A6
1673#define CMU_FTDC_OUTLOW_H 0x09A7
1674#define CMU_FTDC_OUTHIGH_L 0x09A8
1675#define CMU_FTDC_OUTHIGH_H 0x09A9
1676#define CMU_FTDC_YLOW 0x09AA
1677#define CMU_FTDC_YHIGH 0x09AB
1678#define CMU_FTDC_CH1 0x09AC
1679#define CMU_FTDC_CH2_L 0x09AE
1680#define CMU_FTDC_CH2_H 0x09AF
1681#define CMU_FTDC_CH3_L 0x09B0
1682#define CMU_FTDC_CH3_H 0x09B1
1683#define CMU_FTDC_1_C00_6 0x09B2
1684#define CMU_FTDC_1_C01_6 0x09B8
1685#define CMU_FTDC_1_C11_6 0x09BE
1686#define CMU_FTDC_1_C10_6 0x09C4
1687#define CMU_FTDC_1_OFF00_6 0x09CA
1688#define CMU_FTDC_1_OFF10_6 0x09D0
1689#define CMU_HS_M_EN 0x0A00
1690#define CMU_HS_M_AX1_L 0x0A02
1691#define CMU_HS_M_AX1_H 0x0A03
1692#define CMU_HS_M_AX2_L 0x0A04
1693#define CMU_HS_M_AX2_H 0x0A05
1694#define CMU_HS_M_AX3_L 0x0A06
1695#define CMU_HS_M_AX3_H 0x0A07
1696#define CMU_HS_M_AX4_L 0x0A08
1697#define CMU_HS_M_AX4_H 0x0A09
1698#define CMU_HS_M_AX5_L 0x0A0A
1699#define CMU_HS_M_AX5_H 0x0A0B
1700#define CMU_HS_M_AX6_L 0x0A0C
1701#define CMU_HS_M_AX6_H 0x0A0D
1702#define CMU_HS_M_AX7_L 0x0A0E
1703#define CMU_HS_M_AX7_H 0x0A0F
1704#define CMU_HS_M_AX8_L 0x0A10
1705#define CMU_HS_M_AX8_H 0x0A11
1706#define CMU_HS_M_AX9_L 0x0A12
1707#define CMU_HS_M_AX9_H 0x0A13
1708#define CMU_HS_M_AX10_L 0x0A14
1709#define CMU_HS_M_AX10_H 0x0A15
1710#define CMU_HS_M_AX11_L 0x0A16
1711#define CMU_HS_M_AX11_H 0x0A17
1712#define CMU_HS_M_AX12_L 0x0A18
1713#define CMU_HS_M_AX12_H 0x0A19
1714#define CMU_HS_M_AX13_L 0x0A1A
1715#define CMU_HS_M_AX13_H 0x0A1B
1716#define CMU_HS_M_AX14_L 0x0A1C
1717#define CMU_HS_M_AX14_H 0x0A1D
1718#define CMU_HS_M_H1_H14 0x0A1E
1719#define CMU_HS_M_S1_S14 0x0A2C
1720#define CMU_HS_M_GL 0x0A3A
1721#define CMU_HS_M_MAXSAT_RGB_Y_L 0x0A3C
1722#define CMU_HS_M_MAXSAT_RGB_Y_H 0x0A3D
1723#define CMU_HS_M_MAXSAT_RCR_L 0x0A3E
1724#define CMU_HS_M_MAXSAT_RCR_H 0x0A3F
1725#define CMU_HS_M_MAXSAT_RCB_L 0x0A40
1726#define CMU_HS_M_MAXSAT_RCB_H 0x0A41
1727#define CMU_HS_M_MAXSAT_GCR_L 0x0A42
1728#define CMU_HS_M_MAXSAT_GCR_H 0x0A43
1729#define CMU_HS_M_MAXSAT_GCB_L 0x0A44
1730#define CMU_HS_M_MAXSAT_GCB_H 0x0A45
1731#define CMU_HS_M_MAXSAT_BCR_L 0x0A46
1732#define CMU_HS_M_MAXSAT_BCR_H 0x0A47
1733#define CMU_HS_M_MAXSAT_BCB_L 0x0A48
1734#define CMU_HS_M_MAXSAT_BCB_H 0x0A49
1735#define CMU_HS_M_ROFF_L 0x0A4A
1736#define CMU_HS_M_ROFF_H 0x0A4B
1737#define CMU_HS_M_GOFF_L 0x0A4C
1738#define CMU_HS_M_GOFF_H 0x0A4D
1739#define CMU_HS_M_BOFF_L 0x0A4E
1740#define CMU_HS_M_BOFF_H 0x0A4F
1741#define CMU_HS_P_EN 0x0A50
1742#define CMU_HS_P_AX1_L 0x0A52
1743#define CMU_HS_P_AX1_H 0x0A53
1744#define CMU_HS_P_AX2_L 0x0A54
1745#define CMU_HS_P_AX2_H 0x0A55
1746#define CMU_HS_P_AX3_L 0x0A56
1747#define CMU_HS_P_AX3_H 0x0A57
1748#define CMU_HS_P_AX4_L 0x0A58
1749#define CMU_HS_P_AX4_H 0x0A59
1750#define CMU_HS_P_AX5_L 0x0A5A
1751#define CMU_HS_P_AX5_H 0x0A5B
1752#define CMU_HS_P_AX6_L 0x0A5C
1753#define CMU_HS_P_AX6_H 0x0A5D
1754#define CMU_HS_P_AX7_L 0x0A5E
1755#define CMU_HS_P_AX7_H 0x0A5F
1756#define CMU_HS_P_AX8_L 0x0A60
1757#define CMU_HS_P_AX8_H 0x0A61
1758#define CMU_HS_P_AX9_L 0x0A62
1759#define CMU_HS_P_AX9_H 0x0A63
1760#define CMU_HS_P_AX10_L 0x0A64
1761#define CMU_HS_P_AX10_H 0x0A65
1762#define CMU_HS_P_AX11_L 0x0A66
1763#define CMU_HS_P_AX11_H 0x0A67
1764#define CMU_HS_P_AX12_L 0x0A68
1765#define CMU_HS_P_AX12_H 0x0A69
1766#define CMU_HS_P_AX13_L 0x0A6A
1767#define CMU_HS_P_AX13_H 0x0A6B
1768#define CMU_HS_P_AX14_L 0x0A6C
1769#define CMU_HS_P_AX14_H 0x0A6D
1770#define CMU_HS_P_H1_H14 0x0A6E
1771#define CMU_HS_P_S1_S14 0x0A7C
1772#define CMU_HS_P_GL 0x0A8A
1773#define CMU_HS_P_MAXSAT_RGB_Y_L 0x0A8C
1774#define CMU_HS_P_MAXSAT_RGB_Y_H 0x0A8D
1775#define CMU_HS_P_MAXSAT_RCR_L 0x0A8E
1776#define CMU_HS_P_MAXSAT_RCR_H 0x0A8F
1777#define CMU_HS_P_MAXSAT_RCB_L 0x0A90
1778#define CMU_HS_P_MAXSAT_RCB_H 0x0A91
1779#define CMU_HS_P_MAXSAT_GCR_L 0x0A92
1780#define CMU_HS_P_MAXSAT_GCR_H 0x0A93
1781#define CMU_HS_P_MAXSAT_GCB_L 0x0A94
1782#define CMU_HS_P_MAXSAT_GCB_H 0x0A95
1783#define CMU_HS_P_MAXSAT_BCR_L 0x0A96
1784#define CMU_HS_P_MAXSAT_BCR_H 0x0A97
1785#define CMU_HS_P_MAXSAT_BCB_L 0x0A98
1786#define CMU_HS_P_MAXSAT_BCB_H 0x0A99
1787#define CMU_HS_P_ROFF_L 0x0A9A
1788#define CMU_HS_P_ROFF_H 0x0A9B
1789#define CMU_HS_P_GOFF_L 0x0A9C
1790#define CMU_HS_P_GOFF_H 0x0A9D
1791#define CMU_HS_P_BOFF_L 0x0A9E
1792#define CMU_HS_P_BOFF_H 0x0A9F
1793#define CMU_GLCSC_M_C0_L 0x0AA0
1794#define CMU_GLCSC_M_C0_H 0x0AA1
1795#define CMU_GLCSC_M_C1_L 0x0AA2
1796#define CMU_GLCSC_M_C1_H 0x0AA3
1797#define CMU_GLCSC_M_C2_L 0x0AA4
1798#define CMU_GLCSC_M_C2_H 0x0AA5
1799#define CMU_GLCSC_M_C3_L 0x0AA6
1800#define CMU_GLCSC_M_C3_H 0x0AA7
1801#define CMU_GLCSC_M_C4_L 0x0AA8
1802#define CMU_GLCSC_M_C4_H 0x0AA9
1803#define CMU_GLCSC_M_C5_L 0x0AAA
1804#define CMU_GLCSC_M_C5_H 0x0AAB
1805#define CMU_GLCSC_M_C6_L 0x0AAC
1806#define CMU_GLCSC_M_C6_H 0x0AAD
1807#define CMU_GLCSC_M_C7_L 0x0AAE
1808#define CMU_GLCSC_M_C7_H 0x0AAF
1809#define CMU_GLCSC_M_C8_L 0x0AB0
1810#define CMU_GLCSC_M_C8_H 0x0AB1
1811#define CMU_GLCSC_M_O1_1 0x0AB4
1812#define CMU_GLCSC_M_O1_2 0x0AB5
1813#define CMU_GLCSC_M_O1_3 0x0AB6
1814#define CMU_GLCSC_M_O2_1 0x0AB8
1815#define CMU_GLCSC_M_O2_2 0x0AB9
1816#define CMU_GLCSC_M_O2_3 0x0ABA
1817#define CMU_GLCSC_M_O3_1 0x0ABC
1818#define CMU_GLCSC_M_O3_2 0x0ABD
1819#define CMU_GLCSC_M_O3_3 0x0ABE
1820#define CMU_GLCSC_P_C0_L 0x0AC0
1821#define CMU_GLCSC_P_C0_H 0x0AC1
1822#define CMU_GLCSC_P_C1_L 0x0AC2
1823#define CMU_GLCSC_P_C1_H 0x0AC3
1824#define CMU_GLCSC_P_C2_L 0x0AC4
1825#define CMU_GLCSC_P_C2_H 0x0AC5
1826#define CMU_GLCSC_P_C3_L 0x0AC6
1827#define CMU_GLCSC_P_C3_H 0x0AC7
1828#define CMU_GLCSC_P_C4_L 0x0AC8
1829#define CMU_GLCSC_P_C4_H 0x0AC9
1830#define CMU_GLCSC_P_C5_L 0x0ACA
1831#define CMU_GLCSC_P_C5_H 0x0ACB
1832#define CMU_GLCSC_P_C6_L 0x0ACC
1833#define CMU_GLCSC_P_C6_H 0x0ACD
1834#define CMU_GLCSC_P_C7_L 0x0ACE
1835#define CMU_GLCSC_P_C7_H 0x0ACF
1836#define CMU_GLCSC_P_C8_L 0x0AD0
1837#define CMU_GLCSC_P_C8_H 0x0AD1
1838#define CMU_GLCSC_P_O1_1 0x0AD4
1839#define CMU_GLCSC_P_O1_2 0x0AD5
1840#define CMU_GLCSC_P_O1_3 0x0AD6
1841#define CMU_GLCSC_P_O2_1 0x0AD8
1842#define CMU_GLCSC_P_O2_2 0x0AD9
1843#define CMU_GLCSC_P_O2_3 0x0ADA
1844#define CMU_GLCSC_P_O3_1 0x0ADC
1845#define CMU_GLCSC_P_O3_2 0x0ADD
1846#define CMU_GLCSC_P_O3_3 0x0ADE
1847#define CMU_PIXVAL_M_EN 0x0AE0
1848#define CMU_PIXVAL_P_EN 0x0AE1
1849
1850#define CMU_CLK_CTRL_TCLK 0x0
1851#define CMU_CLK_CTRL_SCLK 0x2
1852#define CMU_CLK_CTRL_MSK 0x2
1853#define CMU_CLK_CTRL_ENABLE 0x1
1854
1855#define LCD_TOP_CTRL_TV 0x2
1856#define LCD_TOP_CTRL_PN 0x0
1857#define LCD_TOP_CTRL_SEL_MSK 0x2
1858#define LCD_IO_CMU_IN_SEL_MSK (0x3 << 20)
1859#define LCD_IO_CMU_IN_SEL_TV 0
1860#define LCD_IO_CMU_IN_SEL_PN 1
1861#define LCD_IO_CMU_IN_SEL_PN2 2
1862#define LCD_IO_TV_OUT_SEL_MSK (0x3 << 26)
1863#define LCD_IO_PN_OUT_SEL_MSK (0x3 << 24)
1864#define LCD_IO_PN2_OUT_SEL_MSK (0x3 << 28)
1865#define LCD_IO_TV_OUT_SEL_NON 3
1866#define LCD_IO_PN_OUT_SEL_NON 3
1867#define LCD_IO_PN2_OUT_SEL_NON 3
1868#define LCD_TOP_CTRL_CMU_ENABLE 0x1
1869#define LCD_IO_OVERL_MSK 0xC00000
1870#define LCD_IO_OVERL_TV 0x0
1871#define LCD_IO_OVERL_LCD1 0x400000
1872#define LCD_IO_OVERL_LCD2 0xC00000
1873#define HINVERT_MSK 0x4
1874#define VINVERT_MSK 0x8
1875#define HINVERT_LEN 0x2
1876#define VINVERT_LEN 0x3
1877
1878#define CMU_CTRL 0x88
1879#define CMU_CTRL_A0_MSK 0x6
1880#define CMU_CTRL_A0_TV 0x0
1881#define CMU_CTRL_A0_LCD1 0x1
1882#define CMU_CTRL_A0_LCD2 0x2
1883#define CMU_CTRL_A0_HDMI 0x3
1884
1885#define ICR_DRV_ROUTE_OFF 0x0
1886#define ICR_DRV_ROUTE_TV 0x1
1887#define ICR_DRV_ROUTE_LCD1 0x2
1888#define ICR_DRV_ROUTE_LCD2 0x3
1889
1890enum { 1413enum {
1891 PATH_PN = 0, 1414 PATH_PN = 0,
1892 PATH_TV, 1415 PATH_TV,
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
index 13ecd9897010..56009bc02b02 100644
--- a/drivers/video/of_display_timing.c
+++ b/drivers/video/of_display_timing.c
@@ -79,25 +79,24 @@ static struct display_timing *of_get_display_timing(struct device_node *np)
79 ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len); 79 ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
80 ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock); 80 ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
81 81
82 dt->dmt_flags = 0; 82 dt->flags = 0;
83 dt->data_flags = 0;
84 if (!of_property_read_u32(np, "vsync-active", &val)) 83 if (!of_property_read_u32(np, "vsync-active", &val))
85 dt->dmt_flags |= val ? VESA_DMT_VSYNC_HIGH : 84 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
86 VESA_DMT_VSYNC_LOW; 85 DISPLAY_FLAGS_VSYNC_LOW;
87 if (!of_property_read_u32(np, "hsync-active", &val)) 86 if (!of_property_read_u32(np, "hsync-active", &val))
88 dt->dmt_flags |= val ? VESA_DMT_HSYNC_HIGH : 87 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
89 VESA_DMT_HSYNC_LOW; 88 DISPLAY_FLAGS_HSYNC_LOW;
90 if (!of_property_read_u32(np, "de-active", &val)) 89 if (!of_property_read_u32(np, "de-active", &val))
91 dt->data_flags |= val ? DISPLAY_FLAGS_DE_HIGH : 90 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
92 DISPLAY_FLAGS_DE_LOW; 91 DISPLAY_FLAGS_DE_LOW;
93 if (!of_property_read_u32(np, "pixelclk-active", &val)) 92 if (!of_property_read_u32(np, "pixelclk-active", &val))
94 dt->data_flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : 93 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
95 DISPLAY_FLAGS_PIXDATA_NEGEDGE; 94 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
96 95
97 if (of_property_read_bool(np, "interlaced")) 96 if (of_property_read_bool(np, "interlaced"))
98 dt->data_flags |= DISPLAY_FLAGS_INTERLACED; 97 dt->flags |= DISPLAY_FLAGS_INTERLACED;
99 if (of_property_read_bool(np, "doublescan")) 98 if (of_property_read_bool(np, "doublescan"))
100 dt->data_flags |= DISPLAY_FLAGS_DOUBLESCAN; 99 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
101 100
102 if (ret) { 101 if (ret) {
103 pr_err("%s: error reading timing properties\n", 102 pr_err("%s: error reading timing properties\n",
diff --git a/drivers/video/of_videomode.c b/drivers/video/of_videomode.c
index 5b8066cd397f..111c2d1911d3 100644
--- a/drivers/video/of_videomode.c
+++ b/drivers/video/of_videomode.c
@@ -43,7 +43,7 @@ int of_get_videomode(struct device_node *np, struct videomode *vm,
43 if (index == OF_USE_NATIVE_MODE) 43 if (index == OF_USE_NATIVE_MODE)
44 index = disp->native_mode; 44 index = disp->native_mode;
45 45
46 ret = videomode_from_timing(disp, vm, index); 46 ret = videomode_from_timings(disp, vm, index);
47 if (ret) 47 if (ret)
48 return ret; 48 return ret;
49 49
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index e512581300fc..0bc3a936ce2b 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -39,17 +39,6 @@ config FB_OMAP_LCD_MIPID
39 the Mobile Industry Processor Interface DBI-C/DCS 39 the Mobile Industry Processor Interface DBI-C/DCS
40 specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3) 40 specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3)
41 41
42config FB_OMAP_CONSISTENT_DMA_SIZE
43 int "Consistent DMA memory size (MB)"
44 depends on FB_OMAP
45 range 1 14
46 default 2
47 help
48 Increase the DMA consistent memory size according to your video
49 memory needs, for example if you want to use multiple planes.
50 The size must be 2MB aligned.
51 If unsure say 1.
52
53config FB_OMAP_DMA_TUNE 42config FB_OMAP_DMA_TUNE
54 bool "Set DMA SDRAM access priority high" 43 bool "Set DMA SDRAM access priority high"
55 depends on FB_OMAP 44 depends on FB_OMAP
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index 5ea7cb9aed17..296e5c5281c5 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -1,5 +1,5 @@
1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o 1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
2 2
3obj-$(CONFIG_OMAP2_DSS) += dss/ 3obj-$(CONFIG_OMAP2_DSS) += dss/
4obj-$(CONFIG_FB_OMAP2) += omapfb/
5obj-y += displays/ 4obj-y += displays/
5obj-$(CONFIG_FB_OMAP2) += omapfb/
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index 72699f88c002..d7f69c09ecf1 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -29,8 +29,10 @@
29#include <linux/sched.h> 29#include <linux/sched.h>
30#include <linux/backlight.h> 30#include <linux/backlight.h>
31#include <linux/fb.h> 31#include <linux/fb.h>
32#include <linux/gpio.h>
32 33
33#include <video/omapdss.h> 34#include <video/omapdss.h>
35#include <video/omap-panel-data.h>
34 36
35#define MIPID_CMD_READ_DISP_ID 0x04 37#define MIPID_CMD_READ_DISP_ID 0x04
36#define MIPID_CMD_READ_RED 0x06 38#define MIPID_CMD_READ_RED 0x06
@@ -336,8 +338,6 @@ static int acx565akm_bl_update_status(struct backlight_device *dev)
336 r = 0; 338 r = 0;
337 if (md->has_bc) 339 if (md->has_bc)
338 acx565akm_set_brightness(md, level); 340 acx565akm_set_brightness(md, level);
339 else if (md->dssdev->set_backlight)
340 r = md->dssdev->set_backlight(md->dssdev, level);
341 else 341 else
342 r = -ENODEV; 342 r = -ENODEV;
343 343
@@ -352,7 +352,7 @@ static int acx565akm_bl_get_intensity(struct backlight_device *dev)
352 352
353 dev_dbg(&dev->dev, "%s\n", __func__); 353 dev_dbg(&dev->dev, "%s\n", __func__);
354 354
355 if (!md->has_bc && md->dssdev->set_backlight == NULL) 355 if (!md->has_bc)
356 return -ENODEV; 356 return -ENODEV;
357 357
358 if (dev->props.fb_blank == FB_BLANK_UNBLANK && 358 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
@@ -496,21 +496,38 @@ static struct omap_video_timings acx_panel_timings = {
496 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, 496 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
497}; 497};
498 498
499static struct panel_acx565akm_data *get_panel_data(struct omap_dss_device *dssdev)
500{
501 return (struct panel_acx565akm_data *) dssdev->data;
502}
503
499static int acx_panel_probe(struct omap_dss_device *dssdev) 504static int acx_panel_probe(struct omap_dss_device *dssdev)
500{ 505{
501 int r; 506 int r;
502 struct acx565akm_device *md = &acx_dev; 507 struct acx565akm_device *md = &acx_dev;
508 struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
503 struct backlight_device *bldev; 509 struct backlight_device *bldev;
504 int max_brightness, brightness; 510 int max_brightness, brightness;
505 struct backlight_properties props; 511 struct backlight_properties props;
506 512
507 dev_dbg(&dssdev->dev, "%s\n", __func__); 513 dev_dbg(&dssdev->dev, "%s\n", __func__);
508 514
515 if (!panel_data)
516 return -EINVAL;
517
509 /* FIXME AC bias ? */ 518 /* FIXME AC bias ? */
510 dssdev->panel.timings = acx_panel_timings; 519 dssdev->panel.timings = acx_panel_timings;
511 520
512 if (dssdev->platform_enable) 521 if (gpio_is_valid(panel_data->reset_gpio)) {
513 dssdev->platform_enable(dssdev); 522 r = devm_gpio_request_one(&dssdev->dev, panel_data->reset_gpio,
523 GPIOF_OUT_INIT_LOW, "lcd reset");
524 if (r)
525 return r;
526 }
527
528 if (gpio_is_valid(panel_data->reset_gpio))
529 gpio_set_value(panel_data->reset_gpio, 1);
530
514 /* 531 /*
515 * After reset we have to wait 5 msec before the first 532 * After reset we have to wait 5 msec before the first
516 * command can be sent. 533 * command can be sent.
@@ -522,8 +539,9 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
522 r = panel_detect(md); 539 r = panel_detect(md);
523 if (r) { 540 if (r) {
524 dev_err(&dssdev->dev, "%s panel detect error\n", __func__); 541 dev_err(&dssdev->dev, "%s panel detect error\n", __func__);
525 if (!md->enabled && dssdev->platform_disable) 542 if (!md->enabled && gpio_is_valid(panel_data->reset_gpio))
526 dssdev->platform_disable(dssdev); 543 gpio_set_value(panel_data->reset_gpio, 0);
544
527 return r; 545 return r;
528 } 546 }
529 547
@@ -532,8 +550,8 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
532 mutex_unlock(&acx_dev.mutex); 550 mutex_unlock(&acx_dev.mutex);
533 551
534 if (!md->enabled) { 552 if (!md->enabled) {
535 if (dssdev->platform_disable) 553 if (gpio_is_valid(panel_data->reset_gpio))
536 dssdev->platform_disable(dssdev); 554 gpio_set_value(panel_data->reset_gpio, 0);
537 } 555 }
538 556
539 /*------- Backlight control --------*/ 557 /*------- Backlight control --------*/
@@ -557,15 +575,10 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
557 md->cabc_mode = get_hw_cabc_mode(md); 575 md->cabc_mode = get_hw_cabc_mode(md);
558 } 576 }
559 577
560 if (md->has_bc) 578 max_brightness = 255;
561 max_brightness = 255;
562 else
563 max_brightness = dssdev->max_backlight_level;
564 579
565 if (md->has_bc) 580 if (md->has_bc)
566 brightness = acx565akm_get_actual_brightness(md); 581 brightness = acx565akm_get_actual_brightness(md);
567 else if (dssdev->get_backlight)
568 brightness = dssdev->get_backlight(dssdev);
569 else 582 else
570 brightness = 0; 583 brightness = 0;
571 584
@@ -591,6 +604,7 @@ static void acx_panel_remove(struct omap_dss_device *dssdev)
591static int acx_panel_power_on(struct omap_dss_device *dssdev) 604static int acx_panel_power_on(struct omap_dss_device *dssdev)
592{ 605{
593 struct acx565akm_device *md = &acx_dev; 606 struct acx565akm_device *md = &acx_dev;
607 struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
594 int r; 608 int r;
595 609
596 dev_dbg(&dssdev->dev, "%s\n", __func__); 610 dev_dbg(&dssdev->dev, "%s\n", __func__);
@@ -612,11 +626,8 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
612 /*FIXME tweak me */ 626 /*FIXME tweak me */
613 msleep(50); 627 msleep(50);
614 628
615 if (dssdev->platform_enable) { 629 if (gpio_is_valid(panel_data->reset_gpio))
616 r = dssdev->platform_enable(dssdev); 630 gpio_set_value(panel_data->reset_gpio, 1);
617 if (r)
618 goto fail;
619 }
620 631
621 if (md->enabled) { 632 if (md->enabled) {
622 dev_dbg(&md->spi->dev, "panel already enabled\n"); 633 dev_dbg(&md->spi->dev, "panel already enabled\n");
@@ -645,8 +656,7 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
645 mutex_unlock(&md->mutex); 656 mutex_unlock(&md->mutex);
646 657
647 return acx565akm_bl_update_status(md->bl_dev); 658 return acx565akm_bl_update_status(md->bl_dev);
648fail: 659
649 omapdss_sdi_display_disable(dssdev);
650fail_unlock: 660fail_unlock:
651 mutex_unlock(&md->mutex); 661 mutex_unlock(&md->mutex);
652 return r; 662 return r;
@@ -655,6 +665,7 @@ fail_unlock:
655static void acx_panel_power_off(struct omap_dss_device *dssdev) 665static void acx_panel_power_off(struct omap_dss_device *dssdev)
656{ 666{
657 struct acx565akm_device *md = &acx_dev; 667 struct acx565akm_device *md = &acx_dev;
668 struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
658 669
659 dev_dbg(&dssdev->dev, "%s\n", __func__); 670 dev_dbg(&dssdev->dev, "%s\n", __func__);
660 671
@@ -678,8 +689,8 @@ static void acx_panel_power_off(struct omap_dss_device *dssdev)
678 */ 689 */
679 msleep(50); 690 msleep(50);
680 691
681 if (dssdev->platform_disable) 692 if (gpio_is_valid(panel_data->reset_gpio))
682 dssdev->platform_disable(dssdev); 693 gpio_set_value(panel_data->reset_gpio, 0);
683 694
684 /* FIXME need to tweak this delay */ 695 /* FIXME need to tweak this delay */
685 msleep(100); 696 msleep(100);
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index c904f42d81c1..97363f733683 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -33,9 +33,10 @@
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 <linux/gpio.h>
36#include <video/omapdss.h> 37#include <video/omapdss.h>
37 38
38#include <video/omap-panel-generic-dpi.h> 39#include <video/omap-panel-data.h>
39 40
40struct panel_config { 41struct panel_config {
41 struct omap_video_timings timings; 42 struct omap_video_timings timings;
@@ -533,7 +534,7 @@ static inline struct panel_generic_dpi_data
533 534
534static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev) 535static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
535{ 536{
536 int r; 537 int r, i;
537 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); 538 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
538 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); 539 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
539 struct panel_config *panel_config = drv_data->panel_config; 540 struct panel_config *panel_config = drv_data->panel_config;
@@ -552,15 +553,13 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
552 if (panel_config->power_on_delay) 553 if (panel_config->power_on_delay)
553 msleep(panel_config->power_on_delay); 554 msleep(panel_config->power_on_delay);
554 555
555 if (panel_data->platform_enable) { 556 for (i = 0; i < panel_data->num_gpios; ++i) {
556 r = panel_data->platform_enable(dssdev); 557 gpio_set_value_cansleep(panel_data->gpios[i],
557 if (r) 558 panel_data->gpio_invert[i] ? 0 : 1);
558 goto err1;
559 } 559 }
560 560
561 return 0; 561 return 0;
562err1: 562
563 omapdss_dpi_display_disable(dssdev);
564err0: 563err0:
565 return r; 564 return r;
566} 565}
@@ -570,12 +569,15 @@ static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev)
570 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); 569 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
571 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); 570 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
572 struct panel_config *panel_config = drv_data->panel_config; 571 struct panel_config *panel_config = drv_data->panel_config;
572 int i;
573 573
574 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 574 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
575 return; 575 return;
576 576
577 if (panel_data->platform_disable) 577 for (i = panel_data->num_gpios - 1; i >= 0; --i) {
578 panel_data->platform_disable(dssdev); 578 gpio_set_value_cansleep(panel_data->gpios[i],
579 panel_data->gpio_invert[i] ? 1 : 0);
580 }
579 581
580 /* wait couple of vsyncs after disabling the LCD */ 582 /* wait couple of vsyncs after disabling the LCD */
581 if (panel_config->power_off_delay) 583 if (panel_config->power_off_delay)
@@ -589,7 +591,7 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
589 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); 591 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
590 struct panel_config *panel_config = NULL; 592 struct panel_config *panel_config = NULL;
591 struct panel_drv_data *drv_data = NULL; 593 struct panel_drv_data *drv_data = NULL;
592 int i; 594 int i, r;
593 595
594 dev_dbg(&dssdev->dev, "probe\n"); 596 dev_dbg(&dssdev->dev, "probe\n");
595 597
@@ -606,9 +608,18 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
606 if (!panel_config) 608 if (!panel_config)
607 return -EINVAL; 609 return -EINVAL;
608 610
611 for (i = 0; i < panel_data->num_gpios; ++i) {
612 r = devm_gpio_request_one(&dssdev->dev, panel_data->gpios[i],
613 panel_data->gpio_invert[i] ?
614 GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
615 "panel gpio");
616 if (r)
617 return r;
618 }
619
609 dssdev->panel.timings = panel_config->timings; 620 dssdev->panel.timings = panel_config->timings;
610 621
611 drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL); 622 drv_data = devm_kzalloc(&dssdev->dev, sizeof(*drv_data), GFP_KERNEL);
612 if (!drv_data) 623 if (!drv_data)
613 return -ENOMEM; 624 return -ENOMEM;
614 625
@@ -624,12 +635,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
624 635
625static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev) 636static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
626{ 637{
627 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
628
629 dev_dbg(&dssdev->dev, "remove\n"); 638 dev_dbg(&dssdev->dev, "remove\n");
630 639
631 kfree(drv_data);
632
633 dev_set_drvdata(&dssdev->dev, NULL); 640 dev_set_drvdata(&dssdev->dev, NULL);
634} 641}
635 642
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index 6e5abe8fd2dd..4ea6548c0ae9 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -20,8 +20,10 @@
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/spi/spi.h> 21#include <linux/spi/spi.h>
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/gpio.h>
23 24
24#include <video/omapdss.h> 25#include <video/omapdss.h>
26#include <video/omap-panel-data.h>
25 27
26struct lb035q02_data { 28struct lb035q02_data {
27 struct mutex lock; 29 struct mutex lock;
@@ -48,9 +50,16 @@ static struct omap_video_timings lb035q02_timings = {
48 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, 50 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
49}; 51};
50 52
53static inline struct panel_generic_dpi_data
54*get_panel_data(const struct omap_dss_device *dssdev)
55{
56 return (struct panel_generic_dpi_data *) dssdev->data;
57}
58
51static int lb035q02_panel_power_on(struct omap_dss_device *dssdev) 59static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
52{ 60{
53 int r; 61 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
62 int r, i;
54 63
55 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 64 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
56 return 0; 65 return 0;
@@ -62,54 +71,65 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
62 if (r) 71 if (r)
63 goto err0; 72 goto err0;
64 73
65 if (dssdev->platform_enable) { 74 for (i = 0; i < panel_data->num_gpios; ++i) {
66 r = dssdev->platform_enable(dssdev); 75 gpio_set_value_cansleep(panel_data->gpios[i],
67 if (r) 76 panel_data->gpio_invert[i] ? 0 : 1);
68 goto err1;
69 } 77 }
70 78
71 return 0; 79 return 0;
72err1: 80
73 omapdss_dpi_display_disable(dssdev);
74err0: 81err0:
75 return r; 82 return r;
76} 83}
77 84
78static void lb035q02_panel_power_off(struct omap_dss_device *dssdev) 85static void lb035q02_panel_power_off(struct omap_dss_device *dssdev)
79{ 86{
87 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
88 int i;
89
80 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 90 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
81 return; 91 return;
82 92
83 if (dssdev->platform_disable) 93 for (i = panel_data->num_gpios - 1; i >= 0; --i) {
84 dssdev->platform_disable(dssdev); 94 gpio_set_value_cansleep(panel_data->gpios[i],
95 panel_data->gpio_invert[i] ? 1 : 0);
96 }
85 97
86 omapdss_dpi_display_disable(dssdev); 98 omapdss_dpi_display_disable(dssdev);
87} 99}
88 100
89static int lb035q02_panel_probe(struct omap_dss_device *dssdev) 101static int lb035q02_panel_probe(struct omap_dss_device *dssdev)
90{ 102{
103 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
91 struct lb035q02_data *ld; 104 struct lb035q02_data *ld;
92 int r; 105 int r, i;
106
107 if (!panel_data)
108 return -EINVAL;
93 109
94 dssdev->panel.timings = lb035q02_timings; 110 dssdev->panel.timings = lb035q02_timings;
95 111
96 ld = kzalloc(sizeof(*ld), GFP_KERNEL); 112 ld = devm_kzalloc(&dssdev->dev, sizeof(*ld), GFP_KERNEL);
97 if (!ld) { 113 if (!ld)
98 r = -ENOMEM; 114 return -ENOMEM;
99 goto err; 115
116 for (i = 0; i < panel_data->num_gpios; ++i) {
117 r = devm_gpio_request_one(&dssdev->dev, panel_data->gpios[i],
118 panel_data->gpio_invert[i] ?
119 GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
120 "panel gpio");
121 if (r)
122 return r;
100 } 123 }
124
101 mutex_init(&ld->lock); 125 mutex_init(&ld->lock);
102 dev_set_drvdata(&dssdev->dev, ld); 126 dev_set_drvdata(&dssdev->dev, ld);
127
103 return 0; 128 return 0;
104err:
105 return r;
106} 129}
107 130
108static void lb035q02_panel_remove(struct omap_dss_device *dssdev) 131static void lb035q02_panel_remove(struct omap_dss_device *dssdev)
109{ 132{
110 struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
111
112 kfree(ld);
113} 133}
114 134
115static int lb035q02_panel_enable(struct omap_dss_device *dssdev) 135static int lb035q02_panel_enable(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index dd1294750802..f94ead6a3183 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -5,11 +5,10 @@
5#include <linux/slab.h> 5#include <linux/slab.h>
6#include <linux/gpio.h> 6#include <linux/gpio.h>
7#include <linux/spi/spi.h> 7#include <linux/spi/spi.h>
8#include <linux/backlight.h>
9#include <linux/fb.h> 8#include <linux/fb.h>
10 9
11#include <video/omapdss.h> 10#include <video/omapdss.h>
12#include <video/omap-panel-n8x0.h> 11#include <video/omap-panel-data.h>
13 12
14#define BLIZZARD_REV_CODE 0x00 13#define BLIZZARD_REV_CODE 0x00
15#define BLIZZARD_CONFIG 0x02 14#define BLIZZARD_CONFIG 0x02
@@ -69,7 +68,6 @@ static struct panel_drv_data {
69 68
70 struct omap_dss_device *dssdev; 69 struct omap_dss_device *dssdev;
71 struct spi_device *spidev; 70 struct spi_device *spidev;
72 struct backlight_device *bldev;
73 71
74 int blizzard_ver; 72 int blizzard_ver;
75} s_drv_data; 73} s_drv_data;
@@ -297,12 +295,6 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
297 295
298 gpio_direction_output(bdata->ctrl_pwrdown, 1); 296 gpio_direction_output(bdata->ctrl_pwrdown, 1);
299 297
300 if (bdata->platform_enable) {
301 r = bdata->platform_enable(dssdev);
302 if (r)
303 goto err_plat_en;
304 }
305
306 omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res, 298 omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
307 dssdev->panel.timings.y_res); 299 dssdev->panel.timings.y_res);
308 omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size); 300 omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
@@ -375,9 +367,6 @@ err_inv_panel:
375err_inv_chip: 367err_inv_chip:
376 omapdss_rfbi_display_disable(dssdev); 368 omapdss_rfbi_display_disable(dssdev);
377err_rfbi_en: 369err_rfbi_en:
378 if (bdata->platform_disable)
379 bdata->platform_disable(dssdev);
380err_plat_en:
381 gpio_direction_output(bdata->ctrl_pwrdown, 0); 370 gpio_direction_output(bdata->ctrl_pwrdown, 0);
382 return r; 371 return r;
383} 372}
@@ -394,9 +383,6 @@ static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
394 send_display_off(spi); 383 send_display_off(spi);
395 send_sleep_in(spi); 384 send_sleep_in(spi);
396 385
397 if (bdata->platform_disable)
398 bdata->platform_disable(dssdev);
399
400 /* 386 /*
401 * HACK: we should turn off the panel here, but there is some problem 387 * HACK: we should turn off the panel here, but there is some problem
402 * with the initialization sequence, and we fail to init the panel if we 388 * with the initialization sequence, and we fail to init the panel if we
@@ -424,54 +410,10 @@ static const struct rfbi_timings n8x0_panel_timings = {
424 .cs_pulse_width = 0, 410 .cs_pulse_width = 0,
425}; 411};
426 412
427static int n8x0_bl_update_status(struct backlight_device *dev)
428{
429 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
430 struct panel_n8x0_data *bdata = get_board_data(dssdev);
431 struct panel_drv_data *ddata = get_drv_data(dssdev);
432 int r;
433 int level;
434
435 mutex_lock(&ddata->lock);
436
437 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
438 dev->props.power == FB_BLANK_UNBLANK)
439 level = dev->props.brightness;
440 else
441 level = 0;
442
443 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
444
445 if (!bdata->set_backlight)
446 r = -EINVAL;
447 else
448 r = bdata->set_backlight(dssdev, level);
449
450 mutex_unlock(&ddata->lock);
451
452 return r;
453}
454
455static int n8x0_bl_get_intensity(struct backlight_device *dev)
456{
457 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
458 dev->props.power == FB_BLANK_UNBLANK)
459 return dev->props.brightness;
460
461 return 0;
462}
463
464static const struct backlight_ops n8x0_bl_ops = {
465 .get_brightness = n8x0_bl_get_intensity,
466 .update_status = n8x0_bl_update_status,
467};
468
469static int n8x0_panel_probe(struct omap_dss_device *dssdev) 413static int n8x0_panel_probe(struct omap_dss_device *dssdev)
470{ 414{
471 struct panel_n8x0_data *bdata = get_board_data(dssdev); 415 struct panel_n8x0_data *bdata = get_board_data(dssdev);
472 struct panel_drv_data *ddata; 416 struct panel_drv_data *ddata;
473 struct backlight_device *bldev;
474 struct backlight_properties props;
475 int r; 417 int r;
476 418
477 dev_dbg(&dssdev->dev, "probe\n"); 419 dev_dbg(&dssdev->dev, "probe\n");
@@ -491,40 +433,27 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)
491 dssdev->ctrl.rfbi_timings = n8x0_panel_timings; 433 dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
492 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; 434 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
493 435
494 memset(&props, 0, sizeof(props)); 436 if (gpio_is_valid(bdata->panel_reset)) {
495 props.max_brightness = 127; 437 r = devm_gpio_request_one(&dssdev->dev, bdata->panel_reset,
496 props.type = BACKLIGHT_PLATFORM; 438 GPIOF_OUT_INIT_LOW, "PANEL RESET");
497 bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, 439 if (r)
498 dssdev, &n8x0_bl_ops, &props); 440 return r;
499 if (IS_ERR(bldev)) {
500 r = PTR_ERR(bldev);
501 dev_err(&dssdev->dev, "register backlight failed\n");
502 return r;
503 } 441 }
504 442
505 ddata->bldev = bldev; 443 if (gpio_is_valid(bdata->ctrl_pwrdown)) {
506 444 r = devm_gpio_request_one(&dssdev->dev, bdata->ctrl_pwrdown,
507 bldev->props.fb_blank = FB_BLANK_UNBLANK; 445 GPIOF_OUT_INIT_LOW, "PANEL PWRDOWN");
508 bldev->props.power = FB_BLANK_UNBLANK; 446 if (r)
509 bldev->props.brightness = 127; 447 return r;
510 448 }
511 n8x0_bl_update_status(bldev);
512 449
513 return 0; 450 return 0;
514} 451}
515 452
516static void n8x0_panel_remove(struct omap_dss_device *dssdev) 453static void n8x0_panel_remove(struct omap_dss_device *dssdev)
517{ 454{
518 struct panel_drv_data *ddata = get_drv_data(dssdev);
519 struct backlight_device *bldev;
520
521 dev_dbg(&dssdev->dev, "remove\n"); 455 dev_dbg(&dssdev->dev, "remove\n");
522 456
523 bldev = ddata->bldev;
524 bldev->props.power = FB_BLANK_POWERDOWN;
525 n8x0_bl_update_status(bldev);
526 backlight_device_unregister(bldev);
527
528 dev_set_drvdata(&dssdev->dev, NULL); 457 dev_set_drvdata(&dssdev->dev, NULL);
529} 458}
530 459
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index c4e9c2b1b465..20c3cd91ff9b 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -19,10 +19,11 @@
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/spi/spi.h> 21#include <linux/spi/spi.h>
22#include <linux/backlight.h>
23#include <linux/fb.h> 22#include <linux/fb.h>
23#include <linux/gpio.h>
24 24
25#include <video/omapdss.h> 25#include <video/omapdss.h>
26#include <video/omap-panel-data.h>
26 27
27#define LCD_XRES 800 28#define LCD_XRES 800
28#define LCD_YRES 480 29#define LCD_YRES 480
@@ -32,10 +33,6 @@
32 */ 33 */
33#define LCD_PIXEL_CLOCK 23800 34#define LCD_PIXEL_CLOCK 23800
34 35
35struct nec_8048_data {
36 struct backlight_device *bl;
37};
38
39static const struct { 36static const struct {
40 unsigned char addr; 37 unsigned char addr;
41 unsigned char dat; 38 unsigned char dat;
@@ -84,93 +81,47 @@ static struct omap_video_timings nec_8048_panel_timings = {
84 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, 81 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
85}; 82};
86 83
87static int nec_8048_bl_update_status(struct backlight_device *bl) 84static inline struct panel_nec_nl8048_data
88{ 85*get_panel_data(const struct omap_dss_device *dssdev)
89 struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
90 int level;
91
92 if (!dssdev->set_backlight)
93 return -EINVAL;
94
95 if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
96 bl->props.power == FB_BLANK_UNBLANK)
97 level = bl->props.brightness;
98 else
99 level = 0;
100
101 return dssdev->set_backlight(dssdev, level);
102}
103
104static int nec_8048_bl_get_brightness(struct backlight_device *bl)
105{ 86{
106 if (bl->props.fb_blank == FB_BLANK_UNBLANK && 87 return (struct panel_nec_nl8048_data *) dssdev->data;
107 bl->props.power == FB_BLANK_UNBLANK)
108 return bl->props.brightness;
109
110 return 0;
111} 88}
112 89
113static const struct backlight_ops nec_8048_bl_ops = {
114 .get_brightness = nec_8048_bl_get_brightness,
115 .update_status = nec_8048_bl_update_status,
116};
117
118static int nec_8048_panel_probe(struct omap_dss_device *dssdev) 90static int nec_8048_panel_probe(struct omap_dss_device *dssdev)
119{ 91{
120 struct backlight_device *bl; 92 struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
121 struct nec_8048_data *necd;
122 struct backlight_properties props;
123 int r; 93 int r;
124 94
125 dssdev->panel.timings = nec_8048_panel_timings; 95 if (!pd)
126 96 return -EINVAL;
127 necd = kzalloc(sizeof(*necd), GFP_KERNEL);
128 if (!necd)
129 return -ENOMEM;
130
131 dev_set_drvdata(&dssdev->dev, necd);
132 97
133 memset(&props, 0, sizeof(struct backlight_properties)); 98 dssdev->panel.timings = nec_8048_panel_timings;
134 props.max_brightness = 255;
135 99
136 bl = backlight_device_register("nec-8048", &dssdev->dev, dssdev, 100 if (gpio_is_valid(pd->qvga_gpio)) {
137 &nec_8048_bl_ops, &props); 101 r = devm_gpio_request_one(&dssdev->dev, pd->qvga_gpio,
138 if (IS_ERR(bl)) { 102 GPIOF_OUT_INIT_HIGH, "lcd QVGA");
139 r = PTR_ERR(bl); 103 if (r)
140 kfree(necd); 104 return r;
141 return r;
142 } 105 }
143 necd->bl = bl;
144
145 bl->props.fb_blank = FB_BLANK_UNBLANK;
146 bl->props.power = FB_BLANK_UNBLANK;
147 bl->props.max_brightness = dssdev->max_backlight_level;
148 bl->props.brightness = dssdev->max_backlight_level;
149 106
150 r = nec_8048_bl_update_status(bl); 107 if (gpio_is_valid(pd->res_gpio)) {
151 if (r < 0) 108 r = devm_gpio_request_one(&dssdev->dev, pd->res_gpio,
152 dev_err(&dssdev->dev, "failed to set lcd brightness\n"); 109 GPIOF_OUT_INIT_LOW, "lcd RES");
110 if (r)
111 return r;
112 }
153 113
154 return 0; 114 return 0;
155} 115}
156 116
157static void nec_8048_panel_remove(struct omap_dss_device *dssdev) 117static void nec_8048_panel_remove(struct omap_dss_device *dssdev)
158{ 118{
159 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
160 struct backlight_device *bl = necd->bl;
161
162 bl->props.power = FB_BLANK_POWERDOWN;
163 nec_8048_bl_update_status(bl);
164 backlight_device_unregister(bl);
165
166 kfree(necd);
167} 119}
168 120
169static int nec_8048_panel_power_on(struct omap_dss_device *dssdev) 121static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
170{ 122{
123 struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
171 int r; 124 int r;
172 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
173 struct backlight_device *bl = necd->bl;
174 125
175 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 126 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
176 return 0; 127 return 0;
@@ -182,36 +133,24 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
182 if (r) 133 if (r)
183 goto err0; 134 goto err0;
184 135
185 if (dssdev->platform_enable) { 136 if (gpio_is_valid(pd->res_gpio))
186 r = dssdev->platform_enable(dssdev); 137 gpio_set_value_cansleep(pd->res_gpio, 1);
187 if (r)
188 goto err1;
189 }
190
191 r = nec_8048_bl_update_status(bl);
192 if (r < 0)
193 dev_err(&dssdev->dev, "failed to set lcd brightness\n");
194 138
195 return 0; 139 return 0;
196err1: 140
197 omapdss_dpi_display_disable(dssdev);
198err0: 141err0:
199 return r; 142 return r;
200} 143}
201 144
202static void nec_8048_panel_power_off(struct omap_dss_device *dssdev) 145static void nec_8048_panel_power_off(struct omap_dss_device *dssdev)
203{ 146{
204 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); 147 struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
205 struct backlight_device *bl = necd->bl;
206 148
207 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 149 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
208 return; 150 return;
209 151
210 bl->props.brightness = 0; 152 if (gpio_is_valid(pd->res_gpio))
211 nec_8048_bl_update_status(bl); 153 gpio_set_value_cansleep(pd->res_gpio, 0);
212
213 if (dssdev->platform_disable)
214 dssdev->platform_disable(dssdev);
215 154
216 omapdss_dpi_display_disable(dssdev); 155 omapdss_dpi_display_disable(dssdev);
217} 156}
@@ -303,16 +242,22 @@ static int nec_8048_spi_remove(struct spi_device *spi)
303 return 0; 242 return 0;
304} 243}
305 244
306static int nec_8048_spi_suspend(struct spi_device *spi, pm_message_t mesg) 245#ifdef CONFIG_PM_SLEEP
246
247static int nec_8048_spi_suspend(struct device *dev)
307{ 248{
249 struct spi_device *spi = to_spi_device(dev);
250
308 nec_8048_spi_send(spi, 2, 0x01); 251 nec_8048_spi_send(spi, 2, 0x01);
309 mdelay(40); 252 mdelay(40);
310 253
311 return 0; 254 return 0;
312} 255}
313 256
314static int nec_8048_spi_resume(struct spi_device *spi) 257static int nec_8048_spi_resume(struct device *dev)
315{ 258{
259 struct spi_device *spi = to_spi_device(dev);
260
316 /* reinitialize the panel */ 261 /* reinitialize the panel */
317 spi_setup(spi); 262 spi_setup(spi);
318 nec_8048_spi_send(spi, 2, 0x00); 263 nec_8048_spi_send(spi, 2, 0x00);
@@ -321,14 +266,20 @@ static int nec_8048_spi_resume(struct spi_device *spi)
321 return 0; 266 return 0;
322} 267}
323 268
269static SIMPLE_DEV_PM_OPS(nec_8048_spi_pm_ops, nec_8048_spi_suspend,
270 nec_8048_spi_resume);
271#define NEC_8048_SPI_PM_OPS (&nec_8048_spi_pm_ops)
272#else
273#define NEC_8048_SPI_PM_OPS NULL
274#endif
275
324static struct spi_driver nec_8048_spi_driver = { 276static struct spi_driver nec_8048_spi_driver = {
325 .probe = nec_8048_spi_probe, 277 .probe = nec_8048_spi_probe,
326 .remove = nec_8048_spi_remove, 278 .remove = nec_8048_spi_remove,
327 .suspend = nec_8048_spi_suspend,
328 .resume = nec_8048_spi_resume,
329 .driver = { 279 .driver = {
330 .name = "nec_8048_spi", 280 .name = "nec_8048_spi",
331 .owner = THIS_MODULE, 281 .owner = THIS_MODULE,
282 .pm = NEC_8048_SPI_PM_OPS,
332 }, 283 },
333}; 284};
334 285
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
index 1b94018aac3e..62f2db04fbc8 100644
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -31,7 +31,7 @@
31#include <linux/gpio.h> 31#include <linux/gpio.h>
32 32
33#include <video/omapdss.h> 33#include <video/omapdss.h>
34#include <video/omap-panel-picodlp.h> 34#include <video/omap-panel-data.h>
35 35
36#include "panel-picodlp.h" 36#include "panel-picodlp.h"
37 37
@@ -354,12 +354,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
354 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); 354 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
355 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); 355 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
356 356
357 if (dssdev->platform_enable) {
358 r = dssdev->platform_enable(dssdev);
359 if (r)
360 return r;
361 }
362
363 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); 357 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
364 msleep(1); 358 msleep(1);
365 gpio_set_value(picodlp_pdata->pwrgood_gpio, 1); 359 gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
@@ -398,9 +392,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
398err: 392err:
399 omapdss_dpi_display_disable(dssdev); 393 omapdss_dpi_display_disable(dssdev);
400err1: 394err1:
401 if (dssdev->platform_disable)
402 dssdev->platform_disable(dssdev);
403
404 return r; 395 return r;
405} 396}
406 397
@@ -412,9 +403,6 @@ static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
412 403
413 gpio_set_value(picodlp_pdata->emu_done_gpio, 0); 404 gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
414 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); 405 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
415
416 if (dssdev->platform_disable)
417 dssdev->platform_disable(dssdev);
418} 406}
419 407
420static int picodlp_panel_probe(struct omap_dss_device *dssdev) 408static int picodlp_panel_probe(struct omap_dss_device *dssdev)
@@ -423,11 +411,14 @@ static int picodlp_panel_probe(struct omap_dss_device *dssdev)
423 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); 411 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
424 struct i2c_adapter *adapter; 412 struct i2c_adapter *adapter;
425 struct i2c_client *picodlp_i2c_client; 413 struct i2c_client *picodlp_i2c_client;
426 int r = 0, picodlp_adapter_id; 414 int r, picodlp_adapter_id;
427 415
428 dssdev->panel.timings = pico_ls_timings; 416 dssdev->panel.timings = pico_ls_timings;
429 417
430 picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL); 418 if (!picodlp_pdata)
419 return -EINVAL;
420
421 picod = devm_kzalloc(&dssdev->dev, sizeof(*picod), GFP_KERNEL);
431 if (!picod) 422 if (!picod)
432 return -ENOMEM; 423 return -ENOMEM;
433 424
@@ -438,25 +429,37 @@ static int picodlp_panel_probe(struct omap_dss_device *dssdev)
438 adapter = i2c_get_adapter(picodlp_adapter_id); 429 adapter = i2c_get_adapter(picodlp_adapter_id);
439 if (!adapter) { 430 if (!adapter) {
440 dev_err(&dssdev->dev, "can't get i2c adapter\n"); 431 dev_err(&dssdev->dev, "can't get i2c adapter\n");
441 r = -ENODEV; 432 return -ENODEV;
442 goto err;
443 } 433 }
444 434
445 picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info); 435 picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
446 if (!picodlp_i2c_client) { 436 if (!picodlp_i2c_client) {
447 dev_err(&dssdev->dev, "can't add i2c device::" 437 dev_err(&dssdev->dev, "can't add i2c device::"
448 " picodlp_i2c_client is NULL\n"); 438 " picodlp_i2c_client is NULL\n");
449 r = -ENODEV; 439 return -ENODEV;
450 goto err;
451 } 440 }
452 441
453 picod->picodlp_i2c_client = picodlp_i2c_client; 442 picod->picodlp_i2c_client = picodlp_i2c_client;
454 443
455 dev_set_drvdata(&dssdev->dev, picod); 444 dev_set_drvdata(&dssdev->dev, picod);
456 return r; 445
457err: 446 if (gpio_is_valid(picodlp_pdata->emu_done_gpio)) {
458 kfree(picod); 447 r = devm_gpio_request_one(&dssdev->dev,
459 return r; 448 picodlp_pdata->emu_done_gpio,
449 GPIOF_IN, "DLP EMU DONE");
450 if (r)
451 return r;
452 }
453
454 if (gpio_is_valid(picodlp_pdata->pwrgood_gpio)) {
455 r = devm_gpio_request_one(&dssdev->dev,
456 picodlp_pdata->pwrgood_gpio,
457 GPIOF_OUT_INIT_LOW, "DLP PWRGOOD");
458 if (r)
459 return r;
460 }
461
462 return 0;
460} 463}
461 464
462static void picodlp_panel_remove(struct omap_dss_device *dssdev) 465static void picodlp_panel_remove(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index cada8c621e01..74cb0eb45311 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -20,16 +20,13 @@
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/device.h> 22#include <linux/device.h>
23#include <linux/backlight.h>
24#include <linux/fb.h> 23#include <linux/fb.h>
25#include <linux/err.h> 24#include <linux/err.h>
26#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/gpio.h>
27 27
28#include <video/omapdss.h> 28#include <video/omapdss.h>
29 29#include <video/omap-panel-data.h>
30struct sharp_data {
31 struct backlight_device *bl;
32};
33 30
34static struct omap_video_timings sharp_ls_timings = { 31static struct omap_video_timings sharp_ls_timings = {
35 .x_res = 480, 32 .x_res = 480,
@@ -52,91 +49,67 @@ static struct omap_video_timings sharp_ls_timings = {
52 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, 49 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
53}; 50};
54 51
55static int sharp_ls_bl_update_status(struct backlight_device *bl) 52static inline struct panel_sharp_ls037v7dw01_data
53*get_panel_data(const struct omap_dss_device *dssdev)
56{ 54{
57 struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev); 55 return (struct panel_sharp_ls037v7dw01_data *) dssdev->data;
58 int level;
59
60 if (!dssdev->set_backlight)
61 return -EINVAL;
62
63 if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
64 bl->props.power == FB_BLANK_UNBLANK)
65 level = bl->props.brightness;
66 else
67 level = 0;
68
69 return dssdev->set_backlight(dssdev, level);
70} 56}
71 57
72static int sharp_ls_bl_get_brightness(struct backlight_device *bl)
73{
74 if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
75 bl->props.power == FB_BLANK_UNBLANK)
76 return bl->props.brightness;
77
78 return 0;
79}
80
81static const struct backlight_ops sharp_ls_bl_ops = {
82 .get_brightness = sharp_ls_bl_get_brightness,
83 .update_status = sharp_ls_bl_update_status,
84};
85
86
87
88static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) 58static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
89{ 59{
90 struct backlight_properties props; 60 struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
91 struct backlight_device *bl;
92 struct sharp_data *sd;
93 int r; 61 int r;
94 62
63 if (!pd)
64 return -EINVAL;
65
95 dssdev->panel.timings = sharp_ls_timings; 66 dssdev->panel.timings = sharp_ls_timings;
96 67
97 sd = kzalloc(sizeof(*sd), GFP_KERNEL); 68 if (gpio_is_valid(pd->mo_gpio)) {
98 if (!sd) 69 r = devm_gpio_request_one(&dssdev->dev, pd->mo_gpio,
99 return -ENOMEM; 70 GPIOF_OUT_INIT_LOW, "lcd MO");
71 if (r)
72 return r;
73 }
100 74
101 dev_set_drvdata(&dssdev->dev, sd); 75 if (gpio_is_valid(pd->lr_gpio)) {
76 r = devm_gpio_request_one(&dssdev->dev, pd->lr_gpio,
77 GPIOF_OUT_INIT_HIGH, "lcd LR");
78 if (r)
79 return r;
80 }
102 81
103 memset(&props, 0, sizeof(struct backlight_properties)); 82 if (gpio_is_valid(pd->ud_gpio)) {
104 props.max_brightness = dssdev->max_backlight_level; 83 r = devm_gpio_request_one(&dssdev->dev, pd->ud_gpio,
105 props.type = BACKLIGHT_RAW; 84 GPIOF_OUT_INIT_HIGH, "lcd UD");
85 if (r)
86 return r;
87 }
106 88
107 bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev, 89 if (gpio_is_valid(pd->resb_gpio)) {
108 &sharp_ls_bl_ops, &props); 90 r = devm_gpio_request_one(&dssdev->dev, pd->resb_gpio,
109 if (IS_ERR(bl)) { 91 GPIOF_OUT_INIT_LOW, "lcd RESB");
110 r = PTR_ERR(bl); 92 if (r)
111 kfree(sd); 93 return r;
112 return r;
113 } 94 }
114 sd->bl = bl;
115 95
116 bl->props.fb_blank = FB_BLANK_UNBLANK; 96 if (gpio_is_valid(pd->ini_gpio)) {
117 bl->props.power = FB_BLANK_UNBLANK; 97 r = devm_gpio_request_one(&dssdev->dev, pd->ini_gpio,
118 bl->props.brightness = dssdev->max_backlight_level; 98 GPIOF_OUT_INIT_LOW, "lcd INI");
119 r = sharp_ls_bl_update_status(bl); 99 if (r)
120 if (r < 0) 100 return r;
121 dev_err(&dssdev->dev, "failed to set lcd brightness\n"); 101 }
122 102
123 return 0; 103 return 0;
124} 104}
125 105
126static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev) 106static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev)
127{ 107{
128 struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
129 struct backlight_device *bl = sd->bl;
130
131 bl->props.power = FB_BLANK_POWERDOWN;
132 sharp_ls_bl_update_status(bl);
133 backlight_device_unregister(bl);
134
135 kfree(sd);
136} 108}
137 109
138static int sharp_ls_power_on(struct omap_dss_device *dssdev) 110static int sharp_ls_power_on(struct omap_dss_device *dssdev)
139{ 111{
112 struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
140 int r = 0; 113 int r = 0;
141 114
142 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 115 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
@@ -152,26 +125,29 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
152 /* wait couple of vsyncs until enabling the LCD */ 125 /* wait couple of vsyncs until enabling the LCD */
153 msleep(50); 126 msleep(50);
154 127
155 if (dssdev->platform_enable) { 128 if (gpio_is_valid(pd->resb_gpio))
156 r = dssdev->platform_enable(dssdev); 129 gpio_set_value_cansleep(pd->resb_gpio, 1);
157 if (r) 130
158 goto err1; 131 if (gpio_is_valid(pd->ini_gpio))
159 } 132 gpio_set_value_cansleep(pd->ini_gpio, 1);
160 133
161 return 0; 134 return 0;
162err1:
163 omapdss_dpi_display_disable(dssdev);
164err0: 135err0:
165 return r; 136 return r;
166} 137}
167 138
168static void sharp_ls_power_off(struct omap_dss_device *dssdev) 139static void sharp_ls_power_off(struct omap_dss_device *dssdev)
169{ 140{
141 struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
142
170 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 143 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
171 return; 144 return;
172 145
173 if (dssdev->platform_disable) 146 if (gpio_is_valid(pd->ini_gpio))
174 dssdev->platform_disable(dssdev); 147 gpio_set_value_cansleep(pd->ini_gpio, 0);
148
149 if (gpio_is_valid(pd->resb_gpio))
150 gpio_set_value_cansleep(pd->resb_gpio, 0);
175 151
176 /* wait at least 5 vsyncs after disabling the LCD */ 152 /* wait at least 5 vsyncs after disabling the LCD */
177 153
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index a32407a5735a..c4f78bda115a 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -33,7 +33,7 @@
33#include <linux/mutex.h> 33#include <linux/mutex.h>
34 34
35#include <video/omapdss.h> 35#include <video/omapdss.h>
36#include <video/omap-panel-nokia-dsi.h> 36#include <video/omap-panel-data.h>
37#include <video/mipi_display.h> 37#include <video/mipi_display.h>
38 38
39/* DSI Virtual channel. Hardcoded for now. */ 39/* DSI Virtual channel. Hardcoded for now. */
@@ -54,61 +54,6 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
54 54
55static int taal_panel_reset(struct omap_dss_device *dssdev); 55static int taal_panel_reset(struct omap_dss_device *dssdev);
56 56
57/**
58 * struct panel_config - panel configuration
59 * @name: panel name
60 * @type: panel type
61 * @timings: panel resolution
62 * @sleep: various panel specific delays, passed to msleep() if non-zero
63 * @reset_sequence: reset sequence timings, passed to udelay() if non-zero
64 * @regulators: array of panel regulators
65 * @num_regulators: number of regulators in the array
66 */
67struct panel_config {
68 const char *name;
69 int type;
70
71 struct omap_video_timings timings;
72
73 struct {
74 unsigned int sleep_in;
75 unsigned int sleep_out;
76 unsigned int hw_reset;
77 unsigned int enable_te;
78 } sleep;
79
80 struct {
81 unsigned int high;
82 unsigned int low;
83 } reset_sequence;
84
85};
86
87enum {
88 PANEL_TAAL,
89};
90
91static struct panel_config panel_configs[] = {
92 {
93 .name = "taal",
94 .type = PANEL_TAAL,
95 .timings = {
96 .x_res = 864,
97 .y_res = 480,
98 },
99 .sleep = {
100 .sleep_in = 5,
101 .sleep_out = 5,
102 .hw_reset = 5,
103 .enable_te = 100, /* possible panel bug */
104 },
105 .reset_sequence = {
106 .high = 10,
107 .low = 10,
108 },
109 },
110};
111
112struct taal_data { 57struct taal_data {
113 struct mutex lock; 58 struct mutex lock;
114 59
@@ -121,9 +66,6 @@ struct taal_data {
121 66
122 struct omap_dss_device *dssdev; 67 struct omap_dss_device *dssdev;
123 68
124 /* panel specific HW info */
125 struct panel_config *panel_config;
126
127 /* panel HW configuration from DT or platform data */ 69 /* panel HW configuration from DT or platform data */
128 int reset_gpio; 70 int reset_gpio;
129 int ext_te_gpio; 71 int ext_te_gpio;
@@ -134,8 +76,6 @@ struct taal_data {
134 76
135 /* runtime variables */ 77 /* runtime variables */
136 bool enabled; 78 bool enabled;
137 u8 rotate;
138 bool mirror;
139 79
140 bool te_enabled; 80 bool te_enabled;
141 81
@@ -221,8 +161,7 @@ static int taal_sleep_in(struct taal_data *td)
221 161
222 hw_guard_start(td, 120); 162 hw_guard_start(td, 120);
223 163
224 if (td->panel_config->sleep.sleep_in) 164 msleep(5);
225 msleep(td->panel_config->sleep.sleep_in);
226 165
227 return 0; 166 return 0;
228} 167}
@@ -239,8 +178,7 @@ static int taal_sleep_out(struct taal_data *td)
239 178
240 hw_guard_start(td, 120); 179 hw_guard_start(td, 120);
241 180
242 if (td->panel_config->sleep.sleep_out) 181 msleep(5);
243 msleep(td->panel_config->sleep.sleep_out);
244 182
245 return 0; 183 return 0;
246} 184}
@@ -262,49 +200,6 @@ static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3)
262 return 0; 200 return 0;
263} 201}
264 202
265static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
266{
267 int r;
268 u8 mode;
269 int b5, b6, b7;
270
271 r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);
272 if (r)
273 return r;
274
275 switch (rotate) {
276 default:
277 case 0:
278 b7 = 0;
279 b6 = 0;
280 b5 = 0;
281 break;
282 case 1:
283 b7 = 0;
284 b6 = 1;
285 b5 = 1;
286 break;
287 case 2:
288 b7 = 1;
289 b6 = 1;
290 b5 = 0;
291 break;
292 case 3:
293 b7 = 1;
294 b6 = 0;
295 b5 = 1;
296 break;
297 }
298
299 if (mirror)
300 b6 = !b6;
301
302 mode &= ~((1<<7) | (1<<6) | (1<<5));
303 mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
304
305 return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);
306}
307
308static int taal_set_update_window(struct taal_data *td, 203static int taal_set_update_window(struct taal_data *td,
309 u16 x, u16 y, u16 w, u16 h) 204 u16 x, u16 y, u16 w, u16 h)
310{ 205{
@@ -515,15 +410,8 @@ static const struct backlight_ops taal_bl_ops = {
515static void taal_get_resolution(struct omap_dss_device *dssdev, 410static void taal_get_resolution(struct omap_dss_device *dssdev,
516 u16 *xres, u16 *yres) 411 u16 *xres, u16 *yres)
517{ 412{
518 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 413 *xres = dssdev->panel.timings.x_res;
519 414 *yres = dssdev->panel.timings.y_res;
520 if (td->rotate == 0 || td->rotate == 2) {
521 *xres = dssdev->panel.timings.x_res;
522 *yres = dssdev->panel.timings.y_res;
523 } else {
524 *yres = dssdev->panel.timings.x_res;
525 *xres = dssdev->panel.timings.y_res;
526 }
527} 415}
528 416
529static ssize_t taal_num_errors_show(struct device *dev, 417static ssize_t taal_num_errors_show(struct device *dev,
@@ -845,17 +733,14 @@ static void taal_hw_reset(struct omap_dss_device *dssdev)
845 return; 733 return;
846 734
847 gpio_set_value(td->reset_gpio, 1); 735 gpio_set_value(td->reset_gpio, 1);
848 if (td->panel_config->reset_sequence.high) 736 udelay(10);
849 udelay(td->panel_config->reset_sequence.high);
850 /* reset the panel */ 737 /* reset the panel */
851 gpio_set_value(td->reset_gpio, 0); 738 gpio_set_value(td->reset_gpio, 0);
852 /* assert reset */ 739 /* assert reset */
853 if (td->panel_config->reset_sequence.low) 740 udelay(10);
854 udelay(td->panel_config->reset_sequence.low);
855 gpio_set_value(td->reset_gpio, 1); 741 gpio_set_value(td->reset_gpio, 1);
856 /* wait after releasing reset */ 742 /* wait after releasing reset */
857 if (td->panel_config->sleep.hw_reset) 743 msleep(5);
858 msleep(td->panel_config->sleep.hw_reset);
859} 744}
860 745
861static void taal_probe_pdata(struct taal_data *td, 746static void taal_probe_pdata(struct taal_data *td,
@@ -881,8 +766,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
881 struct backlight_properties props; 766 struct backlight_properties props;
882 struct taal_data *td; 767 struct taal_data *td;
883 struct backlight_device *bldev = NULL; 768 struct backlight_device *bldev = NULL;
884 int r, i; 769 int r;
885 const char *panel_name;
886 770
887 dev_dbg(&dssdev->dev, "probe\n"); 771 dev_dbg(&dssdev->dev, "probe\n");
888 772
@@ -897,26 +781,13 @@ static int taal_probe(struct omap_dss_device *dssdev)
897 const struct nokia_dsi_panel_data *pdata = dssdev->data; 781 const struct nokia_dsi_panel_data *pdata = dssdev->data;
898 782
899 taal_probe_pdata(td, pdata); 783 taal_probe_pdata(td, pdata);
900
901 panel_name = pdata->name;
902 } else { 784 } else {
903 return -ENODEV; 785 return -ENODEV;
904 } 786 }
905 787
906 if (panel_name == NULL) 788 dssdev->panel.timings.x_res = 864;
907 return -EINVAL; 789 dssdev->panel.timings.y_res = 480;
908 790 dssdev->panel.timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000);
909 for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
910 if (strcmp(panel_name, panel_configs[i].name) == 0) {
911 td->panel_config = &panel_configs[i];
912 break;
913 }
914 }
915
916 if (!td->panel_config)
917 return -EINVAL;
918
919 dssdev->panel.timings = td->panel_config->timings;
920 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; 791 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
921 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | 792 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
922 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; 793 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
@@ -1049,6 +920,15 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1049 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 920 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1050 u8 id1, id2, id3; 921 u8 id1, id2, id3;
1051 int r; 922 int r;
923 struct omap_dss_dsi_config dsi_config = {
924 .mode = OMAP_DSS_DSI_CMD_MODE,
925 .pixel_format = OMAP_DSS_DSI_FMT_RGB888,
926 .timings = &dssdev->panel.timings,
927 .hs_clk_min = 150000000,
928 .hs_clk_max = 300000000,
929 .lp_clk_min = 7000000,
930 .lp_clk_max = 10000000,
931 };
1052 932
1053 r = omapdss_dsi_configure_pins(dssdev, &td->pin_config); 933 r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
1054 if (r) { 934 if (r) {
@@ -1056,14 +936,9 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1056 goto err0; 936 goto err0;
1057 }; 937 };
1058 938
1059 omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res, 939 r = omapdss_dsi_set_config(dssdev, &dsi_config);
1060 dssdev->panel.timings.y_res);
1061 omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
1062 omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
1063
1064 r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
1065 if (r) { 940 if (r) {
1066 dev_err(&dssdev->dev, "failed to set HS and LP clocks\n"); 941 dev_err(&dssdev->dev, "failed to configure DSI\n");
1067 goto err0; 942 goto err0;
1068 } 943 }
1069 944
@@ -1086,8 +961,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1086 goto err; 961 goto err;
1087 962
1088 /* on early Taal revisions CABC is broken */ 963 /* on early Taal revisions CABC is broken */
1089 if (td->panel_config->type == PANEL_TAAL && 964 if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
1090 (id2 == 0x00 || id2 == 0xff || id2 == 0x81))
1091 td->cabc_broken = true; 965 td->cabc_broken = true;
1092 966
1093 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff); 967 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff);
@@ -1104,10 +978,6 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1104 if (r) 978 if (r)
1105 goto err; 979 goto err;
1106 980
1107 r = taal_set_addr_mode(td, td->rotate, td->mirror);
1108 if (r)
1109 goto err;
1110
1111 if (!td->cabc_broken) { 981 if (!td->cabc_broken) {
1112 r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode); 982 r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode);
1113 if (r) 983 if (r)
@@ -1129,8 +999,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1129 td->enabled = 1; 999 td->enabled = 1;
1130 1000
1131 if (!td->intro_printed) { 1001 if (!td->intro_printed) {
1132 dev_info(&dssdev->dev, "%s panel revision %02x.%02x.%02x\n", 1002 dev_info(&dssdev->dev, "panel revision %02x.%02x.%02x\n",
1133 td->panel_config->name, id1, id2, id3); 1003 id1, id2, id3);
1134 if (td->cabc_broken) 1004 if (td->cabc_broken)
1135 dev_info(&dssdev->dev, 1005 dev_info(&dssdev->dev,
1136 "old Taal version, CABC disabled\n"); 1006 "old Taal version, CABC disabled\n");
@@ -1311,8 +1181,8 @@ static int taal_update(struct omap_dss_device *dssdev,
1311 1181
1312 /* XXX no need to send this every frame, but dsi break if not done */ 1182 /* XXX no need to send this every frame, but dsi break if not done */
1313 r = taal_set_update_window(td, 0, 0, 1183 r = taal_set_update_window(td, 0, 0,
1314 td->panel_config->timings.x_res, 1184 dssdev->panel.timings.x_res,
1315 td->panel_config->timings.y_res); 1185 dssdev->panel.timings.y_res);
1316 if (r) 1186 if (r)
1317 goto err; 1187 goto err;
1318 1188
@@ -1365,8 +1235,8 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1365 if (!gpio_is_valid(td->ext_te_gpio)) 1235 if (!gpio_is_valid(td->ext_te_gpio))
1366 omapdss_dsi_enable_te(dssdev, enable); 1236 omapdss_dsi_enable_te(dssdev, enable);
1367 1237
1368 if (td->panel_config->sleep.enable_te) 1238 /* possible panel bug */
1369 msleep(td->panel_config->sleep.enable_te); 1239 msleep(100);
1370 1240
1371 return r; 1241 return r;
1372} 1242}
@@ -1419,112 +1289,6 @@ static int taal_get_te(struct omap_dss_device *dssdev)
1419 return r; 1289 return r;
1420} 1290}
1421 1291
1422static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
1423{
1424 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1425 u16 dw, dh;
1426 int r;
1427
1428 dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
1429
1430 mutex_lock(&td->lock);
1431
1432 if (td->rotate == rotate)
1433 goto end;
1434
1435 dsi_bus_lock(dssdev);
1436
1437 if (td->enabled) {
1438 r = taal_wake_up(dssdev);
1439 if (r)
1440 goto err;
1441
1442 r = taal_set_addr_mode(td, rotate, td->mirror);
1443 if (r)
1444 goto err;
1445 }
1446
1447 if (rotate == 0 || rotate == 2) {
1448 dw = dssdev->panel.timings.x_res;
1449 dh = dssdev->panel.timings.y_res;
1450 } else {
1451 dw = dssdev->panel.timings.y_res;
1452 dh = dssdev->panel.timings.x_res;
1453 }
1454
1455 omapdss_dsi_set_size(dssdev, dw, dh);
1456
1457 td->rotate = rotate;
1458
1459 dsi_bus_unlock(dssdev);
1460end:
1461 mutex_unlock(&td->lock);
1462 return 0;
1463err:
1464 dsi_bus_unlock(dssdev);
1465 mutex_unlock(&td->lock);
1466 return r;
1467}
1468
1469static u8 taal_get_rotate(struct omap_dss_device *dssdev)
1470{
1471 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1472 int r;
1473
1474 mutex_lock(&td->lock);
1475 r = td->rotate;
1476 mutex_unlock(&td->lock);
1477
1478 return r;
1479}
1480
1481static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
1482{
1483 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1484 int r;
1485
1486 dev_dbg(&dssdev->dev, "mirror %d\n", enable);
1487
1488 mutex_lock(&td->lock);
1489
1490 if (td->mirror == enable)
1491 goto end;
1492
1493 dsi_bus_lock(dssdev);
1494 if (td->enabled) {
1495 r = taal_wake_up(dssdev);
1496 if (r)
1497 goto err;
1498
1499 r = taal_set_addr_mode(td, td->rotate, enable);
1500 if (r)
1501 goto err;
1502 }
1503
1504 td->mirror = enable;
1505
1506 dsi_bus_unlock(dssdev);
1507end:
1508 mutex_unlock(&td->lock);
1509 return 0;
1510err:
1511 dsi_bus_unlock(dssdev);
1512 mutex_unlock(&td->lock);
1513 return r;
1514}
1515
1516static bool taal_get_mirror(struct omap_dss_device *dssdev)
1517{
1518 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1519 int r;
1520
1521 mutex_lock(&td->lock);
1522 r = td->mirror;
1523 mutex_unlock(&td->lock);
1524
1525 return r;
1526}
1527
1528static int taal_run_test(struct omap_dss_device *dssdev, int test_num) 1292static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
1529{ 1293{
1530 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1294 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
@@ -1758,10 +1522,6 @@ static struct omap_dss_driver taal_driver = {
1758 .enable_te = taal_enable_te, 1522 .enable_te = taal_enable_te,
1759 .get_te = taal_get_te, 1523 .get_te = taal_get_te,
1760 1524
1761 .set_rotate = taal_rotate,
1762 .get_rotate = taal_get_rotate,
1763 .set_mirror = taal_mirror,
1764 .get_mirror = taal_get_mirror,
1765 .run_test = taal_run_test, 1525 .run_test = taal_run_test,
1766 .memory_read = taal_memory_read, 1526 .memory_read = taal_memory_read,
1767 1527
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
index 8281baafe1ef..46039c4bf1ed 100644
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -24,7 +24,7 @@
24#include <linux/gpio.h> 24#include <linux/gpio.h>
25#include <drm/drm_edid.h> 25#include <drm/drm_edid.h>
26 26
27#include <video/omap-panel-tfp410.h> 27#include <video/omap-panel-data.h>
28 28
29static const struct omap_video_timings tfp410_default_timings = { 29static const struct omap_video_timings tfp410_default_timings = {
30 .x_res = 640, 30 .x_res = 640,
@@ -135,7 +135,7 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
135 if (!adapter) { 135 if (!adapter) {
136 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n", 136 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
137 i2c_bus_num); 137 i2c_bus_num);
138 return -EINVAL; 138 return -EPROBE_DEFER;
139 } 139 }
140 140
141 ddata->i2c_adapter = adapter; 141 ddata->i2c_adapter = adapter;
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index 048c98381ef6..abf2bc4a18ab 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -18,6 +18,7 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19 19
20#include <video/omapdss.h> 20#include <video/omapdss.h>
21#include <video/omap-panel-data.h>
21 22
22#define TPO_R02_MODE(x) ((x) & 7) 23#define TPO_R02_MODE(x) ((x) & 7)
23#define TPO_R02_MODE_800x480 7 24#define TPO_R02_MODE_800x480 7
@@ -278,9 +279,14 @@ static const struct omap_video_timings tpo_td043_timings = {
278 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, 279 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
279}; 280};
280 281
282static inline struct panel_tpo_td043_data
283*get_panel_data(const struct omap_dss_device *dssdev)
284{
285 return (struct panel_tpo_td043_data *) dssdev->data;
286}
287
281static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) 288static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
282{ 289{
283 int nreset_gpio = tpo_td043->nreset_gpio;
284 int r; 290 int r;
285 291
286 if (tpo_td043->powered_on) 292 if (tpo_td043->powered_on)
@@ -293,8 +299,8 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
293 /* wait for panel to stabilize */ 299 /* wait for panel to stabilize */
294 msleep(160); 300 msleep(160);
295 301
296 if (gpio_is_valid(nreset_gpio)) 302 if (gpio_is_valid(tpo_td043->nreset_gpio))
297 gpio_set_value(nreset_gpio, 1); 303 gpio_set_value(tpo_td043->nreset_gpio, 1);
298 304
299 tpo_td043_write(tpo_td043->spi, 2, 305 tpo_td043_write(tpo_td043->spi, 2,
300 TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING); 306 TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING);
@@ -311,16 +317,14 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
311 317
312static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043) 318static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043)
313{ 319{
314 int nreset_gpio = tpo_td043->nreset_gpio;
315
316 if (!tpo_td043->powered_on) 320 if (!tpo_td043->powered_on)
317 return; 321 return;
318 322
319 tpo_td043_write(tpo_td043->spi, 3, 323 tpo_td043_write(tpo_td043->spi, 3,
320 TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM); 324 TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
321 325
322 if (gpio_is_valid(nreset_gpio)) 326 if (gpio_is_valid(tpo_td043->nreset_gpio))
323 gpio_set_value(nreset_gpio, 0); 327 gpio_set_value(tpo_td043->nreset_gpio, 0);
324 328
325 /* wait for at least 2 vsyncs before cutting off power */ 329 /* wait for at least 2 vsyncs before cutting off power */
326 msleep(50); 330 msleep(50);
@@ -347,12 +351,6 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
347 if (r) 351 if (r)
348 goto err0; 352 goto err0;
349 353
350 if (dssdev->platform_enable) {
351 r = dssdev->platform_enable(dssdev);
352 if (r)
353 goto err1;
354 }
355
356 /* 354 /*
357 * If we are resuming from system suspend, SPI clocks might not be 355 * If we are resuming from system suspend, SPI clocks might not be
358 * enabled yet, so we'll program the LCD from SPI PM resume callback. 356 * enabled yet, so we'll program the LCD from SPI PM resume callback.
@@ -379,9 +377,6 @@ static void tpo_td043_disable_dss(struct omap_dss_device *dssdev)
379 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 377 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
380 return; 378 return;
381 379
382 if (dssdev->platform_disable)
383 dssdev->platform_disable(dssdev);
384
385 omapdss_dpi_display_disable(dssdev); 380 omapdss_dpi_display_disable(dssdev);
386 381
387 if (!tpo_td043->spi_suspended) 382 if (!tpo_td043->spi_suspended)
@@ -407,7 +402,7 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
407static int tpo_td043_probe(struct omap_dss_device *dssdev) 402static int tpo_td043_probe(struct omap_dss_device *dssdev)
408{ 403{
409 struct tpo_td043_device *tpo_td043 = g_tpo_td043; 404 struct tpo_td043_device *tpo_td043 = g_tpo_td043;
410 int nreset_gpio = dssdev->reset_gpio; 405 struct panel_tpo_td043_data *pdata = get_panel_data(dssdev);
411 int ret = 0; 406 int ret = 0;
412 407
413 dev_dbg(&dssdev->dev, "probe\n"); 408 dev_dbg(&dssdev->dev, "probe\n");
@@ -417,6 +412,11 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
417 return -ENODEV; 412 return -ENODEV;
418 } 413 }
419 414
415 if (!pdata)
416 return -EINVAL;
417
418 tpo_td043->nreset_gpio = pdata->nreset_gpio;
419
420 dssdev->panel.timings = tpo_td043_timings; 420 dssdev->panel.timings = tpo_td043_timings;
421 dssdev->ctrl.pixel_size = 24; 421 dssdev->ctrl.pixel_size = 24;
422 422
@@ -430,9 +430,10 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
430 goto fail_regulator; 430 goto fail_regulator;
431 } 431 }
432 432
433 if (gpio_is_valid(nreset_gpio)) { 433 if (gpio_is_valid(tpo_td043->nreset_gpio)) {
434 ret = gpio_request_one(nreset_gpio, GPIOF_OUT_INIT_LOW, 434 ret = devm_gpio_request_one(&dssdev->dev,
435 "lcd reset"); 435 tpo_td043->nreset_gpio, GPIOF_OUT_INIT_LOW,
436 "lcd reset");
436 if (ret < 0) { 437 if (ret < 0) {
437 dev_err(&dssdev->dev, "couldn't request reset GPIO\n"); 438 dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
438 goto fail_gpio_req; 439 goto fail_gpio_req;
@@ -457,14 +458,11 @@ fail_regulator:
457static void tpo_td043_remove(struct omap_dss_device *dssdev) 458static void tpo_td043_remove(struct omap_dss_device *dssdev)
458{ 459{
459 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); 460 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
460 int nreset_gpio = dssdev->reset_gpio;
461 461
462 dev_dbg(&dssdev->dev, "remove\n"); 462 dev_dbg(&dssdev->dev, "remove\n");
463 463
464 sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group); 464 sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
465 regulator_put(tpo_td043->vcc_reg); 465 regulator_put(tpo_td043->vcc_reg);
466 if (gpio_is_valid(nreset_gpio))
467 gpio_free(nreset_gpio);
468} 466}
469 467
470static void tpo_td043_set_timings(struct omap_dss_device *dssdev, 468static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
@@ -527,7 +525,6 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
527 return -ENOMEM; 525 return -ENOMEM;
528 526
529 tpo_td043->spi = spi; 527 tpo_td043->spi = spi;
530 tpo_td043->nreset_gpio = dssdev->reset_gpio;
531 dev_set_drvdata(&spi->dev, tpo_td043); 528 dev_set_drvdata(&spi->dev, tpo_td043);
532 g_tpo_td043 = tpo_td043; 529 g_tpo_td043 = tpo_td043;
533 530
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index d446bdfc4c82..a4b356a9780d 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -435,20 +435,27 @@ static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_man
435static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) 435static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
436{ 436{
437 unsigned long timeout = msecs_to_jiffies(500); 437 unsigned long timeout = msecs_to_jiffies(500);
438 struct omap_dss_device *dssdev = mgr->get_device(mgr);
439 u32 irq; 438 u32 irq;
440 int r; 439 int r;
441 440
441 if (mgr->output == NULL)
442 return -ENODEV;
443
442 r = dispc_runtime_get(); 444 r = dispc_runtime_get();
443 if (r) 445 if (r)
444 return r; 446 return r;
445 447
446 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) 448 switch (mgr->output->id) {
449 case OMAP_DSS_OUTPUT_VENC:
447 irq = DISPC_IRQ_EVSYNC_ODD; 450 irq = DISPC_IRQ_EVSYNC_ODD;
448 else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI) 451 break;
452 case OMAP_DSS_OUTPUT_HDMI:
449 irq = DISPC_IRQ_EVSYNC_EVEN; 453 irq = DISPC_IRQ_EVSYNC_EVEN;
450 else 454 break;
455 default:
451 irq = dispc_mgr_get_vsync_irq(mgr->id); 456 irq = dispc_mgr_get_vsync_irq(mgr->id);
457 break;
458 }
452 459
453 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 460 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
454 461
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index f8779d4750ba..60cc6fee6548 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -181,10 +181,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
181 d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, 181 d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
182 write, &dss_debug_fops); 182 write, &dss_debug_fops);
183 183
184 if (IS_ERR(d)) 184 return PTR_RET(d);
185 return PTR_ERR(d);
186
187 return 0;
188} 185}
189#else /* CONFIG_OMAP2_DSS_DEBUGFS */ 186#else /* CONFIG_OMAP2_DSS_DEBUGFS */
190static inline int dss_initialize_debugfs(void) 187static inline int dss_initialize_debugfs(void)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 05ff2b91d9e8..b33b0169bb3b 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -69,6 +69,8 @@ struct dispc_features {
69 u8 mgr_height_start; 69 u8 mgr_height_start;
70 u16 mgr_width_max; 70 u16 mgr_width_max;
71 u16 mgr_height_max; 71 u16 mgr_height_max;
72 unsigned long max_lcd_pclk;
73 unsigned long max_tv_pclk;
72 int (*calc_scaling) (unsigned long pclk, unsigned long lclk, 74 int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
73 const struct omap_video_timings *mgr_timings, 75 const struct omap_video_timings *mgr_timings,
74 u16 width, u16 height, u16 out_width, u16 out_height, 76 u16 width, u16 height, u16 out_width, u16 out_height,
@@ -85,6 +87,9 @@ struct dispc_features {
85 87
86 /* no DISPC_IRQ_FRAMEDONETV on this SoC */ 88 /* no DISPC_IRQ_FRAMEDONETV on this SoC */
87 bool no_framedone_tv:1; 89 bool no_framedone_tv:1;
90
91 /* revert to the OMAP4 mechanism of DISPC Smart Standby operation */
92 bool mstandby_workaround:1;
88}; 93};
89 94
90#define DISPC_MAX_NR_FIFOS 5 95#define DISPC_MAX_NR_FIFOS 5
@@ -97,6 +102,8 @@ static struct {
97 102
98 int irq; 103 int irq;
99 104
105 unsigned long core_clk_rate;
106
100 u32 fifo_size[DISPC_MAX_NR_FIFOS]; 107 u32 fifo_size[DISPC_MAX_NR_FIFOS];
101 /* maps which plane is using a fifo. fifo-id -> plane-id */ 108 /* maps which plane is using a fifo. fifo-id -> plane-id */
102 int fifo_assignment[DISPC_MAX_NR_FIFOS]; 109 int fifo_assignment[DISPC_MAX_NR_FIFOS];
@@ -1584,6 +1591,7 @@ static void dispc_ovl_set_scaling(enum omap_plane plane,
1584} 1591}
1585 1592
1586static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, 1593static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1594 enum omap_dss_rotation_type rotation_type,
1587 bool mirroring, enum omap_color_mode color_mode) 1595 bool mirroring, enum omap_color_mode color_mode)
1588{ 1596{
1589 bool row_repeat = false; 1597 bool row_repeat = false;
@@ -1634,6 +1642,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1634 if (dss_has_feature(FEAT_ROWREPEATENABLE)) 1642 if (dss_has_feature(FEAT_ROWREPEATENABLE))
1635 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 1643 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
1636 row_repeat ? 1 : 0, 18, 18); 1644 row_repeat ? 1 : 0, 18, 18);
1645
1646 if (color_mode == OMAP_DSS_COLOR_NV12) {
1647 bool doublestride = (rotation_type == OMAP_DSS_ROT_TILER) &&
1648 (rotation == OMAP_DSS_ROT_0 ||
1649 rotation == OMAP_DSS_ROT_180);
1650 /* DOUBLESTRIDE */
1651 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), doublestride, 22, 22);
1652 }
1653
1637} 1654}
1638 1655
1639static int color_mode_to_bpp(enum omap_color_mode color_mode) 1656static int color_mode_to_bpp(enum omap_color_mode color_mode)
@@ -2512,7 +2529,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
2512 dispc_ovl_set_vid_color_conv(plane, cconv); 2529 dispc_ovl_set_vid_color_conv(plane, cconv);
2513 } 2530 }
2514 2531
2515 dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode); 2532 dispc_ovl_set_rotation_attrs(plane, rotation, rotation_type, mirror,
2533 color_mode);
2516 2534
2517 dispc_ovl_set_zorder(plane, caps, zorder); 2535 dispc_ovl_set_zorder(plane, caps, zorder);
2518 dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha); 2536 dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
@@ -2823,6 +2841,15 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2823 return true; 2841 return true;
2824} 2842}
2825 2843
2844static bool _dispc_mgr_pclk_ok(enum omap_channel channel,
2845 unsigned long pclk)
2846{
2847 if (dss_mgr_is_lcd(channel))
2848 return pclk <= dispc.feat->max_lcd_pclk ? true : false;
2849 else
2850 return pclk <= dispc.feat->max_tv_pclk ? true : false;
2851}
2852
2826bool dispc_mgr_timings_ok(enum omap_channel channel, 2853bool dispc_mgr_timings_ok(enum omap_channel channel,
2827 const struct omap_video_timings *timings) 2854 const struct omap_video_timings *timings)
2828{ 2855{
@@ -2830,11 +2857,13 @@ bool dispc_mgr_timings_ok(enum omap_channel channel,
2830 2857
2831 timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res); 2858 timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res);
2832 2859
2833 if (dss_mgr_is_lcd(channel)) 2860 timings_ok &= _dispc_mgr_pclk_ok(channel, timings->pixel_clock * 1000);
2834 timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw, 2861
2835 timings->hfp, timings->hbp, 2862 if (dss_mgr_is_lcd(channel)) {
2836 timings->vsw, timings->vfp, 2863 timings_ok &= _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
2837 timings->vbp); 2864 timings->hbp, timings->vsw, timings->vfp,
2865 timings->vbp);
2866 }
2838 2867
2839 return timings_ok; 2868 return timings_ok;
2840} 2869}
@@ -2951,6 +2980,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
2951 2980
2952 dispc_write_reg(DISPC_DIVISORo(channel), 2981 dispc_write_reg(DISPC_DIVISORo(channel),
2953 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); 2982 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
2983
2984 if (dss_has_feature(FEAT_CORE_CLK_DIV) == false &&
2985 channel == OMAP_DSS_CHANNEL_LCD)
2986 dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
2954} 2987}
2955 2988
2956static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div, 2989static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -3056,15 +3089,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
3056 3089
3057unsigned long dispc_core_clk_rate(void) 3090unsigned long dispc_core_clk_rate(void)
3058{ 3091{
3059 int lcd; 3092 return dispc.core_clk_rate;
3060 unsigned long fclk = dispc_fclk_rate();
3061
3062 if (dss_has_feature(FEAT_CORE_CLK_DIV))
3063 lcd = REG_GET(DISPC_DIVISOR, 23, 16);
3064 else
3065 lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
3066
3067 return fclk / lcd;
3068} 3093}
3069 3094
3070static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) 3095static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
@@ -3313,67 +3338,79 @@ static void dispc_dump_regs(struct seq_file *s)
3313#undef DUMPREG 3338#undef DUMPREG
3314} 3339}
3315 3340
3316/* with fck as input clock rate, find dispc dividers that produce req_pck */ 3341/* calculate clock rates using dividers in cinfo */
3317void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck, 3342int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
3318 struct dispc_clock_info *cinfo) 3343 struct dispc_clock_info *cinfo)
3319{ 3344{
3320 u16 pcd_min, pcd_max; 3345 if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
3321 unsigned long best_pck; 3346 return -EINVAL;
3322 u16 best_ld, cur_ld; 3347 if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
3323 u16 best_pd, cur_pd; 3348 return -EINVAL;
3324 3349
3325 pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); 3350 cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
3326 pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); 3351 cinfo->pck = cinfo->lck / cinfo->pck_div;
3327 3352
3328 best_pck = 0; 3353 return 0;
3329 best_ld = 0; 3354}
3330 best_pd = 0;
3331 3355
3332 for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { 3356bool dispc_div_calc(unsigned long dispc,
3333 unsigned long lck = fck / cur_ld; 3357 unsigned long pck_min, unsigned long pck_max,
3358 dispc_div_calc_func func, void *data)
3359{
3360 int lckd, lckd_start, lckd_stop;
3361 int pckd, pckd_start, pckd_stop;
3362 unsigned long pck, lck;
3363 unsigned long lck_max;
3364 unsigned long pckd_hw_min, pckd_hw_max;
3365 unsigned min_fck_per_pck;
3366 unsigned long fck;
3334 3367
3335 for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) { 3368#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK
3336 unsigned long pck = lck / cur_pd; 3369 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
3337 long old_delta = abs(best_pck - req_pck); 3370#else
3338 long new_delta = abs(pck - req_pck); 3371 min_fck_per_pck = 0;
3372#endif
3339 3373
3340 if (best_pck == 0 || new_delta < old_delta) { 3374 pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
3341 best_pck = pck; 3375 pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
3342 best_ld = cur_ld;
3343 best_pd = cur_pd;
3344 3376
3345 if (pck == req_pck) 3377 lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
3346 goto found;
3347 }
3348 3378
3349 if (pck < req_pck) 3379 pck_min = pck_min ? pck_min : 1;
3350 break; 3380 pck_max = pck_max ? pck_max : ULONG_MAX;
3351 }
3352 3381
3353 if (lck / pcd_min < req_pck) 3382 lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul);
3354 break; 3383 lckd_stop = min(dispc / pck_min, 255ul);
3355 }
3356 3384
3357found: 3385 for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) {
3358 cinfo->lck_div = best_ld; 3386 lck = dispc / lckd;
3359 cinfo->pck_div = best_pd;
3360 cinfo->lck = fck / cinfo->lck_div;
3361 cinfo->pck = cinfo->lck / cinfo->pck_div;
3362}
3363 3387
3364/* calculate clock rates using dividers in cinfo */ 3388 pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min);
3365int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, 3389 pckd_stop = min(lck / pck_min, pckd_hw_max);
3366 struct dispc_clock_info *cinfo)
3367{
3368 if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
3369 return -EINVAL;
3370 if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
3371 return -EINVAL;
3372 3390
3373 cinfo->lck = dispc_fclk_rate / cinfo->lck_div; 3391 for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) {
3374 cinfo->pck = cinfo->lck / cinfo->pck_div; 3392 pck = lck / pckd;
3375 3393
3376 return 0; 3394 /*
3395 * For OMAP2/3 the DISPC fclk is the same as LCD's logic
3396 * clock, which means we're configuring DISPC fclk here
3397 * also. Thus we need to use the calculated lck. For
3398 * OMAP4+ the DISPC fclk is a separate clock.
3399 */
3400 if (dss_has_feature(FEAT_CORE_CLK_DIV))
3401 fck = dispc_core_clk_rate();
3402 else
3403 fck = lck;
3404
3405 if (fck < pck * min_fck_per_pck)
3406 continue;
3407
3408 if (func(lckd, pckd, lck, pck, data))
3409 return true;
3410 }
3411 }
3412
3413 return false;
3377} 3414}
3378 3415
3379void dispc_mgr_set_clock_div(enum omap_channel channel, 3416void dispc_mgr_set_clock_div(enum omap_channel channel,
@@ -3451,6 +3488,8 @@ static void _omap_dispc_initial_config(void)
3451 l = FLD_MOD(l, 1, 0, 0); 3488 l = FLD_MOD(l, 1, 0, 0);
3452 l = FLD_MOD(l, 1, 23, 16); 3489 l = FLD_MOD(l, 1, 23, 16);
3453 dispc_write_reg(DISPC_DIVISOR, l); 3490 dispc_write_reg(DISPC_DIVISOR, l);
3491
3492 dispc.core_clk_rate = dispc_fclk_rate();
3454 } 3493 }
3455 3494
3456 /* FUNCGATED */ 3495 /* FUNCGATED */
@@ -3466,6 +3505,9 @@ static void _omap_dispc_initial_config(void)
3466 dispc_configure_burst_sizes(); 3505 dispc_configure_burst_sizes();
3467 3506
3468 dispc_ovl_enable_zorder_planes(); 3507 dispc_ovl_enable_zorder_planes();
3508
3509 if (dispc.feat->mstandby_workaround)
3510 REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0);
3469} 3511}
3470 3512
3471static const struct dispc_features omap24xx_dispc_feats __initconst = { 3513static const struct dispc_features omap24xx_dispc_feats __initconst = {
@@ -3479,6 +3521,7 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
3479 .mgr_height_start = 26, 3521 .mgr_height_start = 26,
3480 .mgr_width_max = 2048, 3522 .mgr_width_max = 2048,
3481 .mgr_height_max = 2048, 3523 .mgr_height_max = 2048,
3524 .max_lcd_pclk = 66500000,
3482 .calc_scaling = dispc_ovl_calc_scaling_24xx, 3525 .calc_scaling = dispc_ovl_calc_scaling_24xx,
3483 .calc_core_clk = calc_core_clk_24xx, 3526 .calc_core_clk = calc_core_clk_24xx,
3484 .num_fifos = 3, 3527 .num_fifos = 3,
@@ -3496,6 +3539,8 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
3496 .mgr_height_start = 26, 3539 .mgr_height_start = 26,
3497 .mgr_width_max = 2048, 3540 .mgr_width_max = 2048,
3498 .mgr_height_max = 2048, 3541 .mgr_height_max = 2048,
3542 .max_lcd_pclk = 173000000,
3543 .max_tv_pclk = 59000000,
3499 .calc_scaling = dispc_ovl_calc_scaling_34xx, 3544 .calc_scaling = dispc_ovl_calc_scaling_34xx,
3500 .calc_core_clk = calc_core_clk_34xx, 3545 .calc_core_clk = calc_core_clk_34xx,
3501 .num_fifos = 3, 3546 .num_fifos = 3,
@@ -3513,6 +3558,8 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
3513 .mgr_height_start = 26, 3558 .mgr_height_start = 26,
3514 .mgr_width_max = 2048, 3559 .mgr_width_max = 2048,
3515 .mgr_height_max = 2048, 3560 .mgr_height_max = 2048,
3561 .max_lcd_pclk = 173000000,
3562 .max_tv_pclk = 59000000,
3516 .calc_scaling = dispc_ovl_calc_scaling_34xx, 3563 .calc_scaling = dispc_ovl_calc_scaling_34xx,
3517 .calc_core_clk = calc_core_clk_34xx, 3564 .calc_core_clk = calc_core_clk_34xx,
3518 .num_fifos = 3, 3565 .num_fifos = 3,
@@ -3530,6 +3577,8 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
3530 .mgr_height_start = 26, 3577 .mgr_height_start = 26,
3531 .mgr_width_max = 2048, 3578 .mgr_width_max = 2048,
3532 .mgr_height_max = 2048, 3579 .mgr_height_max = 2048,
3580 .max_lcd_pclk = 170000000,
3581 .max_tv_pclk = 185625000,
3533 .calc_scaling = dispc_ovl_calc_scaling_44xx, 3582 .calc_scaling = dispc_ovl_calc_scaling_44xx,
3534 .calc_core_clk = calc_core_clk_44xx, 3583 .calc_core_clk = calc_core_clk_44xx,
3535 .num_fifos = 5, 3584 .num_fifos = 5,
@@ -3547,10 +3596,13 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = {
3547 .mgr_height_start = 27, 3596 .mgr_height_start = 27,
3548 .mgr_width_max = 4096, 3597 .mgr_width_max = 4096,
3549 .mgr_height_max = 4096, 3598 .mgr_height_max = 4096,
3599 .max_lcd_pclk = 170000000,
3600 .max_tv_pclk = 186000000,
3550 .calc_scaling = dispc_ovl_calc_scaling_44xx, 3601 .calc_scaling = dispc_ovl_calc_scaling_44xx,
3551 .calc_core_clk = calc_core_clk_44xx, 3602 .calc_core_clk = calc_core_clk_44xx,
3552 .num_fifos = 5, 3603 .num_fifos = 5,
3553 .gfx_fifo_workaround = true, 3604 .gfx_fifo_workaround = true,
3605 .mstandby_workaround = true,
3554}; 3606};
3555 3607
3556static int __init dispc_init_features(struct platform_device *pdev) 3608static int __init dispc_init_features(struct platform_device *pdev)
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index 222363c6e623..de4863d21ab7 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -39,6 +39,7 @@
39#define DISPC_GLOBAL_BUFFER 0x0800 39#define DISPC_GLOBAL_BUFFER 0x0800
40#define DISPC_CONTROL3 0x0848 40#define DISPC_CONTROL3 0x0848
41#define DISPC_CONFIG3 0x084C 41#define DISPC_CONFIG3 0x084C
42#define DISPC_MSTANDBY_CTRL 0x0858
42 43
43/* DISPC overlay registers */ 44/* DISPC overlay registers */
44#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \ 45#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 4af136a04e53..757b57f7275a 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -63,15 +63,29 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
63 case OMAPDSS_VER_OMAP3630: 63 case OMAPDSS_VER_OMAP3630:
64 case OMAPDSS_VER_AM35xx: 64 case OMAPDSS_VER_AM35xx:
65 return NULL; 65 return NULL;
66 default:
67 break;
68 }
69 66
70 switch (channel) { 67 case OMAPDSS_VER_OMAP4430_ES1:
71 case OMAP_DSS_CHANNEL_LCD: 68 case OMAPDSS_VER_OMAP4430_ES2:
72 return dsi_get_dsidev_from_id(0); 69 case OMAPDSS_VER_OMAP4:
73 case OMAP_DSS_CHANNEL_LCD2: 70 switch (channel) {
74 return dsi_get_dsidev_from_id(1); 71 case OMAP_DSS_CHANNEL_LCD:
72 return dsi_get_dsidev_from_id(0);
73 case OMAP_DSS_CHANNEL_LCD2:
74 return dsi_get_dsidev_from_id(1);
75 default:
76 return NULL;
77 }
78
79 case OMAPDSS_VER_OMAP5:
80 switch (channel) {
81 case OMAP_DSS_CHANNEL_LCD:
82 return dsi_get_dsidev_from_id(0);
83 case OMAP_DSS_CHANNEL_LCD3:
84 return dsi_get_dsidev_from_id(1);
85 default:
86 return NULL;
87 }
88
75 default: 89 default:
76 return NULL; 90 return NULL;
77 } 91 }
@@ -91,75 +105,211 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
91 } 105 }
92} 106}
93 107
94static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, 108struct dpi_clk_calc_ctx {
109 struct platform_device *dsidev;
110
111 /* inputs */
112
113 unsigned long pck_min, pck_max;
114
115 /* outputs */
116
117 struct dsi_clock_info dsi_cinfo;
118 struct dss_clock_info dss_cinfo;
119 struct dispc_clock_info dispc_cinfo;
120};
121
122static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
123 unsigned long pck, void *data)
124{
125 struct dpi_clk_calc_ctx *ctx = data;
126
127 /*
128 * Odd dividers give us uneven duty cycle, causing problem when level
129 * shifted. So skip all odd dividers when the pixel clock is on the
130 * higher side.
131 */
132 if (ctx->pck_min >= 1000000) {
133 if (lckd > 1 && lckd % 2 != 0)
134 return false;
135
136 if (pckd > 1 && pckd % 2 != 0)
137 return false;
138 }
139
140 ctx->dispc_cinfo.lck_div = lckd;
141 ctx->dispc_cinfo.pck_div = pckd;
142 ctx->dispc_cinfo.lck = lck;
143 ctx->dispc_cinfo.pck = pck;
144
145 return true;
146}
147
148
149static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
150 void *data)
151{
152 struct dpi_clk_calc_ctx *ctx = data;
153
154 /*
155 * Odd dividers give us uneven duty cycle, causing problem when level
156 * shifted. So skip all odd dividers when the pixel clock is on the
157 * higher side.
158 */
159 if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 1000000)
160 return false;
161
162 ctx->dsi_cinfo.regm_dispc = regm_dispc;
163 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
164
165 return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
166 dpi_calc_dispc_cb, ctx);
167}
168
169
170static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
171 unsigned long pll,
172 void *data)
173{
174 struct dpi_clk_calc_ctx *ctx = data;
175
176 ctx->dsi_cinfo.regn = regn;
177 ctx->dsi_cinfo.regm = regm;
178 ctx->dsi_cinfo.fint = fint;
179 ctx->dsi_cinfo.clkin4ddr = pll;
180
181 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
182 dpi_calc_hsdiv_cb, ctx);
183}
184
185static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
186{
187 struct dpi_clk_calc_ctx *ctx = data;
188
189 ctx->dss_cinfo.fck = fck;
190 ctx->dss_cinfo.fck_div = fckd;
191
192 return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
193 dpi_calc_dispc_cb, ctx);
194}
195
196static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
197{
198 unsigned long clkin;
199 unsigned long pll_min, pll_max;
200
201 clkin = dsi_get_pll_clkin(dpi.dsidev);
202
203 memset(ctx, 0, sizeof(*ctx));
204 ctx->dsidev = dpi.dsidev;
205 ctx->pck_min = pck - 1000;
206 ctx->pck_max = pck + 1000;
207 ctx->dsi_cinfo.clkin = clkin;
208
209 pll_min = 0;
210 pll_max = 0;
211
212 return dsi_pll_calc(dpi.dsidev, clkin,
213 pll_min, pll_max,
214 dpi_calc_pll_cb, ctx);
215}
216
217static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
218{
219 int i;
220
221 /*
222 * DSS fck gives us very few possibilities, so finding a good pixel
223 * clock may not be possible. We try multiple times to find the clock,
224 * each time widening the pixel clock range we look for, up to
225 * +/- ~15MHz.
226 */
227
228 for (i = 0; i < 25; ++i) {
229 bool ok;
230
231 memset(ctx, 0, sizeof(*ctx));
232 if (pck > 1000 * i * i * i)
233 ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
234 else
235 ctx->pck_min = 0;
236 ctx->pck_max = pck + 1000 * i * i * i;
237
238 ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx);
239 if (ok)
240 return ok;
241 }
242
243 return false;
244}
245
246
247
248static int dpi_set_dsi_clk(enum omap_channel channel,
95 unsigned long pck_req, unsigned long *fck, int *lck_div, 249 unsigned long pck_req, unsigned long *fck, int *lck_div,
96 int *pck_div) 250 int *pck_div)
97{ 251{
98 struct omap_overlay_manager *mgr = dssdev->output->manager; 252 struct dpi_clk_calc_ctx ctx;
99 struct dsi_clock_info dsi_cinfo;
100 struct dispc_clock_info dispc_cinfo;
101 int r; 253 int r;
254 bool ok;
102 255
103 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, pck_req, &dsi_cinfo, 256 ok = dpi_dsi_clk_calc(pck_req, &ctx);
104 &dispc_cinfo); 257 if (!ok)
105 if (r) 258 return -EINVAL;
106 return r;
107 259
108 r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo); 260 r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
109 if (r) 261 if (r)
110 return r; 262 return r;
111 263
112 dss_select_lcd_clk_source(mgr->id, 264 dss_select_lcd_clk_source(channel,
113 dpi_get_alt_clk_src(mgr->id)); 265 dpi_get_alt_clk_src(channel));
114 266
115 dpi.mgr_config.clock_info = dispc_cinfo; 267 dpi.mgr_config.clock_info = ctx.dispc_cinfo;
116 268
117 *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; 269 *fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
118 *lck_div = dispc_cinfo.lck_div; 270 *lck_div = ctx.dispc_cinfo.lck_div;
119 *pck_div = dispc_cinfo.pck_div; 271 *pck_div = ctx.dispc_cinfo.pck_div;
120 272
121 return 0; 273 return 0;
122} 274}
123 275
124static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, 276static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
125 unsigned long pck_req, unsigned long *fck, int *lck_div, 277 int *lck_div, int *pck_div)
126 int *pck_div)
127{ 278{
128 struct dss_clock_info dss_cinfo; 279 struct dpi_clk_calc_ctx ctx;
129 struct dispc_clock_info dispc_cinfo;
130 int r; 280 int r;
281 bool ok;
131 282
132 r = dss_calc_clock_div(pck_req, &dss_cinfo, &dispc_cinfo); 283 ok = dpi_dss_clk_calc(pck_req, &ctx);
133 if (r) 284 if (!ok)
134 return r; 285 return -EINVAL;
135 286
136 r = dss_set_clock_div(&dss_cinfo); 287 r = dss_set_clock_div(&ctx.dss_cinfo);
137 if (r) 288 if (r)
138 return r; 289 return r;
139 290
140 dpi.mgr_config.clock_info = dispc_cinfo; 291 dpi.mgr_config.clock_info = ctx.dispc_cinfo;
141 292
142 *fck = dss_cinfo.fck; 293 *fck = ctx.dss_cinfo.fck;
143 *lck_div = dispc_cinfo.lck_div; 294 *lck_div = ctx.dispc_cinfo.lck_div;
144 *pck_div = dispc_cinfo.pck_div; 295 *pck_div = ctx.dispc_cinfo.pck_div;
145 296
146 return 0; 297 return 0;
147} 298}
148 299
149static int dpi_set_mode(struct omap_dss_device *dssdev) 300static int dpi_set_mode(struct omap_overlay_manager *mgr)
150{ 301{
151 struct omap_video_timings *t = &dpi.timings; 302 struct omap_video_timings *t = &dpi.timings;
152 struct omap_overlay_manager *mgr = dssdev->output->manager;
153 int lck_div = 0, pck_div = 0; 303 int lck_div = 0, pck_div = 0;
154 unsigned long fck = 0; 304 unsigned long fck = 0;
155 unsigned long pck; 305 unsigned long pck;
156 int r = 0; 306 int r = 0;
157 307
158 if (dpi.dsidev) 308 if (dpi.dsidev)
159 r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck, 309 r = dpi_set_dsi_clk(mgr->id, t->pixel_clock * 1000, &fck,
160 &lck_div, &pck_div); 310 &lck_div, &pck_div);
161 else 311 else
162 r = dpi_set_dispc_clk(dssdev, t->pixel_clock * 1000, &fck, 312 r = dpi_set_dispc_clk(t->pixel_clock * 1000, &fck,
163 &lck_div, &pck_div); 313 &lck_div, &pck_div);
164 if (r) 314 if (r)
165 return r; 315 return r;
@@ -179,10 +329,8 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
179 return 0; 329 return 0;
180} 330}
181 331
182static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) 332static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr)
183{ 333{
184 struct omap_overlay_manager *mgr = dssdev->output->manager;
185
186 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 334 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
187 335
188 dpi.mgr_config.stallmode = false; 336 dpi.mgr_config.stallmode = false;
@@ -197,7 +345,7 @@ static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
197 345
198int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) 346int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
199{ 347{
200 struct omap_dss_output *out = dssdev->output; 348 struct omap_dss_output *out = &dpi.output;
201 int r; 349 int r;
202 350
203 mutex_lock(&dpi.lock); 351 mutex_lock(&dpi.lock);
@@ -230,7 +378,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
230 if (r) 378 if (r)
231 goto err_get_dispc; 379 goto err_get_dispc;
232 380
233 r = dss_dpi_select_source(dssdev->channel); 381 r = dss_dpi_select_source(out->manager->id);
234 if (r) 382 if (r)
235 goto err_src_sel; 383 goto err_src_sel;
236 384
@@ -244,11 +392,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
244 goto err_dsi_pll_init; 392 goto err_dsi_pll_init;
245 } 393 }
246 394
247 r = dpi_set_mode(dssdev); 395 r = dpi_set_mode(out->manager);
248 if (r) 396 if (r)
249 goto err_set_mode; 397 goto err_set_mode;
250 398
251 dpi_config_lcd_manager(dssdev); 399 dpi_config_lcd_manager(out->manager);
252 400
253 mdelay(2); 401 mdelay(2);
254 402
@@ -285,7 +433,7 @@ EXPORT_SYMBOL(omapdss_dpi_display_enable);
285 433
286void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) 434void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
287{ 435{
288 struct omap_overlay_manager *mgr = dssdev->output->manager; 436 struct omap_overlay_manager *mgr = dpi.output.manager;
289 437
290 mutex_lock(&dpi.lock); 438 mutex_lock(&dpi.lock);
291 439
@@ -324,12 +472,12 @@ EXPORT_SYMBOL(omapdss_dpi_set_timings);
324int dpi_check_timings(struct omap_dss_device *dssdev, 472int dpi_check_timings(struct omap_dss_device *dssdev,
325 struct omap_video_timings *timings) 473 struct omap_video_timings *timings)
326{ 474{
327 int r; 475 struct omap_overlay_manager *mgr = dpi.output.manager;
328 struct omap_overlay_manager *mgr = dssdev->output->manager;
329 int lck_div, pck_div; 476 int lck_div, pck_div;
330 unsigned long fck; 477 unsigned long fck;
331 unsigned long pck; 478 unsigned long pck;
332 struct dispc_clock_info dispc_cinfo; 479 struct dpi_clk_calc_ctx ctx;
480 bool ok;
333 481
334 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings)) 482 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
335 return -EINVAL; 483 return -EINVAL;
@@ -338,28 +486,21 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
338 return -EINVAL; 486 return -EINVAL;
339 487
340 if (dpi.dsidev) { 488 if (dpi.dsidev) {
341 struct dsi_clock_info dsi_cinfo; 489 ok = dpi_dsi_clk_calc(timings->pixel_clock * 1000, &ctx);
342 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, 490 if (!ok)
343 timings->pixel_clock * 1000, 491 return -EINVAL;
344 &dsi_cinfo, &dispc_cinfo);
345 492
346 if (r) 493 fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
347 return r;
348
349 fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
350 } else { 494 } else {
351 struct dss_clock_info dss_cinfo; 495 ok = dpi_dss_clk_calc(timings->pixel_clock * 1000, &ctx);
352 r = dss_calc_clock_div(timings->pixel_clock * 1000, 496 if (!ok)
353 &dss_cinfo, &dispc_cinfo); 497 return -EINVAL;
354 498
355 if (r) 499 fck = ctx.dss_cinfo.fck;
356 return r;
357
358 fck = dss_cinfo.fck;
359 } 500 }
360 501
361 lck_div = dispc_cinfo.lck_div; 502 lck_div = ctx.dispc_cinfo.lck_div;
362 pck_div = dispc_cinfo.pck_div; 503 pck_div = ctx.dispc_cinfo.pck_div;
363 504
364 pck = fck / lck_div / pck_div / 1000; 505 pck = fck / lck_div / pck_div / 1000;
365 506
@@ -379,7 +520,7 @@ void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
379} 520}
380EXPORT_SYMBOL(omapdss_dpi_set_data_lines); 521EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
381 522
382static int __init dpi_verify_dsi_pll(struct platform_device *dsidev) 523static int dpi_verify_dsi_pll(struct platform_device *dsidev)
383{ 524{
384 int r; 525 int r;
385 526
@@ -401,7 +542,37 @@ static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
401 return 0; 542 return 0;
402} 543}
403 544
404static int __init dpi_init_display(struct omap_dss_device *dssdev) 545/*
546 * Return a hardcoded channel for the DPI output. This should work for
547 * current use cases, but this can be later expanded to either resolve
548 * the channel in some more dynamic manner, or get the channel as a user
549 * parameter.
550 */
551static enum omap_channel dpi_get_channel(void)
552{
553 switch (omapdss_get_version()) {
554 case OMAPDSS_VER_OMAP24xx:
555 case OMAPDSS_VER_OMAP34xx_ES1:
556 case OMAPDSS_VER_OMAP34xx_ES3:
557 case OMAPDSS_VER_OMAP3630:
558 case OMAPDSS_VER_AM35xx:
559 return OMAP_DSS_CHANNEL_LCD;
560
561 case OMAPDSS_VER_OMAP4430_ES1:
562 case OMAPDSS_VER_OMAP4430_ES2:
563 case OMAPDSS_VER_OMAP4:
564 return OMAP_DSS_CHANNEL_LCD2;
565
566 case OMAPDSS_VER_OMAP5:
567 return OMAP_DSS_CHANNEL_LCD3;
568
569 default:
570 DSSWARN("unsupported DSS version\n");
571 return OMAP_DSS_CHANNEL_LCD;
572 }
573}
574
575static int dpi_init_display(struct omap_dss_device *dssdev)
405{ 576{
406 struct platform_device *dsidev; 577 struct platform_device *dsidev;
407 578
@@ -421,12 +592,7 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
421 dpi.vdds_dsi_reg = vdds_dsi; 592 dpi.vdds_dsi_reg = vdds_dsi;
422 } 593 }
423 594
424 /* 595 dsidev = dpi_get_dsidev(dpi.output.dispc_channel);
425 * XXX We shouldn't need dssdev->channel for this. The dsi pll clock
426 * source for DPI is SoC integration detail, not something that should
427 * be configured in the dssdev
428 */
429 dsidev = dpi_get_dsidev(dssdev->channel);
430 596
431 if (dsidev && dpi_verify_dsi_pll(dsidev)) { 597 if (dsidev && dpi_verify_dsi_pll(dsidev)) {
432 dsidev = NULL; 598 dsidev = NULL;
@@ -441,7 +607,7 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
441 return 0; 607 return 0;
442} 608}
443 609
444static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev) 610static struct omap_dss_device *dpi_find_dssdev(struct platform_device *pdev)
445{ 611{
446 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 612 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
447 const char *def_disp_name = omapdss_get_default_display_name(); 613 const char *def_disp_name = omapdss_get_default_display_name();
@@ -469,7 +635,7 @@ static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *p
469 return def_dssdev; 635 return def_dssdev;
470} 636}
471 637
472static void __init dpi_probe_pdata(struct platform_device *dpidev) 638static int dpi_probe_pdata(struct platform_device *dpidev)
473{ 639{
474 struct omap_dss_device *plat_dssdev; 640 struct omap_dss_device *plat_dssdev;
475 struct omap_dss_device *dssdev; 641 struct omap_dss_device *dssdev;
@@ -478,11 +644,11 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev)
478 plat_dssdev = dpi_find_dssdev(dpidev); 644 plat_dssdev = dpi_find_dssdev(dpidev);
479 645
480 if (!plat_dssdev) 646 if (!plat_dssdev)
481 return; 647 return 0;
482 648
483 dssdev = dss_alloc_and_init_device(&dpidev->dev); 649 dssdev = dss_alloc_and_init_device(&dpidev->dev);
484 if (!dssdev) 650 if (!dssdev)
485 return; 651 return -ENOMEM;
486 652
487 dss_copy_device_pdata(dssdev, plat_dssdev); 653 dss_copy_device_pdata(dssdev, plat_dssdev);
488 654
@@ -490,7 +656,7 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev)
490 if (r) { 656 if (r) {
491 DSSERR("device %s init failed: %d\n", dssdev->name, r); 657 DSSERR("device %s init failed: %d\n", dssdev->name, r);
492 dss_put_device(dssdev); 658 dss_put_device(dssdev);
493 return; 659 return r;
494 } 660 }
495 661
496 r = omapdss_output_set_device(&dpi.output, dssdev); 662 r = omapdss_output_set_device(&dpi.output, dssdev);
@@ -498,7 +664,7 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev)
498 DSSERR("failed to connect output to new device: %s\n", 664 DSSERR("failed to connect output to new device: %s\n",
499 dssdev->name); 665 dssdev->name);
500 dss_put_device(dssdev); 666 dss_put_device(dssdev);
501 return; 667 return r;
502 } 668 }
503 669
504 r = dss_add_device(dssdev); 670 r = dss_add_device(dssdev);
@@ -506,17 +672,21 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev)
506 DSSERR("device %s register failed: %d\n", dssdev->name, r); 672 DSSERR("device %s register failed: %d\n", dssdev->name, r);
507 omapdss_output_unset_device(&dpi.output); 673 omapdss_output_unset_device(&dpi.output);
508 dss_put_device(dssdev); 674 dss_put_device(dssdev);
509 return; 675 return r;
510 } 676 }
677
678 return 0;
511} 679}
512 680
513static void __init dpi_init_output(struct platform_device *pdev) 681static void dpi_init_output(struct platform_device *pdev)
514{ 682{
515 struct omap_dss_output *out = &dpi.output; 683 struct omap_dss_output *out = &dpi.output;
516 684
517 out->pdev = pdev; 685 out->pdev = pdev;
518 out->id = OMAP_DSS_OUTPUT_DPI; 686 out->id = OMAP_DSS_OUTPUT_DPI;
519 out->type = OMAP_DISPLAY_TYPE_DPI; 687 out->type = OMAP_DISPLAY_TYPE_DPI;
688 out->name = "dpi.0";
689 out->dispc_channel = dpi_get_channel();
520 690
521 dss_register_output(out); 691 dss_register_output(out);
522} 692}
@@ -528,13 +698,19 @@ static void __exit dpi_uninit_output(struct platform_device *pdev)
528 dss_unregister_output(out); 698 dss_unregister_output(out);
529} 699}
530 700
531static int __init omap_dpi_probe(struct platform_device *pdev) 701static int omap_dpi_probe(struct platform_device *pdev)
532{ 702{
703 int r;
704
533 mutex_init(&dpi.lock); 705 mutex_init(&dpi.lock);
534 706
535 dpi_init_output(pdev); 707 dpi_init_output(pdev);
536 708
537 dpi_probe_pdata(pdev); 709 r = dpi_probe_pdata(pdev);
710 if (r) {
711 dpi_uninit_output(pdev);
712 return r;
713 }
538 714
539 return 0; 715 return 0;
540} 716}
@@ -549,6 +725,7 @@ static int __exit omap_dpi_remove(struct platform_device *pdev)
549} 725}
550 726
551static struct platform_driver omap_dpi_driver = { 727static struct platform_driver omap_dpi_driver = {
728 .probe = omap_dpi_probe,
552 .remove = __exit_p(omap_dpi_remove), 729 .remove = __exit_p(omap_dpi_remove),
553 .driver = { 730 .driver = {
554 .name = "omapdss_dpi", 731 .name = "omapdss_dpi",
@@ -558,7 +735,7 @@ static struct platform_driver omap_dpi_driver = {
558 735
559int __init dpi_init_platform_driver(void) 736int __init dpi_init_platform_driver(void)
560{ 737{
561 return platform_driver_probe(&omap_dpi_driver, omap_dpi_probe); 738 return platform_driver_register(&omap_dpi_driver);
562} 739}
563 740
564void __exit dpi_uninit_platform_driver(void) 741void __exit dpi_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 28d41d16b7be..a73dedc33101 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -200,6 +200,11 @@ struct dsi_reg { u16 idx; };
200 200
201typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); 201typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
202 202
203static int dsi_display_init_dispc(struct platform_device *dsidev,
204 struct omap_overlay_manager *mgr);
205static void dsi_display_uninit_dispc(struct platform_device *dsidev,
206 struct omap_overlay_manager *mgr);
207
203#define DSI_MAX_NR_ISRS 2 208#define DSI_MAX_NR_ISRS 2
204#define DSI_MAX_NR_LANES 5 209#define DSI_MAX_NR_LANES 5
205 210
@@ -250,6 +255,24 @@ struct dsi_isr_tables {
250 struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; 255 struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
251}; 256};
252 257
258struct dsi_clk_calc_ctx {
259 struct platform_device *dsidev;
260
261 /* inputs */
262
263 const struct omap_dss_dsi_config *config;
264
265 unsigned long req_pck_min, req_pck_nom, req_pck_max;
266
267 /* outputs */
268
269 struct dsi_clock_info dsi_cinfo;
270 struct dispc_clock_info dispc_cinfo;
271
272 struct omap_video_timings dispc_vm;
273 struct omap_dss_dsi_videomode_timings dsi_vm;
274};
275
253struct dsi_data { 276struct dsi_data {
254 struct platform_device *pdev; 277 struct platform_device *pdev;
255 void __iomem *base; 278 void __iomem *base;
@@ -261,6 +284,9 @@ struct dsi_data {
261 struct clk *dss_clk; 284 struct clk *dss_clk;
262 struct clk *sys_clk; 285 struct clk *sys_clk;
263 286
287 struct dispc_clock_info user_dispc_cinfo;
288 struct dsi_clock_info user_dsi_cinfo;
289
264 struct dsi_clock_info current_cinfo; 290 struct dsi_clock_info current_cinfo;
265 291
266 bool vdds_dsi_enabled; 292 bool vdds_dsi_enabled;
@@ -324,6 +350,7 @@ struct dsi_data {
324 unsigned long lpdiv_max; 350 unsigned long lpdiv_max;
325 351
326 unsigned num_lanes_supported; 352 unsigned num_lanes_supported;
353 unsigned line_buffer_size;
327 354
328 struct dsi_lane_config lanes[DSI_MAX_NR_LANES]; 355 struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
329 unsigned num_lanes_used; 356 unsigned num_lanes_used;
@@ -1192,15 +1219,33 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
1192 return r; 1219 return r;
1193} 1220}
1194 1221
1195static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) 1222static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
1223 unsigned long lp_clk_min, unsigned long lp_clk_max)
1224{
1225 unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk;
1226 unsigned lp_clk_div;
1227 unsigned long lp_clk;
1228
1229 lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk_max * 2);
1230 lp_clk = dsi_fclk / 2 / lp_clk_div;
1231
1232 if (lp_clk < lp_clk_min || lp_clk > lp_clk_max)
1233 return -EINVAL;
1234
1235 cinfo->lp_clk_div = lp_clk_div;
1236 cinfo->lp_clk = lp_clk;
1237
1238 return 0;
1239}
1240
1241static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
1196{ 1242{
1197 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
1198 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1243 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1199 unsigned long dsi_fclk; 1244 unsigned long dsi_fclk;
1200 unsigned lp_clk_div; 1245 unsigned lp_clk_div;
1201 unsigned long lp_clk; 1246 unsigned long lp_clk;
1202 1247
1203 lp_clk_div = dssdev->clocks.dsi.lp_clk_div; 1248 lp_clk_div = dsi->user_dsi_cinfo.lp_clk_div;
1204 1249
1205 if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max) 1250 if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max)
1206 return -EINVAL; 1251 return -EINVAL;
@@ -1272,6 +1317,75 @@ static int dsi_pll_power(struct platform_device *dsidev,
1272 return 0; 1317 return 0;
1273} 1318}
1274 1319
1320unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
1321{
1322 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1323 return clk_get_rate(dsi->sys_clk);
1324}
1325
1326bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
1327 unsigned long out_min, dsi_hsdiv_calc_func func, void *data)
1328{
1329 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1330 int regm, regm_start, regm_stop;
1331 unsigned long out_max;
1332 unsigned long out;
1333
1334 out_min = out_min ? out_min : 1;
1335 out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1336
1337 regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul);
1338 regm_stop = min(pll / out_min, dsi->regm_dispc_max);
1339
1340 for (regm = regm_start; regm <= regm_stop; ++regm) {
1341 out = pll / regm;
1342
1343 if (func(regm, out, data))
1344 return true;
1345 }
1346
1347 return false;
1348}
1349
1350bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
1351 unsigned long pll_min, unsigned long pll_max,
1352 dsi_pll_calc_func func, void *data)
1353{
1354 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1355 int regn, regn_start, regn_stop;
1356 int regm, regm_start, regm_stop;
1357 unsigned long fint, pll;
1358 const unsigned long pll_hw_max = 1800000000;
1359 unsigned long fint_hw_min, fint_hw_max;
1360
1361 fint_hw_min = dsi->fint_min;
1362 fint_hw_max = dsi->fint_max;
1363
1364 regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
1365 regn_stop = min(clkin / fint_hw_min, dsi->regn_max);
1366
1367 pll_max = pll_max ? pll_max : ULONG_MAX;
1368
1369 for (regn = regn_start; regn <= regn_stop; ++regn) {
1370 fint = clkin / regn;
1371
1372 regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
1373 1ul);
1374 regm_stop = min3(pll_max / fint / 2,
1375 pll_hw_max / fint / 2,
1376 dsi->regm_max);
1377
1378 for (regm = regm_start; regm <= regm_stop; ++regm) {
1379 pll = 2 * regm * fint;
1380
1381 if (func(regn, regm, fint, pll, data))
1382 return true;
1383 }
1384 }
1385
1386 return false;
1387}
1388
1275/* calculate clock rates using dividers in cinfo */ 1389/* calculate clock rates using dividers in cinfo */
1276static int dsi_calc_clock_rates(struct platform_device *dsidev, 1390static int dsi_calc_clock_rates(struct platform_device *dsidev,
1277 struct dsi_clock_info *cinfo) 1391 struct dsi_clock_info *cinfo)
@@ -1316,192 +1430,7 @@ static int dsi_calc_clock_rates(struct platform_device *dsidev,
1316 return 0; 1430 return 0;
1317} 1431}
1318 1432
1319int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, 1433static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
1320 unsigned long req_pck, struct dsi_clock_info *dsi_cinfo,
1321 struct dispc_clock_info *dispc_cinfo)
1322{
1323 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1324 struct dsi_clock_info cur, best;
1325 struct dispc_clock_info best_dispc;
1326 int min_fck_per_pck;
1327 int match = 0;
1328 unsigned long dss_sys_clk, max_dss_fck;
1329
1330 dss_sys_clk = clk_get_rate(dsi->sys_clk);
1331
1332 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1333
1334 if (req_pck == dsi->cache_req_pck &&
1335 dsi->cache_cinfo.clkin == dss_sys_clk) {
1336 DSSDBG("DSI clock info found from cache\n");
1337 *dsi_cinfo = dsi->cache_cinfo;
1338 dispc_find_clk_divs(req_pck, dsi_cinfo->dsi_pll_hsdiv_dispc_clk,
1339 dispc_cinfo);
1340 return 0;
1341 }
1342
1343 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
1344
1345 if (min_fck_per_pck &&
1346 req_pck * min_fck_per_pck > max_dss_fck) {
1347 DSSERR("Requested pixel clock not possible with the current "
1348 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
1349 "the constraint off.\n");
1350 min_fck_per_pck = 0;
1351 }
1352
1353 DSSDBG("dsi_pll_calc\n");
1354
1355retry:
1356 memset(&best, 0, sizeof(best));
1357 memset(&best_dispc, 0, sizeof(best_dispc));
1358
1359 memset(&cur, 0, sizeof(cur));
1360 cur.clkin = dss_sys_clk;
1361
1362 /* 0.75MHz < Fint = clkin / regn < 2.1MHz */
1363 /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
1364 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
1365 cur.fint = cur.clkin / cur.regn;
1366
1367 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
1368 continue;
1369
1370 /* DSIPHY(MHz) = (2 * regm / regn) * clkin */
1371 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
1372 unsigned long a, b;
1373
1374 a = 2 * cur.regm * (cur.clkin/1000);
1375 b = cur.regn;
1376 cur.clkin4ddr = a / b * 1000;
1377
1378 if (cur.clkin4ddr > 1800 * 1000 * 1000)
1379 break;
1380
1381 /* dsi_pll_hsdiv_dispc_clk(MHz) =
1382 * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */
1383 for (cur.regm_dispc = 1; cur.regm_dispc <
1384 dsi->regm_dispc_max; ++cur.regm_dispc) {
1385 struct dispc_clock_info cur_dispc;
1386 cur.dsi_pll_hsdiv_dispc_clk =
1387 cur.clkin4ddr / cur.regm_dispc;
1388
1389 if (cur.regm_dispc > 1 &&
1390 cur.regm_dispc % 2 != 0 &&
1391 req_pck >= 1000000)
1392 continue;
1393
1394 /* this will narrow down the search a bit,
1395 * but still give pixclocks below what was
1396 * requested */
1397 if (cur.dsi_pll_hsdiv_dispc_clk < req_pck)
1398 break;
1399
1400 if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck)
1401 continue;
1402
1403 if (min_fck_per_pck &&
1404 cur.dsi_pll_hsdiv_dispc_clk <
1405 req_pck * min_fck_per_pck)
1406 continue;
1407
1408 match = 1;
1409
1410 dispc_find_clk_divs(req_pck,
1411 cur.dsi_pll_hsdiv_dispc_clk,
1412 &cur_dispc);
1413
1414 if (abs(cur_dispc.pck - req_pck) <
1415 abs(best_dispc.pck - req_pck)) {
1416 best = cur;
1417 best_dispc = cur_dispc;
1418
1419 if (cur_dispc.pck == req_pck)
1420 goto found;
1421 }
1422 }
1423 }
1424 }
1425found:
1426 if (!match) {
1427 if (min_fck_per_pck) {
1428 DSSERR("Could not find suitable clock settings.\n"
1429 "Turning FCK/PCK constraint off and"
1430 "trying again.\n");
1431 min_fck_per_pck = 0;
1432 goto retry;
1433 }
1434
1435 DSSERR("Could not find suitable clock settings.\n");
1436
1437 return -EINVAL;
1438 }
1439
1440 /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */
1441 best.regm_dsi = 0;
1442 best.dsi_pll_hsdiv_dsi_clk = 0;
1443
1444 if (dsi_cinfo)
1445 *dsi_cinfo = best;
1446 if (dispc_cinfo)
1447 *dispc_cinfo = best_dispc;
1448
1449 dsi->cache_req_pck = req_pck;
1450 dsi->cache_clk_freq = 0;
1451 dsi->cache_cinfo = best;
1452
1453 return 0;
1454}
1455
1456static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
1457 unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
1458{
1459 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1460 struct dsi_clock_info cur, best;
1461
1462 DSSDBG("dsi_pll_calc_ddrfreq\n");
1463
1464 memset(&best, 0, sizeof(best));
1465 memset(&cur, 0, sizeof(cur));
1466
1467 cur.clkin = clk_get_rate(dsi->sys_clk);
1468
1469 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
1470 cur.fint = cur.clkin / cur.regn;
1471
1472 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
1473 continue;
1474
1475 /* DSIPHY(MHz) = (2 * regm / regn) * clkin */
1476 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
1477 unsigned long a, b;
1478
1479 a = 2 * cur.regm * (cur.clkin/1000);
1480 b = cur.regn;
1481 cur.clkin4ddr = a / b * 1000;
1482
1483 if (cur.clkin4ddr > 1800 * 1000 * 1000)
1484 break;
1485
1486 if (abs(cur.clkin4ddr - req_clkin4ddr) <
1487 abs(best.clkin4ddr - req_clkin4ddr)) {
1488 best = cur;
1489 DSSDBG("best %ld\n", best.clkin4ddr);
1490 }
1491
1492 if (cur.clkin4ddr == req_clkin4ddr)
1493 goto found;
1494 }
1495 }
1496found:
1497 if (cinfo)
1498 *cinfo = best;
1499
1500 return 0;
1501}
1502
1503static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
1504 struct dsi_clock_info *cinfo)
1505{ 1434{
1506 unsigned long max_dsi_fck; 1435 unsigned long max_dsi_fck;
1507 1436
@@ -1511,90 +1440,6 @@ static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
1511 cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi; 1440 cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
1512} 1441}
1513 1442
1514static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
1515 unsigned long req_pck, struct dsi_clock_info *cinfo,
1516 struct dispc_clock_info *dispc_cinfo)
1517{
1518 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1519 unsigned regm_dispc, best_regm_dispc;
1520 unsigned long dispc_clk, best_dispc_clk;
1521 int min_fck_per_pck;
1522 unsigned long max_dss_fck;
1523 struct dispc_clock_info best_dispc;
1524 bool match;
1525
1526 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1527
1528 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
1529
1530 if (min_fck_per_pck &&
1531 req_pck * min_fck_per_pck > max_dss_fck) {
1532 DSSERR("Requested pixel clock not possible with the current "
1533 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
1534 "the constraint off.\n");
1535 min_fck_per_pck = 0;
1536 }
1537
1538retry:
1539 best_regm_dispc = 0;
1540 best_dispc_clk = 0;
1541 memset(&best_dispc, 0, sizeof(best_dispc));
1542 match = false;
1543
1544 for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
1545 struct dispc_clock_info cur_dispc;
1546
1547 dispc_clk = cinfo->clkin4ddr / regm_dispc;
1548
1549 /* this will narrow down the search a bit,
1550 * but still give pixclocks below what was
1551 * requested */
1552 if (dispc_clk < req_pck)
1553 break;
1554
1555 if (dispc_clk > max_dss_fck)
1556 continue;
1557
1558 if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
1559 continue;
1560
1561 match = true;
1562
1563 dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
1564
1565 if (abs(cur_dispc.pck - req_pck) <
1566 abs(best_dispc.pck - req_pck)) {
1567 best_regm_dispc = regm_dispc;
1568 best_dispc_clk = dispc_clk;
1569 best_dispc = cur_dispc;
1570
1571 if (cur_dispc.pck == req_pck)
1572 goto found;
1573 }
1574 }
1575
1576 if (!match) {
1577 if (min_fck_per_pck) {
1578 DSSERR("Could not find suitable clock settings.\n"
1579 "Turning FCK/PCK constraint off and"
1580 "trying again.\n");
1581 min_fck_per_pck = 0;
1582 goto retry;
1583 }
1584
1585 DSSERR("Could not find suitable clock settings.\n");
1586
1587 return -EINVAL;
1588 }
1589found:
1590 cinfo->regm_dispc = best_regm_dispc;
1591 cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
1592
1593 *dispc_cinfo = best_dispc;
1594
1595 return 0;
1596}
1597
1598int dsi_pll_set_clock_div(struct platform_device *dsidev, 1443int dsi_pll_set_clock_div(struct platform_device *dsidev,
1599 struct dsi_clock_info *cinfo) 1444 struct dsi_clock_info *cinfo)
1600{ 1445{
@@ -2783,6 +2628,7 @@ static int dsi_vc_enable(struct platform_device *dsidev, int channel,
2783 2628
2784static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) 2629static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
2785{ 2630{
2631 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2786 u32 r; 2632 u32 r;
2787 2633
2788 DSSDBG("Initial config of virtual channel %d", channel); 2634 DSSDBG("Initial config of virtual channel %d", channel);
@@ -2807,6 +2653,8 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
2807 r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ 2653 r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
2808 2654
2809 dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); 2655 dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);
2656
2657 dsi->vc[channel].source = DSI_VC_SOURCE_L4;
2810} 2658}
2811 2659
2812static int dsi_vc_config_source(struct platform_device *dsidev, int channel, 2660static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
@@ -3777,13 +3625,12 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
3777 3625
3778 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { 3626 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3779 int bpp = dsi_get_pixel_size(dsi->pix_fmt); 3627 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3780 unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
3781 struct omap_video_timings *timings = &dsi->timings; 3628 struct omap_video_timings *timings = &dsi->timings;
3782 /* 3629 /*
3783 * Don't use line buffers if width is greater than the video 3630 * Don't use line buffers if width is greater than the video
3784 * port's line buffer size 3631 * port's line buffer size
3785 */ 3632 */
3786 if (line_buf_size <= timings->x_res * bpp / 8) 3633 if (dsi->line_buffer_size <= timings->x_res * bpp / 8)
3787 num_line_buffers = 0; 3634 num_line_buffers = 0;
3788 else 3635 else
3789 num_line_buffers = 2; 3636 num_line_buffers = 2;
@@ -3799,18 +3646,22 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
3799static void dsi_config_vp_sync_events(struct platform_device *dsidev) 3646static void dsi_config_vp_sync_events(struct platform_device *dsidev)
3800{ 3647{
3801 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3648 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3802 bool vsync_end = dsi->vm_timings.vp_vsync_end; 3649 bool sync_end;
3803 bool hsync_end = dsi->vm_timings.vp_hsync_end;
3804 u32 r; 3650 u32 r;
3805 3651
3652 if (dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE)
3653 sync_end = true;
3654 else
3655 sync_end = false;
3656
3806 r = dsi_read_reg(dsidev, DSI_CTRL); 3657 r = dsi_read_reg(dsidev, DSI_CTRL);
3807 r = FLD_MOD(r, 1, 9, 9); /* VP_DE_POL */ 3658 r = FLD_MOD(r, 1, 9, 9); /* VP_DE_POL */
3808 r = FLD_MOD(r, 1, 10, 10); /* VP_HSYNC_POL */ 3659 r = FLD_MOD(r, 1, 10, 10); /* VP_HSYNC_POL */
3809 r = FLD_MOD(r, 1, 11, 11); /* VP_VSYNC_POL */ 3660 r = FLD_MOD(r, 1, 11, 11); /* VP_VSYNC_POL */
3810 r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */ 3661 r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */
3811 r = FLD_MOD(r, vsync_end, 16, 16); /* VP_VSYNC_END */ 3662 r = FLD_MOD(r, sync_end, 16, 16); /* VP_VSYNC_END */
3812 r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */ 3663 r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */
3813 r = FLD_MOD(r, hsync_end, 18, 18); /* VP_HSYNC_END */ 3664 r = FLD_MOD(r, sync_end, 18, 18); /* VP_HSYNC_END */
3814 dsi_write_reg(dsidev, DSI_CTRL, r); 3665 dsi_write_reg(dsidev, DSI_CTRL, r);
3815} 3666}
3816 3667
@@ -3897,9 +3748,8 @@ static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs,
3897 return max(lp_inter, 0); 3748 return max(lp_inter, 0);
3898} 3749}
3899 3750
3900static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) 3751static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev)
3901{ 3752{
3902 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3903 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3753 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3904 int blanking_mode; 3754 int blanking_mode;
3905 int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode; 3755 int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode;
@@ -3910,7 +3760,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
3910 struct omap_video_timings *timings = &dsi->timings; 3760 struct omap_video_timings *timings = &dsi->timings;
3911 int bpp = dsi_get_pixel_size(dsi->pix_fmt); 3761 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3912 int ndl = dsi->num_lanes_used - 1; 3762 int ndl = dsi->num_lanes_used - 1;
3913 int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1; 3763 int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.regm_dsi + 1;
3914 int hsa_interleave_hs = 0, hsa_interleave_lp = 0; 3764 int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
3915 int hfp_interleave_hs = 0, hfp_interleave_lp = 0; 3765 int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
3916 int hbp_interleave_hs = 0, hbp_interleave_lp = 0; 3766 int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
@@ -4015,9 +3865,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
4015 dsi_write_reg(dsidev, DSI_VM_TIMING6, r); 3865 dsi_write_reg(dsidev, DSI_VM_TIMING6, r);
4016} 3866}
4017 3867
4018static int dsi_proto_config(struct omap_dss_device *dssdev) 3868static int dsi_proto_config(struct platform_device *dsidev)
4019{ 3869{
4020 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4021 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3870 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4022 u32 r; 3871 u32 r;
4023 int buswidth = 0; 3872 int buswidth = 0;
@@ -4075,7 +3924,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
4075 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { 3924 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4076 dsi_config_vp_sync_events(dsidev); 3925 dsi_config_vp_sync_events(dsidev);
4077 dsi_config_blanking_modes(dsidev); 3926 dsi_config_blanking_modes(dsidev);
4078 dsi_config_cmd_mode_interleaving(dssdev); 3927 dsi_config_cmd_mode_interleaving(dsidev);
4079 } 3928 }
4080 3929
4081 dsi_vc_initial_config(dsidev, 0); 3930 dsi_vc_initial_config(dsidev, 0);
@@ -4159,11 +4008,12 @@ static void dsi_proto_timings(struct platform_device *dsidev)
4159 int vfp = dsi->vm_timings.vfp; 4008 int vfp = dsi->vm_timings.vfp;
4160 int vbp = dsi->vm_timings.vbp; 4009 int vbp = dsi->vm_timings.vbp;
4161 int window_sync = dsi->vm_timings.window_sync; 4010 int window_sync = dsi->vm_timings.window_sync;
4162 bool hsync_end = dsi->vm_timings.vp_hsync_end; 4011 bool hsync_end;
4163 struct omap_video_timings *timings = &dsi->timings; 4012 struct omap_video_timings *timings = &dsi->timings;
4164 int bpp = dsi_get_pixel_size(dsi->pix_fmt); 4013 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
4165 int tl, t_he, width_bytes; 4014 int tl, t_he, width_bytes;
4166 4015
4016 hsync_end = dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE;
4167 t_he = hsync_end ? 4017 t_he = hsync_end ?
4168 ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; 4018 ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
4169 4019
@@ -4266,82 +4116,26 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
4266} 4116}
4267EXPORT_SYMBOL(omapdss_dsi_configure_pins); 4117EXPORT_SYMBOL(omapdss_dsi_configure_pins);
4268 4118
4269int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
4270 unsigned long ddr_clk, unsigned long lp_clk)
4271{
4272 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4273 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4274 struct dsi_clock_info cinfo;
4275 struct dispc_clock_info dispc_cinfo;
4276 unsigned lp_clk_div;
4277 unsigned long dsi_fclk;
4278 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
4279 unsigned long pck;
4280 int r;
4281
4282 DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
4283
4284 mutex_lock(&dsi->lock);
4285
4286 /* Calculate PLL output clock */
4287 r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
4288 if (r)
4289 goto err;
4290
4291 /* Calculate PLL's DSI clock */
4292 dsi_pll_calc_dsi_fck(dsidev, &cinfo);
4293
4294 /* Calculate PLL's DISPC clock and pck & lck divs */
4295 pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
4296 DSSDBG("finding dispc dividers for pck %lu\n", pck);
4297 r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
4298 if (r)
4299 goto err;
4300
4301 /* Calculate LP clock */
4302 dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
4303 lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
4304
4305 dssdev->clocks.dsi.regn = cinfo.regn;
4306 dssdev->clocks.dsi.regm = cinfo.regm;
4307 dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
4308 dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
4309
4310 dssdev->clocks.dsi.lp_clk_div = lp_clk_div;
4311
4312 dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div;
4313 dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;
4314
4315 dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
4316
4317 dssdev->clocks.dispc.channel.lcd_clk_src =
4318 dsi->module_id == 0 ?
4319 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
4320 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
4321
4322 dssdev->clocks.dsi.dsi_fclk_src =
4323 dsi->module_id == 0 ?
4324 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
4325 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
4326
4327 mutex_unlock(&dsi->lock);
4328 return 0;
4329err:
4330 mutex_unlock(&dsi->lock);
4331 return r;
4332}
4333EXPORT_SYMBOL(omapdss_dsi_set_clocks);
4334
4335int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) 4119int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4336{ 4120{
4337 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4121 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4338 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4122 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4339 struct omap_overlay_manager *mgr = dssdev->output->manager; 4123 struct omap_overlay_manager *mgr = dsi->output.manager;
4340 int bpp = dsi_get_pixel_size(dsi->pix_fmt); 4124 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
4125 struct omap_dss_output *out = &dsi->output;
4341 u8 data_type; 4126 u8 data_type;
4342 u16 word_count; 4127 u16 word_count;
4343 int r; 4128 int r;
4344 4129
4130 if (out == NULL || out->manager == NULL) {
4131 DSSERR("failed to enable display: no output/manager\n");
4132 return -ENODEV;
4133 }
4134
4135 r = dsi_display_init_dispc(dsidev, mgr);
4136 if (r)
4137 goto err_init_dispc;
4138
4345 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { 4139 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4346 switch (dsi->pix_fmt) { 4140 switch (dsi->pix_fmt) {
4347 case OMAP_DSS_DSI_FMT_RGB888: 4141 case OMAP_DSS_DSI_FMT_RGB888:
@@ -4357,8 +4151,8 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4357 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; 4151 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
4358 break; 4152 break;
4359 default: 4153 default:
4360 BUG(); 4154 r = -EINVAL;
4361 return -EINVAL; 4155 goto err_pix_fmt;
4362 }; 4156 };
4363 4157
4364 dsi_if_enable(dsidev, false); 4158 dsi_if_enable(dsidev, false);
@@ -4377,16 +4171,20 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4377 } 4171 }
4378 4172
4379 r = dss_mgr_enable(mgr); 4173 r = dss_mgr_enable(mgr);
4380 if (r) { 4174 if (r)
4381 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { 4175 goto err_mgr_enable;
4382 dsi_if_enable(dsidev, false);
4383 dsi_vc_enable(dsidev, channel, false);
4384 }
4385
4386 return r;
4387 }
4388 4176
4389 return 0; 4177 return 0;
4178
4179err_mgr_enable:
4180 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4181 dsi_if_enable(dsidev, false);
4182 dsi_vc_enable(dsidev, channel, false);
4183 }
4184err_pix_fmt:
4185 dsi_display_uninit_dispc(dsidev, mgr);
4186err_init_dispc:
4187 return r;
4390} 4188}
4391EXPORT_SYMBOL(dsi_enable_video_output); 4189EXPORT_SYMBOL(dsi_enable_video_output);
4392 4190
@@ -4394,7 +4192,7 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
4394{ 4192{
4395 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4193 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4396 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4194 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4397 struct omap_overlay_manager *mgr = dssdev->output->manager; 4195 struct omap_overlay_manager *mgr = dsi->output.manager;
4398 4196
4399 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { 4197 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4400 dsi_if_enable(dsidev, false); 4198 dsi_if_enable(dsidev, false);
@@ -4408,14 +4206,15 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
4408 } 4206 }
4409 4207
4410 dss_mgr_disable(mgr); 4208 dss_mgr_disable(mgr);
4209
4210 dsi_display_uninit_dispc(dsidev, mgr);
4411} 4211}
4412EXPORT_SYMBOL(dsi_disable_video_output); 4212EXPORT_SYMBOL(dsi_disable_video_output);
4413 4213
4414static void dsi_update_screen_dispc(struct omap_dss_device *dssdev) 4214static void dsi_update_screen_dispc(struct platform_device *dsidev)
4415{ 4215{
4416 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4417 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4216 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4418 struct omap_overlay_manager *mgr = dssdev->output->manager; 4217 struct omap_overlay_manager *mgr = dsi->output.manager;
4419 unsigned bytespp; 4218 unsigned bytespp;
4420 unsigned bytespl; 4219 unsigned bytespl;
4421 unsigned bytespf; 4220 unsigned bytespf;
@@ -4425,7 +4224,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
4425 u32 l; 4224 u32 l;
4426 int r; 4225 int r;
4427 const unsigned channel = dsi->update_channel; 4226 const unsigned channel = dsi->update_channel;
4428 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); 4227 const unsigned line_buf_size = dsi->line_buffer_size;
4429 u16 w = dsi->timings.x_res; 4228 u16 w = dsi->timings.x_res;
4430 u16 h = dsi->timings.y_res; 4229 u16 h = dsi->timings.y_res;
4431 4230
@@ -4571,7 +4370,7 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
4571 dsi->update_bytes = dw * dh * 4370 dsi->update_bytes = dw * dh *
4572 dsi_get_pixel_size(dsi->pix_fmt) / 8; 4371 dsi_get_pixel_size(dsi->pix_fmt) / 8;
4573#endif 4372#endif
4574 dsi_update_screen_dispc(dssdev); 4373 dsi_update_screen_dispc(dsidev);
4575 4374
4576 return 0; 4375 return 0;
4577} 4376}
@@ -4579,18 +4378,17 @@ EXPORT_SYMBOL(omap_dsi_update);
4579 4378
4580/* Display funcs */ 4379/* Display funcs */
4581 4380
4582static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) 4381static int dsi_configure_dispc_clocks(struct platform_device *dsidev)
4583{ 4382{
4584 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4585 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4383 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4586 struct dispc_clock_info dispc_cinfo; 4384 struct dispc_clock_info dispc_cinfo;
4587 int r; 4385 int r;
4588 unsigned long long fck; 4386 unsigned long fck;
4589 4387
4590 fck = dsi_get_pll_hsdiv_dispc_rate(dsidev); 4388 fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
4591 4389
4592 dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div; 4390 dispc_cinfo.lck_div = dsi->user_dispc_cinfo.lck_div;
4593 dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div; 4391 dispc_cinfo.pck_div = dsi->user_dispc_cinfo.pck_div;
4594 4392
4595 r = dispc_calc_clock_rates(fck, &dispc_cinfo); 4393 r = dispc_calc_clock_rates(fck, &dispc_cinfo);
4596 if (r) { 4394 if (r) {
@@ -4603,21 +4401,17 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
4603 return 0; 4401 return 0;
4604} 4402}
4605 4403
4606static int dsi_display_init_dispc(struct omap_dss_device *dssdev) 4404static int dsi_display_init_dispc(struct platform_device *dsidev,
4405 struct omap_overlay_manager *mgr)
4607{ 4406{
4608 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4609 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4407 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4610 struct omap_overlay_manager *mgr = dssdev->output->manager;
4611 int r; 4408 int r;
4612 4409
4613 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { 4410 dss_select_lcd_clk_source(mgr->id, dsi->module_id == 0 ?
4614 dsi->timings.hsw = 1; 4411 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
4615 dsi->timings.hfp = 1; 4412 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
4616 dsi->timings.hbp = 1;
4617 dsi->timings.vsw = 1;
4618 dsi->timings.vfp = 0;
4619 dsi->timings.vbp = 0;
4620 4413
4414 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4621 r = dss_mgr_register_framedone_handler(mgr, 4415 r = dss_mgr_register_framedone_handler(mgr,
4622 dsi_framedone_irq_callback, dsidev); 4416 dsi_framedone_irq_callback, dsidev);
4623 if (r) { 4417 if (r) {
@@ -4645,7 +4439,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4645 4439
4646 dss_mgr_set_timings(mgr, &dsi->timings); 4440 dss_mgr_set_timings(mgr, &dsi->timings);
4647 4441
4648 r = dsi_configure_dispc_clocks(dssdev); 4442 r = dsi_configure_dispc_clocks(dsidev);
4649 if (r) 4443 if (r)
4650 goto err1; 4444 goto err1;
4651 4445
@@ -4662,30 +4456,30 @@ err1:
4662 dss_mgr_unregister_framedone_handler(mgr, 4456 dss_mgr_unregister_framedone_handler(mgr,
4663 dsi_framedone_irq_callback, dsidev); 4457 dsi_framedone_irq_callback, dsidev);
4664err: 4458err:
4459 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4665 return r; 4460 return r;
4666} 4461}
4667 4462
4668static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) 4463static void dsi_display_uninit_dispc(struct platform_device *dsidev,
4464 struct omap_overlay_manager *mgr)
4669{ 4465{
4670 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4671 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4466 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4672 struct omap_overlay_manager *mgr = dssdev->output->manager;
4673 4467
4674 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) 4468 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4675 dss_mgr_unregister_framedone_handler(mgr, 4469 dss_mgr_unregister_framedone_handler(mgr,
4676 dsi_framedone_irq_callback, dsidev); 4470 dsi_framedone_irq_callback, dsidev);
4471
4472 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4677} 4473}
4678 4474
4679static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) 4475static int dsi_configure_dsi_clocks(struct platform_device *dsidev)
4680{ 4476{
4681 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4477 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4682 struct dsi_clock_info cinfo; 4478 struct dsi_clock_info cinfo;
4683 int r; 4479 int r;
4684 4480
4685 cinfo.regn = dssdev->clocks.dsi.regn; 4481 cinfo = dsi->user_dsi_cinfo;
4686 cinfo.regm = dssdev->clocks.dsi.regm; 4482
4687 cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc;
4688 cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi;
4689 r = dsi_calc_clock_rates(dsidev, &cinfo); 4483 r = dsi_calc_clock_rates(dsidev, &cinfo);
4690 if (r) { 4484 if (r) {
4691 DSSERR("Failed to calc dsi clocks\n"); 4485 DSSERR("Failed to calc dsi clocks\n");
@@ -4701,24 +4495,22 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
4701 return 0; 4495 return 0;
4702} 4496}
4703 4497
4704static int dsi_display_init_dsi(struct omap_dss_device *dssdev) 4498static int dsi_display_init_dsi(struct platform_device *dsidev)
4705{ 4499{
4706 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4707 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4500 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4708 struct omap_overlay_manager *mgr = dssdev->output->manager;
4709 int r; 4501 int r;
4710 4502
4711 r = dsi_pll_init(dsidev, true, true); 4503 r = dsi_pll_init(dsidev, true, true);
4712 if (r) 4504 if (r)
4713 goto err0; 4505 goto err0;
4714 4506
4715 r = dsi_configure_dsi_clocks(dssdev); 4507 r = dsi_configure_dsi_clocks(dsidev);
4716 if (r) 4508 if (r)
4717 goto err1; 4509 goto err1;
4718 4510
4719 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); 4511 dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ?
4720 dss_select_lcd_clk_source(mgr->id, 4512 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
4721 dssdev->clocks.dispc.channel.lcd_clk_src); 4513 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI);
4722 4514
4723 DSSDBG("PLL OK\n"); 4515 DSSDBG("PLL OK\n");
4724 4516
@@ -4729,12 +4521,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4729 _dsi_print_reset_status(dsidev); 4521 _dsi_print_reset_status(dsidev);
4730 4522
4731 dsi_proto_timings(dsidev); 4523 dsi_proto_timings(dsidev);
4732 dsi_set_lp_clk_divisor(dssdev); 4524 dsi_set_lp_clk_divisor(dsidev);
4733 4525
4734 if (1) 4526 if (1)
4735 _dsi_print_reset_status(dsidev); 4527 _dsi_print_reset_status(dsidev);
4736 4528
4737 r = dsi_proto_config(dssdev); 4529 r = dsi_proto_config(dsidev);
4738 if (r) 4530 if (r)
4739 goto err3; 4531 goto err3;
4740 4532
@@ -4751,20 +4543,16 @@ err3:
4751 dsi_cio_uninit(dsidev); 4543 dsi_cio_uninit(dsidev);
4752err2: 4544err2:
4753 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4545 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4754 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4755
4756err1: 4546err1:
4757 dsi_pll_uninit(dsidev, true); 4547 dsi_pll_uninit(dsidev, true);
4758err0: 4548err0:
4759 return r; 4549 return r;
4760} 4550}
4761 4551
4762static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, 4552static void dsi_display_uninit_dsi(struct platform_device *dsidev,
4763 bool disconnect_lanes, bool enter_ulps) 4553 bool disconnect_lanes, bool enter_ulps)
4764{ 4554{
4765 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4766 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4555 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4767 struct omap_overlay_manager *mgr = dssdev->output->manager;
4768 4556
4769 if (enter_ulps && !dsi->ulps_enabled) 4557 if (enter_ulps && !dsi->ulps_enabled)
4770 dsi_enter_ulps(dsidev); 4558 dsi_enter_ulps(dsidev);
@@ -4777,7 +4565,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4777 dsi_vc_enable(dsidev, 3, 0); 4565 dsi_vc_enable(dsidev, 3, 0);
4778 4566
4779 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4567 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4780 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4781 dsi_cio_uninit(dsidev); 4568 dsi_cio_uninit(dsidev);
4782 dsi_pll_uninit(dsidev, disconnect_lanes); 4569 dsi_pll_uninit(dsidev, disconnect_lanes);
4783} 4570}
@@ -4786,7 +4573,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4786{ 4573{
4787 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4574 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4788 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4575 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4789 struct omap_dss_output *out = dssdev->output;
4790 int r = 0; 4576 int r = 0;
4791 4577
4792 DSSDBG("dsi_display_enable\n"); 4578 DSSDBG("dsi_display_enable\n");
@@ -4795,12 +4581,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4795 4581
4796 mutex_lock(&dsi->lock); 4582 mutex_lock(&dsi->lock);
4797 4583
4798 if (out == NULL || out->manager == NULL) {
4799 DSSERR("failed to enable display: no output/manager\n");
4800 r = -ENODEV;
4801 goto err_start_dev;
4802 }
4803
4804 r = omap_dss_start_device(dssdev); 4584 r = omap_dss_start_device(dssdev);
4805 if (r) { 4585 if (r) {
4806 DSSERR("failed to start device\n"); 4586 DSSERR("failed to start device\n");
@@ -4815,11 +4595,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4815 4595
4816 _dsi_initialize_irq(dsidev); 4596 _dsi_initialize_irq(dsidev);
4817 4597
4818 r = dsi_display_init_dispc(dssdev); 4598 r = dsi_display_init_dsi(dsidev);
4819 if (r)
4820 goto err_init_dispc;
4821
4822 r = dsi_display_init_dsi(dssdev);
4823 if (r) 4599 if (r)
4824 goto err_init_dsi; 4600 goto err_init_dsi;
4825 4601
@@ -4828,8 +4604,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4828 return 0; 4604 return 0;
4829 4605
4830err_init_dsi: 4606err_init_dsi:
4831 dsi_display_uninit_dispc(dssdev);
4832err_init_dispc:
4833 dsi_enable_pll_clock(dsidev, 0); 4607 dsi_enable_pll_clock(dsidev, 0);
4834 dsi_runtime_put(dsidev); 4608 dsi_runtime_put(dsidev);
4835err_get_dsi: 4609err_get_dsi:
@@ -4858,9 +4632,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
4858 dsi_sync_vc(dsidev, 2); 4632 dsi_sync_vc(dsidev, 2);
4859 dsi_sync_vc(dsidev, 3); 4633 dsi_sync_vc(dsidev, 3);
4860 4634
4861 dsi_display_uninit_dispc(dssdev); 4635 dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps);
4862
4863 dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
4864 4636
4865 dsi_runtime_put(dsidev); 4637 dsi_runtime_put(dsidev);
4866 dsi_enable_pll_clock(dsidev, 0); 4638 dsi_enable_pll_clock(dsidev, 0);
@@ -4881,77 +4653,579 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
4881} 4653}
4882EXPORT_SYMBOL(omapdss_dsi_enable_te); 4654EXPORT_SYMBOL(omapdss_dsi_enable_te);
4883 4655
4884void omapdss_dsi_set_timings(struct omap_dss_device *dssdev, 4656#ifdef PRINT_VERBOSE_VM_TIMINGS
4885 struct omap_video_timings *timings) 4657static void print_dsi_vm(const char *str,
4658 const struct omap_dss_dsi_videomode_timings *t)
4659{
4660 unsigned long byteclk = t->hsclk / 4;
4661 int bl, wc, pps, tot;
4662
4663 wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
4664 pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
4665 bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
4666 tot = bl + pps;
4667
4668#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
4669
4670 pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, "
4671 "%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
4672 str,
4673 byteclk,
4674 t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
4675 bl, pps, tot,
4676 TO_DSI_T(t->hss),
4677 TO_DSI_T(t->hsa),
4678 TO_DSI_T(t->hse),
4679 TO_DSI_T(t->hbp),
4680 TO_DSI_T(pps),
4681 TO_DSI_T(t->hfp),
4682
4683 TO_DSI_T(bl),
4684 TO_DSI_T(pps),
4685
4686 TO_DSI_T(tot));
4687#undef TO_DSI_T
4688}
4689
4690static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
4691{
4692 unsigned long pck = t->pixel_clock * 1000;
4693 int hact, bl, tot;
4694
4695 hact = t->x_res;
4696 bl = t->hsw + t->hbp + t->hfp;
4697 tot = hact + bl;
4698
4699#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
4700
4701 pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, "
4702 "%u/%u/%u/%u = %u + %u = %u\n",
4703 str,
4704 pck,
4705 t->hsw, t->hbp, hact, t->hfp,
4706 bl, hact, tot,
4707 TO_DISPC_T(t->hsw),
4708 TO_DISPC_T(t->hbp),
4709 TO_DISPC_T(hact),
4710 TO_DISPC_T(t->hfp),
4711 TO_DISPC_T(bl),
4712 TO_DISPC_T(hact),
4713 TO_DISPC_T(tot));
4714#undef TO_DISPC_T
4715}
4716
4717/* note: this is not quite accurate */
4718static void print_dsi_dispc_vm(const char *str,
4719 const struct omap_dss_dsi_videomode_timings *t)
4720{
4721 struct omap_video_timings vm = { 0 };
4722 unsigned long byteclk = t->hsclk / 4;
4723 unsigned long pck;
4724 u64 dsi_tput;
4725 int dsi_hact, dsi_htot;
4726
4727 dsi_tput = (u64)byteclk * t->ndl * 8;
4728 pck = (u32)div64_u64(dsi_tput, t->bitspp);
4729 dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
4730 dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
4731
4732 vm.pixel_clock = pck / 1000;
4733 vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
4734 vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
4735 vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
4736 vm.x_res = t->hact;
4737
4738 print_dispc_vm(str, &vm);
4739}
4740#endif /* PRINT_VERBOSE_VM_TIMINGS */
4741
4742static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
4743 unsigned long pck, void *data)
4886{ 4744{
4887 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4745 struct dsi_clk_calc_ctx *ctx = data;
4888 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4746 struct omap_video_timings *t = &ctx->dispc_vm;
4889 4747
4890 mutex_lock(&dsi->lock); 4748 ctx->dispc_cinfo.lck_div = lckd;
4749 ctx->dispc_cinfo.pck_div = pckd;
4750 ctx->dispc_cinfo.lck = lck;
4751 ctx->dispc_cinfo.pck = pck;
4891 4752
4892 dsi->timings = *timings; 4753 *t = *ctx->config->timings;
4754 t->pixel_clock = pck / 1000;
4755 t->x_res = ctx->config->timings->x_res;
4756 t->y_res = ctx->config->timings->y_res;
4757 t->hsw = t->hfp = t->hbp = t->vsw = 1;
4758 t->vfp = t->vbp = 0;
4893 4759
4894 mutex_unlock(&dsi->lock); 4760 return true;
4895} 4761}
4896EXPORT_SYMBOL(omapdss_dsi_set_timings);
4897 4762
4898void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) 4763static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
4764 void *data)
4899{ 4765{
4900 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4766 struct dsi_clk_calc_ctx *ctx = data;
4901 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4902 4767
4903 mutex_lock(&dsi->lock); 4768 ctx->dsi_cinfo.regm_dispc = regm_dispc;
4769 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
4904 4770
4905 dsi->timings.x_res = w; 4771 return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
4906 dsi->timings.y_res = h; 4772 dsi_cm_calc_dispc_cb, ctx);
4773}
4907 4774
4908 mutex_unlock(&dsi->lock); 4775static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint,
4776 unsigned long pll, void *data)
4777{
4778 struct dsi_clk_calc_ctx *ctx = data;
4779
4780 ctx->dsi_cinfo.regn = regn;
4781 ctx->dsi_cinfo.regm = regm;
4782 ctx->dsi_cinfo.fint = fint;
4783 ctx->dsi_cinfo.clkin4ddr = pll;
4784
4785 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
4786 dsi_cm_calc_hsdiv_cb, ctx);
4909} 4787}
4910EXPORT_SYMBOL(omapdss_dsi_set_size);
4911 4788
4912void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev, 4789static bool dsi_cm_calc(struct dsi_data *dsi,
4913 enum omap_dss_dsi_pixel_format fmt) 4790 const struct omap_dss_dsi_config *cfg,
4791 struct dsi_clk_calc_ctx *ctx)
4914{ 4792{
4915 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4793 unsigned long clkin;
4916 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4794 int bitspp, ndl;
4795 unsigned long pll_min, pll_max;
4796 unsigned long pck, txbyteclk;
4917 4797
4918 mutex_lock(&dsi->lock); 4798 clkin = clk_get_rate(dsi->sys_clk);
4799 bitspp = dsi_get_pixel_size(cfg->pixel_format);
4800 ndl = dsi->num_lanes_used - 1;
4919 4801
4920 dsi->pix_fmt = fmt; 4802 /*
4803 * Here we should calculate minimum txbyteclk to be able to send the
4804 * frame in time, and also to handle TE. That's not very simple, though,
4805 * especially as we go to LP between each pixel packet due to HW
4806 * "feature". So let's just estimate very roughly and multiply by 1.5.
4807 */
4808 pck = cfg->timings->pixel_clock * 1000;
4809 pck = pck * 3 / 2;
4810 txbyteclk = pck * bitspp / 8 / ndl;
4921 4811
4922 mutex_unlock(&dsi->lock); 4812 memset(ctx, 0, sizeof(*ctx));
4813 ctx->dsidev = dsi->pdev;
4814 ctx->config = cfg;
4815 ctx->req_pck_min = pck;
4816 ctx->req_pck_nom = pck;
4817 ctx->req_pck_max = pck * 3 / 2;
4818 ctx->dsi_cinfo.clkin = clkin;
4819
4820 pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
4821 pll_max = cfg->hs_clk_max * 4;
4822
4823 return dsi_pll_calc(dsi->pdev, clkin,
4824 pll_min, pll_max,
4825 dsi_cm_calc_pll_cb, ctx);
4923} 4826}
4924EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
4925 4827
4926void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev, 4828static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
4927 enum omap_dss_dsi_mode mode)
4928{ 4829{
4929 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4830 struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
4930 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4831 const struct omap_dss_dsi_config *cfg = ctx->config;
4832 int bitspp = dsi_get_pixel_size(cfg->pixel_format);
4833 int ndl = dsi->num_lanes_used - 1;
4834 unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4;
4835 unsigned long byteclk = hsclk / 4;
4931 4836
4932 mutex_lock(&dsi->lock); 4837 unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
4838 int xres;
4839 int panel_htot, panel_hbl; /* pixels */
4840 int dispc_htot, dispc_hbl; /* pixels */
4841 int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
4842 int hfp, hsa, hbp;
4843 const struct omap_video_timings *req_vm;
4844 struct omap_video_timings *dispc_vm;
4845 struct omap_dss_dsi_videomode_timings *dsi_vm;
4846 u64 dsi_tput, dispc_tput;
4933 4847
4934 dsi->mode = mode; 4848 dsi_tput = (u64)byteclk * ndl * 8;
4935 4849
4936 mutex_unlock(&dsi->lock); 4850 req_vm = cfg->timings;
4851 req_pck_min = ctx->req_pck_min;
4852 req_pck_max = ctx->req_pck_max;
4853 req_pck_nom = ctx->req_pck_nom;
4854
4855 dispc_pck = ctx->dispc_cinfo.pck;
4856 dispc_tput = (u64)dispc_pck * bitspp;
4857
4858 xres = req_vm->x_res;
4859
4860 panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
4861 panel_htot = xres + panel_hbl;
4862
4863 dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
4864
4865 /*
4866 * When there are no line buffers, DISPC and DSI must have the
4867 * same tput. Otherwise DISPC tput needs to be higher than DSI's.
4868 */
4869 if (dsi->line_buffer_size < xres * bitspp / 8) {
4870 if (dispc_tput != dsi_tput)
4871 return false;
4872 } else {
4873 if (dispc_tput < dsi_tput)
4874 return false;
4875 }
4876
4877 /* DSI tput must be over the min requirement */
4878 if (dsi_tput < (u64)bitspp * req_pck_min)
4879 return false;
4880
4881 /* When non-burst mode, DSI tput must be below max requirement. */
4882 if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) {
4883 if (dsi_tput > (u64)bitspp * req_pck_max)
4884 return false;
4885 }
4886
4887 hss = DIV_ROUND_UP(4, ndl);
4888
4889 if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
4890 if (ndl == 3 && req_vm->hsw == 0)
4891 hse = 1;
4892 else
4893 hse = DIV_ROUND_UP(4, ndl);
4894 } else {
4895 hse = 0;
4896 }
4897
4898 /* DSI htot to match the panel's nominal pck */
4899 dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom);
4900
4901 /* fail if there would be no time for blanking */
4902 if (dsi_htot < hss + hse + dsi_hact)
4903 return false;
4904
4905 /* total DSI blanking needed to achieve panel's TL */
4906 dsi_hbl = dsi_htot - dsi_hact;
4907
4908 /* DISPC htot to match the DSI TL */
4909 dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk);
4910
4911 /* verify that the DSI and DISPC TLs are the same */
4912 if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk)
4913 return false;
4914
4915 dispc_hbl = dispc_htot - xres;
4916
4917 /* setup DSI videomode */
4918
4919 dsi_vm = &ctx->dsi_vm;
4920 memset(dsi_vm, 0, sizeof(*dsi_vm));
4921
4922 dsi_vm->hsclk = hsclk;
4923
4924 dsi_vm->ndl = ndl;
4925 dsi_vm->bitspp = bitspp;
4926
4927 if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) {
4928 hsa = 0;
4929 } else if (ndl == 3 && req_vm->hsw == 0) {
4930 hsa = 0;
4931 } else {
4932 hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom);
4933 hsa = max(hsa - hse, 1);
4934 }
4935
4936 hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
4937 hbp = max(hbp, 1);
4938
4939 hfp = dsi_hbl - (hss + hsa + hse + hbp);
4940 if (hfp < 1) {
4941 int t;
4942 /* we need to take cycles from hbp */
4943
4944 t = 1 - hfp;
4945 hbp = max(hbp - t, 1);
4946 hfp = dsi_hbl - (hss + hsa + hse + hbp);
4947
4948 if (hfp < 1 && hsa > 0) {
4949 /* we need to take cycles from hsa */
4950 t = 1 - hfp;
4951 hsa = max(hsa - t, 1);
4952 hfp = dsi_hbl - (hss + hsa + hse + hbp);
4953 }
4954 }
4955
4956 if (hfp < 1)
4957 return false;
4958
4959 dsi_vm->hss = hss;
4960 dsi_vm->hsa = hsa;
4961 dsi_vm->hse = hse;
4962 dsi_vm->hbp = hbp;
4963 dsi_vm->hact = xres;
4964 dsi_vm->hfp = hfp;
4965
4966 dsi_vm->vsa = req_vm->vsw;
4967 dsi_vm->vbp = req_vm->vbp;
4968 dsi_vm->vact = req_vm->y_res;
4969 dsi_vm->vfp = req_vm->vfp;
4970
4971 dsi_vm->trans_mode = cfg->trans_mode;
4972
4973 dsi_vm->blanking_mode = 0;
4974 dsi_vm->hsa_blanking_mode = 1;
4975 dsi_vm->hfp_blanking_mode = 1;
4976 dsi_vm->hbp_blanking_mode = 1;
4977
4978 dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on;
4979 dsi_vm->window_sync = 4;
4980
4981 /* setup DISPC videomode */
4982
4983 dispc_vm = &ctx->dispc_vm;
4984 *dispc_vm = *req_vm;
4985 dispc_vm->pixel_clock = dispc_pck / 1000;
4986
4987 if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
4988 hsa = div64_u64((u64)req_vm->hsw * dispc_pck,
4989 req_pck_nom);
4990 hsa = max(hsa, 1);
4991 } else {
4992 hsa = 1;
4993 }
4994
4995 hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
4996 hbp = max(hbp, 1);
4997
4998 hfp = dispc_hbl - hsa - hbp;
4999 if (hfp < 1) {
5000 int t;
5001 /* we need to take cycles from hbp */
5002
5003 t = 1 - hfp;
5004 hbp = max(hbp - t, 1);
5005 hfp = dispc_hbl - hsa - hbp;
5006
5007 if (hfp < 1) {
5008 /* we need to take cycles from hsa */
5009 t = 1 - hfp;
5010 hsa = max(hsa - t, 1);
5011 hfp = dispc_hbl - hsa - hbp;
5012 }
5013 }
5014
5015 if (hfp < 1)
5016 return false;
5017
5018 dispc_vm->hfp = hfp;
5019 dispc_vm->hsw = hsa;
5020 dispc_vm->hbp = hbp;
5021
5022 return true;
4937} 5023}
4938EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
4939 5024
4940void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev, 5025
4941 struct omap_dss_dsi_videomode_timings *timings) 5026static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
5027 unsigned long pck, void *data)
5028{
5029 struct dsi_clk_calc_ctx *ctx = data;
5030
5031 ctx->dispc_cinfo.lck_div = lckd;
5032 ctx->dispc_cinfo.pck_div = pckd;
5033 ctx->dispc_cinfo.lck = lck;
5034 ctx->dispc_cinfo.pck = pck;
5035
5036 if (dsi_vm_calc_blanking(ctx) == false)
5037 return false;
5038
5039#ifdef PRINT_VERBOSE_VM_TIMINGS
5040 print_dispc_vm("dispc", &ctx->dispc_vm);
5041 print_dsi_vm("dsi ", &ctx->dsi_vm);
5042 print_dispc_vm("req ", ctx->config->timings);
5043 print_dsi_dispc_vm("act ", &ctx->dsi_vm);
5044#endif
5045
5046 return true;
5047}
5048
5049static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
5050 void *data)
5051{
5052 struct dsi_clk_calc_ctx *ctx = data;
5053 unsigned long pck_max;
5054
5055 ctx->dsi_cinfo.regm_dispc = regm_dispc;
5056 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
5057
5058 /*
5059 * In burst mode we can let the dispc pck be arbitrarily high, but it
5060 * limits our scaling abilities. So for now, don't aim too high.
5061 */
5062
5063 if (ctx->config->trans_mode == OMAP_DSS_DSI_BURST_MODE)
5064 pck_max = ctx->req_pck_max + 10000000;
5065 else
5066 pck_max = ctx->req_pck_max;
5067
5068 return dispc_div_calc(dispc, ctx->req_pck_min, pck_max,
5069 dsi_vm_calc_dispc_cb, ctx);
5070}
5071
5072static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint,
5073 unsigned long pll, void *data)
5074{
5075 struct dsi_clk_calc_ctx *ctx = data;
5076
5077 ctx->dsi_cinfo.regn = regn;
5078 ctx->dsi_cinfo.regm = regm;
5079 ctx->dsi_cinfo.fint = fint;
5080 ctx->dsi_cinfo.clkin4ddr = pll;
5081
5082 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
5083 dsi_vm_calc_hsdiv_cb, ctx);
5084}
5085
5086static bool dsi_vm_calc(struct dsi_data *dsi,
5087 const struct omap_dss_dsi_config *cfg,
5088 struct dsi_clk_calc_ctx *ctx)
5089{
5090 const struct omap_video_timings *t = cfg->timings;
5091 unsigned long clkin;
5092 unsigned long pll_min;
5093 unsigned long pll_max;
5094 int ndl = dsi->num_lanes_used - 1;
5095 int bitspp = dsi_get_pixel_size(cfg->pixel_format);
5096 unsigned long byteclk_min;
5097
5098 clkin = clk_get_rate(dsi->sys_clk);
5099
5100 memset(ctx, 0, sizeof(*ctx));
5101 ctx->dsidev = dsi->pdev;
5102 ctx->config = cfg;
5103
5104 ctx->dsi_cinfo.clkin = clkin;
5105
5106 /* these limits should come from the panel driver */
5107 ctx->req_pck_min = t->pixel_clock * 1000 - 1000;
5108 ctx->req_pck_nom = t->pixel_clock * 1000;
5109 ctx->req_pck_max = t->pixel_clock * 1000 + 1000;
5110
5111 byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
5112 pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
5113
5114 if (cfg->trans_mode == OMAP_DSS_DSI_BURST_MODE) {
5115 pll_max = cfg->hs_clk_max * 4;
5116 } else {
5117 unsigned long byteclk_max;
5118 byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp,
5119 ndl * 8);
5120
5121 pll_max = byteclk_max * 4 * 4;
5122 }
5123
5124 return dsi_pll_calc(dsi->pdev, clkin,
5125 pll_min, pll_max,
5126 dsi_vm_calc_pll_cb, ctx);
5127}
5128
5129int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
5130 const struct omap_dss_dsi_config *config)
4942{ 5131{
4943 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 5132 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4944 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5133 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5134 struct dsi_clk_calc_ctx ctx;
5135 bool ok;
5136 int r;
4945 5137
4946 mutex_lock(&dsi->lock); 5138 mutex_lock(&dsi->lock);
4947 5139
4948 dsi->vm_timings = *timings; 5140 dsi->pix_fmt = config->pixel_format;
5141 dsi->mode = config->mode;
5142
5143 if (config->mode == OMAP_DSS_DSI_VIDEO_MODE)
5144 ok = dsi_vm_calc(dsi, config, &ctx);
5145 else
5146 ok = dsi_cm_calc(dsi, config, &ctx);
5147
5148 if (!ok) {
5149 DSSERR("failed to find suitable DSI clock settings\n");
5150 r = -EINVAL;
5151 goto err;
5152 }
5153
5154 dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
5155
5156 r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min,
5157 config->lp_clk_max);
5158 if (r) {
5159 DSSERR("failed to find suitable DSI LP clock settings\n");
5160 goto err;
5161 }
5162
5163 dsi->user_dsi_cinfo = ctx.dsi_cinfo;
5164 dsi->user_dispc_cinfo = ctx.dispc_cinfo;
5165
5166 dsi->timings = ctx.dispc_vm;
5167 dsi->vm_timings = ctx.dsi_vm;
4949 5168
4950 mutex_unlock(&dsi->lock); 5169 mutex_unlock(&dsi->lock);
5170
5171 return 0;
5172err:
5173 mutex_unlock(&dsi->lock);
5174
5175 return r;
4951} 5176}
4952EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings); 5177EXPORT_SYMBOL(omapdss_dsi_set_config);
5178
5179/*
5180 * Return a hardcoded channel for the DSI output. This should work for
5181 * current use cases, but this can be later expanded to either resolve
5182 * the channel in some more dynamic manner, or get the channel as a user
5183 * parameter.
5184 */
5185static enum omap_channel dsi_get_channel(int module_id)
5186{
5187 switch (omapdss_get_version()) {
5188 case OMAPDSS_VER_OMAP24xx:
5189 DSSWARN("DSI not supported\n");
5190 return OMAP_DSS_CHANNEL_LCD;
5191
5192 case OMAPDSS_VER_OMAP34xx_ES1:
5193 case OMAPDSS_VER_OMAP34xx_ES3:
5194 case OMAPDSS_VER_OMAP3630:
5195 case OMAPDSS_VER_AM35xx:
5196 return OMAP_DSS_CHANNEL_LCD;
5197
5198 case OMAPDSS_VER_OMAP4430_ES1:
5199 case OMAPDSS_VER_OMAP4430_ES2:
5200 case OMAPDSS_VER_OMAP4:
5201 switch (module_id) {
5202 case 0:
5203 return OMAP_DSS_CHANNEL_LCD;
5204 case 1:
5205 return OMAP_DSS_CHANNEL_LCD2;
5206 default:
5207 DSSWARN("unsupported module id\n");
5208 return OMAP_DSS_CHANNEL_LCD;
5209 }
5210
5211 case OMAPDSS_VER_OMAP5:
5212 switch (module_id) {
5213 case 0:
5214 return OMAP_DSS_CHANNEL_LCD;
5215 case 1:
5216 return OMAP_DSS_CHANNEL_LCD3;
5217 default:
5218 DSSWARN("unsupported module id\n");
5219 return OMAP_DSS_CHANNEL_LCD;
5220 }
4953 5221
4954static int __init dsi_init_display(struct omap_dss_device *dssdev) 5222 default:
5223 DSSWARN("unsupported DSS version\n");
5224 return OMAP_DSS_CHANNEL_LCD;
5225 }
5226}
5227
5228static int dsi_init_display(struct omap_dss_device *dssdev)
4955{ 5229{
4956 struct platform_device *dsidev = 5230 struct platform_device *dsidev =
4957 dsi_get_dsidev_from_id(dssdev->phy.dsi.module); 5231 dsi_get_dsidev_from_id(dssdev->phy.dsi.module);
@@ -5073,7 +5347,7 @@ static int dsi_get_clocks(struct platform_device *dsidev)
5073 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5347 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5074 struct clk *clk; 5348 struct clk *clk;
5075 5349
5076 clk = clk_get(&dsidev->dev, "fck"); 5350 clk = devm_clk_get(&dsidev->dev, "fck");
5077 if (IS_ERR(clk)) { 5351 if (IS_ERR(clk)) {
5078 DSSERR("can't get fck\n"); 5352 DSSERR("can't get fck\n");
5079 return PTR_ERR(clk); 5353 return PTR_ERR(clk);
@@ -5081,11 +5355,9 @@ static int dsi_get_clocks(struct platform_device *dsidev)
5081 5355
5082 dsi->dss_clk = clk; 5356 dsi->dss_clk = clk;
5083 5357
5084 clk = clk_get(&dsidev->dev, "sys_clk"); 5358 clk = devm_clk_get(&dsidev->dev, "sys_clk");
5085 if (IS_ERR(clk)) { 5359 if (IS_ERR(clk)) {
5086 DSSERR("can't get sys_clk\n"); 5360 DSSERR("can't get sys_clk\n");
5087 clk_put(dsi->dss_clk);
5088 dsi->dss_clk = NULL;
5089 return PTR_ERR(clk); 5361 return PTR_ERR(clk);
5090 } 5362 }
5091 5363
@@ -5094,17 +5366,7 @@ static int dsi_get_clocks(struct platform_device *dsidev)
5094 return 0; 5366 return 0;
5095} 5367}
5096 5368
5097static void dsi_put_clocks(struct platform_device *dsidev) 5369static struct omap_dss_device *dsi_find_dssdev(struct platform_device *pdev)
5098{
5099 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5100
5101 if (dsi->dss_clk)
5102 clk_put(dsi->dss_clk);
5103 if (dsi->sys_clk)
5104 clk_put(dsi->sys_clk);
5105}
5106
5107static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)
5108{ 5370{
5109 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 5371 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
5110 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev); 5372 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
@@ -5136,7 +5398,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
5136 return def_dssdev; 5398 return def_dssdev;
5137} 5399}
5138 5400
5139static void __init dsi_probe_pdata(struct platform_device *dsidev) 5401static int dsi_probe_pdata(struct platform_device *dsidev)
5140{ 5402{
5141 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5403 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5142 struct omap_dss_device *plat_dssdev; 5404 struct omap_dss_device *plat_dssdev;
@@ -5146,11 +5408,11 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
5146 plat_dssdev = dsi_find_dssdev(dsidev); 5408 plat_dssdev = dsi_find_dssdev(dsidev);
5147 5409
5148 if (!plat_dssdev) 5410 if (!plat_dssdev)
5149 return; 5411 return 0;
5150 5412
5151 dssdev = dss_alloc_and_init_device(&dsidev->dev); 5413 dssdev = dss_alloc_and_init_device(&dsidev->dev);
5152 if (!dssdev) 5414 if (!dssdev)
5153 return; 5415 return -ENOMEM;
5154 5416
5155 dss_copy_device_pdata(dssdev, plat_dssdev); 5417 dss_copy_device_pdata(dssdev, plat_dssdev);
5156 5418
@@ -5158,7 +5420,7 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
5158 if (r) { 5420 if (r) {
5159 DSSERR("device %s init failed: %d\n", dssdev->name, r); 5421 DSSERR("device %s init failed: %d\n", dssdev->name, r);
5160 dss_put_device(dssdev); 5422 dss_put_device(dssdev);
5161 return; 5423 return r;
5162 } 5424 }
5163 5425
5164 r = omapdss_output_set_device(&dsi->output, dssdev); 5426 r = omapdss_output_set_device(&dsi->output, dssdev);
@@ -5166,7 +5428,7 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
5166 DSSERR("failed to connect output to new device: %s\n", 5428 DSSERR("failed to connect output to new device: %s\n",
5167 dssdev->name); 5429 dssdev->name);
5168 dss_put_device(dssdev); 5430 dss_put_device(dssdev);
5169 return; 5431 return r;
5170 } 5432 }
5171 5433
5172 r = dss_add_device(dssdev); 5434 r = dss_add_device(dssdev);
@@ -5174,11 +5436,13 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
5174 DSSERR("device %s register failed: %d\n", dssdev->name, r); 5436 DSSERR("device %s register failed: %d\n", dssdev->name, r);
5175 omapdss_output_unset_device(&dsi->output); 5437 omapdss_output_unset_device(&dsi->output);
5176 dss_put_device(dssdev); 5438 dss_put_device(dssdev);
5177 return; 5439 return r;
5178 } 5440 }
5441
5442 return 0;
5179} 5443}
5180 5444
5181static void __init dsi_init_output(struct platform_device *dsidev) 5445static void dsi_init_output(struct platform_device *dsidev)
5182{ 5446{
5183 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5447 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5184 struct omap_dss_output *out = &dsi->output; 5448 struct omap_dss_output *out = &dsi->output;
@@ -5188,11 +5452,13 @@ static void __init dsi_init_output(struct platform_device *dsidev)
5188 OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; 5452 OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
5189 5453
5190 out->type = OMAP_DISPLAY_TYPE_DSI; 5454 out->type = OMAP_DISPLAY_TYPE_DSI;
5455 out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
5456 out->dispc_channel = dsi_get_channel(dsi->module_id);
5191 5457
5192 dss_register_output(out); 5458 dss_register_output(out);
5193} 5459}
5194 5460
5195static void __exit dsi_uninit_output(struct platform_device *dsidev) 5461static void dsi_uninit_output(struct platform_device *dsidev)
5196{ 5462{
5197 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5463 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5198 struct omap_dss_output *out = &dsi->output; 5464 struct omap_dss_output *out = &dsi->output;
@@ -5201,7 +5467,7 @@ static void __exit dsi_uninit_output(struct platform_device *dsidev)
5201} 5467}
5202 5468
5203/* DSI1 HW IP initialisation */ 5469/* DSI1 HW IP initialisation */
5204static int __init omap_dsihw_probe(struct platform_device *dsidev) 5470static int omap_dsihw_probe(struct platform_device *dsidev)
5205{ 5471{
5206 u32 rev; 5472 u32 rev;
5207 int r, i; 5473 int r, i;
@@ -5293,9 +5559,17 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
5293 else 5559 else
5294 dsi->num_lanes_supported = 3; 5560 dsi->num_lanes_supported = 3;
5295 5561
5562 dsi->line_buffer_size = dsi_get_line_buf_size(dsidev);
5563
5296 dsi_init_output(dsidev); 5564 dsi_init_output(dsidev);
5297 5565
5298 dsi_probe_pdata(dsidev); 5566 r = dsi_probe_pdata(dsidev);
5567 if (r) {
5568 dsi_runtime_put(dsidev);
5569 dsi_uninit_output(dsidev);
5570 pm_runtime_disable(&dsidev->dev);
5571 return r;
5572 }
5299 5573
5300 dsi_runtime_put(dsidev); 5574 dsi_runtime_put(dsidev);
5301 5575
@@ -5314,7 +5588,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
5314 5588
5315err_runtime_get: 5589err_runtime_get:
5316 pm_runtime_disable(&dsidev->dev); 5590 pm_runtime_disable(&dsidev->dev);
5317 dsi_put_clocks(dsidev);
5318 return r; 5591 return r;
5319} 5592}
5320 5593
@@ -5330,8 +5603,6 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
5330 5603
5331 pm_runtime_disable(&dsidev->dev); 5604 pm_runtime_disable(&dsidev->dev);
5332 5605
5333 dsi_put_clocks(dsidev);
5334
5335 if (dsi->vdds_dsi_reg != NULL) { 5606 if (dsi->vdds_dsi_reg != NULL) {
5336 if (dsi->vdds_dsi_enabled) { 5607 if (dsi->vdds_dsi_enabled) {
5337 regulator_disable(dsi->vdds_dsi_reg); 5608 regulator_disable(dsi->vdds_dsi_reg);
@@ -5369,6 +5640,7 @@ static const struct dev_pm_ops dsi_pm_ops = {
5369}; 5640};
5370 5641
5371static struct platform_driver omap_dsihw_driver = { 5642static struct platform_driver omap_dsihw_driver = {
5643 .probe = omap_dsihw_probe,
5372 .remove = __exit_p(omap_dsihw_remove), 5644 .remove = __exit_p(omap_dsihw_remove),
5373 .driver = { 5645 .driver = {
5374 .name = "omapdss_dsi", 5646 .name = "omapdss_dsi",
@@ -5379,7 +5651,7 @@ static struct platform_driver omap_dsihw_driver = {
5379 5651
5380int __init dsi_init_platform_driver(void) 5652int __init dsi_init_platform_driver(void)
5381{ 5653{
5382 return platform_driver_probe(&omap_dsihw_driver, omap_dsihw_probe); 5654 return platform_driver_register(&omap_dsihw_driver);
5383} 5655}
5384 5656
5385void __exit dsi_uninit_platform_driver(void) 5657void __exit dsi_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 054c2a22b3f1..94f66f9f10a3 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -473,6 +473,47 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
473 return 0; 473 return 0;
474} 474}
475 475
476bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
477{
478 int fckd, fckd_start, fckd_stop;
479 unsigned long fck;
480 unsigned long fck_hw_max;
481 unsigned long fckd_hw_max;
482 unsigned long prate;
483 unsigned m;
484
485 if (dss.dpll4_m4_ck == NULL) {
486 /*
487 * TODO: dss1_fclk can be changed on OMAP2, but the available
488 * dividers are not continuous. We just use the pre-set rate for
489 * now.
490 */
491 fck = clk_get_rate(dss.dss_clk);
492 fckd = 1;
493 return func(fckd, fck, data);
494 }
495
496 fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
497 fckd_hw_max = dss.feat->fck_div_max;
498
499 m = dss.feat->dss_fck_multiplier;
500 prate = dss_get_dpll4_rate();
501
502 fck_min = fck_min ? fck_min : 1;
503
504 fckd_start = min(prate * m / fck_min, fckd_hw_max);
505 fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
506
507 for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
508 fck = prate / fckd * m;
509
510 if (func(fckd, fck, data))
511 return true;
512 }
513
514 return false;
515}
516
476int dss_set_clock_div(struct dss_clock_info *cinfo) 517int dss_set_clock_div(struct dss_clock_info *cinfo)
477{ 518{
478 if (dss.dpll4_m4_ck) { 519 if (dss.dpll4_m4_ck) {
@@ -482,7 +523,8 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
482 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 523 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
483 DSSDBG("dpll4_m4 = %ld\n", prate); 524 DSSDBG("dpll4_m4 = %ld\n", prate);
484 525
485 r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); 526 r = clk_set_rate(dss.dpll4_m4_ck,
527 DIV_ROUND_UP(prate, cinfo->fck_div));
486 if (r) 528 if (r)
487 return r; 529 return r;
488 } else { 530 } else {
@@ -492,7 +534,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
492 534
493 dss.dss_clk_rate = clk_get_rate(dss.dss_clk); 535 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
494 536
495 WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch"); 537 WARN_ONCE(dss.dss_clk_rate != cinfo->fck,
538 "clk rate mismatch: %lu != %lu", dss.dss_clk_rate,
539 cinfo->fck);
496 540
497 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); 541 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
498 542
@@ -542,121 +586,6 @@ static int dss_setup_default_clock(void)
542 return 0; 586 return 0;
543} 587}
544 588
545int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
546 struct dispc_clock_info *dispc_cinfo)
547{
548 unsigned long prate;
549 struct dss_clock_info best_dss;
550 struct dispc_clock_info best_dispc;
551
552 unsigned long fck, max_dss_fck;
553
554 u16 fck_div;
555
556 int match = 0;
557 int min_fck_per_pck;
558
559 prate = dss_get_dpll4_rate();
560
561 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
562
563 fck = clk_get_rate(dss.dss_clk);
564 if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
565 dss.cache_dss_cinfo.fck == fck) {
566 DSSDBG("dispc clock info found from cache.\n");
567 *dss_cinfo = dss.cache_dss_cinfo;
568 *dispc_cinfo = dss.cache_dispc_cinfo;
569 return 0;
570 }
571
572 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
573
574 if (min_fck_per_pck &&
575 req_pck * min_fck_per_pck > max_dss_fck) {
576 DSSERR("Requested pixel clock not possible with the current "
577 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
578 "the constraint off.\n");
579 min_fck_per_pck = 0;
580 }
581
582retry:
583 memset(&best_dss, 0, sizeof(best_dss));
584 memset(&best_dispc, 0, sizeof(best_dispc));
585
586 if (dss.dpll4_m4_ck == NULL) {
587 struct dispc_clock_info cur_dispc;
588 /* XXX can we change the clock on omap2? */
589 fck = clk_get_rate(dss.dss_clk);
590 fck_div = 1;
591
592 dispc_find_clk_divs(req_pck, fck, &cur_dispc);
593 match = 1;
594
595 best_dss.fck = fck;
596 best_dss.fck_div = fck_div;
597
598 best_dispc = cur_dispc;
599
600 goto found;
601 } else {
602 for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
603 struct dispc_clock_info cur_dispc;
604
605 fck = prate / fck_div * dss.feat->dss_fck_multiplier;
606
607 if (fck > max_dss_fck)
608 continue;
609
610 if (min_fck_per_pck &&
611 fck < req_pck * min_fck_per_pck)
612 continue;
613
614 match = 1;
615
616 dispc_find_clk_divs(req_pck, fck, &cur_dispc);
617
618 if (abs(cur_dispc.pck - req_pck) <
619 abs(best_dispc.pck - req_pck)) {
620
621 best_dss.fck = fck;
622 best_dss.fck_div = fck_div;
623
624 best_dispc = cur_dispc;
625
626 if (cur_dispc.pck == req_pck)
627 goto found;
628 }
629 }
630 }
631
632found:
633 if (!match) {
634 if (min_fck_per_pck) {
635 DSSERR("Could not find suitable clock settings.\n"
636 "Turning FCK/PCK constraint off and"
637 "trying again.\n");
638 min_fck_per_pck = 0;
639 goto retry;
640 }
641
642 DSSERR("Could not find suitable clock settings.\n");
643
644 return -EINVAL;
645 }
646
647 if (dss_cinfo)
648 *dss_cinfo = best_dss;
649 if (dispc_cinfo)
650 *dispc_cinfo = best_dispc;
651
652 dss.cache_req_pck = req_pck;
653 dss.cache_prate = prate;
654 dss.cache_dss_cinfo = best_dss;
655 dss.cache_dispc_cinfo = best_dispc;
656
657 return 0;
658}
659
660void dss_set_venc_output(enum omap_dss_venc_type type) 589void dss_set_venc_output(enum omap_dss_venc_type type)
661{ 590{
662 int l = 0; 591 int l = 0;
@@ -767,13 +696,11 @@ int dss_dpi_select_source(enum omap_channel channel)
767static int dss_get_clocks(void) 696static int dss_get_clocks(void)
768{ 697{
769 struct clk *clk; 698 struct clk *clk;
770 int r;
771 699
772 clk = clk_get(&dss.pdev->dev, "fck"); 700 clk = devm_clk_get(&dss.pdev->dev, "fck");
773 if (IS_ERR(clk)) { 701 if (IS_ERR(clk)) {
774 DSSERR("can't get clock fck\n"); 702 DSSERR("can't get clock fck\n");
775 r = PTR_ERR(clk); 703 return PTR_ERR(clk);
776 goto err;
777 } 704 }
778 705
779 dss.dss_clk = clk; 706 dss.dss_clk = clk;
@@ -782,8 +709,7 @@ static int dss_get_clocks(void)
782 clk = clk_get(NULL, dss.feat->clk_name); 709 clk = clk_get(NULL, dss.feat->clk_name);
783 if (IS_ERR(clk)) { 710 if (IS_ERR(clk)) {
784 DSSERR("Failed to get %s\n", dss.feat->clk_name); 711 DSSERR("Failed to get %s\n", dss.feat->clk_name);
785 r = PTR_ERR(clk); 712 return PTR_ERR(clk);
786 goto err;
787 } 713 }
788 } else { 714 } else {
789 clk = NULL; 715 clk = NULL;
@@ -792,21 +718,12 @@ static int dss_get_clocks(void)
792 dss.dpll4_m4_ck = clk; 718 dss.dpll4_m4_ck = clk;
793 719
794 return 0; 720 return 0;
795
796err:
797 if (dss.dss_clk)
798 clk_put(dss.dss_clk);
799 if (dss.dpll4_m4_ck)
800 clk_put(dss.dpll4_m4_ck);
801
802 return r;
803} 721}
804 722
805static void dss_put_clocks(void) 723static void dss_put_clocks(void)
806{ 724{
807 if (dss.dpll4_m4_ck) 725 if (dss.dpll4_m4_ck)
808 clk_put(dss.dpll4_m4_ck); 726 clk_put(dss.dpll4_m4_ck);
809 clk_put(dss.dss_clk);
810} 727}
811 728
812static int dss_runtime_get(void) 729static int dss_runtime_get(void)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 610c8e563daa..84758936429d 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -268,14 +268,21 @@ void dss_set_dac_pwrdn_bgz(bool enable);
268unsigned long dss_get_dpll4_rate(void); 268unsigned long dss_get_dpll4_rate(void);
269int dss_calc_clock_rates(struct dss_clock_info *cinfo); 269int dss_calc_clock_rates(struct dss_clock_info *cinfo);
270int dss_set_clock_div(struct dss_clock_info *cinfo); 270int dss_set_clock_div(struct dss_clock_info *cinfo);
271int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, 271
272 struct dispc_clock_info *dispc_cinfo); 272typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
273bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
273 274
274/* SDI */ 275/* SDI */
275int sdi_init_platform_driver(void) __init; 276int sdi_init_platform_driver(void) __init;
276void sdi_uninit_platform_driver(void) __exit; 277void sdi_uninit_platform_driver(void) __exit;
277 278
278/* DSI */ 279/* DSI */
280
281typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
282 unsigned long pll, void *data);
283typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
284 void *data);
285
279#ifdef CONFIG_OMAP2_DSS_DSI 286#ifdef CONFIG_OMAP2_DSS_DSI
280 287
281struct dentry; 288struct dentry;
@@ -292,12 +299,17 @@ void dsi_dump_clocks(struct seq_file *s);
292void dsi_irq_handler(void); 299void dsi_irq_handler(void);
293u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); 300u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
294 301
302unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
303
304bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
305 unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
306bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
307 unsigned long pll_min, unsigned long pll_max,
308 dsi_pll_calc_func func, void *data);
309
295unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); 310unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
296int dsi_pll_set_clock_div(struct platform_device *dsidev, 311int dsi_pll_set_clock_div(struct platform_device *dsidev,
297 struct dsi_clock_info *cinfo); 312 struct dsi_clock_info *cinfo);
298int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
299 unsigned long req_pck, struct dsi_clock_info *cinfo,
300 struct dispc_clock_info *dispc_cinfo);
301int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, 313int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
302 bool enable_hsdiv); 314 bool enable_hsdiv);
303void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); 315void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
@@ -328,14 +340,6 @@ static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
328 WARN("%s: DSI not compiled in\n", __func__); 340 WARN("%s: DSI not compiled in\n", __func__);
329 return -ENODEV; 341 return -ENODEV;
330} 342}
331static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
332 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}
339static inline int dsi_pll_init(struct platform_device *dsidev, 343static inline int dsi_pll_init(struct platform_device *dsidev,
340 bool enable_hsclk, bool enable_hsdiv) 344 bool enable_hsclk, bool enable_hsdiv)
341{ 345{
@@ -356,6 +360,27 @@ static inline struct platform_device *dsi_get_dsidev_from_id(int module)
356{ 360{
357 return NULL; 361 return NULL;
358} 362}
363
364static inline unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
365{
366 return 0;
367}
368
369static inline bool dsi_hsdiv_calc(struct platform_device *dsidev,
370 unsigned long pll, unsigned long out_min,
371 dsi_hsdiv_calc_func func, void *data)
372{
373 return false;
374}
375
376static inline bool dsi_pll_calc(struct platform_device *dsidev,
377 unsigned long clkin,
378 unsigned long pll_min, unsigned long pll_max,
379 dsi_pll_calc_func func, void *data)
380{
381 return false;
382}
383
359#endif 384#endif
360 385
361/* DPI */ 386/* DPI */
@@ -376,11 +401,15 @@ void dispc_enable_fifomerge(bool enable);
376void dispc_enable_gamma_table(bool enable); 401void dispc_enable_gamma_table(bool enable);
377void dispc_set_loadmode(enum omap_dss_load_mode mode); 402void dispc_set_loadmode(enum omap_dss_load_mode mode);
378 403
404typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck,
405 unsigned long pck, void *data);
406bool dispc_div_calc(unsigned long dispc,
407 unsigned long pck_min, unsigned long pck_max,
408 dispc_div_calc_func func, void *data);
409
379bool dispc_mgr_timings_ok(enum omap_channel channel, 410bool dispc_mgr_timings_ok(enum omap_channel channel,
380 const struct omap_video_timings *timings); 411 const struct omap_video_timings *timings);
381unsigned long dispc_fclk_rate(void); 412unsigned long dispc_fclk_rate(void);
382void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck,
383 struct dispc_clock_info *cinfo);
384int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, 413int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
385 struct dispc_clock_info *cinfo); 414 struct dispc_clock_info *cinfo);
386 415
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 7f791aeda4d2..77dbe0cfb34c 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -414,7 +414,7 @@ static const char * const omap5_dss_clk_source_names[] = {
414}; 414};
415 415
416static const struct dss_param_range omap2_dss_param_range[] = { 416static const struct dss_param_range omap2_dss_param_range[] = {
417 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, 417 [FEAT_PARAM_DSS_FCK] = { 0, 133000000 },
418 [FEAT_PARAM_DSS_PCD] = { 2, 255 }, 418 [FEAT_PARAM_DSS_PCD] = { 2, 255 },
419 [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, 419 [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 },
420 [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, 420 [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 },
@@ -459,15 +459,15 @@ static const struct dss_param_range omap4_dss_param_range[] = {
459}; 459};
460 460
461static const struct dss_param_range omap5_dss_param_range[] = { 461static const struct dss_param_range omap5_dss_param_range[] = {
462 [FEAT_PARAM_DSS_FCK] = { 0, 200000000 }, 462 [FEAT_PARAM_DSS_FCK] = { 0, 209250000 },
463 [FEAT_PARAM_DSS_PCD] = { 1, 255 }, 463 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
464 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, 464 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
465 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, 465 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
466 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, 466 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
467 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, 467 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
468 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, 468 [FEAT_PARAM_DSIPLL_FINT] = { 150000, 52000000 },
469 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 469 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
470 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, 470 [FEAT_PARAM_DSI_FCK] = { 0, 209250000 },
471 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 471 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
472 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, 472 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
473}; 473};
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 72923645dcce..17f4d55c621c 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -328,7 +328,7 @@ static void hdmi_runtime_put(void)
328 WARN_ON(r < 0 && r != -ENOSYS); 328 WARN_ON(r < 0 && r != -ENOSYS);
329} 329}
330 330
331static int __init hdmi_init_display(struct omap_dss_device *dssdev) 331static int hdmi_init_display(struct omap_dss_device *dssdev)
332{ 332{
333 int r; 333 int r;
334 334
@@ -472,17 +472,12 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
472 * Input clock is predivided by N + 1 472 * Input clock is predivided by N + 1
473 * out put of which is reference clk 473 * out put of which is reference clk
474 */ 474 */
475 if (dssdev->clocks.hdmi.regn == 0) 475
476 pi->regn = HDMI_DEFAULT_REGN; 476 pi->regn = HDMI_DEFAULT_REGN;
477 else
478 pi->regn = dssdev->clocks.hdmi.regn;
479 477
480 refclk = clkin / pi->regn; 478 refclk = clkin / pi->regn;
481 479
482 if (dssdev->clocks.hdmi.regm2 == 0) 480 pi->regm2 = HDMI_DEFAULT_REGM2;
483 pi->regm2 = HDMI_DEFAULT_REGM2;
484 else
485 pi->regm2 = dssdev->clocks.hdmi.regm2;
486 481
487 /* 482 /*
488 * multiplier is pixel_clk/ref_clk 483 * multiplier is pixel_clk/ref_clk
@@ -804,7 +799,7 @@ static int hdmi_get_clocks(struct platform_device *pdev)
804{ 799{
805 struct clk *clk; 800 struct clk *clk;
806 801
807 clk = clk_get(&pdev->dev, "sys_clk"); 802 clk = devm_clk_get(&pdev->dev, "sys_clk");
808 if (IS_ERR(clk)) { 803 if (IS_ERR(clk)) {
809 DSSERR("can't get sys_clk\n"); 804 DSSERR("can't get sys_clk\n");
810 return PTR_ERR(clk); 805 return PTR_ERR(clk);
@@ -815,12 +810,6 @@ static int hdmi_get_clocks(struct platform_device *pdev)
815 return 0; 810 return 0;
816} 811}
817 812
818static void hdmi_put_clocks(void)
819{
820 if (hdmi.sys_clk)
821 clk_put(hdmi.sys_clk);
822}
823
824#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) 813#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
825int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts) 814int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
826{ 815{
@@ -965,7 +954,7 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
965 954
966#endif 955#endif
967 956
968static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev) 957static struct omap_dss_device *hdmi_find_dssdev(struct platform_device *pdev)
969{ 958{
970 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 959 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
971 const char *def_disp_name = omapdss_get_default_display_name(); 960 const char *def_disp_name = omapdss_get_default_display_name();
@@ -993,7 +982,7 @@ static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *
993 return def_dssdev; 982 return def_dssdev;
994} 983}
995 984
996static void __init hdmi_probe_pdata(struct platform_device *pdev) 985static int hdmi_probe_pdata(struct platform_device *pdev)
997{ 986{
998 struct omap_dss_device *plat_dssdev; 987 struct omap_dss_device *plat_dssdev;
999 struct omap_dss_device *dssdev; 988 struct omap_dss_device *dssdev;
@@ -1003,11 +992,11 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
1003 plat_dssdev = hdmi_find_dssdev(pdev); 992 plat_dssdev = hdmi_find_dssdev(pdev);
1004 993
1005 if (!plat_dssdev) 994 if (!plat_dssdev)
1006 return; 995 return 0;
1007 996
1008 dssdev = dss_alloc_and_init_device(&pdev->dev); 997 dssdev = dss_alloc_and_init_device(&pdev->dev);
1009 if (!dssdev) 998 if (!dssdev)
1010 return; 999 return -ENOMEM;
1011 1000
1012 dss_copy_device_pdata(dssdev, plat_dssdev); 1001 dss_copy_device_pdata(dssdev, plat_dssdev);
1013 1002
@@ -1017,13 +1006,11 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
1017 hdmi.ls_oe_gpio = priv->ls_oe_gpio; 1006 hdmi.ls_oe_gpio = priv->ls_oe_gpio;
1018 hdmi.hpd_gpio = priv->hpd_gpio; 1007 hdmi.hpd_gpio = priv->hpd_gpio;
1019 1008
1020 dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
1021
1022 r = hdmi_init_display(dssdev); 1009 r = hdmi_init_display(dssdev);
1023 if (r) { 1010 if (r) {
1024 DSSERR("device %s init failed: %d\n", dssdev->name, r); 1011 DSSERR("device %s init failed: %d\n", dssdev->name, r);
1025 dss_put_device(dssdev); 1012 dss_put_device(dssdev);
1026 return; 1013 return r;
1027 } 1014 }
1028 1015
1029 r = omapdss_output_set_device(&hdmi.output, dssdev); 1016 r = omapdss_output_set_device(&hdmi.output, dssdev);
@@ -1031,7 +1018,7 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
1031 DSSERR("failed to connect output to new device: %s\n", 1018 DSSERR("failed to connect output to new device: %s\n",
1032 dssdev->name); 1019 dssdev->name);
1033 dss_put_device(dssdev); 1020 dss_put_device(dssdev);
1034 return; 1021 return r;
1035 } 1022 }
1036 1023
1037 r = dss_add_device(dssdev); 1024 r = dss_add_device(dssdev);
@@ -1040,17 +1027,21 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
1040 omapdss_output_unset_device(&hdmi.output); 1027 omapdss_output_unset_device(&hdmi.output);
1041 hdmi_uninit_display(dssdev); 1028 hdmi_uninit_display(dssdev);
1042 dss_put_device(dssdev); 1029 dss_put_device(dssdev);
1043 return; 1030 return r;
1044 } 1031 }
1032
1033 return 0;
1045} 1034}
1046 1035
1047static void __init hdmi_init_output(struct platform_device *pdev) 1036static void hdmi_init_output(struct platform_device *pdev)
1048{ 1037{
1049 struct omap_dss_output *out = &hdmi.output; 1038 struct omap_dss_output *out = &hdmi.output;
1050 1039
1051 out->pdev = pdev; 1040 out->pdev = pdev;
1052 out->id = OMAP_DSS_OUTPUT_HDMI; 1041 out->id = OMAP_DSS_OUTPUT_HDMI;
1053 out->type = OMAP_DISPLAY_TYPE_HDMI; 1042 out->type = OMAP_DISPLAY_TYPE_HDMI;
1043 out->name = "hdmi.0";
1044 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
1054 1045
1055 dss_register_output(out); 1046 dss_register_output(out);
1056} 1047}
@@ -1063,7 +1054,7 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev)
1063} 1054}
1064 1055
1065/* HDMI HW IP initialisation */ 1056/* HDMI HW IP initialisation */
1066static int __init omapdss_hdmihw_probe(struct platform_device *pdev) 1057static int omapdss_hdmihw_probe(struct platform_device *pdev)
1067{ 1058{
1068 struct resource *res; 1059 struct resource *res;
1069 int r; 1060 int r;
@@ -1097,23 +1088,25 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
1097 hdmi.ip_data.pll_offset = HDMI_PLLCTRL; 1088 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
1098 hdmi.ip_data.phy_offset = HDMI_PHY; 1089 hdmi.ip_data.phy_offset = HDMI_PHY;
1099 1090
1091 hdmi_init_output(pdev);
1092
1100 r = hdmi_panel_init(); 1093 r = hdmi_panel_init();
1101 if (r) { 1094 if (r) {
1102 DSSERR("can't init panel\n"); 1095 DSSERR("can't init panel\n");
1103 goto err_panel_init; 1096 return r;
1104 } 1097 }
1105 1098
1106 dss_debugfs_create_file("hdmi", hdmi_dump_regs); 1099 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
1107 1100
1108 hdmi_init_output(pdev); 1101 r = hdmi_probe_pdata(pdev);
1109 1102 if (r) {
1110 hdmi_probe_pdata(pdev); 1103 hdmi_panel_exit();
1104 hdmi_uninit_output(pdev);
1105 pm_runtime_disable(&pdev->dev);
1106 return r;
1107 }
1111 1108
1112 return 0; 1109 return 0;
1113
1114err_panel_init:
1115 hdmi_put_clocks();
1116 return r;
1117} 1110}
1118 1111
1119static int __exit hdmi_remove_child(struct device *dev, void *data) 1112static int __exit hdmi_remove_child(struct device *dev, void *data)
@@ -1135,8 +1128,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
1135 1128
1136 pm_runtime_disable(&pdev->dev); 1129 pm_runtime_disable(&pdev->dev);
1137 1130
1138 hdmi_put_clocks();
1139
1140 return 0; 1131 return 0;
1141} 1132}
1142 1133
@@ -1168,6 +1159,7 @@ static const struct dev_pm_ops hdmi_pm_ops = {
1168}; 1159};
1169 1160
1170static struct platform_driver omapdss_hdmihw_driver = { 1161static struct platform_driver omapdss_hdmihw_driver = {
1162 .probe = omapdss_hdmihw_probe,
1171 .remove = __exit_p(omapdss_hdmihw_remove), 1163 .remove = __exit_p(omapdss_hdmihw_remove),
1172 .driver = { 1164 .driver = {
1173 .name = "omapdss_hdmi", 1165 .name = "omapdss_hdmi",
@@ -1178,7 +1170,7 @@ static struct platform_driver omapdss_hdmihw_driver = {
1178 1170
1179int __init hdmi_init_platform_driver(void) 1171int __init hdmi_init_platform_driver(void)
1180{ 1172{
1181 return platform_driver_probe(&omapdss_hdmihw_driver, omapdss_hdmihw_probe); 1173 return platform_driver_register(&omapdss_hdmihw_driver);
1182} 1174}
1183 1175
1184void __exit hdmi_uninit_platform_driver(void) 1176void __exit hdmi_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
index 79dea1a1a732..5214df63e0a9 100644
--- a/drivers/video/omap2/dss/output.c
+++ b/drivers/video/omap2/dss/output.c
@@ -113,6 +113,7 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
113 113
114 return NULL; 114 return NULL;
115} 115}
116EXPORT_SYMBOL(omap_dss_get_output);
116 117
117static const struct dss_mgr_ops *dss_mgr_ops; 118static const struct dss_mgr_ops *dss_mgr_ops;
118 119
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index e903dd3f54d9..1a17dd1447dc 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -943,13 +943,13 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
943} 943}
944EXPORT_SYMBOL(omapdss_rfbi_display_disable); 944EXPORT_SYMBOL(omapdss_rfbi_display_disable);
945 945
946static int __init rfbi_init_display(struct omap_dss_device *dssdev) 946static int rfbi_init_display(struct omap_dss_device *dssdev)
947{ 947{
948 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; 948 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
949 return 0; 949 return 0;
950} 950}
951 951
952static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev) 952static struct omap_dss_device *rfbi_find_dssdev(struct platform_device *pdev)
953{ 953{
954 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 954 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
955 const char *def_disp_name = omapdss_get_default_display_name(); 955 const char *def_disp_name = omapdss_get_default_display_name();
@@ -977,7 +977,7 @@ static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *
977 return def_dssdev; 977 return def_dssdev;
978} 978}
979 979
980static void __init rfbi_probe_pdata(struct platform_device *rfbidev) 980static int rfbi_probe_pdata(struct platform_device *rfbidev)
981{ 981{
982 struct omap_dss_device *plat_dssdev; 982 struct omap_dss_device *plat_dssdev;
983 struct omap_dss_device *dssdev; 983 struct omap_dss_device *dssdev;
@@ -986,11 +986,11 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
986 plat_dssdev = rfbi_find_dssdev(rfbidev); 986 plat_dssdev = rfbi_find_dssdev(rfbidev);
987 987
988 if (!plat_dssdev) 988 if (!plat_dssdev)
989 return; 989 return 0;
990 990
991 dssdev = dss_alloc_and_init_device(&rfbidev->dev); 991 dssdev = dss_alloc_and_init_device(&rfbidev->dev);
992 if (!dssdev) 992 if (!dssdev)
993 return; 993 return -ENOMEM;
994 994
995 dss_copy_device_pdata(dssdev, plat_dssdev); 995 dss_copy_device_pdata(dssdev, plat_dssdev);
996 996
@@ -998,7 +998,7 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
998 if (r) { 998 if (r) {
999 DSSERR("device %s init failed: %d\n", dssdev->name, r); 999 DSSERR("device %s init failed: %d\n", dssdev->name, r);
1000 dss_put_device(dssdev); 1000 dss_put_device(dssdev);
1001 return; 1001 return r;
1002 } 1002 }
1003 1003
1004 r = omapdss_output_set_device(&rfbi.output, dssdev); 1004 r = omapdss_output_set_device(&rfbi.output, dssdev);
@@ -1006,7 +1006,7 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
1006 DSSERR("failed to connect output to new device: %s\n", 1006 DSSERR("failed to connect output to new device: %s\n",
1007 dssdev->name); 1007 dssdev->name);
1008 dss_put_device(dssdev); 1008 dss_put_device(dssdev);
1009 return; 1009 return r;
1010 } 1010 }
1011 1011
1012 r = dss_add_device(dssdev); 1012 r = dss_add_device(dssdev);
@@ -1014,17 +1014,21 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
1014 DSSERR("device %s register failed: %d\n", dssdev->name, r); 1014 DSSERR("device %s register failed: %d\n", dssdev->name, r);
1015 omapdss_output_unset_device(&rfbi.output); 1015 omapdss_output_unset_device(&rfbi.output);
1016 dss_put_device(dssdev); 1016 dss_put_device(dssdev);
1017 return; 1017 return r;
1018 } 1018 }
1019
1020 return 0;
1019} 1021}
1020 1022
1021static void __init rfbi_init_output(struct platform_device *pdev) 1023static void rfbi_init_output(struct platform_device *pdev)
1022{ 1024{
1023 struct omap_dss_output *out = &rfbi.output; 1025 struct omap_dss_output *out = &rfbi.output;
1024 1026
1025 out->pdev = pdev; 1027 out->pdev = pdev;
1026 out->id = OMAP_DSS_OUTPUT_DBI; 1028 out->id = OMAP_DSS_OUTPUT_DBI;
1027 out->type = OMAP_DISPLAY_TYPE_DBI; 1029 out->type = OMAP_DISPLAY_TYPE_DBI;
1030 out->name = "rfbi.0";
1031 out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
1028 1032
1029 dss_register_output(out); 1033 dss_register_output(out);
1030} 1034}
@@ -1037,7 +1041,7 @@ static void __exit rfbi_uninit_output(struct platform_device *pdev)
1037} 1041}
1038 1042
1039/* RFBI HW IP initialisation */ 1043/* RFBI HW IP initialisation */
1040static int __init omap_rfbihw_probe(struct platform_device *pdev) 1044static int omap_rfbihw_probe(struct platform_device *pdev)
1041{ 1045{
1042 u32 rev; 1046 u32 rev;
1043 struct resource *rfbi_mem; 1047 struct resource *rfbi_mem;
@@ -1089,7 +1093,12 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev)
1089 1093
1090 rfbi_init_output(pdev); 1094 rfbi_init_output(pdev);
1091 1095
1092 rfbi_probe_pdata(pdev); 1096 r = rfbi_probe_pdata(pdev);
1097 if (r) {
1098 rfbi_uninit_output(pdev);
1099 pm_runtime_disable(&pdev->dev);
1100 return r;
1101 }
1093 1102
1094 return 0; 1103 return 0;
1095 1104
@@ -1133,6 +1142,7 @@ static const struct dev_pm_ops rfbi_pm_ops = {
1133}; 1142};
1134 1143
1135static struct platform_driver omap_rfbihw_driver = { 1144static struct platform_driver omap_rfbihw_driver = {
1145 .probe = omap_rfbihw_probe,
1136 .remove = __exit_p(omap_rfbihw_remove), 1146 .remove = __exit_p(omap_rfbihw_remove),
1137 .driver = { 1147 .driver = {
1138 .name = "omapdss_rfbi", 1148 .name = "omapdss_rfbi",
@@ -1143,7 +1153,7 @@ static struct platform_driver omap_rfbihw_driver = {
1143 1153
1144int __init rfbi_init_platform_driver(void) 1154int __init rfbi_init_platform_driver(void)
1145{ 1155{
1146 return platform_driver_probe(&omap_rfbihw_driver, omap_rfbihw_probe); 1156 return platform_driver_register(&omap_rfbihw_driver);
1147} 1157}
1148 1158
1149void __exit rfbi_uninit_platform_driver(void) 1159void __exit rfbi_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 62b5374ce438..0bcd30272f69 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -41,6 +41,72 @@ static struct {
41 struct omap_dss_output output; 41 struct omap_dss_output output;
42} sdi; 42} sdi;
43 43
44struct sdi_clk_calc_ctx {
45 unsigned long pck_min, pck_max;
46
47 struct dss_clock_info dss_cinfo;
48 struct dispc_clock_info dispc_cinfo;
49};
50
51static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
52 unsigned long pck, void *data)
53{
54 struct sdi_clk_calc_ctx *ctx = data;
55
56 ctx->dispc_cinfo.lck_div = lckd;
57 ctx->dispc_cinfo.pck_div = pckd;
58 ctx->dispc_cinfo.lck = lck;
59 ctx->dispc_cinfo.pck = pck;
60
61 return true;
62}
63
64static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
65{
66 struct sdi_clk_calc_ctx *ctx = data;
67
68 ctx->dss_cinfo.fck = fck;
69 ctx->dss_cinfo.fck_div = fckd;
70
71 return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
72 dpi_calc_dispc_cb, ctx);
73}
74
75static int sdi_calc_clock_div(unsigned long pclk,
76 struct dss_clock_info *dss_cinfo,
77 struct dispc_clock_info *dispc_cinfo)
78{
79 int i;
80 struct sdi_clk_calc_ctx ctx;
81
82 /*
83 * DSS fclk gives us very few possibilities, so finding a good pixel
84 * clock may not be possible. We try multiple times to find the clock,
85 * each time widening the pixel clock range we look for, up to
86 * +/- 1MHz.
87 */
88
89 for (i = 0; i < 10; ++i) {
90 bool ok;
91
92 memset(&ctx, 0, sizeof(ctx));
93 if (pclk > 1000 * i * i * i)
94 ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
95 else
96 ctx.pck_min = 0;
97 ctx.pck_max = pclk + 1000 * i * i * i;
98
99 ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx);
100 if (ok) {
101 *dss_cinfo = ctx.dss_cinfo;
102 *dispc_cinfo = ctx.dispc_cinfo;
103 return 0;
104 }
105 }
106
107 return -EINVAL;
108}
109
44static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) 110static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
45{ 111{
46 struct omap_overlay_manager *mgr = dssdev->output->manager; 112 struct omap_overlay_manager *mgr = dssdev->output->manager;
@@ -88,7 +154,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
88 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 154 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
89 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 155 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
90 156
91 r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); 157 r = sdi_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
92 if (r) 158 if (r)
93 goto err_calc_clock_div; 159 goto err_calc_clock_div;
94 160
@@ -182,7 +248,7 @@ void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
182} 248}
183EXPORT_SYMBOL(omapdss_sdi_set_datapairs); 249EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
184 250
185static int __init sdi_init_display(struct omap_dss_device *dssdev) 251static int sdi_init_display(struct omap_dss_device *dssdev)
186{ 252{
187 DSSDBG("SDI init\n"); 253 DSSDBG("SDI init\n");
188 254
@@ -202,7 +268,7 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
202 return 0; 268 return 0;
203} 269}
204 270
205static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev) 271static struct omap_dss_device *sdi_find_dssdev(struct platform_device *pdev)
206{ 272{
207 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 273 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
208 const char *def_disp_name = omapdss_get_default_display_name(); 274 const char *def_disp_name = omapdss_get_default_display_name();
@@ -230,7 +296,7 @@ static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *p
230 return def_dssdev; 296 return def_dssdev;
231} 297}
232 298
233static void __init sdi_probe_pdata(struct platform_device *sdidev) 299static int sdi_probe_pdata(struct platform_device *sdidev)
234{ 300{
235 struct omap_dss_device *plat_dssdev; 301 struct omap_dss_device *plat_dssdev;
236 struct omap_dss_device *dssdev; 302 struct omap_dss_device *dssdev;
@@ -239,11 +305,11 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev)
239 plat_dssdev = sdi_find_dssdev(sdidev); 305 plat_dssdev = sdi_find_dssdev(sdidev);
240 306
241 if (!plat_dssdev) 307 if (!plat_dssdev)
242 return; 308 return 0;
243 309
244 dssdev = dss_alloc_and_init_device(&sdidev->dev); 310 dssdev = dss_alloc_and_init_device(&sdidev->dev);
245 if (!dssdev) 311 if (!dssdev)
246 return; 312 return -ENOMEM;
247 313
248 dss_copy_device_pdata(dssdev, plat_dssdev); 314 dss_copy_device_pdata(dssdev, plat_dssdev);
249 315
@@ -251,7 +317,7 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev)
251 if (r) { 317 if (r) {
252 DSSERR("device %s init failed: %d\n", dssdev->name, r); 318 DSSERR("device %s init failed: %d\n", dssdev->name, r);
253 dss_put_device(dssdev); 319 dss_put_device(dssdev);
254 return; 320 return r;
255 } 321 }
256 322
257 r = omapdss_output_set_device(&sdi.output, dssdev); 323 r = omapdss_output_set_device(&sdi.output, dssdev);
@@ -259,7 +325,7 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev)
259 DSSERR("failed to connect output to new device: %s\n", 325 DSSERR("failed to connect output to new device: %s\n",
260 dssdev->name); 326 dssdev->name);
261 dss_put_device(dssdev); 327 dss_put_device(dssdev);
262 return; 328 return r;
263 } 329 }
264 330
265 r = dss_add_device(dssdev); 331 r = dss_add_device(dssdev);
@@ -267,17 +333,21 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev)
267 DSSERR("device %s register failed: %d\n", dssdev->name, r); 333 DSSERR("device %s register failed: %d\n", dssdev->name, r);
268 omapdss_output_unset_device(&sdi.output); 334 omapdss_output_unset_device(&sdi.output);
269 dss_put_device(dssdev); 335 dss_put_device(dssdev);
270 return; 336 return r;
271 } 337 }
338
339 return 0;
272} 340}
273 341
274static void __init sdi_init_output(struct platform_device *pdev) 342static void sdi_init_output(struct platform_device *pdev)
275{ 343{
276 struct omap_dss_output *out = &sdi.output; 344 struct omap_dss_output *out = &sdi.output;
277 345
278 out->pdev = pdev; 346 out->pdev = pdev;
279 out->id = OMAP_DSS_OUTPUT_SDI; 347 out->id = OMAP_DSS_OUTPUT_SDI;
280 out->type = OMAP_DISPLAY_TYPE_SDI; 348 out->type = OMAP_DISPLAY_TYPE_SDI;
349 out->name = "sdi.0";
350 out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
281 351
282 dss_register_output(out); 352 dss_register_output(out);
283} 353}
@@ -289,11 +359,17 @@ static void __exit sdi_uninit_output(struct platform_device *pdev)
289 dss_unregister_output(out); 359 dss_unregister_output(out);
290} 360}
291 361
292static int __init omap_sdi_probe(struct platform_device *pdev) 362static int omap_sdi_probe(struct platform_device *pdev)
293{ 363{
364 int r;
365
294 sdi_init_output(pdev); 366 sdi_init_output(pdev);
295 367
296 sdi_probe_pdata(pdev); 368 r = sdi_probe_pdata(pdev);
369 if (r) {
370 sdi_uninit_output(pdev);
371 return r;
372 }
297 373
298 return 0; 374 return 0;
299} 375}
@@ -308,6 +384,7 @@ static int __exit omap_sdi_remove(struct platform_device *pdev)
308} 384}
309 385
310static struct platform_driver omap_sdi_driver = { 386static struct platform_driver omap_sdi_driver = {
387 .probe = omap_sdi_probe,
311 .remove = __exit_p(omap_sdi_remove), 388 .remove = __exit_p(omap_sdi_remove),
312 .driver = { 389 .driver = {
313 .name = "omapdss_sdi", 390 .name = "omapdss_sdi",
@@ -317,7 +394,7 @@ static struct platform_driver omap_sdi_driver = {
317 394
318int __init sdi_init_platform_driver(void) 395int __init sdi_init_platform_driver(void)
319{ 396{
320 return platform_driver_probe(&omap_sdi_driver, omap_sdi_probe); 397 return platform_driver_register(&omap_sdi_driver);
321} 398}
322 399
323void __exit sdi_uninit_platform_driver(void) 400void __exit sdi_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 006caf3cb509..74fdb3ee209e 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -519,10 +519,6 @@ int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
519 goto err0; 519 goto err0;
520 } 520 }
521 521
522 if (dssdev->platform_enable)
523 dssdev->platform_enable(dssdev);
524
525
526 r = venc_power_on(dssdev); 522 r = venc_power_on(dssdev);
527 if (r) 523 if (r)
528 goto err1; 524 goto err1;
@@ -533,8 +529,6 @@ int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
533 529
534 return 0; 530 return 0;
535err1: 531err1:
536 if (dssdev->platform_disable)
537 dssdev->platform_disable(dssdev);
538 omap_dss_stop_device(dssdev); 532 omap_dss_stop_device(dssdev);
539err0: 533err0:
540 mutex_unlock(&venc.venc_lock); 534 mutex_unlock(&venc.venc_lock);
@@ -551,9 +545,6 @@ void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
551 545
552 omap_dss_stop_device(dssdev); 546 omap_dss_stop_device(dssdev);
553 547
554 if (dssdev->platform_disable)
555 dssdev->platform_disable(dssdev);
556
557 mutex_unlock(&venc.venc_lock); 548 mutex_unlock(&venc.venc_lock);
558} 549}
559 550
@@ -642,7 +633,7 @@ void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
642 mutex_unlock(&venc.venc_lock); 633 mutex_unlock(&venc.venc_lock);
643} 634}
644 635
645static int __init venc_init_display(struct omap_dss_device *dssdev) 636static int venc_init_display(struct omap_dss_device *dssdev)
646{ 637{
647 DSSDBG("init_display\n"); 638 DSSDBG("init_display\n");
648 639
@@ -721,7 +712,7 @@ static int venc_get_clocks(struct platform_device *pdev)
721 struct clk *clk; 712 struct clk *clk;
722 713
723 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { 714 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
724 clk = clk_get(&pdev->dev, "tv_dac_clk"); 715 clk = devm_clk_get(&pdev->dev, "tv_dac_clk");
725 if (IS_ERR(clk)) { 716 if (IS_ERR(clk)) {
726 DSSERR("can't get tv_dac_clk\n"); 717 DSSERR("can't get tv_dac_clk\n");
727 return PTR_ERR(clk); 718 return PTR_ERR(clk);
@@ -735,13 +726,7 @@ static int venc_get_clocks(struct platform_device *pdev)
735 return 0; 726 return 0;
736} 727}
737 728
738static void venc_put_clocks(void) 729static struct omap_dss_device *venc_find_dssdev(struct platform_device *pdev)
739{
740 if (venc.tv_dac_clk)
741 clk_put(venc.tv_dac_clk);
742}
743
744static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
745{ 730{
746 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 731 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
747 const char *def_disp_name = omapdss_get_default_display_name(); 732 const char *def_disp_name = omapdss_get_default_display_name();
@@ -769,7 +754,7 @@ static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *
769 return def_dssdev; 754 return def_dssdev;
770} 755}
771 756
772static void __init venc_probe_pdata(struct platform_device *vencdev) 757static int venc_probe_pdata(struct platform_device *vencdev)
773{ 758{
774 struct omap_dss_device *plat_dssdev; 759 struct omap_dss_device *plat_dssdev;
775 struct omap_dss_device *dssdev; 760 struct omap_dss_device *dssdev;
@@ -778,21 +763,19 @@ static void __init venc_probe_pdata(struct platform_device *vencdev)
778 plat_dssdev = venc_find_dssdev(vencdev); 763 plat_dssdev = venc_find_dssdev(vencdev);
779 764
780 if (!plat_dssdev) 765 if (!plat_dssdev)
781 return; 766 return 0;
782 767
783 dssdev = dss_alloc_and_init_device(&vencdev->dev); 768 dssdev = dss_alloc_and_init_device(&vencdev->dev);
784 if (!dssdev) 769 if (!dssdev)
785 return; 770 return -ENOMEM;
786 771
787 dss_copy_device_pdata(dssdev, plat_dssdev); 772 dss_copy_device_pdata(dssdev, plat_dssdev);
788 773
789 dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
790
791 r = venc_init_display(dssdev); 774 r = venc_init_display(dssdev);
792 if (r) { 775 if (r) {
793 DSSERR("device %s init failed: %d\n", dssdev->name, r); 776 DSSERR("device %s init failed: %d\n", dssdev->name, r);
794 dss_put_device(dssdev); 777 dss_put_device(dssdev);
795 return; 778 return r;
796 } 779 }
797 780
798 r = omapdss_output_set_device(&venc.output, dssdev); 781 r = omapdss_output_set_device(&venc.output, dssdev);
@@ -800,7 +783,7 @@ static void __init venc_probe_pdata(struct platform_device *vencdev)
800 DSSERR("failed to connect output to new device: %s\n", 783 DSSERR("failed to connect output to new device: %s\n",
801 dssdev->name); 784 dssdev->name);
802 dss_put_device(dssdev); 785 dss_put_device(dssdev);
803 return; 786 return r;
804 } 787 }
805 788
806 r = dss_add_device(dssdev); 789 r = dss_add_device(dssdev);
@@ -808,17 +791,21 @@ static void __init venc_probe_pdata(struct platform_device *vencdev)
808 DSSERR("device %s register failed: %d\n", dssdev->name, r); 791 DSSERR("device %s register failed: %d\n", dssdev->name, r);
809 omapdss_output_unset_device(&venc.output); 792 omapdss_output_unset_device(&venc.output);
810 dss_put_device(dssdev); 793 dss_put_device(dssdev);
811 return; 794 return r;
812 } 795 }
796
797 return 0;
813} 798}
814 799
815static void __init venc_init_output(struct platform_device *pdev) 800static void venc_init_output(struct platform_device *pdev)
816{ 801{
817 struct omap_dss_output *out = &venc.output; 802 struct omap_dss_output *out = &venc.output;
818 803
819 out->pdev = pdev; 804 out->pdev = pdev;
820 out->id = OMAP_DSS_OUTPUT_VENC; 805 out->id = OMAP_DSS_OUTPUT_VENC;
821 out->type = OMAP_DISPLAY_TYPE_VENC; 806 out->type = OMAP_DISPLAY_TYPE_VENC;
807 out->name = "venc.0";
808 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
822 809
823 dss_register_output(out); 810 dss_register_output(out);
824} 811}
@@ -831,7 +818,7 @@ static void __exit venc_uninit_output(struct platform_device *pdev)
831} 818}
832 819
833/* VENC HW IP initialisation */ 820/* VENC HW IP initialisation */
834static int __init omap_venchw_probe(struct platform_device *pdev) 821static int omap_venchw_probe(struct platform_device *pdev)
835{ 822{
836 u8 rev_id; 823 u8 rev_id;
837 struct resource *venc_mem; 824 struct resource *venc_mem;
@@ -879,14 +866,19 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
879 866
880 venc_init_output(pdev); 867 venc_init_output(pdev);
881 868
882 venc_probe_pdata(pdev); 869 r = venc_probe_pdata(pdev);
870 if (r) {
871 venc_panel_exit();
872 venc_uninit_output(pdev);
873 pm_runtime_disable(&pdev->dev);
874 return r;
875 }
883 876
884 return 0; 877 return 0;
885 878
886err_panel_init: 879err_panel_init:
887err_runtime_get: 880err_runtime_get:
888 pm_runtime_disable(&pdev->dev); 881 pm_runtime_disable(&pdev->dev);
889 venc_put_clocks();
890 return r; 882 return r;
891} 883}
892 884
@@ -904,7 +896,6 @@ static int __exit omap_venchw_remove(struct platform_device *pdev)
904 venc_uninit_output(pdev); 896 venc_uninit_output(pdev);
905 897
906 pm_runtime_disable(&pdev->dev); 898 pm_runtime_disable(&pdev->dev);
907 venc_put_clocks();
908 899
909 return 0; 900 return 0;
910} 901}
@@ -939,6 +930,7 @@ static const struct dev_pm_ops venc_pm_ops = {
939}; 930};
940 931
941static struct platform_driver omap_venchw_driver = { 932static struct platform_driver omap_venchw_driver = {
933 .probe = omap_venchw_probe,
942 .remove = __exit_p(omap_venchw_remove), 934 .remove = __exit_p(omap_venchw_remove),
943 .driver = { 935 .driver = {
944 .name = "omapdss_venc", 936 .name = "omapdss_venc",
@@ -949,7 +941,7 @@ static struct platform_driver omap_venchw_driver = {
949 941
950int __init venc_init_platform_driver(void) 942int __init venc_init_platform_driver(void)
951{ 943{
952 return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe); 944 return platform_driver_register(&omap_venchw_driver);
953} 945}
954 946
955void __exit venc_uninit_platform_driver(void) 947void __exit venc_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index ca585ef37f25..c84bb8a4d0c4 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -1101,41 +1101,25 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1101 struct omapfb_info *ofbi = FB2OFB(fbi); 1101 struct omapfb_info *ofbi = FB2OFB(fbi);
1102 struct fb_fix_screeninfo *fix = &fbi->fix; 1102 struct fb_fix_screeninfo *fix = &fbi->fix;
1103 struct omapfb2_mem_region *rg; 1103 struct omapfb2_mem_region *rg;
1104 unsigned long off;
1105 unsigned long start; 1104 unsigned long start;
1106 u32 len; 1105 u32 len;
1107 int r = -EINVAL; 1106 int r;
1108
1109 if (vma->vm_end - vma->vm_start == 0)
1110 return 0;
1111 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1112 return -EINVAL;
1113 off = vma->vm_pgoff << PAGE_SHIFT;
1114 1107
1115 rg = omapfb_get_mem_region(ofbi->region); 1108 rg = omapfb_get_mem_region(ofbi->region);
1116 1109
1117 start = omapfb_get_region_paddr(ofbi); 1110 start = omapfb_get_region_paddr(ofbi);
1118 len = fix->smem_len; 1111 len = fix->smem_len;
1119 if (off >= len)
1120 goto error;
1121 if ((vma->vm_end - vma->vm_start + off) > len)
1122 goto error;
1123 1112
1124 off += start; 1113 DBG("user mmap region start %lx, len %d, off %lx\n", start, len,
1114 vma->vm_pgoff << PAGE_SHIFT);
1125 1115
1126 DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
1127
1128 vma->vm_pgoff = off >> PAGE_SHIFT;
1129 /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
1130 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); 1116 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1131 vma->vm_ops = &mmap_user_ops; 1117 vma->vm_ops = &mmap_user_ops;
1132 vma->vm_private_data = rg; 1118 vma->vm_private_data = rg;
1133 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, 1119
1134 vma->vm_end - vma->vm_start, 1120 r = vm_iomap_memory(vma, start, len);
1135 vma->vm_page_prot)) { 1121 if (r)
1136 r = -EAGAIN;
1137 goto error; 1122 goto error;
1138 }
1139 1123
1140 /* vm_ops.open won't be called for mmap itself. */ 1124 /* vm_ops.open won't be called for mmap itself. */
1141 atomic_inc(&rg->map_count); 1125 atomic_inc(&rg->map_count);
@@ -1144,7 +1128,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1144 1128
1145 return 0; 1129 return 0;
1146 1130
1147 error: 1131error:
1148 omapfb_put_mem_region(ofbi->region); 1132 omapfb_put_mem_region(ofbi->region);
1149 1133
1150 return r; 1134 return r;
@@ -2388,7 +2372,7 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev,
2388 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; 2372 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
2389 struct omap_dss_output *out = dssdev->output; 2373 struct omap_dss_output *out = dssdev->output;
2390 2374
2391 mgr = omap_dss_get_overlay_manager(dssdev->channel); 2375 mgr = omap_dss_get_overlay_manager(out->dispc_channel);
2392 2376
2393 if (!mgr || !out) 2377 if (!mgr || !out)
2394 continue; 2378 continue;
@@ -2422,7 +2406,7 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev,
2422 return 0; 2406 return 0;
2423} 2407}
2424 2408
2425static int __init omapfb_probe(struct platform_device *pdev) 2409static int omapfb_probe(struct platform_device *pdev)
2426{ 2410{
2427 struct omapfb2_device *fbdev = NULL; 2411 struct omapfb2_device *fbdev = NULL;
2428 int r = 0; 2412 int r = 0;
@@ -2484,7 +2468,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
2484 2468
2485 if (fbdev->num_displays == 0) { 2469 if (fbdev->num_displays == 0) {
2486 dev_err(&pdev->dev, "no displays\n"); 2470 dev_err(&pdev->dev, "no displays\n");
2487 r = -EINVAL; 2471 r = -EPROBE_DEFER;
2488 goto cleanup; 2472 goto cleanup;
2489 } 2473 }
2490 2474
@@ -2595,6 +2579,7 @@ static int __exit omapfb_remove(struct platform_device *pdev)
2595} 2579}
2596 2580
2597static struct platform_driver omapfb_driver = { 2581static struct platform_driver omapfb_driver = {
2582 .probe = omapfb_probe,
2598 .remove = __exit_p(omapfb_remove), 2583 .remove = __exit_p(omapfb_remove),
2599 .driver = { 2584 .driver = {
2600 .name = "omapfb", 2585 .name = "omapfb",
@@ -2602,36 +2587,13 @@ static struct platform_driver omapfb_driver = {
2602 }, 2587 },
2603}; 2588};
2604 2589
2605static int __init omapfb_init(void)
2606{
2607 DBG("omapfb_init\n");
2608
2609 if (platform_driver_probe(&omapfb_driver, omapfb_probe)) {
2610 printk(KERN_ERR "failed to register omapfb driver\n");
2611 return -ENODEV;
2612 }
2613
2614 return 0;
2615}
2616
2617static void __exit omapfb_exit(void)
2618{
2619 DBG("omapfb_exit\n");
2620 platform_driver_unregister(&omapfb_driver);
2621}
2622
2623module_param_named(mode, def_mode, charp, 0); 2590module_param_named(mode, def_mode, charp, 0);
2624module_param_named(vram, def_vram, charp, 0); 2591module_param_named(vram, def_vram, charp, 0);
2625module_param_named(rotate, def_rotate, int, 0); 2592module_param_named(rotate, def_rotate, int, 0);
2626module_param_named(vrfb, def_vrfb, bool, 0); 2593module_param_named(vrfb, def_vrfb, bool, 0);
2627module_param_named(mirror, def_mirror, bool, 0); 2594module_param_named(mirror, def_mirror, bool, 0);
2628 2595
2629/* late_initcall to let panel/ctrl drivers loaded first. 2596module_platform_driver(omapfb_driver);
2630 * I guess better option would be a more dynamic approach,
2631 * so that omapfb reacts to new panels when they are loaded */
2632late_initcall(omapfb_init);
2633/*module_init(omapfb_init);*/
2634module_exit(omapfb_exit);
2635 2597
2636MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); 2598MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
2637MODULE_DESCRIPTION("OMAP2/3 Framebuffer"); 2599MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 10560efeb35a..5261229c79af 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -397,18 +397,7 @@ static struct platform_driver vrfb_driver = {
397 .remove = __exit_p(vrfb_remove), 397 .remove = __exit_p(vrfb_remove),
398}; 398};
399 399
400static int __init vrfb_init(void) 400module_platform_driver_probe(vrfb_driver, vrfb_probe);
401{
402 return platform_driver_probe(&vrfb_driver, &vrfb_probe);
403}
404
405static void __exit vrfb_exit(void)
406{
407 platform_driver_unregister(&vrfb_driver);
408}
409
410module_init(vrfb_init);
411module_exit(vrfb_exit);
412 401
413MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); 402MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
414MODULE_DESCRIPTION("OMAP VRFB"); 403MODULE_DESCRIPTION("OMAP VRFB");
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 920c27bf3947..d9f08c653d62 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -705,21 +705,15 @@ static int ps3fb_pan_display(struct fb_var_screeninfo *var,
705 705
706static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma) 706static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
707{ 707{
708 unsigned long size, offset; 708 int r;
709 709
710 size = vma->vm_end - vma->vm_start; 710 r = vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
711 offset = vma->vm_pgoff << PAGE_SHIFT;
712 if (offset + size > info->fix.smem_len)
713 return -EINVAL;
714
715 offset += info->fix.smem_start;
716 if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
717 size, vma->vm_page_prot))
718 return -EAGAIN;
719 711
720 dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", 712 dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n",
721 offset, vma->vm_start); 713 info->fix.smem_start + vma->vm_pgoff << PAGE_SHIFT,
722 return 0; 714 vma->vm_start);
715
716 return r;
723} 717}
724 718
725 /* 719 /*
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
index 6c984eacc7e3..97563c55af63 100644
--- a/drivers/video/pxa3xx-gcu.c
+++ b/drivers/video/pxa3xx-gcu.c
@@ -101,7 +101,6 @@ struct pxa3xx_gcu_priv {
101 dma_addr_t shared_phys; 101 dma_addr_t shared_phys;
102 struct resource *resource_mem; 102 struct resource *resource_mem;
103 struct miscdevice misc_dev; 103 struct miscdevice misc_dev;
104 struct file_operations misc_fops;
105 wait_queue_head_t wait_idle; 104 wait_queue_head_t wait_idle;
106 wait_queue_head_t wait_free; 105 wait_queue_head_t wait_free;
107 spinlock_t spinlock; 106 spinlock_t spinlock;
@@ -369,15 +368,20 @@ pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv)
369 368
370/* Misc device layer */ 369/* Misc device layer */
371 370
371static inline struct pxa3xx_gcu_priv *file_dev(struct file *file)
372{
373 struct miscdevice *dev = file->private_data;
374 return container_of(dev, struct pxa3xx_gcu_priv, misc_dev);
375}
376
372static ssize_t 377static ssize_t
373pxa3xx_gcu_misc_write(struct file *filp, const char *buff, 378pxa3xx_gcu_misc_write(struct file *file, const char *buff,
374 size_t count, loff_t *offp) 379 size_t count, loff_t *offp)
375{ 380{
376 int ret; 381 int ret;
377 unsigned long flags; 382 unsigned long flags;
378 struct pxa3xx_gcu_batch *buffer; 383 struct pxa3xx_gcu_batch *buffer;
379 struct pxa3xx_gcu_priv *priv = 384 struct pxa3xx_gcu_priv *priv = file_dev(file);
380 container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
381 385
382 int words = count / 4; 386 int words = count / 4;
383 387
@@ -450,11 +454,10 @@ pxa3xx_gcu_misc_write(struct file *filp, const char *buff,
450 454
451 455
452static long 456static long
453pxa3xx_gcu_misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 457pxa3xx_gcu_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
454{ 458{
455 unsigned long flags; 459 unsigned long flags;
456 struct pxa3xx_gcu_priv *priv = 460 struct pxa3xx_gcu_priv *priv = file_dev(file);
457 container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
458 461
459 switch (cmd) { 462 switch (cmd) {
460 case PXA3XX_GCU_IOCTL_RESET: 463 case PXA3XX_GCU_IOCTL_RESET:
@@ -471,11 +474,10 @@ pxa3xx_gcu_misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
471} 474}
472 475
473static int 476static int
474pxa3xx_gcu_misc_mmap(struct file *filp, struct vm_area_struct *vma) 477pxa3xx_gcu_misc_mmap(struct file *file, struct vm_area_struct *vma)
475{ 478{
476 unsigned int size = vma->vm_end - vma->vm_start; 479 unsigned int size = vma->vm_end - vma->vm_start;
477 struct pxa3xx_gcu_priv *priv = 480 struct pxa3xx_gcu_priv *priv = file_dev(file);
478 container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
479 481
480 switch (vma->vm_pgoff) { 482 switch (vma->vm_pgoff) {
481 case 0: 483 case 0:
@@ -574,6 +576,13 @@ free_buffers(struct platform_device *dev,
574 priv->free = NULL; 576 priv->free = NULL;
575} 577}
576 578
579static const struct file_operations misc_fops = {
580 .owner = THIS_MODULE,
581 .write = pxa3xx_gcu_misc_write,
582 .unlocked_ioctl = pxa3xx_gcu_misc_ioctl,
583 .mmap = pxa3xx_gcu_misc_mmap
584};
585
577static int pxa3xx_gcu_probe(struct platform_device *dev) 586static int pxa3xx_gcu_probe(struct platform_device *dev)
578{ 587{
579 int i, ret, irq; 588 int i, ret, irq;
@@ -601,14 +610,9 @@ static int pxa3xx_gcu_probe(struct platform_device *dev)
601 * container_of(). This isn't really necessary as we have a fixed minor 610 * container_of(). This isn't really necessary as we have a fixed minor
602 * number anyway, but this is to avoid statics. */ 611 * number anyway, but this is to avoid statics. */
603 612
604 priv->misc_fops.owner = THIS_MODULE;
605 priv->misc_fops.write = pxa3xx_gcu_misc_write;
606 priv->misc_fops.unlocked_ioctl = pxa3xx_gcu_misc_ioctl;
607 priv->misc_fops.mmap = pxa3xx_gcu_misc_mmap;
608
609 priv->misc_dev.minor = MISCDEV_MINOR, 613 priv->misc_dev.minor = MISCDEV_MINOR,
610 priv->misc_dev.name = DRV_NAME, 614 priv->misc_dev.name = DRV_NAME,
611 priv->misc_dev.fops = &priv->misc_fops, 615 priv->misc_dev.fops = &misc_fops,
612 616
613 /* register misc device */ 617 /* register misc device */
614 ret = misc_register(&priv->misc_dev); 618 ret = misc_register(&priv->misc_dev);
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index 76d9053d88c1..05c2dc3d4bc0 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -862,7 +862,7 @@ static int s1d13xxxfb_probe(struct platform_device *pdev)
862 printk(KERN_INFO PFX 862 printk(KERN_INFO PFX
863 "unknown chip production id %i, revision %i\n", 863 "unknown chip production id %i, revision %i\n",
864 prod_id, revision); 864 prod_id, revision);
865 printk(KERN_INFO PFX "please contant maintainer\n"); 865 printk(KERN_INFO PFX "please contact maintainer\n");
866 goto bail; 866 goto bail;
867 } 867 }
868 868
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 968a62571df7..2e7991c7ca08 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -24,10 +24,9 @@
24#include <linux/uaccess.h> 24#include <linux/uaccess.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/pm_runtime.h> 26#include <linux/pm_runtime.h>
27#include <linux/platform_data/video_s3c.h>
27 28
28#include <video/samsung_fimd.h> 29#include <video/samsung_fimd.h>
29#include <mach/map.h>
30#include <plat/fb.h>
31 30
32/* This driver will export a number of framebuffer interfaces depending 31/* This driver will export a number of framebuffer interfaces depending
33 * on the configuration passed in via the platform data. Each fb instance 32 * on the configuration passed in via the platform data. Each fb instance
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index cfbde5e85cbf..f34c858642e8 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -556,7 +556,7 @@ static int sa1100fb_mmap(struct fb_info *info,
556 struct vm_area_struct *vma) 556 struct vm_area_struct *vma)
557{ 557{
558 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 558 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
559 unsigned long start, len, off = vma->vm_pgoff << PAGE_SHIFT; 559 unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
560 560
561 if (off < info->fix.smem_len) { 561 if (off < info->fix.smem_len) {
562 vma->vm_pgoff += 1; /* skip over the palette */ 562 vma->vm_pgoff += 1; /* skip over the palette */
@@ -564,19 +564,9 @@ static int sa1100fb_mmap(struct fb_info *info,
564 fbi->map_dma, fbi->map_size); 564 fbi->map_dma, fbi->map_size);
565 } 565 }
566 566
567 start = info->fix.mmio_start;
568 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
569
570 if ((vma->vm_end - vma->vm_start + off) > len)
571 return -EINVAL;
572
573 off += start & PAGE_MASK;
574 vma->vm_pgoff = off >> PAGE_SHIFT;
575 vma->vm_flags |= VM_IO;
576 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 567 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
577 return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, 568
578 vma->vm_end - vma->vm_start, 569 return vm_iomap_memory(vma, info->fix.mmio_start, info->fix.mmio_len);
579 vma->vm_page_prot);
580} 570}
581 571
582static struct fb_ops sa1100fb_ops = { 572static struct fb_ops sa1100fb_ops = {
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 2331fadc272b..b2a8912f6435 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -705,23 +705,17 @@ static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
705static int sgivwfb_mmap(struct fb_info *info, 705static int sgivwfb_mmap(struct fb_info *info,
706 struct vm_area_struct *vma) 706 struct vm_area_struct *vma)
707{ 707{
708 unsigned long size = vma->vm_end - vma->vm_start; 708 int r;
709 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
710 709
711 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
712 return -EINVAL;
713 if (offset + size > sgivwfb_mem_size)
714 return -EINVAL;
715 offset += sgivwfb_mem_phys;
716 pgprot_val(vma->vm_page_prot) = 710 pgprot_val(vma->vm_page_prot) =
717 pgprot_val(vma->vm_page_prot) | _PAGE_PCD; 711 pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
718 vma->vm_flags |= VM_IO; 712
719 if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, 713 r = vm_iomap_memory(vma, sgivwfb_mem_phys, sgivwfb_mem_size);
720 size, vma->vm_page_prot)) 714
721 return -EAGAIN;
722 printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", 715 printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
723 offset, vma->vm_start); 716 offset, vma->vm_start);
724 return 0; 717
718 return r;
725} 719}
726 720
727int __init sgivwfb_setup(char *options) 721int __init sgivwfb_setup(char *options)
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 701b461cf8a9..6cad53075e99 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -581,17 +581,7 @@ static struct platform_driver sh_mipi_driver = {
581 }, 581 },
582}; 582};
583 583
584static int __init sh_mipi_init(void) 584module_platform_driver_probe(sh_mipi_driver, sh_mipi_probe);
585{
586 return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe);
587}
588module_init(sh_mipi_init);
589
590static void __exit sh_mipi_exit(void)
591{
592 platform_driver_unregister(&sh_mipi_driver);
593}
594module_exit(sh_mipi_exit);
595 585
596MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); 586MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
597MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver"); 587MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 930e550e752a..bfe4728480fd 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -1445,17 +1445,7 @@ static struct platform_driver sh_hdmi_driver = {
1445 }, 1445 },
1446}; 1446};
1447 1447
1448static int __init sh_hdmi_init(void) 1448module_platform_driver_probe(sh_hdmi_driver, sh_hdmi_probe);
1449{
1450 return platform_driver_probe(&sh_hdmi_driver, sh_hdmi_probe);
1451}
1452module_init(sh_hdmi_init);
1453
1454static void __exit sh_hdmi_exit(void)
1455{
1456 platform_driver_unregister(&sh_hdmi_driver);
1457}
1458module_exit(sh_hdmi_exit);
1459 1449
1460MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); 1450MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
1461MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver"); 1451MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver");
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c
index 97bd6620c364..b2b33fc1ac3f 100644
--- a/drivers/video/smscufx.c
+++ b/drivers/video/smscufx.c
@@ -782,7 +782,11 @@ static int ufx_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
782 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; 782 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
783 unsigned long page, pos; 783 unsigned long page, pos;
784 784
785 if (offset + size > info->fix.smem_len) 785 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
786 return -EINVAL;
787 if (size > info->fix.smem_len)
788 return -EINVAL;
789 if (offset > info->fix.smem_len - size)
786 return -EINVAL; 790 return -EINVAL;
787 791
788 pos = (unsigned long)info->fix.smem_start + offset; 792 pos = (unsigned long)info->fix.smem_start + offset;
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
index 395cb6a8d8f3..9ef05d3ef68a 100644
--- a/drivers/video/ssd1307fb.c
+++ b/drivers/video/ssd1307fb.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Driver for the Solomon SSD1307 OLED controler 2 * Driver for the Solomon SSD1307 OLED controller
3 * 3 *
4 * Copyright 2012 Free Electrons 4 * Copyright 2012 Free Electrons
5 * 5 *
@@ -392,6 +392,6 @@ static struct i2c_driver ssd1307fb_driver = {
392 392
393module_i2c_driver(ssd1307fb_driver); 393module_i2c_driver(ssd1307fb_driver);
394 394
395MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controler"); 395MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controller");
396MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 396MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
397MODULE_LICENSE("GPL"); 397MODULE_LICENSE("GPL");
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index 86d449ea3169..ec03e726c940 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -324,7 +324,11 @@ static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
324 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; 324 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
325 unsigned long page, pos; 325 unsigned long page, pos;
326 326
327 if (offset + size > info->fix.smem_len) 327 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
328 return -EINVAL;
329 if (size > info->fix.smem_len)
330 return -EINVAL;
331 if (offset > info->fix.smem_len - size)
328 return -EINVAL; 332 return -EINVAL;
329 333
330 pos = (unsigned long)info->fix.smem_start + offset; 334 pos = (unsigned long)info->fix.smem_start + offset;
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index d4284458377e..e328a61b64ba 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -166,7 +166,7 @@ static int uvesafb_exec(struct uvesafb_ktask *task)
166 memcpy(&m->id, &uvesafb_cn_id, sizeof(m->id)); 166 memcpy(&m->id, &uvesafb_cn_id, sizeof(m->id));
167 m->seq = seq; 167 m->seq = seq;
168 m->len = len; 168 m->len = len;
169 m->ack = random32(); 169 m->ack = prandom_u32();
170 170
171 /* uvesafb_task structure */ 171 /* uvesafb_task structure */
172 memcpy(m + 1, &task->t, sizeof(task->t)); 172 memcpy(m + 1, &task->t, sizeof(task->t));
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
index 0aa516fc59cd..09a136633f35 100644
--- a/drivers/video/vermilion/vermilion.c
+++ b/drivers/video/vermilion/vermilion.c
@@ -1003,24 +1003,18 @@ static int vmlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1003static int vmlfb_mmap(struct fb_info *info, struct vm_area_struct *vma) 1003static int vmlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
1004{ 1004{
1005 struct vml_info *vinfo = container_of(info, struct vml_info, info); 1005 struct vml_info *vinfo = container_of(info, struct vml_info, info);
1006 unsigned long size = vma->vm_end - vma->vm_start;
1007 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; 1006 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
1008 int ret; 1007 int ret;
1009 1008
1010 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1011 return -EINVAL;
1012 if (offset + size > vinfo->vram_contig_size)
1013 return -EINVAL;
1014 ret = vmlfb_vram_offset(vinfo, offset); 1009 ret = vmlfb_vram_offset(vinfo, offset);
1015 if (ret) 1010 if (ret)
1016 return -EINVAL; 1011 return -EINVAL;
1017 offset += vinfo->vram_start; 1012
1018 pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; 1013 pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
1019 pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; 1014 pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
1020 if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, 1015
1021 size, vma->vm_page_prot)) 1016 return vm_iomap_memory(vma, vinfo->vram_start,
1022 return -EAGAIN; 1017 vinfo->vram_contig_size);
1023 return 0;
1024} 1018}
1025 1019
1026static int vmlfb_sync(struct fb_info *info) 1020static int vmlfb_sync(struct fb_info *info)
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 8bc1f9398945..ee5985efa15c 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -420,9 +420,12 @@ static int vfb_mmap(struct fb_info *info,
420 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; 420 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
421 unsigned long page, pos; 421 unsigned long page, pos;
422 422
423 if (offset + size > info->fix.smem_len) { 423 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
424 return -EINVAL;
425 if (size > info->fix.smem_len)
426 return -EINVAL;
427 if (offset > info->fix.smem_len - size)
424 return -EINVAL; 428 return -EINVAL;
425 }
426 429
427 pos = (unsigned long)info->fix.smem_start + offset; 430 pos = (unsigned long)info->fix.smem_start + offset;
428 431
diff --git a/drivers/video/videomode.c b/drivers/video/videomode.c
index 21c47a202afa..df375c96c5d3 100644
--- a/drivers/video/videomode.c
+++ b/drivers/video/videomode.c
@@ -11,7 +11,25 @@
11#include <video/display_timing.h> 11#include <video/display_timing.h>
12#include <video/videomode.h> 12#include <video/videomode.h>
13 13
14int videomode_from_timing(const struct display_timings *disp, 14void videomode_from_timing(const struct display_timing *dt,
15 struct videomode *vm)
16{
17 vm->pixelclock = dt->pixelclock.typ;
18 vm->hactive = dt->hactive.typ;
19 vm->hfront_porch = dt->hfront_porch.typ;
20 vm->hback_porch = dt->hback_porch.typ;
21 vm->hsync_len = dt->hsync_len.typ;
22
23 vm->vactive = dt->vactive.typ;
24 vm->vfront_porch = dt->vfront_porch.typ;
25 vm->vback_porch = dt->vback_porch.typ;
26 vm->vsync_len = dt->vsync_len.typ;
27
28 vm->flags = dt->flags;
29}
30EXPORT_SYMBOL_GPL(videomode_from_timing);
31
32int videomode_from_timings(const struct display_timings *disp,
15 struct videomode *vm, unsigned int index) 33 struct videomode *vm, unsigned int index)
16{ 34{
17 struct display_timing *dt; 35 struct display_timing *dt;
@@ -20,20 +38,8 @@ int videomode_from_timing(const struct display_timings *disp,
20 if (!dt) 38 if (!dt)
21 return -EINVAL; 39 return -EINVAL;
22 40
23 vm->pixelclock = display_timing_get_value(&dt->pixelclock, TE_TYP); 41 videomode_from_timing(dt, vm);
24 vm->hactive = display_timing_get_value(&dt->hactive, TE_TYP);
25 vm->hfront_porch = display_timing_get_value(&dt->hfront_porch, TE_TYP);
26 vm->hback_porch = display_timing_get_value(&dt->hback_porch, TE_TYP);
27 vm->hsync_len = display_timing_get_value(&dt->hsync_len, TE_TYP);
28
29 vm->vactive = display_timing_get_value(&dt->vactive, TE_TYP);
30 vm->vfront_porch = display_timing_get_value(&dt->vfront_porch, TE_TYP);
31 vm->vback_porch = display_timing_get_value(&dt->vback_porch, TE_TYP);
32 vm->vsync_len = display_timing_get_value(&dt->vsync_len, TE_TYP);
33
34 vm->dmt_flags = dt->dmt_flags;
35 vm->data_flags = dt->data_flags;
36 42
37 return 0; 43 return 0;
38} 44}
39EXPORT_SYMBOL_GPL(videomode_from_timing); 45EXPORT_SYMBOL_GPL(videomode_from_timings);
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
index aa2579c2364a..9547e1831e03 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/vt8500lcdfb.c
@@ -15,22 +15,21 @@
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 */ 16 */
17 17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/string.h>
22#include <linux/mm.h>
23#include <linux/slab.h>
24#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/dma-mapping.h>
20#include <linux/errno.h>
25#include <linux/fb.h> 21#include <linux/fb.h>
26#include <linux/init.h> 22#include <linux/init.h>
27#include <linux/interrupt.h> 23#include <linux/interrupt.h>
28#include <linux/io.h> 24#include <linux/io.h>
29#include <linux/dma-mapping.h> 25#include <linux/kernel.h>
26#include <linux/mm.h>
27#include <linux/module.h>
30#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/slab.h>
30#include <linux/string.h>
31#include <linux/wait.h> 31#include <linux/wait.h>
32 32#include <video/of_display_timing.h>
33#include <linux/platform_data/video-vt8500lcdfb.h>
34 33
35#include "vt8500lcdfb.h" 34#include "vt8500lcdfb.h"
36#include "wmt_ge_rops.h" 35#include "wmt_ge_rops.h"
@@ -277,11 +276,11 @@ static int vt8500lcd_probe(struct platform_device *pdev)
277{ 276{
278 struct vt8500lcd_info *fbi; 277 struct vt8500lcd_info *fbi;
279 struct resource *res; 278 struct resource *res;
279 struct display_timings *disp_timing;
280 void *addr; 280 void *addr;
281 int irq, ret; 281 int irq, ret;
282 282
283 struct fb_videomode of_mode; 283 struct fb_videomode of_mode;
284 struct device_node *np;
285 u32 bpp; 284 u32 bpp;
286 dma_addr_t fb_mem_phys; 285 dma_addr_t fb_mem_phys;
287 unsigned long fb_mem_len; 286 unsigned long fb_mem_len;
@@ -346,32 +345,18 @@ static int vt8500lcd_probe(struct platform_device *pdev)
346 goto failed_free_res; 345 goto failed_free_res;
347 } 346 }
348 347
349 np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0); 348 disp_timing = of_get_display_timings(pdev->dev.of_node);
350 if (!np) { 349 if (!disp_timing)
351 pr_err("%s: No display description in Device Tree\n", __func__); 350 return -EINVAL;
352 ret = -EINVAL;
353 goto failed_free_res;
354 }
355 351
356 /* 352 ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode,
357 * This code is copied from Sascha Hauer's of_videomode helper 353 OF_USE_NATIVE_MODE);
358 * and can be replaced with a call to the helper once mainlined 354 if (ret)
359 */ 355 return ret;
360 ret = 0; 356
361 ret |= of_property_read_u32(np, "hactive", &of_mode.xres); 357 ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
362 ret |= of_property_read_u32(np, "vactive", &of_mode.yres); 358 if (ret)
363 ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin); 359 return ret;
364 ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin);
365 ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len);
366 ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin);
367 ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin);
368 ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len);
369 ret |= of_property_read_u32(np, "bpp", &bpp);
370 if (ret) {
371 pr_err("%s: Unable to read display properties\n", __func__);
372 goto failed_free_res;
373 }
374 of_mode.vmode = FB_VMODE_NONINTERLACED;
375 360
376 /* try allocating the framebuffer */ 361 /* try allocating the framebuffer */
377 fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8); 362 fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index 4dd0580f96fd..01f9ace068e2 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -14,25 +14,25 @@
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 */ 15 */
16 16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/errno.h>
20#include <linux/string.h>
21#include <linux/mm.h>
22#include <linux/slab.h>
23#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/dma-mapping.h>
24#include <linux/fb.h> 19#include <linux/fb.h>
20#include <linux/errno.h>
21#include <linux/err.h>
25#include <linux/init.h> 22#include <linux/init.h>
26#include <linux/interrupt.h> 23#include <linux/interrupt.h>
27#include <linux/io.h> 24#include <linux/io.h>
28#include <linux/dma-mapping.h> 25#include <linux/kernel.h>
29#include <linux/platform_device.h> 26#include <linux/memblock.h>
30#include <linux/wait.h> 27#include <linux/mm.h>
28#include <linux/module.h>
31#include <linux/of.h> 29#include <linux/of.h>
32#include <linux/of_fdt.h> 30#include <linux/of_fdt.h>
33#include <linux/memblock.h> 31#include <linux/platform_device.h>
34 32#include <linux/slab.h>
35#include <linux/platform_data/video-vt8500lcdfb.h> 33#include <linux/string.h>
34#include <linux/wait.h>
35#include <video/of_display_timing.h>
36 36
37#include "wm8505fb_regs.h" 37#include "wm8505fb_regs.h"
38#include "wmt_ge_rops.h" 38#include "wmt_ge_rops.h"
@@ -263,26 +263,22 @@ static struct fb_ops wm8505fb_ops = {
263static int wm8505fb_probe(struct platform_device *pdev) 263static int wm8505fb_probe(struct platform_device *pdev)
264{ 264{
265 struct wm8505fb_info *fbi; 265 struct wm8505fb_info *fbi;
266 struct resource *res; 266 struct resource *res;
267 struct display_timings *disp_timing;
267 void *addr; 268 void *addr;
268 int ret; 269 int ret;
269 270
270 struct fb_videomode of_mode; 271 struct fb_videomode mode;
271 struct device_node *np;
272 u32 bpp; 272 u32 bpp;
273 dma_addr_t fb_mem_phys; 273 dma_addr_t fb_mem_phys;
274 unsigned long fb_mem_len; 274 unsigned long fb_mem_len;
275 void *fb_mem_virt; 275 void *fb_mem_virt;
276 276
277 ret = -ENOMEM;
278 fbi = NULL;
279
280 fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) + 277 fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) +
281 sizeof(u32) * 16, GFP_KERNEL); 278 sizeof(u32) * 16, GFP_KERNEL);
282 if (!fbi) { 279 if (!fbi) {
283 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); 280 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
284 ret = -ENOMEM; 281 return -ENOMEM;
285 goto failed;
286 } 282 }
287 283
288 strcpy(fbi->fb.fix.id, DRIVER_NAME); 284 strcpy(fbi->fb.fix.id, DRIVER_NAME);
@@ -308,54 +304,23 @@ static int wm8505fb_probe(struct platform_device *pdev)
308 fbi->fb.pseudo_palette = addr; 304 fbi->fb.pseudo_palette = addr;
309 305
310 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 306 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
311 if (res == NULL) { 307 fbi->regbase = devm_ioremap_resource(&pdev->dev, res);
312 dev_err(&pdev->dev, "no I/O memory resource defined\n"); 308 if (IS_ERR(fbi->regbase))
313 ret = -ENODEV; 309 return PTR_ERR(fbi->regbase);
314 goto failed_fbi;
315 }
316 310
317 res = request_mem_region(res->start, resource_size(res), DRIVER_NAME); 311 disp_timing = of_get_display_timings(pdev->dev.of_node);
318 if (res == NULL) { 312 if (!disp_timing)
319 dev_err(&pdev->dev, "failed to request I/O memory\n"); 313 return -EINVAL;
320 ret = -EBUSY;
321 goto failed_fbi;
322 }
323
324 fbi->regbase = ioremap(res->start, resource_size(res));
325 if (fbi->regbase == NULL) {
326 dev_err(&pdev->dev, "failed to map I/O memory\n");
327 ret = -EBUSY;
328 goto failed_free_res;
329 }
330 314
331 np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0); 315 ret = of_get_fb_videomode(pdev->dev.of_node, &mode, OF_USE_NATIVE_MODE);
332 if (!np) { 316 if (ret)
333 pr_err("%s: No display description in Device Tree\n", __func__); 317 return ret;
334 ret = -EINVAL;
335 goto failed_free_res;
336 }
337 318
338 /* 319 ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
339 * This code is copied from Sascha Hauer's of_videomode helper 320 if (ret)
340 * and can be replaced with a call to the helper once mainlined 321 return ret;
341 */
342 ret = 0;
343 ret |= of_property_read_u32(np, "hactive", &of_mode.xres);
344 ret |= of_property_read_u32(np, "vactive", &of_mode.yres);
345 ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin);
346 ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin);
347 ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len);
348 ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin);
349 ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin);
350 ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len);
351 ret |= of_property_read_u32(np, "bpp", &bpp);
352 if (ret) {
353 pr_err("%s: Unable to read display properties\n", __func__);
354 goto failed_free_res;
355 }
356 322
357 of_mode.vmode = FB_VMODE_NONINTERLACED; 323 fb_videomode_to_var(&fbi->fb.var, &mode);
358 fb_videomode_to_var(&fbi->fb.var, &of_mode);
359 324
360 fbi->fb.var.nonstd = 0; 325 fbi->fb.var.nonstd = 0;
361 fbi->fb.var.activate = FB_ACTIVATE_NOW; 326 fbi->fb.var.activate = FB_ACTIVATE_NOW;
@@ -364,16 +329,16 @@ static int wm8505fb_probe(struct platform_device *pdev)
364 fbi->fb.var.width = -1; 329 fbi->fb.var.width = -1;
365 330
366 /* try allocating the framebuffer */ 331 /* try allocating the framebuffer */
367 fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8); 332 fb_mem_len = mode.xres * mode.yres * 2 * (bpp / 8);
368 fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys, 333 fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
369 GFP_KERNEL); 334 GFP_KERNEL);
370 if (!fb_mem_virt) { 335 if (!fb_mem_virt) {
371 pr_err("%s: Failed to allocate framebuffer\n", __func__); 336 pr_err("%s: Failed to allocate framebuffer\n", __func__);
372 return -ENOMEM; 337 return -ENOMEM;
373 }; 338 }
374 339
375 fbi->fb.var.xres_virtual = of_mode.xres; 340 fbi->fb.var.xres_virtual = mode.xres;
376 fbi->fb.var.yres_virtual = of_mode.yres * 2; 341 fbi->fb.var.yres_virtual = mode.yres * 2;
377 fbi->fb.var.bits_per_pixel = bpp; 342 fbi->fb.var.bits_per_pixel = bpp;
378 343
379 fbi->fb.fix.smem_start = fb_mem_phys; 344 fbi->fb.fix.smem_start = fb_mem_phys;
@@ -381,28 +346,29 @@ static int wm8505fb_probe(struct platform_device *pdev)
381 fbi->fb.screen_base = fb_mem_virt; 346 fbi->fb.screen_base = fb_mem_virt;
382 fbi->fb.screen_size = fb_mem_len; 347 fbi->fb.screen_size = fb_mem_len;
383 348
349 fbi->contrast = 0x10;
350 ret = wm8505fb_set_par(&fbi->fb);
351 if (ret) {
352 dev_err(&pdev->dev, "Failed to set parameters\n");
353 return ret;
354 }
355
384 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) { 356 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
385 dev_err(&pdev->dev, "Failed to allocate color map\n"); 357 dev_err(&pdev->dev, "Failed to allocate color map\n");
386 ret = -ENOMEM; 358 return -ENOMEM;
387 goto failed_free_io;
388 } 359 }
389 360
390 wm8505fb_init_hw(&fbi->fb); 361 wm8505fb_init_hw(&fbi->fb);
391 362
392 fbi->contrast = 0x80;
393 ret = wm8505fb_set_par(&fbi->fb);
394 if (ret) {
395 dev_err(&pdev->dev, "Failed to set parameters\n");
396 goto failed_free_cmap;
397 }
398
399 platform_set_drvdata(pdev, fbi); 363 platform_set_drvdata(pdev, fbi);
400 364
401 ret = register_framebuffer(&fbi->fb); 365 ret = register_framebuffer(&fbi->fb);
402 if (ret < 0) { 366 if (ret < 0) {
403 dev_err(&pdev->dev, 367 dev_err(&pdev->dev,
404 "Failed to register framebuffer device: %d\n", ret); 368 "Failed to register framebuffer device: %d\n", ret);
405 goto failed_free_cmap; 369 if (fbi->fb.cmap.len)
370 fb_dealloc_cmap(&fbi->fb.cmap);
371 return ret;
406 } 372 }
407 373
408 ret = device_create_file(&pdev->dev, &dev_attr_contrast); 374 ret = device_create_file(&pdev->dev, &dev_attr_contrast);
@@ -416,25 +382,11 @@ static int wm8505fb_probe(struct platform_device *pdev)
416 fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1); 382 fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
417 383
418 return 0; 384 return 0;
419
420failed_free_cmap:
421 if (fbi->fb.cmap.len)
422 fb_dealloc_cmap(&fbi->fb.cmap);
423failed_free_io:
424 iounmap(fbi->regbase);
425failed_free_res:
426 release_mem_region(res->start, resource_size(res));
427failed_fbi:
428 platform_set_drvdata(pdev, NULL);
429 kfree(fbi);
430failed:
431 return ret;
432} 385}
433 386
434static int wm8505fb_remove(struct platform_device *pdev) 387static int wm8505fb_remove(struct platform_device *pdev)
435{ 388{
436 struct wm8505fb_info *fbi = platform_get_drvdata(pdev); 389 struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
437 struct resource *res;
438 390
439 device_remove_file(&pdev->dev, &dev_attr_contrast); 391 device_remove_file(&pdev->dev, &dev_attr_contrast);
440 392
@@ -445,13 +397,6 @@ static int wm8505fb_remove(struct platform_device *pdev)
445 if (fbi->fb.cmap.len) 397 if (fbi->fb.cmap.len)
446 fb_dealloc_cmap(&fbi->fb.cmap); 398 fb_dealloc_cmap(&fbi->fb.cmap);
447 399
448 iounmap(fbi->regbase);
449
450 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
451 release_mem_region(res->start, resource_size(res));
452
453 kfree(fbi);
454
455 return 0; 400 return 0;
456} 401}
457 402
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h
index 87380751a443..f73ec6377a46 100644
--- a/drivers/video/wmt_ge_rops.h
+++ b/drivers/video/wmt_ge_rops.h
@@ -1,5 +1,28 @@
1#ifdef CONFIG_FB_WMT_GE_ROPS
2
1extern void wmt_ge_fillrect(struct fb_info *info, 3extern void wmt_ge_fillrect(struct fb_info *info,
2 const struct fb_fillrect *rect); 4 const struct fb_fillrect *rect);
3extern void wmt_ge_copyarea(struct fb_info *info, 5extern void wmt_ge_copyarea(struct fb_info *info,
4 const struct fb_copyarea *area); 6 const struct fb_copyarea *area);
5extern int wmt_ge_sync(struct fb_info *info); 7extern int wmt_ge_sync(struct fb_info *info);
8
9#else
10
11static inline int wmt_ge_sync(struct fb_info *p)
12{
13 return 0;
14}
15
16static inline void wmt_ge_fillrect(struct fb_info *p,
17 const struct fb_fillrect *rect)
18{
19 sys_fillrect(p, rect);
20}
21
22static inline void wmt_ge_copyarea(struct fb_info *p,
23 const struct fb_copyarea *area)
24{
25 sys_copyarea(p, area);
26}
27
28#endif