[v2,12/15] auxdisplay: ht16k33: Switch to use line display character mapping

Message ID 20240212170423.2860895-13-andriy.shevchenko@linux.intel.com
State New
Headers
Series auxdisplay: linedisp: Clean up and add new driver |

Commit Message

Andy Shevchenko Feb. 12, 2024, 5:01 p.m. UTC
  Since line display library supports necessary bits to map the characters
(if required), switch this driver to use that.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/auxdisplay/ht16k33.c | 109 +++++++++++------------------------
 1 file changed, 34 insertions(+), 75 deletions(-)
  

Comments

Robin van der Gracht Feb. 15, 2024, 8:09 a.m. UTC | #1
On Mon, 12 Feb 2024 19:01:45 +0200
Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:

> Since line display library supports necessary bits to map the characters
> (if required), switch this driver to use that.
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
>  drivers/auxdisplay/ht16k33.c | 109 +++++++++++------------------------
>  1 file changed, 34 insertions(+), 75 deletions(-)
> 
> diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c
> index 75c4a8d31642..b104f08252dd 100644
> --- a/drivers/auxdisplay/ht16k33.c
> +++ b/drivers/auxdisplay/ht16k33.c

Acked-by: Robin van der Gracht <robin@protonic.nl>
  
Geert Uytterhoeven Feb. 15, 2024, 8:16 a.m. UTC | #2
Hi Andy,

On Mon, Feb 12, 2024 at 6:04 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
> Since line display library supports necessary bits to map the characters
> (if required), switch this driver to use that.
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

Thanks for your patch!

> --- a/drivers/auxdisplay/ht16k33.c
> +++ b/drivers/auxdisplay/ht16k33.c

> +static int ht16k33_linedisp_get_map_type(struct linedisp *linedisp)
> +{
> +       struct ht16k33_priv *priv = container_of(linedisp, struct ht16k33_priv,
> +                                                seg.linedisp);
> +
> +       switch (priv->type) {
> +       case DISP_MATRIX:
> +               /* not handled here */
> +               return -EINVAL;
> +
> +       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;
> +       }

error: control reaches end of non-void function [-Werror=return-type]

Missing "return -EINVAL";

This case cannot happen, so it wasn't handled in the old code.
But with the new code, it fails at compile-time.

Gr{oetje,eeting}s,

                        Geert
  
Geert Uytterhoeven Feb. 15, 2024, 10:44 a.m. UTC | #3
Hi Andy,

On Mon, Feb 12, 2024 at 6:04 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
> Since line display library supports necessary bits to map the characters
> (if required), switch this driver to use that.
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

Thanks for your patch!

Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>

Minor nits below.

> --- a/drivers/auxdisplay/ht16k33.c
> +++ b/drivers/auxdisplay/ht16k33.c
> @@ -445,18 +413,20 @@ 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;
> +       struct linedisp *linedisp = &seg->linedisp;
> +       struct linedisp_map *map = linedisp->map;

struct linedisp_map *map = seg.linedisp->map;

as linedisp is not used below.

>         char *s = seg->curr;
>         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);
>  }
> @@ -466,17 +436,39 @@ 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;
> +       struct linedisp *linedisp = &seg->linedisp;
> +       struct linedisp_map *map = linedisp->map;

Likewise.

>         char *s = seg->curr;
>         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);
>  }

Gr{oetje,eeting}s,

                        Geert
  
Geert Uytterhoeven Feb. 15, 2024, 10:47 a.m. UTC | #4
On Thu, Feb 15, 2024 at 11:44 AM Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On Mon, Feb 12, 2024 at 6:04 PM Andy Shevchenko
> <andriy.shevchenko@linux.intel.com> wrote:
> > Since line display library supports necessary bits to map the characters
> > (if required), switch this driver to use that.
> >
> > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>
> Thanks for your patch!
>
> Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>

With the missing return-statement reported before added, of course ;-)

Gr{oetje,eeting}s,

                        Geert
  
Andy Shevchenko Feb. 15, 2024, 12:20 p.m. UTC | #5
On Thu, Feb 15, 2024 at 09:16:05AM +0100, Geert Uytterhoeven wrote:
> On Mon, Feb 12, 2024 at 6:04 PM Andy Shevchenko
> <andriy.shevchenko@linux.intel.com> wrote:

