Skip to content

Commit

Permalink
auxdisplay: ht16k33: Switch to use line display character mapping
Browse files Browse the repository at this point in the history
Since line display library supports necessary bits to map the characters
(if required), switch this driver to use that.

Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Robin van der Gracht <robin@protonic.nl>
Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
  • Loading branch information
Andy Shevchenko committed Feb 26, 2024
1 parent 0ee6eb8 commit 815876d
Showing 1 changed file with 30 additions and 73 deletions.
103 changes: 30 additions & 73 deletions drivers/auxdisplay/ht16k33.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,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;
};

struct ht16k33_priv {
Expand Down Expand Up @@ -144,33 +139,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;
Expand Down Expand Up @@ -450,18 +418,19 @@ static void ht16k33_seg7_update(struct work_struct *work)
{
struct ht16k33_priv *priv = ht16k33_work_to_priv(work);
struct ht16k33_seg *seg = &priv->seg;
struct linedisp_map *map = seg->linedisp.map;
char *s = seg->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);
}
Expand All @@ -470,17 +439,36 @@ static void ht16k33_seg14_update(struct work_struct *work)
{
struct ht16k33_priv *priv = ht16k33_work_to_priv(work);
struct ht16k33_seg *seg = &priv->seg;
struct linedisp_map *map = seg->linedisp.map;
char *s = seg->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);
Expand All @@ -489,6 +477,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,
};

Expand Down Expand Up @@ -680,37 +669,7 @@ static int ht16k33_seg_probe(struct device *dev, struct ht16k33_priv *priv,
if (err)
return err;

switch (priv->type) {
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;

default:
return -EINVAL;
}
if (err)
return err;

err = linedisp_register(&seg->linedisp, dev, 4, &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, &ht16k33_linedisp_ops);
}

static int ht16k33_probe(struct i2c_client *client)
Expand Down Expand Up @@ -798,8 +757,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;

default:
Expand Down

0 comments on commit 815876d

Please sign in to comment.