]> Git Repo - J-linux.git/blob - drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
Merge branch 'asoc-5.3' into asoc-5.4
[J-linux.git] / drivers / gpu / drm / omapdrm / displays / panel-sharp-ls037v7dw01.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * LCD panel driver for Sharp LS037V7DW01
4  *
5  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
6  * Author: Tomi Valkeinen <[email protected]>
7  */
8
9 #include <linux/delay.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/platform_device.h>
14 #include <linux/slab.h>
15 #include <linux/regulator/consumer.h>
16
17 #include "../dss/omapdss.h"
18
19 struct panel_drv_data {
20         struct omap_dss_device dssdev;
21         struct regulator *vcc;
22
23         struct videomode vm;
24
25         struct gpio_desc *resb_gpio;    /* low = reset active min 20 us */
26         struct gpio_desc *ini_gpio;     /* high = power on */
27         struct gpio_desc *mo_gpio;      /* low = 480x640, high = 240x320 */
28         struct gpio_desc *lr_gpio;      /* high = conventional horizontal scanning */
29         struct gpio_desc *ud_gpio;      /* high = conventional vertical scanning */
30 };
31
32 static const struct videomode sharp_ls_vm = {
33         .hactive = 480,
34         .vactive = 640,
35
36         .pixelclock     = 19200000,
37
38         .hsync_len      = 2,
39         .hfront_porch   = 1,
40         .hback_porch    = 28,
41
42         .vsync_len      = 1,
43         .vfront_porch   = 1,
44         .vback_porch    = 1,
45
46         .flags          = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
47 };
48
49 #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
50
51 static int sharp_ls_connect(struct omap_dss_device *src,
52                             struct omap_dss_device *dst)
53 {
54         return 0;
55 }
56
57 static void sharp_ls_disconnect(struct omap_dss_device *src,
58                                 struct omap_dss_device *dst)
59 {
60 }
61
62 static void sharp_ls_pre_enable(struct omap_dss_device *dssdev)
63 {
64         struct panel_drv_data *ddata = to_panel_data(dssdev);
65         int r;
66
67         if (ddata->vcc) {
68                 r = regulator_enable(ddata->vcc);
69                 if (r)
70                         dev_err(dssdev->dev, "%s: failed to enable regulator\n",
71                                 __func__);
72         }
73 }
74
75 static void sharp_ls_enable(struct omap_dss_device *dssdev)
76 {
77         struct panel_drv_data *ddata = to_panel_data(dssdev);
78
79         /* wait couple of vsyncs until enabling the LCD */
80         msleep(50);
81
82         if (ddata->resb_gpio)
83                 gpiod_set_value_cansleep(ddata->resb_gpio, 1);
84
85         if (ddata->ini_gpio)
86                 gpiod_set_value_cansleep(ddata->ini_gpio, 1);
87 }
88
89 static void sharp_ls_disable(struct omap_dss_device *dssdev)
90 {
91         struct panel_drv_data *ddata = to_panel_data(dssdev);
92
93         if (ddata->ini_gpio)
94                 gpiod_set_value_cansleep(ddata->ini_gpio, 0);
95
96         if (ddata->resb_gpio)
97                 gpiod_set_value_cansleep(ddata->resb_gpio, 0);
98
99         /* wait at least 5 vsyncs after disabling the LCD */
100         msleep(100);
101 }
102
103 static void sharp_ls_post_disable(struct omap_dss_device *dssdev)
104 {
105         struct panel_drv_data *ddata = to_panel_data(dssdev);
106
107         if (ddata->vcc)
108                 regulator_disable(ddata->vcc);
109 }
110
111 static int sharp_ls_get_modes(struct omap_dss_device *dssdev,
112                               struct drm_connector *connector)
113 {
114         struct panel_drv_data *ddata = to_panel_data(dssdev);
115
116         return omapdss_display_get_modes(connector, &ddata->vm);
117 }
118
119 static const struct omap_dss_device_ops sharp_ls_ops = {
120         .connect        = sharp_ls_connect,
121         .disconnect     = sharp_ls_disconnect,
122
123         .pre_enable     = sharp_ls_pre_enable,
124         .enable         = sharp_ls_enable,
125         .disable        = sharp_ls_disable,
126         .post_disable   = sharp_ls_post_disable,
127
128         .get_modes      = sharp_ls_get_modes,
129 };
130
131 static  int sharp_ls_get_gpio_of(struct device *dev, int index, int val,
132         const char *desc, struct gpio_desc **gpiod)
133 {
134         struct gpio_desc *gd;
135
136         *gpiod = NULL;
137
138         gd = devm_gpiod_get_index(dev, desc, index, GPIOD_OUT_LOW);
139         if (IS_ERR(gd))
140                 return PTR_ERR(gd);
141
142         *gpiod = gd;
143         return 0;
144 }
145
146 static int sharp_ls_probe_of(struct platform_device *pdev)
147 {
148         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
149         int r;
150
151         ddata->vcc = devm_regulator_get(&pdev->dev, "envdd");
152         if (IS_ERR(ddata->vcc)) {
153                 dev_err(&pdev->dev, "failed to get regulator\n");
154                 return PTR_ERR(ddata->vcc);
155         }
156
157         /* lcd INI */
158         r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "enable", &ddata->ini_gpio);
159         if (r)
160                 return r;
161
162         /* lcd RESB */
163         r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "reset", &ddata->resb_gpio);
164         if (r)
165                 return r;
166
167         /* lcd MO */
168         r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "mode", &ddata->mo_gpio);
169         if (r)
170                 return r;
171
172         /* lcd LR */
173         r = sharp_ls_get_gpio_of(&pdev->dev, 1, 1, "mode", &ddata->lr_gpio);
174         if (r)
175                 return r;
176
177         /* lcd UD */
178         r = sharp_ls_get_gpio_of(&pdev->dev, 2, 1, "mode", &ddata->ud_gpio);
179         if (r)
180                 return r;
181
182         return 0;
183 }
184
185 static int sharp_ls_probe(struct platform_device *pdev)
186 {
187         struct panel_drv_data *ddata;
188         struct omap_dss_device *dssdev;
189         int r;
190
191         ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
192         if (ddata == NULL)
193                 return -ENOMEM;
194
195         platform_set_drvdata(pdev, ddata);
196
197         r = sharp_ls_probe_of(pdev);
198         if (r)
199                 return r;
200
201         ddata->vm = sharp_ls_vm;
202
203         dssdev = &ddata->dssdev;
204         dssdev->dev = &pdev->dev;
205         dssdev->ops = &sharp_ls_ops;
206         dssdev->type = OMAP_DISPLAY_TYPE_DPI;
207         dssdev->display = true;
208         dssdev->owner = THIS_MODULE;
209         dssdev->of_ports = BIT(0);
210         dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
211
212         /*
213          * Note: According to the panel documentation:
214          * DATA needs to be driven on the FALLING edge
215          */
216         dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH
217                           | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE
218                           | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
219
220         omapdss_display_init(dssdev);
221         omapdss_device_register(dssdev);
222
223         return 0;
224 }
225
226 static int __exit sharp_ls_remove(struct platform_device *pdev)
227 {
228         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
229         struct omap_dss_device *dssdev = &ddata->dssdev;
230
231         omapdss_device_unregister(dssdev);
232
233         if (omapdss_device_is_enabled(dssdev)) {
234                 sharp_ls_disable(dssdev);
235                 sharp_ls_post_disable(dssdev);
236         }
237
238         return 0;
239 }
240
241 static const struct of_device_id sharp_ls_of_match[] = {
242         { .compatible = "omapdss,sharp,ls037v7dw01", },
243         {},
244 };
245
246 MODULE_DEVICE_TABLE(of, sharp_ls_of_match);
247
248 static struct platform_driver sharp_ls_driver = {
249         .probe = sharp_ls_probe,
250         .remove = __exit_p(sharp_ls_remove),
251         .driver = {
252                 .name = "panel-sharp-ls037v7dw01",
253                 .of_match_table = sharp_ls_of_match,
254                 .suppress_bind_attrs = true,
255         },
256 };
257
258 module_platform_driver(sharp_ls_driver);
259
260 MODULE_AUTHOR("Tomi Valkeinen <[email protected]>");
261 MODULE_DESCRIPTION("Sharp LS037V7DW01 Panel Driver");
262 MODULE_LICENSE("GPL");
This page took 0.04514 seconds and 4 git commands to generate.