diff options
author | Daisuke Nojiri <dnojiri@chromium.org> | 2021-12-04 13:08:04 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-03-01 19:41:59 +0000 |
commit | 14b34644fe16349af348d21f20d3897707132896 (patch) | |
tree | 1439a332e77c942d809b2ebfc128d690d72fe8e8 /driver/led | |
parent | 10a7a0a72017fe15633fa563977b748e88ec8726 (diff) | |
download | chrome-ec-14b34644fe16349af348d21f20d3897707132896.tar.gz |
RGBKBD: Add RGB Keyboard task
This patch introduces a RGB keyboard task and a IS31FL3743B driver.
BUG=b:203664745, b:213921985, b:199995751
BRANCH=None
TEST=Vell and unit test.
Change-Id: Iefc1714efca9a4dc70db5a024d1ab020ec7b69b6
Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3342506
Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
Reviewed-by: Aaron Massey <aaronmassey@google.com>
Diffstat (limited to 'driver/led')
-rw-r--r-- | driver/led/is31fl3743b.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/driver/led/is31fl3743b.c b/driver/led/is31fl3743b.c new file mode 100644 index 0000000000..f1a8833318 --- /dev/null +++ b/driver/led/is31fl3743b.c @@ -0,0 +1,189 @@ +/* Copyright 2022 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include <string.h> + +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "rgb_keyboard.h" +#include "spi.h" +#include "stddef.h" +#include "timer.h" + +#define CPRINTF(fmt, args...) cprintf(CC_RGBKBD, "RGBKBD: " fmt, ##args) +#define CPRINTS(fmt, args...) cprints(CC_RGBKBD, "RGBKBD: " fmt, ##args) + +#define SPI(id) (&(spi_devices[id])) + +#define IS31FL3743B_ROW_SIZE 6 +#define IS31FL3743B_COL_SIZE 11 +#define IS31FL3743B_GRID_SIZE (IS31FL3743B_COL_SIZE * IS31FL3743B_ROW_SIZE) +#define IS31FL3743B_BUF_SIZE (SIZE_OF_RGB * IS31FL3743B_GRID_SIZE) + +#define IS31FL3743B_CMD_ID 0b101 +#define IS31FL3743B_PAGE_PWM 0 +#define IS31FL3743B_PAGE_SCALE 1 +#define IS31FL3743B_PAGE_FUNC 2 + +#define IS31FL3743B_REG_CONFIG 0x00 +#define IS31FL3743B_REG_GCC 0x01 +#define IS31FL3743B_REG_PD_PU 0x02 +#define IS31FL3743B_REG_SPREAD_SPECTRUM 0x25 +#define IS31FL3743B_REG_RSTN 0x2f + +struct is31fl3743b_cmd { + uint8_t page: 4; + uint8_t id: 3; + uint8_t read: 1; +} __packed; + +struct is31fl3743b_msg { + struct is31fl3743b_cmd cmd; + uint8_t addr; + uint8_t payload[]; +} __packed; + +static int is31fl3743b_read(struct rgbkbd *ctx, uint8_t addr, uint8_t *value) +{ + uint8_t buf[8]; + struct is31fl3743b_msg *msg = (void *)buf; + const int frame_len = sizeof(*msg); + + msg->cmd.read = 1; + msg->cmd.id = IS31FL3743B_CMD_ID; + msg->cmd.page = IS31FL3743B_PAGE_FUNC; + msg->addr = addr; + + return spi_transaction(SPI(ctx->cfg->spi), buf, frame_len, value, 1); +} + +static int is31fl3743b_write(struct rgbkbd *ctx, uint8_t addr, uint8_t value) +{ + uint8_t buf[8]; + struct is31fl3743b_msg *msg = (void *)buf; + const int frame_len = sizeof(*msg) + 1; + + msg->cmd.read = 0; + msg->cmd.id = IS31FL3743B_CMD_ID; + msg->cmd.page = IS31FL3743B_PAGE_FUNC; + msg->addr = addr; + msg->payload[0] = value; + + return spi_transaction(SPI(ctx->cfg->spi), buf, frame_len, NULL, 0); +} + +static int is31fl3743b_reset(struct rgbkbd *ctx) +{ + return is31fl3743b_write(ctx, IS31FL3743B_REG_RSTN, 0xae); +} + +static int is31fl3743b_enable(struct rgbkbd *ctx, bool enable) +{ + uint8_t u8; + int rv; + + gpio_set_level(GPIO_RGBKBD_SDB_L, enable ? 1 : 0); + + rv = is31fl3743b_read(ctx, IS31FL3743B_REG_CONFIG, &u8); + if (rv) { + return rv; + } + + return is31fl3743b_write(ctx, IS31FL3743B_REG_CONFIG, + u8 | BIT(3) | (enable ? BIT(0) : 0)); +} + +static int is31fl3743b_set_color(struct rgbkbd *ctx, uint8_t offset, + struct rgb_s *color, uint8_t len) +{ + uint8_t buf[sizeof(struct is31fl3743b_msg) + IS31FL3743B_BUF_SIZE]; + struct is31fl3743b_msg *msg = (void *)buf; + const int frame_len = len * SIZE_OF_RGB + sizeof(*msg); + const int frame_offset = offset * SIZE_OF_RGB; + int i; + + msg->cmd.read = 0; + msg->cmd.id = IS31FL3743B_CMD_ID; + msg->cmd.page = IS31FL3743B_PAGE_PWM; + + if (frame_offset + frame_len > sizeof(buf)) { + return EC_ERROR_OVERFLOW; + } + + msg->addr = frame_offset + 1; /* Register addr base is 1. */ + for (i = 0; i < len; i++) { + msg->payload[i * SIZE_OF_RGB +0] = color[i].r; + msg->payload[i * SIZE_OF_RGB +1] = color[i].g; + msg->payload[i * SIZE_OF_RGB +2] = color[i].b; + } + + return spi_transaction(SPI(ctx->cfg->spi), buf, frame_len, NULL, 0); +} + +static int is31fl3743b_set_scale(struct rgbkbd *ctx, uint8_t offset, + uint8_t scale, uint8_t len) +{ + uint8_t buf[sizeof(struct is31fl3743b_msg) + IS31FL3743B_BUF_SIZE]; + struct is31fl3743b_msg *msg = (void *)buf; + const int frame_len = len * SIZE_OF_RGB + sizeof(*msg); + + msg->cmd.read = 0; + msg->cmd.id = IS31FL3743B_CMD_ID; + msg->cmd.page = IS31FL3743B_PAGE_SCALE; + + if (offset + frame_len > sizeof(buf)) { + return EC_ERROR_OVERFLOW; + } + + msg->addr = offset + 1; /* Address base is 1. */ + memset(msg->payload, scale, len * SIZE_OF_RGB); + + return spi_transaction(SPI(ctx->cfg->spi), buf, frame_len, NULL, 0); +} + +static int is31fl3743b_set_gcc(struct rgbkbd *ctx, uint8_t level) +{ + uint8_t buf[8]; + struct is31fl3743b_msg *msg = (void *)buf; + const int frame_len = sizeof(*msg) + 1; + + msg->cmd.read = 0; + msg->cmd.id = IS31FL3743B_CMD_ID; + msg->cmd.page = IS31FL3743B_PAGE_FUNC; + msg->addr = IS31FL3743B_REG_GCC; + msg->payload[0] = level; + + return spi_transaction(SPI(ctx->cfg->spi), buf, frame_len, NULL, 0); +} + +static int is31fl3743b_init(struct rgbkbd *ctx) +{ + int rv; + + rv = is31fl3743b_reset(ctx); + msleep(3); + rv |= is31fl3743b_enable(ctx, true); + if (rv) { + CPRINTS("Failed to enable or reset (%d)", rv); + return rv; + } + + if (IS_ENABLED(CONFIG_RGB_KEYBOARD_DEBUG)) { + uint8_t val; + rv = is31fl3743b_read(ctx, IS31FL3743B_REG_PD_PU, &val); + CPRINTS("PD/PU. val=0x%02x (rv=%d)", val, rv); + } + + return EC_SUCCESS; +} + +const struct rgbkbd_drv is31fl3743b_drv = { + .reset = is31fl3743b_reset, + .init = is31fl3743b_init, + .enable = is31fl3743b_enable, + .set_color = is31fl3743b_set_color, + .set_scale = is31fl3743b_set_scale, + .set_gcc = is31fl3743b_set_gcc, +}; |