cregit-Linux how code gets into the kernel

Release 4.14 drivers/auxdisplay/hd44780.c

/*
 * HD44780 Character LCD driver for Linux
 *
 * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
 * Copyright (C) 2016-2017 Glider bvba
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>

#include <misc/charlcd.h>



enum hd44780_pin {
	/* Order does matter due to writing to GPIO array subsets! */
	
PIN_DATA0,	/* Optional */
	
PIN_DATA1,	/* Optional */
	
PIN_DATA2,	/* Optional */
	
PIN_DATA3,	/* Optional */
	
PIN_DATA4,
	
PIN_DATA5,
	
PIN_DATA6,
	
PIN_DATA7,
	
PIN_CTRL_RS,
	
PIN_CTRL_RW,	/* Optional */
	
PIN_CTRL_E,
	
PIN_CTRL_BL,   /* Optional */
	
PIN_NUM
};


struct hd44780 {
	
struct gpio_desc *pins[PIN_NUM];
};


static void hd44780_backlight(struct charlcd *lcd, int on) { struct hd44780 *hd = lcd->drvdata; if (hd->pins[PIN_CTRL_BL]) gpiod_set_value_cansleep(hd->pins[PIN_CTRL_BL], on); }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven44100.00%1100.00%
Total44100.00%1100.00%


static void hd44780_strobe_gpio(struct hd44780 *hd) { /* Maintain the data during 20 us before the strobe */ udelay(20); gpiod_set_value_cansleep(hd->pins[PIN_CTRL_E], 1); /* Maintain the strobe during 40 us */ udelay(40); gpiod_set_value_cansleep(hd->pins[PIN_CTRL_E], 0); }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven47100.00%1100.00%
Total47100.00%1100.00%

/* write to an LCD panel register in 8 bit GPIO mode */
static void hd44780_write_gpio8(struct hd44780 *hd, u8 val, unsigned int rs) { int values[10]; /* for DATA[0-7], RS, RW */ unsigned int i, n; for (i = 0; i < 8; i++) values[PIN_DATA0 + i] = !!(val & BIT(i)); values[PIN_CTRL_RS] = rs; n = 9; if (hd->pins[PIN_CTRL_RW]) { values[PIN_CTRL_RW] = 0; n++; } /* Present the data to the port */ gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA0], values); hd44780_strobe_gpio(hd); }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven115100.00%1100.00%
Total115100.00%1100.00%

/* write to an LCD panel register in 4 bit GPIO mode */
static void hd44780_write_gpio4(struct hd44780 *hd, u8 val, unsigned int rs) { int values[10]; /* for DATA[0-7], RS, RW, but DATA[0-3] is unused */ unsigned int i, n; /* High nibble + RS, RW */ for (i = 4; i < 8; i++) values[PIN_DATA0 + i] = !!(val & BIT(i)); values[PIN_CTRL_RS] = rs; n = 5; if (hd->pins[PIN_CTRL_RW]) { values[PIN_CTRL_RW] = 0; n++; } /* Present the data to the port */ gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], &values[PIN_DATA4]); hd44780_strobe_gpio(hd); /* Low nibble */ for (i = 0; i < 4; i++) values[PIN_DATA4 + i] = !!(val & BIT(i)); /* Present the data to the port */ gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], &values[PIN_DATA4]); hd44780_strobe_gpio(hd); }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven177100.00%1100.00%
Total177100.00%1100.00%

/* Send a command to the LCD panel in 8 bit GPIO mode */
static void hd44780_write_cmd_gpio8(struct charlcd *lcd, int cmd) { struct hd44780 *hd = lcd->drvdata; hd44780_write_gpio8(hd, cmd, 0); /* The shortest command takes at least 120 us */ udelay(120); }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven38100.00%1100.00%
Total38100.00%1100.00%

