alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV
@ 2019-10-14 10:20 Tzung-Bi Shih
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature Tzung-Bi Shih
                   ` (10 more replies)
  0 siblings, 11 replies; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid

This series makes mt6358, cros_ec_codec, and mt8183-mt6358-ts3a227-max98357
support WoV (wake on voice).

The first 3 commits are some cleanups and refactors.  It looks like
breaking the existing interface.  But please be noticed that, the
cros_ec_codec has not used by any real device yet.  The refactor is
very necessary to keep the style consistent and for easier to further
extend and maintain.
  platform/chrome: cros_ec: remove unused EC feature
  ASoC: cros_ec_codec: refactor I2S RX
  ASoC: cros_ec_codec: extract DMIC EC command from I2S RX

The 4th commit extends the feature offered from EC codec.
  platform/chrome: cros_ec: add common commands for EC codec

The 5th commit changes the behavior of setting and getting DMIC gains.
  ASoC: cros_ec_codec: read max DMIC gain from EC codec

The 6th and 7th commit make cros_ec_codec support WoV.
  ASoC: dt-bindings: cros_ec_codec: add SHM bindings
  ASoC: cros_ec_codec: support WoV

The 8th commit sets necessary registers on mt6358 to support WoV.
  ASoC: mediatek: mt6358: support WoV

The last 2 commit make machine driver mt8183-mt6358-ts3a227-max98357
support WoV if ec-codec is in DTS.
  ASoC: dt-bindings: mt8183: add ec-codec
  ASoC: mediatek: mt8183: support WoV

Changes from v1:
- fix a compile error and make kbuild bot happy
https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/156315.html
Changes from v2:
- rebase upon to "don't use snd_pcm_ops" series
https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/156170.html
- fix sparse errors
https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/156328.html
- use "reg" for SHM binding
https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/156657.html

Tzung-Bi Shih (10):
  WIP: platform/chrome: cros_ec: remove unused EC feature
  WIP: ASoC: cros_ec_codec: refactor I2S RX
  WIP: ASoC: cros_ec_codec: extract DMIC EC command from I2S RX
  WIP: platform/chrome: cros_ec: add common commands for EC codec
  WIP: ASoC: cros_ec_codec: read max DMIC gain from EC codec
  WIP: ASoC: dt-bindings: cros_ec_codec: add SHM bindings
  WIP: ASoC: cros_ec_codec: support WoV
  WIP: ASoC: mediatek: mt6358: support WoV
  WIP: ASoC: dt-bindings: mt8183: add ec-codec
  WIP: ASoC: mediatek: mt8183: support WoV

 .../bindings/sound/google,cros-ec-codec.txt   |   24 +-
 .../sound/mt8183-mt6358-ts3a227-max98357.txt  |    3 +
 drivers/platform/chrome/cros_ec_trace.c       |    5 +-
 .../linux/platform_data/cros_ec_commands.h    |  285 ++++-
 sound/soc/codecs/cros_ec_codec.c              | 1128 +++++++++++++----
 sound/soc/codecs/mt6358.c                     |  105 ++
 sound/soc/mediatek/Kconfig                    |    1 +
 .../mt8183/mt8183-mt6358-ts3a227-max98357.c   |   70 +-
 8 files changed, 1296 insertions(+), 325 deletions(-)

-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
@ 2019-10-14 10:20 ` Tzung-Bi Shih
  2019-10-15 11:48   ` Mark Brown
                     ` (2 more replies)
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 02/10] ASoC: cros_ec_codec: refactor I2S RX Tzung-Bi Shih
                   ` (9 subsequent siblings)
  10 siblings, 3 replies; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid

Remove unused EC_FEATURE_AUDIO_CODEC.

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 include/linux/platform_data/cros_ec_commands.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 98415686cbfa..43b8f7dae4cc 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -1277,8 +1277,6 @@ enum ec_feature_code {
 	 * MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE.
 	 */
 	EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37,
-	/* EC supports audio codec. */
-	EC_FEATURE_AUDIO_CODEC = 38,
 	/* The MCU is a System Companion Processor (SCP). */
 	EC_FEATURE_SCP = 39,
 	/* The MCU is an Integrated Sensor Hub */
-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] [PATCH v3 02/10] ASoC: cros_ec_codec: refactor I2S RX
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature Tzung-Bi Shih
@ 2019-10-14 10:20 ` Tzung-Bi Shih
  2019-10-17  2:30   ` Benson Leung
  2019-10-18 18:06   ` [alsa-devel] Applied "ASoC: cros_ec_codec: refactor I2S RX" to the asoc tree Mark Brown
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 03/10] ASoC: cros_ec_codec: extract DMIC EC command from I2S RX Tzung-Bi Shih
                   ` (8 subsequent siblings)
  10 siblings, 2 replies; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid

Refactor by the following items:
- reformat copyright declaration
- use more specific name "i2s rx"
- use verbose symbol names to separate namespaces
- make some short functions inline
- remove unused TDM-related code

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 drivers/platform/chrome/cros_ec_trace.c       |   2 +-
 .../linux/platform_data/cros_ec_commands.h    | 120 ++---
 sound/soc/codecs/cros_ec_codec.c              | 502 +++++++-----------
 3 files changed, 251 insertions(+), 373 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c
index 6f80ff4532ae..901850004b2b 100644
--- a/drivers/platform/chrome/cros_ec_trace.c
+++ b/drivers/platform/chrome/cros_ec_trace.c
@@ -98,7 +98,7 @@
 	TRACE_SYMBOL(EC_CMD_SB_READ_BLOCK), \
 	TRACE_SYMBOL(EC_CMD_SB_WRITE_BLOCK), \
 	TRACE_SYMBOL(EC_CMD_BATTERY_VENDOR_PARAM), \
-	TRACE_SYMBOL(EC_CMD_CODEC_I2S), \
+	TRACE_SYMBOL(EC_CMD_EC_CODEC_I2S_RX), \
 	TRACE_SYMBOL(EC_CMD_REBOOT_EC), \
 	TRACE_SYMBOL(EC_CMD_GET_PANIC_INFO), \
 	TRACE_SYMBOL(EC_CMD_ACPI_READ), \
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 43b8f7dae4cc..261ac83bd007 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -4466,92 +4466,74 @@ enum mkbp_cec_event {
 
 /*****************************************************************************/
 
-/* Commands for I2S recording on audio codec. */
-
-#define EC_CMD_CODEC_I2S 0x00BC
-#define EC_WOV_I2S_SAMPLE_RATE 48000
-
-enum ec_codec_i2s_subcmd {
-	EC_CODEC_SET_SAMPLE_DEPTH = 0x0,
-	EC_CODEC_SET_GAIN = 0x1,
-	EC_CODEC_GET_GAIN = 0x2,
-	EC_CODEC_I2S_ENABLE = 0x3,
-	EC_CODEC_I2S_SET_CONFIG = 0x4,
-	EC_CODEC_I2S_SET_TDM_CONFIG = 0x5,
-	EC_CODEC_I2S_SET_BCLK = 0x6,
-	EC_CODEC_I2S_SUBCMD_COUNT = 0x7,
+/* Commands for I2S RX on audio codec. */
+
+#define EC_CMD_EC_CODEC_I2S_RX 0x00BC
+
+enum ec_codec_i2s_rx_subcmd {
+	EC_CODEC_I2S_RX_ENABLE = 0x0,
+	EC_CODEC_I2S_RX_DISABLE = 0x1,
+	EC_CODEC_I2S_RX_SET_GAIN = 0x2,
+	EC_CODEC_I2S_RX_GET_GAIN = 0x3,
+	EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x4,
+	EC_CODEC_I2S_RX_SET_DAIFMT = 0x5,
+	EC_CODEC_I2S_RX_SET_BCLK = 0x6,
+	EC_CODEC_I2S_RX_SUBCMD_COUNT,
 };
 
-enum ec_sample_depth_value {
-	EC_CODEC_SAMPLE_DEPTH_16 = 0,
-	EC_CODEC_SAMPLE_DEPTH_24 = 1,
+enum ec_codec_i2s_rx_sample_depth {
+	EC_CODEC_I2S_RX_SAMPLE_DEPTH_16 = 0x0,
+	EC_CODEC_I2S_RX_SAMPLE_DEPTH_24 = 0x1,
+	EC_CODEC_I2S_RX_SAMPLE_DEPTH_COUNT,
 };
 
-enum ec_i2s_config {
-	EC_DAI_FMT_I2S = 0,
-	EC_DAI_FMT_RIGHT_J = 1,
-	EC_DAI_FMT_LEFT_J = 2,
-	EC_DAI_FMT_PCM_A = 3,
-	EC_DAI_FMT_PCM_B = 4,
-	EC_DAI_FMT_PCM_TDM = 5,
+enum ec_codec_i2s_rx_daifmt {
+	EC_CODEC_I2S_RX_DAIFMT_I2S = 0x0,
+	EC_CODEC_I2S_RX_DAIFMT_RIGHT_J = 0x1,
+	EC_CODEC_I2S_RX_DAIFMT_LEFT_J = 0x2,
+	EC_CODEC_I2S_RX_DAIFMT_COUNT,
 };
 
-/*
- * For subcommand EC_CODEC_GET_GAIN.
- */
-struct __ec_align1 ec_codec_i2s_gain {
+struct __ec_align1 ec_param_ec_codec_i2s_rx_set_sample_depth {
+	uint8_t depth;
+	uint8_t reserved[3];
+};
+
+struct __ec_align1 ec_param_ec_codec_i2s_rx_set_gain {
 	uint8_t left;
 	uint8_t right;
+	uint8_t reserved[2];
 };
 
-struct __ec_todo_unpacked ec_param_codec_i2s_tdm {
-	int16_t ch0_delay; /* 0 to 496 */
-	int16_t ch1_delay; /* -1 to 496 */
-	uint8_t adjacent_to_ch0;
-	uint8_t adjacent_to_ch1;
+struct __ec_align1 ec_param_ec_codec_i2s_rx_set_daifmt {
+	uint8_t daifmt;
+	uint8_t reserved[3];
 };
 
-struct __ec_todo_packed ec_param_codec_i2s {
-	/* enum ec_codec_i2s_subcmd */
-	uint8_t cmd;
-	union {
-		/*
-		 * EC_CODEC_SET_SAMPLE_DEPTH
-		 * Value should be one of ec_sample_depth_value.
-		 */
-		uint8_t depth;
-
-		/*
-		 * EC_CODEC_SET_GAIN
-		 * Value should be 0~43 for both channels.
-		 */
-		struct ec_codec_i2s_gain gain;
-
-		/*
-		 * EC_CODEC_I2S_ENABLE
-		 * 1 to enable, 0 to disable.
-		 */
-		uint8_t i2s_enable;
-
-		/*
-		 * EC_CODEC_I2S_SET_CONFIG
-		 * Value should be one of ec_i2s_config.
-		 */
-		uint8_t i2s_config;
+struct __ec_align4 ec_param_ec_codec_i2s_rx_set_bclk {
+	uint32_t bclk;
+};
 
-		/*
-		 * EC_CODEC_I2S_SET_TDM_CONFIG
-		 * Value should be one of ec_i2s_config.
-		 */
-		struct ec_param_codec_i2s_tdm tdm_param;
+struct __ec_align4 ec_param_ec_codec_i2s_rx {
+	uint8_t cmd; /* enum ec_codec_i2s_rx_subcmd */
+	uint8_t reserved[3];
 
-		/*
-		 * EC_CODEC_I2S_SET_BCLK
-		 */
-		uint32_t bclk;
+	union {
+		struct ec_param_ec_codec_i2s_rx_set_sample_depth
+				set_sample_depth_param;
+		struct ec_param_ec_codec_i2s_rx_set_gain
+				set_gain_param;
+		struct ec_param_ec_codec_i2s_rx_set_daifmt
+				set_daifmt_param;
+		struct ec_param_ec_codec_i2s_rx_set_bclk
+				set_bclk_param;
 	};
 };
 
+struct __ec_align1 ec_response_ec_codec_i2s_rx_get_gain {
+	uint8_t left;
+	uint8_t right;
+};
 
 /*****************************************************************************/
 /* System commands */
diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
index 3c1bd24a1057..179fa77291cd 100644
--- a/sound/soc/codecs/cros_ec_codec.c
+++ b/sound/soc/codecs/cros_ec_codec.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Driver for ChromeOS Embedded Controller codec.
+ * Copyright 2019 Google, Inc.
+ *
+ * ChromeOS Embedded Controller codec driver.
  *
  * This driver uses the cros-ec interface to communicate with the ChromeOS
  * EC for audio function.
@@ -18,403 +20,297 @@
 #include <sound/soc.h>
 #include <sound/tlv.h>
 
-#define DRV_NAME "cros-ec-codec"
-
-/**
- * struct cros_ec_codec_data - ChromeOS EC codec driver data.
- * @dev:		Device structure used in sysfs.
- * @ec_device:		cros_ec_device structure to talk to the physical device.
- * @component:		Pointer to the component.
- * @max_dmic_gain:	Maximum gain in dB supported by EC codec.
- */
-struct cros_ec_codec_data {
+struct cros_ec_codec_priv {
 	struct device *dev;
 	struct cros_ec_device *ec_device;
-	struct snd_soc_component *component;
-	unsigned int max_dmic_gain;
 };
 
-static const DECLARE_TLV_DB_SCALE(ec_mic_gain_tlv, 0, 100, 0);
-
-static int ec_command_get_gain(struct snd_soc_component *component,
-			       struct ec_param_codec_i2s *param,
-			       struct ec_codec_i2s_gain *resp)
+static int send_ec_host_command(struct cros_ec_device *ec_dev, uint32_t cmd,
+				uint8_t *out, size_t outsize,
+				uint8_t *in, size_t insize)
 {
-	struct cros_ec_codec_data *codec_data =
-		snd_soc_component_get_drvdata(component);
-	struct cros_ec_device *ec_device = codec_data->ec_device;
-	u8 buffer[sizeof(struct cros_ec_command) +
-		  max(sizeof(struct ec_param_codec_i2s),
-		      sizeof(struct ec_codec_i2s_gain))];
-	struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
 	int ret;
+	struct cros_ec_command *msg;
+
+	msg = kmalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
 
 	msg->version = 0;
-	msg->command = EC_CMD_CODEC_I2S;
-	msg->outsize = sizeof(struct ec_param_codec_i2s);
-	msg->insize = sizeof(struct ec_codec_i2s_gain);
+	msg->command = cmd;
+	msg->outsize = outsize;
+	msg->insize = insize;
+
+	if (outsize)
+		memcpy(msg->data, out, outsize);
 
-	memcpy(msg->data, param, msg->outsize);
+	ret = cros_ec_cmd_xfer_status(ec_dev, msg);
+	if (ret < 0)
+		goto error;
 
-	ret = cros_ec_cmd_xfer_status(ec_device, msg);
-	if (ret > 0)
-		memcpy(resp, msg->data, msg->insize);
+	if (insize)
+		memcpy(in, msg->data, insize);
 
+	ret = 0;
+error:
+	kfree(msg);
 	return ret;
 }
 
-/*
- * Wrapper for EC command without response.
- */
-static int ec_command_no_resp(struct snd_soc_component *component,
-			      struct ec_param_codec_i2s *param)
+static int dmic_get_gain(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
 {
-	struct cros_ec_codec_data *codec_data =
+	struct snd_soc_component *component =
+		snd_soc_kcontrol_component(kcontrol);
+	struct cros_ec_codec_priv *priv =
 		snd_soc_component_get_drvdata(component);
-	struct cros_ec_device *ec_device = codec_data->ec_device;
-	u8 buffer[sizeof(struct cros_ec_command) +
-		  sizeof(struct ec_param_codec_i2s)];
-	struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
-
-	msg->version = 0;
-	msg->command = EC_CMD_CODEC_I2S;
-	msg->outsize = sizeof(struct ec_param_codec_i2s);
-	msg->insize = 0;
-
-	memcpy(msg->data, param, msg->outsize);
-
-	return cros_ec_cmd_xfer_status(ec_device, msg);
-}
-
-static int set_i2s_config(struct snd_soc_component *component,
-			  enum ec_i2s_config i2s_config)
-{
-	struct ec_param_codec_i2s param;
+	struct ec_param_ec_codec_i2s_rx p;
+	struct ec_response_ec_codec_i2s_rx_get_gain r;
+	int ret;
 
-	dev_dbg(component->dev, "%s set I2S format to %u\n", __func__,
-		i2s_config);
+	p.cmd = EC_CODEC_I2S_RX_GET_GAIN;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				   (uint8_t *)&p, sizeof(p),
+				   (uint8_t *)&r, sizeof(r));
+	if (ret < 0)
+		return ret;
 
-	param.cmd = EC_CODEC_I2S_SET_CONFIG;
-	param.i2s_config = i2s_config;
+	ucontrol->value.integer.value[0] = r.left;
+	ucontrol->value.integer.value[1] = r.right;
 
-	return ec_command_no_resp(component, &param);
+	return 0;
 }
 
-static int cros_ec_i2s_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+static int dmic_put_gain(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_component *component = dai->component;
-	enum ec_i2s_config i2s_config;
-
-	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-	case SND_SOC_DAIFMT_CBS_CFS:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-	case SND_SOC_DAIFMT_NB_NF:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_I2S:
-		i2s_config = EC_DAI_FMT_I2S;
-		break;
-
-	case SND_SOC_DAIFMT_RIGHT_J:
-		i2s_config = EC_DAI_FMT_RIGHT_J;
-		break;
-
-	case SND_SOC_DAIFMT_LEFT_J:
-		i2s_config = EC_DAI_FMT_LEFT_J;
-		break;
-
-	case SND_SOC_DAIFMT_DSP_A:
-		i2s_config = EC_DAI_FMT_PCM_A;
-		break;
-
-	case SND_SOC_DAIFMT_DSP_B:
-		i2s_config = EC_DAI_FMT_PCM_B;
-		break;
+	struct snd_soc_component *component =
+		snd_soc_kcontrol_component(kcontrol);
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct soc_mixer_control *control =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	int max_dmic_gain = control->max;
+	int left = ucontrol->value.integer.value[0];
+	int right = ucontrol->value.integer.value[1];
+	struct ec_param_ec_codec_i2s_rx p;
 
-	default:
+	if (left > max_dmic_gain || right > max_dmic_gain)
 		return -EINVAL;
-	}
 
-	return set_i2s_config(component, i2s_config);
-}
-
-static int set_i2s_sample_depth(struct snd_soc_component *component,
-				enum ec_sample_depth_value depth)
-{
-	struct ec_param_codec_i2s param;
-
-	dev_dbg(component->dev, "%s set depth to %u\n", __func__, depth);
-
-	param.cmd = EC_CODEC_SET_SAMPLE_DEPTH;
-	param.depth = depth;
+	dev_dbg(component->dev, "set mic gain to %u, %u\n", left, right);
 
-	return ec_command_no_resp(component, &param);
+	p.cmd = EC_CODEC_I2S_RX_SET_GAIN;
+	p.set_gain_param.left = left;
+	p.set_gain_param.right = right;
+	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
 
-static int set_i2s_bclk(struct snd_soc_component *component, uint32_t bclk)
-{
-	struct ec_param_codec_i2s param;
-
-	dev_dbg(component->dev, "%s set i2s bclk to %u\n", __func__, bclk);
+static const DECLARE_TLV_DB_SCALE(dmic_gain_tlv, 0, 100, 0);
 
-	param.cmd = EC_CODEC_I2S_SET_BCLK;
-	param.bclk = bclk;
+enum {
+	DMIC_CTL_GAIN = 0,
+};
 
-	return ec_command_no_resp(component, &param);
-}
+static struct snd_kcontrol_new dmic_controls[] = {
+	[DMIC_CTL_GAIN] =
+		SOC_DOUBLE_EXT_TLV("EC Mic Gain", SND_SOC_NOPM, SND_SOC_NOPM,
+				   0, 0, 0, dmic_get_gain, dmic_put_gain,
+				   dmic_gain_tlv),
+};
 
-static int cros_ec_i2s_hw_params(struct snd_pcm_substream *substream,
-				 struct snd_pcm_hw_params *params,
-				 struct snd_soc_dai *dai)
+static int i2s_rx_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
 {
 	struct snd_soc_component *component = dai->component;
-	unsigned int rate, bclk;
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct ec_param_ec_codec_i2s_rx p;
+	enum ec_codec_i2s_rx_sample_depth depth;
 	int ret;
 
-	rate = params_rate(params);
-	if (rate != 48000)
+	if (params_rate(params) != 48000)
 		return -EINVAL;
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
-		ret = set_i2s_sample_depth(component, EC_CODEC_SAMPLE_DEPTH_16);
+		depth = EC_CODEC_I2S_RX_SAMPLE_DEPTH_16;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
-		ret = set_i2s_sample_depth(component, EC_CODEC_SAMPLE_DEPTH_24);
+		depth = EC_CODEC_I2S_RX_SAMPLE_DEPTH_24;
 		break;
 	default:
 		return -EINVAL;
 	}
-	if (ret < 0)
-		return ret;
-
-	bclk = snd_soc_params_to_bclk(params);
-	return set_i2s_bclk(component, bclk);
-}
 
-static const struct snd_soc_dai_ops cros_ec_i2s_dai_ops = {
-	.hw_params = cros_ec_i2s_hw_params,
-	.set_fmt = cros_ec_i2s_set_dai_fmt,
-};
+	dev_dbg(component->dev, "set depth to %u\n", depth);
 
-static struct snd_soc_dai_driver cros_ec_dai[] = {
-	{
-		.name = "cros_ec_codec I2S",
-		.id = 0,
-		.capture = {
-			.stream_name = "I2S Capture",
-			.channels_min = 2,
-			.channels_max = 2,
-			.rates = SNDRV_PCM_RATE_48000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE |
-				   SNDRV_PCM_FMTBIT_S24_LE,
-		},
-		.ops = &cros_ec_i2s_dai_ops,
-	}
-};
-
-static int get_ec_mic_gain(struct snd_soc_component *component,
-			   u8 *left, u8 *right)
-{
-	struct ec_param_codec_i2s param;
-	struct ec_codec_i2s_gain resp;
-	int ret;
-
-	param.cmd = EC_CODEC_GET_GAIN;
-
-	ret = ec_command_get_gain(component, &param, &resp);
+	p.cmd = EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH;
+	p.set_sample_depth_param.depth = depth;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				   (uint8_t *)&p, sizeof(p), NULL, 0);
 	if (ret < 0)
 		return ret;
 
-	*left = resp.left;
-	*right = resp.right;
-
-	return 0;
-}
-
-static int mic_gain_get(struct snd_kcontrol *kcontrol,
-			struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_component *component =
-		snd_soc_kcontrol_component(kcontrol);
-	u8 left, right;
-	int ret;
-
-	ret = get_ec_mic_gain(component, &left, &right);
-	if (ret)
-		return ret;
-
-	ucontrol->value.integer.value[0] = left;
-	ucontrol->value.integer.value[1] = right;
-
-	return 0;
-}
-
-static int set_ec_mic_gain(struct snd_soc_component *component,
-			   u8 left, u8 right)
-{
-	struct ec_param_codec_i2s param;
-
-	dev_dbg(component->dev, "%s set mic gain to %u, %u\n",
-		__func__, left, right);
+	dev_dbg(component->dev, "set bclk to %u\n",
+		snd_soc_params_to_bclk(params));
 
-	param.cmd = EC_CODEC_SET_GAIN;
-	param.gain.left = left;
-	param.gain.right = right;
-
-	return ec_command_no_resp(component, &param);
+	p.cmd = EC_CODEC_I2S_RX_SET_BCLK;
+	p.set_bclk_param.bclk = snd_soc_params_to_bclk(params);
+	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
 
-static int mic_gain_put(struct snd_kcontrol *kcontrol,
-			struct snd_ctl_elem_value *ucontrol)
+static int i2s_rx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-	struct snd_soc_component *component =
-		snd_soc_kcontrol_component(kcontrol);
-	struct cros_ec_codec_data *codec_data =
+	struct snd_soc_component *component = dai->component;
+	struct cros_ec_codec_priv *priv =
 		snd_soc_component_get_drvdata(component);
-	int left = ucontrol->value.integer.value[0];
-	int right = ucontrol->value.integer.value[1];
-	unsigned int max_dmic_gain = codec_data->max_dmic_gain;
+	struct ec_param_ec_codec_i2s_rx p;
+	enum ec_codec_i2s_rx_daifmt daifmt;
 
-	if (left > max_dmic_gain || right > max_dmic_gain)
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
 		return -EINVAL;
+	}
 
-	return set_ec_mic_gain(component, (u8)left, (u8)right);
-}
-
-static struct snd_kcontrol_new mic_gain_control =
-	SOC_DOUBLE_EXT_TLV("EC Mic Gain", SND_SOC_NOPM, SND_SOC_NOPM, 0, 0, 0,
-			   mic_gain_get, mic_gain_put, ec_mic_gain_tlv);
-
-static int enable_i2s(struct snd_soc_component *component, int enable)
-{
-	struct ec_param_codec_i2s param;
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	default:
+		return -EINVAL;
+	}
 
-	dev_dbg(component->dev, "%s set i2s to %u\n", __func__, enable);
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		daifmt = EC_CODEC_I2S_RX_DAIFMT_I2S;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		daifmt = EC_CODEC_I2S_RX_DAIFMT_RIGHT_J;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		daifmt = EC_CODEC_I2S_RX_DAIFMT_LEFT_J;
+		break;
+	default:
+		return -EINVAL;
+	}
 
-	param.cmd = EC_CODEC_I2S_ENABLE;
-	param.i2s_enable = enable;
+	dev_dbg(component->dev, "set format to %u\n", daifmt);
 
-	return ec_command_no_resp(component, &param);
+	p.cmd = EC_CODEC_I2S_RX_SET_DAIFMT;
+	p.set_daifmt_param.daifmt = daifmt;
+	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
 
-static int cros_ec_i2s_enable_event(struct snd_soc_dapm_widget *w,
-				    struct snd_kcontrol *kcontrol, int event)
+static const struct snd_soc_dai_ops i2s_rx_dai_ops = {
+	.hw_params = i2s_rx_hw_params,
+	.set_fmt = i2s_rx_set_fmt,
+};
+
+static int i2s_rx_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_component *component =
 		snd_soc_dapm_to_component(w->dapm);
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct ec_param_ec_codec_i2s_rx p;
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		dev_dbg(component->dev,
-			"%s got SND_SOC_DAPM_PRE_PMU event\n", __func__);
-		return enable_i2s(component, 1);
-
+		dev_dbg(component->dev, "enable I2S RX\n");
+		p.cmd = EC_CODEC_I2S_RX_ENABLE;
+		break;
 	case SND_SOC_DAPM_PRE_PMD:
-		dev_dbg(component->dev,
-			"%s got SND_SOC_DAPM_PRE_PMD event\n", __func__);
-		return enable_i2s(component, 0);
+		dev_dbg(component->dev, "disable I2S RX\n");
+		p.cmd = EC_CODEC_I2S_RX_DISABLE;
+		break;
+	default:
+		return 0;
 	}
 
-	return 0;
+	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
 
-/*
- * The goal of this DAPM route is to turn on/off I2S using EC
- * host command when capture stream is started/stopped.
- */
-static const struct snd_soc_dapm_widget cros_ec_codec_dapm_widgets[] = {
+static struct snd_soc_dapm_widget i2s_rx_dapm_widgets[] = {
 	SND_SOC_DAPM_INPUT("DMIC"),
-
-	/*
-	 * Control EC to enable/disable I2S.
-	 */
-	SND_SOC_DAPM_SUPPLY("I2S Enable", SND_SOC_NOPM,
-			    0, 0, cros_ec_i2s_enable_event,
+	SND_SOC_DAPM_SUPPLY("I2S RX Enable", SND_SOC_NOPM, 0, 0, i2s_rx_event,
 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_AIF_OUT("I2S RX", "I2S Capture", 0, SND_SOC_NOPM, 0, 0),
+};
 
-	SND_SOC_DAPM_AIF_OUT("I2STX", "I2S Capture", 0, SND_SOC_NOPM, 0, 0),
+static struct snd_soc_dapm_route i2s_rx_dapm_routes[] = {
+	{"I2S RX", NULL, "DMIC"},
+	{"I2S RX", NULL, "I2S RX Enable"},
 };
 
-static const struct snd_soc_dapm_route cros_ec_codec_dapm_routes[] = {
-	{ "I2STX", NULL, "DMIC" },
-	{ "I2STX", NULL, "I2S Enable" },
+static struct snd_soc_dai_driver i2s_rx_dai_driver = {
+	.name = "EC Codec I2S RX",
+	.capture = {
+		.stream_name = "I2S Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE |
+			SNDRV_PCM_FMTBIT_S24_LE,
+	},
+	.ops = &i2s_rx_dai_ops,
 };
 
-/*
- * Read maximum gain from device property and set it to mixer control.
- */
-static int cros_ec_set_gain_range(struct device *dev)
+static int i2s_rx_probe(struct snd_soc_component *component)
 {
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct device *dev = priv->dev;
+	int ret, val;
 	struct soc_mixer_control *control;
-	struct cros_ec_codec_data *codec_data = dev_get_drvdata(dev);
-	int rc;
 
-	rc = device_property_read_u32(dev, "max-dmic-gain",
-				      &codec_data->max_dmic_gain);
-	if (rc)
-		return rc;
+	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
+	if (ret) {
+		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
+		return ret;
+	}
 
 	control = (struct soc_mixer_control *)
-				mic_gain_control.private_value;
-	control->max = codec_data->max_dmic_gain;
-	control->platform_max = codec_data->max_dmic_gain;
+			dmic_controls[DMIC_CTL_GAIN].private_value;
+	control->max = val;
+	control->platform_max = val;
 
-	return 0;
-}
-
-static int cros_ec_codec_probe(struct snd_soc_component *component)
-{
-	int rc;
-
-	struct cros_ec_codec_data *codec_data =
-		snd_soc_component_get_drvdata(component);
-
-	rc = cros_ec_set_gain_range(codec_data->dev);
-	if (rc)
-		return rc;
-
-	return snd_soc_add_component_controls(component, &mic_gain_control, 1);
+	return snd_soc_add_component_controls(component,
+			&dmic_controls[DMIC_CTL_GAIN], 1);
 }
 
-static const struct snd_soc_component_driver cros_ec_component_driver = {
-	.probe			= cros_ec_codec_probe,
-	.dapm_widgets		= cros_ec_codec_dapm_widgets,
-	.num_dapm_widgets	= ARRAY_SIZE(cros_ec_codec_dapm_widgets),
-	.dapm_routes		= cros_ec_codec_dapm_routes,
-	.num_dapm_routes	= ARRAY_SIZE(cros_ec_codec_dapm_routes),
+static const struct snd_soc_component_driver i2s_rx_component_driver = {
+	.probe			= i2s_rx_probe,
+	.dapm_widgets		= i2s_rx_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(i2s_rx_dapm_widgets),
+	.dapm_routes		= i2s_rx_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(i2s_rx_dapm_routes),
 };
 
-/*
- * Platform device and platform driver fro cros-ec-codec.
- */
-static int cros_ec_codec_platform_probe(struct platform_device *pd)
+static int cros_ec_codec_platform_probe(struct platform_device *pdev)
 {
-	struct device *dev = &pd->dev;
-	struct cros_ec_device *ec_device = dev_get_drvdata(pd->dev.parent);
-	struct cros_ec_codec_data *codec_data;
+	struct device *dev = &pdev->dev;
+	struct cros_ec_device *ec_device = dev_get_drvdata(pdev->dev.parent);
+	struct cros_ec_codec_priv *priv;
 
-	codec_data = devm_kzalloc(dev, sizeof(struct cros_ec_codec_data),
-				  GFP_KERNEL);
-	if (!codec_data)
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
 
-	codec_data->dev = dev;
-	codec_data->ec_device = ec_device;
+	priv->dev = dev;
+	priv->ec_device = ec_device;
 
-	platform_set_drvdata(pd, codec_data);
+	platform_set_drvdata(pdev, priv);
 
-	return devm_snd_soc_register_component(dev, &cros_ec_component_driver,
-					  cros_ec_dai, ARRAY_SIZE(cros_ec_dai));
+	return devm_snd_soc_register_component(dev, &i2s_rx_component_driver,
+					       &i2s_rx_dai_driver, 1);
 }
 
 #ifdef CONFIG_OF
@@ -427,7 +323,7 @@ MODULE_DEVICE_TABLE(of, cros_ec_codec_of_match);
 
 static struct platform_driver cros_ec_codec_platform_driver = {
 	.driver = {
-		.name = DRV_NAME,
+		.name = "cros-ec-codec",
 		.of_match_table = of_match_ptr(cros_ec_codec_of_match),
 	},
 	.probe = cros_ec_codec_platform_probe,
@@ -438,4 +334,4 @@ module_platform_driver(cros_ec_codec_platform_driver);
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("ChromeOS EC codec driver");
 MODULE_AUTHOR("Cheng-Yi Chiang <cychiang@chromium.org>");
-MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS("platform:cros-ec-codec");
-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] [PATCH v3 03/10] ASoC: cros_ec_codec: extract DMIC EC command from I2S RX
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature Tzung-Bi Shih
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 02/10] ASoC: cros_ec_codec: refactor I2S RX Tzung-Bi Shih
@ 2019-10-14 10:20 ` Tzung-Bi Shih
  2019-10-17  2:48   ` Benson Leung
  2019-10-18 18:06   ` [alsa-devel] Applied "ASoC: cros_ec_codec: extract DMIC EC command from I2S RX" to the asoc tree Mark Brown
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 04/10] platform/chrome: cros_ec: add common commands for EC codec Tzung-Bi Shih
                   ` (7 subsequent siblings)
  10 siblings, 2 replies; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid

Extract DMIC EC command from I2S RX.  Setting and getting
microphone gains is common features.

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 drivers/platform/chrome/cros_ec_trace.c       |  1 +
 .../linux/platform_data/cros_ec_commands.h    | 49 +++++++++++-----
 sound/soc/codecs/cros_ec_codec.c              | 57 ++++++++++---------
 3 files changed, 68 insertions(+), 39 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c
index 901850004b2b..e73bb6a8b00e 100644
--- a/drivers/platform/chrome/cros_ec_trace.c
+++ b/drivers/platform/chrome/cros_ec_trace.c
@@ -98,6 +98,7 @@
 	TRACE_SYMBOL(EC_CMD_SB_READ_BLOCK), \
 	TRACE_SYMBOL(EC_CMD_SB_WRITE_BLOCK), \
 	TRACE_SYMBOL(EC_CMD_BATTERY_VENDOR_PARAM), \
+	TRACE_SYMBOL(EC_CMD_EC_CODEC_DMIC), \
 	TRACE_SYMBOL(EC_CMD_EC_CODEC_I2S_RX), \
 	TRACE_SYMBOL(EC_CMD_REBOOT_EC), \
 	TRACE_SYMBOL(EC_CMD_GET_PANIC_INFO), \
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 261ac83bd007..58e460c015ef 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -4466,18 +4466,48 @@ enum mkbp_cec_event {
 
 /*****************************************************************************/
 
+/* Commands for DMIC on audio codec. */
+#define EC_CMD_EC_CODEC_DMIC 0x00BC
+
+enum ec_codec_dmic_subcmd {
+	EC_CODEC_DMIC_SET_GAIN = 0x0,
+	EC_CODEC_DMIC_GET_GAIN = 0x1,
+	EC_CODEC_DMIC_SUBCMD_COUNT,
+};
+
+struct __ec_align1 ec_param_ec_codec_dmic_set_gain {
+	uint8_t left;
+	uint8_t right;
+	uint8_t reserved[2];
+};
+
+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_align1 ec_response_ec_codec_dmic_get_gain {
+	uint8_t left;
+	uint8_t right;
+};
+
+/*****************************************************************************/
+
 /* Commands for I2S RX on audio codec. */
 
-#define EC_CMD_EC_CODEC_I2S_RX 0x00BC
+#define EC_CMD_EC_CODEC_I2S_RX 0x00BD
 
 enum ec_codec_i2s_rx_subcmd {
 	EC_CODEC_I2S_RX_ENABLE = 0x0,
 	EC_CODEC_I2S_RX_DISABLE = 0x1,
-	EC_CODEC_I2S_RX_SET_GAIN = 0x2,
-	EC_CODEC_I2S_RX_GET_GAIN = 0x3,
-	EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x4,
-	EC_CODEC_I2S_RX_SET_DAIFMT = 0x5,
-	EC_CODEC_I2S_RX_SET_BCLK = 0x6,
+	EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x2,
+	EC_CODEC_I2S_RX_SET_DAIFMT = 0x3,
+	EC_CODEC_I2S_RX_SET_BCLK = 0x4,
 	EC_CODEC_I2S_RX_SUBCMD_COUNT,
 };
 
@@ -4521,8 +4551,6 @@ struct __ec_align4 ec_param_ec_codec_i2s_rx {
 	union {
 		struct ec_param_ec_codec_i2s_rx_set_sample_depth
 				set_sample_depth_param;
-		struct ec_param_ec_codec_i2s_rx_set_gain
-				set_gain_param;
 		struct ec_param_ec_codec_i2s_rx_set_daifmt
 				set_daifmt_param;
 		struct ec_param_ec_codec_i2s_rx_set_bclk
@@ -4530,11 +4558,6 @@ struct __ec_align4 ec_param_ec_codec_i2s_rx {
 	};
 };
 
-struct __ec_align1 ec_response_ec_codec_i2s_rx_get_gain {
-	uint8_t left;
-	uint8_t right;
-};
-
 /*****************************************************************************/
 /* System commands */
 
diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
index 179fa77291cd..c19c7fe42e2e 100644
--- a/sound/soc/codecs/cros_ec_codec.c
+++ b/sound/soc/codecs/cros_ec_codec.c
@@ -64,12 +64,12 @@ static int dmic_get_gain(struct snd_kcontrol *kcontrol,
 		snd_soc_kcontrol_component(kcontrol);
 	struct cros_ec_codec_priv *priv =
 		snd_soc_component_get_drvdata(component);
-	struct ec_param_ec_codec_i2s_rx p;
-	struct ec_response_ec_codec_i2s_rx_get_gain r;
+	struct ec_param_ec_codec_dmic p;
+	struct ec_response_ec_codec_dmic_get_gain r;
 	int ret;
 
-	p.cmd = EC_CODEC_I2S_RX_GET_GAIN;
-	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+	p.cmd = EC_CODEC_DMIC_GET_GAIN;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 				   (uint8_t *)&p, sizeof(p),
 				   (uint8_t *)&r, sizeof(r));
 	if (ret < 0)
@@ -93,17 +93,17 @@ static int dmic_put_gain(struct snd_kcontrol *kcontrol,
 	int max_dmic_gain = control->max;
 	int left = ucontrol->value.integer.value[0];
 	int right = ucontrol->value.integer.value[1];
-	struct ec_param_ec_codec_i2s_rx p;
+	struct ec_param_ec_codec_dmic p;
 
 	if (left > max_dmic_gain || right > max_dmic_gain)
 		return -EINVAL;
 
 	dev_dbg(component->dev, "set mic gain to %u, %u\n", left, right);
 
-	p.cmd = EC_CODEC_I2S_RX_SET_GAIN;
+	p.cmd = EC_CODEC_DMIC_SET_GAIN;
 	p.set_gain_param.left = left;
 	p.set_gain_param.right = right;
-	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
 
@@ -120,6 +120,29 @@ static struct snd_kcontrol_new dmic_controls[] = {
 				   dmic_gain_tlv),
 };
 
+static int dmic_probe(struct snd_soc_component *component)
+{
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct device *dev = priv->dev;
+	int ret, val;
+	struct soc_mixer_control *control;
+
+	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
+	if (ret) {
+		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
+		return ret;
+	}
+
+	control = (struct soc_mixer_control *)
+		dmic_controls[DMIC_CTL_GAIN].private_value;
+	control->max = val;
+	control->platform_max = val;
+
+	return snd_soc_add_component_controls(component,
+			&dmic_controls[DMIC_CTL_GAIN], 1);
+}
+
 static int i2s_rx_hw_params(struct snd_pcm_substream *substream,
 			    struct snd_pcm_hw_params *params,
 			    struct snd_soc_dai *dai)
@@ -265,25 +288,7 @@ static struct snd_soc_dai_driver i2s_rx_dai_driver = {
 
 static int i2s_rx_probe(struct snd_soc_component *component)
 {
-	struct cros_ec_codec_priv *priv =
-		snd_soc_component_get_drvdata(component);
-	struct device *dev = priv->dev;
-	int ret, val;
-	struct soc_mixer_control *control;
-
-	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
-	if (ret) {
-		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
-		return ret;
-	}
-
-	control = (struct soc_mixer_control *)
-			dmic_controls[DMIC_CTL_GAIN].private_value;
-	control->max = val;
-	control->platform_max = val;
-
-	return snd_soc_add_component_controls(component,
-			&dmic_controls[DMIC_CTL_GAIN], 1);
+	return dmic_probe(component);
 }
 
 static const struct snd_soc_component_driver i2s_rx_component_driver = {
-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] [PATCH v3 04/10] platform/chrome: cros_ec: add common commands for EC codec
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
                   ` (2 preceding siblings ...)
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 03/10] ASoC: cros_ec_codec: extract DMIC EC command from I2S RX Tzung-Bi Shih
@ 2019-10-14 10:20 ` Tzung-Bi Shih
  2019-10-17  2:57   ` Benson Leung
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 05/10] ASoC: cros_ec_codec: read max DMIC gain from " Tzung-Bi Shih
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid

