ht16k33.c (20614B)
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 * Copyright (C) 2021 Glider bv 9 */ 10 11#include <linux/kernel.h> 12#include <linux/module.h> 13#include <linux/interrupt.h> 14#include <linux/i2c.h> 15#include <linux/property.h> 16#include <linux/fb.h> 17#include <linux/backlight.h> 18#include <linux/input.h> 19#include <linux/input/matrix_keypad.h> 20#include <linux/leds.h> 21#include <linux/workqueue.h> 22#include <linux/mm.h> 23 24#include <linux/map_to_7segment.h> 25#include <linux/map_to_14segment.h> 26 27#include <asm/unaligned.h> 28 29#include "line-display.h" 30 31/* Registers */ 32#define REG_SYSTEM_SETUP 0x20 33#define REG_SYSTEM_SETUP_OSC_ON BIT(0) 34 35#define REG_DISPLAY_SETUP 0x80 36#define REG_DISPLAY_SETUP_ON BIT(0) 37#define REG_DISPLAY_SETUP_BLINK_OFF (0 << 1) 38#define REG_DISPLAY_SETUP_BLINK_2HZ (1 << 1) 39#define REG_DISPLAY_SETUP_BLINK_1HZ (2 << 1) 40#define REG_DISPLAY_SETUP_BLINK_0HZ5 (3 << 1) 41 42#define REG_ROWINT_SET 0xA0 43#define REG_ROWINT_SET_INT_EN BIT(0) 44#define REG_ROWINT_SET_INT_ACT_HIGH BIT(1) 45 46#define REG_BRIGHTNESS 0xE0 47 48/* Defines */ 49#define DRIVER_NAME "ht16k33" 50 51#define MIN_BRIGHTNESS 0x1 52#define MAX_BRIGHTNESS 0x10 53 54#define HT16K33_MATRIX_LED_MAX_COLS 8 55#define HT16K33_MATRIX_LED_MAX_ROWS 16 56#define HT16K33_MATRIX_KEYPAD_MAX_COLS 3 57#define HT16K33_MATRIX_KEYPAD_MAX_ROWS 12 58 59#define BYTES_PER_ROW (HT16K33_MATRIX_LED_MAX_ROWS / 8) 60#define HT16K33_FB_SIZE (HT16K33_MATRIX_LED_MAX_COLS * BYTES_PER_ROW) 61 62enum display_type { 63 DISP_MATRIX = 0, 64 DISP_QUAD_7SEG, 65 DISP_QUAD_14SEG, 66}; 67 68struct ht16k33_keypad { 69 struct i2c_client *client; 70 struct input_dev *dev; 71 uint32_t cols; 72 uint32_t rows; 73 uint32_t row_shift; 74 uint32_t debounce_ms; 75 uint16_t last_key_state[HT16K33_MATRIX_KEYPAD_MAX_COLS]; 76 77 wait_queue_head_t wait; 78 bool stopped; 79}; 80 81struct ht16k33_fbdev { 82 struct fb_info *info; 83 uint32_t refresh_rate; 84 uint8_t *buffer; 85 uint8_t *cache; 86}; 87 88struct ht16k33_seg { 89 struct linedisp linedisp; 90 union { 91 struct seg7_conversion_map seg7; 92 struct seg14_conversion_map seg14; 93 } map; 94 unsigned int map_size; 95 char curr[4]; 96}; 97 98struct ht16k33_priv { 99 struct i2c_client *client; 100 struct delayed_work work; 101 struct led_classdev led; 102 struct ht16k33_keypad keypad; 103 union { 104 struct ht16k33_fbdev fbdev; 105 struct ht16k33_seg seg; 106 }; 107 enum display_type type; 108 uint8_t blink; 109}; 110 111static const struct fb_fix_screeninfo ht16k33_fb_fix = { 112 .id = DRIVER_NAME, 113 .type = FB_TYPE_PACKED_PIXELS, 114 .visual = FB_VISUAL_MONO10, 115 .xpanstep = 0, 116 .ypanstep = 0, 117 .ywrapstep = 0, 118 .line_length = HT16K33_MATRIX_LED_MAX_ROWS, 119 .accel = FB_ACCEL_NONE, 120}; 121 122static const struct fb_var_screeninfo ht16k33_fb_var = { 123 .xres = HT16K33_MATRIX_LED_MAX_ROWS, 124 .yres = HT16K33_MATRIX_LED_MAX_COLS, 125 .xres_virtual = HT16K33_MATRIX_LED_MAX_ROWS, 126 .yres_virtual = HT16K33_MATRIX_LED_MAX_COLS, 127 .bits_per_pixel = 1, 128 .red = { 0, 1, 0 }, 129 .green = { 0, 1, 0 }, 130 .blue = { 0, 1, 0 }, 131 .left_margin = 0, 132 .right_margin = 0, 133 .upper_margin = 0, 134 .lower_margin = 0, 135 .vmode = FB_VMODE_NONINTERLACED, 136}; 137 138static const SEG7_DEFAULT_MAP(initial_map_seg7); 139static const SEG14_DEFAULT_MAP(initial_map_seg14); 140 141static ssize_t map_seg_show(struct device *dev, struct device_attribute *attr, 142 char *buf) 143{ 144 struct ht16k33_priv *priv = dev_get_drvdata(dev); 145 146 memcpy(buf, &priv->seg.map, priv->seg.map_size); 147 return priv->seg.map_size; 148} 149 150static ssize_t map_seg_store(struct device *dev, struct device_attribute *attr, 151 const char *buf, size_t cnt) 152{ 153 struct ht16k33_priv *priv = dev_get_drvdata(dev); 154 155 if (cnt != priv->seg.map_size) 156 return -EINVAL; 157 158 memcpy(&priv->seg.map, buf, cnt); 159 return cnt; 160} 161 162static DEVICE_ATTR(map_seg7, 0644, map_seg_show, map_seg_store); 163static DEVICE_ATTR(map_seg14, 0644, map_seg_show, map_seg_store); 164 165static int ht16k33_display_on(struct ht16k33_priv *priv) 166{ 167 uint8_t data = REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON | priv->blink; 168 169 return i2c_smbus_write_byte(priv->client, data); 170} 171 172static int ht16k33_display_off(struct ht16k33_priv *priv) 173{ 174 return i2c_smbus_write_byte(priv->client, REG_DISPLAY_SETUP); 175} 176 177static int ht16k33_brightness_set(struct ht16k33_priv *priv, 178 unsigned int brightness) 179{ 180 int err; 181 182 if (brightness == 0) { 183 priv->blink = REG_DISPLAY_SETUP_BLINK_OFF; 184 return ht16k33_display_off(priv); 185 } 186 187 err = ht16k33_display_on(priv); 188 if (err) 189 return err; 190 191 return i2c_smbus_write_byte(priv->client, 192 REG_BRIGHTNESS | (brightness - 1)); 193} 194 195static int ht16k33_brightness_set_blocking(struct led_classdev *led_cdev, 196 enum led_brightness brightness) 197{ 198 struct ht16k33_priv *priv = container_of(led_cdev, struct ht16k33_priv, 199 led); 200 201 return ht16k33_brightness_set(priv, brightness); 202} 203 204static int ht16k33_blink_set(struct led_classdev *led_cdev, 205 unsigned long *delay_on, unsigned long *delay_off) 206{ 207 struct ht16k33_priv *priv = container_of(led_cdev, struct ht16k33_priv, 208 led); 209 unsigned int delay; 210 uint8_t blink; 211 int err; 212 213 if (!*delay_on && !*delay_off) { 214 blink = REG_DISPLAY_SETUP_BLINK_1HZ; 215 delay = 1000; 216 } else if (*delay_on <= 750) { 217 blink = REG_DISPLAY_SETUP_BLINK_2HZ; 218 delay = 500; 219 } else if (*delay_on <= 1500) { 220 blink = REG_DISPLAY_SETUP_BLINK_1HZ; 221 delay = 1000; 222 } else { 223 blink = REG_DISPLAY_SETUP_BLINK_0HZ5; 224 delay = 2000; 225 } 226 227 err = i2c_smbus_write_byte(priv->client, 228 REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON | 229 blink); 230 if (err) 231 return err; 232 233 priv->blink = blink; 234 *delay_on = *delay_off = delay; 235 return 0; 236} 237 238static void ht16k33_fb_queue(struct ht16k33_priv *priv) 239{ 240 struct ht16k33_fbdev *fbdev = &priv->fbdev; 241 242 schedule_delayed_work(&priv->work, HZ / fbdev->refresh_rate); 243} 244 245/* 246 * This gets the fb data from cache and copies it to ht16k33 display RAM 247 */ 248static void ht16k33_fb_update(struct work_struct *work) 249{ 250 struct ht16k33_priv *priv = container_of(work, struct ht16k33_priv, 251 work.work); 252 struct ht16k33_fbdev *fbdev = &priv->fbdev; 253 254 uint8_t *p1, *p2; 255 int len, pos = 0, first = -1; 256 257 p1 = fbdev->cache; 258 p2 = fbdev->buffer; 259 260 /* Search for the first byte with changes */ 261 while (pos < HT16K33_FB_SIZE && first < 0) { 262 if (*(p1++) - *(p2++)) 263 first = pos; 264 pos++; 265 } 266 267 /* No changes found */ 268 if (first < 0) 269 goto requeue; 270 271 len = HT16K33_FB_SIZE - first; 272 p1 = fbdev->cache + HT16K33_FB_SIZE - 1; 273 p2 = fbdev->buffer + HT16K33_FB_SIZE - 1; 274 275 /* Determine i2c transfer length */ 276 while (len > 1) { 277 if (*(p1--) - *(p2--)) 278 break; 279 len--; 280 } 281 282 p1 = fbdev->cache + first; 283 p2 = fbdev->buffer + first; 284 if (!i2c_smbus_write_i2c_block_data(priv->client, first, len, p2)) 285 memcpy(p1, p2, len); 286requeue: 287 ht16k33_fb_queue(priv); 288} 289 290static int ht16k33_initialize(struct ht16k33_priv *priv) 291{ 292 uint8_t data[HT16K33_FB_SIZE]; 293 uint8_t byte; 294 int err; 295 296 /* Clear RAM (8 * 16 bits) */ 297 memset(data, 0, sizeof(data)); 298 err = i2c_smbus_write_block_data(priv->client, 0, sizeof(data), data); 299 if (err) 300 return err; 301 302 /* Turn on internal oscillator */ 303 byte = REG_SYSTEM_SETUP_OSC_ON | REG_SYSTEM_SETUP; 304 err = i2c_smbus_write_byte(priv->client, byte); 305 if (err) 306 return err; 307 308 /* Configure INT pin */ 309 byte = REG_ROWINT_SET | REG_ROWINT_SET_INT_ACT_HIGH; 310 if (priv->client->irq > 0) 311 byte |= REG_ROWINT_SET_INT_EN; 312 return i2c_smbus_write_byte(priv->client, byte); 313} 314 315static int ht16k33_bl_update_status(struct backlight_device *bl) 316{ 317 int brightness = bl->props.brightness; 318 struct ht16k33_priv *priv = bl_get_data(bl); 319 320 if (bl->props.power != FB_BLANK_UNBLANK || 321 bl->props.fb_blank != FB_BLANK_UNBLANK || 322 bl->props.state & BL_CORE_FBBLANK) 323 brightness = 0; 324 325 return ht16k33_brightness_set(priv, brightness); 326} 327 328static int ht16k33_bl_check_fb(struct backlight_device *bl, struct fb_info *fi) 329{ 330 struct ht16k33_priv *priv = bl_get_data(bl); 331 332 return (fi == NULL) || (fi->par == priv); 333} 334 335static const struct backlight_ops ht16k33_bl_ops = { 336 .update_status = ht16k33_bl_update_status, 337 .check_fb = ht16k33_bl_check_fb, 338}; 339 340/* 341 * Blank events will be passed to the actual device handling the backlight when 342 * we return zero here. 343 */ 344static int ht16k33_blank(int blank, struct fb_info *info) 345{ 346 return 0; 347} 348 349static int ht16k33_mmap(struct fb_info *info, struct vm_area_struct *vma) 350{ 351 struct ht16k33_priv *priv = info->par; 352 struct page *pages = virt_to_page(priv->fbdev.buffer); 353 354 return vm_map_pages_zero(vma, &pages, 1); 355} 356 357static const struct fb_ops ht16k33_fb_ops = { 358 .owner = THIS_MODULE, 359 .fb_read = fb_sys_read, 360 .fb_write = fb_sys_write, 361 .fb_blank = ht16k33_blank, 362 .fb_fillrect = sys_fillrect, 363 .fb_copyarea = sys_copyarea, 364 .fb_imageblit = sys_imageblit, 365 .fb_mmap = ht16k33_mmap, 366}; 367 368/* 369 * This gets the keys from keypad and reports it to input subsystem. 370 * Returns true if a key is pressed. 371 */ 372static bool ht16k33_keypad_scan(struct ht16k33_keypad *keypad) 373{ 374 const unsigned short *keycodes = keypad->dev->keycode; 375 u16 new_state[HT16K33_MATRIX_KEYPAD_MAX_COLS]; 376 __le16 data[HT16K33_MATRIX_KEYPAD_MAX_COLS]; 377 unsigned long bits_changed; 378 int row, col, code; 379 int rc; 380 bool pressed = false; 381 382 rc = i2c_smbus_read_i2c_block_data(keypad->client, 0x40, 383 sizeof(data), (u8 *)data); 384 if (rc != sizeof(data)) { 385 dev_err(&keypad->client->dev, 386 "Failed to read key data, rc=%d\n", rc); 387 return false; 388 } 389 390 for (col = 0; col < keypad->cols; col++) { 391 new_state[col] = le16_to_cpu(data[col]); 392 if (new_state[col]) 393 pressed = true; 394 bits_changed = keypad->last_key_state[col] ^ new_state[col]; 395 396 for_each_set_bit(row, &bits_changed, BITS_PER_LONG) { 397 code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); 398 input_event(keypad->dev, EV_MSC, MSC_SCAN, code); 399 input_report_key(keypad->dev, keycodes[code], 400 new_state[col] & BIT(row)); 401 } 402 } 403 input_sync(keypad->dev); 404 memcpy(keypad->last_key_state, new_state, sizeof(u16) * keypad->cols); 405 406 return pressed; 407} 408 409static irqreturn_t ht16k33_keypad_irq_thread(int irq, void *dev) 410{ 411 struct ht16k33_keypad *keypad = dev; 412 413 do { 414 wait_event_timeout(keypad->wait, keypad->stopped, 415 msecs_to_jiffies(keypad->debounce_ms)); 416 if (keypad->stopped) 417 break; 418 } while (ht16k33_keypad_scan(keypad)); 419 420 return IRQ_HANDLED; 421} 422 423static int ht16k33_keypad_start(struct input_dev *dev) 424{ 425 struct ht16k33_keypad *keypad = input_get_drvdata(dev); 426 427 keypad->stopped = false; 428 mb(); 429 enable_irq(keypad->client->irq); 430 431 return 0; 432} 433 434static void ht16k33_keypad_stop(struct input_dev *dev) 435{ 436 struct ht16k33_keypad *keypad = input_get_drvdata(dev); 437 438 keypad->stopped = true; 439 mb(); 440 wake_up(&keypad->wait); 441 disable_irq(keypad->client->irq); 442} 443 444static void ht16k33_linedisp_update(struct linedisp *linedisp) 445{ 446 struct ht16k33_priv *priv = container_of(linedisp, struct ht16k33_priv, 447 seg.linedisp); 448 449 schedule_delayed_work(&priv->work, 0); 450} 451 452static void ht16k33_seg7_update(struct work_struct *work) 453{ 454 struct ht16k33_priv *priv = container_of(work, struct ht16k33_priv, 455 work.work); 456 struct ht16k33_seg *seg = &priv->seg; 457 char *s = seg->curr; 458 uint8_t buf[9]; 459 460 buf[0] = map_to_seg7(&seg->map.seg7, *s++); 461 buf[1] = 0; 462 buf[2] = map_to_seg7(&seg->map.seg7, *s++); 463 buf[3] = 0; 464 buf[4] = 0; 465 buf[5] = 0; 466 buf[6] = map_to_seg7(&seg->map.seg7, *s++); 467 buf[7] = 0; 468 buf[8] = map_to_seg7(&seg->map.seg7, *s++); 469 470 i2c_smbus_write_i2c_block_data(priv->client, 0, ARRAY_SIZE(buf), buf); 471} 472 473static void ht16k33_seg14_update(struct work_struct *work) 474{ 475 struct ht16k33_priv *priv = container_of(work, struct ht16k33_priv, 476 work.work); 477 struct ht16k33_seg *seg = &priv->seg; 478 char *s = seg->curr; 479 uint8_t buf[8]; 480 481 put_unaligned_le16(map_to_seg14(&seg->map.seg14, *s++), buf); 482 put_unaligned_le16(map_to_seg14(&seg->map.seg14, *s++), buf + 2); 483 put_unaligned_le16(map_to_seg14(&seg->map.seg14, *s++), buf + 4); 484 put_unaligned_le16(map_to_seg14(&seg->map.seg14, *s++), buf + 6); 485 486 i2c_smbus_write_i2c_block_data(priv->client, 0, ARRAY_SIZE(buf), buf); 487} 488 489static int ht16k33_led_probe(struct device *dev, struct led_classdev *led, 490 unsigned int brightness) 491{ 492 struct led_init_data init_data = {}; 493 int err; 494 495 /* The LED is optional */ 496 init_data.fwnode = device_get_named_child_node(dev, "led"); 497 if (!init_data.fwnode) 498 return 0; 499 500 init_data.devicename = "auxdisplay"; 501 init_data.devname_mandatory = true; 502 503 led->brightness_set_blocking = ht16k33_brightness_set_blocking; 504 led->blink_set = ht16k33_blink_set; 505 led->flags = LED_CORE_SUSPENDRESUME; 506 led->brightness = brightness; 507 led->max_brightness = MAX_BRIGHTNESS; 508 509 err = devm_led_classdev_register_ext(dev, led, &init_data); 510 if (err) 511 dev_err(dev, "Failed to register LED\n"); 512 513 return err; 514} 515 516static int ht16k33_keypad_probe(struct i2c_client *client, 517 struct ht16k33_keypad *keypad) 518{ 519 struct device *dev = &client->dev; 520 u32 rows = HT16K33_MATRIX_KEYPAD_MAX_ROWS; 521 u32 cols = HT16K33_MATRIX_KEYPAD_MAX_COLS; 522 int err; 523 524 keypad->client = client; 525 init_waitqueue_head(&keypad->wait); 526 527 keypad->dev = devm_input_allocate_device(dev); 528 if (!keypad->dev) 529 return -ENOMEM; 530 531 input_set_drvdata(keypad->dev, keypad); 532 533 keypad->dev->name = DRIVER_NAME"-keypad"; 534 keypad->dev->id.bustype = BUS_I2C; 535 keypad->dev->open = ht16k33_keypad_start; 536 keypad->dev->close = ht16k33_keypad_stop; 537 538 if (!device_property_read_bool(dev, "linux,no-autorepeat")) 539 __set_bit(EV_REP, keypad->dev->evbit); 540 541 err = device_property_read_u32(dev, "debounce-delay-ms", 542 &keypad->debounce_ms); 543 if (err) { 544 dev_err(dev, "key debounce delay not specified\n"); 545 return err; 546 } 547 548 err = matrix_keypad_parse_properties(dev, &rows, &cols); 549 if (err) 550 return err; 551 if (rows > HT16K33_MATRIX_KEYPAD_MAX_ROWS || 552 cols > HT16K33_MATRIX_KEYPAD_MAX_COLS) { 553 dev_err(dev, "%u rows or %u cols out of range in DT\n", rows, 554 cols); 555 return -ERANGE; 556 } 557 558 keypad->rows = rows; 559 keypad->cols = cols; 560 keypad->row_shift = get_count_order(cols); 561 562 err = matrix_keypad_build_keymap(NULL, NULL, rows, cols, NULL, 563 keypad->dev); 564 if (err) { 565 dev_err(dev, "failed to build keymap\n"); 566 return err; 567 } 568 569 err = devm_request_threaded_irq(dev, client->irq, NULL, 570 ht16k33_keypad_irq_thread, 571 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 572 DRIVER_NAME, keypad); 573 if (err) { 574 dev_err(dev, "irq request failed %d, error %d\n", client->irq, 575 err); 576 return err; 577 } 578 579 ht16k33_keypad_stop(keypad->dev); 580 581 return input_register_device(keypad->dev); 582} 583 584static int ht16k33_fbdev_probe(struct device *dev, struct ht16k33_priv *priv, 585 uint32_t brightness) 586{ 587 struct ht16k33_fbdev *fbdev = &priv->fbdev; 588 struct backlight_device *bl = NULL; 589 int err; 590 591 if (priv->led.dev) { 592 err = ht16k33_brightness_set(priv, brightness); 593 if (err) 594 return err; 595 } else { 596 /* backwards compatibility with DT lacking an led subnode */ 597 struct backlight_properties bl_props; 598 599 memset(&bl_props, 0, sizeof(struct backlight_properties)); 600 bl_props.type = BACKLIGHT_RAW; 601 bl_props.max_brightness = MAX_BRIGHTNESS; 602 603 bl = devm_backlight_device_register(dev, DRIVER_NAME"-bl", dev, 604 priv, &ht16k33_bl_ops, 605 &bl_props); 606 if (IS_ERR(bl)) { 607 dev_err(dev, "failed to register backlight\n"); 608 return PTR_ERR(bl); 609 } 610 611 bl->props.brightness = brightness; 612 ht16k33_bl_update_status(bl); 613 } 614 615 /* Framebuffer (2 bytes per column) */ 616 BUILD_BUG_ON(PAGE_SIZE < HT16K33_FB_SIZE); 617 fbdev->buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL); 618 if (!fbdev->buffer) 619 return -ENOMEM; 620 621 fbdev->cache = devm_kmalloc(dev, HT16K33_FB_SIZE, GFP_KERNEL); 622 if (!fbdev->cache) { 623 err = -ENOMEM; 624 goto err_fbdev_buffer; 625 } 626 627 fbdev->info = framebuffer_alloc(0, dev); 628 if (!fbdev->info) { 629 err = -ENOMEM; 630 goto err_fbdev_buffer; 631 } 632 633 err = device_property_read_u32(dev, "refresh-rate-hz", 634 &fbdev->refresh_rate); 635 if (err) { 636 dev_err(dev, "refresh rate not specified\n"); 637 goto err_fbdev_info; 638 } 639 fb_bl_default_curve(fbdev->info, 0, MIN_BRIGHTNESS, MAX_BRIGHTNESS); 640 641 INIT_DELAYED_WORK(&priv->work, ht16k33_fb_update); 642 fbdev->info->fbops = &ht16k33_fb_ops; 643 fbdev->info->screen_base = (char __iomem *) fbdev->buffer; 644 fbdev->info->screen_size = HT16K33_FB_SIZE; 645 fbdev->info->fix = ht16k33_fb_fix; 646 fbdev->info->var = ht16k33_fb_var; 647 fbdev->info->bl_dev = bl; 648 fbdev->info->pseudo_palette = NULL; 649 fbdev->info->flags = FBINFO_FLAG_DEFAULT; 650 fbdev->info->par = priv; 651 652 err = register_framebuffer(fbdev->info); 653 if (err) 654 goto err_fbdev_info; 655 656 ht16k33_fb_queue(priv); 657 return 0; 658 659err_fbdev_info: 660 framebuffer_release(fbdev->info); 661err_fbdev_buffer: 662 free_page((unsigned long) fbdev->buffer); 663 664 return err; 665} 666 667static int ht16k33_seg_probe(struct device *dev, struct ht16k33_priv *priv, 668 uint32_t brightness) 669{ 670 struct ht16k33_seg *seg = &priv->seg; 671 int err; 672 673 err = ht16k33_brightness_set(priv, brightness); 674 if (err) 675 return err; 676 677 switch (priv->type) { 678 case DISP_MATRIX: 679 /* not handled here */ 680 err = -EINVAL; 681 break; 682 683 case DISP_QUAD_7SEG: 684 INIT_DELAYED_WORK(&priv->work, ht16k33_seg7_update); 685 seg->map.seg7 = initial_map_seg7; 686 seg->map_size = sizeof(seg->map.seg7); 687 err = device_create_file(dev, &dev_attr_map_seg7); 688 break; 689 690 case DISP_QUAD_14SEG: 691 INIT_DELAYED_WORK(&priv->work, ht16k33_seg14_update); 692 seg->map.seg14 = initial_map_seg14; 693 seg->map_size = sizeof(seg->map.seg14); 694 err = device_create_file(dev, &dev_attr_map_seg14); 695 break; 696 } 697 if (err) 698 return err; 699 700 err = linedisp_register(&seg->linedisp, dev, 4, seg->curr, 701 ht16k33_linedisp_update); 702 if (err) 703 goto err_remove_map_file; 704 705 return 0; 706 707err_remove_map_file: 708 device_remove_file(dev, &dev_attr_map_seg7); 709 device_remove_file(dev, &dev_attr_map_seg14); 710 return err; 711} 712 713static int ht16k33_probe(struct i2c_client *client) 714{ 715 struct device *dev = &client->dev; 716 const struct of_device_id *id; 717 struct ht16k33_priv *priv; 718 uint32_t dft_brightness; 719 int err; 720 721 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 722 dev_err(dev, "i2c_check_functionality error\n"); 723 return -EIO; 724 } 725 726 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 727 if (!priv) 728 return -ENOMEM; 729 730 priv->client = client; 731 id = i2c_of_match_device(dev->driver->of_match_table, client); 732 if (id) 733 priv->type = (uintptr_t)id->data; 734 i2c_set_clientdata(client, priv); 735 736 err = ht16k33_initialize(priv); 737 if (err) 738 return err; 739 740 err = device_property_read_u32(dev, "default-brightness-level", 741 &dft_brightness); 742 if (err) { 743 dft_brightness = MAX_BRIGHTNESS; 744 } else if (dft_brightness > MAX_BRIGHTNESS) { 745 dev_warn(dev, 746 "invalid default brightness level: %u, using %u\n", 747 dft_brightness, MAX_BRIGHTNESS); 748 dft_brightness = MAX_BRIGHTNESS; 749 } 750 751 /* LED */ 752 err = ht16k33_led_probe(dev, &priv->led, dft_brightness); 753 if (err) 754 return err; 755 756 /* Keypad */ 757 if (client->irq > 0) { 758 err = ht16k33_keypad_probe(client, &priv->keypad); 759 if (err) 760 return err; 761 } 762 763 switch (priv->type) { 764 case DISP_MATRIX: 765 /* Frame Buffer Display */ 766 err = ht16k33_fbdev_probe(dev, priv, dft_brightness); 767 break; 768 769 case DISP_QUAD_7SEG: 770 case DISP_QUAD_14SEG: 771 /* Segment Display */ 772 err = ht16k33_seg_probe(dev, priv, dft_brightness); 773 break; 774 } 775 return err; 776} 777 778static int ht16k33_remove(struct i2c_client *client) 779{ 780 struct ht16k33_priv *priv = i2c_get_clientdata(client); 781 struct ht16k33_fbdev *fbdev = &priv->fbdev; 782 783 cancel_delayed_work_sync(&priv->work); 784 785 switch (priv->type) { 786 case DISP_MATRIX: 787 unregister_framebuffer(fbdev->info); 788 framebuffer_release(fbdev->info); 789 free_page((unsigned long)fbdev->buffer); 790 break; 791 792 case DISP_QUAD_7SEG: 793 case DISP_QUAD_14SEG: 794 linedisp_unregister(&priv->seg.linedisp); 795 device_remove_file(&client->dev, &dev_attr_map_seg7); 796 device_remove_file(&client->dev, &dev_attr_map_seg14); 797 break; 798 } 799 800 return 0; 801} 802 803static const struct i2c_device_id ht16k33_i2c_match[] = { 804 { "ht16k33", 0 }, 805 { } 806}; 807MODULE_DEVICE_TABLE(i2c, ht16k33_i2c_match); 808 809static const struct of_device_id ht16k33_of_match[] = { 810 { 811 /* 0.56" 4-Digit 7-Segment FeatherWing Display (Red) */ 812 .compatible = "adafruit,3108", .data = (void *)DISP_QUAD_7SEG, 813 }, { 814 /* 0.54" Quad Alphanumeric FeatherWing Display (Red) */ 815 .compatible = "adafruit,3130", .data = (void *)DISP_QUAD_14SEG, 816 }, { 817 /* Generic, assumed Dot-Matrix Display */ 818 .compatible = "holtek,ht16k33", .data = (void *)DISP_MATRIX, 819 }, 820 { } 821}; 822MODULE_DEVICE_TABLE(of, ht16k33_of_match); 823 824static struct i2c_driver ht16k33_driver = { 825 .probe_new = ht16k33_probe, 826 .remove = ht16k33_remove, 827 .driver = { 828 .name = DRIVER_NAME, 829 .of_match_table = ht16k33_of_match, 830 }, 831 .id_table = ht16k33_i2c_match, 832}; 833module_i2c_driver(ht16k33_driver); 834 835MODULE_DESCRIPTION("Holtek HT16K33 driver"); 836MODULE_LICENSE("GPL"); 837MODULE_AUTHOR("Robin van der Gracht <robin@protonic.nl>");