/* Send data to the LCD panel in 8 bit GPIO mode */
static void hd44780_write_data_gpio8(struct charlcd *lcd, int data) { struct hd44780 *hd = lcd->drvdata; hd44780_write_gpio8(hd, data, 1); /* The shortest data takes at least 45 us */ udelay(45); }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven38100.00%1100.00%
Total38100.00%1100.00%

static const struct charlcd_ops hd44780_ops_gpio8 = { .write_cmd = hd44780_write_cmd_gpio8, .write_data = hd44780_write_data_gpio8, .backlight = hd44780_backlight, }; /* Send a command to the LCD panel in 4 bit GPIO mode */
static void hd44780_write_cmd_gpio4(struct charlcd *lcd, int cmd) { struct hd44780 *hd = lcd->drvdata; hd44780_write_gpio4(hd, cmd, 0); /* The shortest command takes at least 120 us */ udelay(120); }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven38100.00%1100.00%
Total38100.00%1100.00%

/* 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) { int values[10]; /* for DATA[0-7], RS, RW, but DATA[0-3] is unused */ struct hd44780 *hd = lcd->drvdata; unsigned int i, n; /* Command nibble + RS, RW */ for (i = 0; i < 4; i++) values[PIN_DATA4 + i] = !!(cmd & BIT(i)); values[PIN_CTRL_RS] = 0; n = 5; if (hd->pins[PIN_CTRL_RW]) { values[PIN_CTRL_RW] = 0; n++; } /* Present the data to the port */ gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], &values[PIN_DATA4]); hd44780_strobe_gpio(hd); }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven125100.00%1100.00%
Total125100.00%1100.00%

/* Send data to the LCD panel in 4 bit GPIO mode */
static void hd44780_write_data_gpio4(struct charlcd *lcd, int data) { struct hd44780 *hd = lcd->drvdata; hd44780_write_gpio4(hd, data, 1); /* The shortest data takes at least 45 us */ udelay(45); }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven38100.00%1100.00%
Total38100.00%1100.00%

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, };
static int hd44780_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; unsigned int i, base; struct charlcd *lcd; struct hd44780 *hd; int ifwidth, ret; /* Required pins */ ifwidth = gpiod_count(dev, "data"); if (ifwidth < 0) return ifwidth; switch (ifwidth) { case 4: base = PIN_DATA4; break; case 8: base = PIN_DATA0; break; default: return -EINVAL; } lcd = charlcd_alloc(sizeof(struct hd44780)); if (!lcd) return -ENOMEM; hd = lcd->drvdata; 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; } } 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; } 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; } /* Optional pins */ hd->pins[PIN_CTRL_RW] = devm_gpiod_get_optional(dev, "rw", GPIOD_OUT_LOW); if (IS_ERR(hd->pins[PIN_CTRL_RW])) { ret = PTR_ERR(hd->pins[PIN_CTRL_RW]); goto fail; } 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; } /* Required properties */ ret = device_property_read_u32(dev, "display-height-chars", &lcd->height); if (ret) goto fail; ret = device_property_read_u32(dev, "display-width-chars", &lcd->width); if (ret) goto fail; /* * 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; /* 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; ret = charlcd_register(lcd); if (ret) goto fail; platform_set_drvdata(pdev, lcd); return 0; fail: kfree(lcd); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven490100.00%2100.00%
Total490100.00%2100.00%


static int hd44780_remove(struct platform_device *pdev) { struct charlcd *lcd = platform_get_drvdata(pdev); charlcd_unregister(lcd); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven29100.00%1100.00%
Total29100.00%1100.00%

static const struct of_device_id hd44780_of_match[] = { { .compatible = "hit,hd44780" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, hd44780_of_match); static struct platform_driver hd44780_driver = { .probe = hd44780_probe, .remove = hd44780_remove, .driver = { .name = "hd44780", .of_match_table = hd44780_of_match, }, }; module_platform_driver(hd44780_driver); MODULE_DESCRIPTION("HD44780 Character LCD driver"); MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Geert Uytterhoeven1388100.00%2100.00%
Total1388100.00%2100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.