diff options
Diffstat (limited to 'drivers/auxdisplay/hd44780.c')
-rw-r--r-- | drivers/auxdisplay/hd44780.c | 120 |
1 files changed, 83 insertions, 37 deletions
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c index bcbe13092327..2e5e7c993933 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! */ @@ -37,9 +38,10 @@ struct hd44780 { struct gpio_desc *pins[PIN_NUM]; }; -static void hd44780_backlight(struct charlcd *lcd, int on) +static void hd44780_backlight(struct charlcd *lcd, enum charlcd_onoff on) { - struct hd44780 *hd = lcd->drvdata; + struct hd44780_common *hdc = lcd->drvdata; + struct hd44780 *hd = hdc->hd44780; if (hd->pins[PIN_CTRL_BL]) gpiod_set_value_cansleep(hd->pins[PIN_CTRL_BL], on); @@ -101,9 +103,9 @@ static void hd44780_write_gpio4(struct hd44780 *hd, u8 val, unsigned int rs) } /* Send a command to the LCD panel in 8 bit GPIO mode */ -static void hd44780_write_cmd_gpio8(struct charlcd *lcd, int cmd) +static void hd44780_write_cmd_gpio8(struct hd44780_common *hdc, int cmd) { - struct hd44780 *hd = lcd->drvdata; + struct hd44780 *hd = hdc->hd44780; hd44780_write_gpio8(hd, cmd, 0); @@ -112,9 +114,9 @@ static void hd44780_write_cmd_gpio8(struct charlcd *lcd, int cmd) } /* Send data to the LCD panel in 8 bit GPIO mode */ -static void hd44780_write_data_gpio8(struct charlcd *lcd, int data) +static void hd44780_write_data_gpio8(struct hd44780_common *hdc, int data) { - struct hd44780 *hd = lcd->drvdata; + struct hd44780 *hd = hdc->hd44780; hd44780_write_gpio8(hd, data, 1); @@ -123,15 +125,26 @@ static void hd44780_write_data_gpio8(struct charlcd *lcd, int data) } static const struct charlcd_ops hd44780_ops_gpio8 = { - .write_cmd = hd44780_write_cmd_gpio8, - .write_data = hd44780_write_data_gpio8, .backlight = hd44780_backlight, + .print = hd44780_common_print, + .gotoxy = hd44780_common_gotoxy, + .home = hd44780_common_home, + .clear_display = hd44780_common_clear_display, + .init_display = hd44780_common_init_display, + .shift_cursor = hd44780_common_shift_cursor, + .shift_display = hd44780_common_shift_display, + .display = hd44780_common_display, + .cursor = hd44780_common_cursor, + .blink = hd44780_common_blink, + .fontsize = hd44780_common_fontsize, + .lines = hd44780_common_lines, + .redefine_char = hd44780_common_redefine_char, }; /* Send a command to the LCD panel in 4 bit GPIO mode */ -static void hd44780_write_cmd_gpio4(struct charlcd *lcd, int cmd) +static void hd44780_write_cmd_gpio4(struct hd44780_common *hdc, int cmd) { - struct hd44780 *hd = lcd->drvdata; + struct hd44780 *hd = hdc->hd44780; hd44780_write_gpio4(hd, cmd, 0); @@ -140,10 +153,10 @@ static void hd44780_write_cmd_gpio4(struct charlcd *lcd, int cmd) } /* Send 4-bits of a command to the LCD panel in raw 4 bit GPIO mode */ -static void hd44780_write_cmd_raw_gpio4(struct charlcd *lcd, int cmd) +static void hd44780_write_cmd_raw_gpio4(struct hd44780_common *hdc, int cmd) { DECLARE_BITMAP(values, 6); /* for DATA[4-7], RS, RW */ - struct hd44780 *hd = lcd->drvdata; + struct hd44780 *hd = hdc->hd44780; unsigned int n; /* Command nibble + RS, RW */ @@ -157,9 +170,9 @@ static void hd44780_write_cmd_raw_gpio4(struct charlcd *lcd, int cmd) } /* Send data to the LCD panel in 4 bit GPIO mode */ -static void hd44780_write_data_gpio4(struct charlcd *lcd, int data) +static void hd44780_write_data_gpio4(struct hd44780_common *hdc, int data) { - struct hd44780 *hd = lcd->drvdata; + struct hd44780 *hd = hdc->hd44780; hd44780_write_gpio4(hd, data, 1); @@ -168,10 +181,20 @@ static void hd44780_write_data_gpio4(struct charlcd *lcd, int data) } static const struct charlcd_ops hd44780_ops_gpio4 = { - .write_cmd = hd44780_write_cmd_gpio4, - .write_cmd_raw4 = hd44780_write_cmd_raw_gpio4, - .write_data = hd44780_write_data_gpio4, .backlight = hd44780_backlight, + .print = hd44780_common_print, + .gotoxy = hd44780_common_gotoxy, + .home = hd44780_common_home, + .clear_display = hd44780_common_clear_display, + .init_display = hd44780_common_init_display, + .shift_cursor = hd44780_common_shift_cursor, + .shift_display = hd44780_common_shift_display, + .display = hd44780_common_display, + .cursor = hd44780_common_cursor, + .blink = hd44780_common_blink, + .fontsize = hd44780_common_fontsize, + .lines = hd44780_common_lines, + .redefine_char = hd44780_common_redefine_char, }; static int hd44780_probe(struct platform_device *pdev) @@ -179,8 +202,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 +222,39 @@ static int hd44780_probe(struct platform_device *pdev) return -EINVAL; } - lcd = charlcd_alloc(sizeof(struct hd44780)); - if (!lcd) + hdc = hd44780_common_alloc(); + if (!hdc) return -ENOMEM; - hd = lcd->drvdata; + lcd = charlcd_alloc(); + if (!lcd) + goto fail1; + + 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,47 +262,60 @@ 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 * usually equal to the display width */ if (lcd->height > 2) - lcd->bwidth = lcd->width; + hdc->bwidth = lcd->width; /* Optional properties */ - device_property_read_u32(dev, "internal-buffer-width", &lcd->bwidth); - - lcd->ifwidth = ifwidth; - lcd->ops = ifwidth == 8 ? &hd44780_ops_gpio8 : &hd44780_ops_gpio4; + device_property_read_u32(dev, "internal-buffer-width", &hdc->bwidth); + + hdc->ifwidth = ifwidth; + if (ifwidth == 8) { + lcd->ops = &hd44780_ops_gpio8; + hdc->write_data = hd44780_write_data_gpio8; + hdc->write_cmd = hd44780_write_cmd_gpio8; + } else { + lcd->ops = &hd44780_ops_gpio4; + hdc->write_data = hd44780_write_data_gpio4; + hdc->write_cmd = hd44780_write_cmd_gpio4; + hdc->write_cmd_raw4 = hd44780_write_cmd_raw_gpio4; + } 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 +323,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; } |