diff options
Diffstat (limited to 'drivers/video')
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 | ||
22 | source "drivers/gpu/drm/Kconfig" | 22 | source "drivers/gpu/drm/Kconfig" |
23 | 23 | ||
24 | source "drivers/gpu/host1x/Kconfig" | ||
25 | |||
24 | config VGASTATE | 26 | config 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 | ||
34 | config DISPLAY_TIMING | 36 | config VIDEOMODE_HELPERS |
35 | bool | 37 | bool |
36 | |||
37 | config VIDEOMODE | ||
38 | bool | ||
39 | |||
40 | config 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 | |||
47 | config 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 | ||
55 | config HDMI | 39 | config 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 | ||
215 | config 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 | |||
223 | config FB_DEFERRED_IO | 199 | config 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 | ||
1799 | config FB_VT8500 | 1775 | config 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 | ||
1808 | config FB_WM8505 | 1787 | config 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 | |||
1800 | config 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 | ||
1817 | source "drivers/video/geode/Kconfig" | 1808 | source "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 | ||
2447 | config 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 | |||
2456 | source "drivers/video/omap/Kconfig" | 2456 | source "drivers/video/omap/Kconfig" |
2457 | source "drivers/video/omap2/Kconfig" | 2457 | source "drivers/video/omap2/Kconfig" |
2458 | source "drivers/video/exynos/Kconfig" | 2458 | source "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/ | |||
149 | obj-$(CONFIG_FB_NUC900) += nuc900fb.o | 149 | obj-$(CONFIG_FB_NUC900) += nuc900fb.o |
150 | obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o | 150 | obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o |
151 | obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o | 151 | obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o |
152 | obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o | ||
152 | 153 | ||
153 | # Platform or fallback drivers go here | 154 | # Platform or fallback drivers go here |
154 | obj-$(CONFIG_FB_UVESA) += uvesafb.o | 155 | obj-$(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 |
173 | obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o | 174 | obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o |
174 | obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o | 175 | obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o |
175 | obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o | 176 | ifeq ($(CONFIG_OF),y) |
176 | obj-$(CONFIG_VIDEOMODE) += videomode.o | 177 | obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o |
177 | obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o | 178 | endif |
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 | ||
3791 | static int __init amifb_init(void) | 3791 | module_platform_driver_probe(amifb_driver, amifb_probe); |
3792 | { | ||
3793 | return platform_driver_probe(&amifb_driver, amifb_probe); | ||
3794 | } | ||
3795 | |||
3796 | module_init(amifb_init); | ||
3797 | |||
3798 | static void __exit amifb_exit(void) | ||
3799 | { | ||
3800 | platform_driver_unregister(&amifb_driver); | ||
3801 | } | ||
3802 | |||
3803 | module_exit(amifb_exit); | ||
3804 | 3792 | ||
3805 | MODULE_LICENSE("GPL"); | 3793 | MODULE_LICENSE("GPL"); |
3806 | MODULE_ALIAS("platform:amiga-video"); | 3794 | MODULE_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 | ||
37 | struct atmel_lcdfb_config { | ||
38 | bool have_alt_pixclock; | ||
39 | bool have_hozval; | ||
40 | bool have_intensity_bit; | ||
41 | }; | ||
42 | |||
43 | static struct atmel_lcdfb_config at91sam9261_config = { | ||
44 | .have_hozval = true, | ||
45 | .have_intensity_bit = true, | ||
46 | }; | ||
47 | |||
48 | static struct atmel_lcdfb_config at91sam9263_config = { | ||
49 | .have_intensity_bit = true, | ||
50 | }; | ||
51 | |||
52 | static struct atmel_lcdfb_config at91sam9g10_config = { | ||
53 | .have_hozval = true, | ||
54 | }; | ||
55 | |||
56 | static struct atmel_lcdfb_config at91sam9g45_config = { | ||
57 | .have_alt_pixclock = true, | ||
58 | }; | ||
59 | |||
60 | static struct atmel_lcdfb_config at91sam9g45es_config = { | ||
61 | }; | ||
62 | |||
63 | static struct atmel_lcdfb_config at91sam9rl_config = { | ||
64 | .have_intensity_bit = true, | ||
65 | }; | ||
66 | |||
67 | static struct atmel_lcdfb_config at32ap_config = { | ||
68 | .have_hozval = true, | ||
69 | }; | ||
70 | |||
71 | static 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 | |||
98 | static struct atmel_lcdfb_config * | ||
99 | atmel_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 | ||
196 | static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) | 267 | static 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 | ||
822 | static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) | 894 | static 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 | ||
829 | static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) | 900 | static 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); |
1057 | put_bus_clk: | 1123 | put_bus_clk: |
1058 | if (sinfo->bus_clk) | 1124 | clk_put(sinfo->bus_clk); |
1059 | clk_put(sinfo->bus_clk); | ||
1060 | free_info: | 1125 | free_info: |
1061 | framebuffer_release(info); | 1126 | framebuffer_release(info); |
1062 | out: | 1127 | out: |
@@ -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 | ||
1161 | static int __init atmel_lcdfb_init(void) | 1225 | module_platform_driver_probe(atmel_lcdfb_driver, atmel_lcdfb_probe); |
1162 | { | ||
1163 | return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe); | ||
1164 | } | ||
1165 | |||
1166 | static void __exit atmel_lcdfb_exit(void) | ||
1167 | { | ||
1168 | platform_driver_unregister(&atmel_lcdfb_driver); | ||
1169 | } | ||
1170 | |||
1171 | module_init(atmel_lcdfb_init); | ||
1172 | module_exit(atmel_lcdfb_exit); | ||
1173 | 1226 | ||
1174 | MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); | 1227 | MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); |
1175 | MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>"); | 1228 | MODULE_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 | ||
61 | static void auok1900_init(struct auok190xfb_par *par) | 61 | static 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 | ||
79 | static void auok1900_update_region(struct auok190xfb_par *par, int mode, | 85 | static void auok1900_update_region(struct auok190xfb_par *par, int mode, |
@@ -82,6 +88,7 @@ static void auok1900_update_region(struct auok190xfb_par *par, int mode, | |||
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 | ||
102 | static void auok1901_init(struct auok190xfb_par *par) | 102 | static 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 | ||
118 | static void auok1901_update_region(struct auok190xfb_par *par, int mode, | 124 | static void auok1901_update_region(struct auok190xfb_par *par, int mode, |
@@ -121,6 +127,7 @@ static void auok1901_update_region(struct auok190xfb_par *par, int mode, | |||
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 | ||
63 | static 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 | */ | ||
75 | static 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 | |||
82 | static 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 | |||
111 | static 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 | ||
142 | static 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 | |||
94 | static u16 auok190x_read_data(struct auok190xfb_par *par) | 159 | static 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, | |||
376 | static int auok190xfb_check_var(struct fb_var_screeninfo *var, | 441 | static 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 | ||
531 | static 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 | |||
549 | static 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 | |||
400 | static struct fb_ops auok190xfb_ops = { | 565 | static 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 | ||
589 | static void auok190x_recover(struct auok190xfb_par *par) | 755 | static 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 | ||
62 | config 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 | |||
62 | config LCD_ILI9320 | 69 | config 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 | |||
161 | config BACKLIGHT_ATMEL_LCDC | 168 | config 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 | |||
5 | obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o | 5 | obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o |
6 | obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o | 6 | obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o |
7 | obj-$(CONFIG_LCD_HX8357) += hx8357.o | 7 | obj-$(CONFIG_LCD_HX8357) += hx8357.o |
8 | obj-$(CONFIG_LCD_ILI922X) += ili922x.o | ||
8 | obj-$(CONFIG_LCD_ILI9320) += ili9320.o | 9 | obj-$(CONFIG_LCD_ILI9320) += ili9320.o |
9 | obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o | 10 | obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o |
10 | obj-$(CONFIG_LCD_LD9040) += ld9040.o | 11 | obj-$(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) | |||
143 | static ssize_t adp5520_show(struct device *dev, char *buf, int reg) | 143 | static 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, ®_val); | 150 | ret = adp5520_read(data->master, 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 |
353 | static int adp5520_bl_suspend(struct platform_device *pdev, | 356 | static 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 | ||
360 | static int adp5520_bl_resume(struct platform_device *pdev) | 363 | static 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 | ||
372 | static SIMPLE_DEV_PM_OPS(adp5520_bl_pm_ops, adp5520_bl_suspend, | ||
373 | adp5520_bl_resume); | ||
374 | |||
372 | static struct platform_driver adp5520_bl_driver = { | 375 | static 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 | ||
383 | module_platform_driver(adp5520_bl_driver); | 385 | module_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 |
777 | static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message) | 779 | static 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 | ||
784 | static int adp8860_i2c_resume(struct i2c_client *client) | 788 | static 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 | ||
798 | static SIMPLE_DEV_PM_OPS(adp8860_i2c_pm_ops, adp8860_i2c_suspend, | ||
799 | adp8860_i2c_resume); | ||
800 | |||
795 | static const struct i2c_device_id adp8860_id[] = { | 801 | static 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 | ||
803 | static struct i2c_driver adp8860_driver = { | 809 | static 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 |
951 | static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message) | 953 | static 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 | ||
958 | static int adp8870_i2c_resume(struct i2c_client *client) | 962 | static 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 | ||
972 | static SIMPLE_DEV_PM_OPS(adp8870_i2c_pm_ops, adp8870_i2c_suspend, | ||
973 | adp8870_i2c_resume); | ||
974 | |||
969 | static const struct i2c_device_id adp8870_id[] = { | 975 | static 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 | ||
975 | static struct i2c_driver adp8870_driver = { | 981 | static 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 |
537 | static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg) | 537 | static 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 | ||
550 | static int ams369fg06_resume(struct spi_device *spi) | 550 | static 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 | ||
560 | static SIMPLE_DEV_PM_OPS(ams369fg06_pm_ops, ams369fg06_suspend, | ||
561 | ams369fg06_resume); | ||
562 | |||
563 | static void ams369fg06_shutdown(struct spi_device *spi) | 563 | static 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 | ||
582 | module_spi_driver(ams369fg06_driver); | 581 | module_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 | ||
261 | static 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 | |||
261 | static int as3711_backlight_probe(struct platform_device *pdev) | 364 | static 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 | ||
121 | static int atmel_pwm_bl_probe(struct platform_device *pdev) | 121 | static 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 | ||
228 | static int __init atmel_pwm_bl_init(void) | 228 | module_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 | } | ||
232 | module_init(atmel_pwm_bl_init); | ||
233 | |||
234 | static void __exit atmel_pwm_bl_exit(void) | ||
235 | { | ||
236 | platform_driver_unregister(&atmel_pwm_bl_driver); | ||
237 | } | ||
238 | module_exit(atmel_pwm_bl_exit); | ||
239 | 229 | ||
240 | MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>"); | 230 | MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>"); |
241 | MODULE_DESCRIPTION("Atmel PWM backlight driver"); | 231 | MODULE_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 |
461 | static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state) | 461 | static 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 | ||
471 | static int corgi_lcd_resume(struct spi_device *spi) | 471 | static 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 | ||
482 | static SIMPLE_DEV_PM_OPS(corgi_lcd_pm_ops, corgi_lcd_suspend, corgi_lcd_resume); | ||
483 | |||
485 | static int setup_gpio_backlight(struct corgi_lcd *lcd, | 484 | static 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 | ||
621 | module_spi_driver(corgi_lcd_driver); | 619 | module_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 | ||
94 | static int da903x_backlight_get_brightness(struct backlight_device *bl) | 97 | static 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 | ||
100 | static const struct backlight_ops da903x_backlight_ops = { | 104 | static 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 | ||
165 | static 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 | |||
172 | static 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 | |||
180 | static const struct dev_pm_ops da903x_backlight_pm_ops = { | ||
181 | .suspend = da903x_backlight_suspend, | ||
182 | .resume = da903x_backlight_resume, | ||
183 | }; | ||
184 | #endif | ||
185 | |||
186 | static struct platform_driver da903x_backlight_driver = { | 169 | static 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 | ||
63 | static int __init ep93xxbl_probe(struct platform_device *dev) | 63 | static 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 |
119 | static int ep93xxbl_suspend(struct platform_device *dev, pm_message_t state) | 119 | static 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 | ||
126 | static int ep93xxbl_resume(struct platform_device *dev) | 126 | static 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 | ||
135 | static SIMPLE_DEV_PM_OPS(ep93xxbl_pm_ops, ep93xxbl_suspend, ep93xxbl_resume); | ||
136 | |||
138 | static struct platform_driver ep93xxbl_driver = { | 137 | static 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 | ||
149 | module_platform_driver(ep93xxbl_driver); | 147 | module_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 |
68 | static int hp680bl_suspend(struct platform_device *pdev, pm_message_t state) | 68 | static 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 | ||
77 | static int hp680bl_resume(struct platform_device *pdev) | 77 | static 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 | ||
87 | static SIMPLE_DEV_PM_OPS(hp680bl_pm_ops, hp680bl_suspend, hp680bl_resume); | ||
88 | |||
90 | static int hp680bl_set_intensity(struct backlight_device *bd) | 89 | static 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) | |||
140 | static struct platform_driver hp680bl_driver = { | 139 | static 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 | */ | ||
131 | static int ili922x_id = 1; | ||
132 | module_param(ili922x_id, int, 0); | ||
133 | |||
134 | static int tx_invert; | ||
135 | module_param(tx_invert, int, 0); | ||
136 | |||
137 | /** | ||
138 | * driver's private structure | ||
139 | */ | ||
140 | struct 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 | */ | ||
151 | static 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 | */ | ||
194 | static 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 | */ | ||
248 | static 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 | */ | ||
302 | static 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 | ||
315 | static 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 | */ | ||
322 | static 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 | */ | ||
353 | static 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 | */ | ||
382 | static 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 | */ | ||
403 | static 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 | |||
443 | static 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 | |||
458 | static 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 | |||
465 | static int ili922x_get_power(struct lcd_device *ld) | ||
466 | { | ||
467 | struct ili922x *ili = lcd_get_data(ld); | ||
468 | |||
469 | return ili->power; | ||
470 | } | ||
471 | |||
472 | static struct lcd_ops ili922x_ops = { | ||
473 | .get_power = ili922x_get_power, | ||
474 | .set_power = ili922x_set_power, | ||
475 | }; | ||
476 | |||
477 | static 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, ®); | ||
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, ®); | ||
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 | |||
531 | static 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 | |||
540 | static 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 | |||
549 | module_spi_driver(ili922x_driver); | ||
550 | |||
551 | MODULE_AUTHOR("Stefano Babic <sbabic@denx.de>"); | ||
552 | MODULE_DESCRIPTION("ILI9221/9222 LCD driver"); | ||
553 | MODULE_LICENSE("GPL"); | ||
554 | MODULE_PARM_DESC(ili922x_id, "set controller identifier (default=1)"); | ||
555 | MODULE_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 | } |
271 | EXPORT_SYMBOL_GPL(ili9320_remove); | 271 | EXPORT_SYMBOL_GPL(ili9320_remove); |
272 | 272 | ||
273 | #ifdef CONFIG_PM | 273 | #ifdef CONFIG_PM_SLEEP |
274 | int ili9320_suspend(struct ili9320 *lcd, pm_message_t state) | 274 | int 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 | } |
295 | EXPORT_SYMBOL_GPL(ili9320_suspend); | 289 | EXPORT_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 | ||
79 | extern int ili9320_suspend(struct ili9320 *lcd, pm_message_t state); | 79 | extern int ili9320_suspend(struct ili9320 *lcd); |
80 | extern int ili9320_resume(struct ili9320 *lcd); | 80 | extern 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 | ||
30 | static int jornada_lcd_get_power(struct lcd_device *dev) | 28 | static 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 | ||
39 | static int jornada_lcd_get_contrast(struct lcd_device *dev) | 37 | static 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 | ||
59 | static int jornada_lcd_set_contrast(struct lcd_device *dev, int value) | 57 | static 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 | ||
81 | static int jornada_lcd_set_power(struct lcd_device *dev, int power) | 79 | static 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 |
110 | static int kb3886bl_suspend(struct platform_device *pdev, pm_message_t state) | 110 | static 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 | ||
119 | static int kb3886bl_resume(struct platform_device *pdev) | 119 | static 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 | ||
129 | static SIMPLE_DEV_PM_OPS(kb3886bl_pm_ops, kb3886bl_suspend, kb3886bl_resume); | ||
130 | |||
132 | static int kb3886bl_get_intensity(struct backlight_device *bd) | 131 | static 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) | |||
179 | static struct platform_driver kb3886bl_driver = { | 178 | static 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 |
779 | static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg) | 779 | static 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 | ||
792 | static int ld9040_resume(struct spi_device *spi) | 792 | static 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 | ||
802 | static 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. */ |
806 | static void ld9040_shutdown(struct spi_device *spi) | 805 | static 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 | ||
825 | module_spi_driver(ld9040_driver); | 823 | module_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 |
372 | static int lm3533_bl_suspend(struct platform_device *pdev, pm_message_t state) | 372 | static 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 | ||
381 | static int lm3533_bl_resume(struct platform_device *pdev) | 381 | static 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 | ||
391 | static SIMPLE_DEV_PM_OPS(lm3533_bl_pm_ops, lm3533_bl_suspend, lm3533_bl_resume); | ||
392 | |||
394 | static void lm3533_bl_shutdown(struct platform_device *pdev) | 393 | static 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 | }; |
414 | module_platform_driver(lm3533_bl_driver); | 412 | module_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 | 391 | static int lms501kf03_suspend(struct device *dev) | |
392 | static 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 | ||
405 | static int lms501kf03_resume(struct spi_device *spi) | 404 | static 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 | ||
414 | static SIMPLE_DEV_PM_OPS(lms501kf03_pm_ops, lms501kf03_suspend, | ||
415 | lms501kf03_resume); | ||
416 | |||
418 | static void lms501kf03_shutdown(struct spi_device *spi) | 417 | static 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 | ||
437 | module_spi_driver(lms501kf03_driver); | 435 | module_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 |
161 | static int locomolcd_suspend(struct locomo_dev *dev, pm_message_t state) | 161 | static 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 | ||
168 | static int locomolcd_resume(struct locomo_dev *dev) | 168 | static 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 | ||
176 | static SIMPLE_DEV_PM_OPS(locomolcd_pm_ops, locomolcd_suspend, locomolcd_resume); | ||
177 | |||
179 | static int locomolcd_probe(struct locomo_dev *ldev) | 178 | static 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 | ||
231 | static struct locomo_driver poodle_lcd_driver = { | 230 | static 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 | ||
242 | static int __init locomolcd_init(void) | 240 | static 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 | ||
42 | enum lp855x_brightness_ctrl_mode { | ||
43 | PWM_BASED = 1, | ||
44 | REGISTER_BASED, | ||
45 | }; | ||
46 | |||
42 | struct lp855x; | 47 | struct lp855x; |
43 | 48 | ||
44 | /* | 49 | /* |
@@ -58,6 +63,7 @@ struct lp855x_device_config { | |||
58 | struct lp855x { | 63 | struct 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) | |||
239 | static int lp855x_bl_update_status(struct backlight_device *bl) | 245 | static 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 | ||
310 | static ssize_t lp855x_get_bl_ctl_mode(struct device *dev, | 315 | static 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 | ||
325 | static DEVICE_ATTR(chip_id, S_IRUGO, lp855x_get_chip_id, NULL); | 329 | static 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 | ||
343 | static 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 | ||
388 | static int lp855x_parse_dt(struct device *dev, struct device_node *node) | ||
389 | { | ||
390 | return -EINVAL; | ||
391 | } | ||
392 | #endif | ||
393 | |||
338 | static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) | 394 | static 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 | ||
468 | static 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 | }; | ||
477 | MODULE_DEVICE_TABLE(of, lp855x_dt_ids); | ||
478 | |||
405 | static const struct i2c_device_id lp855x_ids[] = { | 479 | static 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); | |||
416 | static struct i2c_driver lp855x_driver = { | 490 | static 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 |
275 | static int ltv350qv_suspend(struct spi_device *spi, pm_message_t state) | 275 | static 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 | ||
282 | static int ltv350qv_resume(struct spi_device *spi) | 282 | static 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 | ||
290 | static 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 */ |
294 | static void ltv350qv_shutdown(struct spi_device *spi) | 293 | static 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 = <v350qv_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 | ||
314 | module_spi_driver(ltv350qv_driver); | 312 | module_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 |
77 | static int omapbl_suspend(struct platform_device *pdev, pm_message_t state) | 75 | static 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 | ||
86 | static int omapbl_resume(struct platform_device *pdev) | 84 | static 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 | ||
99 | static int omapbl_set_power(struct backlight_device *dev, int state) | 94 | static 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 | ||
182 | static SIMPLE_DEV_PM_OPS(omapbl_pm_ops, omapbl_suspend, omapbl_resume); | ||
183 | |||
187 | static struct platform_driver omapbl_driver = { | 184 | static 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 |
125 | static int platform_lcd_suspend(struct device *dev) | 131 | static 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 | ||
145 | static SIMPLE_DEV_PM_OPS(platform_lcd_pm_ops, platform_lcd_suspend, | 152 | static 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 |
150 | static const struct of_device_id platform_lcd_of_match[] = { | 156 | static 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 |
278 | static int pwm_backlight_suspend(struct device *dev) | 278 | static 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 | ||
300 | static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend, | 301 | static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend, |
301 | pwm_backlight_resume); | 302 | pwm_backlight_resume); |
302 | 303 | ||
303 | #endif | ||
304 | |||
305 | static struct platform_driver pwm_backlight_driver = { | 304 | static 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 |
821 | static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) | 821 | static 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 | ||
834 | static int s6e63m0_resume(struct spi_device *spi) | 834 | static 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 | ||
844 | static 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. */ |
848 | static void s6e63m0_shutdown(struct spi_device *spi) | 847 | static 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 | ||
867 | module_spi_driver(s6e63m0_driver); | 865 | module_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 |
416 | static int tdo24m_suspend(struct spi_device *spi, pm_message_t state) | 416 | static 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 | ||
423 | static int tdo24m_resume(struct spi_device *spi) | 423 | static 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 | ||
431 | static 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 */ |
435 | static void tdo24m_shutdown(struct spi_device *spi) | 434 | static 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 | ||
454 | module_spi_driver(tdo24m_driver); | 452 | module_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 |
138 | static int tosa_bl_suspend(struct i2c_client *client, pm_message_t pm) | 138 | static 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 | ||
147 | static int tosa_bl_resume(struct i2c_client *client) | 147 | static 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 | ||
156 | static SIMPLE_DEV_PM_OPS(tosa_bl_pm_ops, tosa_bl_suspend, tosa_bl_resume); | ||
157 | |||
159 | static const struct i2c_device_id tosa_bl_id[] = { | 158 | static 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 |
244 | static int tosa_lcd_suspend(struct spi_device *spi, pm_message_t state) | 244 | static 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 | ||
253 | static int tosa_lcd_resume(struct spi_device *spi) | 253 | static 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 | ||
267 | static SIMPLE_DEV_PM_OPS(tosa_lcd_pm_ops, tosa_lcd_suspend, tosa_lcd_resume); | ||
268 | |||
270 | static struct spi_driver tosa_lcd_driver = { | 269 | static 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 | ||
281 | module_spi_driver(tosa_lcd_driver); | 279 | module_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 |
209 | static int vgg2432a4_suspend(struct spi_device *spi, pm_message_t state) | 209 | static 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 | } |
213 | static int vgg2432a4_resume(struct spi_device *spi) | 213 | static 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 | ||
222 | static struct ili9320_client vgg2432a4_client = { | 219 | static 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 | ||
249 | static SIMPLE_DEV_PM_OPS(vgg2432a4_pm_ops, vgg2432a4_suspend, vgg2432a4_resume); | ||
250 | |||
252 | static struct spi_driver vgg2432a4_driver = { | 251 | static 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 | ||
264 | module_spi_driver(vgg2432a4_driver); | 262 | module_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 | ||
336 | static int | 336 | static ssize_t |
337 | adv7393_read_proc(char *page, char **start, off_t off, | 337 | adv7393_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 | ||
354 | static int | 348 | static ssize_t |
355 | adv7393_write_proc(struct file *file, const char __user * buffer, | 349 | adv7393_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 | ||
365 | static const struct file_operations fops = { | ||
366 | .read = adv7393_read_proc, | ||
367 | .write = adv7393_write_proc, | ||
368 | .llseek = default_llseek, | ||
369 | }; | ||
370 | |||
371 | static int bfin_adv7393_fb_probe(struct i2c_client *client, | 371 | static 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 | ||
522 | free_fb: | 517 | free_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) | ||
1880 | static 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 |
1889 | static int release_io_ports; | 1860 | static 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) | |||
1228 | finished: | 1228 | finished: |
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, | |||
285 | static int controlfb_mmap(struct fb_info *info, | 285 | static 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 | ||
320 | static int controlfb_blank(int blank_mode, struct fb_info *info) | 310 | static 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 | ||
422 | static int __init ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info) | 422 | static 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 | ||
444 | static int __init ep93xxfb_alloc_videomem(struct fb_info *info) | 444 | static 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 | 630 | module_platform_driver(ep93xxfb_driver); | |
631 | static int ep93xxfb_init(void) | ||
632 | { | ||
633 | return platform_driver_register(&ep93xxfb_driver); | ||
634 | } | ||
635 | |||
636 | static void __exit ep93xxfb_exit(void) | ||
637 | { | ||
638 | platform_driver_unregister(&ep93xxfb_driver); | ||
639 | } | ||
640 | |||
641 | module_init(ep93xxfb_init); | ||
642 | module_exit(ep93xxfb_exit); | ||
643 | 631 | ||
644 | MODULE_DESCRIPTION("EP93XX Framebuffer Driver"); | 632 | MODULE_DESCRIPTION("EP93XX Framebuffer Driver"); |
645 | MODULE_ALIAS("platform:ep93xx-fb"); | 633 | MODULE_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 | ||
33 | void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim) | 31 | void 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, | |||
640 | int unifb_mmap(struct fb_info *info, | 640 | int 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 | ||
660 | static struct fb_ops unifb_ops = { | 648 | static 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 | ||
1424 | static int | 1418 | static 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 |
1380 | int fb_videomode_from_videomode(const struct videomode *vm, | 1380 | int 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 | } |
1426 | EXPORT_SYMBOL_GPL(fb_videomode_from_videomode); | 1426 | EXPORT_SYMBOL_GPL(fb_videomode_from_videomode); |
1427 | #endif | ||
1428 | 1427 | ||
1429 | #if IS_ENABLED(CONFIG_OF_VIDEOMODE) | 1428 | #ifdef CONFIG_OF |
1430 | static inline void dump_fb_videomode(const struct fb_videomode *m) | 1429 | static 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 | } |
1467 | EXPORT_SYMBOL_GPL(of_get_fb_videomode); | 1466 | EXPORT_SYMBOL_GPL(of_get_fb_videomode); |
1468 | #endif | 1467 | #endif /* CONFIG_OF */ |
1468 | #endif /* CONFIG_VIDEOMODE_HELPERS */ | ||
1469 | 1469 | ||
1470 | #else | 1470 | #else |
1471 | int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) | 1471 | int 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 | */ | ||
994 | static 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 | */ | ||
1023 | static 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 | ||
1317 | static int install_fb(struct fb_info *info) | 1470 | static 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 | |||
69 | enum pipe_msg_type { | ||
70 | PIPE_MSG_INVALID, | ||
71 | PIPE_MSG_DATA, | ||
72 | PIPE_MSG_MAX | ||
73 | }; | ||
74 | |||
75 | struct pipe_msg_hdr { | ||
76 | u32 type; | ||
77 | u32 size; /* size of message after this field */ | ||
78 | } __packed; | ||
79 | |||
80 | |||
81 | enum 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 | |||
97 | struct synthvid_msg_hdr { | ||
98 | u32 type; | ||
99 | u32 size; /* size of this header + payload after this field*/ | ||
100 | } __packed; | ||
101 | |||
102 | |||
103 | struct synthvid_version_req { | ||
104 | u32 version; | ||
105 | } __packed; | ||
106 | |||
107 | struct synthvid_version_resp { | ||
108 | u32 version; | ||
109 | u8 is_accepted; | ||
110 | u8 max_video_outputs; | ||
111 | } __packed; | ||
112 | |||
113 | struct synthvid_vram_location { | ||
114 | u64 user_ctx; | ||
115 | u8 is_vram_gpa_specified; | ||
116 | u64 vram_gpa; | ||
117 | } __packed; | ||
118 | |||
119 | struct synthvid_vram_location_ack { | ||
120 | u64 user_ctx; | ||
121 | } __packed; | ||
122 | |||
123 | struct 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 | |||
132 | struct synthvid_situation_update { | ||
133 | u64 user_ctx; | ||
134 | u8 video_output_count; | ||
135 | struct video_output_situation video_output[1]; | ||
136 | } __packed; | ||
137 | |||
138 | struct synthvid_situation_update_ack { | ||
139 | u64 user_ctx; | ||
140 | } __packed; | ||
141 | |||
142 | struct 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 | |||
156 | struct 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 | |||
166 | struct 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 | |||
173 | struct rect { | ||
174 | s32 x1, y1; /* top left corner */ | ||
175 | s32 x2, y2; /* bottom right corner, exclusive */ | ||
176 | } __packed; | ||
177 | |||
178 | struct synthvid_dirt { | ||
179 | u8 video_output; | ||
180 | u8 dirt_count; | ||
181 | struct rect rect[1]; | ||
182 | } __packed; | ||
183 | |||
184 | struct 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 | |||
213 | struct 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 | |||
227 | static uint screen_width = HVFB_WIDTH; | ||
228 | static uint screen_height = HVFB_HEIGHT; | ||
229 | static uint screen_depth; | ||
230 | static uint screen_fb_size; | ||
231 | |||
232 | /* Send message to Hyper-V host */ | ||
233 | static 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 */ | ||
255 | static 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 */ | ||
283 | static 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 */ | ||
317 | static 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 | */ | ||
345 | static 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 */ | ||
379 | static 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 */ | ||
406 | static 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 | |||
433 | out: | ||
434 | return ret; | ||
435 | } | ||
436 | |||
437 | /* Connect to VSP (Virtual Service Provider) on host */ | ||
438 | static 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 | |||
473 | error: | ||
474 | vmbus_close(hdev->channel); | ||
475 | return ret; | ||
476 | } | ||
477 | |||
478 | /* Send VRAM and Situation messages to the host */ | ||
479 | static 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 | |||
511 | out: | ||
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 | */ | ||
521 | static 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 | |||
536 | static 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 | |||
549 | static 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 | |||
557 | static inline u32 chan_to_field(u32 chan, struct fb_bitfield *bf) | ||
558 | { | ||
559 | return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset; | ||
560 | } | ||
561 | |||
562 | static 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 | |||
579 | static 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=" */ | ||
591 | static 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 */ | ||
623 | static 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 | |||
662 | err3: | ||
663 | iounmap(fb_virt); | ||
664 | err2: | ||
665 | release_mem_region(fb_phys, screen_fb_size); | ||
666 | err1: | ||
667 | pci_dev_put(pdev); | ||
668 | return -ENOMEM; | ||
669 | } | ||
670 | |||
671 | /* Release the framebuffer */ | ||
672 | static 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 | |||
679 | static 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 | |||
765 | error: | ||
766 | hvfb_putmem(info); | ||
767 | error2: | ||
768 | vmbus_close(hdev->channel); | ||
769 | error1: | ||
770 | cancel_delayed_work_sync(&par->dwork); | ||
771 | hv_set_drvdata(hdev, NULL); | ||
772 | framebuffer_release(info); | ||
773 | return ret; | ||
774 | } | ||
775 | |||
776 | |||
777 | static 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 | |||
798 | static const struct hv_vmbus_device_id id_table[] = { | ||
799 | /* Synthetic Video Device GUID */ | ||
800 | {HV_SYNTHVID_GUID}, | ||
801 | {} | ||
802 | }; | ||
803 | |||
804 | MODULE_DEVICE_TABLE(vmbus, id_table); | ||
805 | |||
806 | static 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 | |||
814 | static int __init hvfb_drv_init(void) | ||
815 | { | ||
816 | return vmbus_driver_register(&hvfb_drv); | ||
817 | } | ||
818 | |||
819 | static void __exit hvfb_drv_exit(void) | ||
820 | { | ||
821 | vmbus_driver_unregister(&hvfb_drv); | ||
822 | } | ||
823 | |||
824 | module_init(hvfb_drv_init); | ||
825 | module_exit(hvfb_drv_exit); | ||
826 | |||
827 | MODULE_LICENSE("GPL"); | ||
828 | MODULE_VERSION(HV_DRV_VERSION); | ||
829 | MODULE_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 | ||
138 | static int maven_get_reg(struct i2c_client* c, char reg) { | 138 | static 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), ® }, | 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 = ® | ||
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 | } |
258 | EXPORT_SYMBOL_GPL(mmp_unregister_path); | 256 | EXPORT_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 */ | ||
1475 | struct 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 | }; | ||
1511 | struct 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 | |||
1890 | enum { | 1413 | enum { |
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 | ||
42 | config 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 | |||
53 | config FB_OMAP_DMA_TUNE | 42 | config 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 @@ | |||
1 | obj-$(CONFIG_OMAP2_VRFB) += vrfb.o | 1 | obj-$(CONFIG_OMAP2_VRFB) += vrfb.o |
2 | 2 | ||
3 | obj-$(CONFIG_OMAP2_DSS) += dss/ | 3 | obj-$(CONFIG_OMAP2_DSS) += dss/ |
4 | obj-$(CONFIG_FB_OMAP2) += omapfb/ | ||
5 | obj-y += displays/ | 4 | obj-y += displays/ |
5 | obj-$(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 | ||
499 | static struct panel_acx565akm_data *get_panel_data(struct omap_dss_device *dssdev) | ||
500 | { | ||
501 | return (struct panel_acx565akm_data *) dssdev->data; | ||
502 | } | ||
503 | |||
499 | static int acx_panel_probe(struct omap_dss_device *dssdev) | 504 | static 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) | |||
591 | static int acx_panel_power_on(struct omap_dss_device *dssdev) | 604 | static 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); |
648 | fail: | 659 | |
649 | omapdss_sdi_display_disable(dssdev); | ||
650 | fail_unlock: | 660 | fail_unlock: |
651 | mutex_unlock(&md->mutex); | 661 | mutex_unlock(&md->mutex); |
652 | return r; | 662 | return r; |
@@ -655,6 +665,7 @@ fail_unlock: | |||
655 | static void acx_panel_power_off(struct omap_dss_device *dssdev) | 665 | static 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 | ||
40 | struct panel_config { | 41 | struct 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 | ||
534 | static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev) | 535 | static 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; |
562 | err1: | 562 | |
563 | omapdss_dpi_display_disable(dssdev); | ||
564 | err0: | 563 | err0: |
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 | ||
625 | static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev) | 636 | static 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 | ||
26 | struct lb035q02_data { | 28 | struct 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 | ||
53 | static 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 | |||
51 | static int lb035q02_panel_power_on(struct omap_dss_device *dssdev) | 59 | static 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; |
72 | err1: | 80 | |
73 | omapdss_dpi_display_disable(dssdev); | ||
74 | err0: | 81 | err0: |
75 | return r; | 82 | return r; |
76 | } | 83 | } |
77 | 84 | ||
78 | static void lb035q02_panel_power_off(struct omap_dss_device *dssdev) | 85 | static 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 | ||
89 | static int lb035q02_panel_probe(struct omap_dss_device *dssdev) | 101 | static 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; |
104 | err: | ||
105 | return r; | ||
106 | } | 129 | } |
107 | 130 | ||
108 | static void lb035q02_panel_remove(struct omap_dss_device *dssdev) | 131 | static 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 | ||
115 | static int lb035q02_panel_enable(struct omap_dss_device *dssdev) | 135 | static 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: | |||
375 | err_inv_chip: | 367 | err_inv_chip: |
376 | omapdss_rfbi_display_disable(dssdev); | 368 | omapdss_rfbi_display_disable(dssdev); |
377 | err_rfbi_en: | 369 | err_rfbi_en: |
378 | if (bdata->platform_disable) | ||
379 | bdata->platform_disable(dssdev); | ||
380 | err_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 | ||
427 | static 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 | |||
455 | static 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 | |||
464 | static const struct backlight_ops n8x0_bl_ops = { | ||
465 | .get_brightness = n8x0_bl_get_intensity, | ||
466 | .update_status = n8x0_bl_update_status, | ||
467 | }; | ||
468 | |||
469 | static int n8x0_panel_probe(struct omap_dss_device *dssdev) | 413 | static 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 | ||
516 | static void n8x0_panel_remove(struct omap_dss_device *dssdev) | 453 | static 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 | ||
35 | struct nec_8048_data { | ||
36 | struct backlight_device *bl; | ||
37 | }; | ||
38 | |||
39 | static const struct { | 36 | static 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 | ||
87 | static int nec_8048_bl_update_status(struct backlight_device *bl) | 84 | static 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 | |||
104 | static 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 | ||
113 | static 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 | |||
118 | static int nec_8048_panel_probe(struct omap_dss_device *dssdev) | 90 | static 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 | ||
157 | static void nec_8048_panel_remove(struct omap_dss_device *dssdev) | 117 | static 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 | ||
169 | static int nec_8048_panel_power_on(struct omap_dss_device *dssdev) | 121 | static 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; |
196 | err1: | 140 | |
197 | omapdss_dpi_display_disable(dssdev); | ||
198 | err0: | 141 | err0: |
199 | return r; | 142 | return r; |
200 | } | 143 | } |
201 | 144 | ||
202 | static void nec_8048_panel_power_off(struct omap_dss_device *dssdev) | 145 | static 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 | ||
306 | static int nec_8048_spi_suspend(struct spi_device *spi, pm_message_t mesg) | 245 | #ifdef CONFIG_PM_SLEEP |
246 | |||
247 | static 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 | ||
314 | static int nec_8048_spi_resume(struct spi_device *spi) | 257 | static 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 | ||
269 | static 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 | |||
324 | static struct spi_driver nec_8048_spi_driver = { | 276 | static 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) | |||
398 | err: | 392 | err: |
399 | omapdss_dpi_display_disable(dssdev); | 393 | omapdss_dpi_display_disable(dssdev); |
400 | err1: | 394 | err1: |
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 | ||
420 | static int picodlp_panel_probe(struct omap_dss_device *dssdev) | 408 | static 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 | |
457 | err: | 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 | ||
462 | static void picodlp_panel_remove(struct omap_dss_device *dssdev) | 465 | static 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> | |
30 | struct sharp_data { | ||
31 | struct backlight_device *bl; | ||
32 | }; | ||
33 | 30 | ||
34 | static struct omap_video_timings sharp_ls_timings = { | 31 | static 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 | ||
55 | static int sharp_ls_bl_update_status(struct backlight_device *bl) | 52 | static 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 | ||
72 | static 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 | |||
81 | static 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 | |||
88 | static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) | 58 | static 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 | ||
126 | static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev) | 106 | static 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 | ||
138 | static int sharp_ls_power_on(struct omap_dss_device *dssdev) | 110 | static 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; |
162 | err1: | ||
163 | omapdss_dpi_display_disable(dssdev); | ||
164 | err0: | 135 | err0: |
165 | return r; | 136 | return r; |
166 | } | 137 | } |
167 | 138 | ||
168 | static void sharp_ls_power_off(struct omap_dss_device *dssdev) | 139 | static 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 | ||
55 | static int taal_panel_reset(struct omap_dss_device *dssdev); | 55 | static 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 | */ | ||
67 | struct 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 | |||
87 | enum { | ||
88 | PANEL_TAAL, | ||
89 | }; | ||
90 | |||
91 | static 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 | |||
112 | struct taal_data { | 57 | struct 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 | ||
265 | static 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 | |||
308 | static int taal_set_update_window(struct taal_data *td, | 203 | static 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 = { | |||
515 | static void taal_get_resolution(struct omap_dss_device *dssdev, | 410 | static 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 | ||
529 | static ssize_t taal_num_errors_show(struct device *dev, | 417 | static 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 | ||
861 | static void taal_probe_pdata(struct taal_data *td, | 746 | static 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 | ||
1422 | static 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); | ||
1460 | end: | ||
1461 | mutex_unlock(&td->lock); | ||
1462 | return 0; | ||
1463 | err: | ||
1464 | dsi_bus_unlock(dssdev); | ||
1465 | mutex_unlock(&td->lock); | ||
1466 | return r; | ||
1467 | } | ||
1468 | |||
1469 | static 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 | |||
1481 | static 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); | ||
1507 | end: | ||
1508 | mutex_unlock(&td->lock); | ||
1509 | return 0; | ||
1510 | err: | ||
1511 | dsi_bus_unlock(dssdev); | ||
1512 | mutex_unlock(&td->lock); | ||
1513 | return r; | ||
1514 | } | ||
1515 | |||
1516 | static 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 | |||
1528 | static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | 1292 | static 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 | ||
29 | static const struct omap_video_timings tfp410_default_timings = { | 29 | static 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 | ||
282 | static 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 | |||
281 | static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) | 288 | static 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 | ||
312 | static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043) | 318 | static 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) | |||
407 | static int tpo_td043_probe(struct omap_dss_device *dssdev) | 402 | static 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: | |||
457 | static void tpo_td043_remove(struct omap_dss_device *dssdev) | 458 | static 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 | ||
470 | static void tpo_td043_set_timings(struct omap_dss_device *dssdev, | 468 | static 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 | |||
435 | static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) | 435 | static 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 */ |
190 | static inline int dss_initialize_debugfs(void) | 187 | static 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 | ||
1586 | static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, | 1593 | static 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 | ||
1639 | static int color_mode_to_bpp(enum omap_color_mode color_mode) | 1656 | static 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 | ||
2844 | static 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 | |||
2826 | bool dispc_mgr_timings_ok(enum omap_channel channel, | 2853 | bool 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 | ||
2956 | static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div, | 2989 | static 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 | ||
3057 | unsigned long dispc_core_clk_rate(void) | 3090 | unsigned 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 | ||
3070 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) | 3095 | static 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 */ |
3317 | void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck, | 3342 | int 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) { | 3356 | bool 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 | ||
3357 | found: | 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); |
3365 | int 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 | ||
3379 | void dispc_mgr_set_clock_div(enum omap_channel channel, | 3416 | void 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 | ||
3471 | static const struct dispc_features omap24xx_dispc_feats __initconst = { | 3513 | static 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 | ||
3556 | static int __init dispc_init_features(struct platform_device *pdev) | 3608 | static 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 | ||
94 | static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, | 108 | struct 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 | |||
122 | static 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 | |||
149 | static 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 | |||
170 | static 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 | |||
185 | static 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 | |||
196 | static 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 | |||
217 | static 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 | |||
248 | static 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 | ||
124 | static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, | 276 | static 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 | ||
149 | static int dpi_set_mode(struct omap_dss_device *dssdev) | 300 | static 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 | ||
182 | static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) | 332 | static 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 | ||
198 | int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | 346 | int 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 | ||
286 | void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) | 434 | void 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); | |||
324 | int dpi_check_timings(struct omap_dss_device *dssdev, | 472 | int 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 | } |
380 | EXPORT_SYMBOL(omapdss_dpi_set_data_lines); | 521 | EXPORT_SYMBOL(omapdss_dpi_set_data_lines); |
381 | 522 | ||
382 | static int __init dpi_verify_dsi_pll(struct platform_device *dsidev) | 523 | static 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 | ||
404 | static 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 | */ | ||
551 | static 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 | |||
575 | static 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 | ||
444 | static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev) | 610 | static 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 | ||
472 | static void __init dpi_probe_pdata(struct platform_device *dpidev) | 638 | static 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 | ||
513 | static void __init dpi_init_output(struct platform_device *pdev) | 681 | static 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 | ||
531 | static int __init omap_dpi_probe(struct platform_device *pdev) | 701 | static 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 | ||
551 | static struct platform_driver omap_dpi_driver = { | 727 | static 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 | ||
559 | int __init dpi_init_platform_driver(void) | 736 | int __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 | ||
564 | void __exit dpi_uninit_platform_driver(void) | 741 | void __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 | ||
201 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); | 201 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); |
202 | 202 | ||
203 | static int dsi_display_init_dispc(struct platform_device *dsidev, | ||
204 | struct omap_overlay_manager *mgr); | ||
205 | static 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 | ||
258 | struct 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 | |||
253 | struct dsi_data { | 276 | struct 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 | ||
1195 | static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) | 1222 | static 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 | |||
1241 | static 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 | ||
1320 | unsigned 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 | |||
1326 | bool 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 | |||
1350 | bool 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 */ |
1276 | static int dsi_calc_clock_rates(struct platform_device *dsidev, | 1390 | static 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 | ||
1319 | int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, | 1433 | static 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 | |||
1355 | retry: | ||
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 | } | ||
1425 | found: | ||
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 | |||
1456 | static 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 | } | ||
1496 | found: | ||
1497 | if (cinfo) | ||
1498 | *cinfo = best; | ||
1499 | |||
1500 | return 0; | ||
1501 | } | ||
1502 | |||
1503 | static 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 | ||
1514 | static 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 | |||
1538 | retry: | ||
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 | } | ||
1589 | found: | ||
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 | |||
1598 | int dsi_pll_set_clock_div(struct platform_device *dsidev, | 1443 | int 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 | ||
2784 | static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) | 2629 | static 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 | ||
2812 | static int dsi_vc_config_source(struct platform_device *dsidev, int channel, | 2660 | static 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) | |||
3799 | static void dsi_config_vp_sync_events(struct platform_device *dsidev) | 3646 | static 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 | ||
3900 | static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) | 3751 | static 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 | ||
4018 | static int dsi_proto_config(struct omap_dss_device *dssdev) | 3868 | static 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 | } |
4267 | EXPORT_SYMBOL(omapdss_dsi_configure_pins); | 4117 | EXPORT_SYMBOL(omapdss_dsi_configure_pins); |
4268 | 4118 | ||
4269 | int 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; | ||
4329 | err: | ||
4330 | mutex_unlock(&dsi->lock); | ||
4331 | return r; | ||
4332 | } | ||
4333 | EXPORT_SYMBOL(omapdss_dsi_set_clocks); | ||
4334 | |||
4335 | int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) | 4119 | int 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 | |||
4179 | err_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 | } | ||
4184 | err_pix_fmt: | ||
4185 | dsi_display_uninit_dispc(dsidev, mgr); | ||
4186 | err_init_dispc: | ||
4187 | return r; | ||
4390 | } | 4188 | } |
4391 | EXPORT_SYMBOL(dsi_enable_video_output); | 4189 | EXPORT_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 | } |
4412 | EXPORT_SYMBOL(dsi_disable_video_output); | 4212 | EXPORT_SYMBOL(dsi_disable_video_output); |
4413 | 4213 | ||
4414 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev) | 4214 | static 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 | ||
4582 | static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | 4381 | static 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 | ||
4606 | static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | 4404 | static 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); |
4664 | err: | 4458 | err: |
4459 | dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); | ||
4665 | return r; | 4460 | return r; |
4666 | } | 4461 | } |
4667 | 4462 | ||
4668 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) | 4463 | static 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 | ||
4679 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | 4475 | static 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 | ||
4704 | static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | 4498 | static 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); |
4752 | err2: | 4544 | err2: |
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 | |||
4756 | err1: | 4546 | err1: |
4757 | dsi_pll_uninit(dsidev, true); | 4547 | dsi_pll_uninit(dsidev, true); |
4758 | err0: | 4548 | err0: |
4759 | return r; | 4549 | return r; |
4760 | } | 4550 | } |
4761 | 4551 | ||
4762 | static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, | 4552 | static 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 | ||
4830 | err_init_dsi: | 4606 | err_init_dsi: |
4831 | dsi_display_uninit_dispc(dssdev); | ||
4832 | err_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); |
4835 | err_get_dsi: | 4609 | err_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 | } |
4882 | EXPORT_SYMBOL(omapdss_dsi_enable_te); | 4654 | EXPORT_SYMBOL(omapdss_dsi_enable_te); |
4883 | 4655 | ||
4884 | void omapdss_dsi_set_timings(struct omap_dss_device *dssdev, | 4656 | #ifdef PRINT_VERBOSE_VM_TIMINGS |
4885 | struct omap_video_timings *timings) | 4657 | static 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 | |||
4690 | static 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 */ | ||
4718 | static 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 | |||
4742 | static 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 | } |
4896 | EXPORT_SYMBOL(omapdss_dsi_set_timings); | ||
4897 | 4762 | ||
4898 | void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) | 4763 | static 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); | 4775 | static 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 | } |
4910 | EXPORT_SYMBOL(omapdss_dsi_set_size); | ||
4911 | 4788 | ||
4912 | void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev, | 4789 | static 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 | } |
4924 | EXPORT_SYMBOL(omapdss_dsi_set_pixel_format); | ||
4925 | 4827 | ||
4926 | void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev, | 4828 | static 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 | } |
4938 | EXPORT_SYMBOL(omapdss_dsi_set_operation_mode); | ||
4939 | 5024 | ||
4940 | void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev, | 5025 | |
4941 | struct omap_dss_dsi_videomode_timings *timings) | 5026 | static 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 | |||
5049 | static 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 | |||
5072 | static 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 | |||
5086 | static 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 | |||
5129 | int 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; | ||
5172 | err: | ||
5173 | mutex_unlock(&dsi->lock); | ||
5174 | |||
5175 | return r; | ||
4951 | } | 5176 | } |
4952 | EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings); | 5177 | EXPORT_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 | */ | ||
5185 | static 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 | ||
4954 | static 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 | |||
5228 | static 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 | ||
5097 | static void dsi_put_clocks(struct platform_device *dsidev) | 5369 | static 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 | |||
5107 | static 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 | ||
5139 | static void __init dsi_probe_pdata(struct platform_device *dsidev) | 5401 | static 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 | ||
5181 | static void __init dsi_init_output(struct platform_device *dsidev) | 5445 | static 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 | ||
5195 | static void __exit dsi_uninit_output(struct platform_device *dsidev) | 5461 | static 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 */ |
5204 | static int __init omap_dsihw_probe(struct platform_device *dsidev) | 5470 | static 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 | ||
5315 | err_runtime_get: | 5589 | err_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 | ||
5371 | static struct platform_driver omap_dsihw_driver = { | 5642 | static 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 | ||
5380 | int __init dsi_init_platform_driver(void) | 5652 | int __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 | ||
5385 | void __exit dsi_uninit_platform_driver(void) | 5657 | void __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 | ||
476 | bool 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 | |||
476 | int dss_set_clock_div(struct dss_clock_info *cinfo) | 517 | int 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 | ||
545 | int 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 | |||
582 | retry: | ||
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 | |||
632 | found: | ||
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 | |||
660 | void dss_set_venc_output(enum omap_dss_venc_type type) | 589 | void 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) | |||
767 | static int dss_get_clocks(void) | 696 | static 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 | |||
796 | err: | ||
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 | ||
805 | static void dss_put_clocks(void) | 723 | static 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 | ||
812 | static int dss_runtime_get(void) | 729 | static 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); | |||
268 | unsigned long dss_get_dpll4_rate(void); | 268 | unsigned long dss_get_dpll4_rate(void); |
269 | int dss_calc_clock_rates(struct dss_clock_info *cinfo); | 269 | int dss_calc_clock_rates(struct dss_clock_info *cinfo); |
270 | int dss_set_clock_div(struct dss_clock_info *cinfo); | 270 | int dss_set_clock_div(struct dss_clock_info *cinfo); |
271 | int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, | 271 | |
272 | struct dispc_clock_info *dispc_cinfo); | 272 | typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data); |
273 | bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data); | ||
273 | 274 | ||
274 | /* SDI */ | 275 | /* SDI */ |
275 | int sdi_init_platform_driver(void) __init; | 276 | int sdi_init_platform_driver(void) __init; |
276 | void sdi_uninit_platform_driver(void) __exit; | 277 | void sdi_uninit_platform_driver(void) __exit; |
277 | 278 | ||
278 | /* DSI */ | 279 | /* DSI */ |
280 | |||
281 | typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint, | ||
282 | unsigned long pll, void *data); | ||
283 | typedef 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 | ||
281 | struct dentry; | 288 | struct dentry; |
@@ -292,12 +299,17 @@ void dsi_dump_clocks(struct seq_file *s); | |||
292 | void dsi_irq_handler(void); | 299 | void dsi_irq_handler(void); |
293 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); | 300 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); |
294 | 301 | ||
302 | unsigned long dsi_get_pll_clkin(struct platform_device *dsidev); | ||
303 | |||
304 | bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll, | ||
305 | unsigned long out_min, dsi_hsdiv_calc_func func, void *data); | ||
306 | bool 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 | |||
295 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); | 310 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); |
296 | int dsi_pll_set_clock_div(struct platform_device *dsidev, | 311 | int dsi_pll_set_clock_div(struct platform_device *dsidev, |
297 | struct dsi_clock_info *cinfo); | 312 | struct dsi_clock_info *cinfo); |
298 | int 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); | ||
301 | int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, | 313 | int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, |
302 | bool enable_hsdiv); | 314 | bool enable_hsdiv); |
303 | void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); | 315 | void 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 | } |
331 | static 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 | } | ||
339 | static inline int dsi_pll_init(struct platform_device *dsidev, | 343 | static 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 | |||
364 | static inline unsigned long dsi_get_pll_clkin(struct platform_device *dsidev) | ||
365 | { | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | static 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 | |||
376 | static 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); | |||
376 | void dispc_enable_gamma_table(bool enable); | 401 | void dispc_enable_gamma_table(bool enable); |
377 | void dispc_set_loadmode(enum omap_dss_load_mode mode); | 402 | void dispc_set_loadmode(enum omap_dss_load_mode mode); |
378 | 403 | ||
404 | typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck, | ||
405 | unsigned long pck, void *data); | ||
406 | bool dispc_div_calc(unsigned long dispc, | ||
407 | unsigned long pck_min, unsigned long pck_max, | ||
408 | dispc_div_calc_func func, void *data); | ||
409 | |||
379 | bool dispc_mgr_timings_ok(enum omap_channel channel, | 410 | bool dispc_mgr_timings_ok(enum omap_channel channel, |
380 | const struct omap_video_timings *timings); | 411 | const struct omap_video_timings *timings); |
381 | unsigned long dispc_fclk_rate(void); | 412 | unsigned long dispc_fclk_rate(void); |
382 | void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck, | ||
383 | struct dispc_clock_info *cinfo); | ||
384 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | 413 | int 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 | ||
416 | static const struct dss_param_range omap2_dss_param_range[] = { | 416 | static 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 | ||
461 | static const struct dss_param_range omap5_dss_param_range[] = { | 461 | static 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 | ||
331 | static int __init hdmi_init_display(struct omap_dss_device *dssdev) | 331 | static 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 | ||
818 | static 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) |
825 | int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts) | 814 | int 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 | ||
968 | static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev) | 957 | static 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 | ||
996 | static void __init hdmi_probe_pdata(struct platform_device *pdev) | 985 | static 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 | ||
1047 | static void __init hdmi_init_output(struct platform_device *pdev) | 1036 | static 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 */ |
1066 | static int __init omapdss_hdmihw_probe(struct platform_device *pdev) | 1057 | static 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 | |||
1114 | err_panel_init: | ||
1115 | hdmi_put_clocks(); | ||
1116 | return r; | ||
1117 | } | 1110 | } |
1118 | 1111 | ||
1119 | static int __exit hdmi_remove_child(struct device *dev, void *data) | 1112 | static 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 | ||
1170 | static struct platform_driver omapdss_hdmihw_driver = { | 1161 | static 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 | ||
1179 | int __init hdmi_init_platform_driver(void) | 1171 | int __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 | ||
1184 | void __exit hdmi_uninit_platform_driver(void) | 1176 | void __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 | } |
116 | EXPORT_SYMBOL(omap_dss_get_output); | ||
116 | 117 | ||
117 | static const struct dss_mgr_ops *dss_mgr_ops; | 118 | static 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 | } |
944 | EXPORT_SYMBOL(omapdss_rfbi_display_disable); | 944 | EXPORT_SYMBOL(omapdss_rfbi_display_disable); |
945 | 945 | ||
946 | static int __init rfbi_init_display(struct omap_dss_device *dssdev) | 946 | static 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 | ||
952 | static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev) | 952 | static 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 | ||
980 | static void __init rfbi_probe_pdata(struct platform_device *rfbidev) | 980 | static 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 | ||
1021 | static void __init rfbi_init_output(struct platform_device *pdev) | 1023 | static 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 */ |
1040 | static int __init omap_rfbihw_probe(struct platform_device *pdev) | 1044 | static 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 | ||
1135 | static struct platform_driver omap_rfbihw_driver = { | 1144 | static 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 | ||
1144 | int __init rfbi_init_platform_driver(void) | 1154 | int __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 | ||
1149 | void __exit rfbi_uninit_platform_driver(void) | 1159 | void __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 | ||
44 | struct 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 | |||
51 | static 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 | |||
64 | static 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 | |||
75 | static 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 | |||
44 | static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) | 110 | static 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 | } |
183 | EXPORT_SYMBOL(omapdss_sdi_set_datapairs); | 249 | EXPORT_SYMBOL(omapdss_sdi_set_datapairs); |
184 | 250 | ||
185 | static int __init sdi_init_display(struct omap_dss_device *dssdev) | 251 | static 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 | ||
205 | static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev) | 271 | static 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 | ||
233 | static void __init sdi_probe_pdata(struct platform_device *sdidev) | 299 | static 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 | ||
274 | static void __init sdi_init_output(struct platform_device *pdev) | 342 | static 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 | ||
292 | static int __init omap_sdi_probe(struct platform_device *pdev) | 362 | static 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 | ||
310 | static struct platform_driver omap_sdi_driver = { | 386 | static 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 | ||
318 | int __init sdi_init_platform_driver(void) | 395 | int __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 | ||
323 | void __exit sdi_uninit_platform_driver(void) | 400 | void __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; |
535 | err1: | 531 | err1: |
536 | if (dssdev->platform_disable) | ||
537 | dssdev->platform_disable(dssdev); | ||
538 | omap_dss_stop_device(dssdev); | 532 | omap_dss_stop_device(dssdev); |
539 | err0: | 533 | err0: |
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 | ||
645 | static int __init venc_init_display(struct omap_dss_device *dssdev) | 636 | static 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 | ||
738 | static void venc_put_clocks(void) | 729 | static 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 | |||
744 | static 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 | ||
772 | static void __init venc_probe_pdata(struct platform_device *vencdev) | 757 | static 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 | ||
815 | static void __init venc_init_output(struct platform_device *pdev) | 800 | static 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 */ |
834 | static int __init omap_venchw_probe(struct platform_device *pdev) | 821 | static 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 | ||
886 | err_panel_init: | 879 | err_panel_init: |
887 | err_runtime_get: | 880 | err_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 | ||
941 | static struct platform_driver omap_venchw_driver = { | 932 | static 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 | ||
950 | int __init venc_init_platform_driver(void) | 942 | int __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 | ||
955 | void __exit venc_uninit_platform_driver(void) | 947 | void __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: | 1131 | error: |
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 | ||
2425 | static int __init omapfb_probe(struct platform_device *pdev) | 2409 | static 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 | ||
2597 | static struct platform_driver omapfb_driver = { | 2581 | static 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 | ||
2605 | static 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 | |||
2617 | static void __exit omapfb_exit(void) | ||
2618 | { | ||
2619 | DBG("omapfb_exit\n"); | ||
2620 | platform_driver_unregister(&omapfb_driver); | ||
2621 | } | ||
2622 | |||
2623 | module_param_named(mode, def_mode, charp, 0); | 2590 | module_param_named(mode, def_mode, charp, 0); |
2624 | module_param_named(vram, def_vram, charp, 0); | 2591 | module_param_named(vram, def_vram, charp, 0); |
2625 | module_param_named(rotate, def_rotate, int, 0); | 2592 | module_param_named(rotate, def_rotate, int, 0); |
2626 | module_param_named(vrfb, def_vrfb, bool, 0); | 2593 | module_param_named(vrfb, def_vrfb, bool, 0); |
2627 | module_param_named(mirror, def_mirror, bool, 0); | 2594 | module_param_named(mirror, def_mirror, bool, 0); |
2628 | 2595 | ||
2629 | /* late_initcall to let panel/ctrl drivers loaded first. | 2596 | module_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 */ | ||
2632 | late_initcall(omapfb_init); | ||
2633 | /*module_init(omapfb_init);*/ | ||
2634 | module_exit(omapfb_exit); | ||
2635 | 2597 | ||
2636 | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); | 2598 | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); |
2637 | MODULE_DESCRIPTION("OMAP2/3 Framebuffer"); | 2599 | MODULE_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 | ||
400 | static int __init vrfb_init(void) | 400 | module_platform_driver_probe(vrfb_driver, vrfb_probe); |
401 | { | ||
402 | return platform_driver_probe(&vrfb_driver, &vrfb_probe); | ||
403 | } | ||
404 | |||
405 | static void __exit vrfb_exit(void) | ||
406 | { | ||
407 | platform_driver_unregister(&vrfb_driver); | ||
408 | } | ||
409 | |||
410 | module_init(vrfb_init); | ||
411 | module_exit(vrfb_exit); | ||
412 | 401 | ||
413 | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); | 402 | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); |
414 | MODULE_DESCRIPTION("OMAP VRFB"); | 403 | MODULE_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 | ||
706 | static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | 706 | static 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 | ||
371 | static 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 | |||
372 | static ssize_t | 377 | static ssize_t |
373 | pxa3xx_gcu_misc_write(struct file *filp, const char *buff, | 378 | pxa3xx_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 | ||
452 | static long | 456 | static long |
453 | pxa3xx_gcu_misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 457 | pxa3xx_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 | ||
473 | static int | 476 | static int |
474 | pxa3xx_gcu_misc_mmap(struct file *filp, struct vm_area_struct *vma) | 477 | pxa3xx_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 | ||
579 | static 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 | |||
577 | static int pxa3xx_gcu_probe(struct platform_device *dev) | 586 | static 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 | ||
582 | static struct fb_ops sa1100fb_ops = { | 572 | static 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, | |||
705 | static int sgivwfb_mmap(struct fb_info *info, | 705 | static 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 | ||
727 | int __init sgivwfb_setup(char *options) | 721 | int __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 | ||
584 | static int __init sh_mipi_init(void) | 584 | module_platform_driver_probe(sh_mipi_driver, sh_mipi_probe); |
585 | { | ||
586 | return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe); | ||
587 | } | ||
588 | module_init(sh_mipi_init); | ||
589 | |||
590 | static void __exit sh_mipi_exit(void) | ||
591 | { | ||
592 | platform_driver_unregister(&sh_mipi_driver); | ||
593 | } | ||
594 | module_exit(sh_mipi_exit); | ||
595 | 585 | ||
596 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | 586 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); |
597 | MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver"); | 587 | MODULE_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 | ||
1448 | static int __init sh_hdmi_init(void) | 1448 | module_platform_driver_probe(sh_hdmi_driver, sh_hdmi_probe); |
1449 | { | ||
1450 | return platform_driver_probe(&sh_hdmi_driver, sh_hdmi_probe); | ||
1451 | } | ||
1452 | module_init(sh_hdmi_init); | ||
1453 | |||
1454 | static void __exit sh_hdmi_exit(void) | ||
1455 | { | ||
1456 | platform_driver_unregister(&sh_hdmi_driver); | ||
1457 | } | ||
1458 | module_exit(sh_hdmi_exit); | ||
1459 | 1449 | ||
1460 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | 1450 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); |
1461 | MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver"); | 1451 | MODULE_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 | ||
393 | module_i2c_driver(ssd1307fb_driver); | 393 | module_i2c_driver(ssd1307fb_driver); |
394 | 394 | ||
395 | MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controler"); | 395 | MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controller"); |
396 | MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); | 396 | MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); |
397 | MODULE_LICENSE("GPL"); | 397 | MODULE_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, | |||
1003 | static int vmlfb_mmap(struct fb_info *info, struct vm_area_struct *vma) | 1003 | static 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 | ||
1026 | static int vmlfb_sync(struct fb_info *info) | 1020 | static 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 | ||
14 | int videomode_from_timing(const struct display_timings *disp, | 14 | void 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 | } | ||
30 | EXPORT_SYMBOL_GPL(videomode_from_timing); | ||
31 | |||
32 | int 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 | } |
39 | EXPORT_SYMBOL_GPL(videomode_from_timing); | 45 | EXPORT_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 = { | |||
263 | static int wm8505fb_probe(struct platform_device *pdev) | 263 | static 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 | |||
420 | failed_free_cmap: | ||
421 | if (fbi->fb.cmap.len) | ||
422 | fb_dealloc_cmap(&fbi->fb.cmap); | ||
423 | failed_free_io: | ||
424 | iounmap(fbi->regbase); | ||
425 | failed_free_res: | ||
426 | release_mem_region(res->start, resource_size(res)); | ||
427 | failed_fbi: | ||
428 | platform_set_drvdata(pdev, NULL); | ||
429 | kfree(fbi); | ||
430 | failed: | ||
431 | return ret; | ||
432 | } | 385 | } |
433 | 386 | ||
434 | static int wm8505fb_remove(struct platform_device *pdev) | 387 | static 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 | |||
1 | extern void wmt_ge_fillrect(struct fb_info *info, | 3 | extern void wmt_ge_fillrect(struct fb_info *info, |
2 | const struct fb_fillrect *rect); | 4 | const struct fb_fillrect *rect); |
3 | extern void wmt_ge_copyarea(struct fb_info *info, | 5 | extern void wmt_ge_copyarea(struct fb_info *info, |
4 | const struct fb_copyarea *area); | 6 | const struct fb_copyarea *area); |
5 | extern int wmt_ge_sync(struct fb_info *info); | 7 | extern int wmt_ge_sync(struct fb_info *info); |
8 | |||
9 | #else | ||
10 | |||
11 | static inline int wmt_ge_sync(struct fb_info *p) | ||
12 | { | ||
13 | return 0; | ||
14 | } | ||
15 | |||
16 | static inline void wmt_ge_fillrect(struct fb_info *p, | ||
17 | const struct fb_fillrect *rect) | ||
18 | { | ||
19 | sys_fillrect(p, rect); | ||
20 | } | ||
21 | |||
22 | static 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 | ||