Add the following common commands:
- GET_CAPABILITIES
- GET_SHM_ADDR
- SET_SHM_ADDR

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 drivers/platform/chrome/cros_ec_trace.c       |  1 +
 .../linux/platform_data/cros_ec_commands.h    | 64 ++++++++++++++++++-
 2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c
index e73bb6a8b00e..2ea0d4e0d54d 100644
--- a/drivers/platform/chrome/cros_ec_trace.c
+++ b/drivers/platform/chrome/cros_ec_trace.c
@@ -98,6 +98,7 @@
 	TRACE_SYMBOL(EC_CMD_SB_READ_BLOCK), \
 	TRACE_SYMBOL(EC_CMD_SB_WRITE_BLOCK), \
 	TRACE_SYMBOL(EC_CMD_BATTERY_VENDOR_PARAM), \
+	TRACE_SYMBOL(EC_CMD_EC_CODEC), \
 	TRACE_SYMBOL(EC_CMD_EC_CODEC_DMIC), \
 	TRACE_SYMBOL(EC_CMD_EC_CODEC_I2S_RX), \
 	TRACE_SYMBOL(EC_CMD_REBOOT_EC), \
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 58e460c015ef..3ca0fa9e92a7 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -4466,8 +4466,68 @@ enum mkbp_cec_event {
 
 /*****************************************************************************/
 
+/* Commands for audio codec. */
+#define EC_CMD_EC_CODEC 0x00BC
+
+enum ec_codec_subcmd {
+	EC_CODEC_GET_CAPABILITIES = 0x0,
+	EC_CODEC_GET_SHM_ADDR = 0x1,
+	EC_CODEC_SET_SHM_ADDR = 0x2,
+	EC_CODEC_SUBCMD_COUNT,
+};
+
+enum ec_codec_cap {
+	EC_CODEC_CAP_LAST = 32,
+};
+
+enum ec_codec_shm_id {
+	EC_CODEC_SHM_ID_LAST,
+};
+
+enum ec_codec_shm_type {
+	EC_CODEC_SHM_TYPE_EC_RAM = 0x0,
+	EC_CODEC_SHM_TYPE_SYSTEM_RAM = 0x1,
+};
+
+struct __ec_align1 ec_param_ec_codec_get_shm_addr {
+	uint8_t shm_id;
+	uint8_t reserved[3];
+};
+
+struct __ec_align4 ec_param_ec_codec_set_shm_addr {
+	uint64_t phys_addr;
+	uint32_t len;
+	uint8_t shm_id;
+	uint8_t reserved[3];
+};
+
+struct __ec_align4 ec_param_ec_codec {
+	uint8_t cmd; /* enum ec_codec_subcmd */
+	uint8_t reserved[3];
+
+	union {
+		struct ec_param_ec_codec_get_shm_addr
+				get_shm_addr_param;
+		struct ec_param_ec_codec_set_shm_addr
+				set_shm_addr_param;
+	};
+};
+
+struct __ec_align4 ec_response_ec_codec_get_capabilities {
+	uint32_t capabilities;
+};
+
+struct __ec_align4 ec_response_ec_codec_get_shm_addr {
+	uint64_t phys_addr;
+	uint32_t len;
+	uint8_t type;
+	uint8_t reserved[3];
+};
+
+/*****************************************************************************/
+
 /* Commands for DMIC on audio codec. */
-#define EC_CMD_EC_CODEC_DMIC 0x00BC
+#define EC_CMD_EC_CODEC_DMIC 0x00BD
 
 enum ec_codec_dmic_subcmd {
 	EC_CODEC_DMIC_SET_GAIN = 0x0,
@@ -4500,7 +4560,7 @@ struct __ec_align1 ec_response_ec_codec_dmic_get_gain {
 
 /* Commands for I2S RX on audio codec. */
 
-#define EC_CMD_EC_CODEC_I2S_RX 0x00BD
+#define EC_CMD_EC_CODEC_I2S_RX 0x00BE
 
 enum ec_codec_i2s_rx_subcmd {
 	EC_CODEC_I2S_RX_ENABLE = 0x0,
-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] [PATCH v3 05/10] ASoC: cros_ec_codec: read max DMIC gain from EC codec
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
                   ` (3 preceding siblings ...)
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 04/10] platform/chrome: cros_ec: add common commands for EC codec Tzung-Bi Shih
@ 2019-10-14 10:20 ` Tzung-Bi Shih
  2019-10-17  3:07   ` Benson Leung
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 06/10] ASoC: dt-bindings: cros_ec_codec: add SHM bindings Tzung-Bi Shih
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid, Rob Herring

Read max DMIC gain from EC codec instead of DTS.  Also removes the
dt-binding of max-dmic-gain.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 .../bindings/sound/google,cros-ec-codec.txt   |  4 +-
 .../linux/platform_data/cros_ec_commands.h    | 43 +++++++++++----
 sound/soc/codecs/cros_ec_codec.c              | 53 ++++++++++++++-----
 3 files changed, 73 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
index 1084f7f22eea..0ce9fafc78e2 100644
--- a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
+++ b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
@@ -1,4 +1,4 @@
-* Audio codec controlled by ChromeOS EC
+Audio codec controlled by ChromeOS EC
 
 Google's ChromeOS EC codec is a digital mic codec provided by the
 Embedded Controller (EC) and is controlled via a host-command interface.
@@ -9,7 +9,6 @@ Documentation/devicetree/bindings/mfd/cros-ec.txt).
 Required properties:
 - compatible: Must contain "google,cros-ec-codec"
 - #sound-dai-cells: Should be 1. The cell specifies number of DAIs.
-- max-dmic-gain: A number for maximum gain in dB on digital microphone.
 
 Example:
 
@@ -21,6 +20,5 @@ cros-ec@0 {
 	cros_ec_codec: ec-codec {
 		compatible = "google,cros-ec-codec";
 		#sound-dai-cells = <1>;
-		max-dmic-gain = <43>;
 	};
 };
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 3ca0fa9e92a7..21db0d4d4025 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -4530,30 +4530,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;
 };
 
 /*****************************************************************************/
diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
index c19c7fe42e2e..3d4f9e82d6e9 100644
--- a/sound/soc/codecs/cros_ec_codec.c
+++ b/sound/soc/codecs/cros_ec_codec.c
@@ -65,18 +65,26 @@ static int dmic_get_gain(struct snd_kcontrol *kcontrol,
 	struct cros_ec_codec_priv *priv =
 		snd_soc_component_get_drvdata(component);
 	struct ec_param_ec_codec_dmic p;
-	struct ec_response_ec_codec_dmic_get_gain r;
+	struct ec_response_ec_codec_dmic_get_gain_idx r;
 	int ret;
 
-	p.cmd = EC_CODEC_DMIC_GET_GAIN;
+	p.cmd = EC_CODEC_DMIC_GET_GAIN_IDX;
+	p.get_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_0;
 	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 				   (uint8_t *)&p, sizeof(p),
 				   (uint8_t *)&r, sizeof(r));
 	if (ret < 0)
 		return ret;
+	ucontrol->value.integer.value[0] = r.gain;
 
-	ucontrol->value.integer.value[0] = r.left;
-	ucontrol->value.integer.value[1] = r.right;
+	p.cmd = EC_CODEC_DMIC_GET_GAIN_IDX;
+	p.get_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_1;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
+				   (uint8_t *)&p, sizeof(p),
+				   (uint8_t *)&r, sizeof(r));
+	if (ret < 0)
+		return ret;
+	ucontrol->value.integer.value[1] = r.gain;
 
 	return 0;
 }
@@ -94,15 +102,24 @@ static int dmic_put_gain(struct snd_kcontrol *kcontrol,
 	int left = ucontrol->value.integer.value[0];
 	int right = ucontrol->value.integer.value[1];
 	struct ec_param_ec_codec_dmic p;
+	int ret;
 
 	if (left > max_dmic_gain || right > max_dmic_gain)
 		return -EINVAL;
 
 	dev_dbg(component->dev, "set mic gain to %u, %u\n", left, right);
 
-	p.cmd = EC_CODEC_DMIC_SET_GAIN;
-	p.set_gain_param.left = left;
-	p.set_gain_param.right = right;
+	p.cmd = EC_CODEC_DMIC_SET_GAIN_IDX;
+	p.set_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_0;
+	p.set_gain_idx_param.gain = left;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
+				   (uint8_t *)&p, sizeof(p), NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	p.cmd = EC_CODEC_DMIC_SET_GAIN_IDX;
+	p.set_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_1;
+	p.set_gain_idx_param.gain = right;
 	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
@@ -125,19 +142,27 @@ static int dmic_probe(struct snd_soc_component *component)
 	struct cros_ec_codec_priv *priv =
 		snd_soc_component_get_drvdata(component);
 	struct device *dev = priv->dev;
-	int ret, val;
 	struct soc_mixer_control *control;
+	struct ec_param_ec_codec_dmic p;
+	struct ec_response_ec_codec_dmic_get_max_gain r;
+	int ret;
 
-	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
-	if (ret) {
-		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
-		return ret;
+	p.cmd = EC_CODEC_DMIC_GET_MAX_GAIN;
+
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
+				   (uint8_t *)&p, sizeof(p),
+				   (uint8_t *)&r, sizeof(r));
+	if (ret < 0) {
+		dev_warn(dev, "get_max_gain() unsupported\n");
+		return 0;
 	}
 
+	dev_dbg(dev, "max gain = %d\n", r.max_gain);
+
 	control = (struct soc_mixer_control *)
 		dmic_controls[DMIC_CTL_GAIN].private_value;
-	control->max = val;
-	control->platform_max = val;
+	control->max = r.max_gain;
+	control->platform_max = r.max_gain;
 
 	return snd_soc_add_component_controls(component,
 			&dmic_controls[DMIC_CTL_GAIN], 1);
-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] [PATCH v3 06/10] ASoC: dt-bindings: cros_ec_codec: add SHM bindings
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
                   ` (4 preceding siblings ...)
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 05/10] ASoC: cros_ec_codec: read max DMIC gain from " Tzung-Bi Shih
@ 2019-10-14 10:20 ` Tzung-Bi Shih
  2019-10-14 17:23   ` Rob Herring
  2019-10-17  3:12   ` Benson Leung
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 07/10] ASoC: cros_ec_codec: support WoV Tzung-Bi Shih
                   ` (4 subsequent siblings)
  10 siblings, 2 replies; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid

- Add "reg" for binding to shared memory exposed by EC.
- Add "memory-region" for binding to memory region shared by AP.

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 .../bindings/sound/google,cros-ec-codec.txt   | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
index 0ce9fafc78e2..8ca52dcc5572 100644
--- a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
+++ b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
@@ -10,8 +10,26 @@ Required properties:
 - compatible: Must contain "google,cros-ec-codec"
 - #sound-dai-cells: Should be 1. The cell specifies number of DAIs.
 
+Optional properties:
+- reg: Pysical base address and length of shared memory region from EC.
+       It contains 3 unsigned 32-bit integer.  The first 2 integers
+       combine to become an unsigned 64-bit physical address.  The last
+       one integer is length of the shared memory.
+- memory-region: Shared memory region to EC.  A "shared-dma-pool".  See
+                 ../reserved-memory/reserved-memory.txt for details.
+
 Example:
 
+{
+	...
+
+	reserved_mem: reserved_mem {
+		compatible = "shared-dma-pool";
+		reg = <0 0x52800000 0 0x100000>;
+		no-map;
+	};
+}
+
 cros-ec@0 {
 	compatible = "google,cros-ec-spi";
 
@@ -20,5 +38,7 @@ cros-ec@0 {
 	cros_ec_codec: ec-codec {
 		compatible = "google,cros-ec-codec";
 		#sound-dai-cells = <1>;
+		reg = <0x0 0x10500000 0x80000>;
+		memory-region = <&reserved_mem>;
 	};
 };
-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] [PATCH v3 07/10] ASoC: cros_ec_codec: support WoV
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
                   ` (5 preceding siblings ...)
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 06/10] ASoC: dt-bindings: cros_ec_codec: add SHM bindings Tzung-Bi Shih
@ 2019-10-14 10:20 ` Tzung-Bi Shih
  2019-10-15  1:34   ` kbuild test robot
  2019-10-15  3:20   ` kbuild test robot
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 08/10] ASoC: mediatek: mt6358: " Tzung-Bi Shih
                   ` (3 subsequent siblings)
  10 siblings, 2 replies; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid

1. Get EC codec's capabilities.
2. Get and set SHM address if any.
3. Transmit language model to EC codec if needed.
4. Start to read audio data from EC codec if receives host event.

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 drivers/platform/chrome/cros_ec_trace.c       |   1 +
 .../linux/platform_data/cros_ec_commands.h    |  69 ++
 sound/soc/codecs/cros_ec_codec.c              | 700 +++++++++++++++++-
 3 files changed, 768 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c
index 2ea0d4e0d54d..5af1d66d9eca 100644
--- a/drivers/platform/chrome/cros_ec_trace.c
+++ b/drivers/platform/chrome/cros_ec_trace.c
@@ -101,6 +101,7 @@
 	TRACE_SYMBOL(EC_CMD_EC_CODEC), \
 	TRACE_SYMBOL(EC_CMD_EC_CODEC_DMIC), \
 	TRACE_SYMBOL(EC_CMD_EC_CODEC_I2S_RX), \
+	TRACE_SYMBOL(EC_CMD_EC_CODEC_WOV), \
 	TRACE_SYMBOL(EC_CMD_REBOOT_EC), \
 	TRACE_SYMBOL(EC_CMD_GET_PANIC_INFO), \
 	TRACE_SYMBOL(EC_CMD_ACPI_READ), \
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 21db0d4d4025..69210881ebac 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -556,6 +556,9 @@ enum host_event_code {
 	/* Keyboard recovery combo with hardware reinitialization */
 	EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT = 30,
 
+	/* WoV */
+	EC_HOST_EVENT_WOV = 31,
+
 	/*
 	 * The high bit of the event mask is not used as a host event code.  If
 	 * it reads back as set, then the entire event mask should be
@@ -4477,10 +4480,14 @@ enum ec_codec_subcmd {
 };
 
 enum ec_codec_cap {
+	EC_CODEC_CAP_WOV_AUDIO_SHM = 0,
+	EC_CODEC_CAP_WOV_LANG_SHM = 1,
 	EC_CODEC_CAP_LAST = 32,
 };
 
 enum ec_codec_shm_id {
+	EC_CODEC_SHM_ID_WOV_AUDIO = 0x0,
+	EC_CODEC_SHM_ID_WOV_LANG = 0x1,
 	EC_CODEC_SHM_ID_LAST,
 };
 
@@ -4641,6 +4648,68 @@ struct __ec_align4 ec_param_ec_codec_i2s_rx {
 	};
 };
 
+/*****************************************************************************/
+/* Commands for WoV on audio codec. */
+
+#define EC_CMD_EC_CODEC_WOV 0x00BF
+
+enum ec_codec_wov_subcmd {
+	EC_CODEC_WOV_SET_LANG = 0x0,
+	EC_CODEC_WOV_SET_LANG_SHM = 0x1,
+	EC_CODEC_WOV_GET_LANG = 0x2,
+	EC_CODEC_WOV_ENABLE = 0x3,
+	EC_CODEC_WOV_DISABLE = 0x4,
+	EC_CODEC_WOV_READ_AUDIO = 0x5,
+	EC_CODEC_WOV_READ_AUDIO_SHM = 0x6,
+	EC_CODEC_WOV_SUBCMD_COUNT,
+};
+
+/*
+ * @hash is SHA256 of the whole language model.
+ * @total_len indicates the length of whole language model.
+ * @offset is the cursor from the beginning of the model.
+ * @buf is the packet buffer.
+ * @len denotes how many bytes in the buf.
+ */
+struct __ec_align4 ec_param_ec_codec_wov_set_lang {
+	uint8_t hash[32];
+	uint32_t total_len;
+	uint32_t offset;
+	uint8_t buf[128];
+	uint32_t len;
+};
+
+struct __ec_align4 ec_param_ec_codec_wov_set_lang_shm {
+	uint8_t hash[32];
+	uint32_t total_len;
+};
+
+struct __ec_align4 ec_param_ec_codec_wov {
+	uint8_t cmd; /* enum ec_codec_wov_subcmd */
+	uint8_t reserved[3];
+
+	union {
+		struct ec_param_ec_codec_wov_set_lang
+				set_lang_param;
+		struct ec_param_ec_codec_wov_set_lang_shm
+				set_lang_shm_param;
+	};
+};
+
+struct __ec_align4 ec_response_ec_codec_wov_get_lang {
+	uint8_t hash[32];
+};
+
+struct __ec_align4 ec_response_ec_codec_wov_read_audio {
+	uint8_t buf[128];
+	uint32_t len;
+};
+
+struct __ec_align4 ec_response_ec_codec_wov_read_audio_shm {
+	uint32_t offset;
+	uint32_t len;
+};
+
 /*****************************************************************************/
 /* System commands */
 
diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
index 3d4f9e82d6e9..bd9295548f03 100644
--- a/sound/soc/codecs/cros_ec_codec.c
+++ b/sound/soc/codecs/cros_ec_codec.c
@@ -8,10 +8,15 @@
  * EC for audio function.
  */
 
+#include <crypto/hash.h>
+#include <crypto/sha.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
 #include <linux/platform_data/cros_ec_commands.h>
 #include <linux/platform_data/cros_ec_proto.h>
 #include <linux/platform_device.h>
@@ -23,8 +28,45 @@
 struct cros_ec_codec_priv {
 	struct device *dev;
 	struct cros_ec_device *ec_device;
+
+	/* common */
+	uint32_t ec_capabilities;
+
+	uint64_t ec_shm_addr;
+	uint32_t ec_shm_len;
+
+	uint64_t ap_shm_phys_addr;
+	uint32_t ap_shm_len;
+	uint64_t ap_shm_addr;
+	uint64_t ap_shm_last_alloc;
+
+	/* DMIC */
+	atomic_t dmic_probed;
+
+	/* WoV */
+	bool wov_enabled;
+	uint8_t *wov_audio_shm_p;
+	uint32_t wov_audio_shm_len;
+	uint8_t wov_audio_shm_type;
+	uint8_t *wov_lang_shm_p;
+	uint32_t wov_lang_shm_len;
+	uint8_t wov_lang_shm_type;
+
+	struct mutex wov_dma_lock;
+	uint8_t wov_buf[64000];
+	uint32_t wov_rp, wov_wp;
+	size_t wov_dma_offset;
+	bool wov_burst_read;
+	struct snd_pcm_substream *wov_substream;
+	struct delayed_work wov_copy_work;
+	struct notifier_block wov_notifier;
 };
 
+static int ec_codec_capable(struct cros_ec_codec_priv *priv, uint8_t cap)
+{
+	return priv->ec_capabilities & BIT(cap);
+}
+
 static int send_ec_host_command(struct cros_ec_device *ec_dev, uint32_t cmd,
 				uint8_t *out, size_t outsize,
 				uint8_t *in, size_t insize)
@@ -57,6 +99,41 @@ static int send_ec_host_command(struct cros_ec_device *ec_dev, uint32_t cmd,
 	return ret;
 }
 
+static int calculate_sha256(struct cros_ec_codec_priv *priv,
+			    uint8_t *buf, uint32_t size, uint8_t *digest)
+{
+	struct crypto_shash *tfm;
+
+	tfm = crypto_alloc_shash("sha256", CRYPTO_ALG_TYPE_SHASH, 0);
+	if (IS_ERR(tfm)) {
+		dev_err(priv->dev, "can't alloc shash\n");
+		return PTR_ERR(tfm);
+	}
+
+	{
+		SHASH_DESC_ON_STACK(desc, tfm);
+
+		desc->tfm = tfm;
+
+		crypto_shash_digest(desc, buf, size, digest);
+		shash_desc_zero(desc);
+	}
+
+	crypto_free_shash(tfm);
+
+#ifdef DEBUG
+	{
+		char digest_str[65];
+
+		bin2hex(digest_str, digest, 32);
+		digest_str[64] = 0;
+		dev_dbg(priv->dev, "hash=%s\n", digest_str);
+	}
+#endif
+
+	return 0;
+}
+
 static int dmic_get_gain(struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_value *ucontrol)
 {
@@ -147,6 +224,9 @@ static int dmic_probe(struct snd_soc_component *component)
 	struct ec_response_ec_codec_dmic_get_max_gain r;
 	int ret;
 
+	if (!atomic_add_unless(&priv->dmic_probed, 1, 1))
+		return 0;
+
 	p.cmd = EC_CODEC_DMIC_GET_MAX_GAIN;
 
 	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
@@ -324,23 +404,639 @@ static const struct snd_soc_component_driver i2s_rx_component_driver = {
 	.num_dapm_routes	= ARRAY_SIZE(i2s_rx_dapm_routes),
 };
 
+static void *wov_map_shm(struct cros_ec_codec_priv *priv,
+			 uint8_t shm_id, uint32_t *len, uint8_t *type)
+{
+	struct ec_param_ec_codec p;
+	struct ec_response_ec_codec_get_shm_addr r;
+	uint32_t req, offset;
+
+	p.cmd = EC_CODEC_GET_SHM_ADDR;
+	p.get_shm_addr_param.shm_id = shm_id;
+	if (send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC,
+				 (uint8_t *)&p, sizeof(p),
+				 (uint8_t *)&r, sizeof(r)) < 0) {
+		dev_err(priv->dev, "failed to EC_CODEC_GET_SHM_ADDR\n");
+		return NULL;
+	}
+
+	dev_dbg(priv->dev, "phys_addr=%#llx, len=%#x\n", r.phys_addr, r.len);
+
+	*len = r.len;
+	*type = r.type;
+
+	switch (r.type) {
+	case EC_CODEC_SHM_TYPE_EC_RAM:
+		return (void __force *)devm_ioremap_wc(priv->dev,
+				r.phys_addr + priv->ec_shm_addr, r.len);
+	case EC_CODEC_SHM_TYPE_SYSTEM_RAM:
+		if (r.phys_addr) {
+			dev_err(priv->dev, "unknown status\n");
+			return NULL;
+		}
+
+		req = round_up(r.len, PAGE_SIZE);
+		dev_dbg(priv->dev, "round up from %u to %u\n", r.len, req);
+
+		if (priv->ap_shm_last_alloc + req >
+		    priv->ap_shm_phys_addr + priv->ap_shm_len) {
+			dev_err(priv->dev, "insufficient space for AP SHM\n");
+			return NULL;
+		}
+
+		dev_dbg(priv->dev, "alloc AP SHM addr=%#llx, len=%#x\n",
+			priv->ap_shm_last_alloc, req);
+
+		p.cmd = EC_CODEC_SET_SHM_ADDR;
+		p.set_shm_addr_param.phys_addr = priv->ap_shm_last_alloc;
+		p.set_shm_addr_param.len = req;
+		p.set_shm_addr_param.shm_id = shm_id;
+		if (send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC,
+					 (uint8_t *)&p, sizeof(p),
+					 NULL, 0) < 0) {
+			dev_err(priv->dev, "failed to EC_CODEC_SET_SHM_ADDR\n");
+			return NULL;
+		}
+
+		/*
+		 * Note: EC codec only requests for `r.len' but we allocate
+		 * round up PAGE_SIZE `req'.
+		 */
+		offset = priv->ap_shm_last_alloc - priv->ap_shm_phys_addr;
+		priv->ap_shm_last_alloc += req;
+
+		return (void *)(uintptr_t)(priv->ap_shm_addr + offset);
+	default:
+		return NULL;
+	}
+}
+
+static bool wov_queue_full(struct cros_ec_codec_priv *priv)
+{
+	return ((priv->wov_wp + 1) % sizeof(priv->wov_buf)) == priv->wov_rp;
+}
+
+static size_t wov_queue_size(struct cros_ec_codec_priv *priv)
+{
+	if (priv->wov_wp >= priv->wov_rp)
+		return priv->wov_wp - priv->wov_rp;
+	else
+		return sizeof(priv->wov_buf) - priv->wov_rp + priv->wov_wp;
+}
+
+static void wov_queue_dequeue(struct cros_ec_codec_priv *priv, size_t len)
+{
+	struct snd_pcm_runtime *runtime = priv->wov_substream->runtime;
+	size_t req;
+
+	while (len) {
+		req = min(len, runtime->dma_bytes - priv->wov_dma_offset);
+		if (priv->wov_wp >= priv->wov_rp)
+			req = min(req, (size_t)priv->wov_wp - priv->wov_rp);
+		else
+			req = min(req, sizeof(priv->wov_buf) - priv->wov_rp);
+
+		memcpy(runtime->dma_area + priv->wov_dma_offset,
+		       priv->wov_buf + priv->wov_rp, req);
+
+		priv->wov_dma_offset += req;
+		if (priv->wov_dma_offset == runtime->dma_bytes)
+			priv->wov_dma_offset = 0;
+
+		priv->wov_rp += req;
+		if (priv->wov_rp == sizeof(priv->wov_buf))
+			priv->wov_rp = 0;
+
+		len -= req;
+	}
+
+	snd_pcm_period_elapsed(priv->wov_substream);
+}
+
+static void wov_queue_try_dequeue(struct cros_ec_codec_priv *priv)
+{
+	size_t period_bytes = snd_pcm_lib_period_bytes(priv->wov_substream);
+
+	while (period_bytes && wov_queue_size(priv) >= period_bytes) {
+		wov_queue_dequeue(priv, period_bytes);
+		period_bytes = snd_pcm_lib_period_bytes(priv->wov_substream);
+	}
+}
+
+static void wov_queue_enqueue(struct cros_ec_codec_priv *priv,
+			      uint8_t *addr, size_t len, bool iomem)
+{
+	size_t req;
+
+	while (len) {
+		if (wov_queue_full(priv)) {
+			wov_queue_try_dequeue(priv);
+
+			if (wov_queue_full(priv)) {
+				dev_err(priv->dev, "overrun detected\n");
+				return;
+			}
+		}
+
+		if (priv->wov_wp >= priv->wov_rp)
+			req = sizeof(priv->wov_buf) - priv->wov_wp;
+		else
+			/* Note: waste 1-byte to differentiate full and empty */
+			req = priv->wov_rp - priv->wov_wp - 1;
+		req = min(req, len);
+
+		if (iomem)
+			memcpy_fromio(priv->wov_buf + priv->wov_wp,
+				      (void __force __iomem *)addr, req);
+		else
+			memcpy(priv->wov_buf + priv->wov_wp, addr, req);
+
+		priv->wov_wp += req;
+		if (priv->wov_wp == sizeof(priv->wov_buf))
+			priv->wov_wp = 0;
+
+		addr += req;
+		len -= req;
+	}
+
+	wov_queue_try_dequeue(priv);
+}
+
+static int wov_read_audio_shm(struct cros_ec_codec_priv *priv)
+{
+	struct ec_param_ec_codec_wov p;
+	struct ec_response_ec_codec_wov_read_audio_shm r;
+	int ret;
+
+	p.cmd = EC_CODEC_WOV_READ_AUDIO_SHM;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
+				   (uint8_t *)&p, sizeof(p),
+				   (uint8_t *)&r, sizeof(r));
+	if (ret) {
+		dev_err(priv->dev, "failed to EC_CODEC_WOV_READ_AUDIO_SHM\n");
+		return ret;
+	}
+
+	if (!r.len)
+		dev_dbg(priv->dev, "no data, sleep\n");
+	else
+		wov_queue_enqueue(priv, priv->wov_audio_shm_p + r.offset, r.len,
+			priv->wov_audio_shm_type == EC_CODEC_SHM_TYPE_EC_RAM);
+	return -EAGAIN;
+}
+
+static int wov_read_audio(struct cros_ec_codec_priv *priv)
+{
+	struct ec_param_ec_codec_wov p;
+	struct ec_response_ec_codec_wov_read_audio r;
+	int remain = priv->wov_burst_read ? 16000 : 320;
+	int ret;
+
+	while (remain >= 0) {
+		p.cmd = EC_CODEC_WOV_READ_AUDIO;
+		ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
+					   (uint8_t *)&p, sizeof(p),
+					   (uint8_t *)&r, sizeof(r));
+		if (ret) {
+			dev_err(priv->dev,
+				"failed to EC_CODEC_WOV_READ_AUDIO\n");
+			return ret;
+		}
+
+		if (!r.len) {
+			dev_dbg(priv->dev, "no data, sleep\n");
+			priv->wov_burst_read = false;
+			break;
+		}
+
+		wov_queue_enqueue(priv, r.buf, r.len, false);
+		remain -= r.len;
+	}
+
+	return -EAGAIN;
+}
+
+static void wov_copy_work(struct work_struct *w)
+{
+	struct cros_ec_codec_priv *priv =
+		container_of(w, struct cros_ec_codec_priv, wov_copy_work.work);
+	int ret;
+
+	mutex_lock(&priv->wov_dma_lock);
+	if (!priv->wov_substream) {
+		dev_warn(priv->dev, "no pcm substream\n");
+		goto leave;
+	}
+
+	if (ec_codec_capable(priv, EC_CODEC_CAP_WOV_AUDIO_SHM))
+		ret = wov_read_audio_shm(priv);
+	else
+		ret = wov_read_audio(priv);
+
+	if (ret == -EAGAIN)
+		schedule_delayed_work(&priv->wov_copy_work,
+				      msecs_to_jiffies(10));
+	else if (ret)
+		dev_err(priv->dev, "failed to read audio data\n");
+leave:
+	mutex_unlock(&priv->wov_dma_lock);
+}
+
+static int wov_enable_get(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
+	struct cros_ec_codec_priv *priv = snd_soc_component_get_drvdata(c);
+
+	ucontrol->value.integer.value[0] = priv->wov_enabled;
+	return 0;
+}
+
+static int wov_enable_put(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
+	struct cros_ec_codec_priv *priv = snd_soc_component_get_drvdata(c);
+	int enabled = ucontrol->value.integer.value[0];
+	struct ec_param_ec_codec_wov p;
+	int ret;
+
+	if (priv->wov_enabled != enabled) {
+		if (enabled)
+			p.cmd = EC_CODEC_WOV_ENABLE;
+		else
+			p.cmd = EC_CODEC_WOV_DISABLE;
+
+		ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
+					   (uint8_t *)&p, sizeof(p), NULL, 0);
+		if (ret) {
+			dev_err(priv->dev, "failed to %s wov\n",
+				enabled ? "enable" : "disable");
+			return ret;
+		}
+
+		priv->wov_enabled = enabled;
+	}
+
+	return 0;
+}
+
+static int wov_set_lang_shm(struct cros_ec_codec_priv *priv,
+			    uint8_t *buf, size_t size, uint8_t *digest)
+{
+	struct ec_param_ec_codec_wov p;
+	struct ec_param_ec_codec_wov_set_lang_shm *pp = &p.set_lang_shm_param;
+	int ret;
+
+	if (size > priv->wov_lang_shm_len) {
+		dev_err(priv->dev, "no enough SHM size: %d\n",
+			priv->wov_lang_shm_len);
+		return -EIO;
+	}
+
+	switch (priv->wov_lang_shm_type) {
+	case EC_CODEC_SHM_TYPE_EC_RAM:
+		memcpy_toio((void __force __iomem *)priv->wov_lang_shm_p,
+			    buf, size);
+		memset_io((void __force __iomem *)priv->wov_lang_shm_p + size,
+			  0, priv->wov_lang_shm_len - size);
+		break;
+	case EC_CODEC_SHM_TYPE_SYSTEM_RAM:
+		memcpy(priv->wov_lang_shm_p, buf, size);
+		memset(priv->wov_lang_shm_p + size, 0,
+		       priv->wov_lang_shm_len - size);
+
+		/* make sure write to memory before calling host command */
+		wmb();
+		break;
+	}
+
+	p.cmd = EC_CODEC_WOV_SET_LANG_SHM;
+	memcpy(pp->hash, digest, SHA256_DIGEST_SIZE);
+	pp->total_len = size;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
+				   (uint8_t *)&p, sizeof(p), NULL, 0);
+	if (ret) {
+		dev_err(priv->dev, "failed to EC_CODEC_WOV_SET_LANG_SHM\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int wov_set_lang(struct cros_ec_codec_priv *priv,
+			uint8_t *buf, size_t size, uint8_t *digest)
+{
+	struct ec_param_ec_codec_wov p;
+	struct ec_param_ec_codec_wov_set_lang *pp = &p.set_lang_param;
+	size_t i, req;
+	int ret;
+
+	for (i = 0; i < size; i += req) {
+		req = min(size - i, ARRAY_SIZE(pp->buf));
+
+		p.cmd = EC_CODEC_WOV_SET_LANG;
+		memcpy(pp->hash, digest, SHA256_DIGEST_SIZE);
+		pp->total_len = size;
+		pp->offset = i;
+		memcpy(pp->buf, buf + i, req);
+		pp->len = req;
+		ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
+					   (uint8_t *)&p, sizeof(p), NULL, 0);
+		if (ret) {
+			dev_err(priv->dev, "failed to EC_CODEC_WOV_SET_LANG\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int wov_hotword_model_put(struct snd_kcontrol *kcontrol,
+				 const unsigned int __user *bytes,
+				 unsigned int size)
+{
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct ec_param_ec_codec_wov p;
+	struct ec_response_ec_codec_wov_get_lang r;
+	uint8_t digest[SHA256_DIGEST_SIZE];
+	uint8_t *buf;
+	int ret;
+
+	/* Skips the TLV header. */
+	bytes += 2;
+	size -= 8;
+
+	dev_dbg(priv->dev, "%s: size=%d\n", __func__, size);
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (copy_from_user(buf, bytes, size)) {
+		ret = -EFAULT;
+		goto leave;
+	}
+
+	ret = calculate_sha256(priv, buf, size, digest);
+	if (ret)
+		goto leave;
+
+	p.cmd = EC_CODEC_WOV_GET_LANG;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
+				   (uint8_t *)&p, sizeof(p),
+				   (uint8_t *)&r, sizeof(r));
+	if (ret)
+		goto leave;
+
+	if (memcmp(digest, r.hash, SHA256_DIGEST_SIZE) == 0) {
+		dev_dbg(priv->dev, "not updated");
+		goto leave;
+	}
+
+	if (ec_codec_capable(priv, EC_CODEC_CAP_WOV_LANG_SHM))
+		ret = wov_set_lang_shm(priv, buf, size, digest);
+	else
+		ret = wov_set_lang(priv, buf, size, digest);
+
+leave:
+	kfree(buf);
+	return ret;
+}
+
+static struct snd_kcontrol_new wov_controls[] = {
+	SOC_SINGLE_BOOL_EXT("Wake-on-Voice Switch", 0,
+			    wov_enable_get, wov_enable_put),
+	SND_SOC_BYTES_TLV("Hotword Model", 0x11000, NULL,
+			  wov_hotword_model_put),
+};
+
+static struct snd_soc_dai_driver wov_dai_driver = {
+	.name = "Wake on Voice",
+	.capture = {
+		.stream_name = "WoV Capture",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
+};
+
+static int wov_host_event(struct notifier_block *nb,
+			  unsigned long queued_during_suspend, void *notify)
+{
+	struct cros_ec_codec_priv *priv =
+		container_of(nb, struct cros_ec_codec_priv, wov_notifier);
+	u32 host_event;
+
+	dev_dbg(priv->dev, "%s\n", __func__);
+
+	host_event = cros_ec_get_host_event(priv->ec_device);
+	if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_WOV)) {
+		schedule_delayed_work(&priv->wov_copy_work, 0);
+		return NOTIFY_OK;
+	} else {
+		return NOTIFY_DONE;
+	}
+}
+
+static int wov_probe(struct snd_soc_component *component)
+{
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	int ret;
+
+	mutex_init(&priv->wov_dma_lock);
+	INIT_DELAYED_WORK(&priv->wov_copy_work, wov_copy_work);
+
+	priv->wov_notifier.notifier_call = wov_host_event;
+	ret = blocking_notifier_chain_register(
+			&priv->ec_device->event_notifier, &priv->wov_notifier);
+	if (ret)
+		return ret;
+
+	if (ec_codec_capable(priv, EC_CODEC_CAP_WOV_LANG_SHM)) {
+		priv->wov_lang_shm_p = wov_map_shm(priv,
+				EC_CODEC_SHM_ID_WOV_LANG,
+				&priv->wov_lang_shm_len,
+				&priv->wov_lang_shm_type);
+		if (!priv->wov_lang_shm_p)
+			return -EFAULT;
+	}
+
+	if (ec_codec_capable(priv, EC_CODEC_CAP_WOV_AUDIO_SHM)) {
+		priv->wov_audio_shm_p = wov_map_shm(priv,
+				EC_CODEC_SHM_ID_WOV_AUDIO,
+				&priv->wov_audio_shm_len,
+				&priv->wov_audio_shm_type);
+		if (!priv->wov_audio_shm_p)
+			return -EFAULT;
+	}
+
+	return dmic_probe(component);
+}
+
+static void wov_remove(struct snd_soc_component *component)
+{
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+
+	blocking_notifier_chain_unregister(
+			&priv->ec_device->event_notifier, &priv->wov_notifier);
+}
+
+static int wov_pcm_open(struct snd_soc_component *component,
+			struct snd_pcm_substream *substream)
+{
+	static const struct snd_pcm_hardware hw_param = {
+		.info = SNDRV_PCM_INFO_MMAP |
+			SNDRV_PCM_INFO_INTERLEAVED |
+			SNDRV_PCM_INFO_MMAP_VALID,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.rates = SNDRV_PCM_RATE_16000,
+		.channels_min = 1,
+		.channels_max = 1,
+		.period_bytes_min = PAGE_SIZE,
+		.period_bytes_max = 0x20000 / 8,
+		.periods_min = 8,
+		.periods_max = 8,
+		.buffer_bytes_max = 0x20000,
+	};
+
+	return snd_soc_set_runtime_hwparams(substream, &hw_param);
+}
+
+static int wov_pcm_hw_params(struct snd_soc_component *component,
+			     struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *hw_params)
+{
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+
+	mutex_lock(&priv->wov_dma_lock);
+	priv->wov_substream = substream;
+	priv->wov_rp = priv->wov_wp = 0;
+	priv->wov_dma_offset = 0;
+	priv->wov_burst_read = true;
+	mutex_unlock(&priv->wov_dma_lock);
+
+	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+			params_buffer_bytes(hw_params));
+}
+
+static int wov_pcm_hw_free(struct snd_soc_component *component,
+			   struct snd_pcm_substream *substream)
+{
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+
+	mutex_lock(&priv->wov_dma_lock);
+	wov_queue_dequeue(priv, wov_queue_size(priv));
+	priv->wov_substream = NULL;
+	mutex_unlock(&priv->wov_dma_lock);
+
+	cancel_delayed_work_sync(&priv->wov_copy_work);
+
+	return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+static snd_pcm_uframes_t wov_pcm_pointer(struct snd_soc_component *component,
+					 struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+
+	return bytes_to_frames(runtime, priv->wov_dma_offset);
+}
+
+static struct page *wov_pcm_page(struct snd_soc_component *component,
+				 struct snd_pcm_substream *substream,
+				 unsigned long offset)
+{
+	return snd_pcm_lib_get_vmalloc_page(substream, offset);
+}
+
+static const struct snd_soc_component_driver wov_component_driver = {
+	.probe		= wov_probe,
+	.remove		= wov_remove,
+	.controls	= wov_controls,
+	.num_controls	= ARRAY_SIZE(wov_controls),
+	.open		= wov_pcm_open,
+	.hw_params	= wov_pcm_hw_params,
+	.hw_free	= wov_pcm_hw_free,
+	.pointer	= wov_pcm_pointer,
+	.page		= wov_pcm_page,
+};
+
 static int cros_ec_codec_platform_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct cros_ec_device *ec_device = dev_get_drvdata(pdev->dev.parent);
 	struct cros_ec_codec_priv *priv;
+	struct device_node *node;
+	struct resource res;
+	struct ec_param_ec_codec p;
+	struct ec_response_ec_codec_get_capabilities r;
+	int ret;
+	u64 ec_shm_size;
+	const __be32 *regaddr_p;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
+	regaddr_p = of_get_address(dev->of_node, 0, &ec_shm_size, NULL);
+	if (regaddr_p) {
+		priv->ec_shm_addr = of_read_number(regaddr_p, 2);
+		priv->ec_shm_len = ec_shm_size;
+
+		dev_dbg(dev, "ec_shm_addr=%#llx len=%#x\n",
+			priv->ec_shm_addr, priv->ec_shm_len);
+	}
+
+	node = of_parse_phandle(dev->of_node, "memory-region", 0);
+	if (node) {
+		ret = of_address_to_resource(node, 0, &res);
+		if (!ret) {
+			priv->ap_shm_phys_addr = res.start;
+			priv->ap_shm_len = resource_size(&res);
+			priv->ap_shm_addr =
+				(uint64_t)(uintptr_t)devm_ioremap_wc(
+					dev, priv->ap_shm_phys_addr,
+					priv->ap_shm_len);
+			priv->ap_shm_last_alloc = priv->ap_shm_phys_addr;
+
+			dev_dbg(dev, "ap_shm_phys_addr=%#llx len=%#x\n",
+				priv->ap_shm_phys_addr, priv->ap_shm_len);
+		}
+	}
+
 	priv->dev = dev;
 	priv->ec_device = ec_device;
+	atomic_set(&priv->dmic_probed, 0);
+
+	p.cmd = EC_CODEC_GET_CAPABILITIES;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC,
+				   (uint8_t *)&p, sizeof(p),
+				   (uint8_t *)&r, sizeof(r));
+	if (ret) {
+		dev_err(dev, "failed to EC_CODEC_GET_CAPABILITIES\n");
+		return ret;
+	}
+	priv->ec_capabilities = r.capabilities;
 
 	platform_set_drvdata(pdev, priv);
 
-	return devm_snd_soc_register_component(dev, &i2s_rx_component_driver,
-					       &i2s_rx_dai_driver, 1);
+	ret = devm_snd_soc_register_component(dev, &i2s_rx_component_driver,
+					      &i2s_rx_dai_driver, 1);
+	if (ret)
+		return ret;
+
+	return devm_snd_soc_register_component(dev, &wov_component_driver,
+					       &wov_dai_driver, 1);
 }
 
 #ifdef CONFIG_OF
-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] [PATCH v3 08/10] ASoC: mediatek: mt6358: support WoV
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
                   ` (6 preceding siblings ...)
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 07/10] ASoC: cros_ec_codec: support WoV Tzung-Bi Shih
@ 2019-10-14 10:20 ` Tzung-Bi Shih
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 09/10] ASoC: dt-bindings: mt8183: add ec-codec Tzung-Bi Shih
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid

Switch mono DMIC on to support wake-on-voice.

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 sound/soc/codecs/mt6358.c | 105 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c
index bb737fd678cc..1b830ea4f6ed 100644
--- a/sound/soc/codecs/mt6358.c
+++ b/sound/soc/codecs/mt6358.c
@@ -93,6 +93,8 @@ struct mt6358_priv {
 	int mtkaif_protocol;
 
 	struct regulator *avdd_reg;
+
+	int wov_enabled;
 };
 
 int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt,
@@ -464,6 +466,106 @@ static int mt6358_put_volsw(struct snd_kcontrol *kcontrol,
 	return ret;
 }
 
+static void mt6358_restore_pga(struct mt6358_priv *priv);
+
+static int mt6358_enable_wov_phase2(struct mt6358_priv *priv)
+{
+	/* analog */
+	regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON13,
+			   0xffff, 0x0000);
+	regmap_update_bits(priv->regmap, MT6358_DCXO_CW14, 0xffff, 0xa2b5);
+	regmap_update_bits(priv->regmap, MT6358_AUDENC_ANA_CON1,
+			   0xffff, 0x0800);
+	mt6358_restore_pga(priv);
+
+	regmap_update_bits(priv->regmap, MT6358_DCXO_CW13, 0xffff, 0x9929);
+	regmap_update_bits(priv->regmap, MT6358_AUDENC_ANA_CON9,
+			   0xffff, 0x0025);
+	regmap_update_bits(priv->regmap, MT6358_AUDENC_ANA_CON8,
+			   0xffff, 0x0005);
+
+	/* digital */
+	regmap_update_bits(priv->regmap, MT6358_AUD_TOP_CKPDN_CON0,
+			   0xffff, 0x0000);
+	regmap_update_bits(priv->regmap, MT6358_GPIO_MODE3, 0xffff, 0x0120);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG0, 0xffff, 0xffff);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG1, 0xffff, 0x0200);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG2, 0xffff, 0x2424);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG3, 0xffff, 0xdbac);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG4, 0xffff, 0x029e);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG5, 0xffff, 0x0000);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_POSDIV_CFG0,
+			   0xffff, 0x0000);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_HPF_CFG0,
+			   0xffff, 0x0451);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_TOP, 0xffff, 0x68d1);
+
+	return 0;
+}
+
+static int mt6358_disable_wov_phase2(struct mt6358_priv *priv)
+{
+	/* digital */
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_TOP, 0xffff, 0xc000);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_HPF_CFG0,
+			   0xffff, 0x0450);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_POSDIV_CFG0,
+			   0xffff, 0x0c00);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG5, 0xffff, 0x0100);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG4, 0xffff, 0x006c);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG3, 0xffff, 0xa879);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG2, 0xffff, 0x2323);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG1, 0xffff, 0x0400);
+	regmap_update_bits(priv->regmap, MT6358_AFE_VOW_CFG0, 0xffff, 0x0000);
+	regmap_update_bits(priv->regmap, MT6358_GPIO_MODE3, 0xffff, 0x02d8);
+	regmap_update_bits(priv->regmap, MT6358_AUD_TOP_CKPDN_CON0,
+			   0xffff, 0x0000);
+
+	/* analog */
+	regmap_update_bits(priv->regmap, MT6358_AUDENC_ANA_CON8,
+			   0xffff, 0x0004);
+	regmap_update_bits(priv->regmap, MT6358_AUDENC_ANA_CON9,
+			   0xffff, 0x0000);
+	regmap_update_bits(priv->regmap, MT6358_DCXO_CW13, 0xffff, 0x9829);
+	regmap_update_bits(priv->regmap, MT6358_AUDENC_ANA_CON1,
+			   0xffff, 0x0000);
+	mt6358_restore_pga(priv);
+	regmap_update_bits(priv->regmap, MT6358_DCXO_CW14, 0xffff, 0xa2b5);
+	regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON13,
+			   0xffff, 0x0010);
+
+	return 0;
+}
+
+static int mt6358_get_wov(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
+	struct mt6358_priv *priv = snd_soc_component_get_drvdata(c);
+
+	ucontrol->value.integer.value[0] = priv->wov_enabled;
+	return 0;
+}
+
+static int mt6358_put_wov(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
+	struct mt6358_priv *priv = snd_soc_component_get_drvdata(c);
+	int enabled = ucontrol->value.integer.value[0];
+
+	if (priv->wov_enabled != enabled) {
+		if (enabled)
+			mt6358_enable_wov_phase2(priv);
+		else
+			mt6358_disable_wov_phase2(priv);
+
+		priv->wov_enabled = enabled;
+	}
+
+	return 0;
+}
+
 static const DECLARE_TLV_DB_SCALE(playback_tlv, -1000, 100, 0);
 static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 600, 0);
 
@@ -483,6 +585,9 @@ static const struct snd_kcontrol_new mt6358_snd_controls[] = {
 			     MT6358_AUDENC_ANA_CON0, MT6358_AUDENC_ANA_CON1,
 			     8, 4, 0,
 			     snd_soc_get_volsw, mt6358_put_volsw, pga_tlv),
+
+	SOC_SINGLE_BOOL_EXT("Wake-on-Voice Phase2 Switch", 0,
+			    mt6358_get_wov, mt6358_put_wov),
 };
 
 /* MUX */
-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] [PATCH v3 09/10] ASoC: dt-bindings: mt8183: add ec-codec
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
                   ` (7 preceding siblings ...)
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 08/10] ASoC: mediatek: mt6358: " Tzung-Bi Shih
@ 2019-10-14 10:20 ` Tzung-Bi Shih
  2019-10-14 17:23   ` Rob Herring
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 10/10] ASoC: mediatek: mt8183: support WoV Tzung-Bi Shih
  2019-10-14 12:34 ` [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: " Tzung-Bi Shih
  10 siblings, 1 reply; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid

Add an optional property "ec-codec".  If specified, mt8183 could use the
"wake on voice" feature offered by EC codec.

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 .../bindings/sound/mt8183-mt6358-ts3a227-max98357.txt          | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt b/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt
index 17ff3892f439..decaa013a07e 100644
--- a/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt
+++ b/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt
@@ -6,12 +6,15 @@ Required properties:
 
 Optional properties:
 - mediatek,headset-codec: the phandles of ts3a227 codecs
+- mediatek,ec-codec: the phandle of EC codecs.
+                     See google,cros-ec-codec.txt for more details.
 
 Example:
 
 	sound {
 		compatible = "mediatek,mt8183_mt6358_ts3a227_max98357";
 		mediatek,headset-codec = <&ts3a227>;
+		mediatek,ec-codec = <&ec_codec>;
 		mediatek,platform = <&afe>;
 	};
 
-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] [PATCH v3 10/10] ASoC: mediatek: mt8183: support WoV
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
                   ` (8 preceding siblings ...)
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 09/10] ASoC: dt-bindings: mt8183: add ec-codec Tzung-Bi Shih
@ 2019-10-14 10:20 ` Tzung-Bi Shih
  2019-10-14 12:34 ` [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: " Tzung-Bi Shih
  10 siblings, 0 replies; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 10:20 UTC (permalink / raw)
  To: broonie
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, tzungbi,
	robh+dt, enric.balletbo, bleung, dgreid

Add DAI link and pin muxing for wake on voice.

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 sound/soc/mediatek/Kconfig                    |  1 +
 .../mt8183/mt8183-mt6358-ts3a227-max98357.c   | 70 ++++++++++++++++++-
 2 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 111e44b64b38..8b29f3979899 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -125,6 +125,7 @@ config SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A
 	select SND_SOC_MAX98357A
 	select SND_SOC_BT_SCO
 	select SND_SOC_TS3A227E
+	select SND_SOC_CROS_EC_CODEC
 	help
 	  This adds ASoC driver for Mediatek MT8183 boards
 	  with the MT6358 TS3A227E MAX98357A audio codec.
diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
index bb9cdc0d6552..0555f7d73d05 100644
--- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
@@ -19,11 +19,12 @@ enum PINCTRL_PIN_STATE {
 	PIN_STATE_DEFAULT = 0,
 	PIN_TDM_OUT_ON,
 	PIN_TDM_OUT_OFF,
+	PIN_WOV,
 	PIN_STATE_MAX
 };
 
 static const char * const mt8183_pin_str[PIN_STATE_MAX] = {
-	"default", "aud_tdm_out_on", "aud_tdm_out_off",
+	"default", "aud_tdm_out_on", "aud_tdm_out_off", "wov",
 };
 
 struct mt8183_mt6358_ts3a227_max98357_priv {
@@ -142,6 +143,11 @@ SND_SOC_DAILINK_DEFS(playback_hdmi,
 	DAILINK_COMP_ARRAY(COMP_DUMMY()),
 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
+SND_SOC_DAILINK_DEFS(wake_on_voice,
+	DAILINK_COMP_ARRAY(COMP_DUMMY()),
+	DAILINK_COMP_ARRAY(COMP_DUMMY()),
+	DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
 /* BE */
 SND_SOC_DAILINK_DEFS(primary_codec,
 	DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
@@ -229,6 +235,41 @@ static struct snd_soc_ops mt8183_mt6358_tdm_ops = {
 	.shutdown = mt8183_mt6358_tdm_shutdown,
 };
 
+static int
+mt8183_mt6358_ts3a227_max98357_wov_startup(
+	struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct mt8183_mt6358_ts3a227_max98357_priv *priv =
+			snd_soc_card_get_drvdata(card);
+
+	return pinctrl_select_state(priv->pinctrl,
+				    priv->pin_states[PIN_WOV]);
+}
+
+static void
+mt8183_mt6358_ts3a227_max98357_wov_shutdown(
+	struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct mt8183_mt6358_ts3a227_max98357_priv *priv =
+			snd_soc_card_get_drvdata(card);
+	int ret;
+
+	ret = pinctrl_select_state(priv->pinctrl,
+				   priv->pin_states[PIN_STATE_DEFAULT]);
+	if (ret)
+		dev_err(card->dev, "%s failed to select state %d\n",
+			__func__, ret);
+}
+
+static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_wov_ops = {
+	.startup = mt8183_mt6358_ts3a227_max98357_wov_startup,
+	.shutdown = mt8183_mt6358_ts3a227_max98357_wov_shutdown,
+};
+
 static struct snd_soc_dai_link
 mt8183_mt6358_ts3a227_max98357_dai_links[] = {
 	/* FE */
@@ -306,6 +347,15 @@ mt8183_mt6358_ts3a227_max98357_dai_links[] = {
 		.dpcm_playback = 1,
 		SND_SOC_DAILINK_REG(playback_hdmi),
 	},
+	{
+		.name = "Wake on Voice",
+		.stream_name = "Wake on Voice",
+		.ignore_suspend = 1,
+		.ignore = 1,
+		SND_SOC_DAILINK_REG(wake_on_voice),
+		.ops = &mt8183_mt6358_ts3a227_max98357_wov_ops,
+	},
+
 	/* BE */
 	{
 		.name = "Primary Codec",
@@ -429,7 +479,7 @@ static int
 mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev)
 {
 	struct snd_soc_card *card = &mt8183_mt6358_ts3a227_max98357_card;
-	struct device_node *platform_node;
+	struct device_node *platform_node, *ec_codec;
 	struct snd_soc_dai_link *dai_link;
 	struct mt8183_mt6358_ts3a227_max98357_priv *priv;
 	int ret;
@@ -444,10 +494,24 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
+	ec_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,ec-codec", 0);
+
 	for_each_card_prelinks(card, i, dai_link) {
 		if (dai_link->platforms->name)
 			continue;
-		dai_link->platforms->of_node = platform_node;
+
+		if (ec_codec && strcmp(dai_link->name, "Wake on Voice") == 0) {
+			dai_link->cpus[0].name = NULL;
+			dai_link->cpus[0].of_node = ec_codec;
+			dai_link->cpus[0].dai_name = NULL;
+			dai_link->codecs[0].name = NULL;
+			dai_link->codecs[0].of_node = ec_codec;
+			dai_link->codecs[0].dai_name = "Wake on Voice";
+			dai_link->platforms[0].of_node = ec_codec;
+			dai_link->ignore = 0;
+		} else {
+			dai_link->platforms->of_node = platform_node;
+		}
 	}
 
 	mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node =
-- 
2.23.0.700.g56cf767bdb-goog

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV
  2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
                   ` (9 preceding siblings ...)
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 10/10] ASoC: mediatek: mt8183: support WoV Tzung-Bi Shih
@ 2019-10-14 12:34 ` Tzung-Bi Shih
  10 siblings, 0 replies; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-14 12:34 UTC (permalink / raw)
  To: Mark Brown
  Cc: Gwendal Grignou, devicetree, ALSA development,
	Jimmy Cheng-Yi Chiang, Nicolas Boichat, robh+dt,
	Enric Balletbo i Serra, Benson Leung, Dylan Reid

On Mon, Oct 14, 2019 at 6:20 PM Tzung-Bi Shih <tzungbi@google.com> wrote:
>
> This series makes mt6358, cros_ec_codec, and mt8183-mt6358-ts3a227-max98357
> support WoV (wake on voice).
>
> The first 3 commits are some cleanups and refactors.  It looks like
> breaking the existing interface.  But please be noticed that, the
> cros_ec_codec has not used by any real device yet.  The refactor is
> very necessary to keep the style consistent and for easier to further
> extend and maintain.
>   platform/chrome: cros_ec: remove unused EC feature
>   ASoC: cros_ec_codec: refactor I2S RX
>   ASoC: cros_ec_codec: extract DMIC EC command from I2S RX
>
> The 4th commit extends the feature offered from EC codec.
>   platform/chrome: cros_ec: add common commands for EC codec
>
> The 5th commit changes the behavior of setting and getting DMIC gains.
>   ASoC: cros_ec_codec: read max DMIC gain from EC codec
>
> The 6th and 7th commit make cros_ec_codec support WoV.
>   ASoC: dt-bindings: cros_ec_codec: add SHM bindings
>   ASoC: cros_ec_codec: support WoV
>
> The 8th commit sets necessary registers on mt6358 to support WoV.
>   ASoC: mediatek: mt6358: support WoV
>
> The last 2 commit make machine driver mt8183-mt6358-ts3a227-max98357
> support WoV if ec-codec is in DTS.
>   ASoC: dt-bindings: mt8183: add ec-codec
>   ASoC: mediatek: mt8183: support WoV
>
> Changes from v1:
> - fix a compile error and make kbuild bot happy
> https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/156315.html
> Changes from v2:
> - rebase upon to "don't use snd_pcm_ops" series
> https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/156170.html
> - fix sparse errors
> https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/156328.html
> - use "reg" for SHM binding
> https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/156657.html
>
> Tzung-Bi Shih (10):
>   WIP: platform/chrome: cros_ec: remove unused EC feature
>   WIP: ASoC: cros_ec_codec: refactor I2S RX
>   WIP: ASoC: cros_ec_codec: extract DMIC EC command from I2S RX
>   WIP: platform/chrome: cros_ec: add common commands for EC codec
>   WIP: ASoC: cros_ec_codec: read max DMIC gain from EC codec
>   WIP: ASoC: dt-bindings: cros_ec_codec: add SHM bindings
>   WIP: ASoC: cros_ec_codec: support WoV
>   WIP: ASoC: mediatek: mt6358: support WoV
>   WIP: ASoC: dt-bindings: mt8183: add ec-codec
>   WIP: ASoC: mediatek: mt8183: support WoV

Ha..I noticed here are some "WIP" prefixes forgot to remove.  To not
generate too much flood, will fix in later versions.

>
>  .../bindings/sound/google,cros-ec-codec.txt   |   24 +-
>  .../sound/mt8183-mt6358-ts3a227-max98357.txt  |    3 +
>  drivers/platform/chrome/cros_ec_trace.c       |    5 +-
>  .../linux/platform_data/cros_ec_commands.h    |  285 ++++-
>  sound/soc/codecs/cros_ec_codec.c              | 1128 +++++++++++++----
>  sound/soc/codecs/mt6358.c                     |  105 ++
>  sound/soc/mediatek/Kconfig                    |    1 +
>  .../mt8183/mt8183-mt6358-ts3a227-max98357.c   |   70 +-
>  8 files changed, 1296 insertions(+), 325 deletions(-)
>
> --
> 2.23.0.700.g56cf767bdb-goog
>
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 06/10] ASoC: dt-bindings: cros_ec_codec: add SHM bindings
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 06/10] ASoC: dt-bindings: cros_ec_codec: add SHM bindings Tzung-Bi Shih
@ 2019-10-14 17:23   ` Rob Herring
  2019-10-17  3:12   ` Benson Leung
  1 sibling, 0 replies; 29+ messages in thread
From: Rob Herring @ 2019-10-14 17:23 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	tzungbi, broonie, enric.balletbo, bleung, dgreid

On Mon, 14 Oct 2019 18:20:18 +0800, Tzung-Bi Shih wrote:
> - Add "reg" for binding to shared memory exposed by EC.
> - Add "memory-region" for binding to memory region shared by AP.
> 
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
> ---
>  .../bindings/sound/google,cros-ec-codec.txt   | 20 +++++++++++++++++++
>  1 file changed, 20 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 09/10] ASoC: dt-bindings: mt8183: add ec-codec
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 09/10] ASoC: dt-bindings: mt8183: add ec-codec Tzung-Bi Shih
@ 2019-10-14 17:23   ` Rob Herring
  0 siblings, 0 replies; 29+ messages in thread
From: Rob Herring @ 2019-10-14 17:23 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	tzungbi, broonie, enric.balletbo, bleung, dgreid

On Mon, 14 Oct 2019 18:20:21 +0800, Tzung-Bi Shih wrote:
> Add an optional property "ec-codec".  If specified, mt8183 could use the
> "wake on voice" feature offered by EC codec.
> 
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
> ---
>  .../bindings/sound/mt8183-mt6358-ts3a227-max98357.txt          | 3 +++
>  1 file changed, 3 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 07/10] ASoC: cros_ec_codec: support WoV
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 07/10] ASoC: cros_ec_codec: support WoV Tzung-Bi Shih
@ 2019-10-15  1:34   ` kbuild test robot
  2019-10-15  6:49     ` Tzung-Bi Shih
  2019-10-15  3:20   ` kbuild test robot
  1 sibling, 1 reply; 29+ messages in thread
From: kbuild test robot @ 2019-10-15  1:34 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, kbuild-all, cychiang, drinkcat,
	robh+dt, tzungbi, broonie, enric.balletbo, bleung, dgreid

[-- Attachment #1: Type: text/plain, Size: 3949 bytes --]

Hi Tzung-Bi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on asoc/for-next]
[cannot apply to v5.4-rc3 next-20191014]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Tzung-Bi-Shih/ASoC-mediatek-mt8183-mt6358-ts3a227-max98357-support-WoV/20191014-183227
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
config: x86_64-randconfig-g002-201941 (attached as .config)
compiler: gcc-7 (Debian 7.4.0-13) 7.4.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   sound/soc/codecs/cros_ec_codec.c: In function 'cros_ec_codec_platform_probe':
>> sound/soc/codecs/cros_ec_codec.c:993:23: error: implicit declaration of function 'of_read_number'; did you mean 'wov_read_audio'? [-Werror=implicit-function-declaration]
      priv->ec_shm_addr = of_read_number(regaddr_p, 2);
                          ^~~~~~~~~~~~~~
                          wov_read_audio
   cc1: some warnings being treated as errors

vim +993 sound/soc/codecs/cros_ec_codec.c

   973	
   974	static int cros_ec_codec_platform_probe(struct platform_device *pdev)
   975	{
   976		struct device *dev = &pdev->dev;
   977		struct cros_ec_device *ec_device = dev_get_drvdata(pdev->dev.parent);
   978		struct cros_ec_codec_priv *priv;
   979		struct device_node *node;
   980		struct resource res;
   981		struct ec_param_ec_codec p;
   982		struct ec_response_ec_codec_get_capabilities r;
   983		int ret;
   984		u64 ec_shm_size;
   985		const __be32 *regaddr_p;
   986	
   987		priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
   988		if (!priv)
   989			return -ENOMEM;
   990	
   991		regaddr_p = of_get_address(dev->of_node, 0, &ec_shm_size, NULL);
   992		if (regaddr_p) {
 > 993			priv->ec_shm_addr = of_read_number(regaddr_p, 2);
   994			priv->ec_shm_len = ec_shm_size;
   995	
   996			dev_dbg(dev, "ec_shm_addr=%#llx len=%#x\n",
   997				priv->ec_shm_addr, priv->ec_shm_len);
   998		}
   999	
  1000		node = of_parse_phandle(dev->of_node, "memory-region", 0);
  1001		if (node) {
  1002			ret = of_address_to_resource(node, 0, &res);
  1003			if (!ret) {
  1004				priv->ap_shm_phys_addr = res.start;
  1005				priv->ap_shm_len = resource_size(&res);
  1006				priv->ap_shm_addr =
  1007					(uint64_t)(uintptr_t)devm_ioremap_wc(
  1008						dev, priv->ap_shm_phys_addr,
  1009						priv->ap_shm_len);
  1010				priv->ap_shm_last_alloc = priv->ap_shm_phys_addr;
  1011	
  1012				dev_dbg(dev, "ap_shm_phys_addr=%#llx len=%#x\n",
  1013					priv->ap_shm_phys_addr, priv->ap_shm_len);
  1014			}
  1015		}
  1016	
  1017		priv->dev = dev;
  1018		priv->ec_device = ec_device;
  1019		atomic_set(&priv->dmic_probed, 0);
  1020	
  1021		p.cmd = EC_CODEC_GET_CAPABILITIES;
  1022		ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC,
  1023					   (uint8_t *)&p, sizeof(p),
  1024					   (uint8_t *)&r, sizeof(r));
  1025		if (ret) {
  1026			dev_err(dev, "failed to EC_CODEC_GET_CAPABILITIES\n");
  1027			return ret;
  1028		}
  1029		priv->ec_capabilities = r.capabilities;
  1030	
  1031		platform_set_drvdata(pdev, priv);
  1032	
  1033		ret = devm_snd_soc_register_component(dev, &i2s_rx_component_driver,
  1034						      &i2s_rx_dai_driver, 1);
  1035		if (ret)
  1036			return ret;
  1037	
  1038		return devm_snd_soc_register_component(dev, &wov_component_driver,
  1039						       &wov_dai_driver, 1);
  1040	}
  1041	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29599 bytes --]

[-- Attachment #3: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 07/10] ASoC: cros_ec_codec: support WoV
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 07/10] ASoC: cros_ec_codec: support WoV Tzung-Bi Shih
  2019-10-15  1:34   ` kbuild test robot
@ 2019-10-15  3:20   ` kbuild test robot
  1 sibling, 0 replies; 29+ messages in thread
From: kbuild test robot @ 2019-10-15  3:20 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, kbuild-all, cychiang, drinkcat,
	robh+dt, tzungbi, broonie, enric.balletbo, bleung, dgreid

Hi Tzung-Bi,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on asoc/for-next]
[cannot apply to v5.4-rc3 next-20191014]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Tzung-Bi-Shih/ASoC-mediatek-mt8183-mt6358-ts3a227-max98357-support-WoV/20191014-183227
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>


