Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");