summaryrefslogtreecommitdiff
path: root/driver/led
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2021-12-04 13:08:04 -0800
committerCommit Bot <commit-bot@chromium.org>2022-03-01 19:41:59 +0000
commit14b34644fe16349af348d21f20d3897707132896 (patch)
tree1439a332e77c942d809b2ebfc128d690d72fe8e8 /driver/led
parent10a7a0a72017fe15633fa563977b748e88ec8726 (diff)
downloadchrome-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.c189
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,
+};