coccinelle warnings: (new ones prefixed by >>)

>> sound/soc/codecs/cros_ec_codec.c:774:7-14: WARNING opportunity for memdup_user

vim +774 sound/soc/codecs/cros_ec_codec.c

   754	
   755	static int wov_hotword_model_put(struct snd_kcontrol *kcontrol,
   756					 const unsigned int __user *bytes,
   757					 unsigned int size)
   758	{
   759		struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
   760		struct cros_ec_codec_priv *priv =
   761			snd_soc_component_get_drvdata(component);
   762		struct ec_param_ec_codec_wov p;
   763		struct ec_response_ec_codec_wov_get_lang r;
   764		uint8_t digest[SHA256_DIGEST_SIZE];
   765		uint8_t *buf;
   766		int ret;
   767	
   768		/* Skips the TLV header. */
   769		bytes += 2;
   770		size -= 8;
   771	
   772		dev_dbg(priv->dev, "%s: size=%d\n", __func__, size);
   773	
 > 774		buf = kmalloc(size, GFP_KERNEL);
   775		if (!buf)
   776			return -ENOMEM;
   777	
   778		if (copy_from_user(buf, bytes, size)) {
   779			ret = -EFAULT;
   780			goto leave;
   781		}
   782	
   783		ret = calculate_sha256(priv, buf, size, digest);
   784		if (ret)
   785			goto leave;
   786	
   787		p.cmd = EC_CODEC_WOV_GET_LANG;
   788		ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
   789					   (uint8_t *)&p, sizeof(p),
   790					   (uint8_t *)&r, sizeof(r));
   791		if (ret)
   792			goto leave;
   793	
   794		if (memcmp(digest, r.hash, SHA256_DIGEST_SIZE) == 0) {
   795			dev_dbg(priv->dev, "not updated");
   796			goto leave;
   797		}
   798	
   799		if (ec_codec_capable(priv, EC_CODEC_CAP_WOV_LANG_SHM))
   800			ret = wov_set_lang_shm(priv, buf, size, digest);
   801		else
   802			ret = wov_set_lang(priv, buf, size, digest);
   803	
   804	leave:
   805		kfree(buf);
   806		return ret;
   807	}
   808	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 07/10] ASoC: cros_ec_codec: support WoV
  2019-10-15  1:34   ` kbuild test robot
@ 2019-10-15  6:49     ` Tzung-Bi Shih
  2019-10-17 11:43       ` Mark Brown
  0 siblings, 1 reply; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-15  6:49 UTC (permalink / raw)
  To: kbuild test robot
  Cc: Gwendal Grignou, devicetree, ALSA development, kbuild-all,
	Jimmy Cheng-Yi Chiang, Nicolas Boichat, robh+dt, Mark Brown,
	Enric Balletbo i Serra, Benson Leung, Dylan Reid

On Tue, Oct 15, 2019 at 9:34 AM kbuild test robot <lkp@intel.com> wrote:
>
> Hi Tzung-Bi,
>
> Thank you for the patch! Yet something to improve:
>
> [auto build test ERROR on asoc/for-next]
> [cannot apply to v5.4-rc3 next-20191014]
> [if your patch is applied to the wrong git tree, please drop us a note to help
> improve the system. BTW, we also suggest to use '--base' option to specify the
> base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
>
> url:    https://github.com/0day-ci/linux/commits/Tzung-Bi-Shih/ASoC-mediatek-mt8183-mt6358-ts3a227-max98357-support-WoV/20191014-183227
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
> config: x86_64-randconfig-g002-201941 (attached as .config)
> compiler: gcc-7 (Debian 7.4.0-13) 7.4.0
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=x86_64
>
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
>
> All errors (new ones prefixed by >>):
>
>    sound/soc/codecs/cros_ec_codec.c: In function 'cros_ec_codec_platform_probe':
> >> sound/soc/codecs/cros_ec_codec.c:993:23: error: implicit declaration of function 'of_read_number'; did you mean 'wov_read_audio'? [-Werror=implicit-function-declaration]
>       priv->ec_shm_addr = of_read_number(regaddr_p, 2);
>                           ^~~~~~~~~~~~~~
>                           wov_read_audio
>    cc1: some warnings being treated as errors

The error is caused by EC_CODEC=y but CONFIG_OF is not set:
$ grep -e 'CONFIG_OF.*' -e 'EC_CODEC' config
# CONFIG_OF is not set
CONFIG_SND_SOC_CROS_EC_CODEC=y

>
> vim +993 sound/soc/codecs/cros_ec_codec.c
>
>    973
>    974  static int cros_ec_codec_platform_probe(struct platform_device *pdev)
>    975  {
>    976          struct device *dev = &pdev->dev;
>    977          struct cros_ec_device *ec_device = dev_get_drvdata(pdev->dev.parent);
>    978          struct cros_ec_codec_priv *priv;
>    979          struct device_node *node;
>    980          struct resource res;
>    981          struct ec_param_ec_codec p;
>    982          struct ec_response_ec_codec_get_capabilities r;
>    983          int ret;
>    984          u64 ec_shm_size;
>    985          const __be32 *regaddr_p;
>    986
>    987          priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>    988          if (!priv)
>    989                  return -ENOMEM;
>    990
>    991          regaddr_p = of_get_address(dev->of_node, 0, &ec_shm_size, NULL);
>    992          if (regaddr_p) {
>  > 993                  priv->ec_shm_addr = of_read_number(regaddr_p, 2);

In the case, the of_get_address( ) will get a dummy implementation
(https://elixir.bootlin.com/linux/v5.3.6/source/include/linux/of_address.h#L82)
while of_read_number( ) won't
(https://elixir.bootlin.com/linux/v5.3.6/source/include/linux/of.h#L234).

Rob, what do you think if we add a dummy implementation for
of_read_number( ) if !CONFIG_OF (i.e. after
https://elixir.bootlin.com/linux/v5.3.6/source/include/linux/of.h#L559)?
 Does it make sense?

>    994                  priv->ec_shm_len = ec_shm_size;
>    995
>    996                  dev_dbg(dev, "ec_shm_addr=%#llx len=%#x\n",
>    997                          priv->ec_shm_addr, priv->ec_shm_len);
>    998          }
>    999
>   1000          node = of_parse_phandle(dev->of_node, "memory-region", 0);
>   1001          if (node) {
>   1002                  ret = of_address_to_resource(node, 0, &res);
>   1003                  if (!ret) {
>   1004                          priv->ap_shm_phys_addr = res.start;
>   1005                          priv->ap_shm_len = resource_size(&res);
>   1006                          priv->ap_shm_addr =
>   1007                                  (uint64_t)(uintptr_t)devm_ioremap_wc(
>   1008                                          dev, priv->ap_shm_phys_addr,
>   1009                                          priv->ap_shm_len);
>   1010                          priv->ap_shm_last_alloc = priv->ap_shm_phys_addr;
>   1011
>   1012                          dev_dbg(dev, "ap_shm_phys_addr=%#llx len=%#x\n",
>   1013                                  priv->ap_shm_phys_addr, priv->ap_shm_len);
>   1014                  }
>   1015          }
>   1016
>   1017          priv->dev = dev;
>   1018          priv->ec_device = ec_device;
>   1019          atomic_set(&priv->dmic_probed, 0);
>   1020
>   1021          p.cmd = EC_CODEC_GET_CAPABILITIES;
>   1022          ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC,
>   1023                                     (uint8_t *)&p, sizeof(p),
>   1024                                     (uint8_t *)&r, sizeof(r));
>   1025          if (ret) {
>   1026                  dev_err(dev, "failed to EC_CODEC_GET_CAPABILITIES\n");
>   1027                  return ret;
>   1028          }
>   1029          priv->ec_capabilities = r.capabilities;
>   1030
>   1031          platform_set_drvdata(pdev, priv);
>   1032
>   1033          ret = devm_snd_soc_register_component(dev, &i2s_rx_component_driver,
>   1034                                                &i2s_rx_dai_driver, 1);
>   1035          if (ret)
>   1036                  return ret;
>   1037
>   1038          return devm_snd_soc_register_component(dev, &wov_component_driver,
>   1039                                                 &wov_dai_driver, 1);
>   1040  }
>   1041
>
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature Tzung-Bi Shih
@ 2019-10-15 11:48   ` Mark Brown
  2019-10-15 15:37     ` Tzung-Bi Shih
  2019-10-17  2:25   ` Benson Leung
  2019-10-18 18:06   ` [alsa-devel] Applied "platform/chrome: cros_ec: remove unused EC feature" to the asoc tree Mark Brown
  2 siblings, 1 reply; 29+ messages in thread
From: Mark Brown @ 2019-10-15 11:48 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	enric.balletbo, bleung, dgreid


[-- Attachment #1.1: Type: text/plain, Size: 273 bytes --]

On Mon, Oct 14, 2019 at 06:20:13PM +0800, Tzung-Bi Shih wrote:
> Remove unused EC_FEATURE_AUDIO_CODEC.

What's the route to getting these platform/chrome changes reviewed?
They don't seem to have got any attention thus far and this one is right
at the start of the series.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature
  2019-10-15 11:48   ` Mark Brown
