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