Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / auxdisplay / hd44780.c
1 /*
2  * HD44780 Character LCD driver for Linux
3  *
4  * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
5  * Copyright (C) 2016-2017 Glider bvba
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version
10  * 2 of the License, or (at your option) any later version.
11  */
12
13 #include <linux/delay.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/property.h>
18 #include <linux/slab.h>
19
20 #include <misc/charlcd.h>
21
22
23 enum hd44780_pin {
24         /* Order does matter due to writing to GPIO array subsets! */
25         PIN_DATA0,      /* Optional */
26         PIN_DATA1,      /* Optional */
27         PIN_DATA2,      /* Optional */
28         PIN_DATA3,      /* Optional */
29         PIN_DATA4,
30         PIN_DATA5,
31         PIN_DATA6,
32         PIN_DATA7,
33         PIN_CTRL_RS,
34         PIN_CTRL_RW,    /* Optional */
35         PIN_CTRL_E,
36         PIN_CTRL_BL,   /* Optional */
37         PIN_NUM
38 };
39
40 struct hd44780 {
41         struct gpio_desc *pins[PIN_NUM];
42 };
43
44 static void hd44780_backlight(struct charlcd *lcd, int on)
45 {
46         struct hd44780 *hd = lcd->drvdata;
47
48         if (hd->pins[PIN_CTRL_BL])
49                 gpiod_set_value_cansleep(hd->pins[PIN_CTRL_BL], on);
50 }
51
52 static void hd44780_strobe_gpio(struct hd44780 *hd)
53 {
54         /* Maintain the data during 20 us before the strobe */
55         udelay(20);
56
57         gpiod_set_value_cansleep(hd->pins[PIN_CTRL_E], 1);
58
59         /* Maintain the strobe during 40 us */
60         udelay(40);
61
62         gpiod_set_value_cansleep(hd->pins[PIN_CTRL_E], 0);
63 }
64
65 /* write to an LCD panel register in 8 bit GPIO mode */
66 static void hd44780_write_gpio8(struct hd44780 *hd, u8 val, unsigned int rs)
67 {
68         int values[10]; /* for DATA[0-7], RS, RW */
69         unsigned int i, n;
70
71         for (i = 0; i < 8; i++)
72                 values[PIN_DATA0 + i] = !!(val & BIT(i));
73         values[PIN_CTRL_RS] = rs;
74         n = 9;
75         if (hd->pins[PIN_CTRL_RW]) {
76                 values[PIN_CTRL_RW] = 0;
77                 n++;
78         }
79
80         /* Present the data to the port */
81         gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA0], values);
82
83         hd44780_strobe_gpio(hd);
84 }
85
86 /* write to an LCD panel register in 4 bit GPIO mode */
87 static void hd44780_write_gpio4(struct hd44780 *hd, u8 val, unsigned int rs)
88 {
89         int values[10]; /* for DATA[0-7], RS, RW, but DATA[0-3] is unused */
90         unsigned int i, n;
91
92         /* High nibble + RS, RW */
93         for (i = 4; i < 8; i++)
94                 values[PIN_DATA0 + i] = !!(val & BIT(i));
95         values[PIN_CTRL_RS] = rs;
96         n = 5;
97         if (hd->pins[PIN_CTRL_RW]) {
98                 values[PIN_CTRL_RW] = 0;
99                 n++;
100         }
101
102         /* Present the data to the port */
103         gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4],
104                                        &values[PIN_DATA4]);
105
106         hd44780_strobe_gpio(hd);
107
108         /* Low nibble */
109         for (i = 0; i < 4; i++)
110                 values[PIN_DATA4 + i] = !!(val & BIT(i));
111
112         /* Present the data to the port */
113         gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4],
114                                        &values[PIN_DATA4]);
115
116         hd44780_strobe_gpio(hd);
117 }
118
119 /* Send a command to the LCD panel in 8 bit GPIO mode */
120 static void hd44780_write_cmd_gpio8(struct charlcd *lcd, int cmd)
121 {
122         struct hd44780 *hd = lcd->drvdata;
123
124         hd44780_write_gpio8(hd, cmd, 0);
125
126         /* The shortest command takes at least 120 us */
127         udelay(120);
128 }
129
130 /* Send data to the LCD panel in 8 bit GPIO mode */
131 static void hd44780_write_data_gpio8(struct charlcd *lcd, int data)
132 {
133         struct hd44780 *hd = lcd->drvdata;
134
135         hd44780_write_gpio8(hd, data, 1);
136
137         /* The shortest data takes at least 45 us */
138         udelay(45);
139 }
140
141 static const struct charlcd_ops hd44780_ops_gpio8 = {
142         .write_cmd      = hd44780_write_cmd_gpio8,
143         .write_data     = hd44780_write_data_gpio8,
144         .backlight      = hd44780_backlight,
145 };
146
147 /* Send a command to the LCD panel in 4 bit GPIO mode */
148 static void hd44780_write_cmd_gpio4(struct charlcd *lcd, int cmd)
149 {
150         struct hd44780 *hd = lcd->drvdata;
151
152         hd44780_write_gpio4(hd, cmd, 0);
153
154         /* The shortest command takes at least 120 us */
155         udelay(120);
156 }
157
158 /* Send 4-bits of a command to the LCD panel in raw 4 bit GPIO mode */
159 static void hd44780_write_cmd_raw_gpio4(struct charlcd *lcd, int cmd)
160 {
161         int values[10]; /* for DATA[0-7], RS, RW, but DATA[0-3] is unused */
162         struct hd44780 *hd = lcd->drvdata;
163         unsigned int i, n;
164
165         /* Command nibble + RS, RW */
166         for (i = 0; i < 4; i++)
167                 values[PIN_DATA4 + i] = !!(cmd & BIT(i));
168         values[PIN_CTRL_RS] = 0;
169         n = 5;
170         if (hd->pins[PIN_CTRL_RW]) {
171                 values[PIN_CTRL_RW] = 0;
172                 n++;
173         }
174
175         /* Present the data to the port */
176         gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4],
177                                        &values[PIN_DATA4]);
178
179         hd44780_strobe_gpio(hd);
180 }
181
182 /* Send data to the LCD panel in 4 bit GPIO mode */
183 static void hd44780_write_data_gpio4(struct charlcd *lcd, int data)
184 {
185         struct hd44780 *hd = lcd->drvdata;
186
187         hd44780_write_gpio4(hd, data, 1);
188
189         /* The shortest data takes at least 45 us */
190         udelay(45);
191 }
192
193 static const struct charlcd_ops hd44780_ops_gpio4 = {
194         .write_cmd      = hd44780_write_cmd_gpio4,
195         .write_cmd_raw4 = hd44780_write_cmd_raw_gpio4,
196         .write_data     = hd44780_write_data_gpio4,
197         .backlight      = hd44780_backlight,
198 };
199
200 static int hd44780_probe(struct platform_device *pdev)
201 {
202         struct device *dev = &pdev->dev;
203         unsigned int i, base;
204         struct charlcd *lcd;
205         struct hd44780 *hd;
206         int ifwidth, ret;
207
208         /* Required pins */
209         ifwidth = gpiod_count(dev, "data");
210         if (ifwidth < 0)
211                 return ifwidth;
212
213         switch (ifwidth) {
214         case 4:
215                 base = PIN_DATA4;
216                 break;
217         case 8:
218                 base = PIN_DATA0;
219                 break;
220         default:
221                 return -EINVAL;
222         }
223
224         lcd = charlcd_alloc(sizeof(struct hd44780));
225         if (!lcd)
226                 return -ENOMEM;
227
228         hd = lcd->drvdata;
229
230         for (i = 0; i < ifwidth; i++) {
231                 hd->pins[base + i] = devm_gpiod_get_index(dev, "data", i,
232                                                           GPIOD_OUT_LOW);
233                 if (IS_ERR(hd->pins[base + i])) {
234                         ret = PTR_ERR(hd->pins[base + i]);
235                         goto fail;
236                 }
237         }
238
239         hd->pins[PIN_CTRL_E] = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
240         if (IS_ERR(hd->pins[PIN_CTRL_E])) {
241                 ret = PTR_ERR(hd->pins[PIN_CTRL_E]);
242                 goto fail;
243         }
244
245         hd->pins[PIN_CTRL_RS] = devm_gpiod_get(dev, "rs", GPIOD_OUT_HIGH);
246         if (IS_ERR(hd->pins[PIN_CTRL_RS])) {
247                 ret = PTR_ERR(hd->pins[PIN_CTRL_RS]);
248                 goto fail;
249         }
250
251         /* Optional pins */
252         hd->pins[PIN_CTRL_RW] = devm_gpiod_get_optional(dev, "rw",
253                                                         GPIOD_OUT_LOW);
254         if (IS_ERR(hd->pins[PIN_CTRL_RW])) {
255                 ret = PTR_ERR(hd->pins[PIN_CTRL_RW]);
256                 goto fail;
257         }
258
259         hd->pins[PIN_CTRL_BL] = devm_gpiod_get_optional(dev, "backlight",
260                                                         GPIOD_OUT_LOW);
261         if (IS_ERR(hd->pins[PIN_CTRL_BL])) {
262                 ret = PTR_ERR(hd->pins[PIN_CTRL_BL]);
263                 goto fail;
264         }
265
266         /* Required properties */
267         ret = device_property_read_u32(dev, "display-height-chars",
268                                        &lcd->height);
269         if (ret)
270                 goto fail;
271         ret = device_property_read_u32(dev, "display-width-chars", &lcd->width);
272         if (ret)
273                 goto fail;
274
275         /*
276          * On displays with more than two rows, the internal buffer width is
277          * usually equal to the display width
278          */
279         if (lcd->height > 2)
280                 lcd->bwidth = lcd->width;
281
282         /* Optional properties */
283         device_property_read_u32(dev, "internal-buffer-width", &lcd->bwidth);
284
285         lcd->ifwidth = ifwidth;
286         lcd->ops = ifwidth == 8 ? &hd44780_ops_gpio8 : &hd44780_ops_gpio4;
287
288         ret = charlcd_register(lcd);
289         if (ret)
290                 goto fail;
291
292         platform_set_drvdata(pdev, lcd);
293         return 0;
294
295 fail:
296         kfree(lcd);
297         return ret;
298 }
299
300 static int hd44780_remove(struct platform_device *pdev)
301 {
302         struct charlcd *lcd = platform_get_drvdata(pdev);
303
304         charlcd_unregister(lcd);
305         return 0;
306 }
307
308 static const struct of_device_id hd44780_of_match[] = {
309         { .compatible = "hit,hd44780" },
310         { /* sentinel */ }
311 };
312 MODULE_DEVICE_TABLE(of, hd44780_of_match);
313
314 static struct platform_driver hd44780_driver = {
315         .probe = hd44780_probe,
316         .remove = hd44780_remove,
317         .driver         = {
318                 .name   = "hd44780",
319                 .of_match_table = hd44780_of_match,
320         },
321 };
322
323 module_platform_driver(hd44780_driver);
324 MODULE_DESCRIPTION("HD44780 Character LCD driver");
325 MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
326 MODULE_LICENSE("GPL");