@ 2019-10-15 15:37     ` Tzung-Bi Shih
  0 siblings, 0 replies; 29+ messages in thread
From: Tzung-Bi Shih @ 2019-10-15 15:37 UTC (permalink / raw)
  To: Mark Brown, Enric Balletbo i Serra
  Cc: Gwendal Grignou, devicetree, ALSA development,
	Jimmy Cheng-Yi Chiang, Nicolas Boichat, robh+dt, Benson Leung,
	Dylan Reid

On Tue, Oct 15, 2019 at 7:49 PM Mark Brown <broonie@kernel.org> wrote:
>
> On Mon, Oct 14, 2019 at 06:20:13PM +0800, Tzung-Bi Shih wrote:
> > Remove unused EC_FEATURE_AUDIO_CODEC.
>
> What's the route to getting these platform/chrome changes reviewed?
> They don't seem to have got any attention thus far and this one is right
> at the start of the series.

Enric, could you help to review the "platform/chrome" changes in this
series?  All changes have merged in the EC firmware code
(https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/ec_commands.h).
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature Tzung-Bi Shih
  2019-10-15 11:48   ` Mark Brown
@ 2019-10-17  2:25   ` Benson Leung
  2019-10-18 18:06   ` [alsa-devel] Applied "platform/chrome: cros_ec: remove unused EC feature" to the asoc tree Mark Brown
  2 siblings, 0 replies; 29+ messages in thread
