blob: 74cb0eb453113e46856e9e224fba0f9873ca3926 [file] [log] [blame]
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +02001/*
2 * LCD panel driver for Sharp LS037V7DW01
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/module.h>
21#include <linux/delay.h>
22#include <linux/device.h>
Vaibhav Hiremath2b88c5b2010-04-15 16:00:00 +020023#include <linux/fb.h>
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +020024#include <linux/err.h>
Vaibhav Hiremath2b88c5b2010-04-15 16:00:00 +020025#include <linux/slab.h>
Tomi Valkeinen31030982013-04-03 11:39:19 +030026#include <linux/gpio.h>
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +020027
Tomi Valkeinena0b38cc2011-05-11 14:05:07 +030028#include <video/omapdss.h>
Tomi Valkeinen31030982013-04-03 11:39:19 +030029#include <video/omap-panel-data.h>
Vaibhav Hiremath2b88c5b2010-04-15 16:00:00 +020030
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +020031static struct omap_video_timings sharp_ls_timings = {
32 .x_res = 480,
33 .y_res = 640,
34
35 .pixel_clock = 19200,
36
37 .hsw = 2,
38 .hfp = 1,
39 .hbp = 28,
40
41 .vsw = 1,
42 .vfp = 1,
43 .vbp = 1,
Archit Tanejaa8d5e412012-06-25 12:26:38 +053044
45 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
46 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
47 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
48 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
49 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +020050};
51
Tomi Valkeinen31030982013-04-03 11:39:19 +030052static inline struct panel_sharp_ls037v7dw01_data
53*get_panel_data(const struct omap_dss_device *dssdev)
54{
55 return (struct panel_sharp_ls037v7dw01_data *) dssdev->data;
56}
Vaibhav Hiremath2b88c5b2010-04-15 16:00:00 +020057
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +020058static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
59{
Tomi Valkeinen31030982013-04-03 11:39:19 +030060 struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
61 int r;
62
63 if (!pd)
64 return -EINVAL;
Vaibhav Hiremath2b88c5b2010-04-15 16:00:00 +020065
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +020066 dssdev->panel.timings = sharp_ls_timings;
67
Tomi Valkeinen31030982013-04-03 11:39:19 +030068 if (gpio_is_valid(pd->mo_gpio)) {
69 r = devm_gpio_request_one(&dssdev->dev, pd->mo_gpio,
70 GPIOF_OUT_INIT_LOW, "lcd MO");
71 if (r)
72 return r;
73 }
Vaibhav Hiremath2b88c5b2010-04-15 16:00:00 +020074
Tomi Valkeinen31030982013-04-03 11:39:19 +030075 if (gpio_is_valid(pd->lr_gpio)) {
76 r = devm_gpio_request_one(&dssdev->dev, pd->lr_gpio,
77 GPIOF_OUT_INIT_HIGH, "lcd LR");
78 if (r)
79 return r;
80 }
81
82 if (gpio_is_valid(pd->ud_gpio)) {
83 r = devm_gpio_request_one(&dssdev->dev, pd->ud_gpio,
84 GPIOF_OUT_INIT_HIGH, "lcd UD");
85 if (r)
86 return r;
87 }
88
89 if (gpio_is_valid(pd->resb_gpio)) {
90 r = devm_gpio_request_one(&dssdev->dev, pd->resb_gpio,
91 GPIOF_OUT_INIT_LOW, "lcd RESB");
92 if (r)
93 return r;
94 }
95
96 if (gpio_is_valid(pd->ini_gpio)) {
97 r = devm_gpio_request_one(&dssdev->dev, pd->ini_gpio,
98 GPIOF_OUT_INIT_LOW, "lcd INI");
99 if (r)
100 return r;
101 }
Vaibhav Hiremath2b88c5b2010-04-15 16:00:00 +0200102
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200103 return 0;
104}
105
Tomi Valkeinen14e4d782011-03-31 12:03:51 +0300106static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev)
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200107{
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200108}
109
Tomi Valkeinen37ac60e2010-01-12 15:12:07 +0200110static int sharp_ls_power_on(struct omap_dss_device *dssdev)
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200111{
Tomi Valkeinen31030982013-04-03 11:39:19 +0300112 struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200113 int r = 0;
114
Stanley.Miao18016e32010-09-03 05:03:48 +0200115 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
116 return 0;
117
Archit Tanejac4991442012-08-08 14:28:54 +0530118 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
Archit Tanejac6b393d2012-07-06 15:30:52 +0530119 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
Archit Tanejac4991442012-08-08 14:28:54 +0530120
Tomi Valkeinen37ac60e2010-01-12 15:12:07 +0200121 r = omapdss_dpi_display_enable(dssdev);
122 if (r)
123 goto err0;
124
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200125 /* wait couple of vsyncs until enabling the LCD */
126 msleep(50);
127
Tomi Valkeinen31030982013-04-03 11:39:19 +0300128 if (gpio_is_valid(pd->resb_gpio))
129 gpio_set_value_cansleep(pd->resb_gpio, 1);
130
131 if (gpio_is_valid(pd->ini_gpio))
132 gpio_set_value_cansleep(pd->ini_gpio, 1);
133
Tomi Valkeinen37ac60e2010-01-12 15:12:07 +0200134 return 0;
Tomi Valkeinen37ac60e2010-01-12 15:12:07 +0200135err0:
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200136 return r;
137}
138
Tomi Valkeinen37ac60e2010-01-12 15:12:07 +0200139static void sharp_ls_power_off(struct omap_dss_device *dssdev)
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200140{
Tomi Valkeinen31030982013-04-03 11:39:19 +0300141 struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
142
Stanley.Miao18016e32010-09-03 05:03:48 +0200143 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
144 return;
145
Tomi Valkeinen31030982013-04-03 11:39:19 +0300146 if (gpio_is_valid(pd->ini_gpio))
147 gpio_set_value_cansleep(pd->ini_gpio, 0);
148
149 if (gpio_is_valid(pd->resb_gpio))
150 gpio_set_value_cansleep(pd->resb_gpio, 0);
151
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200152 /* wait at least 5 vsyncs after disabling the LCD */
153
154 msleep(100);
Tomi Valkeinen37ac60e2010-01-12 15:12:07 +0200155
156 omapdss_dpi_display_disable(dssdev);
157}
158
159static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
160{
161 int r;
162 r = sharp_ls_power_on(dssdev);
163 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
164 return r;
165}
166
167static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
168{
169 sharp_ls_power_off(dssdev);
170 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200171}
172
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200173static struct omap_dss_driver sharp_ls_driver = {
174 .probe = sharp_ls_panel_probe,
Tomi Valkeinen14e4d782011-03-31 12:03:51 +0300175 .remove = __exit_p(sharp_ls_panel_remove),
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200176
177 .enable = sharp_ls_panel_enable,
178 .disable = sharp_ls_panel_disable,
Tomi Valkeinen3b8f29b2009-12-09 18:19:42 +0200179
180 .driver = {
181 .name = "sharp_ls_panel",
182 .owner = THIS_MODULE,
183 },
184};
185
186static int __init sharp_ls_panel_drv_init(void)
187{
188 return omap_dss_register_driver(&sharp_ls_driver);
189}
190
191static void __exit sharp_ls_panel_drv_exit(void)
192{
193 omap_dss_unregister_driver(&sharp_ls_driver);
194}
195
196module_init(sharp_ls_panel_drv_init);
197module_exit(sharp_ls_panel_drv_exit);
198MODULE_LICENSE("GPL");