summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzung-Bi Shih <tzungbi@chromium.org>2019-05-17 11:22:53 +0800
committerCommit Bot <commit-bot@chromium.org>2019-09-17 14:56:58 +0000
commit0ba3ba3049226e92d6cf64ed06031ec9a3bb7949 (patch)
treeb4f3aff83258c93042ad2b3a02bda7f2f50e3af3
parentbb5d21d349efbc12fa5596a811a241508621e64d (diff)
downloadchrome-ec-0ba3ba3049226e92d6cf64ed06031ec9a3bb7949.tar.gz
audio_codec: add DMIC abstract layer
Common DMIC host commands: - get_max_gain - get_gain_idx - set_gain_idx BRANCH=none BUG=b:122027734, b:123268236 TEST=1. define CONFIG_AUDIO_CODEC in board.h 2. define CONFIG_AUDIO_CODEC_DMIC in board.h 3. make BOARD=kukui_scp -j Change-Id: I7b4cc11645675f9d790947b17c3ea385dae13483 Signed-off-by: Tzung-Bi Shih <tzungbi@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1564502 Commit-Queue: Sean Abraham <seanabraham@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
-rw-r--r--common/audio_codec_dmic.c77
-rw-r--r--common/build.mk1
-rw-r--r--include/audio_codec.h57
-rw-r--r--include/config.h2
-rw-r--r--include/ec_commands.h43
5 files changed, 170 insertions, 10 deletions
diff --git a/common/audio_codec_dmic.c b/common/audio_codec_dmic.c
new file mode 100644
index 0000000000..461b8508e9
--- /dev/null
+++ b/common/audio_codec_dmic.c
@@ -0,0 +1,77 @@
+/*
+ * 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 int dmic_get_max_gain(struct host_cmd_handler_args *args)
+{
+ struct ec_response_ec_codec_dmic_get_max_gain *r = args->response;
+
+ if (audio_codec_dmic_get_max_gain(&r->max_gain) != EC_SUCCESS)
+ return EC_RES_ERROR;
+
+ args->response_size = sizeof(*r);
+ return EC_RES_SUCCESS;
+}
+
+static int dmic_set_gain_idx(struct host_cmd_handler_args *args)
+{
+ const struct ec_param_ec_codec_dmic *p = args->params;
+
+ if (audio_codec_dmic_set_gain_idx(
+ p->set_gain_idx_param.channel,
+ p->set_gain_idx_param.gain) != EC_SUCCESS)
+ return EC_RES_ERROR;
+
+ return EC_RES_SUCCESS;
+}
+
+static int dmic_get_gain_idx(struct host_cmd_handler_args *args)
+{
+ const struct ec_param_ec_codec_dmic *p = args->params;
+ struct ec_response_ec_codec_dmic_get_gain_idx *r = args->response;
+
+ if (audio_codec_dmic_get_gain_idx(
+ p->get_gain_idx_param.channel, &r->gain) != EC_SUCCESS)
+ return EC_RES_ERROR;
+
+ args->response_size = sizeof(*r);
+ return EC_RES_SUCCESS;
+}
+
+static int (*sub_cmds[])(struct host_cmd_handler_args *) = {
+ [EC_CODEC_DMIC_GET_MAX_GAIN] = dmic_get_max_gain,
+ [EC_CODEC_DMIC_SET_GAIN_IDX] = dmic_set_gain_idx,
+ [EC_CODEC_DMIC_GET_GAIN_IDX] = dmic_get_gain_idx,
+};
+
+#ifdef DEBUG_AUDIO_CODEC
+static char *strcmd[] = {
+ [EC_CODEC_DMIC_GET_MAX_GAIN] = "EC_CODEC_DMIC_GET_MAX_GAIN",
+ [EC_CODEC_DMIC_SET_GAIN_IDX] = "EC_CODEC_DMIC_SET_GAIN_IDX",
+ [EC_CODEC_DMIC_GET_GAIN_IDX] = "EC_CODEC_DMIC_GET_GAIN_IDX",
+};
+BUILD_ASSERT(ARRAY_SIZE(sub_cmds) == ARRAY_SIZE(strcmd));
+#endif
+
+static int dmic_host_command(struct host_cmd_handler_args *args)
+{
+ const struct ec_param_ec_codec_dmic *p = args->params;
+
+#ifdef DEBUG_AUDIO_CODEC
+ CPRINTS("DMIC subcommand: %s", strcmd[p->cmd]);
+#endif
+
+ if (p->cmd < EC_CODEC_DMIC_SUBCMD_COUNT)
+ return sub_cmds[p->cmd](args);
+
+ return EC_RES_INVALID_PARAM;
+}
+DECLARE_HOST_COMMAND(EC_CMD_EC_CODEC_DMIC, dmic_host_command, EC_VER_MASK(0));
diff --git a/common/build.mk b/common/build.mk
index 213db0a0fc..8398434b47 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -30,6 +30,7 @@ common-$(CONFIG_CMD_ADC)+=adc.o
common-$(HAS_TASK_ALS)+=als.o
common-$(CONFIG_AP_HANG_DETECT)+=ap_hang_detect.o
common-$(CONFIG_AUDIO_CODEC)+=audio_codec.o
+common-$(CONFIG_AUDIO_CODEC_DMIC)+=audio_codec_dmic.o
common-$(CONFIG_BACKLIGHT_LID)+=backlight_lid.o
common-$(CONFIG_BASE32)+=base32.o
common-$(CONFIG_DETACHABLE_BASE)+=base_state.o
diff --git a/include/audio_codec.h b/include/audio_codec.h
index ab1c65ae61..29a61ed817 100644
--- a/include/audio_codec.h
+++ b/include/audio_codec.h
@@ -58,4 +58,61 @@ int audio_codec_register_shm(uint8_t shm_id, uint8_t cap,
*/
int audio_codec_memmap_ap_to_ec(uintptr_t ap_addr, uintptr_t *ec_addr);
+
+/*
+ * DMIC abstract layer
+ */
+
+/*
+ * Gets the maximum possible gain value. All channels share the same maximum
+ * gain value [0, max].
+ *
+ * The gain has no unit and should fit in a scale to represent relative dB.
+ *
+ * For example, suppose maximum possible gain value is 4, one could define a
+ * mapping:
+ * - 0 => -10 dB
+ * - 1 => -5 dB
+ * - 2 => 0 dB
+ * - 3 => 5 dB
+ * - 4 => 10 dB
+ *
+ * @max_gain is the destination address to put the gain value.
+ *
+ * Returns:
+ * EC_SUCCESS if success.
+ * EC_ERROR_UNKNOWN if internal error.
+ */
+int audio_codec_dmic_get_max_gain(uint8_t *max_gain);
+
+/*
+ * Sets the microphone gain for the specified channel.
+ *
+ * @channel is an integer from enum ec_codec_dmic_channel. The valid range
+ * is [0, 7].
+ * @gain is the target gain for the specified channel. The valid range
+ * is [0, max_gain]. See also audio_codec_dmic_get_max_gain.
+ *
+ * Returns:
+ * EC_SUCCESS if success.
+ * EC_ERROR_UNKNOWN if internal error.
+ * EC_ERROR_INVAL if channel does not look good.
+ * EC_ERROR_INVAL if gain does not look good.
+ */
+int audio_codec_dmic_set_gain_idx(uint8_t channel, uint8_t gain);
+
+/*
+ * Gets the microphone gain of the specified channel.
+ *
+ * @channel is an integer from enum ec_codec_dmic_channel. The valid range
+ * is [0, 7].
+ * @gain is the destination address to put the gain value of the channel.
+ *
+ * Returns:
+ * EC_SUCCESS if success.
+ * EC_ERROR_UNKNOWN if internal error.
+ * EC_ERROR_INVAL if channel does not look good.
+ */
+int audio_codec_dmic_get_gain_idx(uint8_t channel, uint8_t *gain);
+
#endif
diff --git a/include/config.h b/include/config.h
index b09f26555b..b39196140a 100644
--- a/include/config.h
+++ b/include/config.h
@@ -352,6 +352,8 @@
/* Support audio codec. */
#undef CONFIG_AUDIO_CODEC
+/* Support audio codec on DMIC. */
+#undef CONFIG_AUDIO_CODEC_DMIC
/* Allow proprietary communication protocols' extensions. */
#undef CONFIG_EXTENSION_COMMAND
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 057c3411f4..e553ecdfa9 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -4723,30 +4723,53 @@ struct __ec_align4 ec_response_ec_codec_get_shm_addr {
#define EC_CMD_EC_CODEC_DMIC 0x00BD
enum ec_codec_dmic_subcmd {
- EC_CODEC_DMIC_SET_GAIN = 0x0,
- EC_CODEC_DMIC_GET_GAIN = 0x1,
+ EC_CODEC_DMIC_GET_MAX_GAIN = 0x0,
+ EC_CODEC_DMIC_SET_GAIN_IDX = 0x1,
+ EC_CODEC_DMIC_GET_GAIN_IDX = 0x2,
EC_CODEC_DMIC_SUBCMD_COUNT,
};
-struct __ec_align1 ec_param_ec_codec_dmic_set_gain {
- uint8_t left;
- uint8_t right;
+enum ec_codec_dmic_channel {
+ EC_CODEC_DMIC_CHANNEL_0 = 0x0,
+ EC_CODEC_DMIC_CHANNEL_1 = 0x1,
+ EC_CODEC_DMIC_CHANNEL_2 = 0x2,
+ EC_CODEC_DMIC_CHANNEL_3 = 0x3,
+ EC_CODEC_DMIC_CHANNEL_4 = 0x4,
+ EC_CODEC_DMIC_CHANNEL_5 = 0x5,
+ EC_CODEC_DMIC_CHANNEL_6 = 0x6,
+ EC_CODEC_DMIC_CHANNEL_7 = 0x7,
+ EC_CODEC_DMIC_CHANNEL_COUNT,
+};
+
+struct __ec_align1 ec_param_ec_codec_dmic_set_gain_idx {
+ uint8_t channel; /* enum ec_codec_dmic_channel */
+ uint8_t gain;
uint8_t reserved[2];
};
+struct __ec_align1 ec_param_ec_codec_dmic_get_gain_idx {
+ uint8_t channel; /* enum ec_codec_dmic_channel */
+ uint8_t reserved[3];
+};
+
struct __ec_align4 ec_param_ec_codec_dmic {
uint8_t cmd; /* enum ec_codec_dmic_subcmd */
uint8_t reserved[3];
union {
- struct ec_param_ec_codec_dmic_set_gain
- set_gain_param;
+ struct ec_param_ec_codec_dmic_set_gain_idx
+ set_gain_idx_param;
+ struct ec_param_ec_codec_dmic_get_gain_idx
+ get_gain_idx_param;
};
};
-struct __ec_align1 ec_response_ec_codec_dmic_get_gain {
- uint8_t left;
- uint8_t right;
+struct __ec_align1 ec_response_ec_codec_dmic_get_max_gain {
+ uint8_t max_gain;
+};
+
+struct __ec_align1 ec_response_ec_codec_dmic_get_gain_idx {
+ uint8_t gain;
};
/*****************************************************************************/