2 * LCD panel driver for Sharp LS037V7DW01
4 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
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.
12 #include <linux/delay.h>
13 #include <linux/gpio/consumer.h>
14 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/slab.h>
18 #include <linux/regulator/consumer.h>
20 #include "../dss/omapdss.h"
22 struct panel_drv_data
{
23 struct omap_dss_device dssdev
;
24 struct regulator
*vcc
;
28 struct gpio_desc
*resb_gpio
; /* low = reset active min 20 us */
29 struct gpio_desc
*ini_gpio
; /* high = power on */
30 struct gpio_desc
*mo_gpio
; /* low = 480x640, high = 240x320 */
31 struct gpio_desc
*lr_gpio
; /* high = conventional horizontal scanning */
32 struct gpio_desc
*ud_gpio
; /* high = conventional vertical scanning */
35 static const struct videomode sharp_ls_vm
= {
39 .pixelclock
= 19200000,
49 .flags
= DISPLAY_FLAGS_HSYNC_LOW
| DISPLAY_FLAGS_VSYNC_LOW
,
52 #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
54 static int sharp_ls_connect(struct omap_dss_device
*src
,
55 struct omap_dss_device
*dst
)
60 static void sharp_ls_disconnect(struct omap_dss_device
*src
,
61 struct omap_dss_device
*dst
)
65 static int sharp_ls_enable(struct omap_dss_device
*dssdev
)
67 struct panel_drv_data
*ddata
= to_panel_data(dssdev
);
68 struct omap_dss_device
*src
= dssdev
->src
;
71 if (!omapdss_device_is_connected(dssdev
))
74 if (omapdss_device_is_enabled(dssdev
))
78 r
= regulator_enable(ddata
->vcc
);
83 r
= src
->ops
->enable(src
);
85 regulator_disable(ddata
->vcc
);
89 /* wait couple of vsyncs until enabling the LCD */
93 gpiod_set_value_cansleep(ddata
->resb_gpio
, 1);
96 gpiod_set_value_cansleep(ddata
->ini_gpio
, 1);
98 dssdev
->state
= OMAP_DSS_DISPLAY_ACTIVE
;
103 static void sharp_ls_disable(struct omap_dss_device
*dssdev
)
105 struct panel_drv_data
*ddata
= to_panel_data(dssdev
);
106 struct omap_dss_device
*src
= dssdev
->src
;
108 if (!omapdss_device_is_enabled(dssdev
))
112 gpiod_set_value_cansleep(ddata
->ini_gpio
, 0);
114 if (ddata
->resb_gpio
)
115 gpiod_set_value_cansleep(ddata
->resb_gpio
, 0);
117 /* wait at least 5 vsyncs after disabling the LCD */
121 src
->ops
->disable(src
);
124 regulator_disable(ddata
->vcc
);
126 dssdev
->state
= OMAP_DSS_DISPLAY_DISABLED
;
129 static void sharp_ls_get_timings(struct omap_dss_device
*dssdev
,
130 struct videomode
*vm
)
132 struct panel_drv_data
*ddata
= to_panel_data(dssdev
);
137 static const struct omap_dss_device_ops sharp_ls_ops
= {
138 .connect
= sharp_ls_connect
,
139 .disconnect
= sharp_ls_disconnect
,
141 .enable
= sharp_ls_enable
,
142 .disable
= sharp_ls_disable
,
144 .get_timings
= sharp_ls_get_timings
,
147 static int sharp_ls_get_gpio_of(struct device
*dev
, int index
, int val
,
148 const char *desc
, struct gpio_desc
**gpiod
)
150 struct gpio_desc
*gd
;
154 gd
= devm_gpiod_get_index(dev
, desc
, index
, GPIOD_OUT_LOW
);
162 static int sharp_ls_probe_of(struct platform_device
*pdev
)
164 struct panel_drv_data
*ddata
= platform_get_drvdata(pdev
);
167 ddata
->vcc
= devm_regulator_get(&pdev
->dev
, "envdd");
168 if (IS_ERR(ddata
->vcc
)) {
169 dev_err(&pdev
->dev
, "failed to get regulator\n");
170 return PTR_ERR(ddata
->vcc
);
174 r
= sharp_ls_get_gpio_of(&pdev
->dev
, 0, 0, "enable", &ddata
->ini_gpio
);
179 r
= sharp_ls_get_gpio_of(&pdev
->dev
, 0, 0, "reset", &ddata
->resb_gpio
);
184 r
= sharp_ls_get_gpio_of(&pdev
->dev
, 0, 0, "mode", &ddata
->mo_gpio
);
189 r
= sharp_ls_get_gpio_of(&pdev
->dev
, 1, 1, "mode", &ddata
->lr_gpio
);
194 r
= sharp_ls_get_gpio_of(&pdev
->dev
, 2, 1, "mode", &ddata
->ud_gpio
);
201 static int sharp_ls_probe(struct platform_device
*pdev
)
203 struct panel_drv_data
*ddata
;
204 struct omap_dss_device
*dssdev
;
207 ddata
= devm_kzalloc(&pdev
->dev
, sizeof(*ddata
), GFP_KERNEL
);
211 platform_set_drvdata(pdev
, ddata
);
213 r
= sharp_ls_probe_of(pdev
);
217 ddata
->vm
= sharp_ls_vm
;
219 dssdev
= &ddata
->dssdev
;
220 dssdev
->dev
= &pdev
->dev
;
221 dssdev
->ops
= &sharp_ls_ops
;
222 dssdev
->type
= OMAP_DISPLAY_TYPE_DPI
;
223 dssdev
->owner
= THIS_MODULE
;
224 dssdev
->of_ports
= BIT(0);
227 * Note: According to the panel documentation:
228 * DATA needs to be driven on the FALLING edge
230 dssdev
->bus_flags
= DRM_BUS_FLAG_DE_HIGH
| DRM_BUS_FLAG_SYNC_NEGEDGE
231 | DRM_BUS_FLAG_PIXDATA_POSEDGE
;
233 omapdss_display_init(dssdev
);
234 omapdss_device_register(dssdev
);
239 static int __exit
sharp_ls_remove(struct platform_device
*pdev
)
241 struct panel_drv_data
*ddata
= platform_get_drvdata(pdev
);
242 struct omap_dss_device
*dssdev
= &ddata
->dssdev
;
244 omapdss_device_unregister(dssdev
);
246 sharp_ls_disable(dssdev
);
251 static const struct of_device_id sharp_ls_of_match
[] = {
252 { .compatible
= "omapdss,sharp,ls037v7dw01", },
256 MODULE_DEVICE_TABLE(of
, sharp_ls_of_match
);
258 static struct platform_driver sharp_ls_driver
= {
259 .probe
= sharp_ls_probe
,
260 .remove
= __exit_p(sharp_ls_remove
),
262 .name
= "panel-sharp-ls037v7dw01",
263 .of_match_table
= sharp_ls_of_match
,
264 .suppress_bind_attrs
= true,
268 module_platform_driver(sharp_ls_driver
);
270 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
271 MODULE_DESCRIPTION("Sharp LS037V7DW01 Panel Driver");
272 MODULE_LICENSE("GPL");