summaryrefslogtreecommitdiff
path: root/common/audio_codec.c
diff options
context:
space:
mode:
authorTzung-Bi Shih <tzungbi@chromium.org>2019-05-17 11:20:46 +0800
committerCommit Bot <commit-bot@chromium.org>2019-09-17 14:56:56 +0000
commit6b74ac1f7bbda42d0e6715f350ab7bf1493d70b7 (patch)
tree91f9f67f151d3e8f19c190a811118584948552f3 /common/audio_codec.c
parent6a47d9e360b5f64a3ea0fa9bc32cbab3cd623fe0 (diff)
downloadchrome-ec-6b74ac1f7bbda42d0e6715f350ab7bf1493d70b7.tar.gz
audio_codec: add common abstract layer
Common utilities: - register shared memory (SHM) - console channel Common host commands: - get_capabilities - get_shm_addr - set_shm_addr BRANCH=none BUG=b:122027734, b:123268236 TEST=1. define CONFIG_AUDIO_CODEC in board.h 2. make BOARD=kukui_scp -j Change-Id: I90e3e112bf8fdffc13eb486e0c608c264650768b Signed-off-by: Tzung-Bi Shih <tzungbi@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1616882 Reviewed-by: Nicolas Boichat <drinkcat@chromium.org> Commit-Queue: Sean Abraham <seanabraham@chromium.org>
Diffstat (limited to 'common/audio_codec.c')
-rw-r--r--common/audio_codec.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/common/audio_codec.c b/common/audio_codec.c
new file mode 100644
index 0000000000..1dcc7e9b16
--- /dev/null
+++ b/common/audio_codec.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2019 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 "audio_codec.h"
+#include "console.h"
+#include "host_command.h"
+
+#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args)
+
+static const uint32_t capabilities;
+
+static struct {
+ uint8_t cap;
+ uint8_t type;
+ uintptr_t *addr;
+ uint32_t len;
+} shms[EC_CODEC_SHM_ID_LAST];
+
+static int get_capabilities(struct host_cmd_handler_args *args)
+{
+ struct ec_response_ec_codec_get_capabilities *r = args->response;
+
+ r->capabilities = capabilities;
+
+ args->response_size = sizeof(*r);
+ return EC_RES_SUCCESS;
+}
+
+static int get_shm_addr(struct host_cmd_handler_args *args)
+{
+ const struct ec_param_ec_codec *p = args->params;
+ struct ec_response_ec_codec_get_shm_addr *r = args->response;
+ const uint8_t shm_id = p->get_shm_addr_param.shm_id;
+
+ if (shm_id >= EC_CODEC_SHM_ID_LAST)
+ return EC_RES_INVALID_PARAM;
+ if (!shms[shm_id].addr || !audio_codec_capable(shms[shm_id].cap))
+ return EC_RES_INVALID_PARAM;
+ if (!*shms[shm_id].addr &&
+ shms[shm_id].type == EC_CODEC_SHM_TYPE_EC_RAM)
+ return EC_RES_ERROR;
+
+ r->len = shms[shm_id].len;
+ r->type = shms[shm_id].type;
+ r->phys_addr = *shms[shm_id].addr;
+
+ args->response_size = sizeof(*r);
+ return EC_RES_SUCCESS;
+}
+
+static int set_shm_addr(struct host_cmd_handler_args *args)
+{
+ const struct ec_param_ec_codec *p = args->params;
+ const uint8_t shm_id = p->set_shm_addr_param.shm_id;
+ uintptr_t ap_addr, ec_addr;
+
+ if (shm_id >= EC_CODEC_SHM_ID_LAST)
+ return EC_RES_INVALID_PARAM;
+ if (!shms[shm_id].addr || !audio_codec_capable(shms[shm_id].cap))
+ return EC_RES_INVALID_PARAM;
+ if (p->set_shm_addr_param.len < shms[shm_id].len)
+ return EC_RES_INVALID_PARAM;
+ if (*shms[shm_id].addr)
+ return EC_RES_BUSY;
+
+ ap_addr = (uintptr_t)p->set_shm_addr_param.phys_addr;
+ if (audio_codec_memmap_ap_to_ec(ap_addr, &ec_addr) != EC_SUCCESS)
+ return EC_RES_ERROR;
+ *shms[shm_id].addr = ec_addr;
+
+ args->response_size = 0;
+ return EC_RES_SUCCESS;
+}
+
+static int (*sub_cmds[])(struct host_cmd_handler_args *) = {
+ [EC_CODEC_GET_CAPABILITIES] = get_capabilities,
+ [EC_CODEC_GET_SHM_ADDR] = get_shm_addr,
+ [EC_CODEC_SET_SHM_ADDR] = set_shm_addr,
+};
+
+#ifdef DEBUG_AUDIO_CODEC
+static char *strcmd[] = {
+ [EC_CODEC_GET_CAPABILITIES] = "EC_CODEC_GET_CAPABILITIES",
+ [EC_CODEC_GET_SHM_ADDR] = "EC_CODEC_GET_SHM_ADDR",
+ [EC_CODEC_SET_SHM_ADDR] = "EC_CODEC_SET_SHM_ADDR",
+};
+BUILD_ASSERT(ARRAY_SIZE(sub_cmds) == ARRAY_SIZE(strcmd));
+#endif
+
+static int host_command(struct host_cmd_handler_args *args)
+{
+ const struct ec_param_ec_codec *p = args->params;
+
+#ifdef DEBUG_AUDIO_CODEC
+ CPRINTS("subcommand: %s", strcmd[p->cmd]);
+#endif
+
+ if (p->cmd < EC_CODEC_SUBCMD_COUNT)
+ return sub_cmds[p->cmd](args);
+
+ return EC_RES_INVALID_PARAM;
+}
+DECLARE_HOST_COMMAND(EC_CMD_EC_CODEC, host_command, EC_VER_MASK(0));
+
+/*
+ * Exported interfaces.
+ */
+int audio_codec_capable(uint8_t cap)
+{
+ return capabilities & BIT(cap);
+}
+
+int audio_codec_register_shm(uint8_t shm_id, uint8_t cap,
+ uintptr_t *addr, uint32_t len, uint8_t type)
+{
+ if (shm_id >= EC_CODEC_SHM_ID_LAST)
+ return EC_ERROR_INVAL;
+ if (cap >= EC_CODEC_CAP_LAST)
+ return EC_ERROR_INVAL;
+ if (shms[shm_id].addr || shms[shm_id].len)
+ return EC_ERROR_BUSY;
+
+ shms[shm_id].cap = cap;
+ shms[shm_id].addr = addr;
+ shms[shm_id].len = len;
+ shms[shm_id].type = type;
+
+ return EC_SUCCESS;
+}
+
+__attribute__((weak))
+int audio_codec_memmap_ap_to_ec(uintptr_t ap_addr, uintptr_t *ec_addr)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}