From: Benson Leung @ 2019-10-17  2:25 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	broonie, enric.balletbo, dgreid


[-- Attachment #1.1: Type: text/plain, Size: 1156 bytes --]

Hi Tzung-Bi,

On Mon, Oct 14, 2019 at 06:20:13PM +0800, Tzung-Bi Shih wrote:
> Remove unused EC_FEATURE_AUDIO_CODEC.
> 
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>

Acked-By: Benson Leung <bleung@chromium.org>

Thanks,
Benson

> ---
>  include/linux/platform_data/cros_ec_commands.h | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
> index 98415686cbfa..43b8f7dae4cc 100644
> --- a/include/linux/platform_data/cros_ec_commands.h
> +++ b/include/linux/platform_data/cros_ec_commands.h
> @@ -1277,8 +1277,6 @@ enum ec_feature_code {
>  	 * MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE.
>  	 */
>  	EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37,
> -	/* EC supports audio codec. */
> -	EC_FEATURE_AUDIO_CODEC = 38,
>  	/* The MCU is a System Companion Processor (SCP). */
>  	EC_FEATURE_SCP = 39,
>  	/* The MCU is an Integrated Sensor Hub */
> -- 
> 2.23.0.700.g56cf767bdb-goog
> 

-- 
Benson Leung
Staff Software Engineer
Chrome OS Kernel
Google Inc.
bleung@google.com
Chromium OS Project
bleung@chromium.org

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 02/10] ASoC: cros_ec_codec: refactor I2S RX
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 02/10] ASoC: cros_ec_codec: refactor I2S RX Tzung-Bi Shih
@ 2019-10-17  2:30   ` Benson Leung
  2019-10-18 18:06   ` [alsa-devel] Applied "ASoC: cros_ec_codec: refactor I2S RX" to the asoc tree Mark Brown
  1 sibling, 0 replies; 29+ messages in thread
From: Benson Leung @ 2019-10-17  2:30 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	broonie, enric.balletbo, dgreid


