aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/arcfb.c8
-rw-r--r--drivers/video/aty/atyfb_base.c4
-rw-r--r--drivers/video/backlight/88pm860x_bl.c2
-rw-r--r--drivers/video/backlight/Kconfig116
-rw-r--r--drivers/video/backlight/Makefile4
-rw-r--r--drivers/video/backlight/adp8860_bl.c838
-rw-r--r--drivers/video/backlight/adx_bl.c4
-rw-r--r--drivers/video/backlight/ep93xx_bl.c160
-rw-r--r--drivers/video/backlight/l4f00242t03.c11
-rw-r--r--drivers/video/backlight/max8925_bl.c1
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c47
-rw-r--r--drivers/video/backlight/pcf50633-backlight.c190
-rw-r--r--drivers/video/backlight/s6e63m0.c920
-rw-r--r--drivers/video/backlight/s6e63m0_gamma.h266
-rw-r--r--drivers/video/bf54x-lq043fb.c7
-rw-r--r--drivers/video/bfin-lq035q1-fb.c252
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c7
-rw-r--r--drivers/video/da8xx-fb.c301
-rw-r--r--drivers/video/fb_defio.c42
-rw-r--r--drivers/video/hgafb.c10
-rw-r--r--drivers/video/hitfb.c8
-rw-r--r--drivers/video/intelfb/intelfb.h4
-rw-r--r--drivers/video/nuc900fb.c2
-rw-r--r--drivers/video/s3c2410fb.c10
-rw-r--r--drivers/video/s3fb.c101
-rw-r--r--drivers/video/sgivwfb.c10
-rw-r--r--drivers/video/sis/sis_main.c2
-rw-r--r--drivers/video/vfb.c4
-rw-r--r--drivers/video/vga16fb.c10
-rw-r--r--drivers/video/via/viafbdev.c11
-rw-r--r--drivers/video/w100fb.c10
31 files changed, 3048 insertions, 314 deletions
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index 8d406fb689c1..f3d7440f0072 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -80,7 +80,7 @@ struct arcfb_par {
80 spinlock_t lock; 80 spinlock_t lock;
81}; 81};
82 82
83static struct fb_fix_screeninfo arcfb_fix __initdata = { 83static struct fb_fix_screeninfo arcfb_fix __devinitdata = {
84 .id = "arcfb", 84 .id = "arcfb",
85 .type = FB_TYPE_PACKED_PIXELS, 85 .type = FB_TYPE_PACKED_PIXELS,
86 .visual = FB_VISUAL_MONO01, 86 .visual = FB_VISUAL_MONO01,
@@ -90,7 +90,7 @@ static struct fb_fix_screeninfo arcfb_fix __initdata = {
90 .accel = FB_ACCEL_NONE, 90 .accel = FB_ACCEL_NONE,
91}; 91};
92 92
93static struct fb_var_screeninfo arcfb_var __initdata = { 93static struct fb_var_screeninfo arcfb_var __devinitdata = {
94 .xres = 128, 94 .xres = 128,
95 .yres = 64, 95 .yres = 64,
96 .xres_virtual = 128, 96 .xres_virtual = 128,
@@ -588,7 +588,7 @@ err:
588 return retval; 588 return retval;
589} 589}
590 590
591static int arcfb_remove(struct platform_device *dev) 591static int __devexit arcfb_remove(struct platform_device *dev)
592{ 592{
593 struct fb_info *info = platform_get_drvdata(dev); 593 struct fb_info *info = platform_get_drvdata(dev);
594 594
@@ -602,7 +602,7 @@ static int arcfb_remove(struct platform_device *dev)
602 602
603static struct platform_driver arcfb_driver = { 603static struct platform_driver arcfb_driver = {
604 .probe = arcfb_probe, 604 .probe = arcfb_probe,
605 .remove = arcfb_remove, 605 .remove = __devexit_p(arcfb_remove),
606 .driver = { 606 .driver = {
607 .name = "arcfb", 607 .name = "arcfb",
608 }, 608 },
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 29d72851f85b..f8d69ad36830 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -1820,10 +1820,6 @@ struct atyclk {
1820#define ATYIO_FEATW 0x41545903 /* ATY\03 */ 1820#define ATYIO_FEATW 0x41545903 /* ATY\03 */
1821#endif 1821#endif
1822 1822
1823#ifndef FBIO_WAITFORVSYNC
1824#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
1825#endif
1826
1827static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) 1823static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
1828{ 1824{
1829 struct atyfb_par *par = (struct atyfb_par *) info->par; 1825 struct atyfb_par *par = (struct atyfb_par *) info->par;
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index 68d2518fadaa..38ffc3fbcbe4 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -222,6 +222,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
222 data->port = __check_device(pdata, name); 222 data->port = __check_device(pdata, name);
223 if (data->port < 0) { 223 if (data->port < 0) {
224 dev_err(&pdev->dev, "wrong platform data is assigned"); 224 dev_err(&pdev->dev, "wrong platform data is assigned");
225 kfree(data);
225 return -EINVAL; 226 return -EINVAL;
226 } 227 }
227 228
@@ -266,6 +267,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
266 backlight_update_status(bl); 267 backlight_update_status(bl);
267 return 0; 268 return 0;
268out: 269out:
270 backlight_device_unregister(bl);
269 kfree(data); 271 kfree(data);
270 return ret; 272 return ret;
271} 273}
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index c025c84601b0..e54a337227ea 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -8,12 +8,13 @@ menuconfig BACKLIGHT_LCD_SUPPORT
8 Enable this to be able to choose the drivers for controlling the 8 Enable this to be able to choose the drivers for controlling the
9 backlight and the LCD panel on some platforms, for example on PDAs. 9 backlight and the LCD panel on some platforms, for example on PDAs.
10 10
11if BACKLIGHT_LCD_SUPPORT
12
11# 13#
12# LCD 14# LCD
13# 15#
14config LCD_CLASS_DEVICE 16config LCD_CLASS_DEVICE
15 tristate "Lowlevel LCD controls" 17 tristate "Lowlevel LCD controls"
16 depends on BACKLIGHT_LCD_SUPPORT
17 default m 18 default m
18 help 19 help
19 This framework adds support for low-level control of LCD. 20 This framework adds support for low-level control of LCD.
@@ -24,31 +25,32 @@ config LCD_CLASS_DEVICE
24 To have support for your specific LCD panel you will have to 25 To have support for your specific LCD panel you will have to
25 select the proper drivers which depend on this option. 26 select the proper drivers which depend on this option.
26 27
28if LCD_CLASS_DEVICE
29
27config LCD_CORGI 30config LCD_CORGI
28 tristate "LCD Panel support for SHARP corgi/spitz model" 31 tristate "LCD Panel support for SHARP corgi/spitz model"
29 depends on LCD_CLASS_DEVICE && SPI_MASTER && PXA_SHARPSL 32 depends on SPI_MASTER && PXA_SHARPSL
30 help 33 help
31 Say y here to support the LCD panels usually found on SHARP 34 Say y here to support the LCD panels usually found on SHARP
32 corgi (C7x0) and spitz (Cxx00) models. 35 corgi (C7x0) and spitz (Cxx00) models.
33 36
34config LCD_L4F00242T03 37config LCD_L4F00242T03
35 tristate "Epson L4F00242T03 LCD" 38 tristate "Epson L4F00242T03 LCD"
36 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO 39 depends on SPI_MASTER && GENERIC_GPIO
37 help 40 help
38 SPI driver for Epson L4F00242T03. This provides basic support 41 SPI driver for Epson L4F00242T03. This provides basic support
39 for init and powering the LCD up/down through a sysfs interface. 42 for init and powering the LCD up/down through a sysfs interface.
40 43
41config LCD_LMS283GF05 44config LCD_LMS283GF05
42 tristate "Samsung LMS283GF05 LCD" 45 tristate "Samsung LMS283GF05 LCD"
43 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO 46 depends on SPI_MASTER && GENERIC_GPIO
44 help 47 help
45 SPI driver for Samsung LMS283GF05. This provides basic support 48 SPI driver for Samsung LMS283GF05. This provides basic support
46 for powering the LCD up/down through a sysfs interface. 49 for powering the LCD up/down through a sysfs interface.
47 50
48config LCD_LTV350QV 51config LCD_LTV350QV
49 tristate "Samsung LTV350QV LCD Panel" 52 tristate "Samsung LTV350QV LCD Panel"
50 depends on LCD_CLASS_DEVICE && SPI_MASTER 53 depends on SPI_MASTER
51 default n
52 help 54 help
53 If you have a Samsung LTV350QV LCD panel, say y to include a 55 If you have a Samsung LTV350QV LCD panel, say y to include a
54 power control driver for it. The panel starts up in power 56 power control driver for it. The panel starts up in power
@@ -59,60 +61,61 @@ config LCD_LTV350QV
59 61
60config LCD_ILI9320 62config LCD_ILI9320
61 tristate 63 tristate
62 depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT
63 default n
64 help 64 help
65 If you have a panel based on the ILI9320 controller chip 65 If you have a panel based on the ILI9320 controller chip
66 then say y to include a power driver for it. 66 then say y to include a power driver for it.
67 67
68config LCD_TDO24M 68config LCD_TDO24M
69 tristate "Toppoly TDO24M and TDO35S LCD Panels support" 69 tristate "Toppoly TDO24M and TDO35S LCD Panels support"
70 depends on LCD_CLASS_DEVICE && SPI_MASTER 70 depends on SPI_MASTER
71 default n
72 help 71 help
73 If you have a Toppoly TDO24M/TDO35S series LCD panel, say y here to 72 If you have a Toppoly TDO24M/TDO35S series LCD panel, say y here to
74 include the support for it. 73 include the support for it.
75 74
76config LCD_VGG2432A4 75config LCD_VGG2432A4
77 tristate "VGG2432A4 LCM device support" 76 tristate "VGG2432A4 LCM device support"
78 depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER 77 depends on SPI_MASTER
79 select LCD_ILI9320 78 select LCD_ILI9320
80 default n
81 help 79 help
82 If you have a VGG2432A4 panel based on the ILI9320 controller chip 80 If you have a VGG2432A4 panel based on the ILI9320 controller chip
83 then say y to include a power driver for it. 81 then say y to include a power driver for it.
84 82
85config LCD_PLATFORM 83config LCD_PLATFORM
86 tristate "Platform LCD controls" 84 tristate "Platform LCD controls"
87 depends on LCD_CLASS_DEVICE
88 help 85 help
89 This driver provides a platform-device registered LCD power 86 This driver provides a platform-device registered LCD power
90 control interface. 87 control interface.
91 88
92config LCD_TOSA 89config LCD_TOSA
93 tristate "Sharp SL-6000 LCD Driver" 90 tristate "Sharp SL-6000 LCD Driver"
94 depends on LCD_CLASS_DEVICE && SPI 91 depends on SPI && MACH_TOSA
95 depends on MACH_TOSA
96 default n
97 help 92 help
98 If you have an Sharp SL-6000 Zaurus say Y to enable a driver 93 If you have an Sharp SL-6000 Zaurus say Y to enable a driver
99 for its LCD. 94 for its LCD.
100 95
101config LCD_HP700 96config LCD_HP700
102 tristate "HP Jornada 700 series LCD Driver" 97 tristate "HP Jornada 700 series LCD Driver"
103 depends on LCD_CLASS_DEVICE
104 depends on SA1100_JORNADA720_SSP && !PREEMPT 98 depends on SA1100_JORNADA720_SSP && !PREEMPT
105 default y 99 default y
106 help 100 help
107 If you have an HP Jornada 700 series handheld (710/720/728) 101 If you have an HP Jornada 700 series handheld (710/720/728)
108 say Y to enable LCD control driver. 102 say Y to enable LCD control driver.
109 103
104config LCD_S6E63M0
105 tristate "S6E63M0 AMOLED LCD Driver"
106 depends on SPI && BACKLIGHT_CLASS_DEVICE
107 default n
108 help
109 If you have an S6E63M0 LCD Panel, say Y to enable its
110 LCD control driver.
111
112endif # LCD_CLASS_DEVICE
113
110# 114#
111# Backlight 115# Backlight
112# 116#
113config BACKLIGHT_CLASS_DEVICE 117config BACKLIGHT_CLASS_DEVICE
114 tristate "Lowlevel Backlight controls" 118 tristate "Lowlevel Backlight controls"
115 depends on BACKLIGHT_LCD_SUPPORT
116 default m 119 default m
117 help 120 help
118 This framework adds support for low-level control of the LCD 121 This framework adds support for low-level control of the LCD
@@ -121,9 +124,11 @@ config BACKLIGHT_CLASS_DEVICE
121 To have support for your specific LCD panel you will have to 124 To have support for your specific LCD panel you will have to
122 select the proper drivers which depend on this option. 125 select the proper drivers which depend on this option.
123 126
127if BACKLIGHT_CLASS_DEVICE
128
124config BACKLIGHT_ATMEL_LCDC 129config BACKLIGHT_ATMEL_LCDC
125 bool "Atmel LCDC Contrast-as-Backlight control" 130 bool "Atmel LCDC Contrast-as-Backlight control"
126 depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL 131 depends on FB_ATMEL
127 default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK 132 default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK
128 help 133 help
129 This provides a backlight control internal to the Atmel LCDC 134 This provides a backlight control internal to the Atmel LCDC
@@ -136,8 +141,7 @@ config BACKLIGHT_ATMEL_LCDC
136 141
137config BACKLIGHT_ATMEL_PWM 142config BACKLIGHT_ATMEL_PWM
138 tristate "Atmel PWM backlight control" 143 tristate "Atmel PWM backlight control"
139 depends on BACKLIGHT_CLASS_DEVICE && ATMEL_PWM 144 depends on ATMEL_PWM
140 default n
141 help 145 help
142 Say Y here if you want to use the PWM peripheral in Atmel AT91 and 146 Say Y here if you want to use the PWM peripheral in Atmel AT91 and
143 AVR32 devices. This driver will need additional platform data to know 147 AVR32 devices. This driver will need additional platform data to know
@@ -146,9 +150,18 @@ config BACKLIGHT_ATMEL_PWM
146 To compile this driver as a module, choose M here: the module will be 150 To compile this driver as a module, choose M here: the module will be
147 called atmel-pwm-bl. 151 called atmel-pwm-bl.
148 152
153config BACKLIGHT_EP93XX
154 tristate "Cirrus EP93xx Backlight Driver"
155 depends on FB_EP93XX
156 help
157 If you have a LCD backlight connected to the BRIGHT output of
158 the EP93xx, say Y here to enable this driver.
159
160 To compile this driver as a module, choose M here: the module will
161 be called ep93xx_bl.
162
149config BACKLIGHT_GENERIC 163config BACKLIGHT_GENERIC
150 tristate "Generic (aka Sharp Corgi) Backlight Driver" 164 tristate "Generic (aka Sharp Corgi) Backlight Driver"
151 depends on BACKLIGHT_CLASS_DEVICE
152 default y 165 default y
153 help 166 help
154 Say y to enable the generic platform backlight driver previously 167 Say y to enable the generic platform backlight driver previously
@@ -157,7 +170,7 @@ config BACKLIGHT_GENERIC
157 170
158config BACKLIGHT_LOCOMO 171config BACKLIGHT_LOCOMO
159 tristate "Sharp LOCOMO LCD/Backlight Driver" 172 tristate "Sharp LOCOMO LCD/Backlight Driver"
160 depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO 173 depends on SHARP_LOCOMO
161 default y 174 default y
162 help 175 help
163 If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to 176 If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to
@@ -165,7 +178,7 @@ config BACKLIGHT_LOCOMO
165 178
166config BACKLIGHT_OMAP1 179config BACKLIGHT_OMAP1
167 tristate "OMAP1 PWL-based LCD Backlight" 180 tristate "OMAP1 PWL-based LCD Backlight"
168 depends on BACKLIGHT_CLASS_DEVICE && ARCH_OMAP1 181 depends on ARCH_OMAP1
169 default y 182 default y
170 help 183 help
171 This driver controls the LCD backlight level and power for 184 This driver controls the LCD backlight level and power for
@@ -174,7 +187,7 @@ config BACKLIGHT_OMAP1
174 187
175config BACKLIGHT_HP680 188config BACKLIGHT_HP680
176 tristate "HP Jornada 680 Backlight Driver" 189 tristate "HP Jornada 680 Backlight Driver"
177 depends on BACKLIGHT_CLASS_DEVICE && SH_HP6XX 190 depends on SH_HP6XX
178 default y 191 default y
179 help 192 help
180 If you have a HP Jornada 680, say y to enable the 193 If you have a HP Jornada 680, say y to enable the
@@ -182,7 +195,6 @@ config BACKLIGHT_HP680
182 195
183config BACKLIGHT_HP700 196config BACKLIGHT_HP700
184 tristate "HP Jornada 700 series Backlight Driver" 197 tristate "HP Jornada 700 series Backlight Driver"
185 depends on BACKLIGHT_CLASS_DEVICE
186 depends on SA1100_JORNADA720_SSP && !PREEMPT 198 depends on SA1100_JORNADA720_SSP && !PREEMPT
187 default y 199 default y
188 help 200 help
@@ -191,76 +203,70 @@ config BACKLIGHT_HP700
191 203
192config BACKLIGHT_PROGEAR 204config BACKLIGHT_PROGEAR
193 tristate "Frontpath ProGear Backlight Driver" 205 tristate "Frontpath ProGear Backlight Driver"
194 depends on BACKLIGHT_CLASS_DEVICE && PCI && X86 206 depends on PCI && X86
195 default n
196 help 207 help
197 If you have a Frontpath ProGear say Y to enable the 208 If you have a Frontpath ProGear say Y to enable the
198 backlight driver. 209 backlight driver.
199 210
200config BACKLIGHT_CARILLO_RANCH 211config BACKLIGHT_CARILLO_RANCH
201 tristate "Intel Carillo Ranch Backlight Driver" 212 tristate "Intel Carillo Ranch Backlight Driver"
202 depends on BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 213 depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578
203 default n
204 help 214 help
205 If you have a Intel LE80578 (Carillo Ranch) say Y to enable the 215 If you have a Intel LE80578 (Carillo Ranch) say Y to enable the
206 backlight driver. 216 backlight driver.
207 217
208config BACKLIGHT_PWM 218config BACKLIGHT_PWM
209 tristate "Generic PWM based Backlight Driver" 219 tristate "Generic PWM based Backlight Driver"
210 depends on BACKLIGHT_CLASS_DEVICE && HAVE_PWM 220 depends on HAVE_PWM
211 help 221 help
212 If you have a LCD backlight adjustable by PWM, say Y to enable 222 If you have a LCD backlight adjustable by PWM, say Y to enable
213 this driver. 223 this driver.
214 224
215config BACKLIGHT_DA903X 225config BACKLIGHT_DA903X
216 tristate "Backlight Driver for DA9030/DA9034 using WLED" 226 tristate "Backlight Driver for DA9030/DA9034 using WLED"
217 depends on BACKLIGHT_CLASS_DEVICE && PMIC_DA903X 227 depends on PMIC_DA903X
218 help 228 help
219 If you have a LCD backlight connected to the WLED output of DA9030 229 If you have a LCD backlight connected to the WLED output of DA9030
220 or DA9034 WLED output, say Y here to enable this driver. 230 or DA9034 WLED output, say Y here to enable this driver.
221 231
222config BACKLIGHT_MAX8925 232config BACKLIGHT_MAX8925
223 tristate "Backlight driver for MAX8925" 233 tristate "Backlight driver for MAX8925"
224 depends on BACKLIGHT_CLASS_DEVICE && MFD_MAX8925 234 depends on MFD_MAX8925
225 help 235 help
226 If you have a LCD backlight connected to the WLED output of MAX8925 236 If you have a LCD backlight connected to the WLED output of MAX8925
227 WLED output, say Y here to enable this driver. 237 WLED output, say Y here to enable this driver.
228 238
229config BACKLIGHT_MBP_NVIDIA 239config BACKLIGHT_MBP_NVIDIA
230 tristate "MacBook Pro Nvidia Backlight Driver" 240 tristate "MacBook Pro Nvidia Backlight Driver"
231 depends on BACKLIGHT_CLASS_DEVICE && X86 241 depends on X86
232 default n
233 help 242 help
234 If you have an Apple Macbook Pro with Nvidia graphics hardware say Y 243 If you have an Apple Macbook Pro with Nvidia graphics hardware say Y
235 to enable a driver for its backlight 244 to enable a driver for its backlight
236 245
237config BACKLIGHT_TOSA 246config BACKLIGHT_TOSA
238 tristate "Sharp SL-6000 Backlight Driver" 247 tristate "Sharp SL-6000 Backlight Driver"
239 depends on BACKLIGHT_CLASS_DEVICE && I2C 248 depends on I2C && MACH_TOSA && LCD_TOSA
240 depends on MACH_TOSA && LCD_TOSA
241 default n
242 help 249 help
243 If you have an Sharp SL-6000 Zaurus say Y to enable a driver 250 If you have an Sharp SL-6000 Zaurus say Y to enable a driver
244 for its backlight 251 for its backlight
245 252
246config BACKLIGHT_SAHARA 253config BACKLIGHT_SAHARA
247 tristate "Tabletkiosk Sahara Touch-iT Backlight Driver" 254 tristate "Tabletkiosk Sahara Touch-iT Backlight Driver"
248 depends on BACKLIGHT_CLASS_DEVICE && X86 255 depends on X86
249 default n
250 help 256 help
251 If you have a Tabletkiosk Sahara Touch-iT, say y to enable the 257 If you have a Tabletkiosk Sahara Touch-iT, say y to enable the
252 backlight driver. 258 backlight driver.
253 259
254config BACKLIGHT_WM831X 260config BACKLIGHT_WM831X
255 tristate "WM831x PMIC Backlight Driver" 261 tristate "WM831x PMIC Backlight Driver"
256 depends on BACKLIGHT_CLASS_DEVICE && MFD_WM831X 262 depends on MFD_WM831X
257 help 263 help
258 If you have a backlight driven by the ISINK and DCDC of a 264 If you have a backlight driven by the ISINK and DCDC of a
259 WM831x PMIC say y to enable the backlight driver for it. 265 WM831x PMIC say y to enable the backlight driver for it.
260 266
261config BACKLIGHT_ADX 267config BACKLIGHT_ADX
262 tristate "Avionic Design Xanthos Backlight Driver" 268 tristate "Avionic Design Xanthos Backlight Driver"
263 depends on BACKLIGHT_CLASS_DEVICE && ARCH_PXA_ADX 269 depends on ARCH_PXA_ADX
264 default y 270 default y
265 help 271 help
266 Say Y to enable the backlight driver on Avionic Design Xanthos-based 272 Say Y to enable the backlight driver on Avionic Design Xanthos-based
@@ -268,7 +274,7 @@ config BACKLIGHT_ADX
268 274
269config BACKLIGHT_ADP5520 275config BACKLIGHT_ADP5520
270 tristate "Backlight Driver for ADP5520/ADP5501 using WLED" 276 tristate "Backlight Driver for ADP5520/ADP5501 using WLED"
271 depends on BACKLIGHT_CLASS_DEVICE && PMIC_ADP5520 277 depends on PMIC_ADP5520
272 help 278 help
273 If you have a LCD backlight connected to the BST/BL_SNK output of 279 If you have a LCD backlight connected to the BST/BL_SNK output of
274 ADP5520 or ADP5501, say Y here to enable this driver. 280 ADP5520 or ADP5501, say Y here to enable this driver.
@@ -276,9 +282,31 @@ config BACKLIGHT_ADP5520
276 To compile this driver as a module, choose M here: the module will 282 To compile this driver as a module, choose M here: the module will
277 be called adp5520_bl. 283 be called adp5520_bl.
278 284
285config BACKLIGHT_ADP8860
286 tristate "Backlight Driver for ADP8860/ADP8861/ADP8863 using WLED"
287 depends on BACKLIGHT_CLASS_DEVICE && I2C
288 select NEW_LEDS
289 select LEDS_CLASS
290 help
291 If you have a LCD backlight connected to the ADP8860, ADP8861 or
292 ADP8863 say Y here to enable this driver.
293
294 To compile this driver as a module, choose M here: the module will
295 be called adp8860_bl.
296
279config BACKLIGHT_88PM860X 297config BACKLIGHT_88PM860X
280 tristate "Backlight Driver for 88PM8606 using WLED" 298 tristate "Backlight Driver for 88PM8606 using WLED"
281 depends on BACKLIGHT_CLASS_DEVICE && MFD_88PM860X 299 depends on MFD_88PM860X
282 help 300 help
283 Say Y to enable the backlight driver for Marvell 88PM8606. 301 Say Y to enable the backlight driver for Marvell 88PM8606.
284 302
303config BACKLIGHT_PCF50633
304 tristate "Backlight driver for NXP PCF50633 MFD"
305 depends on BACKLIGHT_CLASS_DEVICE && MFD_PCF50633
306 help
307 If you have a backlight driven by a NXP PCF50633 MFD, say Y here to
308 enable its driver.
309
310endif # BACKLIGHT_CLASS_DEVICE
311
312endif # BACKLIGHT_LCD_SUPPORT
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 09d1f14d6257..44c0f81ad85d 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -11,9 +11,11 @@ obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
11obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o 11obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
12obj-$(CONFIG_LCD_TDO24M) += tdo24m.o 12obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
13obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o 13obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
14obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o
14 15
15obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o 16obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
16obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o 17obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
18obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o
17obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o 19obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o
18obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o 20obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o
19obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o 21obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
@@ -30,5 +32,7 @@ obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
30obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o 32obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
31obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o 33obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o
32obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o 34obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o
35obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o
33obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o 36obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
37obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o
34 38
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
new file mode 100644
index 000000000000..921ca37398f3
--- /dev/null
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -0,0 +1,838 @@
1/*
2 * Backlight driver for Analog Devices ADP8860 Backlight Devices
3 *
4 * Copyright 2009-2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/module.h>
10#include <linux/version.h>
11#include <linux/init.h>
12#include <linux/errno.h>
13#include <linux/pm.h>
14#include <linux/platform_device.h>
15#include <linux/i2c.h>
16#include <linux/fb.h>
17#include <linux/backlight.h>
18#include <linux/leds.h>
19#include <linux/slab.h>
20#include <linux/workqueue.h>
21
22#include <linux/i2c/adp8860.h>
23#define ADP8860_EXT_FEATURES
24#define ADP8860_USE_LEDS
25
26#define ADP8860_MFDVID 0x00 /* Manufacturer and device ID */
27#define ADP8860_MDCR 0x01 /* Device mode and status */
28#define ADP8860_MDCR2 0x02 /* Device mode and Status Register 2 */
29#define ADP8860_INTR_EN 0x03 /* Interrupts enable */
30#define ADP8860_CFGR 0x04 /* Configuration register */
31#define ADP8860_BLSEN 0x05 /* Sink enable backlight or independent */
32#define ADP8860_BLOFF 0x06 /* Backlight off timeout */
33#define ADP8860_BLDIM 0x07 /* Backlight dim timeout */
34#define ADP8860_BLFR 0x08 /* Backlight fade in and out rates */
35#define ADP8860_BLMX1 0x09 /* Backlight (Brightness Level 1-daylight) maximum current */
36#define ADP8860_BLDM1 0x0A /* Backlight (Brightness Level 1-daylight) dim current */
37#define ADP8860_BLMX2 0x0B /* Backlight (Brightness Level 2-office) maximum current */
38#define ADP8860_BLDM2 0x0C /* Backlight (Brightness Level 2-office) dim current */
39#define ADP8860_BLMX3 0x0D /* Backlight (Brightness Level 3-dark) maximum current */
40#define ADP8860_BLDM3 0x0E /* Backlight (Brightness Level 3-dark) dim current */
41#define ADP8860_ISCFR 0x0F /* Independent sink current fade control register */
42#define ADP8860_ISCC 0x10 /* Independent sink current control register */
43#define ADP8860_ISCT1 0x11 /* Independent Sink Current Timer Register LED[7:5] */
44#define ADP8860_ISCT2 0x12 /* Independent Sink Current Timer Register LED[4:1] */
45#define ADP8860_ISCF 0x13 /* Independent sink current fade register */
46#define ADP8860_ISC7 0x14 /* Independent Sink Current LED7 */
47#define ADP8860_ISC6 0x15 /* Independent Sink Current LED6 */
48#define ADP8860_ISC5 0x16 /* Independent Sink Current LED5 */
49#define ADP8860_ISC4 0x17 /* Independent Sink Current LED4 */
50#define ADP8860_ISC3 0x18 /* Independent Sink Current LED3 */
51#define ADP8860_ISC2 0x19 /* Independent Sink Current LED2 */
52#define ADP8860_ISC1 0x1A /* Independent Sink Current LED1 */
53#define ADP8860_CCFG 0x1B /* Comparator configuration */
54#define ADP8860_CCFG2 0x1C /* Second comparator configuration */
55#define ADP8860_L2_TRP 0x1D /* L2 comparator reference */
56#define ADP8860_L2_HYS 0x1E /* L2 hysteresis */
57#define ADP8860_L3_TRP 0x1F /* L3 comparator reference */
58#define ADP8860_L3_HYS 0x20 /* L3 hysteresis */
59#define ADP8860_PH1LEVL 0x21 /* First phototransistor ambient light level-low byte register */
60#define ADP8860_PH1LEVH 0x22 /* First phototransistor ambient light level-high byte register */
61#define ADP8860_PH2LEVL 0x23 /* Second phototransistor ambient light level-low byte register */
62#define ADP8860_PH2LEVH 0x24 /* Second phototransistor ambient light level-high byte register */
63
64#define ADP8860_MANUFID 0x0 /* Analog Devices ADP8860 Manufacturer ID */
65#define ADP8861_MANUFID 0x4 /* Analog Devices ADP8861 Manufacturer ID */
66#define ADP8863_MANUFID 0x2 /* Analog Devices ADP8863 Manufacturer ID */
67
68#define ADP8860_DEVID(x) ((x) & 0xF)
69#define ADP8860_MANID(x) ((x) >> 4)
70
71/* MDCR Device mode and status */
72#define INT_CFG (1 << 6)
73#define NSTBY (1 << 5)
74#define DIM_EN (1 << 4)
75#define GDWN_DIS (1 << 3)
76#define SIS_EN (1 << 2)
77#define CMP_AUTOEN (1 << 1)
78#define BLEN (1 << 0)
79
80/* ADP8860_CCFG Main ALS comparator level enable */
81#define L3_EN (1 << 1)
82#define L2_EN (1 << 0)
83
84#define CFGR_BLV_SHIFT 3
85#define CFGR_BLV_MASK 0x3
86#define ADP8860_FLAG_LED_MASK 0xFF
87
88#define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4))
89#define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1))
90#define ALS_CCFG_VAL(filt) ((0x7 & filt) << 5)
91
92enum {
93 adp8860,
94 adp8861,
95 adp8863
96};
97
98struct adp8860_led {
99 struct led_classdev cdev;
100 struct work_struct work;
101 struct i2c_client *client;
102 enum led_brightness new_brightness;
103 int id;
104 int flags;
105};
106
107struct adp8860_bl {
108 struct i2c_client *client;
109 struct backlight_device *bl;
110 struct adp8860_led *led;
111 struct adp8860_backlight_platform_data *pdata;
112 struct mutex lock;
113 unsigned long cached_daylight_max;
114 int id;
115 int revid;
116 int current_brightness;
117 unsigned en_ambl_sens:1;
118 unsigned gdwn_dis:1;
119};
120
121static int adp8860_read(struct i2c_client *client, int reg, uint8_t *val)
122{
123 int ret;
124
125 ret = i2c_smbus_read_byte_data(client, reg);
126 if (ret < 0) {
127 dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
128 return ret;
129 }
130
131 *val = (uint8_t)ret;
132 return 0;
133}
134
135static int adp8860_write(struct i2c_client *client, u8 reg, u8 val)
136{
137 return i2c_smbus_write_byte_data(client, reg, val);
138}
139
140static int adp8860_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask)
141{
142 struct adp8860_bl *data = i2c_get_clientdata(client);
143 uint8_t reg_val;
144 int ret;
145
146 mutex_lock(&data->lock);
147
148 ret = adp8860_read(client, reg, &reg_val);
149
150 if (!ret && ((reg_val & bit_mask) == 0)) {
151 reg_val |= bit_mask;
152 ret = adp8860_write(client, reg, reg_val);
153 }
154
155 mutex_unlock(&data->lock);
156 return ret;
157}
158
159static int adp8860_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask)
160{
161 struct adp8860_bl *data = i2c_get_clientdata(client);
162 uint8_t reg_val;
163 int ret;
164
165 mutex_lock(&data->lock);
166
167 ret = adp8860_read(client, reg, &reg_val);
168
169 if (!ret && (reg_val & bit_mask)) {
170 reg_val &= ~bit_mask;
171 ret = adp8860_write(client, reg, reg_val);
172 }
173
174 mutex_unlock(&data->lock);
175 return ret;
176}
177
178/*
179 * Independent sink / LED
180 */
181#if defined(ADP8860_USE_LEDS)
182static void adp8860_led_work(struct work_struct *work)
183{
184 struct adp8860_led *led = container_of(work, struct adp8860_led, work);
185 adp8860_write(led->client, ADP8860_ISC1 - led->id + 1,
186 led->new_brightness >> 1);
187}
188
189static void adp8860_led_set(struct led_classdev *led_cdev,
190 enum led_brightness value)
191{
192 struct adp8860_led *led;
193
194 led = container_of(led_cdev, struct adp8860_led, cdev);
195 led->new_brightness = value;
196 schedule_work(&led->work);
197}
198
199static int adp8860_led_setup(struct adp8860_led *led)
200{
201 struct i2c_client *client = led->client;
202 int ret = 0;
203
204 ret = adp8860_write(client, ADP8860_ISC1 - led->id + 1, 0);
205 ret |= adp8860_set_bits(client, ADP8860_ISCC, 1 << (led->id - 1));
206
207 if (led->id > 4)
208 ret |= adp8860_set_bits(client, ADP8860_ISCT1,
209 (led->flags & 0x3) << ((led->id - 5) * 2));
210 else
211 ret |= adp8860_set_bits(client, ADP8860_ISCT2,
212 (led->flags & 0x3) << ((led->id - 1) * 2));
213
214 return ret;
215}
216
217static int __devinit adp8860_led_probe(struct i2c_client *client)
218{
219 struct adp8860_backlight_platform_data *pdata =
220 client->dev.platform_data;
221 struct adp8860_bl *data = i2c_get_clientdata(client);
222 struct adp8860_led *led, *led_dat;
223 struct led_info *cur_led;
224 int ret, i;
225
226 led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
227 if (led == NULL) {
228 dev_err(&client->dev, "failed to alloc memory\n");
229 return -ENOMEM;
230 }
231
232 ret = adp8860_write(client, ADP8860_ISCFR, pdata->led_fade_law);
233 ret = adp8860_write(client, ADP8860_ISCT1,
234 (pdata->led_on_time & 0x3) << 6);
235 ret |= adp8860_write(client, ADP8860_ISCF,
236 FADE_VAL(pdata->led_fade_in, pdata->led_fade_out));
237
238 if (ret) {
239 dev_err(&client->dev, "failed to write\n");
240 goto err_free;
241 }
242
243 for (i = 0; i < pdata->num_leds; ++i) {
244 cur_led = &pdata->leds[i];
245 led_dat = &led[i];
246
247 led_dat->id = cur_led->flags & ADP8860_FLAG_LED_MASK;
248
249 if (led_dat->id > 7 || led_dat->id < 1) {
250 dev_err(&client->dev, "Invalid LED ID %d\n",
251 led_dat->id);
252 goto err;
253 }
254
255 if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) {
256 dev_err(&client->dev, "LED %d used by Backlight\n",
257 led_dat->id);
258 goto err;
259 }
260
261 led_dat->cdev.name = cur_led->name;
262 led_dat->cdev.default_trigger = cur_led->default_trigger;
263 led_dat->cdev.brightness_set = adp8860_led_set;
264 led_dat->cdev.brightness = LED_OFF;
265 led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT;
266 led_dat->client = client;
267 led_dat->new_brightness = LED_OFF;
268 INIT_WORK(&led_dat->work, adp8860_led_work);
269
270 ret = led_classdev_register(&client->dev, &led_dat->cdev);
271 if (ret) {
272 dev_err(&client->dev, "failed to register LED %d\n",
273 led_dat->id);
274 goto err;
275 }
276
277 ret = adp8860_led_setup(led_dat);
278 if (ret) {
279 dev_err(&client->dev, "failed to write\n");
280 i++;
281 goto err;
282 }
283 }
284
285 data->led = led;
286
287 return 0;
288
289 err:
290 for (i = i - 1; i >= 0; --i) {
291 led_classdev_unregister(&led[i].cdev);
292 cancel_work_sync(&led[i].work);
293 }
294
295 err_free:
296 kfree(led);
297
298 return ret;
299}
300
301static int __devexit adp8860_led_remove(struct i2c_client *client)
302{
303 struct adp8860_backlight_platform_data *pdata =
304 client->dev.platform_data;
305 struct adp8860_bl *data = i2c_get_clientdata(client);
306 int i;
307
308 for (i = 0; i < pdata->num_leds; i++) {
309 led_classdev_unregister(&data->led[i].cdev);
310 cancel_work_sync(&data->led[i].work);
311 }
312
313 kfree(data->led);
314 return 0;
315}
316#else
317static int __devinit adp8860_led_probe(struct i2c_client *client)
318{
319 return 0;
320}
321
322static int __devexit adp8860_led_remove(struct i2c_client *client)
323{
324 return 0;
325}
326#endif
327
328static int adp8860_bl_set(struct backlight_device *bl, int brightness)
329{
330 struct adp8860_bl *data = bl_get_data(bl);
331 struct i2c_client *client = data->client;
332 int ret = 0;
333
334 if (data->en_ambl_sens) {
335 if ((brightness > 0) && (brightness < ADP8860_MAX_BRIGHTNESS)) {
336 /* Disable Ambient Light auto adjust */
337 ret |= adp8860_clr_bits(client, ADP8860_MDCR,
338 CMP_AUTOEN);
339 ret |= adp8860_write(client, ADP8860_BLMX1, brightness);
340 } else {
341 /*
342 * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust
343 * restore daylight l1 sysfs brightness
344 */
345 ret |= adp8860_write(client, ADP8860_BLMX1,
346 data->cached_daylight_max);
347 ret |= adp8860_set_bits(client, ADP8860_MDCR,
348 CMP_AUTOEN);
349 }
350 } else
351 ret |= adp8860_write(client, ADP8860_BLMX1, brightness);
352
353 if (data->current_brightness && brightness == 0)
354 ret |= adp8860_set_bits(client,
355 ADP8860_MDCR, DIM_EN);
356 else if (data->current_brightness == 0 && brightness)
357 ret |= adp8860_clr_bits(client,
358 ADP8860_MDCR, DIM_EN);
359
360 if (!ret)
361 data->current_brightness = brightness;
362
363 return ret;
364}
365
366static int adp8860_bl_update_status(struct backlight_device *bl)
367{
368 int brightness = bl->props.brightness;
369 if (bl->props.power != FB_BLANK_UNBLANK)
370 brightness = 0;
371
372 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
373 brightness = 0;
374
375 return adp8860_bl_set(bl, brightness);
376}
377
378static int adp8860_bl_get_brightness(struct backlight_device *bl)
379{
380 struct adp8860_bl *data = bl_get_data(bl);
381
382 return data->current_brightness;
383}
384
385static const struct backlight_ops adp8860_bl_ops = {
386 .update_status = adp8860_bl_update_status,
387 .get_brightness = adp8860_bl_get_brightness,
388};
389
390static int adp8860_bl_setup(struct backlight_device *bl)
391{
392 struct adp8860_bl *data = bl_get_data(bl);
393 struct i2c_client *client = data->client;
394 struct adp8860_backlight_platform_data *pdata = data->pdata;
395 int ret = 0;
396
397 ret |= adp8860_write(client, ADP8860_BLSEN, ~pdata->bl_led_assign);
398 ret |= adp8860_write(client, ADP8860_BLMX1, pdata->l1_daylight_max);
399 ret |= adp8860_write(client, ADP8860_BLDM1, pdata->l1_daylight_dim);
400
401 if (data->en_ambl_sens) {
402 data->cached_daylight_max = pdata->l1_daylight_max;
403 ret |= adp8860_write(client, ADP8860_BLMX2,
404 pdata->l2_office_max);
405 ret |= adp8860_write(client, ADP8860_BLDM2,
406 pdata->l2_office_dim);
407 ret |= adp8860_write(client, ADP8860_BLMX3,
408 pdata->l3_dark_max);
409 ret |= adp8860_write(client, ADP8860_BLDM3,
410 pdata->l3_dark_dim);
411
412 ret |= adp8860_write(client, ADP8860_L2_TRP, pdata->l2_trip);
413 ret |= adp8860_write(client, ADP8860_L2_HYS, pdata->l2_hyst);
414 ret |= adp8860_write(client, ADP8860_L3_TRP, pdata->l3_trip);
415 ret |= adp8860_write(client, ADP8860_L3_HYS, pdata->l3_hyst);
416 ret |= adp8860_write(client, ADP8860_CCFG, L2_EN | L3_EN |
417 ALS_CCFG_VAL(pdata->abml_filt));
418 }
419
420 ret |= adp8860_write(client, ADP8860_CFGR,
421 BL_CFGR_VAL(pdata->bl_fade_law, 0));
422
423 ret |= adp8860_write(client, ADP8860_BLFR, FADE_VAL(pdata->bl_fade_in,
424 pdata->bl_fade_out));
425
426 ret |= adp8860_set_bits(client, ADP8860_MDCR, BLEN | DIM_EN | NSTBY |
427 (data->gdwn_dis ? GDWN_DIS : 0));
428
429 return ret;
430}
431
432static ssize_t adp8860_show(struct device *dev, char *buf, int reg)
433{
434 struct adp8860_bl *data = dev_get_drvdata(dev);
435 int error;
436 uint8_t reg_val;
437
438 mutex_lock(&data->lock);
439 error = adp8860_read(data->client, reg, &reg_val);
440 mutex_unlock(&data->lock);
441
442 if (error < 0)
443 return error;
444
445 return sprintf(buf, "%u\n", reg_val);
446}
447
448static ssize_t adp8860_store(struct device *dev, const char *buf,
449 size_t count, int reg)
450{
451 struct adp8860_bl *data = dev_get_drvdata(dev);
452 unsigned long val;
453 int ret;
454
455 ret = strict_strtoul(buf, 10, &val);
456 if (ret)
457 return ret;
458
459 mutex_lock(&data->lock);
460 adp8860_write(data->client, reg, val);
461 mutex_unlock(&data->lock);
462
463 return count;
464}
465
466static ssize_t adp8860_bl_l3_dark_max_show(struct device *dev,
467 struct device_attribute *attr, char *buf)
468{
469 return adp8860_show(dev, buf, ADP8860_BLMX3);
470}
471
472static ssize_t adp8860_bl_l3_dark_max_store(struct device *dev,
473 struct device_attribute *attr, const char *buf, size_t count)
474{
475 return adp8860_store(dev, buf, count, ADP8860_BLMX3);
476}
477
478static DEVICE_ATTR(l3_dark_max, 0664, adp8860_bl_l3_dark_max_show,
479 adp8860_bl_l3_dark_max_store);
480
481static ssize_t adp8860_bl_l2_office_max_show(struct device *dev,
482 struct device_attribute *attr, char *buf)
483{
484 return adp8860_show(dev, buf, ADP8860_BLMX2);
485}
486
487static ssize_t adp8860_bl_l2_office_max_store(struct device *dev,
488 struct device_attribute *attr, const char *buf, size_t count)
489{
490 return adp8860_store(dev, buf, count, ADP8860_BLMX2);
491}
492static DEVICE_ATTR(l2_office_max, 0664, adp8860_bl_l2_office_max_show,
493 adp8860_bl_l2_office_max_store);
494
495static ssize_t adp8860_bl_l1_daylight_max_show(struct device *dev,
496 struct device_attribute *attr, char *buf)
497{
498 return adp8860_show(dev, buf, ADP8860_BLMX1);
499}
500
501static ssize_t adp8860_bl_l1_daylight_max_store(struct device *dev,
502 struct device_attribute *attr, const char *buf, size_t count)
503{
504 struct adp8860_bl *data = dev_get_drvdata(dev);
505
506 strict_strtoul(buf, 10, &data->cached_daylight_max);
507 return adp8860_store(dev, buf, count, ADP8860_BLMX1);
508}
509static DEVICE_ATTR(l1_daylight_max, 0664, adp8860_bl_l1_daylight_max_show,
510 adp8860_bl_l1_daylight_max_store);
511
512static ssize_t adp8860_bl_l3_dark_dim_show(struct device *dev,
513 struct device_attribute *attr, char *buf)
514{
515 return adp8860_show(dev, buf, ADP8860_BLDM3);
516}
517
518static ssize_t adp8860_bl_l3_dark_dim_store(struct device *dev,
519 struct device_attribute *attr,
520 const char *buf, size_t count)
521{
522 return adp8860_store(dev, buf, count, ADP8860_BLDM3);
523}
524static DEVICE_ATTR(l3_dark_dim, 0664, adp8860_bl_l3_dark_dim_show,
525 adp8860_bl_l3_dark_dim_store);
526
527static ssize_t adp8860_bl_l2_office_dim_show(struct device *dev,
528 struct device_attribute *attr, char *buf)
529{
530 return adp8860_show(dev, buf, ADP8860_BLDM2);
531}
532
533static ssize_t adp8860_bl_l2_office_dim_store(struct device *dev,
534 struct device_attribute *attr,
535 const char *buf, size_t count)
536{
537 return adp8860_store(dev, buf, count, ADP8860_BLDM2);
538}
539static DEVICE_ATTR(l2_office_dim, 0664, adp8860_bl_l2_office_dim_show,
540 adp8860_bl_l2_office_dim_store);
541
542static ssize_t adp8860_bl_l1_daylight_dim_show(struct device *dev,
543 struct device_attribute *attr, char *buf)
544{
545 return adp8860_show(dev, buf, ADP8860_BLDM1);
546}
547
548static ssize_t adp8860_bl_l1_daylight_dim_store(struct device *dev,
549 struct device_attribute *attr,
550 const char *buf, size_t count)
551{
552 return adp8860_store(dev, buf, count, ADP8860_BLDM1);
553}
554static DEVICE_ATTR(l1_daylight_dim, 0664, adp8860_bl_l1_daylight_dim_show,
555 adp8860_bl_l1_daylight_dim_store);
556
557#ifdef ADP8860_EXT_FEATURES
558static ssize_t adp8860_bl_ambient_light_level_show(struct device *dev,
559 struct device_attribute *attr, char *buf)
560{
561 struct adp8860_bl *data = dev_get_drvdata(dev);
562 int error;
563 uint8_t reg_val;
564 uint16_t ret_val;
565
566 mutex_lock(&data->lock);
567 error = adp8860_read(data->client, ADP8860_PH1LEVL, &reg_val);
568 ret_val = reg_val;
569 error |= adp8860_read(data->client, ADP8860_PH1LEVH, &reg_val);
570 mutex_unlock(&data->lock);
571
572 if (error < 0)
573 return error;
574
575 /* Return 13-bit conversion value for the first light sensor */
576 ret_val += (reg_val & 0x1F) << 8;
577
578 return sprintf(buf, "%u\n", ret_val);
579}
580static DEVICE_ATTR(ambient_light_level, 0444,
581 adp8860_bl_ambient_light_level_show, NULL);
582
583static ssize_t adp8860_bl_ambient_light_zone_show(struct device *dev,
584 struct device_attribute *attr, char *buf)
585{
586 struct adp8860_bl *data = dev_get_drvdata(dev);
587 int error;
588 uint8_t reg_val;
589
590 mutex_lock(&data->lock);
591 error = adp8860_read(data->client, ADP8860_CFGR, &reg_val);
592 mutex_unlock(&data->lock);
593
594 if (error < 0)
595 return error;
596
597 return sprintf(buf, "%u\n",
598 ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1);
599}
600
601static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev,
602 struct device_attribute *attr,
603 const char *buf, size_t count)
604{
605 struct adp8860_bl *data = dev_get_drvdata(dev);
606 unsigned long val;
607 uint8_t reg_val;
608 int ret;
609
610 ret = strict_strtoul(buf, 10, &val);
611 if (ret)
612 return ret;
613
614 if (val == 0) {
615 /* Enable automatic ambient light sensing */
616 adp8860_set_bits(data->client, ADP8860_MDCR, CMP_AUTOEN);
617 } else if ((val > 0) && (val < 6)) {
618 /* Disable automatic ambient light sensing */
619 adp8860_clr_bits(data->client, ADP8860_MDCR, CMP_AUTOEN);
620
621 /* Set user supplied ambient light zone */
622 mutex_lock(&data->lock);
623 adp8860_read(data->client, ADP8860_CFGR, &reg_val);
624 reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT);
625 reg_val |= val << CFGR_BLV_SHIFT;
626 adp8860_write(data->client, ADP8860_CFGR, reg_val);
627 mutex_unlock(&data->lock);
628 }
629
630 return count;
631}
632static DEVICE_ATTR(ambient_light_zone, 0664,
633 adp8860_bl_ambient_light_zone_show,
634 adp8860_bl_ambient_light_zone_store);
635#endif
636
637static struct attribute *adp8860_bl_attributes[] = {
638 &dev_attr_l3_dark_max.attr,
639 &dev_attr_l3_dark_dim.attr,
640 &dev_attr_l2_office_max.attr,
641 &dev_attr_l2_office_dim.attr,
642 &dev_attr_l1_daylight_max.attr,
643 &dev_attr_l1_daylight_dim.attr,
644#ifdef ADP8860_EXT_FEATURES
645 &dev_attr_ambient_light_level.attr,
646 &dev_attr_ambient_light_zone.attr,
647#endif
648 NULL
649};
650
651static const struct attribute_group adp8860_bl_attr_group = {
652 .attrs = adp8860_bl_attributes,
653};
654
655static int __devinit adp8860_probe(struct i2c_client *client,
656 const struct i2c_device_id *id)
657{
658 struct backlight_device *bl;
659 struct adp8860_bl *data;
660 struct adp8860_backlight_platform_data *pdata =
661 client->dev.platform_data;
662 struct backlight_properties props;
663 uint8_t reg_val;
664 int ret;
665
666 if (!i2c_check_functionality(client->adapter,
667 I2C_FUNC_SMBUS_BYTE_DATA)) {
668 dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
669 return -EIO;
670 }
671
672 if (!pdata) {
673 dev_err(&client->dev, "no platform data?\n");
674 return -EINVAL;
675 }
676
677 data = kzalloc(sizeof(*data), GFP_KERNEL);
678 if (data == NULL)
679 return -ENOMEM;
680
681 ret = adp8860_read(client, ADP8860_MFDVID, &reg_val);
682 if (ret < 0)
683 goto out2;
684
685 switch (ADP8860_MANID(reg_val)) {
686 case ADP8863_MANUFID:
687 data->gdwn_dis = !!pdata->gdwn_dis;
688 case ADP8860_MANUFID:
689 data->en_ambl_sens = !!pdata->en_ambl_sens;
690 break;
691 case ADP8861_MANUFID:
692 data->gdwn_dis = !!pdata->gdwn_dis;
693 break;
694 default:
695 dev_err(&client->dev, "failed to probe\n");
696 ret = -ENODEV;
697 goto out2;
698 }
699
700 /* It's confirmed that the DEVID field is actually a REVID */
701
702 data->revid = ADP8860_DEVID(reg_val);
703 data->client = client;
704 data->pdata = pdata;
705 data->id = id->driver_data;
706 data->current_brightness = 0;
707 i2c_set_clientdata(client, data);
708
709 memset(&props, 0, sizeof(props));
710 props.max_brightness = ADP8860_MAX_BRIGHTNESS;
711
712 mutex_init(&data->lock);
713
714 bl = backlight_device_register(dev_driver_string(&client->dev),
715 &client->dev, data, &adp8860_bl_ops, &props);
716 if (IS_ERR(bl)) {
717 dev_err(&client->dev, "failed to register backlight\n");
718 ret = PTR_ERR(bl);
719 goto out2;
720 }
721
722 bl->props.max_brightness =
723 bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
724
725 data->bl = bl;
726
727 if (data->en_ambl_sens)
728 ret = sysfs_create_group(&bl->dev.kobj,
729 &adp8860_bl_attr_group);
730
731 if (ret) {
732 dev_err(&client->dev, "failed to register sysfs\n");
733 goto out1;
734 }
735
736 ret = adp8860_bl_setup(bl);
737 if (ret) {
738 ret = -EIO;
739 goto out;
740 }
741
742 backlight_update_status(bl);
743
744 dev_info(&client->dev, "%s Rev.%d Backlight\n",
745 client->name, data->revid);
746
747 if (pdata->num_leds)
748 adp8860_led_probe(client);
749
750 return 0;
751
752out:
753 if (data->en_ambl_sens)
754 sysfs_remove_group(&data->bl->dev.kobj,
755 &adp8860_bl_attr_group);
756out1:
757 backlight_device_unregister(bl);
758out2:
759 i2c_set_clientdata(client, NULL);
760 kfree(data);
761
762 return ret;
763}
764
765static int __devexit adp8860_remove(struct i2c_client *client)
766{
767 struct adp8860_bl *data = i2c_get_clientdata(client);
768
769 adp8860_clr_bits(client, ADP8860_MDCR, NSTBY);
770
771 if (data->led)
772 adp8860_led_remove(client);
773
774 if (data->en_ambl_sens)
775 sysfs_remove_group(&data->bl->dev.kobj,
776 &adp8860_bl_attr_group);
777
778 backlight_device_unregister(data->bl);
779 i2c_set_clientdata(client, NULL);
780 kfree(data);
781
782 return 0;
783}
784
785#ifdef CONFIG_PM
786static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message)
787{
788 adp8860_clr_bits(client, ADP8860_MDCR, NSTBY);
789
790 return 0;
791}
792
793static int adp8860_i2c_resume(struct i2c_client *client)
794{
795 adp8860_set_bits(client, ADP8860_MDCR, NSTBY);
796
797 return 0;
798}
799#else
800#define adp8860_i2c_suspend NULL
801#define adp8860_i2c_resume NULL
802#endif
803
804static const struct i2c_device_id adp8860_id[] = {
805 { "adp8860", adp8860 },
806 { "adp8861", adp8861 },
807 { "adp8863", adp8863 },
808 { }
809};
810MODULE_DEVICE_TABLE(i2c, adp8860_id);
811
812static struct i2c_driver adp8860_driver = {
813 .driver = {
814 .name = KBUILD_MODNAME,
815 },
816 .probe = adp8860_probe,
817 .remove = __devexit_p(adp8860_remove),
818 .suspend = adp8860_i2c_suspend,
819 .resume = adp8860_i2c_resume,
820 .id_table = adp8860_id,
821};
822
823static int __init adp8860_init(void)
824{
825 return i2c_add_driver(&adp8860_driver);
826}
827module_init(adp8860_init);
828
829static void __exit adp8860_exit(void)
830{
831 i2c_del_driver(&adp8860_driver);
832}
833module_exit(adp8860_exit);
834
835MODULE_LICENSE("GPL v2");
836MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
837MODULE_DESCRIPTION("ADP8860 Backlight driver");
838MODULE_ALIAS("i2c:adp8860-backlight");
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
index 7f4a7c30a98b..fe9af129c5dd 100644
--- a/drivers/video/backlight/adx_bl.c
+++ b/drivers/video/backlight/adx_bl.c
@@ -107,8 +107,8 @@ static int __devinit adx_backlight_probe(struct platform_device *pdev)
107 props.max_brightness = 0xff; 107 props.max_brightness = 0xff;
108 bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, 108 bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
109 bl, &adx_backlight_ops, &props); 109 bl, &adx_backlight_ops, &props);
110 if (!bldev) { 110 if (IS_ERR(bldev)) {
111 ret = -ENOMEM; 111 ret = PTR_ERR(bldev);
112 goto out; 112 goto out;
113 } 113 }
114 114
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
new file mode 100644
index 000000000000..b0cc49184803
--- /dev/null
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -0,0 +1,160 @@
1/*
2 * Driver for the Cirrus EP93xx lcd backlight
3 *
4 * Copyright (c) 2010 H Hartley Sweeten <hsweeten@visionengravers.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This driver controls the pulse width modulated brightness control output,
11 * BRIGHT, on the Cirrus EP9307, EP9312, and EP9315 processors.
12 */
13
14
15#include <linux/platform_device.h>
16#include <linux/io.h>
17#include <linux/fb.h>
18#include <linux/backlight.h>
19
20#include <mach/hardware.h>
21
22#define EP93XX_RASTER_REG(x) (EP93XX_RASTER_BASE + (x))
23#define EP93XX_RASTER_BRIGHTNESS EP93XX_RASTER_REG(0x20)
24
25#define EP93XX_MAX_COUNT 255
26#define EP93XX_MAX_BRIGHT 255
27#define EP93XX_DEF_BRIGHT 128
28
29struct ep93xxbl {
30 void __iomem *mmio;
31 int brightness;
32};
33
34static int ep93xxbl_set(struct backlight_device *bl, int brightness)
35{
36 struct ep93xxbl *ep93xxbl = bl_get_data(bl);
37
38 __raw_writel((brightness << 8) | EP93XX_MAX_COUNT, ep93xxbl->mmio);
39
40 ep93xxbl->brightness = brightness;
41
42 return 0;
43}
44
45static int ep93xxbl_update_status(struct backlight_device *bl)
46{
47 int brightness = bl->props.brightness;
48
49 if (bl->props.power != FB_BLANK_UNBLANK ||
50 bl->props.fb_blank != FB_BLANK_UNBLANK)
51 brightness = 0;
52
53 return ep93xxbl_set(bl, brightness);
54}
55
56static int ep93xxbl_get_brightness(struct backlight_device *bl)
57{
58 struct ep93xxbl *ep93xxbl = bl_get_data(bl);
59
60 return ep93xxbl->brightness;
61}
62
63static const struct backlight_ops ep93xxbl_ops = {
64 .update_status = ep93xxbl_update_status,
65 .get_brightness = ep93xxbl_get_brightness,
66};
67
68static int __init ep93xxbl_probe(struct platform_device *dev)
69{
70 struct ep93xxbl *ep93xxbl;
71 struct backlight_device *bl;
72 struct backlight_properties props;
73
74 ep93xxbl = devm_kzalloc(&dev->dev, sizeof(*ep93xxbl), GFP_KERNEL);
75 if (!ep93xxbl)
76 return -ENOMEM;
77
78 /*
79 * This register is located in the range already ioremap'ed by
80 * the framebuffer driver. A MFD driver seems a bit of overkill
81 * to handle this so use the static I/O mapping; this address
82 * is already virtual.
83 *
84 * NOTE: No locking is required; the framebuffer does not touch
85 * this register.
86 */
87 ep93xxbl->mmio = EP93XX_RASTER_BRIGHTNESS;
88
89 memset(&props, 0, sizeof(struct backlight_properties));
90 props.max_brightness = EP93XX_MAX_BRIGHT;
91 bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl,
92 &ep93xxbl_ops, &props);
93 if (IS_ERR(bl))
94 return PTR_ERR(bl);
95
96 bl->props.brightness = EP93XX_DEF_BRIGHT;
97
98 platform_set_drvdata(dev, bl);
99
100 ep93xxbl_update_status(bl);
101
102 return 0;
103}
104
105static int ep93xxbl_remove(struct platform_device *dev)
106{
107 struct backlight_device *bl = platform_get_drvdata(dev);
108
109 backlight_device_unregister(bl);
110 platform_set_drvdata(dev, NULL);
111 return 0;
112}
113
114#ifdef CONFIG_PM
115static int ep93xxbl_suspend(struct platform_device *dev, pm_message_t state)
116{
117 struct backlight_device *bl = platform_get_drvdata(dev);
118
119 return ep93xxbl_set(bl, 0);
120}
121
122static int ep93xxbl_resume(struct platform_device *dev)
123{
124 struct backlight_device *bl = platform_get_drvdata(dev);
125
126 backlight_update_status(bl);
127 return 0;
128}
129#else
130#define ep93xxbl_suspend NULL
131#define ep93xxbl_resume NULL
132#endif
133
134static struct platform_driver ep93xxbl_driver = {
135 .driver = {
136 .name = "ep93xx-bl",
137 .owner = THIS_MODULE,
138 },
139 .probe = ep93xxbl_probe,
140 .remove = __devexit_p(ep93xxbl_remove),
141 .suspend = ep93xxbl_suspend,
142 .resume = ep93xxbl_resume,
143};
144
145static int __init ep93xxbl_init(void)
146{
147 return platform_driver_register(&ep93xxbl_driver);
148}
149module_init(ep93xxbl_init);
150
151static void __exit ep93xxbl_exit(void)
152{
153 platform_driver_unregister(&ep93xxbl_driver);
154}
155module_exit(ep93xxbl_exit);
156
157MODULE_DESCRIPTION("EP93xx Backlight Driver");
158MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
159MODULE_LICENSE("GPL");
160MODULE_ALIAS("platform:ep93xx-bl");
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index bcdb12c93efd..9093ef0fa869 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -125,8 +125,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
125 125
126 if (priv == NULL) { 126 if (priv == NULL) {
127 dev_err(&spi->dev, "No memory for this device.\n"); 127 dev_err(&spi->dev, "No memory for this device.\n");
128 ret = -ENOMEM; 128 return -ENOMEM;
129 goto err;
130 } 129 }
131 130
132 dev_set_drvdata(&spi->dev, priv); 131 dev_set_drvdata(&spi->dev, priv);
@@ -139,7 +138,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
139 if (ret) { 138 if (ret) {
140 dev_err(&spi->dev, 139 dev_err(&spi->dev,
141 "Unable to get the lcd l4f00242t03 reset gpio.\n"); 140 "Unable to get the lcd l4f00242t03 reset gpio.\n");
142 return ret; 141 goto err;
143 } 142 }
144 143
145 ret = gpio_direction_output(pdata->reset_gpio, 1); 144 ret = gpio_direction_output(pdata->reset_gpio, 1);
@@ -151,7 +150,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
151 if (ret) { 150 if (ret) {
152 dev_err(&spi->dev, 151 dev_err(&spi->dev,
153 "Unable to get the lcd l4f00242t03 data en gpio.\n"); 152 "Unable to get the lcd l4f00242t03 data en gpio.\n");
154 return ret; 153 goto err2;
155 } 154 }
156 155
157 ret = gpio_direction_output(pdata->data_enable_gpio, 0); 156 ret = gpio_direction_output(pdata->data_enable_gpio, 0);
@@ -222,9 +221,9 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi)
222 gpio_free(pdata->reset_gpio); 221 gpio_free(pdata->reset_gpio);
223 222
224 if (priv->io_reg) 223 if (priv->io_reg)
225 regulator_put(priv->core_reg);
226 if (priv->core_reg)
227 regulator_put(priv->io_reg); 224 regulator_put(priv->io_reg);
225 if (priv->core_reg)
226 regulator_put(priv->core_reg);
228 227
229 kfree(priv); 228 kfree(priv);
230 229
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
index b5accc957ad3..b2b2c7ba1f63 100644
--- a/drivers/video/backlight/max8925_bl.c
+++ b/drivers/video/backlight/max8925_bl.c
@@ -162,6 +162,7 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
162 backlight_update_status(bl); 162 backlight_update_status(bl);
163 return 0; 163 return 0;
164out: 164out:
165 backlight_device_unregister(bl);
165 kfree(data); 166 kfree(data);
166 return ret; 167 return ret;
167} 168}
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
index 1b5d3fe6bbbc..9fb533f6373e 100644
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -141,7 +141,7 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
141 .callback = mbp_dmi_match, 141 .callback = mbp_dmi_match,
142 .ident = "MacBook 1,1", 142 .ident = "MacBook 1,1",
143 .matches = { 143 .matches = {
144 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 144 DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
145 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), 145 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
146 }, 146 },
147 .driver_data = (void *)&intel_chipset_data, 147 .driver_data = (void *)&intel_chipset_data,
@@ -184,6 +184,42 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
184 }, 184 },
185 { 185 {
186 .callback = mbp_dmi_match, 186 .callback = mbp_dmi_match,
187 .ident = "MacBookPro 1,1",
188 .matches = {
189 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
190 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"),
191 },
192 .driver_data = (void *)&intel_chipset_data,
193 },
194 {
195 .callback = mbp_dmi_match,
196 .ident = "MacBookPro 1,2",
197 .matches = {
198 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
199 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,2"),
200 },
201 .driver_data = (void *)&intel_chipset_data,
202 },
203 {
204 .callback = mbp_dmi_match,
205 .ident = "MacBookPro 2,1",
206 .matches = {
207 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
208 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,1"),
209 },
210 .driver_data = (void *)&intel_chipset_data,
211 },
212 {
213 .callback = mbp_dmi_match,
214 .ident = "MacBookPro 2,2",
215 .matches = {
216 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
217 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"),
218 },
219 .driver_data = (void *)&intel_chipset_data,
220 },
221 {
222 .callback = mbp_dmi_match,
187 .ident = "MacBookPro 3,1", 223 .ident = "MacBookPro 3,1",
188 .matches = { 224 .matches = {
189 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 225 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
@@ -238,6 +274,15 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
238 }, 274 },
239 { 275 {
240 .callback = mbp_dmi_match, 276 .callback = mbp_dmi_match,
277 .ident = "MacBook 6,1",
278 .matches = {
279 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
280 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook6,1"),
281 },
282 .driver_data = (void *)&nvidia_chipset_data,
283 },
284 {
285 .callback = mbp_dmi_match,
241 .ident = "MacBookAir 2,1", 286 .ident = "MacBookAir 2,1",
242 .matches = { 287 .matches = {
243 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 288 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
new file mode 100644
index 000000000000..3c424f7efdcc
--- /dev/null
+++ b/drivers/video/backlight/pcf50633-backlight.c
@@ -0,0 +1,190 @@
1/*
2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
3 * PCF50633 backlight device driver
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/slab.h>
19#include <linux/platform_device.h>
20
21#include <linux/backlight.h>
22#include <linux/fb.h>
23
24#include <linux/mfd/pcf50633/core.h>
25#include <linux/mfd/pcf50633/backlight.h>
26
27struct pcf50633_bl {
28 struct pcf50633 *pcf;
29 struct backlight_device *bl;
30
31 unsigned int brightness;
32 unsigned int brightness_limit;
33};
34
35/*
36 * pcf50633_bl_set_brightness_limit
37 *
38 * Update the brightness limit for the pc50633 backlight. The actual brightness
39 * will not go above the limit. This is useful to limit power drain for example
40 * on low battery.
41 *
42 * @dev: Pointer to a pcf50633 device
43 * @limit: The brightness limit. Valid values are 0-63
44 */
45int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit)
46{
47 struct pcf50633_bl *pcf_bl = platform_get_drvdata(pcf->bl_pdev);
48
49 if (!pcf_bl)
50 return -ENODEV;
51
52 pcf_bl->brightness_limit = limit & 0x3f;
53 backlight_update_status(pcf_bl->bl);
54
55 return 0;
56}
57
58static int pcf50633_bl_update_status(struct backlight_device *bl)
59{
60 struct pcf50633_bl *pcf_bl = bl_get_data(bl);
61 unsigned int new_brightness;
62
63
64 if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK) ||
65 bl->props.power != FB_BLANK_UNBLANK)
66 new_brightness = 0;
67 else if (bl->props.brightness < pcf_bl->brightness_limit)
68 new_brightness = bl->props.brightness;
69 else
70 new_brightness = pcf_bl->brightness_limit;
71
72
73 if (pcf_bl->brightness == new_brightness)
74 return 0;
75
76 if (new_brightness) {
77 pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDOUT,
78 new_brightness);
79 if (!pcf_bl->brightness)
80 pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 1);
81 } else {
82 pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 0);
83 }
84
85 pcf_bl->brightness = new_brightness;
86
87 return 0;
88}
89
90static int pcf50633_bl_get_brightness(struct backlight_device *bl)
91{
92 struct pcf50633_bl *pcf_bl = bl_get_data(bl);
93 return pcf_bl->brightness;
94}
95
96static const struct backlight_ops pcf50633_bl_ops = {
97 .get_brightness = pcf50633_bl_get_brightness,
98 .update_status = pcf50633_bl_update_status,
99 .options = BL_CORE_SUSPENDRESUME,
100};
101
102static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
103{
104 int ret;
105 struct pcf50633_bl *pcf_bl;
106 struct device *parent = pdev->dev.parent;
107 struct pcf50633_platform_data *pcf50633_data = parent->platform_data;
108 struct pcf50633_bl_platform_data *pdata = pcf50633_data->backlight_data;
109 struct backlight_properties bl_props;
110
111 pcf_bl = kzalloc(sizeof(*pcf_bl), GFP_KERNEL);
112 if (!pcf_bl)
113 return -ENOMEM;
114
115 bl_props.max_brightness = 0x3f;
116 bl_props.power = FB_BLANK_UNBLANK;
117
118 if (pdata) {
119 bl_props.brightness = pdata->default_brightness;
120 pcf_bl->brightness_limit = pdata->default_brightness_limit;
121 } else {
122 bl_props.brightness = 0x3f;
123 pcf_bl->brightness_limit = 0x3f;
124 }
125
126 pcf_bl->pcf = dev_to_pcf50633(pdev->dev.parent);
127
128 pcf_bl->bl = backlight_device_register(pdev->name, &pdev->dev, pcf_bl,
129 &pcf50633_bl_ops, &bl_props);
130
131 if (IS_ERR(pcf_bl->bl)) {
132 ret = PTR_ERR(pcf_bl->bl);
133 goto err_free;
134 }
135
136 platform_set_drvdata(pdev, pcf_bl);
137
138 pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time);
139
140 /* Should be different from bl_props.brightness, so we do not exit
141 * update_status early the first time it's called */
142 pcf_bl->brightness = pcf_bl->bl->props.brightness + 1;
143
144 backlight_update_status(pcf_bl->bl);
145
146 return 0;
147
148err_free:
149 kfree(pcf_bl);
150
151 return ret;
152}
153
154static int __devexit pcf50633_bl_remove(struct platform_device *pdev)
155{
156 struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev);
157
158 backlight_device_unregister(pcf_bl->bl);
159
160 platform_set_drvdata(pdev, NULL);
161
162 kfree(pcf_bl);
163
164 return 0;
165}
166
167static struct platform_driver pcf50633_bl_driver = {
168 .probe = pcf50633_bl_probe,
169 .remove = __devexit_p(pcf50633_bl_remove),
170 .driver = {
171 .name = "pcf50633-backlight",
172 },
173};
174
175static int __init pcf50633_bl_init(void)
176{
177 return platform_driver_register(&pcf50633_bl_driver);
178}
179module_init(pcf50633_bl_init);
180
181static void __exit pcf50633_bl_exit(void)
182{
183 platform_driver_unregister(&pcf50633_bl_driver);
184}
185module_exit(pcf50633_bl_exit);
186
187MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
188MODULE_DESCRIPTION("PCF50633 backlight driver");
189MODULE_LICENSE("GPL");
190MODULE_ALIAS("platform:pcf50633-backlight");
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
new file mode 100644
index 000000000000..a3128c9cb7ad
--- /dev/null
+++ b/drivers/video/backlight/s6e63m0.c
@@ -0,0 +1,920 @@
1/*
2 * S6E63M0 AMOLED LCD panel driver.
3 *
4 * Author: InKi Dae <inki.dae@samsung.com>
5 *
6 * Derived from drivers/video/omap/lcd-apollon.c
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include <linux/wait.h>
24#include <linux/fb.h>
25#include <linux/delay.h>
26#include <linux/gpio.h>
27#include <linux/spi/spi.h>
28#include <linux/irq.h>
29#include <linux/interrupt.h>
30#include <linux/kernel.h>
31#include <linux/lcd.h>
32#include <linux/backlight.h>
33
34#include "s6e63m0_gamma.h"
35
36#define SLEEPMSEC 0x1000
37#define ENDDEF 0x2000
38#define DEFMASK 0xFF00
39#define COMMAND_ONLY 0xFE
40#define DATA_ONLY 0xFF
41
42#define MIN_BRIGHTNESS 0
43#define MAX_BRIGHTNESS 10
44
45#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
46
47struct s6e63m0 {
48 struct device *dev;
49 struct spi_device *spi;
50 unsigned int power;
51 unsigned int current_brightness;
52 unsigned int gamma_mode;
53 unsigned int gamma_table_count;
54 struct lcd_device *ld;
55 struct backlight_device *bd;
56 struct lcd_platform_data *lcd_pd;
57};
58
59static const unsigned short SEQ_PANEL_CONDITION_SET[] = {
60 0xF8, 0x01,
61 DATA_ONLY, 0x27,
62 DATA_ONLY, 0x27,
63 DATA_ONLY, 0x07,
64 DATA_ONLY, 0x07,
65 DATA_ONLY, 0x54,
66 DATA_ONLY, 0x9f,
67 DATA_ONLY, 0x63,
68 DATA_ONLY, 0x86,
69 DATA_ONLY, 0x1a,
70 DATA_ONLY, 0x33,
71 DATA_ONLY, 0x0d,
72 DATA_ONLY, 0x00,
73 DATA_ONLY, 0x00,
74
75 ENDDEF, 0x0000
76};
77
78static const unsigned short SEQ_DISPLAY_CONDITION_SET[] = {
79 0xf2, 0x02,
80 DATA_ONLY, 0x03,
81 DATA_ONLY, 0x1c,
82 DATA_ONLY, 0x10,
83 DATA_ONLY, 0x10,
84
85 0xf7, 0x03,
86 DATA_ONLY, 0x00,
87 DATA_ONLY, 0x00,
88
89 ENDDEF, 0x0000
90};
91
92static const unsigned short SEQ_GAMMA_SETTING[] = {
93 0xfa, 0x00,
94 DATA_ONLY, 0x18,
95 DATA_ONLY, 0x08,
96 DATA_ONLY, 0x24,
97 DATA_ONLY, 0x64,
98 DATA_ONLY, 0x56,
99 DATA_ONLY, 0x33,
100 DATA_ONLY, 0xb6,
101 DATA_ONLY, 0xba,
102 DATA_ONLY, 0xa8,
103 DATA_ONLY, 0xac,
104 DATA_ONLY, 0xb1,
105 DATA_ONLY, 0x9d,
106 DATA_ONLY, 0xc1,
107 DATA_ONLY, 0xc1,
108 DATA_ONLY, 0xb7,
109 DATA_ONLY, 0x00,
110 DATA_ONLY, 0x9c,
111 DATA_ONLY, 0x00,
112 DATA_ONLY, 0x9f,
113 DATA_ONLY, 0x00,
114 DATA_ONLY, 0xd6,
115
116 0xfa, 0x01,
117
118 ENDDEF, 0x0000
119};
120
121static const unsigned short SEQ_ETC_CONDITION_SET[] = {
122 0xf6, 0x00,
123 DATA_ONLY, 0x8c,
124 DATA_ONLY, 0x07,
125
126 0xb3, 0xc,
127
128 0xb5, 0x2c,
129 DATA_ONLY, 0x12,
130 DATA_ONLY, 0x0c,
131 DATA_ONLY, 0x0a,
132 DATA_ONLY, 0x10,
133 DATA_ONLY, 0x0e,
134 DATA_ONLY, 0x17,
135 DATA_ONLY, 0x13,
136 DATA_ONLY, 0x1f,
137 DATA_ONLY, 0x1a,
138 DATA_ONLY, 0x2a,
139 DATA_ONLY, 0x24,
140 DATA_ONLY, 0x1f,
141 DATA_ONLY, 0x1b,
142 DATA_ONLY, 0x1a,
143 DATA_ONLY, 0x17,
144
145 DATA_ONLY, 0x2b,
146 DATA_ONLY, 0x26,
147 DATA_ONLY, 0x22,
148 DATA_ONLY, 0x20,
149 DATA_ONLY, 0x3a,
150 DATA_ONLY, 0x34,
151 DATA_ONLY, 0x30,
152 DATA_ONLY, 0x2c,
153 DATA_ONLY, 0x29,
154 DATA_ONLY, 0x26,
155 DATA_ONLY, 0x25,
156 DATA_ONLY, 0x23,
157 DATA_ONLY, 0x21,
158 DATA_ONLY, 0x20,
159 DATA_ONLY, 0x1e,
160 DATA_ONLY, 0x1e,
161
162 0xb6, 0x00,
163 DATA_ONLY, 0x00,
164 DATA_ONLY, 0x11,
165 DATA_ONLY, 0x22,
166 DATA_ONLY, 0x33,
167 DATA_ONLY, 0x44,
168 DATA_ONLY, 0x44,
169 DATA_ONLY, 0x44,
170
171 DATA_ONLY, 0x55,
172 DATA_ONLY, 0x55,
173 DATA_ONLY, 0x66,
174 DATA_ONLY, 0x66,
175 DATA_ONLY, 0x66,
176 DATA_ONLY, 0x66,
177 DATA_ONLY, 0x66,
178 DATA_ONLY, 0x66,
179
180 0xb7, 0x2c,
181 DATA_ONLY, 0x12,
182 DATA_ONLY, 0x0c,
183 DATA_ONLY, 0x0a,
184 DATA_ONLY, 0x10,
185 DATA_ONLY, 0x0e,
186 DATA_ONLY, 0x17,
187 DATA_ONLY, 0x13,
188 DATA_ONLY, 0x1f,
189 DATA_ONLY, 0x1a,
190 DATA_ONLY, 0x2a,
191 DATA_ONLY, 0x24,
192 DATA_ONLY, 0x1f,
193 DATA_ONLY, 0x1b,
194 DATA_ONLY, 0x1a,
195 DATA_ONLY, 0x17,
196
197 DATA_ONLY, 0x2b,
198 DATA_ONLY, 0x26,
199 DATA_ONLY, 0x22,
200 DATA_ONLY, 0x20,
201 DATA_ONLY, 0x3a,
202 DATA_ONLY, 0x34,
203 DATA_ONLY, 0x30,
204 DATA_ONLY, 0x2c,
205 DATA_ONLY, 0x29,
206 DATA_ONLY, 0x26,
207 DATA_ONLY, 0x25,
208 DATA_ONLY, 0x23,
209 DATA_ONLY, 0x21,
210 DATA_ONLY, 0x20,
211 DATA_ONLY, 0x1e,
212 DATA_ONLY, 0x1e,
213
214 0xb8, 0x00,
215 DATA_ONLY, 0x00,
216 DATA_ONLY, 0x11,
217 DATA_ONLY, 0x22,
218 DATA_ONLY, 0x33,
219 DATA_ONLY, 0x44,
220 DATA_ONLY, 0x44,
221 DATA_ONLY, 0x44,
222
223 DATA_ONLY, 0x55,
224 DATA_ONLY, 0x55,
225 DATA_ONLY, 0x66,
226 DATA_ONLY, 0x66,
227 DATA_ONLY, 0x66,
228 DATA_ONLY, 0x66,
229 DATA_ONLY, 0x66,
230 DATA_ONLY, 0x66,
231
232 0xb9, 0x2c,
233 DATA_ONLY, 0x12,
234 DATA_ONLY, 0x0c,
235 DATA_ONLY, 0x0a,
236 DATA_ONLY, 0x10,
237 DATA_ONLY, 0x0e,
238 DATA_ONLY, 0x17,
239 DATA_ONLY, 0x13,
240 DATA_ONLY, 0x1f,
241 DATA_ONLY, 0x1a,
242 DATA_ONLY, 0x2a,
243 DATA_ONLY, 0x24,
244 DATA_ONLY, 0x1f,
245 DATA_ONLY, 0x1b,
246 DATA_ONLY, 0x1a,
247 DATA_ONLY, 0x17,
248
249 DATA_ONLY, 0x2b,
250 DATA_ONLY, 0x26,
251 DATA_ONLY, 0x22,
252 DATA_ONLY, 0x20,
253 DATA_ONLY, 0x3a,
254 DATA_ONLY, 0x34,
255 DATA_ONLY, 0x30,
256 DATA_ONLY, 0x2c,
257 DATA_ONLY, 0x29,
258 DATA_ONLY, 0x26,
259 DATA_ONLY, 0x25,
260 DATA_ONLY, 0x23,
261 DATA_ONLY, 0x21,
262 DATA_ONLY, 0x20,
263 DATA_ONLY, 0x1e,
264 DATA_ONLY, 0x1e,
265
266 0xba, 0x00,
267 DATA_ONLY, 0x00,
268 DATA_ONLY, 0x11,
269 DATA_ONLY, 0x22,
270 DATA_ONLY, 0x33,
271 DATA_ONLY, 0x44,
272 DATA_ONLY, 0x44,
273 DATA_ONLY, 0x44,
274
275 DATA_ONLY, 0x55,
276 DATA_ONLY, 0x55,
277 DATA_ONLY, 0x66,
278 DATA_ONLY, 0x66,
279 DATA_ONLY, 0x66,
280 DATA_ONLY, 0x66,
281 DATA_ONLY, 0x66,
282 DATA_ONLY, 0x66,
283
284 0xc1, 0x4d,
285 DATA_ONLY, 0x96,
286 DATA_ONLY, 0x1d,
287 DATA_ONLY, 0x00,
288 DATA_ONLY, 0x00,
289 DATA_ONLY, 0x01,
290 DATA_ONLY, 0xdf,
291 DATA_ONLY, 0x00,
292 DATA_ONLY, 0x00,
293 DATA_ONLY, 0x03,
294 DATA_ONLY, 0x1f,
295 DATA_ONLY, 0x00,
296 DATA_ONLY, 0x00,
297 DATA_ONLY, 0x00,
298 DATA_ONLY, 0x00,
299 DATA_ONLY, 0x00,
300 DATA_ONLY, 0x00,
301 DATA_ONLY, 0x00,
302 DATA_ONLY, 0x00,
303 DATA_ONLY, 0x03,
304 DATA_ONLY, 0x06,
305 DATA_ONLY, 0x09,
306 DATA_ONLY, 0x0d,
307 DATA_ONLY, 0x0f,
308 DATA_ONLY, 0x12,
309 DATA_ONLY, 0x15,
310 DATA_ONLY, 0x18,
311
312 0xb2, 0x10,
313 DATA_ONLY, 0x10,
314 DATA_ONLY, 0x0b,
315 DATA_ONLY, 0x05,
316
317 ENDDEF, 0x0000
318};
319
320static const unsigned short SEQ_ACL_ON[] = {
321 /* ACL on */
322 0xc0, 0x01,
323
324 ENDDEF, 0x0000
325};
326
327static const unsigned short SEQ_ACL_OFF[] = {
328 /* ACL off */
329 0xc0, 0x00,
330
331 ENDDEF, 0x0000
332};
333
334static const unsigned short SEQ_ELVSS_ON[] = {
335 /* ELVSS on */
336 0xb1, 0x0b,
337
338 ENDDEF, 0x0000
339};
340
341static const unsigned short SEQ_ELVSS_OFF[] = {
342 /* ELVSS off */
343 0xb1, 0x0a,
344
345 ENDDEF, 0x0000
346};
347
348static const unsigned short SEQ_STAND_BY_OFF[] = {
349 0x11, COMMAND_ONLY,
350
351 ENDDEF, 0x0000
352};
353
354static const unsigned short SEQ_STAND_BY_ON[] = {
355 0x10, COMMAND_ONLY,
356
357 ENDDEF, 0x0000
358};
359
360static const unsigned short SEQ_DISPLAY_ON[] = {
361 0x29, COMMAND_ONLY,
362
363 ENDDEF, 0x0000
364};
365
366
367static int s6e63m0_spi_write_byte(struct s6e63m0 *lcd, int addr, int data)
368{
369 u16 buf[1];
370 struct spi_message msg;
371
372 struct spi_transfer xfer = {
373 .len = 2,
374 .tx_buf = buf,
375 };
376
377 buf[0] = (addr << 8) | data;
378
379 spi_message_init(&msg);
380 spi_message_add_tail(&xfer, &msg);
381
382 return spi_sync(lcd->spi, &msg);
383}
384
385static int s6e63m0_spi_write(struct s6e63m0 *lcd, unsigned char address,
386 unsigned char command)
387{
388 int ret = 0;
389
390 if (address != DATA_ONLY)
391 ret = s6e63m0_spi_write_byte(lcd, 0x0, address);
392 if (command != COMMAND_ONLY)
393 ret = s6e63m0_spi_write_byte(lcd, 0x1, command);
394
395 return ret;
396}
397
398static int s6e63m0_panel_send_sequence(struct s6e63m0 *lcd,
399 const unsigned short *wbuf)
400{
401 int ret = 0, i = 0;
402
403 while ((wbuf[i] & DEFMASK) != ENDDEF) {
404 if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
405 ret = s6e63m0_spi_write(lcd, wbuf[i], wbuf[i+1]);
406 if (ret)
407 break;
408 } else
409 udelay(wbuf[i+1]*1000);
410 i += 2;
411 }
412
413 return ret;
414}
415
416static int _s6e63m0_gamma_ctl(struct s6e63m0 *lcd, const unsigned int *gamma)
417{
418 unsigned int i = 0;
419 int ret = 0;
420
421 /* disable gamma table updating. */
422 ret = s6e63m0_spi_write(lcd, 0xfa, 0x00);
423 if (ret) {
424 dev_err(lcd->dev, "failed to disable gamma table updating.\n");
425 goto gamma_err;
426 }
427
428 for (i = 0 ; i < GAMMA_TABLE_COUNT; i++) {
429 ret = s6e63m0_spi_write(lcd, DATA_ONLY, gamma[i]);
430 if (ret) {
431 dev_err(lcd->dev, "failed to set gamma table.\n");
432 goto gamma_err;
433 }
434 }
435
436 /* update gamma table. */
437 ret = s6e63m0_spi_write(lcd, 0xfa, 0x01);
438 if (ret)
439 dev_err(lcd->dev, "failed to update gamma table.\n");
440
441gamma_err:
442 return ret;
443}
444
445static int s6e63m0_gamma_ctl(struct s6e63m0 *lcd, int gamma)
446{
447 int ret = 0;
448
449 ret = _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]);
450
451 return ret;
452}
453
454
455static int s6e63m0_ldi_init(struct s6e63m0 *lcd)
456{
457 int ret, i;
458 const unsigned short *init_seq[] = {
459 SEQ_PANEL_CONDITION_SET,
460 SEQ_DISPLAY_CONDITION_SET,
461 SEQ_GAMMA_SETTING,
462 SEQ_ETC_CONDITION_SET,
463 SEQ_ACL_ON,
464 SEQ_ELVSS_ON,
465 };
466
467 for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
468 ret = s6e63m0_panel_send_sequence(lcd, init_seq[i]);
469 if (ret)
470 break;
471 }
472
473 return ret;
474}
475
476static int s6e63m0_ldi_enable(struct s6e63m0 *lcd)
477{
478 int ret = 0, i;
479 const unsigned short *enable_seq[] = {
480 SEQ_STAND_BY_OFF,
481 SEQ_DISPLAY_ON,
482 };
483
484 for (i = 0; i < ARRAY_SIZE(enable_seq); i++) {
485 ret = s6e63m0_panel_send_sequence(lcd, enable_seq[i]);
486 if (ret)
487 break;
488 }
489
490 return ret;
491}
492
493static int s6e63m0_ldi_disable(struct s6e63m0 *lcd)
494{
495 int ret;
496
497 ret = s6e63m0_panel_send_sequence(lcd, SEQ_STAND_BY_ON);
498
499 return ret;
500}
501
502static int s6e63m0_power_on(struct s6e63m0 *lcd)
503{
504 int ret = 0;
505 struct lcd_platform_data *pd = NULL;
506 struct backlight_device *bd = NULL;
507
508 pd = lcd->lcd_pd;
509 if (!pd) {
510 dev_err(lcd->dev, "platform data is NULL.\n");
511 return -EFAULT;
512 }
513
514 bd = lcd->bd;
515 if (!bd) {
516 dev_err(lcd->dev, "backlight device is NULL.\n");
517 return -EFAULT;
518 }
519
520 if (!pd->power_on) {
521 dev_err(lcd->dev, "power_on is NULL.\n");
522 return -EFAULT;
523 } else {
524 pd->power_on(lcd->ld, 1);
525 mdelay(pd->power_on_delay);
526 }
527
528 if (!pd->reset) {
529 dev_err(lcd->dev, "reset is NULL.\n");
530 return -EFAULT;
531 } else {
532 pd->reset(lcd->ld);
533 mdelay(pd->reset_delay);
534 }
535
536 ret = s6e63m0_ldi_init(lcd);
537 if (ret) {
538 dev_err(lcd->dev, "failed to initialize ldi.\n");
539 return ret;
540 }
541
542 ret = s6e63m0_ldi_enable(lcd);
543 if (ret) {
544 dev_err(lcd->dev, "failed to enable ldi.\n");
545 return ret;
546 }
547
548 /* set brightness to current value after power on or resume. */
549 ret = s6e63m0_gamma_ctl(lcd, bd->props.brightness);
550 if (ret) {
551 dev_err(lcd->dev, "lcd gamma setting failed.\n");
552 return ret;
553 }
554
555 return 0;
556}
557
558static int s6e63m0_power_off(struct s6e63m0 *lcd)
559{
560 int ret = 0;
561 struct lcd_platform_data *pd = NULL;
562
563 pd = lcd->lcd_pd;
564 if (!pd) {
565 dev_err(lcd->dev, "platform data is NULL.\n");
566 return -EFAULT;
567 }
568
569 ret = s6e63m0_ldi_disable(lcd);
570 if (ret) {
571 dev_err(lcd->dev, "lcd setting failed.\n");
572 return -EIO;
573 }
574
575 mdelay(pd->power_off_delay);
576
577 if (!pd->power_on) {
578 dev_err(lcd->dev, "power_on is NULL.\n");
579 return -EFAULT;
580 } else
581 pd->power_on(lcd->ld, 0);
582
583 return 0;
584}
585
586static int s6e63m0_power(struct s6e63m0 *lcd, int power)
587{
588 int ret = 0;
589
590 if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
591 ret = s6e63m0_power_on(lcd);
592 else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
593 ret = s6e63m0_power_off(lcd);
594
595 if (!ret)
596 lcd->power = power;
597
598 return ret;
599}
600
601static int s6e63m0_set_power(struct lcd_device *ld, int power)
602{
603 struct s6e63m0 *lcd = lcd_get_data(ld);
604
605 if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
606 power != FB_BLANK_NORMAL) {
607 dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
608 return -EINVAL;
609 }
610
611 return s6e63m0_power(lcd, power);
612}
613
614static int s6e63m0_get_power(struct lcd_device *ld)
615{
616 struct s6e63m0 *lcd = lcd_get_data(ld);
617
618 return lcd->power;
619}
620
621static int s6e63m0_get_brightness(struct backlight_device *bd)
622{
623 return bd->props.brightness;
624}
625
626static int s6e63m0_set_brightness(struct backlight_device *bd)
627{
628 int ret = 0, brightness = bd->props.brightness;
629 struct s6e63m0 *lcd = bl_get_data(bd);
630
631 if (brightness < MIN_BRIGHTNESS ||
632 brightness > bd->props.max_brightness) {
633 dev_err(&bd->dev, "lcd brightness should be %d to %d.\n",
634 MIN_BRIGHTNESS, MAX_BRIGHTNESS);
635 return -EINVAL;
636 }
637
638 ret = s6e63m0_gamma_ctl(lcd, bd->props.brightness);
639 if (ret) {
640 dev_err(&bd->dev, "lcd brightness setting failed.\n");
641 return -EIO;
642 }
643
644 return ret;
645}
646
647static struct lcd_ops s6e63m0_lcd_ops = {
648 .set_power = s6e63m0_set_power,
649 .get_power = s6e63m0_get_power,
650};
651
652static const struct backlight_ops s6e63m0_backlight_ops = {
653 .get_brightness = s6e63m0_get_brightness,
654 .update_status = s6e63m0_set_brightness,
655};
656
657static ssize_t s6e63m0_sysfs_show_gamma_mode(struct device *dev,
658 struct device_attribute *attr, char *buf)
659{
660 struct s6e63m0 *lcd = dev_get_drvdata(dev);
661 char temp[10];
662
663 switch (lcd->gamma_mode) {
664 case 0:
665 sprintf(temp, "2.2 mode\n");
666 strcat(buf, temp);
667 break;
668 case 1:
669 sprintf(temp, "1.9 mode\n");
670 strcat(buf, temp);
671 break;
672 case 2:
673 sprintf(temp, "1.7 mode\n");
674 strcat(buf, temp);
675 break;
676 default:
677 dev_info(dev, "gamma mode could be 0:2.2, 1:1.9 or 2:1.7)n");
678 break;
679 }
680
681 return strlen(buf);
682}
683
684static ssize_t s6e63m0_sysfs_store_gamma_mode(struct device *dev,
685 struct device_attribute *attr,
686 const char *buf, size_t len)
687{
688 struct s6e63m0 *lcd = dev_get_drvdata(dev);
689 struct backlight_device *bd = NULL;
690 int brightness, rc;
691
692 rc = strict_strtoul(buf, 0, (unsigned long *)&lcd->gamma_mode);
693 if (rc < 0)
694 return rc;
695
696 bd = lcd->bd;
697
698 brightness = bd->props.brightness;
699
700 switch (lcd->gamma_mode) {
701 case 0:
702 _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[brightness]);
703 break;
704 case 1:
705 _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_19_table[brightness]);
706 break;
707 case 2:
708 _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_17_table[brightness]);
709 break;
710 default:
711 dev_info(dev, "gamma mode could be 0:2.2, 1:1.9 or 2:1.7\n");
712 _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[brightness]);
713 break;
714 }
715 return len;
716}
717
718static DEVICE_ATTR(gamma_mode, 0644,
719 s6e63m0_sysfs_show_gamma_mode, s6e63m0_sysfs_store_gamma_mode);
720
721static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev,
722 struct device_attribute *attr, char *buf)
723{
724 struct s6e63m0 *lcd = dev_get_drvdata(dev);
725 char temp[3];
726
727 sprintf(temp, "%d\n", lcd->gamma_table_count);
728 strcpy(buf, temp);
729
730 return strlen(buf);
731}
732static DEVICE_ATTR(gamma_table, 0644,
733 s6e63m0_sysfs_show_gamma_table, NULL);
734
735static int __init s6e63m0_probe(struct spi_device *spi)
736{
737 int ret = 0;
738 struct s6e63m0 *lcd = NULL;
739 struct lcd_device *ld = NULL;
740 struct backlight_device *bd = NULL;
741
742 lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL);
743 if (!lcd)
744 return -ENOMEM;
745
746 /* s6e63m0 lcd panel uses 3-wire 9bits SPI Mode. */
747 spi->bits_per_word = 9;
748
749 ret = spi_setup(spi);
750 if (ret < 0) {
751 dev_err(&spi->dev, "spi setup failed.\n");
752 goto out_free_lcd;
753 }
754
755 lcd->spi = spi;
756 lcd->dev = &spi->dev;
757
758 lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data;
759 if (!lcd->lcd_pd) {
760 dev_err(&spi->dev, "platform data is NULL.\n");
761 goto out_free_lcd;
762 }
763
764 ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops);
765 if (IS_ERR(ld)) {
766 ret = PTR_ERR(ld);
767 goto out_free_lcd;
768 }
769
770 lcd->ld = ld;
771
772 bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd,
773 &s6e63m0_backlight_ops, NULL);
774 if (IS_ERR(bd)) {
775 ret = PTR_ERR(bd);
776 goto out_lcd_unregister;
777 }
778
779 bd->props.max_brightness = MAX_BRIGHTNESS;
780 bd->props.brightness = MAX_BRIGHTNESS;
781 lcd->bd = bd;
782
783 /*
784 * it gets gamma table count available so it gets user
785 * know that.
786 */
787 lcd->gamma_table_count =
788 sizeof(gamma_table) / (MAX_GAMMA_LEVEL * sizeof(int));
789
790 ret = device_create_file(&(spi->dev), &dev_attr_gamma_mode);
791 if (ret < 0)
792 dev_err(&(spi->dev), "failed to add sysfs entries\n");
793
794 ret = device_create_file(&(spi->dev), &dev_attr_gamma_table);
795 if (ret < 0)
796 dev_err(&(spi->dev), "failed to add sysfs entries\n");
797
798 /*
799 * if lcd panel was on from bootloader like u-boot then
800 * do not lcd on.
801 */
802 if (!lcd->lcd_pd->lcd_enabled) {
803 /*
804 * if lcd panel was off from bootloader then
805 * current lcd status is powerdown and then
806 * it enables lcd panel.
807 */
808 lcd->power = FB_BLANK_POWERDOWN;
809
810 s6e63m0_power(lcd, FB_BLANK_UNBLANK);
811 } else
812 lcd->power = FB_BLANK_UNBLANK;
813
814 dev_set_drvdata(&spi->dev, lcd);
815
816 dev_info(&spi->dev, "s6e63m0 panel driver has been probed.\n");
817
818 return 0;
819
820out_lcd_unregister:
821 lcd_device_unregister(ld);
822out_free_lcd:
823 kfree(lcd);
824 return ret;
825}
826
827static int __devexit s6e63m0_remove(struct spi_device *spi)
828{
829 struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
830
831 s6e63m0_power(lcd, FB_BLANK_POWERDOWN);
832 lcd_device_unregister(lcd->ld);
833 kfree(lcd);
834
835 return 0;
836}
837
838#if defined(CONFIG_PM)
839unsigned int before_power;
840
841static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg)
842{
843 int ret = 0;
844 struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
845
846 dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
847
848 before_power = lcd->power;
849
850 /*
851 * when lcd panel is suspend, lcd panel becomes off
852 * regardless of status.
853 */
854 ret = s6e63m0_power(lcd, FB_BLANK_POWERDOWN);
855
856 return ret;
857}
858
859static int s6e63m0_resume(struct spi_device *spi)
860{
861 int ret = 0;
862 struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
863
864 /*
865 * after suspended, if lcd panel status is FB_BLANK_UNBLANK
866 * (at that time, before_power is FB_BLANK_UNBLANK) then
867 * it changes that status to FB_BLANK_POWERDOWN to get lcd on.
868 */
869 if (before_power == FB_BLANK_UNBLANK)
870 lcd->power = FB_BLANK_POWERDOWN;
871
872 dev_dbg(&spi->dev, "before_power = %d\n", before_power);
873
874 ret = s6e63m0_power(lcd, before_power);
875
876 return ret;
877}
878#else
879#define s6e63m0_suspend NULL
880#define s6e63m0_resume NULL
881#endif
882
883/* Power down all displays on reboot, poweroff or halt. */
884static void s6e63m0_shutdown(struct spi_device *spi)
885{
886 struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
887
888 s6e63m0_power(lcd, FB_BLANK_POWERDOWN);
889}
890
891static struct spi_driver s6e63m0_driver = {
892 .driver = {
893 .name = "s6e63m0",
894 .bus = &spi_bus_type,
895 .owner = THIS_MODULE,
896 },
897 .probe = s6e63m0_probe,
898 .remove = __devexit_p(s6e63m0_remove),
899 .shutdown = s6e63m0_shutdown,
900 .suspend = s6e63m0_suspend,
901 .resume = s6e63m0_resume,
902};
903
904static int __init s6e63m0_init(void)
905{
906 return spi_register_driver(&s6e63m0_driver);
907}
908
909static void __exit s6e63m0_exit(void)
910{
911 spi_unregister_driver(&s6e63m0_driver);
912}
913
914module_init(s6e63m0_init);
915module_exit(s6e63m0_exit);
916
917MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
918MODULE_DESCRIPTION("S6E63M0 LCD Driver");
919MODULE_LICENSE("GPL");
920
diff --git a/drivers/video/backlight/s6e63m0_gamma.h b/drivers/video/backlight/s6e63m0_gamma.h
new file mode 100644
index 000000000000..2c44bdb0696b
--- /dev/null
+++ b/drivers/video/backlight/s6e63m0_gamma.h
@@ -0,0 +1,266 @@
1/* linux/drivers/video/samsung/s6e63m0_brightness.h
2 *
3 * Gamma level definitions.
4 *
5 * Copyright (c) 2009 Samsung Electronics
6 * InKi Dae <inki.dae@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef _S6E63M0_BRIGHTNESS_H
14#define _S6E63M0_BRIGHTNESS_H
15
16#define MAX_GAMMA_LEVEL 11
17#define GAMMA_TABLE_COUNT 21
18
19/* gamma value: 2.2 */
20static const unsigned int s6e63m0_22_300[] = {
21 0x18, 0x08, 0x24, 0x5f, 0x50, 0x2d, 0xB6,
22 0xB9, 0xA7, 0xAd, 0xB1, 0x9f, 0xbe, 0xC0,
23 0xB5, 0x00, 0xa0, 0x00, 0xa4, 0x00, 0xdb
24};
25
26static const unsigned int s6e63m0_22_280[] = {
27 0x18, 0x08, 0x24, 0x64, 0x56, 0x33, 0xB6,
28 0xBA, 0xA8, 0xAC, 0xB1, 0x9D, 0xC1, 0xC1,
29 0xB7, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6
30};
31
32static const unsigned int s6e63m0_22_260[] = {
33 0x18, 0x08, 0x24, 0x66, 0x58, 0x34, 0xB6,
34 0xBA, 0xA7, 0xAF, 0xB3, 0xA0, 0xC1, 0xC2,
35 0xB7, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1
36
37};
38
39static const unsigned int s6e63m0_22_240[] = {
40 0x18, 0x08, 0x24, 0x62, 0x54, 0x30, 0xB9,
41 0xBB, 0xA9, 0xB0, 0xB3, 0xA1, 0xC1, 0xC3,
42 0xB7, 0x00, 0x91, 0x00, 0x95, 0x00, 0xDA
43
44};
45static const unsigned int s6e63m0_22_220[] = {
46 0x18, 0x08, 0x24, 0x63, 0x53, 0x31, 0xB8,
47 0xBC, 0xA9, 0xB0, 0xB5, 0xA2, 0xC4, 0xC4,
48 0xB8, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2
49};
50
51static const unsigned int s6e63m0_22_200[] = {
52 0x18, 0x08, 0x24, 0x66, 0x55, 0x34, 0xBA,
53 0xBD, 0xAB, 0xB1, 0xB5, 0xA3, 0xC5, 0xC6,
54 0xB9, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA
55};
56
57static const unsigned int s6e63m0_22_170[] = {
58 0x18, 0x08, 0x24, 0x69, 0x54, 0x37, 0xBB,
59 0xBE, 0xAC, 0xB4, 0xB7, 0xA6, 0xC7, 0xC8,
60 0xBC, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB
61};
62
63static const unsigned int s6e63m0_22_140[] = {
64 0x18, 0x08, 0x24, 0x6C, 0x54, 0x3A, 0xBC,
65 0xBF, 0xAC, 0xB7, 0xBB, 0xA9, 0xC9, 0xC9,
66 0xBE, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E
67};
68
69static const unsigned int s6e63m0_22_110[] = {
70 0x18, 0x08, 0x24, 0x70, 0x51, 0x3E, 0xBF,
71 0xC1, 0xAF, 0xB9, 0xBC, 0xAB, 0xCC, 0xCC,
72 0xC2, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D
73};
74
75static const unsigned int s6e63m0_22_90[] = {
76 0x18, 0x08, 0x24, 0x73, 0x4A, 0x3D, 0xC0,
77 0xC2, 0xB1, 0xBB, 0xBE, 0xAC, 0xCE, 0xCF,
78 0xC5, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82
79};
80
81static const unsigned int s6e63m0_22_30[] = {
82 0x18, 0x08, 0x24, 0x78, 0xEC, 0x3D, 0xC8,
83 0xC2, 0xB6, 0xC4, 0xC7, 0xB6, 0xD5, 0xD7,
84 0xCC, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51
85};
86
87/* gamma value: 1.9 */
88static const unsigned int s6e63m0_19_300[] = {
89 0x18, 0x08, 0x24, 0x61, 0x5F, 0x39, 0xBA,
90 0xBD, 0xAD, 0xB1, 0xB6, 0xA5, 0xC4, 0xC5,
91 0xBC, 0x00, 0xA0, 0x00, 0xA4, 0x00, 0xDB
92};
93
94static const unsigned int s6e63m0_19_280[] = {
95 0x18, 0x08, 0x24, 0x61, 0x60, 0x39, 0xBB,
96 0xBE, 0xAD, 0xB2, 0xB6, 0xA6, 0xC5, 0xC7,
97 0xBD, 0x00, 0x9B, 0x00, 0x9E, 0x00, 0xD5
98};
99
100static const unsigned int s6e63m0_19_260[] = {
101 0x18, 0x08, 0x24, 0x63, 0x61, 0x3B, 0xBA,
102 0xBE, 0xAC, 0xB3, 0xB8, 0xA7, 0xC6, 0xC8,
103 0xBD, 0x00, 0x96, 0x00, 0x98, 0x00, 0xCF
104};
105
106static const unsigned int s6e63m0_19_240[] = {
107 0x18, 0x08, 0x24, 0x67, 0x64, 0x3F, 0xBB,
108 0xBE, 0xAD, 0xB3, 0xB9, 0xA7, 0xC8, 0xC9,
109 0xBE, 0x00, 0x90, 0x00, 0x92, 0x00, 0xC8
110};
111
112static const unsigned int s6e63m0_19_220[] = {
113 0x18, 0x08, 0x24, 0x68, 0x64, 0x40, 0xBC,
114 0xBF, 0xAF, 0xB4, 0xBA, 0xA9, 0xC8, 0xCA,
115 0xBE, 0x00, 0x8B, 0x00, 0x8C, 0x00, 0xC0
116};
117
118static const unsigned int s6e63m0_19_200[] = {
119 0x18, 0x08, 0x24, 0x68, 0x64, 0x3F, 0xBE,
120 0xC0, 0xB0, 0xB6, 0xBB, 0xAB, 0xC8, 0xCB,
121 0xBF, 0x00, 0x85, 0x00, 0x86, 0x00, 0xB8
122};
123
124static const unsigned int s6e63m0_19_170[] = {
125 0x18, 0x08, 0x24, 0x69, 0x64, 0x40, 0xBF,
126 0xC1, 0xB0, 0xB9, 0xBE, 0xAD, 0xCB, 0xCD,
127 0xC2, 0x00, 0x7A, 0x00, 0x7B, 0x00, 0xAA
128};
129
130static const unsigned int s6e63m0_19_140[] = {
131 0x18, 0x08, 0x24, 0x6E, 0x65, 0x45, 0xC0,
132 0xC3, 0xB2, 0xBA, 0xBE, 0xAE, 0xCD, 0xD0,
133 0xC4, 0x00, 0x70, 0x00, 0x70, 0x00, 0x9C
134};
135
136static const unsigned int s6e63m0_19_110[] = {
137 0x18, 0x08, 0x24, 0x6F, 0x65, 0x46, 0xC2,
138 0xC4, 0xB3, 0xBF, 0xC2, 0xB2, 0xCF, 0xD1,
139 0xC6, 0x00, 0x64, 0x00, 0x64, 0x00, 0x8D
140};
141
142static const unsigned int s6e63m0_19_90[] = {
143 0x18, 0x08, 0x24, 0x74, 0x60, 0x4A, 0xC3,
144 0xC6, 0xB5, 0xBF, 0xC3, 0xB2, 0xD2, 0xD3,
145 0xC8, 0x00, 0x5B, 0x00, 0x5B, 0x00, 0x81
146};
147
148static const unsigned int s6e63m0_19_30[] = {
149 0x18, 0x08, 0x24, 0x84, 0x45, 0x4F, 0xCA,
150 0xCB, 0xBC, 0xC9, 0xCB, 0xBC, 0xDA, 0xDA,
151 0xD0, 0x00, 0x35, 0x00, 0x34, 0x00, 0x4E
152};
153
154/* gamma value: 1.7 */
155static const unsigned int s6e63m0_17_300[] = {
156 0x18, 0x08, 0x24, 0x70, 0x70, 0x4F, 0xBF,
157 0xC2, 0xB2, 0xB8, 0xBC, 0xAC, 0xCB, 0xCD,
158 0xC3, 0x00, 0xA0, 0x00, 0xA4, 0x00, 0xDB
159};
160
161static const unsigned int s6e63m0_17_280[] = {
162 0x18, 0x08, 0x24, 0x71, 0x71, 0x50, 0xBF,
163 0xC2, 0xB2, 0xBA, 0xBE, 0xAE, 0xCB, 0xCD,
164 0xC3, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6
165};
166
167static const unsigned int s6e63m0_17_260[] = {
168 0x18, 0x08, 0x24, 0x72, 0x72, 0x50, 0xC0,
169 0xC3, 0xB4, 0xB9, 0xBE, 0xAE, 0xCC, 0xCF,
170 0xC4, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1
171};
172
173static const unsigned int s6e63m0_17_240[] = {
174 0x18, 0x08, 0x24, 0x71, 0x72, 0x4F, 0xC2,
175 0xC4, 0xB5, 0xBB, 0xBF, 0xB0, 0xCC, 0xCF,
176 0xC3, 0x00, 0x91, 0x00, 0x95, 0x00, 0xCA
177};
178
179static const unsigned int s6e63m0_17_220[] = {
180 0x18, 0x08, 0x24, 0x71, 0x73, 0x4F, 0xC2,
181 0xC5, 0xB5, 0xBD, 0xC0, 0xB2, 0xCD, 0xD1,
182 0xC5, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2
183};
184
185static const unsigned int s6e63m0_17_200[] = {
186 0x18, 0x08, 0x24, 0x72, 0x75, 0x51, 0xC2,
187 0xC6, 0xB5, 0xBF, 0xC1, 0xB3, 0xCE, 0xD1,
188 0xC6, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA
189};
190
191static const unsigned int s6e63m0_17_170[] = {
192 0x18, 0x08, 0x24, 0x75, 0x77, 0x54, 0xC3,
193 0xC7, 0xB7, 0xC0, 0xC3, 0xB4, 0xD1, 0xD3,
194 0xC9, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB
195};
196
197static const unsigned int s6e63m0_17_140[] = {
198 0x18, 0x08, 0x24, 0x7B, 0x77, 0x58, 0xC3,
199 0xC8, 0xB8, 0xC2, 0xC6, 0xB6, 0xD3, 0xD4,
200 0xCA, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E
201};
202
203static const unsigned int s6e63m0_17_110[] = {
204 0x18, 0x08, 0x24, 0x81, 0x7B, 0x5D, 0xC6,
205 0xCA, 0xBB, 0xC3, 0xC7, 0xB8, 0xD6, 0xD8,
206 0xCD, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D
207};
208
209static const unsigned int s6e63m0_17_90[] = {
210 0x18, 0x08, 0x24, 0x82, 0x7A, 0x5B, 0xC8,
211 0xCB, 0xBD, 0xC5, 0xCA, 0xBA, 0xD6, 0xD8,
212 0xCE, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82
213};
214
215static const unsigned int s6e63m0_17_30[] = {
216 0x18, 0x08, 0x24, 0x8F, 0x73, 0x63, 0xD1,
217 0xD0, 0xC5, 0xCC, 0xD1, 0xC2, 0xDE, 0xE0,
218 0xD6, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51
219};
220
221struct s6e63m0_gamma {
222 unsigned int *gamma_22_table[MAX_GAMMA_LEVEL];
223 unsigned int *gamma_19_table[MAX_GAMMA_LEVEL];
224 unsigned int *gamma_17_table[MAX_GAMMA_LEVEL];
225};
226
227static struct s6e63m0_gamma gamma_table = {
228 .gamma_22_table[0] = (unsigned int *)&s6e63m0_22_30,
229 .gamma_22_table[1] = (unsigned int *)&s6e63m0_22_90,
230 .gamma_22_table[2] = (unsigned int *)&s6e63m0_22_110,
231 .gamma_22_table[3] = (unsigned int *)&s6e63m0_22_140,
232 .gamma_22_table[4] = (unsigned int *)&s6e63m0_22_170,
233 .gamma_22_table[5] = (unsigned int *)&s6e63m0_22_200,
234 .gamma_22_table[6] = (unsigned int *)&s6e63m0_22_220,
235 .gamma_22_table[7] = (unsigned int *)&s6e63m0_22_240,
236 .gamma_22_table[8] = (unsigned int *)&s6e63m0_22_260,
237 .gamma_22_table[9] = (unsigned int *)&s6e63m0_22_280,
238 .gamma_22_table[10] = (unsigned int *)&s6e63m0_22_300,
239
240 .gamma_19_table[0] = (unsigned int *)&s6e63m0_19_30,
241 .gamma_19_table[1] = (unsigned int *)&s6e63m0_19_90,
242 .gamma_19_table[2] = (unsigned int *)&s6e63m0_19_110,
243 .gamma_19_table[3] = (unsigned int *)&s6e63m0_19_140,
244 .gamma_19_table[4] = (unsigned int *)&s6e63m0_19_170,
245 .gamma_19_table[5] = (unsigned int *)&s6e63m0_19_200,
246 .gamma_19_table[6] = (unsigned int *)&s6e63m0_19_220,
247 .gamma_19_table[7] = (unsigned int *)&s6e63m0_19_240,
248 .gamma_19_table[8] = (unsigned int *)&s6e63m0_19_260,
249 .gamma_19_table[9] = (unsigned int *)&s6e63m0_19_280,
250 .gamma_19_table[10] = (unsigned int *)&s6e63m0_19_300,
251
252 .gamma_17_table[0] = (unsigned int *)&s6e63m0_17_30,
253 .gamma_17_table[1] = (unsigned int *)&s6e63m0_17_90,
254 .gamma_17_table[2] = (unsigned int *)&s6e63m0_17_110,
255 .gamma_17_table[3] = (unsigned int *)&s6e63m0_17_140,
256 .gamma_17_table[4] = (unsigned int *)&s6e63m0_17_170,
257 .gamma_17_table[5] = (unsigned int *)&s6e63m0_17_200,
258 .gamma_17_table[6] = (unsigned int *)&s6e63m0_17_220,
259 .gamma_17_table[7] = (unsigned int *)&s6e63m0_17_240,
260 .gamma_17_table[8] = (unsigned int *)&s6e63m0_17_260,
261 .gamma_17_table[9] = (unsigned int *)&s6e63m0_17_280,
262 .gamma_17_table[10] = (unsigned int *)&s6e63m0_17_300,
263};
264
265#endif
266
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index 23b2a8c0dbfc..b020ba7f1cf2 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -501,7 +501,9 @@ static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id)
501 501
502static int __devinit bfin_bf54x_probe(struct platform_device *pdev) 502static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
503{ 503{
504#ifndef NO_BL_SUPPORT
504 struct backlight_properties props; 505 struct backlight_properties props;
506#endif
505 struct bfin_bf54xfb_info *info; 507 struct bfin_bf54xfb_info *info;
506 struct fb_info *fbinfo; 508 struct fb_info *fbinfo;
507 int ret; 509 int ret;
@@ -654,7 +656,8 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
654 printk(KERN_ERR DRIVER_NAME 656 printk(KERN_ERR DRIVER_NAME
655 ": unable to register backlight.\n"); 657 ": unable to register backlight.\n");
656 ret = -EINVAL; 658 ret = -EINVAL;
657 goto out9; 659 unregister_framebuffer(fbinfo);
660 goto out8;
658 } 661 }
659 662
660 lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops); 663 lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops);
@@ -663,8 +666,6 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
663 666
664 return 0; 667 return 0;
665 668
666out9:
667 unregister_framebuffer(fbinfo);
668out8: 669out8:
669 free_irq(info->irq, info); 670 free_irq(info->irq, info);
670out7: 671out7:
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
index 2baac7cc1425..c8e1f04941bd 100644
--- a/drivers/video/bfin-lq035q1-fb.c
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -61,47 +61,13 @@
61#define LCD_X_RES 320 /* Horizontal Resolution */ 61#define LCD_X_RES 320 /* Horizontal Resolution */
62#define LCD_Y_RES 240 /* Vertical Resolution */ 62#define LCD_Y_RES 240 /* Vertical Resolution */
63#define DMA_BUS_SIZE 16 63#define DMA_BUS_SIZE 16
64#define U_LINE 4 /* Blanking Lines */
64 65
65#define USE_RGB565_16_BIT_PPI
66
67#ifdef USE_RGB565_16_BIT_PPI
68#define LCD_BPP 16 /* Bit Per Pixel */
69#define CLOCKS_PER_PIX 1
70#define CPLD_PIPELINE_DELAY_COR 0 /* NO CPLB */
71#endif
72 66
73/* Interface 16/18-bit TFT over an 8-bit wide PPI using a small Programmable Logic Device (CPLD) 67/* Interface 16/18-bit TFT over an 8-bit wide PPI using a small Programmable Logic Device (CPLD)
74 * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165 68 * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165
75 */ 69 */
76 70
77#ifdef USE_RGB565_8_BIT_PPI
78#define LCD_BPP 16 /* Bit Per Pixel */
79#define CLOCKS_PER_PIX 2
80#define CPLD_PIPELINE_DELAY_COR 3 /* RGB565 */
81#endif
82
83#ifdef USE_RGB888_8_BIT_PPI
84#define LCD_BPP 24 /* Bit Per Pixel */
85#define CLOCKS_PER_PIX 3
86#define CPLD_PIPELINE_DELAY_COR 5 /* RGB888 */
87#endif
88
89 /*
90 * HS and VS timing parameters (all in number of PPI clk ticks)
91 */
92
93#define U_LINE 4 /* Blanking Lines */
94
95#define H_ACTPIX (LCD_X_RES * CLOCKS_PER_PIX) /* active horizontal pixel */
96#define H_PERIOD (336 * CLOCKS_PER_PIX) /* HS period */
97#define H_PULSE (2 * CLOCKS_PER_PIX) /* HS pulse width */
98#define H_START (7 * CLOCKS_PER_PIX + CPLD_PIPELINE_DELAY_COR) /* first valid pixel */
99
100#define V_LINES (LCD_Y_RES + U_LINE) /* total vertical lines */
101#define V_PULSE (2 * CLOCKS_PER_PIX) /* VS pulse width (1-5 H_PERIODs) */
102#define V_PERIOD (H_PERIOD * V_LINES) /* VS period */
103
104#define ACTIVE_VIDEO_MEM_OFFSET ((U_LINE / 2) * LCD_X_RES * (LCD_BPP / 8))
105 71
106#define BFIN_LCD_NBR_PALETTE_ENTRIES 256 72#define BFIN_LCD_NBR_PALETTE_ENTRIES 256
107 73
@@ -110,12 +76,6 @@
110#define PPI_PORT_CFG_01 0x10 76#define PPI_PORT_CFG_01 0x10
111#define PPI_POLS_1 0x8000 77#define PPI_POLS_1 0x8000
112 78
113#if (CLOCKS_PER_PIX > 1)
114#define PPI_PMODE (DLEN_8 | PACK_EN)
115#else
116#define PPI_PMODE (DLEN_16)
117#endif
118
119#define LQ035_INDEX 0x74 79#define LQ035_INDEX 0x74
120#define LQ035_DATA 0x76 80#define LQ035_DATA 0x76
121 81
@@ -139,6 +99,15 @@ struct bfin_lq035q1fb_info {
139 int irq; 99 int irq;
140 spinlock_t lock; /* lock */ 100 spinlock_t lock; /* lock */
141 u32 pseudo_pal[16]; 101 u32 pseudo_pal[16];
102
103 u32 lcd_bpp;
104 u32 h_actpix;
105 u32 h_period;
106 u32 h_pulse;
107 u32 h_start;
108 u32 v_lines;
109 u32 v_pulse;
110 u32 v_period;
142}; 111};
143 112
144static int nocursor; 113static int nocursor;
@@ -234,16 +203,69 @@ static int lq035q1_backlight(struct bfin_lq035q1fb_info *info, unsigned arg)
234 return 0; 203 return 0;
235} 204}
236 205
206static int bfin_lq035q1_calc_timing(struct bfin_lq035q1fb_info *fbi)
207{
208 unsigned long clocks_per_pix, cpld_pipeline_delay_cor;
209
210 /*
211 * Interface 16/18-bit TFT over an 8-bit wide PPI using a small
212 * Programmable Logic Device (CPLD)
213 * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165
214 */
215
216 switch (fbi->disp_info->ppi_mode) {
217 case USE_RGB565_16_BIT_PPI:
218 fbi->lcd_bpp = 16;
219 clocks_per_pix = 1;
220 cpld_pipeline_delay_cor = 0;
221 break;
222 case USE_RGB565_8_BIT_PPI:
223 fbi->lcd_bpp = 16;
224 clocks_per_pix = 2;
225 cpld_pipeline_delay_cor = 3;
226 break;
227 case USE_RGB888_8_BIT_PPI:
228 fbi->lcd_bpp = 24;
229 clocks_per_pix = 3;
230 cpld_pipeline_delay_cor = 5;
231 break;
232 default:
233 return -EINVAL;
234 }
235
236 /*
237 * HS and VS timing parameters (all in number of PPI clk ticks)
238 */
239
240 fbi->h_actpix = (LCD_X_RES * clocks_per_pix); /* active horizontal pixel */
241 fbi->h_period = (336 * clocks_per_pix); /* HS period */
242 fbi->h_pulse = (2 * clocks_per_pix); /* HS pulse width */
243 fbi->h_start = (7 * clocks_per_pix + cpld_pipeline_delay_cor); /* first valid pixel */
244
245 fbi->v_lines = (LCD_Y_RES + U_LINE); /* total vertical lines */
246 fbi->v_pulse = (2 * clocks_per_pix); /* VS pulse width (1-5 H_PERIODs) */
247 fbi->v_period = (fbi->h_period * fbi->v_lines); /* VS period */
248
249 return 0;
250}
251
237static void bfin_lq035q1_config_ppi(struct bfin_lq035q1fb_info *fbi) 252static void bfin_lq035q1_config_ppi(struct bfin_lq035q1fb_info *fbi)
238{ 253{
239 bfin_write_PPI_DELAY(H_START); 254 unsigned ppi_pmode;
240 bfin_write_PPI_COUNT(H_ACTPIX - 1); 255
241 bfin_write_PPI_FRAME(V_LINES); 256 if (fbi->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI)
257 ppi_pmode = DLEN_16;
258 else
259 ppi_pmode = (DLEN_8 | PACK_EN);
260
261 bfin_write_PPI_DELAY(fbi->h_start);
262 bfin_write_PPI_COUNT(fbi->h_actpix - 1);
263 bfin_write_PPI_FRAME(fbi->v_lines);
242 264
243 bfin_write_PPI_CONTROL(PPI_TX_MODE | /* output mode , PORT_DIR */ 265 bfin_write_PPI_CONTROL(PPI_TX_MODE | /* output mode , PORT_DIR */
244 PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */ 266 PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */
245 PPI_PORT_CFG_01 | /* two frame sync PORT_CFG */ 267 PPI_PORT_CFG_01 | /* two frame sync PORT_CFG */
246 PPI_PMODE | /* 8/16 bit data length / PACK_EN? */ 268 ppi_pmode | /* 8/16 bit data length / PACK_EN? */
247 PPI_POLS_1); /* faling edge syncs POLS */ 269 PPI_POLS_1); /* faling edge syncs POLS */
248} 270}
249 271
@@ -272,19 +294,19 @@ static void bfin_lq035q1_stop_timers(void)
272 294
273} 295}
274 296
275static void bfin_lq035q1_init_timers(void) 297static void bfin_lq035q1_init_timers(struct bfin_lq035q1fb_info *fbi)
276{ 298{
277 299
278 bfin_lq035q1_stop_timers(); 300 bfin_lq035q1_stop_timers();
279 301
280 set_gptimer_period(TIMER_HSYNC_id, H_PERIOD); 302 set_gptimer_period(TIMER_HSYNC_id, fbi->h_period);
281 set_gptimer_pwidth(TIMER_HSYNC_id, H_PULSE); 303 set_gptimer_pwidth(TIMER_HSYNC_id, fbi->h_pulse);
282 set_gptimer_config(TIMER_HSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT | 304 set_gptimer_config(TIMER_HSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
283 TIMER_TIN_SEL | TIMER_CLK_SEL| 305 TIMER_TIN_SEL | TIMER_CLK_SEL|
284 TIMER_EMU_RUN); 306 TIMER_EMU_RUN);
285 307
286 set_gptimer_period(TIMER_VSYNC_id, V_PERIOD); 308 set_gptimer_period(TIMER_VSYNC_id, fbi->v_period);
287 set_gptimer_pwidth(TIMER_VSYNC_id, V_PULSE); 309 set_gptimer_pwidth(TIMER_VSYNC_id, fbi->v_pulse);
288 set_gptimer_config(TIMER_VSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT | 310 set_gptimer_config(TIMER_VSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
289 TIMER_TIN_SEL | TIMER_CLK_SEL | 311 TIMER_TIN_SEL | TIMER_CLK_SEL |
290 TIMER_EMU_RUN); 312 TIMER_EMU_RUN);
@@ -294,21 +316,21 @@ static void bfin_lq035q1_init_timers(void)
294static void bfin_lq035q1_config_dma(struct bfin_lq035q1fb_info *fbi) 316static void bfin_lq035q1_config_dma(struct bfin_lq035q1fb_info *fbi)
295{ 317{
296 318
319
297 set_dma_config(CH_PPI, 320 set_dma_config(CH_PPI,
298 set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO, 321 set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
299 INTR_DISABLE, DIMENSION_2D, 322 INTR_DISABLE, DIMENSION_2D,
300 DATA_SIZE_16, 323 DATA_SIZE_16,
301 DMA_NOSYNC_KEEP_DMA_BUF)); 324 DMA_NOSYNC_KEEP_DMA_BUF));
302 set_dma_x_count(CH_PPI, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE); 325 set_dma_x_count(CH_PPI, (LCD_X_RES * fbi->lcd_bpp) / DMA_BUS_SIZE);
303 set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8); 326 set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8);
304 set_dma_y_count(CH_PPI, V_LINES); 327 set_dma_y_count(CH_PPI, fbi->v_lines);
305 328
306 set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8); 329 set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8);
307 set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer); 330 set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer);
308 331
309} 332}
310 333
311#if (CLOCKS_PER_PIX == 1)
312static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, 334static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
313 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, 335 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
314 P_PPI0_D3, P_PPI0_D4, P_PPI0_D5, 336 P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
@@ -316,22 +338,27 @@ static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
316 P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, 338 P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
317 P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, 339 P_PPI0_D12, P_PPI0_D13, P_PPI0_D14,
318 P_PPI0_D15, 0}; 340 P_PPI0_D15, 0};
319#else 341
320static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, 342static const u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
321 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, 343 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
322 P_PPI0_D3, P_PPI0_D4, P_PPI0_D5, 344 P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
323 P_PPI0_D6, P_PPI0_D7, 0}; 345 P_PPI0_D6, P_PPI0_D7, 0};
324#endif
325 346
326static inline void bfin_lq035q1_free_ports(void) 347static inline void bfin_lq035q1_free_ports(unsigned ppi16)
327{ 348{
328 peripheral_free_list(ppi0_req_16); 349 if (ppi16)
350 peripheral_free_list(ppi0_req_16);
351 else
352 peripheral_free_list(ppi0_req_8);
353
329 if (ANOMALY_05000400) 354 if (ANOMALY_05000400)
330 gpio_free(P_IDENT(P_PPI0_FS3)); 355 gpio_free(P_IDENT(P_PPI0_FS3));
331} 356}
332 357
333static int __devinit bfin_lq035q1_request_ports(struct platform_device *pdev) 358static int __devinit bfin_lq035q1_request_ports(struct platform_device *pdev,
359 unsigned ppi16)
334{ 360{
361 int ret;
335 /* ANOMALY_05000400 - PPI Does Not Start Properly In Specific Mode: 362 /* ANOMALY_05000400 - PPI Does Not Start Properly In Specific Mode:
336 * Drive PPI_FS3 Low 363 * Drive PPI_FS3 Low
337 */ 364 */
@@ -342,7 +369,12 @@ static int __devinit bfin_lq035q1_request_ports(struct platform_device *pdev)
342 gpio_direction_output(P_IDENT(P_PPI0_FS3), 0); 369 gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
343 } 370 }
344 371
345 if (peripheral_request_list(ppi0_req_16, DRIVER_NAME)) { 372 if (ppi16)
373 ret = peripheral_request_list(ppi0_req_16, DRIVER_NAME);
374 else
375 ret = peripheral_request_list(ppi0_req_8, DRIVER_NAME);
376
377 if (ret) {
346 dev_err(&pdev->dev, "requesting peripherals failed\n"); 378 dev_err(&pdev->dev, "requesting peripherals failed\n");
347 return -EFAULT; 379 return -EFAULT;
348 } 380 }
@@ -364,7 +396,7 @@ static int bfin_lq035q1_fb_open(struct fb_info *info, int user)
364 396
365 bfin_lq035q1_config_dma(fbi); 397 bfin_lq035q1_config_dma(fbi);
366 bfin_lq035q1_config_ppi(fbi); 398 bfin_lq035q1_config_ppi(fbi);
367 bfin_lq035q1_init_timers(); 399 bfin_lq035q1_init_timers(fbi);
368 400
369 /* start dma */ 401 /* start dma */
370 enable_dma(CH_PPI); 402 enable_dma(CH_PPI);
@@ -402,12 +434,9 @@ static int bfin_lq035q1_fb_release(struct fb_info *info, int user)
402static int bfin_lq035q1_fb_check_var(struct fb_var_screeninfo *var, 434static int bfin_lq035q1_fb_check_var(struct fb_var_screeninfo *var,
403 struct fb_info *info) 435 struct fb_info *info)
404{ 436{
405 switch (var->bits_per_pixel) { 437 struct bfin_lq035q1fb_info *fbi = info->par;
406#if (LCD_BPP == 24) 438
407 case 24:/* TRUECOLOUR, 16m */ 439 if (var->bits_per_pixel == fbi->lcd_bpp) {
408#else
409 case 16:/* DIRECTCOLOUR, 64k */
410#endif
411 var->red.offset = info->var.red.offset; 440 var->red.offset = info->var.red.offset;
412 var->green.offset = info->var.green.offset; 441 var->green.offset = info->var.green.offset;
413 var->blue.offset = info->var.blue.offset; 442 var->blue.offset = info->var.blue.offset;
@@ -420,8 +449,7 @@ static int bfin_lq035q1_fb_check_var(struct fb_var_screeninfo *var,
420 var->red.msb_right = 0; 449 var->red.msb_right = 0;
421 var->green.msb_right = 0; 450 var->green.msb_right = 0;
422 var->blue.msb_right = 0; 451 var->blue.msb_right = 0;
423 break; 452 } else {
424 default:
425 pr_debug("%s: depth not supported: %u BPP\n", __func__, 453 pr_debug("%s: depth not supported: %u BPP\n", __func__,
426 var->bits_per_pixel); 454 var->bits_per_pixel);
427 return -EINVAL; 455 return -EINVAL;
@@ -528,6 +556,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
528{ 556{
529 struct bfin_lq035q1fb_info *info; 557 struct bfin_lq035q1fb_info *info;
530 struct fb_info *fbinfo; 558 struct fb_info *fbinfo;
559 u32 active_video_mem_offset;
531 int ret; 560 int ret;
532 561
533 ret = request_dma(CH_PPI, DRIVER_NAME"_CH_PPI"); 562 ret = request_dma(CH_PPI, DRIVER_NAME"_CH_PPI");
@@ -550,6 +579,12 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
550 579
551 platform_set_drvdata(pdev, fbinfo); 580 platform_set_drvdata(pdev, fbinfo);
552 581
582 ret = bfin_lq035q1_calc_timing(info);
583 if (ret < 0) {
584 dev_err(&pdev->dev, "Failed PPI Mode\n");
585 goto out3;
586 }
587
553 strcpy(fbinfo->fix.id, DRIVER_NAME); 588 strcpy(fbinfo->fix.id, DRIVER_NAME);
554 589
555 fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; 590 fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
@@ -571,46 +606,48 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
571 fbinfo->var.xres_virtual = LCD_X_RES; 606 fbinfo->var.xres_virtual = LCD_X_RES;
572 fbinfo->var.yres = LCD_Y_RES; 607 fbinfo->var.yres = LCD_Y_RES;
573 fbinfo->var.yres_virtual = LCD_Y_RES; 608 fbinfo->var.yres_virtual = LCD_Y_RES;
574 fbinfo->var.bits_per_pixel = LCD_BPP; 609 fbinfo->var.bits_per_pixel = info->lcd_bpp;
575 610
576 if (info->disp_info->mode & LQ035_BGR) { 611 if (info->disp_info->mode & LQ035_BGR) {
577#if (LCD_BPP == 24) 612 if (info->lcd_bpp == 24) {
578 fbinfo->var.red.offset = 0; 613 fbinfo->var.red.offset = 0;
579 fbinfo->var.green.offset = 8; 614 fbinfo->var.green.offset = 8;
580 fbinfo->var.blue.offset = 16; 615 fbinfo->var.blue.offset = 16;
581#else 616 } else {
582 fbinfo->var.red.offset = 0; 617 fbinfo->var.red.offset = 0;
583 fbinfo->var.green.offset = 5; 618 fbinfo->var.green.offset = 5;
584 fbinfo->var.blue.offset = 11; 619 fbinfo->var.blue.offset = 11;
585#endif 620 }
586 } else { 621 } else {
587#if (LCD_BPP == 24) 622 if (info->lcd_bpp == 24) {
588 fbinfo->var.red.offset = 16; 623 fbinfo->var.red.offset = 16;
589 fbinfo->var.green.offset = 8; 624 fbinfo->var.green.offset = 8;
590 fbinfo->var.blue.offset = 0; 625 fbinfo->var.blue.offset = 0;
591#else 626 } else {
592 fbinfo->var.red.offset = 11; 627 fbinfo->var.red.offset = 11;
593 fbinfo->var.green.offset = 5; 628 fbinfo->var.green.offset = 5;
594 fbinfo->var.blue.offset = 0; 629 fbinfo->var.blue.offset = 0;
595#endif 630 }
596 } 631 }
597 632
598 fbinfo->var.transp.offset = 0; 633 fbinfo->var.transp.offset = 0;
599 634
600#if (LCD_BPP == 24) 635 if (info->lcd_bpp == 24) {
601 fbinfo->var.red.length = 8; 636 fbinfo->var.red.length = 8;
602 fbinfo->var.green.length = 8; 637 fbinfo->var.green.length = 8;
603 fbinfo->var.blue.length = 8; 638 fbinfo->var.blue.length = 8;
604#else 639 } else {
605 fbinfo->var.red.length = 5; 640 fbinfo->var.red.length = 5;
606 fbinfo->var.green.length = 6; 641 fbinfo->var.green.length = 6;
607 fbinfo->var.blue.length = 5; 642 fbinfo->var.blue.length = 5;
608#endif 643 }
609 644
610 fbinfo->var.transp.length = 0; 645 fbinfo->var.transp.length = 0;
611 646
612 fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * LCD_BPP / 8 647 active_video_mem_offset = ((U_LINE / 2) * LCD_X_RES * (info->lcd_bpp / 8));
613 + ACTIVE_VIDEO_MEM_OFFSET; 648
649 fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * info->lcd_bpp / 8
650 + active_video_mem_offset;
614 651
615 fbinfo->fix.line_length = fbinfo->var.xres_virtual * 652 fbinfo->fix.line_length = fbinfo->var.xres_virtual *
616 fbinfo->var.bits_per_pixel / 8; 653 fbinfo->var.bits_per_pixel / 8;
@@ -629,8 +666,8 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
629 goto out3; 666 goto out3;
630 } 667 }
631 668
632 fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET; 669 fbinfo->screen_base = (void *)info->fb_buffer + active_video_mem_offset;
633 fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET; 670 fbinfo->fix.smem_start = (int)info->fb_buffer + active_video_mem_offset;
634 671
635 fbinfo->fbops = &bfin_lq035q1_fb_ops; 672 fbinfo->fbops = &bfin_lq035q1_fb_ops;
636 673
@@ -643,7 +680,8 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
643 goto out4; 680 goto out4;
644 } 681 }
645 682
646 ret = bfin_lq035q1_request_ports(pdev); 683 ret = bfin_lq035q1_request_ports(pdev,
684 info->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI);
647 if (ret) { 685 if (ret) {
648 dev_err(&pdev->dev, "couldn't request gpio port\n"); 686 dev_err(&pdev->dev, "couldn't request gpio port\n");
649 goto out6; 687 goto out6;
@@ -693,7 +731,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
693 } 731 }
694 732
695 dev_info(&pdev->dev, "%dx%d %d-bit RGB FrameBuffer initialized\n", 733 dev_info(&pdev->dev, "%dx%d %d-bit RGB FrameBuffer initialized\n",
696 LCD_X_RES, LCD_Y_RES, LCD_BPP); 734 LCD_X_RES, LCD_Y_RES, info->lcd_bpp);
697 735
698 return 0; 736 return 0;
699 737
@@ -705,7 +743,8 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
705 out8: 743 out8:
706 free_irq(info->irq, info); 744 free_irq(info->irq, info);
707 out7: 745 out7:
708 bfin_lq035q1_free_ports(); 746 bfin_lq035q1_free_ports(info->disp_info->ppi_mode ==
747 USE_RGB565_16_BIT_PPI);
709 out6: 748 out6:
710 fb_dealloc_cmap(&fbinfo->cmap); 749 fb_dealloc_cmap(&fbinfo->cmap);
711 out4: 750 out4:
@@ -742,7 +781,8 @@ static int __devexit bfin_lq035q1_remove(struct platform_device *pdev)
742 781
743 fb_dealloc_cmap(&fbinfo->cmap); 782 fb_dealloc_cmap(&fbinfo->cmap);
744 783
745 bfin_lq035q1_free_ports(); 784 bfin_lq035q1_free_ports(info->disp_info->ppi_mode ==
785 USE_RGB565_16_BIT_PPI);
746 786
747 platform_set_drvdata(pdev, NULL); 787 platform_set_drvdata(pdev, NULL);
748 framebuffer_release(fbinfo); 788 framebuffer_release(fbinfo);
@@ -781,7 +821,7 @@ static int bfin_lq035q1_resume(struct device *dev)
781 821
782 bfin_lq035q1_config_dma(info); 822 bfin_lq035q1_config_dma(info);
783 bfin_lq035q1_config_ppi(info); 823 bfin_lq035q1_config_ppi(info);
784 bfin_lq035q1_init_timers(); 824 bfin_lq035q1_init_timers(info);
785 825
786 /* start dma */ 826 /* start dma */
787 enable_dma(CH_PPI); 827 enable_dma(CH_PPI);
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index c2ec3dcd4e91..7a50272eaab9 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -420,7 +420,9 @@ static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id)
420 420
421static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) 421static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
422{ 422{
423#ifndef NO_BL_SUPPORT
423 struct backlight_properties props; 424 struct backlight_properties props;
425#endif
424 struct bfin_t350mcqbfb_info *info; 426 struct bfin_t350mcqbfb_info *info;
425 struct fb_info *fbinfo; 427 struct fb_info *fbinfo;
426 int ret; 428 int ret;
@@ -550,7 +552,8 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
550 printk(KERN_ERR DRIVER_NAME 552 printk(KERN_ERR DRIVER_NAME
551 ": unable to register backlight.\n"); 553 ": unable to register backlight.\n");
552 ret = -EINVAL; 554 ret = -EINVAL;
553 goto out9; 555 unregister_framebuffer(fbinfo);
556 goto out8;
554 } 557 }
555 558
556 lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops); 559 lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
@@ -559,8 +562,6 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
559 562
560 return 0; 563 return 0;
561 564
562out9:
563 unregister_framebuffer(fbinfo);
564out8: 565out8:
565 free_irq(info->irq, info); 566 free_irq(info->irq, info);
566out7: 567out7:
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 8d244ba0f601..cad7d45c8bac 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -36,7 +36,9 @@
36#define DRIVER_NAME "da8xx_lcdc" 36#define DRIVER_NAME "da8xx_lcdc"
37 37
38/* LCD Status Register */ 38/* LCD Status Register */
39#define LCD_END_OF_FRAME1 BIT(9)
39#define LCD_END_OF_FRAME0 BIT(8) 40#define LCD_END_OF_FRAME0 BIT(8)
41#define LCD_PL_LOAD_DONE BIT(6)
40#define LCD_FIFO_UNDERFLOW BIT(5) 42#define LCD_FIFO_UNDERFLOW BIT(5)
41#define LCD_SYNC_LOST BIT(2) 43#define LCD_SYNC_LOST BIT(2)
42 44
@@ -58,11 +60,13 @@
58#define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) 60#define LCD_PALETTE_LOAD_MODE(x) ((x) << 20)
59#define PALETTE_AND_DATA 0x00 61#define PALETTE_AND_DATA 0x00
60#define PALETTE_ONLY 0x01 62#define PALETTE_ONLY 0x01
63#define DATA_ONLY 0x02
61 64
62#define LCD_MONO_8BIT_MODE BIT(9) 65#define LCD_MONO_8BIT_MODE BIT(9)
63#define LCD_RASTER_ORDER BIT(8) 66#define LCD_RASTER_ORDER BIT(8)
64#define LCD_TFT_MODE BIT(7) 67#define LCD_TFT_MODE BIT(7)
65#define LCD_UNDERFLOW_INT_ENA BIT(6) 68#define LCD_UNDERFLOW_INT_ENA BIT(6)
69#define LCD_PL_ENABLE BIT(4)
66#define LCD_MONOCHROME_MODE BIT(1) 70#define LCD_MONOCHROME_MODE BIT(1)
67#define LCD_RASTER_ENABLE BIT(0) 71#define LCD_RASTER_ENABLE BIT(0)
68#define LCD_TFT_ALT_ENABLE BIT(23) 72#define LCD_TFT_ALT_ENABLE BIT(23)
@@ -87,6 +91,10 @@
87#define LCD_DMA_CTRL_REG 0x40 91#define LCD_DMA_CTRL_REG 0x40
88#define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44 92#define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44
89#define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48 93#define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48
94#define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C
95#define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50
96
97#define LCD_NUM_BUFFERS 2
90 98
91#define WSI_TIMEOUT 50 99#define WSI_TIMEOUT 50
92#define PALETTE_SIZE 256 100#define PALETTE_SIZE 256
@@ -111,13 +119,20 @@ static inline void lcdc_write(unsigned int val, unsigned int addr)
111struct da8xx_fb_par { 119struct da8xx_fb_par {
112 resource_size_t p_palette_base; 120 resource_size_t p_palette_base;
113 unsigned char *v_palette_base; 121 unsigned char *v_palette_base;
122 dma_addr_t vram_phys;
123 unsigned long vram_size;
124 void *vram_virt;
125 unsigned int dma_start;
126 unsigned int dma_end;
114 struct clk *lcdc_clk; 127 struct clk *lcdc_clk;
115 int irq; 128 int irq;
116 unsigned short pseudo_palette[16]; 129 unsigned short pseudo_palette[16];
117 unsigned int databuf_sz;
118 unsigned int palette_sz; 130 unsigned int palette_sz;
119 unsigned int pxl_clk; 131 unsigned int pxl_clk;
120 int blank; 132 int blank;
133 wait_queue_head_t vsync_wait;
134 int vsync_flag;
135 int vsync_timeout;
121#ifdef CONFIG_CPU_FREQ 136#ifdef CONFIG_CPU_FREQ
122 struct notifier_block freq_transition; 137 struct notifier_block freq_transition;
123#endif 138#endif
@@ -148,9 +163,9 @@ static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
148 .type = FB_TYPE_PACKED_PIXELS, 163 .type = FB_TYPE_PACKED_PIXELS,
149 .type_aux = 0, 164 .type_aux = 0,
150 .visual = FB_VISUAL_PSEUDOCOLOR, 165 .visual = FB_VISUAL_PSEUDOCOLOR,
151 .xpanstep = 1, 166 .xpanstep = 0,
152 .ypanstep = 1, 167 .ypanstep = 1,
153 .ywrapstep = 1, 168 .ywrapstep = 0,
154 .accel = FB_ACCEL_NONE 169 .accel = FB_ACCEL_NONE
155}; 170};
156 171
@@ -221,22 +236,48 @@ static inline void lcd_disable_raster(void)
221 236
222static void lcd_blit(int load_mode, struct da8xx_fb_par *par) 237static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
223{ 238{
224 u32 tmp = par->p_palette_base + par->databuf_sz - 4; 239 u32 start;
225 u32 reg; 240 u32 end;
241 u32 reg_ras;
242 u32 reg_dma;
243
244 /* init reg to clear PLM (loading mode) fields */
245 reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
246 reg_ras &= ~(3 << 20);
247
248 reg_dma = lcdc_read(LCD_DMA_CTRL_REG);
249
250 if (load_mode == LOAD_DATA) {
251 start = par->dma_start;
252 end = par->dma_end;
253
254 reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY);
255 reg_dma |= LCD_END_OF_FRAME_INT_ENA;
256 reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
257
258 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
259 lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
260 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
261 lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
262 } else if (load_mode == LOAD_PALETTE) {
263 start = par->p_palette_base;
264 end = start + par->palette_sz - 1;
265
266 reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
267 reg_ras |= LCD_PL_ENABLE;
268
269 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
270 lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
271 }
226 272
227 /* Update the databuf in the hw. */ 273 lcdc_write(reg_dma, LCD_DMA_CTRL_REG);
228 lcdc_write(par->p_palette_base, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); 274 lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
229 lcdc_write(tmp, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
230 275
231 /* Start the DMA. */ 276 /*
232 reg = lcdc_read(LCD_RASTER_CTRL_REG); 277 * The Raster enable bit must be set after all other control fields are
233 reg &= ~(3 << 20); 278 * set.
234 if (load_mode == LOAD_DATA) 279 */
235 reg |= LCD_PALETTE_LOAD_MODE(PALETTE_AND_DATA); 280 lcd_enable_raster();
236 else if (load_mode == LOAD_PALETTE)
237 reg |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
238
239 lcdc_write(reg, LCD_RASTER_CTRL_REG);
240} 281}
241 282
242/* Configure the Burst Size of DMA */ 283/* Configure the Burst Size of DMA */
@@ -368,12 +409,8 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
368static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, 409static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
369 u32 bpp, u32 raster_order) 410 u32 bpp, u32 raster_order)
370{ 411{
371 u32 bpl, reg; 412 u32 reg;
372 413
373 /* Disable Dual Frame Buffer. */
374 reg = lcdc_read(LCD_DMA_CTRL_REG);
375 lcdc_write(reg & ~LCD_DUAL_FRAME_BUFFER_ENABLE,
376 LCD_DMA_CTRL_REG);
377 /* Set the Panel Width */ 414 /* Set the Panel Width */
378 /* Pixels per line = (PPL + 1)*16 */ 415 /* Pixels per line = (PPL + 1)*16 */
379 /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ 416 /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/
@@ -410,9 +447,6 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
410 return -EINVAL; 447 return -EINVAL;
411 } 448 }
412 449
413 bpl = width * bpp / 8;
414 par->databuf_sz = height * bpl + par->palette_sz;
415
416 return 0; 450 return 0;
417} 451}
418 452
@@ -421,8 +455,9 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
421 struct fb_info *info) 455 struct fb_info *info)
422{ 456{
423 struct da8xx_fb_par *par = info->par; 457 struct da8xx_fb_par *par = info->par;
424 unsigned short *palette = (unsigned short *)par->v_palette_base; 458 unsigned short *palette = (unsigned short *) par->v_palette_base;
425 u_short pal; 459 u_short pal;
460 int update_hw = 0;
426 461
427 if (regno > 255) 462 if (regno > 255)
428 return 1; 463 return 1;
@@ -439,8 +474,10 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
439 pal |= (green & 0x00f0); 474 pal |= (green & 0x00f0);
440 pal |= (blue & 0x000f); 475 pal |= (blue & 0x000f);
441 476
442 palette[regno] = pal; 477 if (palette[regno] != pal) {
443 478 update_hw = 1;
479 palette[regno] = pal;
480 }
444 } else if ((info->var.bits_per_pixel == 16) && regno < 16) { 481 } else if ((info->var.bits_per_pixel == 16) && regno < 16) {
445 red >>= (16 - info->var.red.length); 482 red >>= (16 - info->var.red.length);
446 red <<= info->var.red.offset; 483 red <<= info->var.red.offset;
@@ -453,9 +490,16 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
453 490
454 par->pseudo_palette[regno] = red | green | blue; 491 par->pseudo_palette[regno] = red | green | blue;
455 492
456 palette[0] = 0x4000; 493 if (palette[0] != 0x4000) {
494 update_hw = 1;
495 palette[0] = 0x4000;
496 }
457 } 497 }
458 498
499 /* Update the palette in the h/w as needed. */
500 if (update_hw)
501 lcd_blit(LOAD_PALETTE, par);
502
459 return 0; 503 return 0;
460} 504}
461 505
@@ -541,15 +585,54 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
541 585
542static irqreturn_t lcdc_irq_handler(int irq, void *arg) 586static irqreturn_t lcdc_irq_handler(int irq, void *arg)
543{ 587{
588 struct da8xx_fb_par *par = arg;
544 u32 stat = lcdc_read(LCD_STAT_REG); 589 u32 stat = lcdc_read(LCD_STAT_REG);
590 u32 reg_ras;
545 591
546 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { 592 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
547 lcd_disable_raster(); 593 lcd_disable_raster();
548 lcdc_write(stat, LCD_STAT_REG); 594 lcdc_write(stat, LCD_STAT_REG);
549 lcd_enable_raster(); 595 lcd_enable_raster();
550 } else 596 } else if (stat & LCD_PL_LOAD_DONE) {
597 /*
598 * Must disable raster before changing state of any control bit.
599 * And also must be disabled before clearing the PL loading
600 * interrupt via the following write to the status register. If
601 * this is done after then one gets multiple PL done interrupts.
602 */
603 lcd_disable_raster();
604
551 lcdc_write(stat, LCD_STAT_REG); 605 lcdc_write(stat, LCD_STAT_REG);
552 606
607 /* Disable PL completion inerrupt */
608 reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
609 reg_ras &= ~LCD_PL_ENABLE;
610 lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
611
612 /* Setup and start data loading mode */
613 lcd_blit(LOAD_DATA, par);
614 } else {
615 lcdc_write(stat, LCD_STAT_REG);
616
617 if (stat & LCD_END_OF_FRAME0) {
618 lcdc_write(par->dma_start,
619 LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
620 lcdc_write(par->dma_end,
621 LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
622 par->vsync_flag = 1;
623 wake_up_interruptible(&par->vsync_wait);
624 }
625
626 if (stat & LCD_END_OF_FRAME1) {
627 lcdc_write(par->dma_start,
628 LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
629 lcdc_write(par->dma_end,
630 LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
631 par->vsync_flag = 1;
632 wake_up_interruptible(&par->vsync_wait);
633 }
634 }
635
553 return IRQ_HANDLED; 636 return IRQ_HANDLED;
554} 637}
555 638
@@ -654,9 +737,10 @@ static int __devexit fb_remove(struct platform_device *dev)
654 737
655 unregister_framebuffer(info); 738 unregister_framebuffer(info);
656 fb_dealloc_cmap(&info->cmap); 739 fb_dealloc_cmap(&info->cmap);
657 dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, 740 dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base,
658 info->screen_base - PAGE_SIZE, 741 par->p_palette_base);
659 info->fix.smem_start); 742 dma_free_coherent(NULL, par->vram_size, par->vram_virt,
743 par->vram_phys);
660 free_irq(par->irq, par); 744 free_irq(par->irq, par);
661 clk_disable(par->lcdc_clk); 745 clk_disable(par->lcdc_clk);
662 clk_put(par->lcdc_clk); 746 clk_put(par->lcdc_clk);
@@ -668,6 +752,39 @@ static int __devexit fb_remove(struct platform_device *dev)
668 return 0; 752 return 0;
669} 753}
670 754
755/*
756 * Function to wait for vertical sync which for this LCD peripheral
757 * translates into waiting for the current raster frame to complete.
758 */
759static int fb_wait_for_vsync(struct fb_info *info)
760{
761 struct da8xx_fb_par *par = info->par;
762 int ret;
763
764 /*
765 * Set flag to 0 and wait for isr to set to 1. It would seem there is a
766 * race condition here where the ISR could have occured just before or
767 * just after this set. But since we are just coarsely waiting for
768 * a frame to complete then that's OK. i.e. if the frame completed
769 * just before this code executed then we have to wait another full
770 * frame time but there is no way to avoid such a situation. On the
771 * other hand if the frame completed just after then we don't need
772 * to wait long at all. Either way we are guaranteed to return to the
773 * user immediately after a frame completion which is all that is
774 * required.
775 */
776 par->vsync_flag = 0;
777 ret = wait_event_interruptible_timeout(par->vsync_wait,
778 par->vsync_flag != 0,
779 par->vsync_timeout);
780 if (ret < 0)
781 return ret;
782 if (ret == 0)
783 return -ETIMEDOUT;
784
785 return 0;
786}
787
671static int fb_ioctl(struct fb_info *info, unsigned int cmd, 788static int fb_ioctl(struct fb_info *info, unsigned int cmd,
672 unsigned long arg) 789 unsigned long arg)
673{ 790{
@@ -697,6 +814,8 @@ static int fb_ioctl(struct fb_info *info, unsigned int cmd,
697 sync_arg.pulse_width, 814 sync_arg.pulse_width,
698 sync_arg.front_porch); 815 sync_arg.front_porch);
699 break; 816 break;
817 case FBIO_WAITFORVSYNC:
818 return fb_wait_for_vsync(info);
700 default: 819 default:
701 return -EINVAL; 820 return -EINVAL;
702 } 821 }
@@ -732,10 +851,47 @@ static int cfb_blank(int blank, struct fb_info *info)
732 return ret; 851 return ret;
733} 852}
734 853
854/*
855 * Set new x,y offsets in the virtual display for the visible area and switch
856 * to the new mode.
857 */
858static int da8xx_pan_display(struct fb_var_screeninfo *var,
859 struct fb_info *fbi)
860{
861 int ret = 0;
862 struct fb_var_screeninfo new_var;
863 struct da8xx_fb_par *par = fbi->par;
864 struct fb_fix_screeninfo *fix = &fbi->fix;
865 unsigned int end;
866 unsigned int start;
867
868 if (var->xoffset != fbi->var.xoffset ||
869 var->yoffset != fbi->var.yoffset) {
870 memcpy(&new_var, &fbi->var, sizeof(new_var));
871 new_var.xoffset = var->xoffset;
872 new_var.yoffset = var->yoffset;
873 if (fb_check_var(&new_var, fbi))
874 ret = -EINVAL;
875 else {
876 memcpy(&fbi->var, &new_var, sizeof(new_var));
877
878 start = fix->smem_start +
879 new_var.yoffset * fix->line_length +
880 new_var.xoffset * var->bits_per_pixel / 8;
881 end = start + var->yres * fix->line_length - 1;
882 par->dma_start = start;
883 par->dma_end = end;
884 }
885 }
886
887 return ret;
888}
889
735static struct fb_ops da8xx_fb_ops = { 890static struct fb_ops da8xx_fb_ops = {
736 .owner = THIS_MODULE, 891 .owner = THIS_MODULE,
737 .fb_check_var = fb_check_var, 892 .fb_check_var = fb_check_var,
738 .fb_setcolreg = fb_setcolreg, 893 .fb_setcolreg = fb_setcolreg,
894 .fb_pan_display = da8xx_pan_display,
739 .fb_ioctl = fb_ioctl, 895 .fb_ioctl = fb_ioctl,
740 .fb_fillrect = cfb_fillrect, 896 .fb_fillrect = cfb_fillrect,
741 .fb_copyarea = cfb_copyarea, 897 .fb_copyarea = cfb_copyarea,
@@ -829,40 +985,53 @@ static int __init fb_probe(struct platform_device *device)
829 } 985 }
830 986
831 /* allocate frame buffer */ 987 /* allocate frame buffer */
832 da8xx_fb_info->screen_base = dma_alloc_coherent(NULL, 988 par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp;
833 par->databuf_sz + PAGE_SIZE, 989 par->vram_size = PAGE_ALIGN(par->vram_size/8);
834 (resource_size_t *) 990 par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
835 &da8xx_fb_info->fix.smem_start, 991
836 GFP_KERNEL | GFP_DMA); 992 par->vram_virt = dma_alloc_coherent(NULL,
837 993 par->vram_size,
838 if (!da8xx_fb_info->screen_base) { 994 (resource_size_t *) &par->vram_phys,
995 GFP_KERNEL | GFP_DMA);
996 if (!par->vram_virt) {
839 dev_err(&device->dev, 997 dev_err(&device->dev,
840 "GLCD: kmalloc for frame buffer failed\n"); 998 "GLCD: kmalloc for frame buffer failed\n");
841 ret = -EINVAL; 999 ret = -EINVAL;
842 goto err_release_fb; 1000 goto err_release_fb;
843 } 1001 }
844 1002
845 /* move palette base pointer by (PAGE_SIZE - palette_sz) bytes */ 1003 da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
846 par->v_palette_base = da8xx_fb_info->screen_base + 1004 da8xx_fb_fix.smem_start = par->vram_phys;
847 (PAGE_SIZE - par->palette_sz); 1005 da8xx_fb_fix.smem_len = par->vram_size;
848 par->p_palette_base = da8xx_fb_info->fix.smem_start + 1006 da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8;
849 (PAGE_SIZE - par->palette_sz); 1007
850 1008 par->dma_start = par->vram_phys;
851 /* the rest of the frame buffer is pixel data */ 1009 par->dma_end = par->dma_start + lcdc_info->height *
852 da8xx_fb_info->screen_base = par->v_palette_base + par->palette_sz; 1010 da8xx_fb_fix.line_length - 1;
853 da8xx_fb_fix.smem_start = par->p_palette_base + par->palette_sz; 1011
854 da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz; 1012 /* allocate palette buffer */
855 da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; 1013 par->v_palette_base = dma_alloc_coherent(NULL,
1014 PALETTE_SIZE,
1015 (resource_size_t *)
1016 &par->p_palette_base,
1017 GFP_KERNEL | GFP_DMA);
1018 if (!par->v_palette_base) {
1019 dev_err(&device->dev,
1020 "GLCD: kmalloc for palette buffer failed\n");
1021 ret = -EINVAL;
1022 goto err_release_fb_mem;
1023 }
1024 memset(par->v_palette_base, 0, PALETTE_SIZE);
856 1025
857 par->irq = platform_get_irq(device, 0); 1026 par->irq = platform_get_irq(device, 0);
858 if (par->irq < 0) { 1027 if (par->irq < 0) {
859 ret = -ENOENT; 1028 ret = -ENOENT;
860 goto err_release_fb_mem; 1029 goto err_release_pl_mem;
861 } 1030 }
862 1031
863 ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); 1032 ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par);
864 if (ret) 1033 if (ret)
865 goto err_release_fb_mem; 1034 goto err_release_pl_mem;
866 1035
867 /* Initialize par */ 1036 /* Initialize par */
868 da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; 1037 da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
@@ -870,8 +1039,8 @@ static int __init fb_probe(struct platform_device *device)
870 da8xx_fb_var.xres = lcdc_info->width; 1039 da8xx_fb_var.xres = lcdc_info->width;
871 da8xx_fb_var.xres_virtual = lcdc_info->width; 1040 da8xx_fb_var.xres_virtual = lcdc_info->width;
872 1041
873 da8xx_fb_var.yres = lcdc_info->height; 1042 da8xx_fb_var.yres = lcdc_info->height;
874 da8xx_fb_var.yres_virtual = lcdc_info->height; 1043 da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS;
875 1044
876 da8xx_fb_var.grayscale = 1045 da8xx_fb_var.grayscale =
877 lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; 1046 lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0;
@@ -892,18 +1061,18 @@ static int __init fb_probe(struct platform_device *device)
892 ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); 1061 ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
893 if (ret) 1062 if (ret)
894 goto err_free_irq; 1063 goto err_free_irq;
895
896 /* First palette_sz byte of the frame buffer is the palette */
897 da8xx_fb_info->cmap.len = par->palette_sz; 1064 da8xx_fb_info->cmap.len = par->palette_sz;
898 1065
899 /* Flush the buffer to the screen. */
900 lcd_blit(LOAD_DATA, par);
901
902 /* initialize var_screeninfo */ 1066 /* initialize var_screeninfo */
903 da8xx_fb_var.activate = FB_ACTIVATE_FORCE; 1067 da8xx_fb_var.activate = FB_ACTIVATE_FORCE;
904 fb_set_var(da8xx_fb_info, &da8xx_fb_var); 1068 fb_set_var(da8xx_fb_info, &da8xx_fb_var);
905 1069
906 dev_set_drvdata(&device->dev, da8xx_fb_info); 1070 dev_set_drvdata(&device->dev, da8xx_fb_info);
1071
1072 /* initialize the vsync wait queue */
1073 init_waitqueue_head(&par->vsync_wait);
1074 par->vsync_timeout = HZ / 5;
1075
907 /* Register the Frame Buffer */ 1076 /* Register the Frame Buffer */
908 if (register_framebuffer(da8xx_fb_info) < 0) { 1077 if (register_framebuffer(da8xx_fb_info) < 0) {
909 dev_err(&device->dev, 1078 dev_err(&device->dev,
@@ -919,10 +1088,6 @@ static int __init fb_probe(struct platform_device *device)
919 goto err_cpu_freq; 1088 goto err_cpu_freq;
920 } 1089 }
921#endif 1090#endif
922
923 /* enable raster engine */
924 lcd_enable_raster();
925
926 return 0; 1091 return 0;
927 1092
928#ifdef CONFIG_CPU_FREQ 1093#ifdef CONFIG_CPU_FREQ
@@ -936,10 +1101,12 @@ err_dealloc_cmap:
936err_free_irq: 1101err_free_irq:
937 free_irq(par->irq, par); 1102 free_irq(par->irq, par);
938 1103
1104err_release_pl_mem:
1105 dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base,
1106 par->p_palette_base);
1107
939err_release_fb_mem: 1108err_release_fb_mem:
940 dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, 1109 dma_free_coherent(NULL, par->vram_size, par->vram_virt, par->vram_phys);
941 da8xx_fb_info->screen_base - PAGE_SIZE,
942 da8xx_fb_info->fix.smem_start);
943 1110
944err_release_fb: 1111err_release_fb:
945 framebuffer_release(da8xx_fb_info); 1112 framebuffer_release(da8xx_fb_info);
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 6113c47e095a..073c9b408cf7 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -66,7 +66,7 @@ static int fb_deferred_io_fault(struct vm_area_struct *vma,
66 return 0; 66 return 0;
67} 67}
68 68
69int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync) 69int fb_deferred_io_fsync(struct file *file, int datasync)
70{ 70{
71 struct fb_info *info = file->private_data; 71 struct fb_info *info = file->private_data;
72 72
@@ -155,25 +155,41 @@ static void fb_deferred_io_work(struct work_struct *work)
155{ 155{
156 struct fb_info *info = container_of(work, struct fb_info, 156 struct fb_info *info = container_of(work, struct fb_info,
157 deferred_work.work); 157 deferred_work.work);
158 struct list_head *node, *next;
159 struct page *cur;
160 struct fb_deferred_io *fbdefio = info->fbdefio; 158 struct fb_deferred_io *fbdefio = info->fbdefio;
159 struct page *page, *tmp_page;
160 struct list_head *node, *tmp_node;
161 struct list_head non_dirty;
162
163 INIT_LIST_HEAD(&non_dirty);
161 164
162 /* here we mkclean the pages, then do all deferred IO */ 165 /* here we mkclean the pages, then do all deferred IO */
163 mutex_lock(&fbdefio->lock); 166 mutex_lock(&fbdefio->lock);
164 list_for_each_entry(cur, &fbdefio->pagelist, lru) { 167 list_for_each_entry_safe(page, tmp_page, &fbdefio->pagelist, lru) {
165 lock_page(cur); 168 lock_page(page);
166 page_mkclean(cur); 169 /*
167 unlock_page(cur); 170 * The workqueue callback can be triggered after a
171 * ->page_mkwrite() call but before the PTE has been marked
172 * dirty. In this case page_mkclean() won't "rearm" the page.
173 *
174 * To avoid this, remove those "non-dirty" pages from the
175 * pagelist before calling the driver's callback, then add
176 * them back to get processed on the next work iteration.
177 * At that time, their PTEs will hopefully be dirty for real.
178 */
179 if (!page_mkclean(page))
180 list_move_tail(&page->lru, &non_dirty);
181 unlock_page(page);
168 } 182 }
169 183
170 /* driver's callback with pagelist */ 184 /* driver's callback with pagelist */
171 fbdefio->deferred_io(info, &fbdefio->pagelist); 185 fbdefio->deferred_io(info, &fbdefio->pagelist);
172 186
173 /* clear the list */ 187 /* clear the list... */
174 list_for_each_safe(node, next, &fbdefio->pagelist) { 188 list_for_each_safe(node, tmp_node, &fbdefio->pagelist) {
175 list_del(node); 189 list_del(node);
176 } 190 }
191 /* ... and add back the "non-dirty" pages to the list */
192 list_splice_tail(&non_dirty, &fbdefio->pagelist);
177 mutex_unlock(&fbdefio->lock); 193 mutex_unlock(&fbdefio->lock);
178} 194}
179 195
@@ -202,6 +218,7 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_open);
202void fb_deferred_io_cleanup(struct fb_info *info) 218void fb_deferred_io_cleanup(struct fb_info *info)
203{ 219{
204 struct fb_deferred_io *fbdefio = info->fbdefio; 220 struct fb_deferred_io *fbdefio = info->fbdefio;
221 struct list_head *node, *tmp_node;
205 struct page *page; 222 struct page *page;
206 int i; 223 int i;
207 224
@@ -209,6 +226,13 @@ void fb_deferred_io_cleanup(struct fb_info *info)
209 cancel_delayed_work(&info->deferred_work); 226 cancel_delayed_work(&info->deferred_work);
210 flush_scheduled_work(); 227 flush_scheduled_work();
211 228
229 /* the list may have still some non-dirty pages at this point */
230 mutex_lock(&fbdefio->lock);
231 list_for_each_safe(node, tmp_node, &fbdefio->pagelist) {
232 list_del(node);
233 }
234 mutex_unlock(&fbdefio->lock);
235
212 /* clear out the mapping that we setup */ 236 /* clear out the mapping that we setup */
213 for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { 237 for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
214 page = fb_deferred_io_page(info, i); 238 page = fb_deferred_io_page(info, i);
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index 8bbf251f83d9..af8f0f2cc782 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -106,7 +106,7 @@ static DEFINE_SPINLOCK(hga_reg_lock);
106 106
107/* Framebuffer driver structures */ 107/* Framebuffer driver structures */
108 108
109static struct fb_var_screeninfo __initdata hga_default_var = { 109static struct fb_var_screeninfo hga_default_var __devinitdata = {
110 .xres = 720, 110 .xres = 720,
111 .yres = 348, 111 .yres = 348,
112 .xres_virtual = 720, 112 .xres_virtual = 720,
@@ -120,7 +120,7 @@ static struct fb_var_screeninfo __initdata hga_default_var = {
120 .width = -1, 120 .width = -1,
121}; 121};
122 122
123static struct fb_fix_screeninfo __initdata hga_fix = { 123static struct fb_fix_screeninfo hga_fix __devinitdata = {
124 .id = "HGA", 124 .id = "HGA",
125 .type = FB_TYPE_PACKED_PIXELS, /* (not sure) */ 125 .type = FB_TYPE_PACKED_PIXELS, /* (not sure) */
126 .visual = FB_VISUAL_MONO10, 126 .visual = FB_VISUAL_MONO10,
@@ -276,7 +276,7 @@ static void hga_blank(int blank_mode)
276 spin_unlock_irqrestore(&hga_reg_lock, flags); 276 spin_unlock_irqrestore(&hga_reg_lock, flags);
277} 277}
278 278
279static int __init hga_card_detect(void) 279static int __devinit hga_card_detect(void)
280{ 280{
281 int count = 0; 281 int count = 0;
282 void __iomem *p, *q; 282 void __iomem *p, *q;
@@ -596,7 +596,7 @@ static int __devinit hgafb_probe(struct platform_device *pdev)
596 return 0; 596 return 0;
597} 597}
598 598
599static int hgafb_remove(struct platform_device *pdev) 599static int __devexit hgafb_remove(struct platform_device *pdev)
600{ 600{
601 struct fb_info *info = platform_get_drvdata(pdev); 601 struct fb_info *info = platform_get_drvdata(pdev);
602 602
@@ -621,7 +621,7 @@ static int hgafb_remove(struct platform_device *pdev)
621 621
622static struct platform_driver hgafb_driver = { 622static struct platform_driver hgafb_driver = {
623 .probe = hgafb_probe, 623 .probe = hgafb_probe,
624 .remove = hgafb_remove, 624 .remove = __devexit_p(hgafb_remove),
625 .driver = { 625 .driver = {
626 .name = "hgafb", 626 .name = "hgafb",
627 }, 627 },
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 393f3f3d3dfe..cfb8d6451014 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -30,14 +30,14 @@
30 30
31#define WIDTH 640 31#define WIDTH 640
32 32
33static struct fb_var_screeninfo hitfb_var __initdata = { 33static struct fb_var_screeninfo hitfb_var __devinitdata = {
34 .activate = FB_ACTIVATE_NOW, 34 .activate = FB_ACTIVATE_NOW,
35 .height = -1, 35 .height = -1,
36 .width = -1, 36 .width = -1,
37 .vmode = FB_VMODE_NONINTERLACED, 37 .vmode = FB_VMODE_NONINTERLACED,
38}; 38};
39 39
40static struct fb_fix_screeninfo hitfb_fix __initdata = { 40static struct fb_fix_screeninfo hitfb_fix __devinitdata = {
41 .id = "Hitachi HD64461", 41 .id = "Hitachi HD64461",
42 .type = FB_TYPE_PACKED_PIXELS, 42 .type = FB_TYPE_PACKED_PIXELS,
43 .accel = FB_ACCEL_NONE, 43 .accel = FB_ACCEL_NONE,
@@ -417,7 +417,7 @@ err_fb:
417 return ret; 417 return ret;
418} 418}
419 419
420static int __exit hitfb_remove(struct platform_device *dev) 420static int __devexit hitfb_remove(struct platform_device *dev)
421{ 421{
422 struct fb_info *info = platform_get_drvdata(dev); 422 struct fb_info *info = platform_get_drvdata(dev);
423 423
@@ -462,7 +462,7 @@ static const struct dev_pm_ops hitfb_dev_pm_ops = {
462 462
463static struct platform_driver hitfb_driver = { 463static struct platform_driver hitfb_driver = {
464 .probe = hitfb_probe, 464 .probe = hitfb_probe,
465 .remove = __exit_p(hitfb_remove), 465 .remove = __devexit_p(hitfb_remove),
466 .driver = { 466 .driver = {
467 .name = "hitfb", 467 .name = "hitfb",
468 .owner = THIS_MODULE, 468 .owner = THIS_MODULE,
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 40984551c927..6b51175629c7 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -371,10 +371,6 @@ struct intelfb_info {
371 ((dinfo)->chipset == INTEL_965G) || \ 371 ((dinfo)->chipset == INTEL_965G) || \
372 ((dinfo)->chipset == INTEL_965GM)) 372 ((dinfo)->chipset == INTEL_965GM))
373 373
374#ifndef FBIO_WAITFORVSYNC
375#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
376#endif
377
378/*** function prototypes ***/ 374/*** function prototypes ***/
379 375
380extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var); 376extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index 6bf0d460a738..d4cde79ea15e 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -667,7 +667,7 @@ release_irq:
667release_regs: 667release_regs:
668 iounmap(fbi->io); 668 iounmap(fbi->io);
669release_mem_region: 669release_mem_region:
670 release_mem_region((unsigned long)fbi->mem, size); 670 release_mem_region(res->start, size);
671free_fb: 671free_fb:
672 framebuffer_release(fbinfo); 672 framebuffer_release(fbinfo);
673 return ret; 673 return ret;
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 2b094dec4a56..46b430978bcc 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -631,7 +631,7 @@ static struct fb_ops s3c2410fb_ops = {
631 * cache. Once this area is remapped, all virtual memory 631 * cache. Once this area is remapped, all virtual memory
632 * access to the video memory should occur at the new region. 632 * access to the video memory should occur at the new region.
633 */ 633 */
634static int __init s3c2410fb_map_video_memory(struct fb_info *info) 634static int __devinit s3c2410fb_map_video_memory(struct fb_info *info)
635{ 635{
636 struct s3c2410fb_info *fbi = info->par; 636 struct s3c2410fb_info *fbi = info->par;
637 dma_addr_t map_dma; 637 dma_addr_t map_dma;
@@ -814,7 +814,7 @@ static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
814 814
815static char driver_name[] = "s3c2410fb"; 815static char driver_name[] = "s3c2410fb";
816 816
817static int __init s3c24xxfb_probe(struct platform_device *pdev, 817static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
818 enum s3c_drv_type drv_type) 818 enum s3c_drv_type drv_type)
819{ 819{
820 struct s3c2410fb_info *info; 820 struct s3c2410fb_info *info;
@@ -1018,7 +1018,7 @@ static int __devinit s3c2412fb_probe(struct platform_device *pdev)
1018/* 1018/*
1019 * Cleanup 1019 * Cleanup
1020 */ 1020 */
1021static int s3c2410fb_remove(struct platform_device *pdev) 1021static int __devexit s3c2410fb_remove(struct platform_device *pdev)
1022{ 1022{
1023 struct fb_info *fbinfo = platform_get_drvdata(pdev); 1023 struct fb_info *fbinfo = platform_get_drvdata(pdev);
1024 struct s3c2410fb_info *info = fbinfo->par; 1024 struct s3c2410fb_info *info = fbinfo->par;
@@ -1096,7 +1096,7 @@ static int s3c2410fb_resume(struct platform_device *dev)
1096 1096
1097static struct platform_driver s3c2410fb_driver = { 1097static struct platform_driver s3c2410fb_driver = {
1098 .probe = s3c2410fb_probe, 1098 .probe = s3c2410fb_probe,
1099 .remove = s3c2410fb_remove, 1099 .remove = __devexit_p(s3c2410fb_remove),
1100 .suspend = s3c2410fb_suspend, 1100 .suspend = s3c2410fb_suspend,
1101 .resume = s3c2410fb_resume, 1101 .resume = s3c2410fb_resume,
1102 .driver = { 1102 .driver = {
@@ -1107,7 +1107,7 @@ static struct platform_driver s3c2410fb_driver = {
1107 1107
1108static struct platform_driver s3c2412fb_driver = { 1108static struct platform_driver s3c2412fb_driver = {
1109 .probe = s3c2412fb_probe, 1109 .probe = s3c2412fb_probe,
1110 .remove = s3c2410fb_remove, 1110 .remove = __devexit_p(s3c2410fb_remove),
1111 .suspend = s3c2410fb_suspend, 1111 .suspend = s3c2410fb_suspend,
1112 .resume = s3c2410fb_resume, 1112 .resume = s3c2410fb_resume,
1113 .driver = { 1113 .driver = {
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index d4471b4c0374..dce8c97b4333 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -71,7 +71,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64",
71 "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", 71 "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
72 "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", 72 "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge",
73 "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", 73 "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
74 "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P"}; 74 "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P",
75 "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X"};
75 76
76#define CHIP_UNKNOWN 0x00 77#define CHIP_UNKNOWN 0x00
77#define CHIP_732_TRIO32 0x01 78#define CHIP_732_TRIO32 0x01
@@ -89,10 +90,14 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64",
89#define CHIP_356_VIRGE_GX2 0x0D 90#define CHIP_356_VIRGE_GX2 0x0D
90#define CHIP_357_VIRGE_GX2P 0x0E 91#define CHIP_357_VIRGE_GX2P 0x0E
91#define CHIP_359_VIRGE_GX2P 0x0F 92#define CHIP_359_VIRGE_GX2P 0x0F
93#define CHIP_360_TRIO3D_1X 0x10
94#define CHIP_362_TRIO3D_2X 0x11
95#define CHIP_368_TRIO3D_2X 0x12
92 96
93#define CHIP_XXX_TRIO 0x80 97#define CHIP_XXX_TRIO 0x80
94#define CHIP_XXX_TRIO64V2_DXGX 0x81 98#define CHIP_XXX_TRIO64V2_DXGX 0x81
95#define CHIP_XXX_VIRGE_DXGX 0x82 99#define CHIP_XXX_VIRGE_DXGX 0x82
100#define CHIP_36X_TRIO3D_1X_2X 0x83
96 101
97#define CHIP_UNDECIDED_FLAG 0x80 102#define CHIP_UNDECIDED_FLAG 0x80
98#define CHIP_MASK 0xFF 103#define CHIP_MASK 0xFF
@@ -324,6 +329,7 @@ static void s3fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
324 329
325static void s3_set_pixclock(struct fb_info *info, u32 pixclock) 330static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
326{ 331{
332 struct s3fb_info *par = info->par;
327 u16 m, n, r; 333 u16 m, n, r;
328 u8 regval; 334 u8 regval;
329 int rv; 335 int rv;
@@ -339,7 +345,13 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
339 vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); 345 vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
340 346
341 /* Set S3 clock registers */ 347 /* Set S3 clock registers */
342 vga_wseq(NULL, 0x12, ((n - 2) | (r << 5))); 348 if (par->chip == CHIP_360_TRIO3D_1X ||
349 par->chip == CHIP_362_TRIO3D_2X ||
350 par->chip == CHIP_368_TRIO3D_2X) {
351 vga_wseq(NULL, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */
352 vga_wseq(NULL, 0x29, r >> 2); /* remaining highest bit of r */
353 } else
354 vga_wseq(NULL, 0x12, (n - 2) | (r << 5));
343 vga_wseq(NULL, 0x13, m - 2); 355 vga_wseq(NULL, 0x13, m - 2);
344 356
345 udelay(1000); 357 udelay(1000);
@@ -456,7 +468,7 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
456static int s3fb_set_par(struct fb_info *info) 468static int s3fb_set_par(struct fb_info *info)
457{ 469{
458 struct s3fb_info *par = info->par; 470 struct s3fb_info *par = info->par;
459 u32 value, mode, hmul, offset_value, screen_size, multiplex; 471 u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes;
460 u32 bpp = info->var.bits_per_pixel; 472 u32 bpp = info->var.bits_per_pixel;
461 473
462 if (bpp != 0) { 474 if (bpp != 0) {
@@ -518,7 +530,7 @@ static int s3fb_set_par(struct fb_info *info)
518 svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ 530 svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */
519 svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ 531 svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */
520 532
521 svga_wcrt_mask(0x5D, 0x00, 0x28); // Clear strange HSlen bits 533 svga_wcrt_mask(0x5D, 0x00, 0x28); /* Clear strange HSlen bits */
522 534
523/* svga_wcrt_mask(0x58, 0x03, 0x03); */ 535/* svga_wcrt_mask(0x58, 0x03, 0x03); */
524 536
@@ -530,10 +542,14 @@ static int s3fb_set_par(struct fb_info *info)
530 pr_debug("fb%d: offset register : %d\n", info->node, offset_value); 542 pr_debug("fb%d: offset register : %d\n", info->node, offset_value);
531 svga_wcrt_multi(s3_offset_regs, offset_value); 543 svga_wcrt_multi(s3_offset_regs, offset_value);
532 544
533 vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ 545 if (par->chip != CHIP_360_TRIO3D_1X &&
534 vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ 546 par->chip != CHIP_362_TRIO3D_2X &&
535 vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ 547 par->chip != CHIP_368_TRIO3D_2X) {
536 vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ 548 vga_wcrt(NULL, 0x54, 0x18); /* M parameter */
549 vga_wcrt(NULL, 0x60, 0xff); /* N parameter */
550 vga_wcrt(NULL, 0x61, 0xff); /* L parameter */
551 vga_wcrt(NULL, 0x62, 0xff); /* L parameter */
552 }
537 553
538 vga_wcrt(NULL, 0x3A, 0x35); 554 vga_wcrt(NULL, 0x3A, 0x35);
539 svga_wattr(0x33, 0x00); 555 svga_wattr(0x33, 0x00);
@@ -570,6 +586,16 @@ static int s3fb_set_par(struct fb_info *info)
570 vga_wcrt(NULL, 0x66, 0x90); 586 vga_wcrt(NULL, 0x66, 0x90);
571 } 587 }
572 588
589 if (par->chip == CHIP_360_TRIO3D_1X ||
590 par->chip == CHIP_362_TRIO3D_2X ||
591 par->chip == CHIP_368_TRIO3D_2X) {
592 dbytes = info->var.xres * ((bpp+7)/8);
593 vga_wcrt(NULL, 0x91, (dbytes + 7) / 8);
594 vga_wcrt(NULL, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80);
595
596 vga_wcrt(NULL, 0x66, 0x81);
597 }
598
573 svga_wcrt_mask(0x31, 0x00, 0x40); 599 svga_wcrt_mask(0x31, 0x00, 0x40);
574 multiplex = 0; 600 multiplex = 0;
575 hmul = 1; 601 hmul = 1;
@@ -615,11 +641,13 @@ static int s3fb_set_par(struct fb_info *info)
615 break; 641 break;
616 case 3: 642 case 3:
617 pr_debug("fb%d: 8 bit pseudocolor\n", info->node); 643 pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
618 if (info->var.pixclock > 20000) { 644 svga_wcrt_mask(0x50, 0x00, 0x30);
619 svga_wcrt_mask(0x50, 0x00, 0x30); 645 if (info->var.pixclock > 20000 ||
646 par->chip == CHIP_360_TRIO3D_1X ||
647 par->chip == CHIP_362_TRIO3D_2X ||
648 par->chip == CHIP_368_TRIO3D_2X)
620 svga_wcrt_mask(0x67, 0x00, 0xF0); 649 svga_wcrt_mask(0x67, 0x00, 0xF0);
621 } else { 650 else {
622 svga_wcrt_mask(0x50, 0x00, 0x30);
623 svga_wcrt_mask(0x67, 0x10, 0xF0); 651 svga_wcrt_mask(0x67, 0x10, 0xF0);
624 multiplex = 1; 652 multiplex = 1;
625 } 653 }
@@ -634,7 +662,10 @@ static int s3fb_set_par(struct fb_info *info)
634 } else { 662 } else {
635 svga_wcrt_mask(0x50, 0x10, 0x30); 663 svga_wcrt_mask(0x50, 0x10, 0x30);
636 svga_wcrt_mask(0x67, 0x30, 0xF0); 664 svga_wcrt_mask(0x67, 0x30, 0xF0);
637 hmul = 2; 665 if (par->chip != CHIP_360_TRIO3D_1X &&
666 par->chip != CHIP_362_TRIO3D_2X &&
667 par->chip != CHIP_368_TRIO3D_2X)
668 hmul = 2;
638 } 669 }
639 break; 670 break;
640 case 5: 671 case 5:
@@ -647,7 +678,10 @@ static int s3fb_set_par(struct fb_info *info)
647 } else { 678 } else {
648 svga_wcrt_mask(0x50, 0x10, 0x30); 679 svga_wcrt_mask(0x50, 0x10, 0x30);
649 svga_wcrt_mask(0x67, 0x50, 0xF0); 680 svga_wcrt_mask(0x67, 0x50, 0xF0);
650 hmul = 2; 681 if (par->chip != CHIP_360_TRIO3D_1X &&
682 par->chip != CHIP_362_TRIO3D_2X &&
683 par->chip != CHIP_368_TRIO3D_2X)
684 hmul = 2;
651 } 685 }
652 break; 686 break;
653 case 6: 687 case 6:
@@ -866,6 +900,17 @@ static int __devinit s3_identification(int chip)
866 return CHIP_385_VIRGE_GX; 900 return CHIP_385_VIRGE_GX;
867 } 901 }
868 902
903 if (chip == CHIP_36X_TRIO3D_1X_2X) {
904 switch (vga_rcrt(NULL, 0x2f)) {
905 case 0x00:
906 return CHIP_360_TRIO3D_1X;
907 case 0x01:
908 return CHIP_362_TRIO3D_2X;
909 case 0x02:
910 return CHIP_368_TRIO3D_2X;
911 }
912 }
913
869 return CHIP_UNKNOWN; 914 return CHIP_UNKNOWN;
870} 915}
871 916
@@ -930,17 +975,32 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
930 vga_wcrt(NULL, 0x38, 0x48); 975 vga_wcrt(NULL, 0x38, 0x48);
931 vga_wcrt(NULL, 0x39, 0xA5); 976 vga_wcrt(NULL, 0x39, 0xA5);
932 977
933 /* Find how many physical memory there is on card */ 978 /* Identify chip type */
934 /* 0x36 register is accessible even if other registers are locked */
935 regval = vga_rcrt(NULL, 0x36);
936 info->screen_size = s3_memsizes[regval >> 5] << 10;
937 info->fix.smem_len = info->screen_size;
938
939 par->chip = id->driver_data & CHIP_MASK; 979 par->chip = id->driver_data & CHIP_MASK;
940 par->rev = vga_rcrt(NULL, 0x2f); 980 par->rev = vga_rcrt(NULL, 0x2f);
941 if (par->chip & CHIP_UNDECIDED_FLAG) 981 if (par->chip & CHIP_UNDECIDED_FLAG)
942 par->chip = s3_identification(par->chip); 982 par->chip = s3_identification(par->chip);
943 983
984 /* Find how many physical memory there is on card */
985 /* 0x36 register is accessible even if other registers are locked */
986 regval = vga_rcrt(NULL, 0x36);
987 if (par->chip == CHIP_360_TRIO3D_1X ||
988 par->chip == CHIP_362_TRIO3D_2X ||
989 par->chip == CHIP_368_TRIO3D_2X) {
990 switch ((regval & 0xE0) >> 5) {
991 case 0: /* 8MB -- only 4MB usable for display */
992 case 1: /* 4MB with 32-bit bus */
993 case 2: /* 4MB */
994 info->screen_size = 4 << 20;
995 break;
996 case 6: /* 2MB */
997 info->screen_size = 2 << 20;
998 break;
999 }
1000 } else
1001 info->screen_size = s3_memsizes[regval >> 5] << 10;
1002 info->fix.smem_len = info->screen_size;
1003
944 /* Find MCLK frequency */ 1004 /* Find MCLK frequency */
945 regval = vga_rseq(NULL, 0x10); 1005 regval = vga_rseq(NULL, 0x10);
946 par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); 1006 par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2);
@@ -1131,6 +1191,7 @@ static struct pci_device_id s3_devices[] __devinitdata = {
1131 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, 1191 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2},
1132 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, 1192 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P},
1133 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, 1193 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
1194 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X},
1134 1195
1135 {0, 0, 0, 0, 0, 0, 0} 1196 {0, 0, 0, 0, 0, 0, 0}
1136}; 1197};
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 7a3a5e28eca1..53455f295510 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -47,7 +47,7 @@ static int ywrap = 0;
47 47
48static int flatpanel_id = -1; 48static int flatpanel_id = -1;
49 49
50static struct fb_fix_screeninfo sgivwfb_fix __initdata = { 50static struct fb_fix_screeninfo sgivwfb_fix __devinitdata = {
51 .id = "SGI Vis WS FB", 51 .id = "SGI Vis WS FB",
52 .type = FB_TYPE_PACKED_PIXELS, 52 .type = FB_TYPE_PACKED_PIXELS,
53 .visual = FB_VISUAL_PSEUDOCOLOR, 53 .visual = FB_VISUAL_PSEUDOCOLOR,
@@ -57,7 +57,7 @@ static struct fb_fix_screeninfo sgivwfb_fix __initdata = {
57 .line_length = 640, 57 .line_length = 640,
58}; 58};
59 59
60static struct fb_var_screeninfo sgivwfb_var __initdata = { 60static struct fb_var_screeninfo sgivwfb_var __devinitdata = {
61 /* 640x480, 8 bpp */ 61 /* 640x480, 8 bpp */
62 .xres = 640, 62 .xres = 640,
63 .yres = 480, 63 .yres = 480,
@@ -79,7 +79,7 @@ static struct fb_var_screeninfo sgivwfb_var __initdata = {
79 .vmode = FB_VMODE_NONINTERLACED 79 .vmode = FB_VMODE_NONINTERLACED
80}; 80};
81 81
82static struct fb_var_screeninfo sgivwfb_var1600sw __initdata = { 82static struct fb_var_screeninfo sgivwfb_var1600sw __devinitdata = {
83 /* 1600x1024, 8 bpp */ 83 /* 1600x1024, 8 bpp */
84 .xres = 1600, 84 .xres = 1600,
85 .yres = 1024, 85 .yres = 1024,
@@ -825,7 +825,7 @@ fail_ioremap_regs:
825 return -ENXIO; 825 return -ENXIO;
826} 826}
827 827
828static int sgivwfb_remove(struct platform_device *dev) 828static int __devexit sgivwfb_remove(struct platform_device *dev)
829{ 829{
830 struct fb_info *info = platform_get_drvdata(dev); 830 struct fb_info *info = platform_get_drvdata(dev);
831 831
@@ -845,7 +845,7 @@ static int sgivwfb_remove(struct platform_device *dev)
845 845
846static struct platform_driver sgivwfb_driver = { 846static struct platform_driver sgivwfb_driver = {
847 .probe = sgivwfb_probe, 847 .probe = sgivwfb_probe,
848 .remove = sgivwfb_remove, 848 .remove = __devexit_p(sgivwfb_remove),
849 .driver = { 849 .driver = {
850 .name = "sgivwfb", 850 .name = "sgivwfb",
851 }, 851 },
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index a531a0f7cdf2..559bf1727a2b 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1845,7 +1845,7 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1845 1845
1846 memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 1846 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1847 1847
1848 strcpy(fix->id, ivideo->myid); 1848 strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
1849 1849
1850 mutex_lock(&info->mm_lock); 1850 mutex_lock(&info->mm_lock);
1851 fix->smem_start = ivideo->video_base + ivideo->video_offset; 1851 fix->smem_start = ivideo->video_base + ivideo->video_offset;
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 9b5532b4de35..bc67251f1a2f 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -78,7 +78,7 @@ static void rvfree(void *mem, unsigned long size)
78 vfree(mem); 78 vfree(mem);
79} 79}
80 80
81static struct fb_var_screeninfo vfb_default __initdata = { 81static struct fb_var_screeninfo vfb_default __devinitdata = {
82 .xres = 640, 82 .xres = 640,
83 .yres = 480, 83 .yres = 480,
84 .xres_virtual = 640, 84 .xres_virtual = 640,
@@ -100,7 +100,7 @@ static struct fb_var_screeninfo vfb_default __initdata = {
100 .vmode = FB_VMODE_NONINTERLACED, 100 .vmode = FB_VMODE_NONINTERLACED,
101}; 101};
102 102
103static struct fb_fix_screeninfo vfb_fix __initdata = { 103static struct fb_fix_screeninfo vfb_fix __devinitdata = {
104 .id = "Virtual FB", 104 .id = "Virtual FB",
105 .type = FB_TYPE_PACKED_PIXELS, 105 .type = FB_TYPE_PACKED_PIXELS,
106 .visual = FB_VISUAL_PSEUDOCOLOR, 106 .visual = FB_VISUAL_PSEUDOCOLOR,
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 149c47ac7e93..28ccab44a391 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -65,7 +65,7 @@ struct vga16fb_par {
65 65
66/* --------------------------------------------------------------------- */ 66/* --------------------------------------------------------------------- */
67 67
68static struct fb_var_screeninfo vga16fb_defined __initdata = { 68static struct fb_var_screeninfo vga16fb_defined __devinitdata = {
69 .xres = 640, 69 .xres = 640,
70 .yres = 480, 70 .yres = 480,
71 .xres_virtual = 640, 71 .xres_virtual = 640,
@@ -85,7 +85,7 @@ static struct fb_var_screeninfo vga16fb_defined __initdata = {
85}; 85};
86 86
87/* name should not depend on EGA/VGA */ 87/* name should not depend on EGA/VGA */
88static struct fb_fix_screeninfo vga16fb_fix __initdata = { 88static struct fb_fix_screeninfo vga16fb_fix __devinitdata = {
89 .id = "VGA16 VGA", 89 .id = "VGA16 VGA",
90 .smem_start = VGA_FB_PHYS, 90 .smem_start = VGA_FB_PHYS,
91 .smem_len = VGA_FB_PHYS_LEN, 91 .smem_len = VGA_FB_PHYS_LEN,
@@ -1287,7 +1287,7 @@ static struct fb_ops vga16fb_ops = {
1287}; 1287};
1288 1288
1289#ifndef MODULE 1289#ifndef MODULE
1290static int vga16fb_setup(char *options) 1290static int __init vga16fb_setup(char *options)
1291{ 1291{
1292 char *this_opt; 1292 char *this_opt;
1293 1293
@@ -1393,7 +1393,7 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
1393 return ret; 1393 return ret;
1394} 1394}
1395 1395
1396static int vga16fb_remove(struct platform_device *dev) 1396static int __devexit vga16fb_remove(struct platform_device *dev)
1397{ 1397{
1398 struct fb_info *info = platform_get_drvdata(dev); 1398 struct fb_info *info = platform_get_drvdata(dev);
1399 1399
@@ -1405,7 +1405,7 @@ static int vga16fb_remove(struct platform_device *dev)
1405 1405
1406static struct platform_driver vga16fb_driver = { 1406static struct platform_driver vga16fb_driver = {
1407 .probe = vga16fb_probe, 1407 .probe = vga16fb_probe,
1408 .remove = vga16fb_remove, 1408 .remove = __devexit_p(vga16fb_remove),
1409 .driver = { 1409 .driver = {
1410 .name = "vga16fb", 1410 .name = "vga16fb",
1411 }, 1411 },
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 2bc40e682f95..1082541358f0 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -578,14 +578,9 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
578 break; 578 break;
579 579
580 case VIAFB_SET_GAMMA_LUT: 580 case VIAFB_SET_GAMMA_LUT:
581 viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL); 581 viafb_gamma_table = memdup_user(argp, 256 * sizeof(u32));
582 if (!viafb_gamma_table) 582 if (IS_ERR(viafb_gamma_table))
583 return -ENOMEM; 583 return PTR_ERR(viafb_gamma_table);
584 if (copy_from_user(viafb_gamma_table, argp,
585 256 * sizeof(u32))) {
586 kfree(viafb_gamma_table);
587 return -EFAULT;
588 }
589 viafb_set_gamma_table(viafb_bpp, viafb_gamma_table); 584 viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
590 kfree(viafb_gamma_table); 585 kfree(viafb_gamma_table);
591 break; 586 break;
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 31b0e17ed090..e66b8b19ce5d 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -53,7 +53,7 @@ static void w100_update_enable(void);
53static void w100_update_disable(void); 53static void w100_update_disable(void);
54static void calc_hsync(struct w100fb_par *par); 54static void calc_hsync(struct w100fb_par *par);
55static void w100_init_graphic_engine(struct w100fb_par *par); 55static void w100_init_graphic_engine(struct w100fb_par *par);
56struct w100_pll_info *w100_get_xtal_table(unsigned int freq); 56struct w100_pll_info *w100_get_xtal_table(unsigned int freq) __devinit;
57 57
58/* Pseudo palette size */ 58/* Pseudo palette size */
59#define MAX_PALETTES 16 59#define MAX_PALETTES 16
@@ -782,7 +782,7 @@ out:
782} 782}
783 783
784 784
785static int w100fb_remove(struct platform_device *pdev) 785static int __devexit w100fb_remove(struct platform_device *pdev)
786{ 786{
787 struct fb_info *info = platform_get_drvdata(pdev); 787 struct fb_info *info = platform_get_drvdata(pdev);
788 struct w100fb_par *par=info->par; 788 struct w100fb_par *par=info->par;
@@ -1020,7 +1020,7 @@ static struct pll_entries {
1020 { 0 }, 1020 { 0 },
1021}; 1021};
1022 1022
1023struct w100_pll_info *w100_get_xtal_table(unsigned int freq) 1023struct w100_pll_info __devinit *w100_get_xtal_table(unsigned int freq)
1024{ 1024{
1025 struct pll_entries *pll_entry = w100_pll_tables; 1025 struct pll_entries *pll_entry = w100_pll_tables;
1026 1026
@@ -1611,7 +1611,7 @@ static void w100_vsync(void)
1611 1611
1612static struct platform_driver w100fb_driver = { 1612static struct platform_driver w100fb_driver = {
1613 .probe = w100fb_probe, 1613 .probe = w100fb_probe,
1614 .remove = w100fb_remove, 1614 .remove = __devexit_p(w100fb_remove),
1615 .suspend = w100fb_suspend, 1615 .suspend = w100fb_suspend,
1616 .resume = w100fb_resume, 1616 .resume = w100fb_resume,
1617 .driver = { 1617 .driver = {
@@ -1619,7 +1619,7 @@ static struct platform_driver w100fb_driver = {
1619 }, 1619 },
1620}; 1620};
1621 1621
1622int __devinit w100fb_init(void) 1622int __init w100fb_init(void)
1623{ 1623{
1624 return platform_driver_register(&w100fb_driver); 1624 return platform_driver_register(&w100fb_driver);
1625} 1625}