summaryrefslogtreecommitdiff
path: root/drivers/auxdisplay/hd44780.c
diff options
context:
space:
mode:
authorLars Poeschel <poeschel@lemonage.de>2020-11-03 10:58:05 +0100
committerMiguel Ojeda <ojeda@kernel.org>2020-11-04 11:04:02 +0100
commit718e05ed92ecac0d9d3954bcc8064527c3ce7565 (patch)
treee724e59f1c8e189aa82ef9585a10c412f4e13007 /drivers/auxdisplay/hd44780.c
parent66ce7d5c1e124b497f45aead50df1dc3c2873382 (diff)
downloadlwn-718e05ed92ecac0d9d3954bcc8064527c3ce7565.tar.gz
lwn-718e05ed92ecac0d9d3954bcc8064527c3ce7565.zip
auxdisplay: Introduce hd44780_common.[ch]
There is some hd44780 specific code in charlcd and this code is used by multiple drivers. To make charlcd independent from this device specific code this has to be moved to a place where the multiple drivers can share their common code. This common place is now introduced as hd44780_common. Reviewed-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Lars Poeschel <poeschel@lemonage.de> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Diffstat (limited to 'drivers/auxdisplay/hd44780.c')
-rw-r--r--drivers/auxdisplay/hd44780.c43
1 files changed, 29 insertions, 14 deletions
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;
}