[-- Attachment #1.1: Type: text/plain, Size: 26279 bytes --]

Hi Tzung-Bi,

On Mon, Oct 14, 2019 at 06:20:14PM +0800, Tzung-Bi Shih wrote:
> Refactor by the following items:
> - reformat copyright declaration
> - use more specific name "i2s rx"
> - use verbose symbol names to separate namespaces
> - make some short functions inline
> - remove unused TDM-related code
> 
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>

Acked-By: Benson Leung <bleung@chromium.org>

Thanks,
Benson

> ---
>  drivers/platform/chrome/cros_ec_trace.c       |   2 +-
>  .../linux/platform_data/cros_ec_commands.h    | 120 ++---
>  sound/soc/codecs/cros_ec_codec.c              | 502 +++++++-----------
>  3 files changed, 251 insertions(+), 373 deletions(-)
> 
> diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c
> index 6f80ff4532ae..901850004b2b 100644
> --- a/drivers/platform/chrome/cros_ec_trace.c
> +++ b/drivers/platform/chrome/cros_ec_trace.c
> @@ -98,7 +98,7 @@
>  	TRACE_SYMBOL(EC_CMD_SB_READ_BLOCK), \
>  	TRACE_SYMBOL(EC_CMD_SB_WRITE_BLOCK), \
>  	TRACE_SYMBOL(EC_CMD_BATTERY_VENDOR_PARAM), \
> -	TRACE_SYMBOL(EC_CMD_CODEC_I2S), \
> +	TRACE_SYMBOL(EC_CMD_EC_CODEC_I2S_RX), \
>  	TRACE_SYMBOL(EC_CMD_REBOOT_EC), \
>  	TRACE_SYMBOL(EC_CMD_GET_PANIC_INFO), \
>  	TRACE_SYMBOL(EC_CMD_ACPI_READ), \
> diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
> index 43b8f7dae4cc..261ac83bd007 100644
> --- a/include/linux/platform_data/cros_ec_commands.h
> +++ b/include/linux/platform_data/cros_ec_commands.h
> @@ -4466,92 +4466,74 @@ enum mkbp_cec_event {
>  
>  /*****************************************************************************/
>  
> -/* Commands for I2S recording on audio codec. */
> -
> -#define EC_CMD_CODEC_I2S 0x00BC
> -#define EC_WOV_I2S_SAMPLE_RATE 48000
> -
> -enum ec_codec_i2s_subcmd {
> -	EC_CODEC_SET_SAMPLE_DEPTH = 0x0,
> -	EC_CODEC_SET_GAIN = 0x1,
> -	EC_CODEC_GET_GAIN = 0x2,
> -	EC_CODEC_I2S_ENABLE = 0x3,
> -	EC_CODEC_I2S_SET_CONFIG = 0x4,
> -	EC_CODEC_I2S_SET_TDM_CONFIG = 0x5,
> -	EC_CODEC_I2S_SET_BCLK = 0x6,
> -	EC_CODEC_I2S_SUBCMD_COUNT = 0x7,
> +/* Commands for I2S RX on audio codec. */
> +
> +#define EC_CMD_EC_CODEC_I2S_RX 0x00BC
> +
> +enum ec_codec_i2s_rx_subcmd {
> +	EC_CODEC_I2S_RX_ENABLE = 0x0,
> +	EC_CODEC_I2S_RX_DISABLE = 0x1,
> +	EC_CODEC_I2S_RX_SET_GAIN = 0x2,
> +	EC_CODEC_I2S_RX_GET_GAIN = 0x3,
> +	EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x4,
> +	EC_CODEC_I2S_RX_SET_DAIFMT = 0x5,
> +	EC_CODEC_I2S_RX_SET_BCLK = 0x6,
> +	EC_CODEC_I2S_RX_SUBCMD_COUNT,
>  };
>  
> -enum ec_sample_depth_value {
> -	EC_CODEC_SAMPLE_DEPTH_16 = 0,
> -	EC_CODEC_SAMPLE_DEPTH_24 = 1,
> +enum ec_codec_i2s_rx_sample_depth {
> +	EC_CODEC_I2S_RX_SAMPLE_DEPTH_16 = 0x0,
> +	EC_CODEC_I2S_RX_SAMPLE_DEPTH_24 = 0x1,
> +	EC_CODEC_I2S_RX_SAMPLE_DEPTH_COUNT,
>  };
>  
> -enum ec_i2s_config {
> -	EC_DAI_FMT_I2S = 0,
> -	EC_DAI_FMT_RIGHT_J = 1,
> -	EC_DAI_FMT_LEFT_J = 2,
> -	EC_DAI_FMT_PCM_A = 3,
> -	EC_DAI_FMT_PCM_B = 4,
> -	EC_DAI_FMT_PCM_TDM = 5,
> +enum ec_codec_i2s_rx_daifmt {
> +	EC_CODEC_I2S_RX_DAIFMT_I2S = 0x0,
> +	EC_CODEC_I2S_RX_DAIFMT_RIGHT_J = 0x1,
> +	EC_CODEC_I2S_RX_DAIFMT_LEFT_J = 0x2,
> +	EC_CODEC_I2S_RX_DAIFMT_COUNT,
>  };
>  
> -/*
> - * For subcommand EC_CODEC_GET_GAIN.
> - */
> -struct __ec_align1 ec_codec_i2s_gain {
> +struct __ec_align1 ec_param_ec_codec_i2s_rx_set_sample_depth {
> +	uint8_t depth;
> +	uint8_t reserved[3];
> +};
> +
> +struct __ec_align1 ec_param_ec_codec_i2s_rx_set_gain {
>  	uint8_t left;
>  	uint8_t right;
> +	uint8_t reserved[2];
>  };
>  
> -struct __ec_todo_unpacked ec_param_codec_i2s_tdm {
> -	int16_t ch0_delay; /* 0 to 496 */
> -	int16_t ch1_delay; /* -1 to 496 */
> -	uint8_t adjacent_to_ch0;
> -	uint8_t adjacent_to_ch1;
> +struct __ec_align1 ec_param_ec_codec_i2s_rx_set_daifmt {
> +	uint8_t daifmt;
> +	uint8_t reserved[3];
>  };
>  
> -struct __ec_todo_packed ec_param_codec_i2s {
> -	/* enum ec_codec_i2s_subcmd */
> -	uint8_t cmd;
> -	union {
> -		/*
> -		 * EC_CODEC_SET_SAMPLE_DEPTH
> -		 * Value should be one of ec_sample_depth_value.
> -		 */
> -		uint8_t depth;
> -
> -		/*
> -		 * EC_CODEC_SET_GAIN
> -		 * Value should be 0~43 for both channels.
> -		 */
> -		struct ec_codec_i2s_gain gain;
> -
> -		/*
> -		 * EC_CODEC_I2S_ENABLE
> -		 * 1 to enable, 0 to disable.
> -		 */
> -		uint8_t i2s_enable;
> -
> -		/*
> -		 * EC_CODEC_I2S_SET_CONFIG
> -		 * Value should be one of ec_i2s_config.
> -		 */
> -		uint8_t i2s_config;
> +struct __ec_align4 ec_param_ec_codec_i2s_rx_set_bclk {
> +	uint32_t bclk;
> +};
>  
> -		/*
> -		 * EC_CODEC_I2S_SET_TDM_CONFIG
> -		 * Value should be one of ec_i2s_config.
> -		 */
> -		struct ec_param_codec_i2s_tdm tdm_param;
> +struct __ec_align4 ec_param_ec_codec_i2s_rx {
> +	uint8_t cmd; /* enum ec_codec_i2s_rx_subcmd */
> +	uint8_t reserved[3];
>  
> -		/*
> -		 * EC_CODEC_I2S_SET_BCLK
> -		 */
> -		uint32_t bclk;
> +	union {
> +		struct ec_param_ec_codec_i2s_rx_set_sample_depth
> +				set_sample_depth_param;
> +		struct ec_param_ec_codec_i2s_rx_set_gain
> +				set_gain_param;
> +		struct ec_param_ec_codec_i2s_rx_set_daifmt
> +				set_daifmt_param;
> +		struct ec_param_ec_codec_i2s_rx_set_bclk
> +				set_bclk_param;
>  	};
>  };
>  
> +struct __ec_align1 ec_response_ec_codec_i2s_rx_get_gain {
> +	uint8_t left;
> +	uint8_t right;
> +};
>  
>  /*****************************************************************************/
>  /* System commands */
> diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
> index 3c1bd24a1057..179fa77291cd 100644
> --- a/sound/soc/codecs/cros_ec_codec.c
> +++ b/sound/soc/codecs/cros_ec_codec.c
> @@ -1,6 +1,8 @@
>  // SPDX-License-Identifier: GPL-2.0
>  /*
> - * Driver for ChromeOS Embedded Controller codec.
> + * Copyright 2019 Google, Inc.
> + *
> + * ChromeOS Embedded Controller codec driver.
>   *
>   * This driver uses the cros-ec interface to communicate with the ChromeOS
>   * EC for audio function.
> @@ -18,403 +20,297 @@
>  #include <sound/soc.h>
>  #include <sound/tlv.h>
>  
> -#define DRV_NAME "cros-ec-codec"
> -
> -/**
> - * struct cros_ec_codec_data - ChromeOS EC codec driver data.
> - * @dev:		Device structure used in sysfs.
> - * @ec_device:		cros_ec_device structure to talk to the physical device.
> - * @component:		Pointer to the component.
> - * @max_dmic_gain:	Maximum gain in dB supported by EC codec.
> - */
> -struct cros_ec_codec_data {
> +struct cros_ec_codec_priv {
>  	struct device *dev;
>  	struct cros_ec_device *ec_device;
> -	struct snd_soc_component *component;
> -	unsigned int max_dmic_gain;
>  };
>  
> -static const DECLARE_TLV_DB_SCALE(ec_mic_gain_tlv, 0, 100, 0);
> -
> -static int ec_command_get_gain(struct snd_soc_component *component,
> -			       struct ec_param_codec_i2s *param,
> -			       struct ec_codec_i2s_gain *resp)
> +static int send_ec_host_command(struct cros_ec_device *ec_dev, uint32_t cmd,
> +				uint8_t *out, size_t outsize,
> +				uint8_t *in, size_t insize)
>  {
> -	struct cros_ec_codec_data *codec_data =
> -		snd_soc_component_get_drvdata(component);
> -	struct cros_ec_device *ec_device = codec_data->ec_device;
> -	u8 buffer[sizeof(struct cros_ec_command) +
> -		  max(sizeof(struct ec_param_codec_i2s),
> -		      sizeof(struct ec_codec_i2s_gain))];
> -	struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
>  	int ret;
> +	struct cros_ec_command *msg;
> +
> +	msg = kmalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL);
> +	if (!msg)
> +		return -ENOMEM;
>  
>  	msg->version = 0;
> -	msg->command = EC_CMD_CODEC_I2S;
> -	msg->outsize = sizeof(struct ec_param_codec_i2s);
> -	msg->insize = sizeof(struct ec_codec_i2s_gain);
> +	msg->command = cmd;
> +	msg->outsize = outsize;
> +	msg->insize = insize;
> +
> +	if (outsize)
> +		memcpy(msg->data, out, outsize);
>  
> -	memcpy(msg->data, param, msg->outsize);
> +	ret = cros_ec_cmd_xfer_status(ec_dev, msg);
> +	if (ret < 0)
> +		goto error;
>  
> -	ret = cros_ec_cmd_xfer_status(ec_device, msg);
> -	if (ret > 0)
> -		memcpy(resp, msg->data, msg->insize);
> +	if (insize)
> +		memcpy(in, msg->data, insize);
>  
> +	ret = 0;
> +error:
> +	kfree(msg);
>  	return ret;
>  }
>  
> -/*
> - * Wrapper for EC command without response.
> - */
> -static int ec_command_no_resp(struct snd_soc_component *component,
> -			      struct ec_param_codec_i2s *param)
> +static int dmic_get_gain(struct snd_kcontrol *kcontrol,
> +			 struct snd_ctl_elem_value *ucontrol)
>  {
> -	struct cros_ec_codec_data *codec_data =
> +	struct snd_soc_component *component =
> +		snd_soc_kcontrol_component(kcontrol);
> +	struct cros_ec_codec_priv *priv =
>  		snd_soc_component_get_drvdata(component);
> -	struct cros_ec_device *ec_device = codec_data->ec_device;
> -	u8 buffer[sizeof(struct cros_ec_command) +
> -		  sizeof(struct ec_param_codec_i2s)];
> -	struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
> -
> -	msg->version = 0;
> -	msg->command = EC_CMD_CODEC_I2S;
> -	msg->outsize = sizeof(struct ec_param_codec_i2s);
> -	msg->insize = 0;
> -
> -	memcpy(msg->data, param, msg->outsize);
> -
> -	return cros_ec_cmd_xfer_status(ec_device, msg);
> -}
> -
> -static int set_i2s_config(struct snd_soc_component *component,
> -			  enum ec_i2s_config i2s_config)
> -{
> -	struct ec_param_codec_i2s param;
> +	struct ec_param_ec_codec_i2s_rx p;
> +	struct ec_response_ec_codec_i2s_rx_get_gain r;
> +	int ret;
>  
> -	dev_dbg(component->dev, "%s set I2S format to %u\n", __func__,
> -		i2s_config);
> +	p.cmd = EC_CODEC_I2S_RX_GET_GAIN;
> +	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
> +				   (uint8_t *)&p, sizeof(p),
> +				   (uint8_t *)&r, sizeof(r));
> +	if (ret < 0)
> +		return ret;
>  
> -	param.cmd = EC_CODEC_I2S_SET_CONFIG;
> -	param.i2s_config = i2s_config;
> +	ucontrol->value.integer.value[0] = r.left;
> +	ucontrol->value.integer.value[1] = r.right;
>  
> -	return ec_command_no_resp(component, &param);
> +	return 0;
>  }
>  
> -static int cros_ec_i2s_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
> +static int dmic_put_gain(struct snd_kcontrol *kcontrol,
> +			 struct snd_ctl_elem_value *ucontrol)
>  {
> -	struct snd_soc_component *component = dai->component;
> -	enum ec_i2s_config i2s_config;
> -
> -	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> -	case SND_SOC_DAIFMT_CBS_CFS:
> -		break;
> -	default:
> -		return -EINVAL;
> -	}
> -
> -	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> -	case SND_SOC_DAIFMT_NB_NF:
> -		break;
> -	default:
> -		return -EINVAL;
> -	}
> -
> -	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> -	case SND_SOC_DAIFMT_I2S:
> -		i2s_config = EC_DAI_FMT_I2S;
> -		break;
> -
> -	case SND_SOC_DAIFMT_RIGHT_J:
> -		i2s_config = EC_DAI_FMT_RIGHT_J;
> -		break;
> -
> -	case SND_SOC_DAIFMT_LEFT_J:
> -		i2s_config = EC_DAI_FMT_LEFT_J;
> -		break;
> -
> -	case SND_SOC_DAIFMT_DSP_A:
> -		i2s_config = EC_DAI_FMT_PCM_A;
> -		break;
> -
> -	case SND_SOC_DAIFMT_DSP_B:
> -		i2s_config = EC_DAI_FMT_PCM_B;
> -		break;
> +	struct snd_soc_component *component =
> +		snd_soc_kcontrol_component(kcontrol);
> +	struct cros_ec_codec_priv *priv =
> +		snd_soc_component_get_drvdata(component);
> +	struct soc_mixer_control *control =
> +		(struct soc_mixer_control *)kcontrol->private_value;
> +	int max_dmic_gain = control->max;
> +	int left = ucontrol->value.integer.value[0];
> +	int right = ucontrol->value.integer.value[1];
> +	struct ec_param_ec_codec_i2s_rx p;
>  
> -	default:
> +	if (left > max_dmic_gain || right > max_dmic_gain)
>  		return -EINVAL;
> -	}
>  
> -	return set_i2s_config(component, i2s_config);
> -}
> -
> -static int set_i2s_sample_depth(struct snd_soc_component *component,
> -				enum ec_sample_depth_value depth)
> -{
> -	struct ec_param_codec_i2s param;
> -
> -	dev_dbg(component->dev, "%s set depth to %u\n", __func__, depth);
> -
> -	param.cmd = EC_CODEC_SET_SAMPLE_DEPTH;
> -	param.depth = depth;
> +	dev_dbg(component->dev, "set mic gain to %u, %u\n", left, right);
>  
> -	return ec_command_no_resp(component, &param);
> +	p.cmd = EC_CODEC_I2S_RX_SET_GAIN;
> +	p.set_gain_param.left = left;
> +	p.set_gain_param.right = right;
> +	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
> +				    (uint8_t *)&p, sizeof(p), NULL, 0);
>  }
>  
> -static int set_i2s_bclk(struct snd_soc_component *component, uint32_t bclk)
> -{
> -	struct ec_param_codec_i2s param;
> -
> -	dev_dbg(component->dev, "%s set i2s bclk to %u\n", __func__, bclk);
> +static const DECLARE_TLV_DB_SCALE(dmic_gain_tlv, 0, 100, 0);
>  
> -	param.cmd = EC_CODEC_I2S_SET_BCLK;
> -	param.bclk = bclk;
> +enum {
> +	DMIC_CTL_GAIN = 0,
> +};
>  
> -	return ec_command_no_resp(component, &param);
> -}
> +static struct snd_kcontrol_new dmic_controls[] = {
> +	[DMIC_CTL_GAIN] =
> +		SOC_DOUBLE_EXT_TLV("EC Mic Gain", SND_SOC_NOPM, SND_SOC_NOPM,
> +				   0, 0, 0, dmic_get_gain, dmic_put_gain,
> +				   dmic_gain_tlv),
> +};
>  
> -static int cros_ec_i2s_hw_params(struct snd_pcm_substream *substream,
> -				 struct snd_pcm_hw_params *params,
> -				 struct snd_soc_dai *dai)
> +static int i2s_rx_hw_params(struct snd_pcm_substream *substream,
> +			    struct snd_pcm_hw_params *params,
> +			    struct snd_soc_dai *dai)
>  {
>  	struct snd_soc_component *component = dai->component;
> -	unsigned int rate, bclk;
> +	struct cros_ec_codec_priv *priv =
> +		snd_soc_component_get_drvdata(component);
> +	struct ec_param_ec_codec_i2s_rx p;
> +	enum ec_codec_i2s_rx_sample_depth depth;
>  	int ret;
>  
> -	rate = params_rate(params);
> -	if (rate != 48000)
> +	if (params_rate(params) != 48000)
>  		return -EINVAL;
>  
>  	switch (params_format(params)) {
>  	case SNDRV_PCM_FORMAT_S16_LE:
> -		ret = set_i2s_sample_depth(component, EC_CODEC_SAMPLE_DEPTH_16);
> +		depth = EC_CODEC_I2S_RX_SAMPLE_DEPTH_16;
>  		break;
>  	case SNDRV_PCM_FORMAT_S24_LE:
> -		ret = set_i2s_sample_depth(component, EC_CODEC_SAMPLE_DEPTH_24);
> +		depth = EC_CODEC_I2S_RX_SAMPLE_DEPTH_24;
>  		break;
>  	default:
>  		return -EINVAL;
>  	}
> -	if (ret < 0)
> -		return ret;
> -
> -	bclk = snd_soc_params_to_bclk(params);
> -	return set_i2s_bclk(component, bclk);
> -}
>  
> -static const struct snd_soc_dai_ops cros_ec_i2s_dai_ops = {
> -	.hw_params = cros_ec_i2s_hw_params,
> -	.set_fmt = cros_ec_i2s_set_dai_fmt,
> -};
> +	dev_dbg(component->dev, "set depth to %u\n", depth);
>  
> -static struct snd_soc_dai_driver cros_ec_dai[] = {
> -	{
> -		.name = "cros_ec_codec I2S",
> -		.id = 0,
> -		.capture = {
> -			.stream_name = "I2S Capture",
> -			.channels_min = 2,
> -			.channels_max = 2,
> -			.rates = SNDRV_PCM_RATE_48000,
> -			.formats = SNDRV_PCM_FMTBIT_S16_LE |
> -				   SNDRV_PCM_FMTBIT_S24_LE,
> -		},
> -		.ops = &cros_ec_i2s_dai_ops,
> -	}
> -};
> -
> -static int get_ec_mic_gain(struct snd_soc_component *component,
> -			   u8 *left, u8 *right)
> -{
> -	struct ec_param_codec_i2s param;
> -	struct ec_codec_i2s_gain resp;
> -	int ret;
> -
> -	param.cmd = EC_CODEC_GET_GAIN;
> -
> -	ret = ec_command_get_gain(component, &param, &resp);
> +	p.cmd = EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH;
> +	p.set_sample_depth_param.depth = depth;
> +	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
> +				   (uint8_t *)&p, sizeof(p), NULL, 0);
>  	if (ret < 0)
>  		return ret;
>  
> -	*left = resp.left;
> -	*right = resp.right;
> -
> -	return 0;
> -}
> -
> -static int mic_gain_get(struct snd_kcontrol *kcontrol,
> -			struct snd_ctl_elem_value *ucontrol)
> -{
> -	struct snd_soc_component *component =
> -		snd_soc_kcontrol_component(kcontrol);
> -	u8 left, right;
> -	int ret;
> -
> -	ret = get_ec_mic_gain(component, &left, &right);
> -	if (ret)
> -		return ret;
> -
> -	ucontrol->value.integer.value[0] = left;
> -	ucontrol->value.integer.value[1] = right;
> -
> -	return 0;
> -}
> -
> -static int set_ec_mic_gain(struct snd_soc_component *component,
> -			   u8 left, u8 right)
> -{
> -	struct ec_param_codec_i2s param;
> -
> -	dev_dbg(component->dev, "%s set mic gain to %u, %u\n",
> -		__func__, left, right);
> +	dev_dbg(component->dev, "set bclk to %u\n",
> +		snd_soc_params_to_bclk(params));
>  
> -	param.cmd = EC_CODEC_SET_GAIN;
> -	param.gain.left = left;
> -	param.gain.right = right;
> -
> -	return ec_command_no_resp(component, &param);
> +	p.cmd = EC_CODEC_I2S_RX_SET_BCLK;
> +	p.set_bclk_param.bclk = snd_soc_params_to_bclk(params);
> +	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
> +				    (uint8_t *)&p, sizeof(p), NULL, 0);
>  }
>  
> -static int mic_gain_put(struct snd_kcontrol *kcontrol,
> -			struct snd_ctl_elem_value *ucontrol)
> +static int i2s_rx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
>  {
> -	struct snd_soc_component *component =
> -		snd_soc_kcontrol_component(kcontrol);
> -	struct cros_ec_codec_data *codec_data =
> +	struct snd_soc_component *component = dai->component;
> +	struct cros_ec_codec_priv *priv =
>  		snd_soc_component_get_drvdata(component);
> -	int left = ucontrol->value.integer.value[0];
> -	int right = ucontrol->value.integer.value[1];
> -	unsigned int max_dmic_gain = codec_data->max_dmic_gain;
> +	struct ec_param_ec_codec_i2s_rx p;
> +	enum ec_codec_i2s_rx_daifmt daifmt;
>  
> -	if (left > max_dmic_gain || right > max_dmic_gain)
> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +	case SND_SOC_DAIFMT_CBS_CFS:
> +		break;
> +	default:
>  		return -EINVAL;
> +	}
>  
> -	return set_ec_mic_gain(component, (u8)left, (u8)right);
> -}
> -
> -static struct snd_kcontrol_new mic_gain_control =
> -	SOC_DOUBLE_EXT_TLV("EC Mic Gain", SND_SOC_NOPM, SND_SOC_NOPM, 0, 0, 0,
> -			   mic_gain_get, mic_gain_put, ec_mic_gain_tlv);
> -
> -static int enable_i2s(struct snd_soc_component *component, int enable)
> -{
> -	struct ec_param_codec_i2s param;
> +	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +	case SND_SOC_DAIFMT_NB_NF:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
>  
> -	dev_dbg(component->dev, "%s set i2s to %u\n", __func__, enable);
> +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +	case SND_SOC_DAIFMT_I2S:
> +		daifmt = EC_CODEC_I2S_RX_DAIFMT_I2S;
> +		break;
> +	case SND_SOC_DAIFMT_RIGHT_J:
> +		daifmt = EC_CODEC_I2S_RX_DAIFMT_RIGHT_J;
> +		break;
> +	case SND_SOC_DAIFMT_LEFT_J:
> +		daifmt = EC_CODEC_I2S_RX_DAIFMT_LEFT_J;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
>  
> -	param.cmd = EC_CODEC_I2S_ENABLE;
> -	param.i2s_enable = enable;
> +	dev_dbg(component->dev, "set format to %u\n", daifmt);
>  
> -	return ec_command_no_resp(component, &param);
> +	p.cmd = EC_CODEC_I2S_RX_SET_DAIFMT;
> +	p.set_daifmt_param.daifmt = daifmt;
> +	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
> +				    (uint8_t *)&p, sizeof(p), NULL, 0);
>  }
>  
> -static int cros_ec_i2s_enable_event(struct snd_soc_dapm_widget *w,
> -				    struct snd_kcontrol *kcontrol, int event)
> +static const struct snd_soc_dai_ops i2s_rx_dai_ops = {
> +	.hw_params = i2s_rx_hw_params,
> +	.set_fmt = i2s_rx_set_fmt,
> +};
> +
> +static int i2s_rx_event(struct snd_soc_dapm_widget *w,
> +			struct snd_kcontrol *kcontrol, int event)
>  {
>  	struct snd_soc_component *component =
>  		snd_soc_dapm_to_component(w->dapm);
> +	struct cros_ec_codec_priv *priv =
> +		snd_soc_component_get_drvdata(component);
> +	struct ec_param_ec_codec_i2s_rx p;
>  
>  	switch (event) {
>  	case SND_SOC_DAPM_PRE_PMU:
> -		dev_dbg(component->dev,
> -			"%s got SND_SOC_DAPM_PRE_PMU event\n", __func__);
> -		return enable_i2s(component, 1);
> -
> +		dev_dbg(component->dev, "enable I2S RX\n");
> +		p.cmd = EC_CODEC_I2S_RX_ENABLE;
> +		break;
>  	case SND_SOC_DAPM_PRE_PMD:
> -		dev_dbg(component->dev,
> -			"%s got SND_SOC_DAPM_PRE_PMD event\n", __func__);
> -		return enable_i2s(component, 0);
> +		dev_dbg(component->dev, "disable I2S RX\n");
> +		p.cmd = EC_CODEC_I2S_RX_DISABLE;
> +		break;
> +	default:
> +		return 0;
>  	}
>  
> -	return 0;
> +	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
> +				    (uint8_t *)&p, sizeof(p), NULL, 0);
>  }
>  
> -/*
> - * The goal of this DAPM route is to turn on/off I2S using EC
> - * host command when capture stream is started/stopped.
> - */
> -static const struct snd_soc_dapm_widget cros_ec_codec_dapm_widgets[] = {
> +static struct snd_soc_dapm_widget i2s_rx_dapm_widgets[] = {
>  	SND_SOC_DAPM_INPUT("DMIC"),
> -
> -	/*
> -	 * Control EC to enable/disable I2S.
> -	 */
> -	SND_SOC_DAPM_SUPPLY("I2S Enable", SND_SOC_NOPM,
> -			    0, 0, cros_ec_i2s_enable_event,
> +	SND_SOC_DAPM_SUPPLY("I2S RX Enable", SND_SOC_NOPM, 0, 0, i2s_rx_event,
>  			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
> +	SND_SOC_DAPM_AIF_OUT("I2S RX", "I2S Capture", 0, SND_SOC_NOPM, 0, 0),
> +};
>  
> -	SND_SOC_DAPM_AIF_OUT("I2STX", "I2S Capture", 0, SND_SOC_NOPM, 0, 0),
> +static struct snd_soc_dapm_route i2s_rx_dapm_routes[] = {
> +	{"I2S RX", NULL, "DMIC"},
> +	{"I2S RX", NULL, "I2S RX Enable"},
>  };
>  
> -static const struct snd_soc_dapm_route cros_ec_codec_dapm_routes[] = {
> -	{ "I2STX", NULL, "DMIC" },
> -	{ "I2STX", NULL, "I2S Enable" },
> +static struct snd_soc_dai_driver i2s_rx_dai_driver = {
> +	.name = "EC Codec I2S RX",
> +	.capture = {
> +		.stream_name = "I2S Capture",
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_48000,
> +		.formats = SNDRV_PCM_FMTBIT_S16_LE |
> +			SNDRV_PCM_FMTBIT_S24_LE,
> +	},
> +	.ops = &i2s_rx_dai_ops,
>  };
>  
> -/*
> - * Read maximum gain from device property and set it to mixer control.
> - */
> -static int cros_ec_set_gain_range(struct device *dev)
> +static int i2s_rx_probe(struct snd_soc_component *component)
>  {
> +	struct cros_ec_codec_priv *priv =
> +		snd_soc_component_get_drvdata(component);
> +	struct device *dev = priv->dev;
> +	int ret, val;
>  	struct soc_mixer_control *control;
> -	struct cros_ec_codec_data *codec_data = dev_get_drvdata(dev);
> -	int rc;
>  
> -	rc = device_property_read_u32(dev, "max-dmic-gain",
> -				      &codec_data->max_dmic_gain);
> -	if (rc)
> -		return rc;
> +	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
> +	if (ret) {
> +		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
> +		return ret;
> +	}
>  
>  	control = (struct soc_mixer_control *)
> -				mic_gain_control.private_value;
> -	control->max = codec_data->max_dmic_gain;
> -	control->platform_max = codec_data->max_dmic_gain;
> +			dmic_controls[DMIC_CTL_GAIN].private_value;
> +	control->max = val;
> +	control->platform_max = val;
>  
> -	return 0;
> -}
> -
> -static int cros_ec_codec_probe(struct snd_soc_component *component)
> -{
> -	int rc;
> -
> -	struct cros_ec_codec_data *codec_data =
> -		snd_soc_component_get_drvdata(component);
> -
> -	rc = cros_ec_set_gain_range(codec_data->dev);
> -	if (rc)
> -		return rc;
> -
> -	return snd_soc_add_component_controls(component, &mic_gain_control, 1);
> +	return snd_soc_add_component_controls(component,
> +			&dmic_controls[DMIC_CTL_GAIN], 1);
>  }
>  
> -static const struct snd_soc_component_driver cros_ec_component_driver = {
> -	.probe			= cros_ec_codec_probe,
> -	.dapm_widgets		= cros_ec_codec_dapm_widgets,
> -	.num_dapm_widgets	= ARRAY_SIZE(cros_ec_codec_dapm_widgets),
> -	.dapm_routes		= cros_ec_codec_dapm_routes,
> -	.num_dapm_routes	= ARRAY_SIZE(cros_ec_codec_dapm_routes),
> +static const struct snd_soc_component_driver i2s_rx_component_driver = {
> +	.probe			= i2s_rx_probe,
> +	.dapm_widgets		= i2s_rx_dapm_widgets,
> +	.num_dapm_widgets	= ARRAY_SIZE(i2s_rx_dapm_widgets),
> +	.dapm_routes		= i2s_rx_dapm_routes,
> +	.num_dapm_routes	= ARRAY_SIZE(i2s_rx_dapm_routes),
>  };
>  
> -/*
> - * Platform device and platform driver fro cros-ec-codec.
> - */
> -static int cros_ec_codec_platform_probe(struct platform_device *pd)
> +static int cros_ec_codec_platform_probe(struct platform_device *pdev)
>  {
> -	struct device *dev = &pd->dev;
> -	struct cros_ec_device *ec_device = dev_get_drvdata(pd->dev.parent);
> -	struct cros_ec_codec_data *codec_data;
> +	struct device *dev = &pdev->dev;
> +	struct cros_ec_device *ec_device = dev_get_drvdata(pdev->dev.parent);
> +	struct cros_ec_codec_priv *priv;
>  
> -	codec_data = devm_kzalloc(dev, sizeof(struct cros_ec_codec_data),
> -				  GFP_KERNEL);
> -	if (!codec_data)
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
>  		return -ENOMEM;
>  
> -	codec_data->dev = dev;
> -	codec_data->ec_device = ec_device;
> +	priv->dev = dev;
> +	priv->ec_device = ec_device;
>  
> -	platform_set_drvdata(pd, codec_data);
> +	platform_set_drvdata(pdev, priv);
>  
> -	return devm_snd_soc_register_component(dev, &cros_ec_component_driver,
> -					  cros_ec_dai, ARRAY_SIZE(cros_ec_dai));
> +	return devm_snd_soc_register_component(dev, &i2s_rx_component_driver,
> +					       &i2s_rx_dai_driver, 1);
>  }
>  
>  #ifdef CONFIG_OF
> @@ -427,7 +323,7 @@ MODULE_DEVICE_TABLE(of, cros_ec_codec_of_match);
>  
>  static struct platform_driver cros_ec_codec_platform_driver = {
>  	.driver = {
> -		.name = DRV_NAME,
> +		.name = "cros-ec-codec",
>  		.of_match_table = of_match_ptr(cros_ec_codec_of_match),
>  	},
>  	.probe = cros_ec_codec_platform_probe,
> @@ -438,4 +334,4 @@ module_platform_driver(cros_ec_codec_platform_driver);
>  MODULE_LICENSE("GPL v2");
>  MODULE_DESCRIPTION("ChromeOS EC codec driver");
>  MODULE_AUTHOR("Cheng-Yi Chiang <cychiang@chromium.org>");
> -MODULE_ALIAS("platform:" DRV_NAME);
> +MODULE_ALIAS("platform:cros-ec-codec");
> -- 
> 2.23.0.700.g56cf767bdb-goog
> 

-- 
Benson Leung
Staff Software Engineer
Chrome OS Kernel
Google Inc.
bleung@google.com
Chromium OS Project
bleung@chromium.org

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 03/10] ASoC: cros_ec_codec: extract DMIC EC command from I2S RX
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 03/10] ASoC: cros_ec_codec: extract DMIC EC command from I2S RX Tzung-Bi Shih
@ 2019-10-17  2:48   ` Benson Leung
  2019-10-18 18:06   ` [alsa-devel] Applied "ASoC: cros_ec_codec: extract DMIC EC command from I2S RX" to the asoc tree Mark Brown
  1 sibling, 0 replies; 29+ messages in thread
From: Benson Leung @ 2019-10-17  2:48 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	broonie, enric.balletbo, dgreid


[-- Attachment #1.1: Type: text/plain, Size: 7416 bytes --]

Hi Tzung-Bi,

On Mon, Oct 14, 2019 at 06:20:15PM +0800, Tzung-Bi Shih wrote:
> Extract DMIC EC command from I2S RX.  Setting and getting
> microphone gains is common features.
> 
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>

Acked-By: Benson Leung <bleung@chromium.org>

Thanks,
Benson

> ---
>  drivers/platform/chrome/cros_ec_trace.c       |  1 +
>  .../linux/platform_data/cros_ec_commands.h    | 49 +++++++++++-----
>  sound/soc/codecs/cros_ec_codec.c              | 57 ++++++++++---------
>  3 files changed, 68 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c
> index 901850004b2b..e73bb6a8b00e 100644
> --- a/drivers/platform/chrome/cros_ec_trace.c
> +++ b/drivers/platform/chrome/cros_ec_trace.c
> @@ -98,6 +98,7 @@
>  	TRACE_SYMBOL(EC_CMD_SB_READ_BLOCK), \
>  	TRACE_SYMBOL(EC_CMD_SB_WRITE_BLOCK), \
>  	TRACE_SYMBOL(EC_CMD_BATTERY_VENDOR_PARAM), \
> +	TRACE_SYMBOL(EC_CMD_EC_CODEC_DMIC), \
>  	TRACE_SYMBOL(EC_CMD_EC_CODEC_I2S_RX), \
>  	TRACE_SYMBOL(EC_CMD_REBOOT_EC), \
>  	TRACE_SYMBOL(EC_CMD_GET_PANIC_INFO), \
> diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
> index 261ac83bd007..58e460c015ef 100644
> --- a/include/linux/platform_data/cros_ec_commands.h
> +++ b/include/linux/platform_data/cros_ec_commands.h
> @@ -4466,18 +4466,48 @@ enum mkbp_cec_event {
>  
>  /*****************************************************************************/
>  
> +/* Commands for DMIC on audio codec. */
> +#define EC_CMD_EC_CODEC_DMIC 0x00BC
> +
> +enum ec_codec_dmic_subcmd {
> +	EC_CODEC_DMIC_SET_GAIN = 0x0,
> +	EC_CODEC_DMIC_GET_GAIN = 0x1,
> +	EC_CODEC_DMIC_SUBCMD_COUNT,
> +};
> +
> +struct __ec_align1 ec_param_ec_codec_dmic_set_gain {
> +	uint8_t left;
> +	uint8_t right;
> +	uint8_t reserved[2];
> +};
> +
> +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_align1 ec_response_ec_codec_dmic_get_gain {
> +	uint8_t left;
> +	uint8_t right;
> +};
> +
> +/*****************************************************************************/
> +
>  /* Commands for I2S RX on audio codec. */
>  
> -#define EC_CMD_EC_CODEC_I2S_RX 0x00BC
> +#define EC_CMD_EC_CODEC_I2S_RX 0x00BD
>  
>  enum ec_codec_i2s_rx_subcmd {
>  	EC_CODEC_I2S_RX_ENABLE = 0x0,
>  	EC_CODEC_I2S_RX_DISABLE = 0x1,
> -	EC_CODEC_I2S_RX_SET_GAIN = 0x2,
> -	EC_CODEC_I2S_RX_GET_GAIN = 0x3,
> -	EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x4,
> -	EC_CODEC_I2S_RX_SET_DAIFMT = 0x5,
> -	EC_CODEC_I2S_RX_SET_BCLK = 0x6,
> +	EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x2,
> +	EC_CODEC_I2S_RX_SET_DAIFMT = 0x3,
> +	EC_CODEC_I2S_RX_SET_BCLK = 0x4,
>  	EC_CODEC_I2S_RX_SUBCMD_COUNT,
>  };
>  
> @@ -4521,8 +4551,6 @@ struct __ec_align4 ec_param_ec_codec_i2s_rx {
>  	union {
>  		struct ec_param_ec_codec_i2s_rx_set_sample_depth
>  				set_sample_depth_param;
> -		struct ec_param_ec_codec_i2s_rx_set_gain
> -				set_gain_param;
>  		struct ec_param_ec_codec_i2s_rx_set_daifmt
>  				set_daifmt_param;
>  		struct ec_param_ec_codec_i2s_rx_set_bclk
> @@ -4530,11 +4558,6 @@ struct __ec_align4 ec_param_ec_codec_i2s_rx {
>  	};
>  };
>  
> -struct __ec_align1 ec_response_ec_codec_i2s_rx_get_gain {
> -	uint8_t left;
> -	uint8_t right;
> -};
> -
>  /*****************************************************************************/
>  /* System commands */
>  
> diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
> index 179fa77291cd..c19c7fe42e2e 100644
> --- a/sound/soc/codecs/cros_ec_codec.c
> +++ b/sound/soc/codecs/cros_ec_codec.c
> @@ -64,12 +64,12 @@ static int dmic_get_gain(struct snd_kcontrol *kcontrol,
>  		snd_soc_kcontrol_component(kcontrol);
>  	struct cros_ec_codec_priv *priv =
>  		snd_soc_component_get_drvdata(component);
> -	struct ec_param_ec_codec_i2s_rx p;
> -	struct ec_response_ec_codec_i2s_rx_get_gain r;
> +	struct ec_param_ec_codec_dmic p;
> +	struct ec_response_ec_codec_dmic_get_gain r;
>  	int ret;
>  
> -	p.cmd = EC_CODEC_I2S_RX_GET_GAIN;
> -	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
> +	p.cmd = EC_CODEC_DMIC_GET_GAIN;
> +	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
>  				   (uint8_t *)&p, sizeof(p),
>  				   (uint8_t *)&r, sizeof(r));
>  	if (ret < 0)
> @@ -93,17 +93,17 @@ static int dmic_put_gain(struct snd_kcontrol *kcontrol,
>  	int max_dmic_gain = control->max;
>  	int left = ucontrol->value.integer.value[0];
>  	int right = ucontrol->value.integer.value[1];
> -	struct ec_param_ec_codec_i2s_rx p;
> +	struct ec_param_ec_codec_dmic p;
>  
>  	if (left > max_dmic_gain || right > max_dmic_gain)
>  		return -EINVAL;
>  
>  	dev_dbg(component->dev, "set mic gain to %u, %u\n", left, right);
>  
> -	p.cmd = EC_CODEC_I2S_RX_SET_GAIN;
> +	p.cmd = EC_CODEC_DMIC_SET_GAIN;
>  	p.set_gain_param.left = left;
>  	p.set_gain_param.right = right;
> -	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
> +	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
>  				    (uint8_t *)&p, sizeof(p), NULL, 0);
>  }
>  
> @@ -120,6 +120,29 @@ static struct snd_kcontrol_new dmic_controls[] = {
>  				   dmic_gain_tlv),
>  };
>  
> +static int dmic_probe(struct snd_soc_component *component)
> +{
> +	struct cros_ec_codec_priv *priv =
> +		snd_soc_component_get_drvdata(component);
> +	struct device *dev = priv->dev;
> +	int ret, val;
> +	struct soc_mixer_control *control;
> +
> +	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
> +	if (ret) {
> +		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
> +		return ret;
> +	}
> +
> +	control = (struct soc_mixer_control *)
> +		dmic_controls[DMIC_CTL_GAIN].private_value;
> +	control->max = val;
> +	control->platform_max = val;
> +
> +	return snd_soc_add_component_controls(component,
> +			&dmic_controls[DMIC_CTL_GAIN], 1);
> +}
> +
>  static int i2s_rx_hw_params(struct snd_pcm_substream *substream,
>  			    struct snd_pcm_hw_params *params,
>  			    struct snd_soc_dai *dai)
> @@ -265,25 +288,7 @@ static struct snd_soc_dai_driver i2s_rx_dai_driver = {
>  
>  static int i2s_rx_probe(struct snd_soc_component *component)
>  {
> -	struct cros_ec_codec_priv *priv =
> -		snd_soc_component_get_drvdata(component);
> -	struct device *dev = priv->dev;
> -	int ret, val;
> -	struct soc_mixer_control *control;
> -
> -	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
> -	if (ret) {
> -		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
> -		return ret;
> -	}
> -
> -	control = (struct soc_mixer_control *)
> -			dmic_controls[DMIC_CTL_GAIN].private_value;
> -	control->max = val;
> -	control->platform_max = val;
> -
> -	return snd_soc_add_component_controls(component,
> -			&dmic_controls[DMIC_CTL_GAIN], 1);
> +	return dmic_probe(component);
>  }
>  
>  static const struct snd_soc_component_driver i2s_rx_component_driver = {
> -- 
> 2.23.0.700.g56cf767bdb-goog
> 

-- 
Benson Leung
Staff Software Engineer
Chrome OS Kernel
Google Inc.
bleung@google.com
Chromium OS Project
bleung@chromium.org

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 04/10] platform/chrome: cros_ec: add common commands for EC codec
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 04/10] platform/chrome: cros_ec: add common commands for EC codec Tzung-Bi Shih
@ 2019-10-17  2:57   ` Benson Leung
  0 siblings, 0 replies; 29+ messages in thread
From: Benson Leung @ 2019-10-17  2:57 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	broonie, enric.balletbo, dgreid


[-- Attachment #1.1: Type: text/plain, Size: 3562 bytes --]

Hi Tzung-Bi,

On Mon, Oct 14, 2019 at 06:20:16PM +0800, Tzung-Bi Shih wrote:
> Add the following common commands:
> - GET_CAPABILITIES
> - GET_SHM_ADDR
> - SET_SHM_ADDR
> 
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>

Acked-By: Benson Leung <bleung@chromium.org>

Thanks,
Benson

> ---
>  drivers/platform/chrome/cros_ec_trace.c       |  1 +
>  .../linux/platform_data/cros_ec_commands.h    | 64 ++++++++++++++++++-
>  2 files changed, 63 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c
> index e73bb6a8b00e..2ea0d4e0d54d 100644
> --- a/drivers/platform/chrome/cros_ec_trace.c
> +++ b/drivers/platform/chrome/cros_ec_trace.c
> @@ -98,6 +98,7 @@
>  	TRACE_SYMBOL(EC_CMD_SB_READ_BLOCK), \
>  	TRACE_SYMBOL(EC_CMD_SB_WRITE_BLOCK), \
>  	TRACE_SYMBOL(EC_CMD_BATTERY_VENDOR_PARAM), \
> +	TRACE_SYMBOL(EC_CMD_EC_CODEC), \
>  	TRACE_SYMBOL(EC_CMD_EC_CODEC_DMIC), \
>  	TRACE_SYMBOL(EC_CMD_EC_CODEC_I2S_RX), \
>  	TRACE_SYMBOL(EC_CMD_REBOOT_EC), \
> diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
> index 58e460c015ef..3ca0fa9e92a7 100644
> --- a/include/linux/platform_data/cros_ec_commands.h
> +++ b/include/linux/platform_data/cros_ec_commands.h
> @@ -4466,8 +4466,68 @@ enum mkbp_cec_event {
>  
>  /*****************************************************************************/
>  
> +/* Commands for audio codec. */
> +#define EC_CMD_EC_CODEC 0x00BC
> +
> +enum ec_codec_subcmd {
> +	EC_CODEC_GET_CAPABILITIES = 0x0,
> +	EC_CODEC_GET_SHM_ADDR = 0x1,
> +	EC_CODEC_SET_SHM_ADDR = 0x2,
> +	EC_CODEC_SUBCMD_COUNT,
> +};
> +
> +enum ec_codec_cap {
> +	EC_CODEC_CAP_LAST = 32,
> +};
> +
> +enum ec_codec_shm_id {
> +	EC_CODEC_SHM_ID_LAST,
> +};
> +
> +enum ec_codec_shm_type {
> +	EC_CODEC_SHM_TYPE_EC_RAM = 0x0,
> +	EC_CODEC_SHM_TYPE_SYSTEM_RAM = 0x1,
> +};
> +
> +struct __ec_align1 ec_param_ec_codec_get_shm_addr {
> +	uint8_t shm_id;
> +	uint8_t reserved[3];
> +};
> +
> +struct __ec_align4 ec_param_ec_codec_set_shm_addr {
> +	uint64_t phys_addr;
> +	uint32_t len;
> +	uint8_t shm_id;
> +	uint8_t reserved[3];
> +};
> +
> +struct __ec_align4 ec_param_ec_codec {
> +	uint8_t cmd; /* enum ec_codec_subcmd */
> +	uint8_t reserved[3];
> +
> +	union {
> +		struct ec_param_ec_codec_get_shm_addr
> +				get_shm_addr_param;
> +		struct ec_param_ec_codec_set_shm_addr
> +				set_shm_addr_param;
> +	};
> +};
> +
> +struct __ec_align4 ec_response_ec_codec_get_capabilities {
> +	uint32_t capabilities;
> +};
> +
> +struct __ec_align4 ec_response_ec_codec_get_shm_addr {
> +	uint64_t phys_addr;
> +	uint32_t len;
> +	uint8_t type;
> +	uint8_t reserved[3];
> +};
> +
> +/*****************************************************************************/
> +
>  /* Commands for DMIC on audio codec. */
> -#define EC_CMD_EC_CODEC_DMIC 0x00BC
> +#define EC_CMD_EC_CODEC_DMIC 0x00BD
>  
>  enum ec_codec_dmic_subcmd {
>  	EC_CODEC_DMIC_SET_GAIN = 0x0,
> @@ -4500,7 +4560,7 @@ struct __ec_align1 ec_response_ec_codec_dmic_get_gain {
>  
>  /* Commands for I2S RX on audio codec. */
>  
> -#define EC_CMD_EC_CODEC_I2S_RX 0x00BD
> +#define EC_CMD_EC_CODEC_I2S_RX 0x00BE
>  
>  enum ec_codec_i2s_rx_subcmd {
>  	EC_CODEC_I2S_RX_ENABLE = 0x0,
> -- 
> 2.23.0.700.g56cf767bdb-goog
> 

-- 
Benson Leung
Staff Software Engineer
Chrome OS Kernel
Google Inc.
bleung@google.com
Chromium OS Project
bleung@chromium.org

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 05/10] ASoC: cros_ec_codec: read max DMIC gain from EC codec
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 05/10] ASoC: cros_ec_codec: read max DMIC gain from " Tzung-Bi Shih
@ 2019-10-17  3:07   ` Benson Leung
  0 siblings, 0 replies; 29+ messages in thread
From: Benson Leung @ 2019-10-17  3:07 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	broonie, enric.balletbo, dgreid, Rob Herring


[-- Attachment #1.1: Type: text/plain, Size: 7724 bytes --]

On Mon, Oct 14, 2019 at 06:20:17PM +0800, Tzung-Bi Shih wrote:
> Read max DMIC gain from EC codec instead of DTS.  Also removes the
> dt-binding of max-dmic-gain.
> 
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>

Acked-By: Benson Leung <bleung@chromium.org>


> ---
>  .../bindings/sound/google,cros-ec-codec.txt   |  4 +-
>  .../linux/platform_data/cros_ec_commands.h    | 43 +++++++++++----
>  sound/soc/codecs/cros_ec_codec.c              | 53 ++++++++++++++-----
>  3 files changed, 73 insertions(+), 27 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
> index 1084f7f22eea..0ce9fafc78e2 100644
> --- a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
> +++ b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
> @@ -1,4 +1,4 @@
> -* Audio codec controlled by ChromeOS EC
> +Audio codec controlled by ChromeOS EC
>  
>  Google's ChromeOS EC codec is a digital mic codec provided by the
>  Embedded Controller (EC) and is controlled via a host-command interface.
> @@ -9,7 +9,6 @@ Documentation/devicetree/bindings/mfd/cros-ec.txt).
>  Required properties:
>  - compatible: Must contain "google,cros-ec-codec"
>  - #sound-dai-cells: Should be 1. The cell specifies number of DAIs.
> -- max-dmic-gain: A number for maximum gain in dB on digital microphone.
>  
>  Example:
>  
> @@ -21,6 +20,5 @@ cros-ec@0 {
>  	cros_ec_codec: ec-codec {
>  		compatible = "google,cros-ec-codec";
>  		#sound-dai-cells = <1>;
> -		max-dmic-gain = <43>;
>  	};
>  };
> diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
> index 3ca0fa9e92a7..21db0d4d4025 100644
> --- a/include/linux/platform_data/cros_ec_commands.h
> +++ b/include/linux/platform_data/cros_ec_commands.h
> @@ -4530,30 +4530,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;
>  };
>  
>  /*****************************************************************************/
> diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
> index c19c7fe42e2e..3d4f9e82d6e9 100644
> --- a/sound/soc/codecs/cros_ec_codec.c
> +++ b/sound/soc/codecs/cros_ec_codec.c
> @@ -65,18 +65,26 @@ static int dmic_get_gain(struct snd_kcontrol *kcontrol,
>  	struct cros_ec_codec_priv *priv =
>  		snd_soc_component_get_drvdata(component);
>  	struct ec_param_ec_codec_dmic p;
> -	struct ec_response_ec_codec_dmic_get_gain r;
> +	struct ec_response_ec_codec_dmic_get_gain_idx r;
>  	int ret;
>  
> -	p.cmd = EC_CODEC_DMIC_GET_GAIN;
> +	p.cmd = EC_CODEC_DMIC_GET_GAIN_IDX;
> +	p.get_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_0;
>  	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
>  				   (uint8_t *)&p, sizeof(p),
>  				   (uint8_t *)&r, sizeof(r));
>  	if (ret < 0)
>  		return ret;
> +	ucontrol->value.integer.value[0] = r.gain;
>  
> -	ucontrol->value.integer.value[0] = r.left;
> -	ucontrol->value.integer.value[1] = r.right;
> +	p.cmd = EC_CODEC_DMIC_GET_GAIN_IDX;
> +	p.get_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_1;
> +	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
> +				   (uint8_t *)&p, sizeof(p),
> +				   (uint8_t *)&r, sizeof(r));
> +	if (ret < 0)
> +		return ret;
> +	ucontrol->value.integer.value[1] = r.gain;
>  
>  	return 0;
>  }
> @@ -94,15 +102,24 @@ static int dmic_put_gain(struct snd_kcontrol *kcontrol,
>  	int left = ucontrol->value.integer.value[0];
>  	int right = ucontrol->value.integer.value[1];
>  	struct ec_param_ec_codec_dmic p;
> +	int ret;
>  
>  	if (left > max_dmic_gain || right > max_dmic_gain)
>  		return -EINVAL;
>  
>  	dev_dbg(component->dev, "set mic gain to %u, %u\n", left, right);
>  
> -	p.cmd = EC_CODEC_DMIC_SET_GAIN;
> -	p.set_gain_param.left = left;
> -	p.set_gain_param.right = right;
> +	p.cmd = EC_CODEC_DMIC_SET_GAIN_IDX;
> +	p.set_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_0;
> +	p.set_gain_idx_param.gain = left;
> +	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
> +				   (uint8_t *)&p, sizeof(p), NULL, 0);
> +	if (ret < 0)
> +		return ret;
> +
> +	p.cmd = EC_CODEC_DMIC_SET_GAIN_IDX;
> +	p.set_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_1;
> +	p.set_gain_idx_param.gain = right;
>  	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
>  				    (uint8_t *)&p, sizeof(p), NULL, 0);
>  }
> @@ -125,19 +142,27 @@ static int dmic_probe(struct snd_soc_component *component)
>  	struct cros_ec_codec_priv *priv =
>  		snd_soc_component_get_drvdata(component);
>  	struct device *dev = priv->dev;
> -	int ret, val;
>  	struct soc_mixer_control *control;
> +	struct ec_param_ec_codec_dmic p;
> +	struct ec_response_ec_codec_dmic_get_max_gain r;
> +	int ret;
>  
> -	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
> -	if (ret) {
> -		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
> -		return ret;
> +	p.cmd = EC_CODEC_DMIC_GET_MAX_GAIN;
> +
> +	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
> +				   (uint8_t *)&p, sizeof(p),
> +				   (uint8_t *)&r, sizeof(r));
> +	if (ret < 0) {
> +		dev_warn(dev, "get_max_gain() unsupported\n");
> +		return 0;
>  	}
>  
> +	dev_dbg(dev, "max gain = %d\n", r.max_gain);
> +
>  	control = (struct soc_mixer_control *)
>  		dmic_controls[DMIC_CTL_GAIN].private_value;
> -	control->max = val;
> -	control->platform_max = val;
> +	control->max = r.max_gain;
> +	control->platform_max = r.max_gain;
>  
>  	return snd_soc_add_component_controls(component,
>  			&dmic_controls[DMIC_CTL_GAIN], 1);
> -- 
> 2.23.0.700.g56cf767bdb-goog
> 

