diff options
-rw-r--r-- | drivers/auxdisplay/Kconfig | 20 | ||||
-rw-r--r-- | drivers/auxdisplay/Makefile | 1 | ||||
-rw-r--r-- | drivers/auxdisplay/hd44780.c | 43 | ||||
-rw-r--r-- | drivers/auxdisplay/hd44780_common.c | 19 | ||||
-rw-r--r-- | drivers/auxdisplay/hd44780_common.h | 7 | ||||
-rw-r--r-- | drivers/auxdisplay/panel.c | 18 |
6 files changed, 91 insertions, 17 deletions
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index 81757eeded68..aaf2d66357a1 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig @@ -16,10 +16,29 @@ menuconfig AUXDISPLAY if AUXDISPLAY +config CHARLCD + tristate "Character LCD core support" if COMPILE_TEST + help + This is the base system for character-based LCD displays. + It makes no sense to have this alone, you select your display driver + and if it needs the charlcd core, it will select it automatically. + This is some character LCD core interface that multiple drivers can + use. + +config HD44780_COMMON + tristate "Common functions for HD44780 (and compatibles) LCD displays" if COMPILE_TEST + help + This is a module with the common symbols for HD44780 (and compatibles) + displays. This is the code that multiple other modules use. It is not + useful alone. If you have some sort of HD44780 compatible display, + you very likely use this. It is selected automatically by selecting + your concrete display. + config HD44780 tristate "HD44780 Character LCD support" depends on GPIOLIB || COMPILE_TEST select CHARLCD + select HD44780_COMMON help Enable support for Character LCDs using a HD44780 controller. The LCD is accessible through the /dev/lcd char device (10, 156). @@ -168,6 +187,7 @@ menuconfig PARPORT_PANEL tristate "Parallel port LCD/Keypad Panel support" depends on PARPORT select CHARLCD + select HD44780_COMMON help Say Y here if you have an HD44780 or KS-0074 LCD connected to your parallel port. This driver also features 4 and 6-key keypads. The LCD diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile index cf54b5efb07e..7e8a8c3eb3c3 100644 --- a/drivers/auxdisplay/Makefile +++ b/drivers/auxdisplay/Makefile @@ -4,6 +4,7 @@ # obj-$(CONFIG_CHARLCD) += charlcd.o +obj-$(CONFIG_HD44780_COMMON) += hd44780_common.o obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o obj-$(CONFIG_KS0108) += ks0108.o obj-$(CONFIG_CFAG12864B) += cfag12864b.o cfag12864bfb.o diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c index 5982158557bb..271dba9cd108 100644 --- a/drivers/auxdisplay/hd44780.c +++ b/drivers/auxdisplay/hd44780.c @@ -15,6 +15,7 @@ #include <linux/slab.h> #include "charlcd.h" +#include "hd44780_common.h" enum hd44780_pin { /* Order does matter due to writing to GPIO array subsets! */ @@ -179,8 +180,9 @@ static int hd44780_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; unsigned int i, base; struct charlcd *lcd; + struct hd44780_common *hdc; struct hd44780 *hd; - int ifwidth, ret; + int ifwidth, ret = -ENOMEM; /* Required pins */ ifwidth = gpiod_count(dev, "data"); @@ -198,31 +200,39 @@ static int hd44780_probe(struct platform_device *pdev) return -EINVAL; } + hdc = hd44780_common_alloc(); + if (!hdc) + return -ENOMEM; + lcd = charlcd_alloc(sizeof(struct hd44780)); if (!lcd) - return -ENOMEM; + goto fail1; - hd = lcd->drvdata; + hd = kzalloc(sizeof(struct hd44780), GFP_KERNEL); + if (!hd) + goto fail2; + hdc->hd44780 = hd; + lcd->drvdata = hdc; for (i = 0; i < ifwidth; i++) { hd->pins[base + i] = devm_gpiod_get_index(dev, "data", i, GPIOD_OUT_LOW); if (IS_ERR(hd->pins[base + i])) { ret = PTR_ERR(hd->pins[base + i]); - goto fail; + goto fail3; } } hd->pins[PIN_CTRL_E] = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(hd->pins[PIN_CTRL_E])) { ret = PTR_ERR(hd->pins[PIN_CTRL_E]); - goto fail; + goto fail3; } hd->pins[PIN_CTRL_RS] = devm_gpiod_get(dev, "rs", GPIOD_OUT_HIGH); if (IS_ERR(hd->pins[PIN_CTRL_RS])) { ret = PTR_ERR(hd->pins[PIN_CTRL_RS]); - goto fail; + goto fail3; } /* Optional pins */ @@ -230,24 +240,24 @@ static int hd44780_probe(struct platform_device *pdev) GPIOD_OUT_LOW); if (IS_ERR(hd->pins[PIN_CTRL_RW])) { ret = PTR_ERR(hd->pins[PIN_CTRL_RW]); - goto fail; + goto fail3; } hd->pins[PIN_CTRL_BL] = devm_gpiod_get_optional(dev, "backlight", GPIOD_OUT_LOW); if (IS_ERR(hd->pins[PIN_CTRL_BL])) { ret = PTR_ERR(hd->pins[PIN_CTRL_BL]); - goto fail; + goto fail3; } /* Required properties */ ret = device_property_read_u32(dev, "display-height-chars", &lcd->height); if (ret) - goto fail; + goto fail3; ret = device_property_read_u32(dev, "display-width-chars", &lcd->width); if (ret) - goto fail; + goto fail3; /* * On displays with more than two rows, the internal buffer width is @@ -264,13 +274,17 @@ static int hd44780_probe(struct platform_device *pdev) ret = charlcd_register(lcd); if (ret) - goto fail; + goto fail3; platform_set_drvdata(pdev, lcd); return 0; -fail: - charlcd_free(lcd); +fail3: + kfree(hd); +fail2: + kfree(lcd); +fail1: + kfree(hdc); return ret; } @@ -278,9 +292,10 @@ static int hd44780_remove(struct platform_device *pdev) { struct charlcd *lcd = platform_get_drvdata(pdev); + kfree(lcd->drvdata); charlcd_unregister(lcd); - charlcd_free(lcd); + kfree(lcd); return 0; } diff --git a/drivers/auxdisplay/hd44780_common.c b/drivers/auxdisplay/hd44780_common.c new file mode 100644 index 000000000000..2fdea29d6a8f --- /dev/null +++ b/drivers/auxdisplay/hd44780_common.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include <linux/module.h> +#include <linux/slab.h> + +#include "hd44780_common.h" + +struct hd44780_common *hd44780_common_alloc(void) +{ + struct hd44780_common *hd; + + hd = kzalloc(sizeof(*hd), GFP_KERNEL); + if (!hd) + return NULL; + + return hd; +} +EXPORT_SYMBOL_GPL(hd44780_common_alloc); + +MODULE_LICENSE("GPL"); diff --git a/drivers/auxdisplay/hd44780_common.h b/drivers/auxdisplay/hd44780_common.h new file mode 100644 index 000000000000..974868f7529c --- /dev/null +++ b/drivers/auxdisplay/hd44780_common.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +struct hd44780_common { + void *hd44780; +}; + +struct hd44780_common *hd44780_common_alloc(void); diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index de623ae219f1..c3a60e190a7a 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c @@ -56,6 +56,7 @@ #include <linux/uaccess.h> #include "charlcd.h" +#include "hd44780_common.h" #define LCD_MAXBYTES 256 /* max burst write */ @@ -895,10 +896,20 @@ static const struct charlcd_ops charlcd_tilcd_ops = { static void lcd_init(void) { struct charlcd *charlcd; + struct hd44780_common *hdc; + + hdc = hd44780_common_alloc(); + if (!hdc) + return; charlcd = charlcd_alloc(0); - if (!charlcd) + if (!charlcd) { + kfree(hdc); return; + } + + hdc->hd44780 = &lcd; + charlcd->drvdata = hdc; /* * Init lcd struct with load-time values to preserve exact @@ -1620,7 +1631,7 @@ err_lcd_unreg: if (lcd.enabled) charlcd_unregister(lcd.charlcd); err_unreg_device: - charlcd_free(lcd.charlcd); + kfree(lcd.charlcd); lcd.charlcd = NULL; parport_unregister_device(pprt); pprt = NULL; @@ -1647,7 +1658,8 @@ static void panel_detach(struct parport *port) if (lcd.enabled) { charlcd_unregister(lcd.charlcd); lcd.initialized = false; - charlcd_free(lcd.charlcd); + kfree(lcd.charlcd->drvdata); + kfree(lcd.charlcd); lcd.charlcd = NULL; } |