diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-03-14 09:43:51 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-03-14 09:43:51 -0700 |
| commit | b345ff698ec7ed52d90bd5603ec8fc1802f40110 (patch) | |
| tree | 8b5ee07efc82e3a457ad41c944e6c23e2aa9bd32 | |
| parent | 480e035fc4c714fb5536e64ab9db04fedc89e910 (diff) | |
| parent | 5d9e12972259cd86ae9c3fc0d5338b15831b9929 (diff) | |
| download | linux-b345ff698ec7ed52d90bd5603ec8fc1802f40110.tar.gz linux-b345ff698ec7ed52d90bd5603ec8fc1802f40110.tar.bz2 linux-b345ff698ec7ed52d90bd5603ec8fc1802f40110.zip | |
Merge tag 'auxdisplay-v6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-auxdisplay
Pull auxdisplay updates from Andy Shevchenko:
- New driver for GPIO based 7-segment LED display (Chris Packham)
- New driver for Maxim MAX6958/6959 I²C 7-segment LED display
controller
- Refactor linedisp library to make the above happen
- Update Holtek HT16k33 driver to follow the linedisp refactoring
- Convert .remove to return void in platform drivers (Uwe Kleine-König)
- Fix DT schemas (Krzysztof Kozlowski)
- Refresh MAINTAINERS database
* tag 'auxdisplay-v6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-auxdisplay: (27 commits)
auxdisplay: img-ascii-lcd: Convert to platform remove callback returning void
auxdisplay: hd44780: Convert to platform remove callback returning void
auxdisplay: cfag12864bfb: Convert to platform remove callback returning void
auxdisplay: seg-led-gpio: Import linedisp namespace
dt-bindings: auxdisplay: Add bindings for generic 7-segment LED
auxdisplay: Add 7-segment LED display driver
auxdisplay: Add driver for MAX695x 7-segment LED controllers
dt-bindings: auxdisplay: Add Maxim MAX6958/6959
auxdisplay: ht16k33: Drop struct ht16k33_seg
auxdisplay: ht16k33: Switch to use line display character mapping
auxdisplay: ht16k33: Define a few helper macros
auxdisplay: ht16k33: Move ht16k33_linedisp_ops down
auxdisplay: ht16k33: Add default to switch-cases
auxdisplay: linedisp: Allocate buffer for the string
auxdisplay: linedisp: Add support for overriding character mapping
auxdisplay: linedisp: Provide struct linedisp_ops for future extension
auxdisplay: linedisp: Move exported symbols to a namespace
auxdisplay: linedisp: Add missing header(s)
auxdisplay: linedisp: Unshadow error codes in ->store()
auxdisplay: linedisp: Use unique number for id
...
| -rw-r--r-- | Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml | 4 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/auxdisplay/gpio-7-segment.yaml | 55 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/auxdisplay/hit,hd44780.yaml | 68 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml | 54 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml | 4 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/auxdisplay/maxim,max6959.yaml | 44 | ||||
| -rw-r--r-- | MAINTAINERS | 8 | ||||
| -rw-r--r-- | drivers/auxdisplay/Kconfig | 25 | ||||
| -rw-r--r-- | drivers/auxdisplay/Makefile | 2 | ||||
| -rw-r--r-- | drivers/auxdisplay/cfag12864bfb.c | 6 | ||||
| -rw-r--r-- | drivers/auxdisplay/hd44780.c | 5 | ||||
| -rw-r--r-- | drivers/auxdisplay/ht16k33.c | 174 | ||||
| -rw-r--r-- | drivers/auxdisplay/img-ascii-lcd.c | 45 | ||||
| -rw-r--r-- | drivers/auxdisplay/line-display.c | 166 | ||||
| -rw-r--r-- | drivers/auxdisplay/line-display.h | 53 | ||||
| -rw-r--r-- | drivers/auxdisplay/max6959.c | 194 | ||||
| -rw-r--r-- | drivers/auxdisplay/panel.c | 202 | ||||
| -rw-r--r-- | drivers/auxdisplay/seg-led-gpio.c | 113 |
18 files changed, 886 insertions, 336 deletions
diff --git a/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml b/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml index 5d02bd032a85..439f7b811a94 100644 --- a/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml +++ b/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml @@ -39,6 +39,6 @@ additionalProperties: false examples: - | lcd@10008000 { - compatible = "arm,versatile-lcd"; - reg = <0x10008000 0x1000>; + compatible = "arm,versatile-lcd"; + reg = <0x10008000 0x1000>; }; diff --git a/Documentation/devicetree/bindings/auxdisplay/gpio-7-segment.yaml b/Documentation/devicetree/bindings/auxdisplay/gpio-7-segment.yaml new file mode 100644 index 000000000000..328954893c64 --- /dev/null +++ b/Documentation/devicetree/bindings/auxdisplay/gpio-7-segment.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/auxdisplay/gpio-7-segment.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO based LED segment display + +maintainers: + - Chris Packham <chris.packham@alliedtelesis.co.nz> + +properties: + compatible: + const: gpio-7-segment + + segment-gpios: + description: | + An array of GPIOs one per segment. The first GPIO corresponds to the A + segment, the seventh GPIO corresponds to the G segment. Some LED blocks + also have a decimal point which can be specified as an optional eighth + segment. + + -a- + | | + f b + | | + -g- + | | + e c + | | + -d- dp + + minItems: 7 + maxItems: 8 + +required: + - segment-gpios + +additionalProperties: false + +examples: + - | + + #include <dt-bindings/gpio/gpio.h> + + led-7seg { + compatible = "gpio-7-segment"; + segment-gpios = <&gpio 0 GPIO_ACTIVE_LOW>, + <&gpio 1 GPIO_ACTIVE_LOW>, + <&gpio 2 GPIO_ACTIVE_LOW>, + <&gpio 3 GPIO_ACTIVE_LOW>, + <&gpio 4 GPIO_ACTIVE_LOW>, + <&gpio 5 GPIO_ACTIVE_LOW>, + <&gpio 6 GPIO_ACTIVE_LOW>; + }; diff --git a/Documentation/devicetree/bindings/auxdisplay/hit,hd44780.yaml b/Documentation/devicetree/bindings/auxdisplay/hit,hd44780.yaml index 406a922a714e..3ca0e9863d83 100644 --- a/Documentation/devicetree/bindings/auxdisplay/hit,hd44780.yaml +++ b/Documentation/devicetree/bindings/auxdisplay/hit,hd44780.yaml @@ -84,42 +84,44 @@ additionalProperties: false examples: - | #include <dt-bindings/gpio/gpio.h> - auxdisplay { - compatible = "hit,hd44780"; - - data-gpios = <&hc595 0 GPIO_ACTIVE_HIGH>, - <&hc595 1 GPIO_ACTIVE_HIGH>, - <&hc595 2 GPIO_ACTIVE_HIGH>, - <&hc595 3 GPIO_ACTIVE_HIGH>; - enable-gpios = <&hc595 4 GPIO_ACTIVE_HIGH>; - rs-gpios = <&hc595 5 GPIO_ACTIVE_HIGH>; - - display-height-chars = <2>; - display-width-chars = <16>; + display-controller { + compatible = "hit,hd44780"; + + data-gpios = <&hc595 0 GPIO_ACTIVE_HIGH>, + <&hc595 1 GPIO_ACTIVE_HIGH>, + <&hc595 2 GPIO_ACTIVE_HIGH>, + <&hc595 3 GPIO_ACTIVE_HIGH>; + enable-gpios = <&hc595 4 GPIO_ACTIVE_HIGH>; + rs-gpios = <&hc595 5 GPIO_ACTIVE_HIGH>; + + display-height-chars = <2>; + display-width-chars = <16>; }; + - | #include <dt-bindings/gpio/gpio.h> i2c { - #address-cells = <1>; - #size-cells = <0>; - - pcf8574: pcf8574@27 { - compatible = "nxp,pcf8574"; - reg = <0x27>; - gpio-controller; - #gpio-cells = <2>; - }; + #address-cells = <1>; + #size-cells = <0>; + + pcf8574: gpio-expander@27 { + compatible = "nxp,pcf8574"; + reg = <0x27>; + gpio-controller; + #gpio-cells = <2>; + }; }; - hd44780 { - compatible = "hit,hd44780"; - display-height-chars = <2>; - display-width-chars = <16>; - data-gpios = <&pcf8574 4 0>, - <&pcf8574 5 0>, - <&pcf8574 6 0>, - <&pcf8574 7 0>; - enable-gpios = <&pcf8574 2 0>; - rs-gpios = <&pcf8574 0 0>; - rw-gpios = <&pcf8574 1 0>; - backlight-gpios = <&pcf8574 3 0>; + + display-controller { + compatible = "hit,hd44780"; + display-height-chars = <2>; + display-width-chars = <16>; + data-gpios = <&pcf8574 4 GPIO_ACTIVE_HIGH>, + <&pcf8574 5 GPIO_ACTIVE_HIGH>, + <&pcf8574 6 GPIO_ACTIVE_HIGH>, + <&pcf8574 7 GPIO_ACTIVE_HIGH>; + enable-gpios = <&pcf8574 2 GPIO_ACTIVE_HIGH>; + rs-gpios = <&pcf8574 0 GPIO_ACTIVE_HIGH>; + rw-gpios = <&pcf8574 1 GPIO_ACTIVE_HIGH>; + backlight-gpios = <&pcf8574 3 GPIO_ACTIVE_HIGH>; }; diff --git a/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml b/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml index be95f6b97b41..b90eec2077b4 100644 --- a/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml +++ b/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml @@ -74,31 +74,31 @@ examples: #include <dt-bindings/input/input.h> #include <dt-bindings/leds/common.h> i2c { - #address-cells = <1>; - #size-cells = <0>; - - ht16k33: ht16k33@70 { - compatible = "holtek,ht16k33"; - reg = <0x70>; - refresh-rate-hz = <20>; - interrupt-parent = <&gpio4>; - interrupts = <5 (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING)>; - debounce-delay-ms = <50>; - linux,keymap = <MATRIX_KEY(2, 0, KEY_F6)>, - <MATRIX_KEY(3, 0, KEY_F8)>, - <MATRIX_KEY(4, 0, KEY_F10)>, - <MATRIX_KEY(5, 0, KEY_F4)>, - <MATRIX_KEY(6, 0, KEY_F2)>, - <MATRIX_KEY(2, 1, KEY_F5)>, - <MATRIX_KEY(3, 1, KEY_F7)>, - <MATRIX_KEY(4, 1, KEY_F9)>, - <MATRIX_KEY(5, 1, KEY_F3)>, - <MATRIX_KEY(6, 1, KEY_F1)>; - - led { - color = <LED_COLOR_ID_RED>; - function = LED_FUNCTION_BACKLIGHT; - linux,default-trigger = "backlight"; - }; + #address-cells = <1>; + #size-cells = <0>; + + display-controller@70 { + compatible = "holtek,ht16k33"; + reg = <0x70>; + refresh-rate-hz = <20>; + interrupt-parent = <&gpio4>; + interrupts = <5 (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING)>; + debounce-delay-ms = <50>; + linux,keymap = <MATRIX_KEY(2, 0, KEY_F6)>, + <MATRIX_KEY(3, 0, KEY_F8)>, + <MATRIX_KEY(4, 0, KEY_F10)>, + <MATRIX_KEY(5, 0, KEY_F4)>, + <MATRIX_KEY(6, 0, KEY_F2)>, + <MATRIX_KEY(2, 1, KEY_F5)>, + <MATRIX_KEY(3, 1, KEY_F7)>, + <MATRIX_KEY(4, 1, KEY_F9)>, + <MATRIX_KEY(5, 1, KEY_F3)>, + <MATRIX_KEY(6, 1, KEY_F1)>; + + led { + color = <LED_COLOR_ID_RED>; + function = LED_FUNCTION_BACKLIGHT; + linux,default-trigger = "backlight"; }; - }; + }; + }; diff --git a/Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml b/Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml index 1899b23de7d1..55e9831b3f67 100644 --- a/Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml +++ b/Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml @@ -50,6 +50,6 @@ additionalProperties: false examples: - | lcd: lcd@17fff000 { - compatible = "img,boston-lcd"; - reg = <0x17fff000 0x8>; + compatible = "img,boston-lcd"; + reg = <0x17fff000 0x8>; }; diff --git a/Documentation/devicetree/bindings/auxdisplay/maxim,max6959.yaml b/Documentation/devicetree/bindings/auxdisplay/maxim,max6959.yaml new file mode 100644 index 000000000000..20dd9e8c8190 --- /dev/null +++ b/Documentation/devicetree/bindings/auxdisplay/maxim,max6959.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/auxdisplay/maxim,max6959.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MAX6958/6959 7-segment LED display controller + +maintainers: + - Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +description: + The Maxim MAX6958/6959 7-segment LED display controller provides + an I2C interface to up to four 7-segment LED digits. The MAX6959, + in comparison to MAX6958, adds input support. Type of the chip can + be autodetected via specific register read, and hence the features + may be enabled in the driver at run-time, in case they are requested + via Device Tree. A given hardware is simple and does not provide + any additional pins, such as reset or power enable. + +properties: + compatible: + const: maxim,max6959 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + display-controller@38 { + compatible = "maxim,max6959"; + reg = <0x38>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index d818866d6d73..c50e72258ba9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3389,11 +3389,15 @@ F: drivers/base/auxiliary.c F: include/linux/auxiliary_bus.h AUXILIARY DISPLAY DRIVERS -M: Miguel Ojeda <ojeda@kernel.org> -S: Maintained +M: Andy Shevchenko <andy@kernel.org> +R: Geert Uytterhoeven <geert@linux-m68k.org> +S: Odd Fixes +T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-auxdisplay.git F: Documentation/devicetree/bindings/auxdisplay/ F: drivers/auxdisplay/ F: include/linux/cfag12864b.h +F: include/uapi/linux/map_to_14segment.h +F: include/uapi/linux/map_to_7segment.h AVIA HX711 ANALOG DIGITAL CONVERTER IIO DRIVER M: Andreas Klinger <ak@it-klinger.de> diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index d944d5298eca..151d95f96b11 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig @@ -177,6 +177,20 @@ config HT16K33 Say yes here to add support for Holtek HT16K33, RAM mapping 16*8 LED controller driver with keyscan. +config MAX6959 + tristate "Maxim MAX6958/6959 7-segment LED controller" + depends on I2C + select REGMAP_I2C + select LINEDISP + help + If you say yes here you get support for the following Maxim chips + (I2C 7-segment LED display controller): + - MAX6958 + - MAX6959 (input support) + + This driver can also be built as a module. If so, the module + will be called max6959. + config LCD2S tristate "lcd2s 20x4 character display over I2C console" depends on I2C @@ -197,6 +211,17 @@ config ARM_CHARLCD line and the Linux version on the second line, but that's still useful. +config SEG_LED_GPIO + tristate "Generic 7-segment LED display" + depends on GPIOLIB || COMPILE_TEST + select LINEDISP + help + This driver supports a generic 7-segment LED display made up + of GPIO pins connected to the individual segments. + + This driver can also be built as a module. If so, the module + will be called seg-led-gpio. + menuconfig PARPORT_PANEL tristate "Parallel port LCD/Keypad Panel support" depends on PARPORT diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile index 6968ed4d3f0a..4a8ea41b0550 100644 --- a/drivers/auxdisplay/Makefile +++ b/drivers/auxdisplay/Makefile @@ -14,3 +14,5 @@ obj-$(CONFIG_HT16K33) += ht16k33.o obj-$(CONFIG_PARPORT_PANEL) += panel.o obj-$(CONFIG_LCD2S) += lcd2s.o obj-$(CONFIG_LINEDISP) += line-display.o +obj-$(CONFIG_MAX6959) += max6959.o +obj-$(CONFIG_SEG_LED_GPIO) += seg-led-gpio.o diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c index 5ba19c339f08..2b74dabe7e17 100644 --- a/drivers/auxdisplay/cfag12864bfb.c +++ b/drivers/auxdisplay/cfag12864bfb.c @@ -96,7 +96,7 @@ none: return ret; } -static int cfag12864bfb_remove(struct platform_device *device) +static void cfag12864bfb_remove(struct platform_device *device) { struct fb_info *info = platform_get_drvdata(device); @@ -104,13 +104,11 @@ static int cfag12864bfb_remove(struct platform_device *device) unregister_framebuffer(info); framebuffer_release(info); } - - return 0; } static struct platform_driver cfag12864bfb_driver = { .probe = cfag12864bfb_probe, - .remove = cfag12864bfb_remove, + .remove_new = cfag12864bfb_remove, .driver = { .name = CFAG12864BFB_NAME, }, diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c index d56a5d508ccd..7ac0b1b1d548 100644 --- a/drivers/auxdisplay/hd44780.c +++ b/drivers/auxdisplay/hd44780.c @@ -319,7 +319,7 @@ fail1: return ret; } -static int hd44780_remove(struct platform_device *pdev) +static void hd44780_remove(struct platform_device *pdev) { struct charlcd *lcd = platform_get_drvdata(pdev); struct hd44780_common *hdc = lcd->drvdata; @@ -329,7 +329,6 @@ static int hd44780_remove(struct platform_device *pdev) kfree(lcd->drvdata); kfree(lcd); - return 0; } static const struct of_device_id hd44780_of_match[] = { @@ -340,7 +339,7 @@ MODULE_DEVICE_TABLE(of, hd44780_of_match); static struct platform_driver hd44780_driver = { .probe = hd44780_probe, - .remove = hd44780_remove, + .remove_new = hd44780_remove, .driver = { .name = "hd44780", .of_match_table = hd44780_of_match, diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c index a90430b7d07b..96acfb2b58cd 100644 --- a/drivers/auxdisplay/ht16k33.c +++ b/drivers/auxdisplay/ht16k33.c @@ -15,6 +15,7 @@ #include <linux/property.h> #include <linux/fb.h> #include <linux/backlight.h> +#include <linux/container_of.h> #include <linux/input.h> #include <linux/input/matrix_keypad.h> #include <linux/leds.h> @@ -85,16 +86,6 @@ struct ht16k33_fbdev { uint8_t *cache; }; -struct ht16k33_seg { - struct linedisp linedisp; - union { - struct seg7_conversion_map seg7; - struct seg14_conversion_map seg14; - } map; - unsigned int map_size; - char curr[4]; -}; - struct ht16k33_priv { struct i2c_client *client; struct delayed_work work; @@ -102,12 +93,21 @@ struct ht16k33_priv { struct ht16k33_keypad keypad; union { struct ht16k33_fbdev fbdev; - struct ht16k33_seg seg; + struct linedisp linedisp; }; enum display_type type; uint8_t blink; }; +#define ht16k33_work_to_priv(p) \ + container_of(p, struct ht16k33_priv, work.work) + +#define ht16k33_led_to_priv(p) \ + container_of(p, struct ht16k33_priv, led) + +#define ht16k33_linedisp_to_priv(p) \ + container_of(p, struct ht16k33_priv, linedisp) + static const struct fb_fix_screeninfo ht16k33_fb_fix = { .id = DRIVER_NAME, .type = FB_TYPE_PACKED_PIXELS, @@ -135,33 +135,6 @@ static const struct fb_var_screeninfo ht16k33_fb_var = { .vmode = FB_VMODE_NONINTERLACED, }; -static const SEG7_DEFAULT_MAP(initial_map_seg7); -static const SEG14_DEFAULT_MAP(initial_map_seg14); - -static ssize_t map_seg_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct ht16k33_priv *priv = dev_get_drvdata(dev); - - memcpy(buf, &priv->seg.map, priv->seg.map_size); - return priv->seg.map_size; -} - -static ssize_t map_seg_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t cnt) -{ - struct ht16k33_priv *priv = dev_get_drvdata(dev); - - if (cnt != priv->seg.map_size) - return -EINVAL; - - memcpy(&priv->seg.map, buf, cnt); - return cnt; -} - -static DEVICE_ATTR(map_seg7, 0644, map_seg_show, map_seg_store); -static DEVICE_ATTR(map_seg14, 0644, map_seg_show, map_seg_store); - static int ht16k33_display_on(struct ht16k33_priv *priv) { uint8_t data = REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON | priv->blink; @@ -195,8 +168,7 @@ static int ht16k33_brightness_set(struct ht16k33_priv *priv, static int ht16k33_brightness_set_blocking(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct ht16k33_priv *priv = container_of(led_cdev, struct ht16k33_priv, - led); + struct ht16k33_priv *priv = ht16k33_led_to_priv(led_cdev); return ht16k33_brightness_set(priv, brightness); } @@ -204,8 +176,7 @@ static int ht16k33_brightness_set_blocking(struct led_classdev *led_cdev, static int ht16k33_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { - struct ht16k33_priv *priv = container_of(led_cdev, struct ht16k33_priv, - led); + struct ht16k33_priv *priv = ht16k33_led_to_priv(led_cdev); unsigned int delay; uint8_t blink; int err; @@ -247,8 +218,7 @@ static void ht16k33_fb_queue(struct ht16k33_priv *priv) */ static void ht16k33_fb_update(struct work_struct *work) { - struct ht16k33_priv *priv = container_of(work, struct ht16k33_priv, - work.work); + struct ht16k33_priv *priv = ht16k33_work_to_priv(work); struct ht16k33_fbdev *fbdev = &priv->fbdev; uint8_t *p1, *p2; @@ -440,51 +410,71 @@ static void ht16k33_keypad_stop(struct input_dev *dev) disable_irq(keypad->client->irq); } -static void ht16k33_linedisp_update(struct linedisp *linedisp) -{ - struct ht16k33_priv *priv = container_of(linedisp, struct ht16k33_priv, - seg.linedisp); - - schedule_delayed_work(&priv->work, 0); -} - static void ht16k33_seg7_update(struct work_struct *work) { - struct ht16k33_priv *priv = container_of(work, struct ht16k33_priv, - work.work); - struct ht16k33_seg *seg = &priv->seg; - char *s = seg->curr; + struct ht16k33_priv *priv = ht16k33_work_to_priv(work); + struct linedisp_map *map = priv->linedisp.map; + char *s = priv->linedisp.buf; uint8_t buf[9]; - buf[0] = map_to_seg7(&seg->map.seg7, *s++); + buf[0] = map_to_seg7(&map->map.seg7, *s++); buf[1] = 0; - buf[2] = map_to_seg7(&seg->map.seg7, *s++); + buf[2] = map_to_seg7(&map->map.seg7, *s++); buf[3] = 0; buf[4] = 0; buf[5] = 0; - buf[6] = map_to_seg7(&seg->map.seg7, *s++); + buf[6] = map_to_seg7(&map->map.seg7, *s++); buf[7] = 0; - buf[8] = map_to_seg7(&seg->map.seg7, *s++); + buf[8] = map_to_seg7(&map->map.seg7, *s++); i2c_smbus_write_i2c_block_data(priv->client, 0, ARRAY_SIZE(buf), buf); } static void ht16k33_seg14_update(struct work_struct *work) { - struct ht16k33_priv *priv = container_of(work, struct ht16k33_priv, - work.work); - struct ht16k33_seg *seg = &priv->seg; - char *s = seg->curr; + struct ht16k33_priv *priv = ht16k33_work_to_priv(work); + struct linedisp_map *map = priv->linedisp.map; + char *s = priv->linedisp.buf; uint8_t buf[8]; - put_unaligned_le16(map_to_seg14(&seg->map.seg14, *s++), buf); - put_unaligned_le16(map_to_seg14(&seg->map.seg14, *s++), buf + 2); - put_unaligned_le16(map_to_seg14(&seg->map.seg14, *s++), buf + 4); - put_unaligned_le16(map_to_seg14(&seg->map.seg14, *s++), buf + 6); + put_unaligned_le16(map_to_seg14(&map->map.seg14, *s++), buf + 0); + put_unaligned_le16(map_to_seg14(&map->map.seg14, *s++), buf + 2); + put_unaligned_le16(map_to_seg14(&map->map.seg14, *s++), buf + 4); + put_unaligned_le16(map_to_seg14(&map->map.seg14, *s++), buf + 6); i2c_smbus_write_i2c_block_data(priv->client, 0, ARRAY_SIZE(buf), buf); } +static int ht16k33_linedisp_get_map_type(struct linedisp *linedisp) +{ + struct ht16k33_priv *priv = ht16k33_linedisp_to_priv(linedisp); + + switch (priv->type) { + case DISP_QUAD_7SEG: + INIT_DELAYED_WORK(&priv->work, ht16k33_seg7_update); + return LINEDISP_MAP_SEG7; + + case DISP_QUAD_14SEG: + INIT_DELAYED_WORK(&priv->work, ht16k33_seg14_update); + return LINEDISP_MAP_SEG14; + + default: + return -EINVAL; + } +} + +static void ht16k33_linedisp_update(struct linedisp *linedisp) +{ + struct ht16k33_priv *priv = ht16k33_linedisp_to_priv(linedisp); + + schedule_delayed_work(&priv->work, 0); +} + +static const struct linedisp_ops ht16k33_linedisp_ops = { + .get_map_type = ht16k33_linedisp_get_map_type, + .update = ht16k33_linedisp_update, +}; + static int ht16k33_led_probe(struct device *dev, struct led_classdev *led, unsigned int brightness) { @@ -666,47 +656,14 @@ err_fbdev_buffer: static int ht16k33_seg_probe(struct device *dev, struct ht16k33_priv *priv, uint32_t brightness) { - struct ht16k33_seg *seg = &priv->seg; + struct linedisp *linedisp = &priv->linedisp; int err; err = ht16k33_brightness_set(priv, brightness); if (err) return err; - switch (priv->type) { - case DISP_MATRIX: - /* not handled here */ - err = -EINVAL; - break; - - case DISP_QUAD_7SEG: - INIT_DELAYED_WORK(&priv->work, ht16k33_seg7_update); - seg->map.seg7 = initial_map_seg7; - seg->map_size = sizeof(seg->map.seg7); - err = device_create_file(dev, &dev_attr_map_seg7); - break; - - case DISP_QUAD_14SEG: - INIT_DELAYED_WORK(&priv->work, ht16k33_seg14_update); - seg->map.seg14 = initial_map_seg14; - seg->map_size = sizeof(seg->map.seg14); - err = device_create_file(dev, &dev_attr_map_seg14); - break; - } - if (err) - return err; - - err = linedisp_register(&seg->linedisp, dev, 4, seg->curr, - ht16k33_linedisp_update); - if (err) - goto err_remove_map_file; - - return 0; - -err_remove_map_file: - device_remove_file(dev, &dev_attr_map_seg7); - device_remove_file(dev, &dev_attr_map_seg14); - return err; + return linedisp_register(linedisp, dev, 4, &ht16k33_linedisp_ops); } static int ht16k33_probe(struct i2c_client *client) @@ -770,6 +727,9 @@ static int ht16k33_probe(struct i2c_client *client) /* Segment Display */ err = ht16k33_seg_probe(dev, priv, dft_brightness); break; + + default: + return -EINVAL; } return err; } @@ -790,9 +750,10 @@ static void ht16k33_remove(struct i2c_client *client) case DISP_QUAD_7SEG: case DISP_QUAD_14SEG: - linedisp_unregister(&priv->seg.linedisp); - device_remove_file(&client->dev, &dev_attr_map_seg7); - device_remove_file(&client->dev, &dev_attr_map_seg14); + linedisp_unregister(&priv->linedisp); + break; + + default: break; } } @@ -831,4 +792,5 @@ module_i2c_driver(ht16k33_driver); MODULE_DESCRIPTION("Holtek HT16K33 driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(LINEDISP); MODULE_AUTHOR("Robin van der Gracht <robin@protonic.nl>"); diff --git a/drivers/auxdisplay/img-ascii-lcd.c b/drivers/auxdisplay/img-ascii-lcd.c index 56efda0740fb..9ba132dc6143 100644 --- a/drivers/auxdisplay/img-ascii-lcd.c +++ b/drivers/auxdisplay/img-ascii-lcd.c @@ -22,32 +22,30 @@ struct img_ascii_lcd_ctx; * struct img_ascii_lcd_config - Configuration information about an LCD model * @num_chars: the number of characters the LCD can display * @external_regmap: true if registers are in a system controller, else false - * @update: function called to update the LCD + * @ops: character line display operations */ struct img_ascii_lcd_config { unsigned int num_chars; bool external_regmap; - void (*update)(struct linedisp *linedisp); + const struct linedisp_ops ops; }; /** * struct img_ascii_lcd_ctx - Private data structure + * @linedisp: line display structure * @base: the base address of the LCD registers * @regmap: the regmap through which LCD registers are accessed * @offset: the offset within regmap to the start of the LCD registers * @cfg: pointer to the LCD model configuration - * @linedisp: line display structure - * @curr: the string currently displayed on the LCD */ struct img_ascii_lcd_ctx { + struct linedisp linedisp; union { void __iomem *base; struct regmap *regmap; }; u32 offset; const struct img_ascii_lcd_config *cfg; - struct linedisp linedisp; - char curr[] __aligned(8); }; /* @@ -61,12 +59,12 @@ static void boston_update(struct linedisp *linedisp) ulong val; #if BITS_PER_LONG == 64 - val = *((u64 *)&ctx->curr[0]); + val = *((u64 *)&linedisp->buf[0]); __raw_writeq(val, ctx->base); #elif BITS_PER_LONG == 32 - val = *((u32 *)&ctx->curr[0]); + val = *((u32 *)&linedisp->buf[0]); __raw_writel(val, ctx->base); - val = *((u32 *)&ctx->curr[4]); + val = *((u32 *)&linedisp->buf[4]); __raw_writel(val, ctx->base + 4); #else # error Not 32 or 64 bit @@ -75,7 +73,9 @@ static void boston_update(struct linedisp *linedisp) static struct img_ascii_lcd_config boston_config = { .num_chars = 8, - .update = boston_update, + .ops = { + .update = boston_update, + }, }; /* @@ -91,7 +91,7 @@ static void malta_update(struct linedisp *linedisp) for (i = 0; i < linedisp->num_chars; i++) { err = regmap_write(ctx->regmap, - ctx->offset + (i * 8), ctx->curr[i]); + ctx->offset + (i * 8), linedisp->buf[i]); if (err) break; } @@ -103,7 +103,9 @@ static void malta_update(struct linedisp *linedisp) static struct img_ascii_lcd_config malta_config = { .num_chars = 8, .external_regmap = true, - .update = malta_update, + .ops = { + .update = malta_update, + }, }; /* @@ -191,7 +193,7 @@ static void sead3_update(struct linedisp *linedisp) err = regmap_write(ctx->regmap, ctx->offset + SEAD3_REG_LCD_DATA, - ctx->curr[i]); + linedisp->buf[i]); if (err) break; } @@ -203,7 +205,9 @@ static void sead3_update(struct linedisp *linedisp) static struct img_ascii_lcd_config sead3_config = { .num_chars = 16, .external_regmap = true, - .update = sead3_update, + .ops = { + .update = sead3_update, + }, }; static const struct of_device_id img_ascii_lcd_matches[] = { @@ -230,7 +234,7 @@ static int img_ascii_lcd_probe(struct platform_device *pdev) struct img_ascii_lcd_ctx *ctx; int err; - ctx = devm_kzalloc(dev, sizeof(*ctx) + cfg->num_chars, GFP_KERNEL); + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);< |