-- 
Benson Leung
Staff Software Engineer
Chrome OS Kernel
Google Inc.
bleung@google.com
Chromium OS Project
bleung@chromium.org

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 06/10] ASoC: dt-bindings: cros_ec_codec: add SHM bindings
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 06/10] ASoC: dt-bindings: cros_ec_codec: add SHM bindings Tzung-Bi Shih
  2019-10-14 17:23   ` Rob Herring
@ 2019-10-17  3:12   ` Benson Leung
  1 sibling, 0 replies; 29+ messages in thread
From: Benson Leung @ 2019-10-17  3:12 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	broonie, enric.balletbo, dgreid


[-- Attachment #1.1: Type: text/plain, Size: 2046 bytes --]

On Mon, Oct 14, 2019 at 06:20:18PM +0800, Tzung-Bi Shih wrote:
> - Add "reg" for binding to shared memory exposed by EC.
> - Add "memory-region" for binding to memory region shared by AP.
> 
> Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>

Acked-By: Benson Leung <bleung@chromium.org>


> ---
>  .../bindings/sound/google,cros-ec-codec.txt   | 20 +++++++++++++++++++
>  1 file changed, 20 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
> index 0ce9fafc78e2..8ca52dcc5572 100644
> --- a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
> +++ b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
> @@ -10,8 +10,26 @@ Required properties:
>  - compatible: Must contain "google,cros-ec-codec"
>  - #sound-dai-cells: Should be 1. The cell specifies number of DAIs.
>  
> +Optional properties:
> +- reg: Pysical base address and length of shared memory region from EC.
> +       It contains 3 unsigned 32-bit integer.  The first 2 integers
> +       combine to become an unsigned 64-bit physical address.  The last
> +       one integer is length of the shared memory.
> +- memory-region: Shared memory region to EC.  A "shared-dma-pool".  See
> +                 ../reserved-memory/reserved-memory.txt for details.
> +
>  Example:
>  
> +{
> +	...
> +
> +	reserved_mem: reserved_mem {
> +		compatible = "shared-dma-pool";
> +		reg = <0 0x52800000 0 0x100000>;
> +		no-map;
> +	};
> +}
> +
>  cros-ec@0 {
>  	compatible = "google,cros-ec-spi";
>  
> @@ -20,5 +38,7 @@ cros-ec@0 {
>  	cros_ec_codec: ec-codec {
>  		compatible = "google,cros-ec-codec";
>  		#sound-dai-cells = <1>;
> +		reg = <0x0 0x10500000 0x80000>;
> +		memory-region = <&reserved_mem>;
>  	};
>  };
> -- 
> 2.23.0.700.g56cf767bdb-goog
> 

-- 
Benson Leung
Staff Software Engineer
Chrome OS Kernel
Google Inc.
bleung@google.com
Chromium OS Project
bleung@chromium.org

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [alsa-devel] [PATCH v3 07/10] ASoC: cros_ec_codec: support WoV
  2019-10-15  6:49     ` Tzung-Bi Shih
@ 2019-10-17 11:43       ` Mark Brown
  0 siblings, 0 replies; 29+ messages in thread
From: Mark Brown @ 2019-10-17 11:43 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: Gwendal Grignou, devicetree, ALSA development, kbuild-all,
	kbuild test robot, Nicolas Boichat, robh+dt,
	Enric Balletbo i Serra, Benson Leung, Dylan Reid,
	Jimmy Cheng-Yi Chiang


[-- Attachment #1.1: Type: text/plain, Size: 598 bytes --]

On Tue, Oct 15, 2019 at 02:49:41PM +0800, Tzung-Bi Shih wrote:
> On Tue, Oct 15, 2019 at 9:34 AM kbuild test robot <lkp@intel.com> wrote:

> >       priv->ec_shm_addr = of_read_number(regaddr_p, 2);
> >                           ^~~~~~~~~~~~~~
> >                           wov_read_audio
> >    cc1: some warnings being treated as errors

> The error is caused by EC_CODEC=y but CONFIG_OF is not set:
> $ grep -e 'CONFIG_OF.*' -e 'EC_CODEC' config
> # CONFIG_OF is not set
> CONFIG_SND_SOC_CROS_EC_CODEC=y

If that can happen there's missing dependencies in Kconfig or missing
ifdefs in the code.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [alsa-devel] Applied "platform/chrome: cros_ec: remove unused EC feature" to the asoc tree
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature Tzung-Bi Shih
  2019-10-15 11:48   ` Mark Brown
  2019-10-17  2:25   ` Benson Leung
@ 2019-10-18 18:06   ` Mark Brown
  2 siblings, 0 replies; 29+ messages in thread
From: Mark Brown @ 2019-10-18 18:06 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	tzungbi, Mark Brown, enric.balletbo, bleung, dgreid

The patch

   platform/chrome: cros_ec: remove unused EC feature

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.5

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

From 036beb0e85f8772acb635c30df573876103b0c21 Mon Sep 17 00:00:00 2001
From: Tzung-Bi Shih <tzungbi@google.com>
Date: Mon, 14 Oct 2019 18:20:13 +0800
Subject: [PATCH] platform/chrome: cros_ec: remove unused EC feature

Remove unused EC_FEATURE_AUDIO_CODEC.

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
Acked-By: Benson Leung <bleung@chromium.org>
Link: https://lore.kernel.org/r/20191014180059.01.I374c311eaca0d47944a37b07acbe48fdb74f734d@changeid
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 include/linux/platform_data/cros_ec_commands.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 98415686cbfa..43b8f7dae4cc 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -1277,8 +1277,6 @@ enum ec_feature_code {
 	 * MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE.
 	 */
 	EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37,
-	/* EC supports audio codec. */
-	EC_FEATURE_AUDIO_CODEC = 38,
 	/* The MCU is a System Companion Processor (SCP). */
 	EC_FEATURE_SCP = 39,
 	/* The MCU is an Integrated Sensor Hub */
-- 
2.20.1

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] Applied "ASoC: cros_ec_codec: extract DMIC EC command from I2S RX" to the asoc tree
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 03/10] ASoC: cros_ec_codec: extract DMIC EC command from I2S RX Tzung-Bi Shih
  2019-10-17  2:48   ` Benson Leung
@ 2019-10-18 18:06   ` Mark Brown
  1 sibling, 0 replies; 29+ messages in thread
From: Mark Brown @ 2019-10-18 18:06 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	tzungbi, Mark Brown, enric.balletbo, bleung, dgreid

The patch

   ASoC: cros_ec_codec: extract DMIC EC command from I2S RX

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.5

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

From 8f731d4c92c2ef9434d4d7f84882c6429754164b Mon Sep 17 00:00:00 2001
From: Tzung-Bi Shih <tzungbi@google.com>
Date: Mon, 14 Oct 2019 18:20:15 +0800
Subject: [PATCH] ASoC: cros_ec_codec: extract DMIC EC command from I2S RX

Extract DMIC EC command from I2S RX.  Setting and getting
microphone gains is common features.

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
Acked-By: Benson Leung <bleung@chromium.org>
Link: https://lore.kernel.org/r/20191014180059.03.I93d9c65964f3c30f85a36d228e31150ff1917706@changeid
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/platform/chrome/cros_ec_trace.c       |  1 +
 .../linux/platform_data/cros_ec_commands.h    | 49 +++++++++++-----
 sound/soc/codecs/cros_ec_codec.c              | 57 ++++++++++---------
 3 files changed, 68 insertions(+), 39 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c
index 901850004b2b..e73bb6a8b00e 100644
--- a/drivers/platform/chrome/cros_ec_trace.c
+++ b/drivers/platform/chrome/cros_ec_trace.c
@@ -98,6 +98,7 @@
 	TRACE_SYMBOL(EC_CMD_SB_READ_BLOCK), \
 	TRACE_SYMBOL(EC_CMD_SB_WRITE_BLOCK), \
 	TRACE_SYMBOL(EC_CMD_BATTERY_VENDOR_PARAM), \
+	TRACE_SYMBOL(EC_CMD_EC_CODEC_DMIC), \
 	TRACE_SYMBOL(EC_CMD_EC_CODEC_I2S_RX), \
 	TRACE_SYMBOL(EC_CMD_REBOOT_EC), \
 	TRACE_SYMBOL(EC_CMD_GET_PANIC_INFO), \
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 261ac83bd007..58e460c015ef 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -4466,18 +4466,48 @@ enum mkbp_cec_event {
 
 /*****************************************************************************/
 
+/* Commands for DMIC on audio codec. */
+#define EC_CMD_EC_CODEC_DMIC 0x00BC
+
+enum ec_codec_dmic_subcmd {
+	EC_CODEC_DMIC_SET_GAIN = 0x0,
+	EC_CODEC_DMIC_GET_GAIN = 0x1,
+	EC_CODEC_DMIC_SUBCMD_COUNT,
+};
+
+struct __ec_align1 ec_param_ec_codec_dmic_set_gain {
+	uint8_t left;
+	uint8_t right;
+	uint8_t reserved[2];
+};
+
+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_align1 ec_response_ec_codec_dmic_get_gain {
+	uint8_t left;
+	uint8_t right;
+};
+
+/*****************************************************************************/
+
 /* Commands for I2S RX on audio codec. */
 
-#define EC_CMD_EC_CODEC_I2S_RX 0x00BC
+#define EC_CMD_EC_CODEC_I2S_RX 0x00BD
 
 enum ec_codec_i2s_rx_subcmd {
 	EC_CODEC_I2S_RX_ENABLE = 0x0,
 	EC_CODEC_I2S_RX_DISABLE = 0x1,
-	EC_CODEC_I2S_RX_SET_GAIN = 0x2,
-	EC_CODEC_I2S_RX_GET_GAIN = 0x3,
-	EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x4,
-	EC_CODEC_I2S_RX_SET_DAIFMT = 0x5,
-	EC_CODEC_I2S_RX_SET_BCLK = 0x6,
+	EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x2,
+	EC_CODEC_I2S_RX_SET_DAIFMT = 0x3,
+	EC_CODEC_I2S_RX_SET_BCLK = 0x4,
 	EC_CODEC_I2S_RX_SUBCMD_COUNT,
 };
 
@@ -4521,8 +4551,6 @@ struct __ec_align4 ec_param_ec_codec_i2s_rx {
 	union {
 		struct ec_param_ec_codec_i2s_rx_set_sample_depth
 				set_sample_depth_param;
-		struct ec_param_ec_codec_i2s_rx_set_gain
-				set_gain_param;
 		struct ec_param_ec_codec_i2s_rx_set_daifmt
 				set_daifmt_param;
 		struct ec_param_ec_codec_i2s_rx_set_bclk
@@ -4530,11 +4558,6 @@ struct __ec_align4 ec_param_ec_codec_i2s_rx {
 	};
 };
 
-struct __ec_align1 ec_response_ec_codec_i2s_rx_get_gain {
-	uint8_t left;
-	uint8_t right;
-};
-
 /*****************************************************************************/
 /* System commands */
 
diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
index 179fa77291cd..c19c7fe42e2e 100644
--- a/sound/soc/codecs/cros_ec_codec.c
+++ b/sound/soc/codecs/cros_ec_codec.c
@@ -64,12 +64,12 @@ static int dmic_get_gain(struct snd_kcontrol *kcontrol,
 		snd_soc_kcontrol_component(kcontrol);
 	struct cros_ec_codec_priv *priv =
 		snd_soc_component_get_drvdata(component);
-	struct ec_param_ec_codec_i2s_rx p;
-	struct ec_response_ec_codec_i2s_rx_get_gain r;
+	struct ec_param_ec_codec_dmic p;
+	struct ec_response_ec_codec_dmic_get_gain r;
 	int ret;
 
-	p.cmd = EC_CODEC_I2S_RX_GET_GAIN;
-	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+	p.cmd = EC_CODEC_DMIC_GET_GAIN;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 				   (uint8_t *)&p, sizeof(p),
 				   (uint8_t *)&r, sizeof(r));
 	if (ret < 0)
@@ -93,17 +93,17 @@ static int dmic_put_gain(struct snd_kcontrol *kcontrol,
 	int max_dmic_gain = control->max;
 	int left = ucontrol->value.integer.value[0];
 	int right = ucontrol->value.integer.value[1];
-	struct ec_param_ec_codec_i2s_rx p;
+	struct ec_param_ec_codec_dmic p;
 
 	if (left > max_dmic_gain || right > max_dmic_gain)
 		return -EINVAL;
 
 	dev_dbg(component->dev, "set mic gain to %u, %u\n", left, right);
 
-	p.cmd = EC_CODEC_I2S_RX_SET_GAIN;
+	p.cmd = EC_CODEC_DMIC_SET_GAIN;
 	p.set_gain_param.left = left;
 	p.set_gain_param.right = right;
-	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
 
@@ -120,6 +120,29 @@ static struct snd_kcontrol_new dmic_controls[] = {
 				   dmic_gain_tlv),
 };
 
+static int dmic_probe(struct snd_soc_component *component)
+{
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct device *dev = priv->dev;
+	int ret, val;
+	struct soc_mixer_control *control;
+
+	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
+	if (ret) {
+		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
+		return ret;
+	}
+
+	control = (struct soc_mixer_control *)
+		dmic_controls[DMIC_CTL_GAIN].private_value;
+	control->max = val;
+	control->platform_max = val;
+
+	return snd_soc_add_component_controls(component,
+			&dmic_controls[DMIC_CTL_GAIN], 1);
+}
+
 static int i2s_rx_hw_params(struct snd_pcm_substream *substream,
 			    struct snd_pcm_hw_params *params,
 			    struct snd_soc_dai *dai)
@@ -265,25 +288,7 @@ static struct snd_soc_dai_driver i2s_rx_dai_driver = {
 
 static int i2s_rx_probe(struct snd_soc_component *component)
 {
-	struct cros_ec_codec_priv *priv =
-		snd_soc_component_get_drvdata(component);
-	struct device *dev = priv->dev;
-	int ret, val;
-	struct soc_mixer_control *control;
-
-	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
-	if (ret) {
-		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
-		return ret;
-	}
-
-	control = (struct soc_mixer_control *)
-			dmic_controls[DMIC_CTL_GAIN].private_value;
-	control->max = val;
-	control->platform_max = val;
-
-	return snd_soc_add_component_controls(component,
-			&dmic_controls[DMIC_CTL_GAIN], 1);
+	return dmic_probe(component);
 }
 
 static const struct snd_soc_component_driver i2s_rx_component_driver = {
-- 
2.20.1

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [alsa-devel] Applied "ASoC: cros_ec_codec: refactor I2S RX" to the asoc tree
  2019-10-14 10:20 ` [alsa-devel] [PATCH v3 02/10] ASoC: cros_ec_codec: refactor I2S RX Tzung-Bi Shih
  2019-10-17  2:30   ` Benson Leung
@ 2019-10-18 18:06   ` Mark Brown
  1 sibling, 0 replies; 29+ messages in thread
From: Mark Brown @ 2019-10-18 18:06 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: gwendal, devicetree, alsa-devel, cychiang, drinkcat, robh+dt,
	tzungbi, Mark Brown, enric.balletbo, bleung, dgreid

The patch

   ASoC: cros_ec_codec: refactor I2S RX

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.5

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

From 727f1c71c780789aeb8f3da2596c65ae008d5d6c Mon Sep 17 00:00:00 2001
From: Tzung-Bi Shih <tzungbi@google.com>
Date: Mon, 14 Oct 2019 18:20:14 +0800
Subject: [PATCH] ASoC: cros_ec_codec: refactor I2S RX

Refactor by the following items:
- reformat copyright declaration
- use more specific name "i2s rx"
- use verbose symbol names to separate namespaces
- make some short functions inline
- remove unused TDM-related code

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
Acked-By: Benson Leung <bleung@chromium.org>
Link: https://lore.kernel.org/r/20191014180059.02.I43373b9a66dbb70196b3f216b3aa86111c410836@changeid
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/platform/chrome/cros_ec_trace.c       |   2 +-
 .../linux/platform_data/cros_ec_commands.h    | 120 ++---
 sound/soc/codecs/cros_ec_codec.c              | 502 +++++++-----------
 3 files changed, 251 insertions(+), 373 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c
index 6f80ff4532ae..901850004b2b 100644
--- a/drivers/platform/chrome/cros_ec_trace.c
+++ b/drivers/platform/chrome/cros_ec_trace.c
@@ -98,7 +98,7 @@
 	TRACE_SYMBOL(EC_CMD_SB_READ_BLOCK), \
 	TRACE_SYMBOL(EC_CMD_SB_WRITE_BLOCK), \
 	TRACE_SYMBOL(EC_CMD_BATTERY_VENDOR_PARAM), \
-	TRACE_SYMBOL(EC_CMD_CODEC_I2S), \
+	TRACE_SYMBOL(EC_CMD_EC_CODEC_I2S_RX), \
 	TRACE_SYMBOL(EC_CMD_REBOOT_EC), \
 	TRACE_SYMBOL(EC_CMD_GET_PANIC_INFO), \
 	TRACE_SYMBOL(EC_CMD_ACPI_READ), \
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 43b8f7dae4cc..261ac83bd007 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -4466,92 +4466,74 @@ enum mkbp_cec_event {
 
 /*****************************************************************************/
 
-/* Commands for I2S recording on audio codec. */
-
-#define EC_CMD_CODEC_I2S 0x00BC
-#define EC_WOV_I2S_SAMPLE_RATE 48000
-
-enum ec_codec_i2s_subcmd {
-	EC_CODEC_SET_SAMPLE_DEPTH = 0x0,
-	EC_CODEC_SET_GAIN = 0x1,
-	EC_CODEC_GET_GAIN = 0x2,
-	EC_CODEC_I2S_ENABLE = 0x3,
-	EC_CODEC_I2S_SET_CONFIG = 0x4,
-	EC_CODEC_I2S_SET_TDM_CONFIG = 0x5,
-	EC_CODEC_I2S_SET_BCLK = 0x6,
-	EC_CODEC_I2S_SUBCMD_COUNT = 0x7,
+/* Commands for I2S RX on audio codec. */
+
+#define EC_CMD_EC_CODEC_I2S_RX 0x00BC
+
+enum ec_codec_i2s_rx_subcmd {
+	EC_CODEC_I2S_RX_ENABLE = 0x0,
+	EC_CODEC_I2S_RX_DISABLE = 0x1,
+	EC_CODEC_I2S_RX_SET_GAIN = 0x2,
+	EC_CODEC_I2S_RX_GET_GAIN = 0x3,
+	EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x4,
+	EC_CODEC_I2S_RX_SET_DAIFMT = 0x5,
+	EC_CODEC_I2S_RX_SET_BCLK = 0x6,
+	EC_CODEC_I2S_RX_SUBCMD_COUNT,
 };
 
-enum ec_sample_depth_value {
-	EC_CODEC_SAMPLE_DEPTH_16 = 0,
-	EC_CODEC_SAMPLE_DEPTH_24 = 1,
+enum ec_codec_i2s_rx_sample_depth {
+	EC_CODEC_I2S_RX_SAMPLE_DEPTH_16 = 0x0,
+	EC_CODEC_I2S_RX_SAMPLE_DEPTH_24 = 0x1,
+	EC_CODEC_I2S_RX_SAMPLE_DEPTH_COUNT,
 };
 
-enum ec_i2s_config {
-	EC_DAI_FMT_I2S = 0,
-	EC_DAI_FMT_RIGHT_J = 1,
-	EC_DAI_FMT_LEFT_J = 2,
-	EC_DAI_FMT_PCM_A = 3,
-	EC_DAI_FMT_PCM_B = 4,
-	EC_DAI_FMT_PCM_TDM = 5,
+enum ec_codec_i2s_rx_daifmt {
+	EC_CODEC_I2S_RX_DAIFMT_I2S = 0x0,
+	EC_CODEC_I2S_RX_DAIFMT_RIGHT_J = 0x1,
+	EC_CODEC_I2S_RX_DAIFMT_LEFT_J = 0x2,
+	EC_CODEC_I2S_RX_DAIFMT_COUNT,
 };
 
-/*
- * For subcommand EC_CODEC_GET_GAIN.
- */
-struct __ec_align1 ec_codec_i2s_gain {
+struct __ec_align1 ec_param_ec_codec_i2s_rx_set_sample_depth {
+	uint8_t depth;
+	uint8_t reserved[3];
+};
+
+struct __ec_align1 ec_param_ec_codec_i2s_rx_set_gain {
 	uint8_t left;
 	uint8_t right;
+	uint8_t reserved[2];
 };
 
-struct __ec_todo_unpacked ec_param_codec_i2s_tdm {
-	int16_t ch0_delay; /* 0 to 496 */
-	int16_t ch1_delay; /* -1 to 496 */
-	uint8_t adjacent_to_ch0;
-	uint8_t adjacent_to_ch1;
+struct __ec_align1 ec_param_ec_codec_i2s_rx_set_daifmt {
+	uint8_t daifmt;
+	uint8_t reserved[3];
 };
 
-struct __ec_todo_packed ec_param_codec_i2s {
-	/* enum ec_codec_i2s_subcmd */
-	uint8_t cmd;
-	union {
-		/*
-		 * EC_CODEC_SET_SAMPLE_DEPTH
-		 * Value should be one of ec_sample_depth_value.
-		 */
-		uint8_t depth;
-
-		/*
-		 * EC_CODEC_SET_GAIN
-		 * Value should be 0~43 for both channels.
-		 */
-		struct ec_codec_i2s_gain gain;
-
-		/*
-		 * EC_CODEC_I2S_ENABLE
-		 * 1 to enable, 0 to disable.
-		 */
-		uint8_t i2s_enable;
-
-		/*
-		 * EC_CODEC_I2S_SET_CONFIG
-		 * Value should be one of ec_i2s_config.
-		 */
-		uint8_t i2s_config;
+struct __ec_align4 ec_param_ec_codec_i2s_rx_set_bclk {
+	uint32_t bclk;
+};
 
-		/*
-		 * EC_CODEC_I2S_SET_TDM_CONFIG
-		 * Value should be one of ec_i2s_config.
-		 */
-		struct ec_param_codec_i2s_tdm tdm_param;
+struct __ec_align4 ec_param_ec_codec_i2s_rx {
+	uint8_t cmd; /* enum ec_codec_i2s_rx_subcmd */
+	uint8_t reserved[3];
 
-		/*
-		 * EC_CODEC_I2S_SET_BCLK
-		 */
-		uint32_t bclk;
+	union {
+		struct ec_param_ec_codec_i2s_rx_set_sample_depth
+				set_sample_depth_param;
+		struct ec_param_ec_codec_i2s_rx_set_gain
+				set_gain_param;
+		struct ec_param_ec_codec_i2s_rx_set_daifmt
+				set_daifmt_param;
+		struct ec_param_ec_codec_i2s_rx_set_bclk
+				set_bclk_param;
 	};
 };
 
+struct __ec_align1 ec_response_ec_codec_i2s_rx_get_gain {
+	uint8_t left;
+	uint8_t right;
+};
 
 /*****************************************************************************/
 /* System commands */
diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
index 3c1bd24a1057..179fa77291cd 100644
--- a/sound/soc/codecs/cros_ec_codec.c
+++ b/sound/soc/codecs/cros_ec_codec.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Driver for ChromeOS Embedded Controller codec.
+ * Copyright 2019 Google, Inc.
+ *
+ * ChromeOS Embedded Controller codec driver.
  *
  * This driver uses the cros-ec interface to communicate with the ChromeOS
  * EC for audio function.
@@ -18,403 +20,297 @@
 #include <sound/soc.h>
 #include <sound/tlv.h>
 
-#define DRV_NAME "cros-ec-codec"
-
-/**
- * struct cros_ec_codec_data - ChromeOS EC codec driver data.
- * @dev:		Device structure used in sysfs.
- * @ec_device:		cros_ec_device structure to talk to the physical device.
- * @component:		Pointer to the component.
- * @max_dmic_gain:	Maximum gain in dB supported by EC codec.
- */
-struct cros_ec_codec_data {
+struct cros_ec_codec_priv {
 	struct device *dev;
 	struct cros_ec_device *ec_device;
-	struct snd_soc_component *component;
-	unsigned int max_dmic_gain;
 };
 
-static const DECLARE_TLV_DB_SCALE(ec_mic_gain_tlv, 0, 100, 0);
-
-static int ec_command_get_gain(struct snd_soc_component *component,
-			       struct ec_param_codec_i2s *param,
-			       struct ec_codec_i2s_gain *resp)
+static int send_ec_host_command(struct cros_ec_device *ec_dev, uint32_t cmd,
+				uint8_t *out, size_t outsize,
+				uint8_t *in, size_t insize)
 {
-	struct cros_ec_codec_data *codec_data =
-		snd_soc_component_get_drvdata(component);
-	struct cros_ec_device *ec_device = codec_data->ec_device;
-	u8 buffer[sizeof(struct cros_ec_command) +
-		  max(sizeof(struct ec_param_codec_i2s),
-		      sizeof(struct ec_codec_i2s_gain))];
-	struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
 	int ret;
+	struct cros_ec_command *msg;
+
+	msg = kmalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
 
 	msg->version = 0;
-	msg->command = EC_CMD_CODEC_I2S;
-	msg->outsize = sizeof(struct ec_param_codec_i2s);
-	msg->insize = sizeof(struct ec_codec_i2s_gain);
+	msg->command = cmd;
+	msg->outsize = outsize;
+	msg->insize = insize;
+
+	if (outsize)
+		memcpy(msg->data, out, outsize);
 
-	memcpy(msg->data, param, msg->outsize);
+	ret = cros_ec_cmd_xfer_status(ec_dev, msg);
+	if (ret < 0)
+		goto error;
 
-	ret = cros_ec_cmd_xfer_status(ec_device, msg);
-	if (ret > 0)
-		memcpy(resp, msg->data, msg->insize);
+	if (insize)
+		memcpy(in, msg->data, insize);
 
+	ret = 0;
+error:
+	kfree(msg);
 	return ret;
 }
 
-/*
- * Wrapper for EC command without response.
- */
-static int ec_command_no_resp(struct snd_soc_component *component,
-			      struct ec_param_codec_i2s *param)
+static int dmic_get_gain(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
 {
-	struct cros_ec_codec_data *codec_data =
+	struct snd_soc_component *component =
+		snd_soc_kcontrol_component(kcontrol);
+	struct cros_ec_codec_priv *priv =
 		snd_soc_component_get_drvdata(component);
-	struct cros_ec_device *ec_device = codec_data->ec_device;
-	u8 buffer[sizeof(struct cros_ec_command) +
-		  sizeof(struct ec_param_codec_i2s)];
-	struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
-
-	msg->version = 0;
-	msg->command = EC_CMD_CODEC_I2S;
-	msg->outsize = sizeof(struct ec_param_codec_i2s);
-	msg->insize = 0;
-
-	memcpy(msg->data, param, msg->outsize);
-
-	return cros_ec_cmd_xfer_status(ec_device, msg);
-}
-
-static int set_i2s_config(struct snd_soc_component *component,
-			  enum ec_i2s_config i2s_config)
-{
-	struct ec_param_codec_i2s param;
+	struct ec_param_ec_codec_i2s_rx p;
+	struct ec_response_ec_codec_i2s_rx_get_gain r;
+	int ret;
 
-	dev_dbg(component->dev, "%s set I2S format to %u\n", __func__,
-		i2s_config);
+	p.cmd = EC_CODEC_I2S_RX_GET_GAIN;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				   (uint8_t *)&p, sizeof(p),
+				   (uint8_t *)&r, sizeof(r));
+	if (ret < 0)
+		return ret;
 
-	param.cmd = EC_CODEC_I2S_SET_CONFIG;
-	param.i2s_config = i2s_config;
+	ucontrol->value.integer.value[0] = r.left;
+	ucontrol->value.integer.value[1] = r.right;
 
-	return ec_command_no_resp(component, &param);
+	return 0;
 }
 
-static int cros_ec_i2s_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+static int dmic_put_gain(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_component *component = dai->component;
-	enum ec_i2s_config i2s_config;
-
-	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-	case SND_SOC_DAIFMT_CBS_CFS:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-	case SND_SOC_DAIFMT_NB_NF:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_I2S:
-		i2s_config = EC_DAI_FMT_I2S;
-		break;
-
-	case SND_SOC_DAIFMT_RIGHT_J:
-		i2s_config = EC_DAI_FMT_RIGHT_J;
-		break;
-
-	case SND_SOC_DAIFMT_LEFT_J:
-		i2s_config = EC_DAI_FMT_LEFT_J;
-		break;
-
-	case SND_SOC_DAIFMT_DSP_A:
-		i2s_config = EC_DAI_FMT_PCM_A;
-		break;
-
-	case SND_SOC_DAIFMT_DSP_B:
-		i2s_config = EC_DAI_FMT_PCM_B;
-		break;
+	struct snd_soc_component *component =
+		snd_soc_kcontrol_component(kcontrol);
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct soc_mixer_control *control =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	int max_dmic_gain = control->max;
+	int left = ucontrol->value.integer.value[0];
+	int right = ucontrol->value.integer.value[1];
+	struct ec_param_ec_codec_i2s_rx p;
 
-	default:
+	if (left > max_dmic_gain || right > max_dmic_gain)
 		return -EINVAL;
-	}
 
-	return set_i2s_config(component, i2s_config);
-}
-
-static int set_i2s_sample_depth(struct snd_soc_component *component,
-				enum ec_sample_depth_value depth)
-{
-	struct ec_param_codec_i2s param;
-
-	dev_dbg(component->dev, "%s set depth to %u\n", __func__, depth);
-
-	param.cmd = EC_CODEC_SET_SAMPLE_DEPTH;
-	param.depth = depth;
+	dev_dbg(component->dev, "set mic gain to %u, %u\n", left, right);
 
-	return ec_command_no_resp(component, &param);
+	p.cmd = EC_CODEC_I2S_RX_SET_GAIN;
+	p.set_gain_param.left = left;
+	p.set_gain_param.right = right;
+	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
 
-static int set_i2s_bclk(struct snd_soc_component *component, uint32_t bclk)
-{
-	struct ec_param_codec_i2s param;
-
-	dev_dbg(component->dev, "%s set i2s bclk to %u\n", __func__, bclk);
+static const DECLARE_TLV_DB_SCALE(dmic_gain_tlv, 0, 100, 0);
 
-	param.cmd = EC_CODEC_I2S_SET_BCLK;
-	param.bclk = bclk;
+enum {
+	DMIC_CTL_GAIN = 0,
+};
 
-	return ec_command_no_resp(component, &param);
-}
+static struct snd_kcontrol_new dmic_controls[] = {
+	[DMIC_CTL_GAIN] =
+		SOC_DOUBLE_EXT_TLV("EC Mic Gain", SND_SOC_NOPM, SND_SOC_NOPM,
+				   0, 0, 0, dmic_get_gain, dmic_put_gain,
+				   dmic_gain_tlv),
+};
 
-static int cros_ec_i2s_hw_params(struct snd_pcm_substream *substream,
-				 struct snd_pcm_hw_params *params,
-				 struct snd_soc_dai *dai)
+static int i2s_rx_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
 {
 	struct snd_soc_component *component = dai->component;
-	unsigned int rate, bclk;
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct ec_param_ec_codec_i2s_rx p;
+	enum ec_codec_i2s_rx_sample_depth depth;
 	int ret;
 
-	rate = params_rate(params);
-	if (rate != 48000)
+	if (params_rate(params) != 48000)
 		return -EINVAL;
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
-		ret = set_i2s_sample_depth(component, EC_CODEC_SAMPLE_DEPTH_16);
+		depth = EC_CODEC_I2S_RX_SAMPLE_DEPTH_16;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
-		ret = set_i2s_sample_depth(component, EC_CODEC_SAMPLE_DEPTH_24);
+		depth = EC_CODEC_I2S_RX_SAMPLE_DEPTH_24;
 		break;
 	default:
 		return -EINVAL;
 	}
-	if (ret < 0)
-		return ret;
-
-	bclk = snd_soc_params_to_bclk(params);
-	return set_i2s_bclk(component, bclk);
-}
 
-static const struct snd_soc_dai_ops cros_ec_i2s_dai_ops = {
-	.hw_params = cros_ec_i2s_hw_params,
-	.set_fmt = cros_ec_i2s_set_dai_fmt,
-};
+	dev_dbg(component->dev, "set depth to %u\n", depth);
 
-static struct snd_soc_dai_driver cros_ec_dai[] = {
-	{
-		.name = "cros_ec_codec I2S",
-		.id = 0,
-		.capture = {
-			.stream_name = "I2S Capture",
-			.channels_min = 2,
-			.channels_max = 2,
-			.rates = SNDRV_PCM_RATE_48000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE |
-				   SNDRV_PCM_FMTBIT_S24_LE,
-		},
-		.ops = &cros_ec_i2s_dai_ops,
-	}
-};
-
-static int get_ec_mic_gain(struct snd_soc_component *component,
-			   u8 *left, u8 *right)
-{
-	struct ec_param_codec_i2s param;
-	struct ec_codec_i2s_gain resp;
-	int ret;
-
-	param.cmd = EC_CODEC_GET_GAIN;
-
-	ret = ec_command_get_gain(component, &param, &resp);
+	p.cmd = EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH;
+	p.set_sample_depth_param.depth = depth;
+	ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				   (uint8_t *)&p, sizeof(p), NULL, 0);
 	if (ret < 0)
 		return ret;
 
-	*left = resp.left;
-	*right = resp.right;
-
-	return 0;
-}
-
-static int mic_gain_get(struct snd_kcontrol *kcontrol,
-			struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_component *component =
-		snd_soc_kcontrol_component(kcontrol);
-	u8 left, right;
-	int ret;
-
-	ret = get_ec_mic_gain(component, &left, &right);
-	if (ret)
-		return ret;
-
-	ucontrol->value.integer.value[0] = left;
-	ucontrol->value.integer.value[1] = right;
-
-	return 0;
-}
-
-static int set_ec_mic_gain(struct snd_soc_component *component,
-			   u8 left, u8 right)
-{
-	struct ec_param_codec_i2s param;
-
-	dev_dbg(component->dev, "%s set mic gain to %u, %u\n",
-		__func__, left, right);
+	dev_dbg(component->dev, "set bclk to %u\n",
+		snd_soc_params_to_bclk(params));
 
-	param.cmd = EC_CODEC_SET_GAIN;
-	param.gain.left = left;
-	param.gain.right = right;
-
-	return ec_command_no_resp(component, &param);
+	p.cmd = EC_CODEC_I2S_RX_SET_BCLK;
+	p.set_bclk_param.bclk = snd_soc_params_to_bclk(params);
+	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
 
-static int mic_gain_put(struct snd_kcontrol *kcontrol,
-			struct snd_ctl_elem_value *ucontrol)
+static int i2s_rx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-	struct snd_soc_component *component =
-		snd_soc_kcontrol_component(kcontrol);
-	struct cros_ec_codec_data *codec_data =
+	struct snd_soc_component *component = dai->component;
+	struct cros_ec_codec_priv *priv =
 		snd_soc_component_get_drvdata(component);
-	int left = ucontrol->value.integer.value[0];
-	int right = ucontrol->value.integer.value[1];
-	unsigned int max_dmic_gain = codec_data->max_dmic_gain;
+	struct ec_param_ec_codec_i2s_rx p;
+	enum ec_codec_i2s_rx_daifmt daifmt;
 
-	if (left > max_dmic_gain || right > max_dmic_gain)
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
 		return -EINVAL;
+	}
 
-	return set_ec_mic_gain(component, (u8)left, (u8)right);
-}
-
-static struct snd_kcontrol_new mic_gain_control =
-	SOC_DOUBLE_EXT_TLV("EC Mic Gain", SND_SOC_NOPM, SND_SOC_NOPM, 0, 0, 0,
-			   mic_gain_get, mic_gain_put, ec_mic_gain_tlv);
-
-static int enable_i2s(struct snd_soc_component *component, int enable)
-{
-	struct ec_param_codec_i2s param;
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	default:
+		return -EINVAL;
+	}
 
-	dev_dbg(component->dev, "%s set i2s to %u\n", __func__, enable);
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		daifmt = EC_CODEC_I2S_RX_DAIFMT_I2S;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		daifmt = EC_CODEC_I2S_RX_DAIFMT_RIGHT_J;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		daifmt = EC_CODEC_I2S_RX_DAIFMT_LEFT_J;
+		break;
+	default:
+		return -EINVAL;
+	}
 
-	param.cmd = EC_CODEC_I2S_ENABLE;
-	param.i2s_enable = enable;
+	dev_dbg(component->dev, "set format to %u\n", daifmt);
 
-	return ec_command_no_resp(component, &param);
+	p.cmd = EC_CODEC_I2S_RX_SET_DAIFMT;
+	p.set_daifmt_param.daifmt = daifmt;
+	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
 
-static int cros_ec_i2s_enable_event(struct snd_soc_dapm_widget *w,
-				    struct snd_kcontrol *kcontrol, int event)
+static const struct snd_soc_dai_ops i2s_rx_dai_ops = {
+	.hw_params = i2s_rx_hw_params,
+	.set_fmt = i2s_rx_set_fmt,
+};
+
+static int i2s_rx_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_component *component =
 		snd_soc_dapm_to_component(w->dapm);
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct ec_param_ec_codec_i2s_rx p;
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		dev_dbg(component->dev,
-			"%s got SND_SOC_DAPM_PRE_PMU event\n", __func__);
-		return enable_i2s(component, 1);
-
+		dev_dbg(component->dev, "enable I2S RX\n");
+		p.cmd = EC_CODEC_I2S_RX_ENABLE;
+		break;
 	case SND_SOC_DAPM_PRE_PMD:
-		dev_dbg(component->dev,
-			"%s got SND_SOC_DAPM_PRE_PMD event\n", __func__);
-		return enable_i2s(component, 0);
+		dev_dbg(component->dev, "disable I2S RX\n");
+		p.cmd = EC_CODEC_I2S_RX_DISABLE;
+		break;
+	default:
+		return 0;
 	}
 
-	return 0;
+	return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+				    (uint8_t *)&p, sizeof(p), NULL, 0);
 }
 
-/*
- * The goal of this DAPM route is to turn on/off I2S using EC
- * host command when capture stream is started/stopped.
- */
-static const struct snd_soc_dapm_widget cros_ec_codec_dapm_widgets[] = {
+static struct snd_soc_dapm_widget i2s_rx_dapm_widgets[] = {
 	SND_SOC_DAPM_INPUT("DMIC"),
-
-	/*
-	 * Control EC to enable/disable I2S.
-	 */
-	SND_SOC_DAPM_SUPPLY("I2S Enable", SND_SOC_NOPM,
-			    0, 0, cros_ec_i2s_enable_event,
+	SND_SOC_DAPM_SUPPLY("I2S RX Enable", SND_SOC_NOPM, 0, 0, i2s_rx_event,
 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_AIF_OUT("I2S RX", "I2S Capture", 0, SND_SOC_NOPM, 0, 0),
+};
 
-	SND_SOC_DAPM_AIF_OUT("I2STX", "I2S Capture", 0, SND_SOC_NOPM, 0, 0),
+static struct snd_soc_dapm_route i2s_rx_dapm_routes[] = {
+	{"I2S RX", NULL, "DMIC"},
+	{"I2S RX", NULL, "I2S RX Enable"},
 };
 
-static const struct snd_soc_dapm_route cros_ec_codec_dapm_routes[] = {
-	{ "I2STX", NULL, "DMIC" },
-	{ "I2STX", NULL, "I2S Enable" },
+static struct snd_soc_dai_driver i2s_rx_dai_driver = {
+	.name = "EC Codec I2S RX",
+	.capture = {
+		.stream_name = "I2S Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE |
+			SNDRV_PCM_FMTBIT_S24_LE,
+	},
+	.ops = &i2s_rx_dai_ops,
 };
 
-/*
- * Read maximum gain from device property and set it to mixer control.
- */
-static int cros_ec_set_gain_range(struct device *dev)
+static int i2s_rx_probe(struct snd_soc_component *component)
 {
+	struct cros_ec_codec_priv *priv =
+		snd_soc_component_get_drvdata(component);
+	struct device *dev = priv->dev;
+	int ret, val;
 	struct soc_mixer_control *control;
-	struct cros_ec_codec_data *codec_data = dev_get_drvdata(dev);
-	int rc;
 
-	rc = device_property_read_u32(dev, "max-dmic-gain",
-				      &codec_data->max_dmic_gain);
-	if (rc)
-		return rc;
+	ret = device_property_read_u32(dev, "max-dmic-gain", &val);
+	if (ret) {
+		dev_err(dev, "Failed to read 'max-dmic-gain'\n");
+		return ret;
+	}
 
 	control = (struct soc_mixer_control *)
-				mic_gain_control.private_value;
-	control->max = codec_data->max_dmic_gain;
-	control->platform_max = codec_data->max_dmic_gain;
+			dmic_controls[DMIC_CTL_GAIN].private_value;
+	control->max = val;
+	control->platform_max = val;
 
-	return 0;
-}
-
-static int cros_ec_codec_probe(struct snd_soc_component *component)
-{
-	int rc;
-
-	struct cros_ec_codec_data *codec_data =
-		snd_soc_component_get_drvdata(component);
-
-	rc = cros_ec_set_gain_range(codec_data->dev);
-	if (rc)
-		return rc;
-
-	return snd_soc_add_component_controls(component, &mic_gain_control, 1);
+	return snd_soc_add_component_controls(component,
+			&dmic_controls[DMIC_CTL_GAIN], 1);
 }
 
-static const struct snd_soc_component_driver cros_ec_component_driver = {
-	.probe			= cros_ec_codec_probe,
-	.dapm_widgets		= cros_ec_codec_dapm_widgets,
-	.num_dapm_widgets	= ARRAY_SIZE(cros_ec_codec_dapm_widgets),
-	.dapm_routes		= cros_ec_codec_dapm_routes,
-	.num_dapm_routes	= ARRAY_SIZE(cros_ec_codec_dapm_routes),
+static const struct snd_soc_component_driver i2s_rx_component_driver = {
+	.probe			= i2s_rx_probe,
+	.dapm_widgets		= i2s_rx_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(i2s_rx_dapm_widgets),
+	.dapm_routes		= i2s_rx_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(i2s_rx_dapm_routes),
 };
 
-/*
- * Platform device and platform driver fro cros-ec-codec.
- */
-static int cros_ec_codec_platform_probe(struct platform_device *pd)
+static int cros_ec_codec_platform_probe(struct platform_device *pdev)
 {
-	struct device *dev = &pd->dev;
-	struct cros_ec_device *ec_device = dev_get_drvdata(pd->dev.parent);
-	struct cros_ec_codec_data *codec_data;
+	struct device *dev = &pdev->dev;
+	struct cros_ec_device *ec_device = dev_get_drvdata(pdev->dev.parent);
+	struct cros_ec_codec_priv *priv;
 
-	codec_data = devm_kzalloc(dev, sizeof(struct cros_ec_codec_data),
-				  GFP_KERNEL);
-	if (!codec_data)
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
 
-	codec_data->dev = dev;
-	codec_data->ec_device = ec_device;
+	priv->dev = dev;
+	priv->ec_device = ec_device;
 
-	platform_set_drvdata(pd, codec_data);
+	platform_set_drvdata(pdev, priv);
 
-	return devm_snd_soc_register_component(dev, &cros_ec_component_driver,
-					  cros_ec_dai, ARRAY_SIZE(cros_ec_dai));
+	return devm_snd_soc_register_component(dev, &i2s_rx_component_driver,
+					       &i2s_rx_dai_driver, 1);
 }
 
 #ifdef CONFIG_OF
@@ -427,7 +323,7 @@ MODULE_DEVICE_TABLE(of, cros_ec_codec_of_match);
 
 static struct platform_driver cros_ec_codec_platform_driver = {
 	.driver = {
-		.name = DRV_NAME,
+		.name = "cros-ec-codec",
 		.of_match_table = of_match_ptr(cros_ec_codec_of_match),
 	},
 	.probe = cros_ec_codec_platform_probe,
@@ -438,4 +334,4 @@ module_platform_driver(cros_ec_codec_platform_driver);
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("ChromeOS EC codec driver");
 MODULE_AUTHOR("Cheng-Yi Chiang <cychiang@chromium.org>");
-MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS("platform:cros-ec-codec");
-- 
2.20.1

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2019-10-18 18:16 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-14 10:20 [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: support WoV Tzung-Bi Shih
2019-10-14 10:20 ` [alsa-devel] [PATCH v3 01/10] platform/chrome: cros_ec: remove unused EC feature Tzung-Bi Shih
2019-10-15 11:48   ` Mark Brown
2019-10-15 15:37     ` Tzung-Bi Shih
2019-10-17  2:25   ` Benson Leung
2019-10-18 18:06   ` [alsa-devel] Applied "platform/chrome: cros_ec: remove unused EC feature" to the asoc tree Mark Brown
2019-10-14 10:20 ` [alsa-devel] [PATCH v3 02/10] ASoC: cros_ec_codec: refactor I2S RX Tzung-Bi Shih
2019-10-17  2:30   ` Benson Leung
2019-10-18 18:06   ` [alsa-devel] Applied "ASoC: cros_ec_codec: refactor I2S RX" to the asoc tree Mark Brown
2019-10-14 10:20 ` [alsa-devel] [PATCH v3 03/10] ASoC: cros_ec_codec: extract DMIC EC command from I2S RX Tzung-Bi Shih
2019-10-17  2:48   ` Benson Leung
2019-10-18 18:06   ` [alsa-devel] Applied "ASoC: cros_ec_codec: extract DMIC EC command from I2S RX" to the asoc tree Mark Brown
2019-10-14 10:20 ` [alsa-devel] [PATCH v3 04/10] platform/chrome: cros_ec: add common commands for EC codec Tzung-Bi Shih
2019-10-17  2:57   ` Benson Leung
2019-10-14 10:20 ` [alsa-devel] [PATCH v3 05/10] ASoC: cros_ec_codec: read max DMIC gain from " Tzung-Bi Shih
2019-10-17  3:07   ` Benson Leung
2019-10-14 10:20 ` [alsa-devel] [PATCH v3 06/10] ASoC: dt-bindings: cros_ec_codec: add SHM bindings Tzung-Bi Shih
2019-10-14 17:23   ` Rob Herring
2019-10-17  3:12   ` Benson Leung
2019-10-14 10:20 ` [alsa-devel] [PATCH v3 07/10] ASoC: cros_ec_codec: support WoV Tzung-Bi Shih
2019-10-15  1:34   ` kbuild test robot
2019-10-15  6:49     ` Tzung-Bi Shih
2019-10-17 11:43       ` Mark Brown
2019-10-15  3:20   ` kbuild test robot
2019-10-14 10:20 ` [alsa-devel] [PATCH v3 08/10] ASoC: mediatek: mt6358: " Tzung-Bi Shih
2019-10-14 10:20 ` [alsa-devel] [PATCH v3 09/10] ASoC: dt-bindings: mt8183: add ec-codec Tzung-Bi Shih
2019-10-14 17:23   ` Rob Herring
2019-10-14 10:20 ` [alsa-devel] [PATCH v3 10/10] ASoC: mediatek: mt8183: support WoV Tzung-Bi Shih
2019-10-14 12:34 ` [alsa-devel] [PATCH v3 00/10] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: " Tzung-Bi Shih

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).