..

> > +static int ht16k33_linedisp_get_map_type(struct linedisp *linedisp)
> > +{
> > +       struct ht16k33_priv *priv = container_of(linedisp, struct ht16k33_priv,
> > +                                                seg.linedisp);
> > +
> > +       switch (priv->type) {
> > +       case DISP_MATRIX:
> > +               /* not handled here */
> > +               return -EINVAL;
> > +
> > +       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;
> > +       }
> 
> error: control reaches end of non-void function [-Werror=return-type]
> 
> Missing "return -EINVAL";
> 
> This case cannot happen, so it wasn't handled in the old code.
> But with the new code, it fails at compile-time.

What is the command line and compiler you are using?
I have compiled this code without issues.
  
Geert Uytterhoeven Feb. 15, 2024, 12:31 p.m. UTC | #6
On Thu, Feb 15, 2024 at 1:20 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> On Thu, Feb 15, 2024 at 09:16:05AM +0100, Geert Uytterhoeven wrote:
> > On Mon, Feb 12, 2024 at 6:04 PM Andy Shevchenko
> > <andriy.shevchenko@linux.intel.com> wrote:
>
> ...
>
> > > +static int ht16k33_linedisp_get_map_type(struct linedisp *linedisp)
> > > +{
> > > +       struct ht16k33_priv *priv = container_of(linedisp, struct ht16k33_priv,
> > > +                                                seg.linedisp);
> > > +
> > > +       switch (priv->type) {
> > > +       case DISP_MATRIX:
> > > +               /* not handled here */
> > > +               return -EINVAL;
> > > +
> > > +       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;
> > > +       }
> >
> > error: control reaches end of non-void function [-Werror=return-type]
> >
> > Missing "return -EINVAL";
> >
> > This case cannot happen, so it wasn't handled in the old code.
> > But with the new code, it fails at compile-time.
>
> What is the command line and compiler you are using?
> I have compiled this code without issues.

riscv64-linux-gnu-gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
aarch64-linux-gnu-gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)

Gr{oetje,eeting}s,

                        Geert
  

Patch

diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c
index 75c4a8d31642..b104f08252dd 100644
--- a/drivers/auxdisplay/ht16k33.c
+++ b/drivers/auxdisplay/ht16k33.c
@@ -87,11 +87,6 @@  struct ht16k33_fbdev {
 
 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];
 };
 
@@ -135,33 +130,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;
@@ -445,18 +413,20 @@  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;
+	struct linedisp *linedisp = &seg->linedisp;
+	struct linedisp_map *map = linedisp->map;
 	char *s = seg->curr;
 	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);
 }
@@ -466,17 +436,39 @@  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;
+	struct linedisp *linedisp = &seg->linedisp;
+	struct linedisp_map *map = linedisp->map;
 	char *s = seg->curr;
 	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 = container_of(linedisp, struct ht16k33_priv,
+						 seg.linedisp);
+
+	switch (priv->type) {
+	case DISP_MATRIX:
+		/* not handled here */
+		return -EINVAL;
+
+	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;
+	}
+}
+
 static void ht16k33_linedisp_update(struct linedisp *linedisp)
 {
 	struct ht16k33_priv *priv = container_of(linedisp, struct ht16k33_priv,
@@ -486,6 +478,7 @@  static void ht16k33_linedisp_update(struct linedisp *linedisp)
 }
 
 static const struct linedisp_ops ht16k33_linedisp_ops = {
+	.get_map_type = ht16k33_linedisp_get_map_type,
 	.update = ht16k33_linedisp_update,
 };
 
@@ -677,39 +670,7 @@  static int ht16k33_seg_probe(struct device *dev, struct ht16k33_priv *priv,
 	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_ops);
-	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(&seg->linedisp, dev, 4, seg->curr, &ht16k33_linedisp_ops);
 }
 
 static int ht16k33_probe(struct i2c_client *client)
@@ -794,8 +755,6 @@  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);
 		break;
 	}
 }