linux/drivers/auxdisplay/ht16k33.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * HT16K33 driver
   4 *
   5 * Author: Robin van der Gracht <robin@protonic.nl>
   6 *
   7 * Copyright: (C) 2016 Protonic Holland.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/interrupt.h>
  13#include <linux/i2c.h>
  14#include <linux/of.h>
  15#include <linux/fb.h>
  16#include <linux/slab.h>
  17#include <linux/backlight.h>
  18#include <linux/input.h>
  19#include <linux/input/matrix_keypad.h>
  20#include <linux/workqueue.h>
  21#include <linux/mm.h>
  22
  23/* Registers */
  24#define REG_SYSTEM_SETUP                0x20
  25#define REG_SYSTEM_SETUP_OSC_ON         BIT(0)
  26
  27#define REG_DISPLAY_SETUP               0x80
  28#define REG_DISPLAY_SETUP_ON            BIT(0)
  29
  30#define REG_ROWINT_SET                  0xA0
  31#define REG_ROWINT_SET_INT_EN           BIT(0)
  32#define REG_ROWINT_SET_INT_ACT_HIGH     BIT(1)
  33
  34#define REG_BRIGHTNESS                  0xE0
  35
  36/* Defines */
  37#define DRIVER_NAME                     "ht16k33"
  38
  39#define MIN_BRIGHTNESS                  0x1
  40#define MAX_BRIGHTNESS                  0x10
  41
  42#define HT16K33_MATRIX_LED_MAX_COLS     8
  43#define HT16K33_MATRIX_LED_MAX_ROWS     16
  44#define HT16K33_MATRIX_KEYPAD_MAX_COLS  3
  45#define HT16K33_MATRIX_KEYPAD_MAX_ROWS  12
  46
  47#define BYTES_PER_ROW           (HT16K33_MATRIX_LED_MAX_ROWS / 8)
  48#define HT16K33_FB_SIZE         (HT16K33_MATRIX_LED_MAX_COLS * BYTES_PER_ROW)
  49
  50struct ht16k33_keypad {
  51        struct i2c_client *client;
  52        struct input_dev *dev;
  53        uint32_t cols;
  54        uint32_t rows;
  55        uint32_t row_shift;
  56        uint32_t debounce_ms;
  57        uint16_t last_key_state[HT16K33_MATRIX_KEYPAD_MAX_COLS];
  58
  59        wait_queue_head_t wait;
  60        bool stopped;
  61};
  62
  63struct ht16k33_fbdev {
  64        struct fb_info *info;
  65        uint32_t refresh_rate;
  66        uint8_t *buffer;
  67        uint8_t *cache;
  68        struct delayed_work work;
  69};
  70
  71struct ht16k33_priv {
  72        struct i2c_client *client;
  73        struct ht16k33_keypad keypad;
  74        struct ht16k33_fbdev fbdev;
  75};
  76
  77static const struct fb_fix_screeninfo ht16k33_fb_fix = {
  78        .id             = DRIVER_NAME,
  79        .type           = FB_TYPE_PACKED_PIXELS,
  80        .visual         = FB_VISUAL_MONO10,
  81        .xpanstep       = 0,
  82        .ypanstep       = 0,
  83        .ywrapstep      = 0,
  84        .line_length    = HT16K33_MATRIX_LED_MAX_ROWS,
  85        .accel          = FB_ACCEL_NONE,
  86};
  87
  88static const struct fb_var_screeninfo ht16k33_fb_var = {
  89        .xres = HT16K33_MATRIX_LED_MAX_ROWS,
  90        .yres = HT16K33_MATRIX_LED_MAX_COLS,
  91        .xres_virtual = HT16K33_MATRIX_LED_MAX_ROWS,
  92        .yres_virtual = HT16K33_MATRIX_LED_MAX_COLS,
  93        .bits_per_pixel = 1,
  94        .red = { 0, 1, 0 },
  95        .green = { 0, 1, 0 },
  96        .blue = { 0, 1, 0 },
  97        .left_margin = 0,
  98        .right_margin = 0,
  99        .upper_margin = 0,
 100        .lower_margin = 0,
 101        .vmode = FB_VMODE_NONINTERLACED,
 102};
 103
 104static int ht16k33_display_on(struct ht16k33_priv *priv)
 105{
 106        uint8_t data = REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON;
 107
 108        return i2c_smbus_write_byte(priv->client, data);
 109}
 110
 111static int ht16k33_display_off(struct ht16k33_priv *priv)
 112{
 113        return i2c_smbus_write_byte(priv->client, REG_DISPLAY_SETUP);
 114}
 115
 116static void ht16k33_fb_queue(struct ht16k33_priv *priv)
 117{
 118        struct ht16k33_fbdev *fbdev = &priv->fbdev;
 119
 120        schedule_delayed_work(&fbdev->work,
 121                              msecs_to_jiffies(HZ / fbdev->refresh_rate));
 122}
 123
 124/*
 125 * This gets the fb data from cache and copies it to ht16k33 display RAM
 126 */
 127static void ht16k33_fb_update(struct work_struct *work)
 128{
 129        struct ht16k33_fbdev *fbdev =
 130                container_of(work, struct ht16k33_fbdev, work.work);
 131        struct ht16k33_priv *priv =
 132                container_of(fbdev, struct ht16k33_priv, fbdev);
 133
 134        uint8_t *p1, *p2;
 135        int len, pos = 0, first = -1;
 136
 137        p1 = fbdev->cache;
 138        p2 = fbdev->buffer;
 139
 140        /* Search for the first byte with changes */
 141        while (pos < HT16K33_FB_SIZE && first < 0) {
 142                if (*(p1++) - *(p2++))
 143                        first = pos;
 144                pos++;
 145        }
 146
 147        /* No changes found */
 148        if (first < 0)
 149                goto requeue;
 150
 151        len = HT16K33_FB_SIZE - first;
 152        p1 = fbdev->cache + HT16K33_FB_SIZE - 1;
 153        p2 = fbdev->buffer + HT16K33_FB_SIZE - 1;
 154
 155        /* Determine i2c transfer length */
 156        while (len > 1) {
 157                if (*(p1--) - *(p2--))
 158                        break;
 159                len--;
 160        }
 161
 162        p1 = fbdev->cache + first;
 163        p2 = fbdev->buffer + first;
 164        if (!i2c_smbus_write_i2c_block_data(priv->client, first, len, p2))
 165                memcpy(p1, p2, len);
 166requeue:
 167        ht16k33_fb_queue(priv);
 168}
 169
 170static int ht16k33_initialize(struct ht16k33_priv *priv)
 171{
 172        uint8_t byte;
 173        int err;
 174        uint8_t data[HT16K33_MATRIX_LED_MAX_COLS * 2];
 175
 176        /* Clear RAM (8 * 16 bits) */
 177        memset(data, 0, sizeof(data));
 178        err = i2c_smbus_write_block_data(priv->client, 0, sizeof(data), data);
 179        if (err)
 180                return err;
 181
 182        /* Turn on internal oscillator */
 183        byte = REG_SYSTEM_SETUP_OSC_ON | REG_SYSTEM_SETUP;
 184        err = i2c_smbus_write_byte(priv->client, byte);
 185        if (err)
 186                return err;
 187
 188        /* Configure INT pin */
 189        byte = REG_ROWINT_SET | REG_ROWINT_SET_INT_ACT_HIGH;
 190        if (priv->client->irq > 0)
 191                byte |= REG_ROWINT_SET_INT_EN;
 192        return i2c_smbus_write_byte(priv->client, byte);
 193}
 194
 195static int ht16k33_bl_update_status(struct backlight_device *bl)
 196{
 197        int brightness = bl->props.brightness;
 198        struct ht16k33_priv *priv = bl_get_data(bl);
 199
 200        if (bl->props.power != FB_BLANK_UNBLANK ||
 201            bl->props.fb_blank != FB_BLANK_UNBLANK ||
 202            bl->props.state & BL_CORE_FBBLANK || brightness == 0) {
 203                return ht16k33_display_off(priv);
 204        }
 205
 206        ht16k33_display_on(priv);
 207        return i2c_smbus_write_byte(priv->client,
 208                                    REG_BRIGHTNESS | (brightness - 1));
 209}
 210
 211static int ht16k33_bl_check_fb(struct backlight_device *bl, struct fb_info *fi)
 212{
 213        struct ht16k33_priv *priv = bl_get_data(bl);
 214
 215        return (fi == NULL) || (fi->par == priv);
 216}
 217
 218static const struct backlight_ops ht16k33_bl_ops = {
 219        .update_status  = ht16k33_bl_update_status,
 220        .check_fb       = ht16k33_bl_check_fb,
 221};
 222
 223static int ht16k33_mmap(struct fb_info *info, struct vm_area_struct *vma)
 224{
 225        struct ht16k33_priv *priv = info->par;
 226        struct page *pages = virt_to_page(priv->fbdev.buffer);
 227
 228        return vm_map_pages_zero(vma, &pages, 1);
 229}
 230
 231static struct fb_ops ht16k33_fb_ops = {
 232        .owner = THIS_MODULE,
 233        .fb_read = fb_sys_read,
 234        .fb_write = fb_sys_write,
 235        .fb_fillrect = sys_fillrect,
 236        .fb_copyarea = sys_copyarea,
 237        .fb_imageblit = sys_imageblit,
 238        .fb_mmap = ht16k33_mmap,
 239};
 240
 241/*
 242 * This gets the keys from keypad and reports it to input subsystem.
 243 * Returns true if a key is pressed.
 244 */
 245static bool ht16k33_keypad_scan(struct ht16k33_keypad *keypad)
 246{
 247        const unsigned short *keycodes = keypad->dev->keycode;
 248        u16 new_state[HT16K33_MATRIX_KEYPAD_MAX_COLS];
 249        __le16 data[HT16K33_MATRIX_KEYPAD_MAX_COLS];
 250        unsigned long bits_changed;
 251        int row, col, code;
 252        int rc;
 253        bool pressed = false;
 254
 255        rc = i2c_smbus_read_i2c_block_data(keypad->client, 0x40,
 256                                           sizeof(data), (u8 *)data);
 257        if (rc != sizeof(data)) {
 258                dev_err(&keypad->client->dev,
 259                        "Failed to read key data, rc=%d\n", rc);
 260                return false;
 261        }
 262
 263        for (col = 0; col < keypad->cols; col++) {
 264                new_state[col] = le16_to_cpu(data[col]);
 265                if (new_state[col])
 266                        pressed = true;
 267                bits_changed = keypad->last_key_state[col] ^ new_state[col];
 268
 269                for_each_set_bit(row, &bits_changed, BITS_PER_LONG) {
 270                        code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
 271                        input_event(keypad->dev, EV_MSC, MSC_SCAN, code);
 272                        input_report_key(keypad->dev, keycodes[code],
 273                                         new_state[col] & BIT(row));
 274                }
 275        }
 276        input_sync(keypad->dev);
 277        memcpy(keypad->last_key_state, new_state, sizeof(u16) * keypad->cols);
 278
 279        return pressed;
 280}
 281
 282static irqreturn_t ht16k33_keypad_irq_thread(int irq, void *dev)
 283{
 284        struct ht16k33_keypad *keypad = dev;
 285
 286        do {
 287                wait_event_timeout(keypad->wait, keypad->stopped,
 288                                    msecs_to_jiffies(keypad->debounce_ms));
 289                if (keypad->stopped)
 290                        break;
 291        } while (ht16k33_keypad_scan(keypad));
 292
 293        return IRQ_HANDLED;
 294}
 295
 296static int ht16k33_keypad_start(struct input_dev *dev)
 297{
 298        struct ht16k33_keypad *keypad = input_get_drvdata(dev);
 299
 300        keypad->stopped = false;
 301        mb();
 302        enable_irq(keypad->client->irq);
 303
 304        return 0;
 305}
 306
 307static void ht16k33_keypad_stop(struct input_dev *dev)
 308{
 309        struct ht16k33_keypad *keypad = input_get_drvdata(dev);
 310
 311        keypad->stopped = true;
 312        mb();
 313        wake_up(&keypad->wait);
 314        disable_irq(keypad->client->irq);
 315}
 316
 317static int ht16k33_keypad_probe(struct i2c_client *client,
 318                                struct ht16k33_keypad *keypad)
 319{
 320        struct device_node *node = client->dev.of_node;
 321        u32 rows = HT16K33_MATRIX_KEYPAD_MAX_ROWS;
 322        u32 cols = HT16K33_MATRIX_KEYPAD_MAX_COLS;
 323        int err;
 324
 325        keypad->client = client;
 326        init_waitqueue_head(&keypad->wait);
 327
 328        keypad->dev = devm_input_allocate_device(&client->dev);
 329        if (!keypad->dev)
 330                return -ENOMEM;
 331
 332        input_set_drvdata(keypad->dev, keypad);
 333
 334        keypad->dev->name = DRIVER_NAME"-keypad";
 335        keypad->dev->id.bustype = BUS_I2C;
 336        keypad->dev->open = ht16k33_keypad_start;
 337        keypad->dev->close = ht16k33_keypad_stop;
 338
 339        if (!of_get_property(node, "linux,no-autorepeat", NULL))
 340                __set_bit(EV_REP, keypad->dev->evbit);
 341
 342        err = of_property_read_u32(node, "debounce-delay-ms",
 343                                   &keypad->debounce_ms);
 344        if (err) {
 345                dev_err(&client->dev, "key debounce delay not specified\n");
 346                return err;
 347        }
 348
 349        err = matrix_keypad_parse_of_params(&client->dev, &rows, &cols);
 350        if (err)
 351                return err;
 352        if (rows > HT16K33_MATRIX_KEYPAD_MAX_ROWS ||
 353            cols > HT16K33_MATRIX_KEYPAD_MAX_COLS) {
 354                dev_err(&client->dev, "%u rows or %u cols out of range in DT\n",
 355                        rows, cols);
 356                return -ERANGE;
 357        }
 358
 359        keypad->rows = rows;
 360        keypad->cols = cols;
 361        keypad->row_shift = get_count_order(cols);
 362
 363        err = matrix_keypad_build_keymap(NULL, NULL, rows, cols, NULL,
 364                                         keypad->dev);
 365        if (err) {
 366                dev_err(&client->dev, "failed to build keymap\n");
 367                return err;
 368        }
 369
 370        err = devm_request_threaded_irq(&client->dev, client->irq,
 371                                        NULL, ht16k33_keypad_irq_thread,
 372                                        IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 373                                        DRIVER_NAME, keypad);
 374        if (err) {
 375                dev_err(&client->dev, "irq request failed %d, error %d\n",
 376                        client->irq, err);
 377                return err;
 378        }
 379
 380        ht16k33_keypad_stop(keypad->dev);
 381
 382        err = input_register_device(keypad->dev);
 383        if (err)
 384                return err;
 385
 386        return 0;
 387}
 388
 389static int ht16k33_probe(struct i2c_client *client,
 390                                  const struct i2c_device_id *id)
 391{
 392        int err;
 393        uint32_t dft_brightness;
 394        struct backlight_device *bl;
 395        struct backlight_properties bl_props;
 396        struct ht16k33_priv *priv;
 397        struct ht16k33_fbdev *fbdev;
 398        struct device_node *node = client->dev.of_node;
 399
 400        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 401                dev_err(&client->dev, "i2c_check_functionality error\n");
 402                return -EIO;
 403        }
 404
 405        if (client->irq <= 0) {
 406                dev_err(&client->dev, "No IRQ specified\n");
 407                return -EINVAL;
 408        }
 409
 410        priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
 411        if (!priv)
 412                return -ENOMEM;
 413
 414        priv->client = client;
 415        i2c_set_clientdata(client, priv);
 416        fbdev = &priv->fbdev;
 417
 418        err = ht16k33_initialize(priv);
 419        if (err)
 420                return err;
 421
 422        /* Framebuffer (2 bytes per column) */
 423        BUILD_BUG_ON(PAGE_SIZE < HT16K33_FB_SIZE);
 424        fbdev->buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL);
 425        if (!fbdev->buffer)
 426                return -ENOMEM;
 427
 428        fbdev->cache = devm_kmalloc(&client->dev, HT16K33_FB_SIZE, GFP_KERNEL);
 429        if (!fbdev->cache) {
 430                err = -ENOMEM;
 431                goto err_fbdev_buffer;
 432        }
 433
 434        fbdev->info = framebuffer_alloc(0, &client->dev);
 435        if (!fbdev->info) {
 436                err = -ENOMEM;
 437                goto err_fbdev_buffer;
 438        }
 439
 440        err = of_property_read_u32(node, "refresh-rate-hz",
 441                &fbdev->refresh_rate);
 442        if (err) {
 443                dev_err(&client->dev, "refresh rate not specified\n");
 444                goto err_fbdev_info;
 445        }
 446        fb_bl_default_curve(fbdev->info, 0, MIN_BRIGHTNESS, MAX_BRIGHTNESS);
 447
 448        INIT_DELAYED_WORK(&fbdev->work, ht16k33_fb_update);
 449        fbdev->info->fbops = &ht16k33_fb_ops;
 450        fbdev->info->screen_base = (char __iomem *) fbdev->buffer;
 451        fbdev->info->screen_size = HT16K33_FB_SIZE;
 452        fbdev->info->fix = ht16k33_fb_fix;
 453        fbdev->info->var = ht16k33_fb_var;
 454        fbdev->info->pseudo_palette = NULL;
 455        fbdev->info->flags = FBINFO_FLAG_DEFAULT;
 456        fbdev->info->par = priv;
 457
 458        err = register_framebuffer(fbdev->info);
 459        if (err)
 460                goto err_fbdev_info;
 461
 462        err = ht16k33_keypad_probe(client, &priv->keypad);
 463        if (err)
 464                goto err_fbdev_unregister;
 465
 466        /* Backlight */
 467        memset(&bl_props, 0, sizeof(struct backlight_properties));
 468        bl_props.type = BACKLIGHT_RAW;
 469        bl_props.max_brightness = MAX_BRIGHTNESS;
 470
 471        bl = devm_backlight_device_register(&client->dev, DRIVER_NAME"-bl",
 472                                            &client->dev, priv,
 473                                            &ht16k33_bl_ops, &bl_props);
 474        if (IS_ERR(bl)) {
 475                dev_err(&client->dev, "failed to register backlight\n");
 476                err = PTR_ERR(bl);
 477                goto err_fbdev_unregister;
 478        }
 479
 480        err = of_property_read_u32(node, "default-brightness-level",
 481                                   &dft_brightness);
 482        if (err) {
 483                dft_brightness = MAX_BRIGHTNESS;
 484        } else if (dft_brightness > MAX_BRIGHTNESS) {
 485                dev_warn(&client->dev,
 486                         "invalid default brightness level: %u, using %u\n",
 487                         dft_brightness, MAX_BRIGHTNESS);
 488                dft_brightness = MAX_BRIGHTNESS;
 489        }
 490
 491        bl->props.brightness = dft_brightness;
 492        ht16k33_bl_update_status(bl);
 493
 494        ht16k33_fb_queue(priv);
 495        return 0;
 496
 497err_fbdev_unregister:
 498        unregister_framebuffer(fbdev->info);
 499err_fbdev_info:
 500        framebuffer_release(fbdev->info);
 501err_fbdev_buffer:
 502        free_page((unsigned long) fbdev->buffer);
 503
 504        return err;
 505}
 506
 507static int ht16k33_remove(struct i2c_client *client)
 508{
 509        struct ht16k33_priv *priv = i2c_get_clientdata(client);
 510        struct ht16k33_fbdev *fbdev = &priv->fbdev;
 511
 512        cancel_delayed_work_sync(&fbdev->work);
 513        unregister_framebuffer(fbdev->info);
 514        framebuffer_release(fbdev->info);
 515        free_page((unsigned long) fbdev->buffer);
 516
 517        return 0;
 518}
 519
 520static const struct i2c_device_id ht16k33_i2c_match[] = {
 521        { "ht16k33", 0 },
 522        { }
 523};
 524MODULE_DEVICE_TABLE(i2c, ht16k33_i2c_match);
 525
 526static const struct of_device_id ht16k33_of_match[] = {
 527        { .compatible = "holtek,ht16k33", },
 528        { }
 529};
 530MODULE_DEVICE_TABLE(of, ht16k33_of_match);
 531
 532static struct i2c_driver ht16k33_driver = {
 533        .probe          = ht16k33_probe,
 534        .remove         = ht16k33_remove,
 535        .driver         = {
 536                .name           = DRIVER_NAME,
 537                .of_match_table = of_match_ptr(ht16k33_of_match),
 538        },
 539        .id_table = ht16k33_i2c_match,
 540};
 541module_i2c_driver(ht16k33_driver);
 542
 543MODULE_DESCRIPTION("Holtek HT16K33 driver");
 544MODULE_LICENSE("GPL");
 545MODULE_AUTHOR("Robin van der Gracht <robin@protonic.nl>");
 546