2 * Support for NEC-nl8048hl11-01b panel driver
4 * Copyright (C) 2010 Texas Instruments Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <linux/module.h>
20 #include <linux/delay.h>
21 #include <linux/spi/spi.h>
22 #include <linux/backlight.h>
25 #include <video/omapdss.h>
30 * NEC PIX Clock Ratings
31 * MIN:21.8MHz TYP:23.8MHz MAX:25.7MHz
33 #define LCD_PIXEL_CLOCK 23800
35 struct nec_8048_data
{
36 struct backlight_device
*bl
;
42 } nec_8048_init_seq
[] = {
43 { 3, 0x01 }, { 0, 0x00 }, { 1, 0x01 }, { 4, 0x00 }, { 5, 0x14 },
44 { 6, 0x24 }, { 16, 0xD7 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x55 },
45 { 20, 0x01 }, { 21, 0x70 }, { 22, 0x1E }, { 23, 0x25 }, { 24, 0x25 },
46 { 25, 0x02 }, { 26, 0x02 }, { 27, 0xA0 }, { 32, 0x2F }, { 33, 0x0F },
47 { 34, 0x0F }, { 35, 0x0F }, { 36, 0x0F }, { 37, 0x0F }, { 38, 0x0F },
48 { 39, 0x00 }, { 40, 0x02 }, { 41, 0x02 }, { 42, 0x02 }, { 43, 0x0F },
49 { 44, 0x0F }, { 45, 0x0F }, { 46, 0x0F }, { 47, 0x0F }, { 48, 0x0F },
50 { 49, 0x0F }, { 50, 0x00 }, { 51, 0x02 }, { 52, 0x02 }, { 53, 0x02 },
51 { 80, 0x0C }, { 83, 0x42 }, { 84, 0x42 }, { 85, 0x41 }, { 86, 0x14 },
52 { 89, 0x88 }, { 90, 0x01 }, { 91, 0x00 }, { 92, 0x02 }, { 93, 0x0C },
53 { 94, 0x1C }, { 95, 0x27 }, { 98, 0x49 }, { 99, 0x27 }, { 102, 0x76 },
54 { 103, 0x27 }, { 112, 0x01 }, { 113, 0x0E }, { 114, 0x02 },
55 { 115, 0x0C }, { 118, 0x0C }, { 121, 0x30 }, { 130, 0x00 },
56 { 131, 0x00 }, { 132, 0xFC }, { 134, 0x00 }, { 136, 0x00 },
57 { 138, 0x00 }, { 139, 0x00 }, { 140, 0x00 }, { 141, 0xFC },
58 { 143, 0x00 }, { 145, 0x00 }, { 147, 0x00 }, { 148, 0x00 },
59 { 149, 0x00 }, { 150, 0xFC }, { 152, 0x00 }, { 154, 0x00 },
60 { 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 },
64 * NEC NL8048HL11-01B Manual
65 * defines HFB, HSW, HBP, VFP, VSW, VBP as shown below
68 static struct omap_video_timings nec_8048_panel_timings
= {
69 /* 800 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
72 .pixel_clock
= LCD_PIXEL_CLOCK
,
81 static int nec_8048_bl_update_status(struct backlight_device
*bl
)
83 struct omap_dss_device
*dssdev
= dev_get_drvdata(&bl
->dev
);
86 if (!dssdev
->set_backlight
)
89 if (bl
->props
.fb_blank
== FB_BLANK_UNBLANK
&&
90 bl
->props
.power
== FB_BLANK_UNBLANK
)
91 level
= bl
->props
.brightness
;
95 return dssdev
->set_backlight(dssdev
, level
);
98 static int nec_8048_bl_get_brightness(struct backlight_device
*bl
)
100 if (bl
->props
.fb_blank
== FB_BLANK_UNBLANK
&&
101 bl
->props
.power
== FB_BLANK_UNBLANK
)
102 return bl
->props
.brightness
;
107 static const struct backlight_ops nec_8048_bl_ops
= {
108 .get_brightness
= nec_8048_bl_get_brightness
,
109 .update_status
= nec_8048_bl_update_status
,
112 static int nec_8048_panel_probe(struct omap_dss_device
*dssdev
)
114 struct backlight_device
*bl
;
115 struct nec_8048_data
*necd
;
116 struct backlight_properties props
;
119 dssdev
->panel
.config
= OMAP_DSS_LCD_TFT
| OMAP_DSS_LCD_IVS
|
120 OMAP_DSS_LCD_IHS
| OMAP_DSS_LCD_RF
|
122 dssdev
->panel
.timings
= nec_8048_panel_timings
;
124 necd
= kzalloc(sizeof(*necd
), GFP_KERNEL
);
128 dev_set_drvdata(&dssdev
->dev
, necd
);
130 memset(&props
, 0, sizeof(struct backlight_properties
));
131 props
.max_brightness
= 255;
133 bl
= backlight_device_register("nec-8048", &dssdev
->dev
, dssdev
,
134 &nec_8048_bl_ops
, &props
);
142 bl
->props
.fb_blank
= FB_BLANK_UNBLANK
;
143 bl
->props
.power
= FB_BLANK_UNBLANK
;
144 bl
->props
.max_brightness
= dssdev
->max_backlight_level
;
145 bl
->props
.brightness
= dssdev
->max_backlight_level
;
147 r
= nec_8048_bl_update_status(bl
);
149 dev_err(&dssdev
->dev
, "failed to set lcd brightness\n");
154 static void nec_8048_panel_remove(struct omap_dss_device
*dssdev
)
156 struct nec_8048_data
*necd
= dev_get_drvdata(&dssdev
->dev
);
157 struct backlight_device
*bl
= necd
->bl
;
159 bl
->props
.power
= FB_BLANK_POWERDOWN
;
160 nec_8048_bl_update_status(bl
);
161 backlight_device_unregister(bl
);
166 static int nec_8048_panel_power_on(struct omap_dss_device
*dssdev
)
169 struct nec_8048_data
*necd
= dev_get_drvdata(&dssdev
->dev
);
170 struct backlight_device
*bl
= necd
->bl
;
172 if (dssdev
->state
== OMAP_DSS_DISPLAY_ACTIVE
)
175 r
= omapdss_dpi_display_enable(dssdev
);
179 if (dssdev
->platform_enable
) {
180 r
= dssdev
->platform_enable(dssdev
);
185 r
= nec_8048_bl_update_status(bl
);
187 dev_err(&dssdev
->dev
, "failed to set lcd brightness\n");
191 omapdss_dpi_display_disable(dssdev
);
196 static void nec_8048_panel_power_off(struct omap_dss_device
*dssdev
)
198 struct nec_8048_data
*necd
= dev_get_drvdata(&dssdev
->dev
);
199 struct backlight_device
*bl
= necd
->bl
;
201 if (dssdev
->state
!= OMAP_DSS_DISPLAY_ACTIVE
)
204 bl
->props
.brightness
= 0;
205 nec_8048_bl_update_status(bl
);
207 if (dssdev
->platform_disable
)
208 dssdev
->platform_disable(dssdev
);
210 omapdss_dpi_display_disable(dssdev
);
213 static int nec_8048_panel_enable(struct omap_dss_device
*dssdev
)
217 r
= nec_8048_panel_power_on(dssdev
);
221 dssdev
->state
= OMAP_DSS_DISPLAY_ACTIVE
;
226 static void nec_8048_panel_disable(struct omap_dss_device
*dssdev
)
228 nec_8048_panel_power_off(dssdev
);
230 dssdev
->state
= OMAP_DSS_DISPLAY_DISABLED
;
233 static int nec_8048_panel_suspend(struct omap_dss_device
*dssdev
)
235 nec_8048_panel_power_off(dssdev
);
237 dssdev
->state
= OMAP_DSS_DISPLAY_SUSPENDED
;
242 static int nec_8048_panel_resume(struct omap_dss_device
*dssdev
)
246 r
= nec_8048_panel_power_on(dssdev
);
250 dssdev
->state
= OMAP_DSS_DISPLAY_ACTIVE
;
255 static int nec_8048_recommended_bpp(struct omap_dss_device
*dssdev
)
260 static struct omap_dss_driver nec_8048_driver
= {
261 .probe
= nec_8048_panel_probe
,
262 .remove
= nec_8048_panel_remove
,
263 .enable
= nec_8048_panel_enable
,
264 .disable
= nec_8048_panel_disable
,
265 .suspend
= nec_8048_panel_suspend
,
266 .resume
= nec_8048_panel_resume
,
267 .get_recommended_bpp
= nec_8048_recommended_bpp
,
270 .name
= "NEC_8048_panel",
271 .owner
= THIS_MODULE
,
275 static int nec_8048_spi_send(struct spi_device
*spi
, unsigned char reg_addr
,
276 unsigned char reg_data
)
279 unsigned int cmd
= 0, data
= 0;
281 cmd
= 0x0000 | reg_addr
; /* register address write */
282 data
= 0x0100 | reg_data
; /* register data write */
283 data
= (cmd
<< 16) | data
;
285 ret
= spi_write(spi
, (unsigned char *)&data
, 4);
287 pr_err("error in spi_write %x\n", data
);
292 static int init_nec_8048_wvga_lcd(struct spi_device
*spi
)
295 /* Initialization Sequence */
296 /* nec_8048_spi_send(spi, REG, VAL) */
297 for (i
= 0; i
< (ARRAY_SIZE(nec_8048_init_seq
) - 1); i
++)
298 nec_8048_spi_send(spi
, nec_8048_init_seq
[i
].addr
,
299 nec_8048_init_seq
[i
].dat
);
301 nec_8048_spi_send(spi
, nec_8048_init_seq
[i
].addr
,
302 nec_8048_init_seq
[i
].dat
);
306 static int nec_8048_spi_probe(struct spi_device
*spi
)
308 spi
->mode
= SPI_MODE_0
;
309 spi
->bits_per_word
= 32;
312 init_nec_8048_wvga_lcd(spi
);
314 return omap_dss_register_driver(&nec_8048_driver
);
317 static int nec_8048_spi_remove(struct spi_device
*spi
)
319 omap_dss_unregister_driver(&nec_8048_driver
);
324 static int nec_8048_spi_suspend(struct spi_device
*spi
, pm_message_t mesg
)
326 nec_8048_spi_send(spi
, 2, 0x01);
332 static int nec_8048_spi_resume(struct spi_device
*spi
)
334 /* reinitialize the panel */
336 nec_8048_spi_send(spi
, 2, 0x00);
337 init_nec_8048_wvga_lcd(spi
);
342 static struct spi_driver nec_8048_spi_driver
= {
343 .probe
= nec_8048_spi_probe
,
344 .remove
= __devexit_p(nec_8048_spi_remove
),
345 .suspend
= nec_8048_spi_suspend
,
346 .resume
= nec_8048_spi_resume
,
348 .name
= "nec_8048_spi",
349 .owner
= THIS_MODULE
,
353 static int __init
nec_8048_lcd_init(void)
355 return spi_register_driver(&nec_8048_spi_driver
);
358 static void __exit
nec_8048_lcd_exit(void)
360 return spi_unregister_driver(&nec_8048_spi_driver
);
363 module_init(nec_8048_lcd_init
);
364 module_exit(nec_8048_lcd_exit
);
365 MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
366 MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver");
367 MODULE_LICENSE("GPL");