linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers
@ 2019-01-17 12:46 Viorel Suman
  2019-01-17 12:46 ` [PATCH v3 1/4] ASoC: fsl: Add Audio Mixer CPU DAI driver Viorel Suman
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Viorel Suman @ 2019-01-17 12:46 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Jaroslav Kysela, Takashi Iwai, Timur Tabi, Nicolin Chen,
	Xiubo Li, Fabio Estevam, Viorel Suman, S.j. Wang, Daniel Baluta,
	Cosmin Samoila
  Cc: alsa-devel, devicetree, linux-kernel, linuxppc-dev, dl-linux-imx,
	Viorel Suman

The patchset adds NXP Audio Mixer (AUDMIX) device and machine
drivers and related DT bindings documentation.

Changes since V2:
1. Moved "dais" node from machine driver DTS node to device driver DTS node
  as suggested by Rob.

Changes since V1:
1. Original patch split into distinct patches for the device driver and
  DT binding documentation.
2. Replaced AMIX with AUDMIX in both code and file names as it looks more
  RM-compliant.
3. Removed polarity control from CPU DAI driver as suggested by Nicolin.
4. Added machine driver and related DT binding documentation.

Viorel Suman (4):
  ASoC: fsl: Add Audio Mixer CPU DAI driver
  ASoC: add fsl_audmix DT binding documentation
  ASoC: fsl: Add Audio Mixer machine driver
  ASoC: add imx-audmix DT binding documentation

 .../devicetree/bindings/sound/fsl,audmix.txt       |  50 ++
 .../devicetree/bindings/sound/imx-audmix.txt       |  18 +
 sound/soc/fsl/Kconfig                              |  16 +
 sound/soc/fsl/Makefile                             |   5 +
 sound/soc/fsl/fsl_audmix.c                         | 551 +++++++++++++++++++++
 sound/soc/fsl/fsl_audmix.h                         | 102 ++++
 sound/soc/fsl/imx-audmix.c                         | 334 +++++++++++++
 7 files changed, 1076 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,audmix.txt
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audmix.txt
 create mode 100644 sound/soc/fsl/fsl_audmix.c
 create mode 100644 sound/soc/fsl/fsl_audmix.h
 create mode 100644 sound/soc/fsl/imx-audmix.c

-- 
2.7.4


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

* [PATCH v3 1/4] ASoC: fsl: Add Audio Mixer CPU DAI driver
  2019-01-17 12:46 [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Viorel Suman
@ 2019-01-17 12:46 ` Viorel Suman
  2019-01-17 12:46 ` [PATCH v3 2/4] ASoC: add fsl_audmix DT binding documentation Viorel Suman
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Viorel Suman @ 2019-01-17 12:46 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Jaroslav Kysela, Takashi Iwai, Timur Tabi, Nicolin Chen,
	Xiubo Li, Fabio Estevam, Viorel Suman, S.j. Wang, Daniel Baluta,
	Cosmin Samoila
  Cc: alsa-devel, devicetree, linux-kernel, linuxppc-dev, dl-linux-imx,
	Viorel Suman

This patch implements Audio Mixer CPU DAI driver for NXP iMX8 SOCs.
The Audio Mixer is a on-chip functional module that allows mixing of
two audio streams into a single audio stream.

Audio Mixer datasheet is available here:
https://www.nxp.com/docs/en/reference-manual/IMX8DQXPRM.pdf

Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
---
 sound/soc/fsl/Kconfig      |   7 +
 sound/soc/fsl/Makefile     |   3 +
 sound/soc/fsl/fsl_audmix.c | 551 +++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/fsl/fsl_audmix.h | 102 +++++++++
 4 files changed, 663 insertions(+)
 create mode 100644 sound/soc/fsl/fsl_audmix.c
 create mode 100644 sound/soc/fsl/fsl_audmix.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 7b1d997..0af2e056 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -24,6 +24,13 @@ config SND_SOC_FSL_SAI
 	  This option is only useful for out-of-tree drivers since
 	  in-tree drivers select it automatically.
 
+config SND_SOC_FSL_AUDMIX
+	tristate "Audio Mixer (AUDMIX) module support"
+	select REGMAP_MMIO
+	help
+	  Say Y if you want to add Audio Mixer (AUDMIX)
+	  support for the NXP iMX CPUs.
+
 config SND_SOC_FSL_SSI
 	tristate "Synchronous Serial Interface module (SSI) support"
 	select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 3c0ff31..4172d5a 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -12,6 +12,7 @@ snd-soc-p1022-rdk-objs := p1022_rdk.o
 obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
 
 # Freescale SSI/DMA/SAI/SPDIF Support
+snd-soc-fsl-audmix-objs := fsl_audmix.o
 snd-soc-fsl-asoc-card-objs := fsl-asoc-card.o
 snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o
 snd-soc-fsl-sai-objs := fsl_sai.o
@@ -22,6 +23,8 @@ snd-soc-fsl-esai-objs := fsl_esai.o
 snd-soc-fsl-micfil-objs := fsl_micfil.o
 snd-soc-fsl-utils-objs := fsl_utils.o
 snd-soc-fsl-dma-objs := fsl_dma.o
+
+obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o
 obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o
 obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o
 obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c
new file mode 100644
index 0000000..f1267e5
--- /dev/null
+++ b/sound/soc/fsl/fsl_audmix.c
@@ -0,0 +1,551 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * NXP AUDMIX ALSA SoC Digital Audio Interface (DAI) driver
+ *
+ * Copyright 2017 NXP
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+
+#include "fsl_audmix.h"
+
+#define SOC_ENUM_SINGLE_S(xreg, xshift, xtexts) \
+	SOC_ENUM_SINGLE(xreg, xshift, ARRAY_SIZE(xtexts), xtexts)
+
+static const char
+	*tdm_sel[] = { "TDM1", "TDM2", },
+	*mode_sel[] = { "Disabled", "TDM1", "TDM2", "Mixed", },
+	*width_sel[] = { "16b", "18b", "20b", "24b", "32b", },
+	*endis_sel[] = { "Disabled", "Enabled", },
+	*updn_sel[] = { "Downward", "Upward", },
+	*mask_sel[] = { "Unmask", "Mask", };
+
+static const struct soc_enum fsl_audmix_enum[] = {
+/* FSL_AUDMIX_CTR enums */
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_CTR, FSL_AUDMIX_CTR_MIXCLK_SHIFT, tdm_sel),
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_CTR, FSL_AUDMIX_CTR_OUTSRC_SHIFT, mode_sel),
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_CTR, FSL_AUDMIX_CTR_OUTWIDTH_SHIFT, width_sel),
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_CTR, FSL_AUDMIX_CTR_MASKRTDF_SHIFT, mask_sel),
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_CTR, FSL_AUDMIX_CTR_MASKCKDF_SHIFT, mask_sel),
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_CTR, FSL_AUDMIX_CTR_SYNCMODE_SHIFT, endis_sel),
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_CTR, FSL_AUDMIX_CTR_SYNCSRC_SHIFT, tdm_sel),
+/* FSL_AUDMIX_ATCR0 enums */
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_ATCR0, 0, endis_sel),
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_ATCR0, 1, updn_sel),
+/* FSL_AUDMIX_ATCR1 enums */
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_ATCR1, 0, endis_sel),
+SOC_ENUM_SINGLE_S(FSL_AUDMIX_ATCR1, 1, updn_sel),
+};
+
+struct fsl_audmix_state {
+	u8 tdms;
+	u8 clk;
+	char msg[64];
+};
+
+static const struct fsl_audmix_state prms[4][4] = {{
+	/* DIS->DIS, do nothing */
+	{ .tdms = 0, .clk = 0, .msg = "" },
+	/* DIS->TDM1*/
+	{ .tdms = 1, .clk = 1, .msg = "DIS->TDM1: TDM1 not started!\n" },
+	/* DIS->TDM2*/
+	{ .tdms = 2, .clk = 2, .msg = "DIS->TDM2: TDM2 not started!\n" },
+	/* DIS->MIX */
+	{ .tdms = 3, .clk = 0, .msg = "DIS->MIX: Please start both TDMs!\n" }
+}, {	/* TDM1->DIS */
+	{ .tdms = 1, .clk = 0, .msg = "TDM1->DIS: TDM1 not started!\n" },
+	/* TDM1->TDM1, do nothing */
+	{ .tdms = 0, .clk = 0, .msg = "" },
+	/* TDM1->TDM2 */
+	{ .tdms = 3, .clk = 2, .msg = "TDM1->TDM2: Please start both TDMs!\n" },
+	/* TDM1->MIX */
+	{ .tdms = 3, .clk = 0, .msg = "TDM1->MIX: Please start both TDMs!\n" }
+}, {	/* TDM2->DIS */
+	{ .tdms = 2, .clk = 0, .msg = "TDM2->DIS: TDM2 not started!\n" },
+	/* TDM2->TDM1 */
+	{ .tdms = 3, .clk = 1, .msg = "TDM2->TDM1: Please start both TDMs!\n" },
+	/* TDM2->TDM2, do nothing */
+	{ .tdms = 0, .clk = 0, .msg = "" },
+	/* TDM2->MIX */
+	{ .tdms = 3, .clk = 0, .msg = "TDM2->MIX: Please start both TDMs!\n" }
+}, {	/* MIX->DIS */
+	{ .tdms = 3, .clk = 0, .msg = "MIX->DIS: Please start both TDMs!\n" },
+	/* MIX->TDM1 */
+	{ .tdms = 3, .clk = 1, .msg = "MIX->TDM1: Please start both TDMs!\n" },
+	/* MIX->TDM2 */
+	{ .tdms = 3, .clk = 2, .msg = "MIX->TDM2: Please start both TDMs!\n" },
+	/* MIX->MIX, do nothing */
+	{ .tdms = 0, .clk = 0, .msg = "" }
+}, };
+
+static int fsl_audmix_state_trans(struct snd_soc_component *comp,
+				  unsigned int *mask, unsigned int *ctr,
+				  const struct fsl_audmix_state prm)
+{
+	struct fsl_audmix *priv = snd_soc_component_get_drvdata(comp);
+	/* Enforce all required TDMs are started */
+	if ((priv->tdms & prm.tdms) != prm.tdms) {
+		dev_dbg(comp->dev, prm.msg);
+		return -EINVAL;
+	}
+
+	switch (prm.clk) {
+	case 1:
+	case 2:
+		/* Set mix clock */
+		(*mask) |= FSL_AUDMIX_CTR_MIXCLK_MASK;
+		(*ctr)  |= FSL_AUDMIX_CTR_MIXCLK(prm.clk - 1);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int fsl_audmix_put_mix_clk_src(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+	struct fsl_audmix *priv = snd_soc_component_get_drvdata(comp);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned int *item = ucontrol->value.enumerated.item;
+	unsigned int reg_val, val, mix_clk;
+	int ret = 0;
+
+	/* Get current state */
+	ret = snd_soc_component_read(comp, FSL_AUDMIX_CTR, &reg_val);
+	if (ret)
+		return ret;
+
+	mix_clk = ((reg_val & FSL_AUDMIX_CTR_MIXCLK_MASK)
+			>> FSL_AUDMIX_CTR_MIXCLK_SHIFT);
+	val = snd_soc_enum_item_to_val(e, item[0]);
+
+	dev_dbg(comp->dev, "TDMs=x%08x, val=x%08x\n", priv->tdms, val);
+
+	/**
+	 * Ensure the current selected mixer clock is available
+	 * for configuration propagation
+	 */
+	if (!(priv->tdms & BIT(mix_clk))) {
+		dev_err(comp->dev,
+			"Started TDM%d needed for config propagation!\n",
+			mix_clk + 1);
+		return -EINVAL;
+	}
+
+	if (!(priv->tdms & BIT(val))) {
+		dev_err(comp->dev,
+			"The selected clock source has no TDM%d enabled!\n",
+			val + 1);
+		return -EINVAL;
+	}
+
+	return snd_soc_put_enum_double(kcontrol, ucontrol);
+}
+
+static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+	struct fsl_audmix *priv = snd_soc_component_get_drvdata(comp);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned int *item = ucontrol->value.enumerated.item;
+	u32 out_src, mix_clk;
+	unsigned int reg_val, val, mask = 0, ctr = 0;
+	int ret = 0;
+
+	/* Get current state */
+	ret = snd_soc_component_read(comp, FSL_AUDMIX_CTR, &reg_val);
+	if (ret)
+		return ret;
+
+	/* "From" state */
+	out_src = ((reg_val & FSL_AUDMIX_CTR_OUTSRC_MASK)
+			>> FSL_AUDMIX_CTR_OUTSRC_SHIFT);
+	mix_clk = ((reg_val & FSL_AUDMIX_CTR_MIXCLK_MASK)
+			>> FSL_AUDMIX_CTR_MIXCLK_SHIFT);
+
+	/* "To" state */
+	val = snd_soc_enum_item_to_val(e, item[0]);
+
+	dev_dbg(comp->dev, "TDMs=x%08x, val=x%08x\n", priv->tdms, val);
+
+	/* Check if state is changing ... */
+	if (out_src == val)
+		return 0;
+	/**
+	 * Ensure the current selected mixer clock is available
+	 * for configuration propagation
+	 */
+	if (!(priv->tdms & BIT(mix_clk))) {
+		dev_err(comp->dev,
+			"Started TDM%d needed for config propagation!\n",
+			mix_clk + 1);
+		return -EINVAL;
+	}
+
+	/* Check state transition constraints */
+	ret = fsl_audmix_state_trans(comp, &mask, &ctr, prms[out_src][val]);
+	if (ret)
+		return ret;
+
+	/* Complete transition to new state */
+	mask |= FSL_AUDMIX_CTR_OUTSRC_MASK;
+	ctr  |= FSL_AUDMIX_CTR_OUTSRC(val);
+
+	return snd_soc_component_update_bits(comp, FSL_AUDMIX_CTR, mask, ctr);
+}
+
+static const struct snd_kcontrol_new fsl_audmix_snd_controls[] = {
+	/* FSL_AUDMIX_CTR controls */
+	SOC_ENUM_EXT("Mixing Clock Source", fsl_audmix_enum[0],
+		     snd_soc_get_enum_double, fsl_audmix_put_mix_clk_src),
+	SOC_ENUM_EXT("Output Source", fsl_audmix_enum[1],
+		     snd_soc_get_enum_double, fsl_audmix_put_out_src),
+	SOC_ENUM("Output Width", fsl_audmix_enum[2]),
+	SOC_ENUM("Frame Rate Diff Error", fsl_audmix_enum[3]),
+	SOC_ENUM("Clock Freq Diff Error", fsl_audmix_enum[4]),
+	SOC_ENUM("Sync Mode Config", fsl_audmix_enum[5]),
+	SOC_ENUM("Sync Mode Clk Source", fsl_audmix_enum[6]),
+	/* TDM1 Attenuation controls */
+	SOC_ENUM("TDM1 Attenuation", fsl_audmix_enum[7]),
+	SOC_ENUM("TDM1 Attenuation Direction", fsl_audmix_enum[8]),
+	SOC_SINGLE("TDM1 Attenuation Step Divider", FSL_AUDMIX_ATCR0,
+		   2, 0x00fff, 0),
+	SOC_SINGLE("TDM1 Attenuation Initial Value", FSL_AUDMIX_ATIVAL0,
+		   0, 0x3ffff, 0),
+	SOC_SINGLE("TDM1 Attenuation Step Up Factor", FSL_AUDMIX_ATSTPUP0,
+		   0, 0x3ffff, 0),
+	SOC_SINGLE("TDM1 Attenuation Step Down Factor", FSL_AUDMIX_ATSTPDN0,
+		   0, 0x3ffff, 0),
+	SOC_SINGLE("TDM1 Attenuation Step Target", FSL_AUDMIX_ATSTPTGT0,
+		   0, 0x3ffff, 0),
+	/* TDM2 Attenuation controls */
+	SOC_ENUM("TDM2 Attenuation", fsl_audmix_enum[9]),
+	SOC_ENUM("TDM2 Attenuation Direction", fsl_audmix_enum[10]),
+	SOC_SINGLE("TDM2 Attenuation Step Divider", FSL_AUDMIX_ATCR1,
+		   2, 0x00fff, 0),
+	SOC_SINGLE("TDM2 Attenuation Initial Value", FSL_AUDMIX_ATIVAL1,
+		   0, 0x3ffff, 0),
+	SOC_SINGLE("TDM2 Attenuation Step Up Factor", FSL_AUDMIX_ATSTPUP1,
+		   0, 0x3ffff, 0),
+	SOC_SINGLE("TDM2 Attenuation Step Down Factor", FSL_AUDMIX_ATSTPDN1,
+		   0, 0x3ffff, 0),
+	SOC_SINGLE("TDM2 Attenuation Step Target", FSL_AUDMIX_ATSTPTGT1,
+		   0, 0x3ffff, 0),
+};
+
+static int fsl_audmix_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_component *comp = dai->component;
+	u32 mask = 0, ctr = 0;
+
+	/* AUDMIX is working in DSP_A format only */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* For playback the AUDMIX is slave, and for record is master */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_IB_NF:
+		/* Output data will be written on positive edge of the clock */
+		ctr |= FSL_AUDMIX_CTR_OUTCKPOL(0);
+		break;
+	case SND_SOC_DAIFMT_NB_NF:
+		/* Output data will be written on negative edge of the clock */
+		ctr |= FSL_AUDMIX_CTR_OUTCKPOL(1);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mask |= FSL_AUDMIX_CTR_OUTCKPOL_MASK;
+
+	return snd_soc_component_update_bits(comp, FSL_AUDMIX_CTR, mask, ctr);
+}
+
+static int fsl_audmix_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+				  struct snd_soc_dai *dai)
+{
+	struct fsl_audmix *priv = snd_soc_dai_get_drvdata(dai);
+
+	/* Capture stream shall not be handled */
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		return 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		priv->tdms |= BIT(dai->driver->id);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		priv->tdms &= ~BIT(dai->driver->id);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops fsl_audmix_dai_ops = {
+	.set_fmt      = fsl_audmix_dai_set_fmt,
+	.trigger      = fsl_audmix_dai_trigger,
+};
+
+static struct snd_soc_dai_driver fsl_audmix_dai[] = {
+	{
+		.id   = 0,
+		.name = "audmix-0",
+		.playback = {
+			.stream_name = "AUDMIX-Playback-0",
+			.channels_min = 8,
+			.channels_max = 8,
+			.rate_min = 8000,
+			.rate_max = 96000,
+			.rates = SNDRV_PCM_RATE_8000_96000,
+			.formats = FSL_AUDMIX_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AUDMIX-Capture-0",
+			.channels_min = 8,
+			.channels_max = 8,
+			.rate_min = 8000,
+			.rate_max = 96000,
+			.rates = SNDRV_PCM_RATE_8000_96000,
+			.formats = FSL_AUDMIX_FORMATS,
+		},
+		.ops = &fsl_audmix_dai_ops,
+	},
+	{
+		.id   = 1,
+		.name = "audmix-1",
+		.playback = {
+			.stream_name = "AUDMIX-Playback-1",
+			.channels_min = 8,
+			.channels_max = 8,
+			.rate_min = 8000,
+			.rate_max = 96000,
+			.rates = SNDRV_PCM_RATE_8000_96000,
+			.formats = FSL_AUDMIX_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AUDMIX-Capture-1",
+			.channels_min = 8,
+			.channels_max = 8,
+			.rate_min = 8000,
+			.rate_max = 96000,
+			.rates = SNDRV_PCM_RATE_8000_96000,
+			.formats = FSL_AUDMIX_FORMATS,
+		},
+		.ops = &fsl_audmix_dai_ops,
+	},
+};
+
+static const struct snd_soc_component_driver fsl_audmix_component = {
+	.name		  = "fsl-audmix-dai",
+	.controls	  = fsl_audmix_snd_controls,
+	.num_controls	  = ARRAY_SIZE(fsl_audmix_snd_controls),
+};
+
+static bool fsl_audmix_readable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case FSL_AUDMIX_CTR:
+	case FSL_AUDMIX_STR:
+	case FSL_AUDMIX_ATCR0:
+	case FSL_AUDMIX_ATIVAL0:
+	case FSL_AUDMIX_ATSTPUP0:
+	case FSL_AUDMIX_ATSTPDN0:
+	case FSL_AUDMIX_ATSTPTGT0:
+	case FSL_AUDMIX_ATTNVAL0:
+	case FSL_AUDMIX_ATSTP0:
+	case FSL_AUDMIX_ATCR1:
+	case FSL_AUDMIX_ATIVAL1:
+	case FSL_AUDMIX_ATSTPUP1:
+	case FSL_AUDMIX_ATSTPDN1:
+	case FSL_AUDMIX_ATSTPTGT1:
+	case FSL_AUDMIX_ATTNVAL1:
+	case FSL_AUDMIX_ATSTP1:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool fsl_audmix_writeable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case FSL_AUDMIX_CTR:
+	case FSL_AUDMIX_ATCR0:
+	case FSL_AUDMIX_ATIVAL0:
+	case FSL_AUDMIX_ATSTPUP0:
+	case FSL_AUDMIX_ATSTPDN0:
+	case FSL_AUDMIX_ATSTPTGT0:
+	case FSL_AUDMIX_ATCR1:
+	case FSL_AUDMIX_ATIVAL1:
+	case FSL_AUDMIX_ATSTPUP1:
+	case FSL_AUDMIX_ATSTPDN1:
+	case FSL_AUDMIX_ATSTPTGT1:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct reg_default fsl_audmix_reg[] = {
+	{ FSL_AUDMIX_CTR,       0x00060 },
+	{ FSL_AUDMIX_STR,       0x00003 },
+	{ FSL_AUDMIX_ATCR0,     0x00000 },
+	{ FSL_AUDMIX_ATIVAL0,   0x3FFFF },
+	{ FSL_AUDMIX_ATSTPUP0,  0x2AAAA },
+	{ FSL_AUDMIX_ATSTPDN0,  0x30000 },
+	{ FSL_AUDMIX_ATSTPTGT0, 0x00010 },
+	{ FSL_AUDMIX_ATTNVAL0,  0x00000 },
+	{ FSL_AUDMIX_ATSTP0,    0x00000 },
+	{ FSL_AUDMIX_ATCR1,     0x00000 },
+	{ FSL_AUDMIX_ATIVAL1,   0x3FFFF },
+	{ FSL_AUDMIX_ATSTPUP1,  0x2AAAA },
+	{ FSL_AUDMIX_ATSTPDN1,  0x30000 },
+	{ FSL_AUDMIX_ATSTPTGT1, 0x00010 },
+	{ FSL_AUDMIX_ATTNVAL1,  0x00000 },
+	{ FSL_AUDMIX_ATSTP1,    0x00000 },
+};
+
+static const struct regmap_config fsl_audmix_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = FSL_AUDMIX_ATSTP1,
+	.reg_defaults = fsl_audmix_reg,
+	.num_reg_defaults = ARRAY_SIZE(fsl_audmix_reg),
+	.readable_reg = fsl_audmix_readable_reg,
+	.writeable_reg = fsl_audmix_writeable_reg,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static int fsl_audmix_probe(struct platform_device *pdev)
+{
+	struct fsl_audmix *priv;
+	struct resource *res;
+	void __iomem *regs;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->pdev = pdev;
+
+	/* Get the addresses */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "ipg", regs,
+						 &fsl_audmix_regmap_config);
+	if (IS_ERR(priv->regmap)) {
+		dev_err(&pdev->dev, "failed to init regmap\n");
+		return PTR_ERR(priv->regmap);
+	}
+
+	priv->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(priv->ipg_clk)) {
+		dev_err(&pdev->dev, "failed to get ipg clock\n");
+		return PTR_ERR(priv->ipg_clk);
+	}
+
+	platform_set_drvdata(pdev, priv);
+	pm_runtime_enable(&pdev->dev);
+
+	ret = devm_snd_soc_register_component(&pdev->dev, &fsl_audmix_component,
+					      fsl_audmix_dai,
+					      ARRAY_SIZE(fsl_audmix_dai));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register ASoC DAI\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int fsl_audmix_runtime_resume(struct device *dev)
+{
+	struct fsl_audmix *priv = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(priv->ipg_clk);
+	if (ret) {
+		dev_err(dev, "Failed to enable IPG clock: %d\n", ret);
+		return ret;
+	}
+
+	regcache_cache_only(priv->regmap, false);
+	regcache_mark_dirty(priv->regmap);
+
+	return regcache_sync(priv->regmap);
+}
+
+static int fsl_audmix_runtime_suspend(struct device *dev)
+{
+	struct fsl_audmix *priv = dev_get_drvdata(dev);
+
+	regcache_cache_only(priv->regmap, true);
+
+	clk_disable_unprepare(priv->ipg_clk);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops fsl_audmix_pm = {
+	SET_RUNTIME_PM_OPS(fsl_audmix_runtime_suspend,
+			   fsl_audmix_runtime_resume,
+			   NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+};
+
+static const struct of_device_id fsl_audmix_ids[] = {
+	{ .compatible = "fsl,imx8qm-audmix", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_audmix_ids);
+
+static struct platform_driver fsl_audmix_driver = {
+	.probe = fsl_audmix_probe,
+	.driver = {
+		.name = "fsl-audmix",
+		.of_match_table = fsl_audmix_ids,
+		.pm = &fsl_audmix_pm,
+	},
+};
+module_platform_driver(fsl_audmix_driver);
+
+MODULE_DESCRIPTION("NXP AUDMIX ASoC DAI driver");
+MODULE_AUTHOR("Viorel Suman <viorel.suman@nxp.com>");
+MODULE_ALIAS("platform:fsl-audmix");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/fsl_audmix.h b/sound/soc/fsl/fsl_audmix.h
new file mode 100644
index 0000000..7812ffe
--- /dev/null
+++ b/sound/soc/fsl/fsl_audmix.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * NXP AUDMIX ALSA SoC Digital Audio Interface (DAI) driver
+ *
+ * Copyright 2017 NXP
+ */
+
+#ifndef __FSL_AUDMIX_H
+#define __FSL_AUDMIX_H
+
+#define FSL_AUDMIX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			SNDRV_PCM_FMTBIT_S24_LE |\
+			SNDRV_PCM_FMTBIT_S32_LE)
+/* AUDMIX Registers */
+#define FSL_AUDMIX_CTR		0x200 /* Control */
+#define FSL_AUDMIX_STR		0x204 /* Status */
+
+#define FSL_AUDMIX_ATCR0	0x208 /* Attenuation Control */
+#define FSL_AUDMIX_ATIVAL0	0x20c /* Attenuation Initial Value */
+#define FSL_AUDMIX_ATSTPUP0	0x210 /* Attenuation step up factor */
+#define FSL_AUDMIX_ATSTPDN0	0x214 /* Attenuation step down factor */
+#define FSL_AUDMIX_ATSTPTGT0	0x218 /* Attenuation step target */
+#define FSL_AUDMIX_ATTNVAL0	0x21c /* Attenuation Value */
+#define FSL_AUDMIX_ATSTP0	0x220 /* Attenuation step number */
+
+#define FSL_AUDMIX_ATCR1	0x228 /* Attenuation Control */
+#define FSL_AUDMIX_ATIVAL1	0x22c /* Attenuation Initial Value */
+#define FSL_AUDMIX_ATSTPUP1	0x230 /* Attenuation step up factor */
+#define FSL_AUDMIX_ATSTPDN1	0x234 /* Attenuation step down factor */
+#define FSL_AUDMIX_ATSTPTGT1	0x238 /* Attenuation step target */
+#define FSL_AUDMIX_ATTNVAL1	0x23c /* Attenuation Value */
+#define FSL_AUDMIX_ATSTP1	0x240 /* Attenuation step number */
+
+/* AUDMIX Control Register */
+#define FSL_AUDMIX_CTR_MIXCLK_SHIFT	0
+#define FSL_AUDMIX_CTR_MIXCLK_MASK	BIT(FSL_AUDMIX_CTR_MIXCLK_SHIFT)
+#define FSL_AUDMIX_CTR_MIXCLK(i)	((i) << FSL_AUDMIX_CTR_MIXCLK_SHIFT)
+#define FSL_AUDMIX_CTR_OUTSRC_SHIFT	1
+#define FSL_AUDMIX_CTR_OUTSRC_MASK	(0x3 << FSL_AUDMIX_CTR_OUTSRC_SHIFT)
+#define FSL_AUDMIX_CTR_OUTSRC(i)	(((i) << FSL_AUDMIX_CTR_OUTSRC_SHIFT)\
+					      & FSL_AUDMIX_CTR_OUTSRC_MASK)
+#define FSL_AUDMIX_CTR_OUTWIDTH_SHIFT	3
+#define FSL_AUDMIX_CTR_OUTWIDTH_MASK	(0x7 << FSL_AUDMIX_CTR_OUTWIDTH_SHIFT)
+#define FSL_AUDMIX_CTR_OUTWIDTH(i)	(((i) << FSL_AUDMIX_CTR_OUTWIDTH_SHIFT)\
+					      & FSL_AUDMIX_CTR_OUTWIDTH_MASK)
+#define FSL_AUDMIX_CTR_OUTCKPOL_SHIFT	6
+#define FSL_AUDMIX_CTR_OUTCKPOL_MASK	BIT(FSL_AUDMIX_CTR_OUTCKPOL_SHIFT)
+#define FSL_AUDMIX_CTR_OUTCKPOL(i)	((i) << FSL_AUDMIX_CTR_OUTCKPOL_SHIFT)
+#define FSL_AUDMIX_CTR_MASKRTDF_SHIFT	7
+#define FSL_AUDMIX_CTR_MASKRTDF_MASK	BIT(FSL_AUDMIX_CTR_MASKRTDF_SHIFT)
+#define FSL_AUDMIX_CTR_MASKRTDF(i)	((i) << FSL_AUDMIX_CTR_MASKRTDF_SHIFT)
+#define FSL_AUDMIX_CTR_MASKCKDF_SHIFT	8
+#define FSL_AUDMIX_CTR_MASKCKDF_MASK	BIT(FSL_AUDMIX_CTR_MASKCKDF_SHIFT)
+#define FSL_AUDMIX_CTR_MASKCKDF(i)	((i) << FSL_AUDMIX_CTR_MASKCKDF_SHIFT)
+#define FSL_AUDMIX_CTR_SYNCMODE_SHIFT	9
+#define FSL_AUDMIX_CTR_SYNCMODE_MASK	BIT(FSL_AUDMIX_CTR_SYNCMODE_SHIFT)
+#define FSL_AUDMIX_CTR_SYNCMODE(i)	((i) << FSL_AUDMIX_CTR_SYNCMODE_SHIFT)
+#define FSL_AUDMIX_CTR_SYNCSRC_SHIFT	10
+#define FSL_AUDMIX_CTR_SYNCSRC_MASK	BIT(FSL_AUDMIX_CTR_SYNCSRC_SHIFT)
+#define FSL_AUDMIX_CTR_SYNCSRC(i)	((i) << FSL_AUDMIX_CTR_SYNCSRC_SHIFT)
+
+/* AUDMIX Status Register */
+#define FSL_AUDMIX_STR_RATEDIFF		BIT(0)
+#define FSL_AUDMIX_STR_CLKDIFF		BIT(1)
+#define FSL_AUDMIX_STR_MIXSTAT_SHIFT	2
+#define FSL_AUDMIX_STR_MIXSTAT_MASK	(0x3 << FSL_AUDMIX_STR_MIXSTAT_SHIFT)
+#define FSL_AUDMIX_STR_MIXSTAT(i)	(((i) & FSL_AUDMIX_STR_MIXSTAT_MASK) \
+					   >> FSL_AUDMIX_STR_MIXSTAT_SHIFT)
+/* AUDMIX Attenuation Control Register */
+#define FSL_AUDMIX_ATCR_AT_EN		BIT(0)
+#define FSL_AUDMIX_ATCR_AT_UPDN		BIT(1)
+#define FSL_AUDMIX_ATCR_ATSTPDIF_SHIFT	2
+#define FSL_AUDMIX_ATCR_ATSTPDFI_MASK	\
+				(0xfff << FSL_AUDMIX_ATCR_ATSTPDIF_SHIFT)
+
+/* AUDMIX Attenuation Initial Value Register */
+#define FSL_AUDMIX_ATIVAL_ATINVAL_MASK	0x3FFFF
+
+/* AUDMIX Attenuation Step Up Factor Register */
+#define FSL_AUDMIX_ATSTPUP_ATSTEPUP_MASK	0x3FFFF
+
+/* AUDMIX Attenuation Step Down Factor Register */
+#define FSL_AUDMIX_ATSTPDN_ATSTEPDN_MASK	0x3FFFF
+
+/* AUDMIX Attenuation Step Target Register */
+#define FSL_AUDMIX_ATSTPTGT_ATSTPTG_MASK	0x3FFFF
+
+/* AUDMIX Attenuation Value Register */
+#define FSL_AUDMIX_ATTNVAL_ATCURVAL_MASK	0x3FFFF
+
+/* AUDMIX Attenuation Step Number Register */
+#define FSL_AUDMIX_ATSTP_STPCTR_MASK	0x3FFFF
+
+#define FSL_AUDMIX_MAX_DAIS		2
+struct fsl_audmix {
+	struct platform_device *pdev;
+	struct regmap *regmap;
+	struct clk *ipg_clk;
+	u8 tdms;
+};
+
+#endif /* __FSL_AUDMIX_H */
-- 
2.7.4


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

* [PATCH v3 2/4] ASoC: add fsl_audmix DT binding documentation
  2019-01-17 12:46 [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Viorel Suman
  2019-01-17 12:46 ` [PATCH v3 1/4] ASoC: fsl: Add Audio Mixer CPU DAI driver Viorel Suman
@ 2019-01-17 12:46 ` Viorel Suman
  2019-01-26  1:49   ` Nicolin Chen
  2019-01-17 12:46 ` [PATCH v3 3/4] ASoC: fsl: Add Audio Mixer machine driver Viorel Suman
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Viorel Suman @ 2019-01-17 12:46 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Jaroslav Kysela, Takashi Iwai, Timur Tabi, Nicolin Chen,
	Xiubo Li, Fabio Estevam, Viorel Suman, S.j. Wang, Daniel Baluta,
	Cosmin Samoila
  Cc: alsa-devel, devicetree, linux-kernel, linuxppc-dev, dl-linux-imx,
	Viorel Suman

Add the DT binding documentation for NXP Audio Mixer
CPU DAI driver.

Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
---
 .../devicetree/bindings/sound/fsl,audmix.txt       | 50 ++++++++++++++++++++++
 1 file changed, 50 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,audmix.txt

diff --git a/Documentation/devicetree/bindings/sound/fsl,audmix.txt b/Documentation/devicetree/bindings/sound/fsl,audmix.txt
new file mode 100644
index 0000000..840b7e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,audmix.txt
@@ -0,0 +1,50 @@
+NXP Audio Mixer (AUDMIX).
+
+The Audio Mixer is a on-chip functional module that allows mixing of two
+audio streams into a single audio stream. Audio Mixer has two input serial
+audio interfaces. These are driven by two Synchronous Audio interface
+modules (SAI). Each input serial interface carries 8 audio channels in its
+frame in TDM manner. Mixer mixes audio samples of corresponding channels
+from two interfaces into a single sample. Before mixing, audio samples of
+two inputs can be attenuated based on configuration. The output of the
+Audio Mixer is also a serial audio interface. Like input interfaces it has
+the same TDM frame format. This output is used to drive the serial DAC TDM
+interface of audio codec and also sent to the external pins along with the
+receive path of normal audio SAI module for readback by the CPU.
+
+The output of Audio Mixer can be selected from any of the three streams
+ - serial audio input 1
+ - serial audio input 2
+ - mixed audio
+
+Mixing operation is independent of audio sample rate but the two audio
+input streams must have same audio sample rate with same number of channels
+in TDM frame to be eligible for mixing.
+
+Device driver required properties:
+=================================
+  - compatible		: Compatible list, contains "fsl,imx8qm-audmix"
+
+  - reg			: Offset and length of the register set for the device.
+
+  - clocks		: Must contain an entry for each entry in clock-names.
+
+  - clock-names		: Must include the "ipg" for register access.
+
+  - power-domains	: Must contain the phandle to AUDMIX power domain node
+
+  - dais		: Must contain a list of phandles to AUDMIX connected
+			  DAIs. The current implementation requires two phandles
+			  to SAI interfaces to be provided, the first SAI in the
+			  list being used to route the AUDMIX output.
+
+Device driver configuration example:
+======================================
+  audmix: audmix@59840000 {
+    compatible = "fsl,imx8qm-audmix";
+    reg = <0x0 0x59840000 0x0 0x10000>;
+    clocks = <&clk IMX8QXP_AUD_AUDMIX_IPG>;
+    clock-names = "ipg";
+    power-domains = <&pd_audmix>;
+    dais = <&sai4>, <&sai5>;
+  };
-- 
2.7.4


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

* [PATCH v3 3/4] ASoC: fsl: Add Audio Mixer machine driver
  2019-01-17 12:46 [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Viorel Suman
  2019-01-17 12:46 ` [PATCH v3 1/4] ASoC: fsl: Add Audio Mixer CPU DAI driver Viorel Suman
  2019-01-17 12:46 ` [PATCH v3 2/4] ASoC: add fsl_audmix DT binding documentation Viorel Suman
@ 2019-01-17 12:46 ` Viorel Suman
  2019-01-17 12:46 ` [PATCH v3 4/4] ASoC: add imx-audmix DT binding documentation Viorel Suman
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Viorel Suman @ 2019-01-17 12:46 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Jaroslav Kysela, Takashi Iwai, Timur Tabi, Nicolin Chen,
	Xiubo Li, Fabio Estevam, Viorel Suman, S.j. Wang, Daniel Baluta,
	Cosmin Samoila
  Cc: alsa-devel, devicetree, linux-kernel, linuxppc-dev, dl-linux-imx,
	Viorel Suman

This patch implements Audio Mixer machine driver for NXP iMX8 SOCs.
It connects together Audio Mixer and related SAI instances.

Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
---
 sound/soc/fsl/Kconfig      |   9 ++
 sound/soc/fsl/Makefile     |   2 +
 sound/soc/fsl/imx-audmix.c | 334 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 345 insertions(+)
 create mode 100644 sound/soc/fsl/imx-audmix.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 0af2e056..d87c842 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -303,6 +303,15 @@ config SND_SOC_FSL_ASOC_CARD
 	 CS4271, CS4272 and SGTL5000.
 	 Say Y if you want to add support for Freescale Generic ASoC Sound Card.
 
+config SND_SOC_IMX_AUDMIX
+	tristate "SoC Audio support for i.MX boards with AUDMIX"
+	select SND_SOC_FSL_AUDMIX
+	select SND_SOC_FSL_SAI
+	help
+	  SoC Audio support for i.MX boards with Audio Mixer
+	  Say Y if you want to add support for SoC audio on an i.MX board with
+	  an Audio Mixer.
+
 endif # SND_IMX_SOC
 
 endmenu
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 4172d5a..c0dd044 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -62,6 +62,7 @@ snd-soc-imx-es8328-objs := imx-es8328.o
 snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
 snd-soc-imx-spdif-objs := imx-spdif.o
 snd-soc-imx-mc13783-objs := imx-mc13783.o
+snd-soc-imx-audmix-objs := imx-audmix.o
 
 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
 obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
@@ -71,3 +72,4 @@ obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o
 obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
 obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
 obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
+obj-$(CONFIG_SND_SOC_IMX_AUDMIX) += snd-soc-imx-audmix.o
diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c
new file mode 100644
index 0000000..30396e4
--- /dev/null
+++ b/sound/soc/fsl/imx-audmix.c
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2017 NXP
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <linux/pm_runtime.h>
+#include "fsl_sai.h"
+#include "fsl_audmix.h"
+
+struct imx_audmix {
+	struct platform_device *pdev;
+	struct snd_soc_card card;
+	struct platform_device *audmix_pdev;
+	struct platform_device *out_pdev;
+	struct clk *cpu_mclk;
+	int num_dai;
+	struct snd_soc_dai_link *dai;
+	int num_dai_conf;
+	struct snd_soc_codec_conf *dai_conf;
+	int num_dapm_routes;
+	struct snd_soc_dapm_route *dapm_routes;
+};
+
+static const u32 imx_audmix_rates[] = {
+	8000, 12000, 16000, 24000, 32000, 48000, 64000, 96000,
+};
+
+static const struct snd_pcm_hw_constraint_list imx_audmix_rate_constraints = {
+	.count = ARRAY_SIZE(imx_audmix_rates),
+	.list = imx_audmix_rates,
+};
+
+static int imx_audmix_fe_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct imx_audmix *priv = snd_soc_card_get_drvdata(rtd->card);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct device *dev = rtd->card->dev;
+	unsigned long clk_rate = clk_get_rate(priv->cpu_mclk);
+	int ret;
+
+	if (clk_rate % 24576000 == 0) {
+		ret = snd_pcm_hw_constraint_list(runtime, 0,
+						 SNDRV_PCM_HW_PARAM_RATE,
+						 &imx_audmix_rate_constraints);
+		if (ret < 0)
+			return ret;
+	} else {
+		dev_warn(dev, "mclk may be not supported %lu\n", clk_rate);
+	}
+
+	ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS,
+					   1, 8);
+	if (ret < 0)
+		return ret;
+
+	return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT,
+					    FSL_AUDMIX_FORMATS);
+}
+
+static int imx_audmix_fe_hw_params(struct snd_pcm_substream *substream,
+				   struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct device *dev = rtd->card->dev;
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+	unsigned int fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF;
+	u32 channels = params_channels(params);
+	int ret, dir;
+
+	/* For playback the AUDMIX is slave, and for record is master */
+	fmt |= tx ? SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+	dir  = tx ? SND_SOC_CLOCK_OUT : SND_SOC_CLOCK_IN;
+
+	/* set DAI configuration */
+	ret = snd_soc_dai_set_fmt(rtd->cpu_dai, fmt);
+	if (ret) {
+		dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, FSL_SAI_CLK_MAST1, 0, dir);
+	if (ret) {
+		dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * Per datasheet, AUDMIX expects 8 slots and 32 bits
+	 * for every slot in TDM mode.
+	 */
+	ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, BIT(channels) - 1,
+				       BIT(channels) - 1, 8, 32);
+	if (ret)
+		dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret);
+
+	return ret;
+}
+
+static int imx_audmix_be_hw_params(struct snd_pcm_substream *substream,
+				   struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct device *dev = rtd->card->dev;
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+	unsigned int fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF;
+	int ret;
+
+	if (!tx)
+		return 0;
+
+	/* For playback the AUDMIX is slave */
+	fmt |= SND_SOC_DAIFMT_CBM_CFM;
+
+	/* set AUDMIX DAI configuration */
+	ret = snd_soc_dai_set_fmt(rtd->cpu_dai, fmt);
+	if (ret)
+		dev_err(dev, "failed to set AUDMIX DAI fmt: %d\n", ret);
+
+	return ret;
+}
+
+static struct snd_soc_ops imx_audmix_fe_ops = {
+	.startup = imx_audmix_fe_startup,
+	.hw_params = imx_audmix_fe_hw_params,
+};
+
+static struct snd_soc_ops imx_audmix_be_ops = {
+	.hw_params = imx_audmix_be_hw_params,
+};
+
+static int imx_audmix_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *audmix_np = NULL, *out_cpu_np = NULL;
+	struct platform_device *audmix_pdev = NULL;
+	struct platform_device *cpu_pdev;
+	struct of_phandle_args args;
+	struct imx_audmix *priv;
+	int i, num_dai, ret;
+	const char *fe_name_pref = "HiFi-AUDMIX-FE-";
+	char *be_name, *be_pb, *be_cp, *dai_name, *capture_dai_name;
+
+	audmix_np = of_parse_phandle(np, "audmix-controller", 0);
+	if (!audmix_np) {
+		dev_err(&pdev->dev, "Missing audmix-controller phandle at %s\n",
+			np->full_name);
+		return -EINVAL;
+	}
+
+	audmix_pdev = of_find_device_by_node(audmix_np);
+	if (!audmix_pdev) {
+		dev_err(&pdev->dev, "Missing AUDMIX platform device for %s\n",
+			np->full_name);
+		return -EINVAL;
+	}
+
+	num_dai = of_count_phandle_with_args(audmix_np, "dais", NULL);
+	if (num_dai != FSL_AUDMIX_MAX_DAIS) {
+		dev_err(&pdev->dev, "Need 2 dais to be provided for %s\n",
+			audmix_np->full_name);
+		return -EINVAL;
+	}
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->num_dai = 2 * num_dai;
+	priv->dai = devm_kzalloc(&pdev->dev, priv->num_dai *
+				 sizeof(struct snd_soc_dai_link), GFP_KERNEL);
+	if (!priv->dai)
+		return -ENOMEM;
+
+	priv->num_dai_conf = num_dai;
+	priv->dai_conf = devm_kzalloc(&pdev->dev, priv->num_dai_conf *
+				      sizeof(struct snd_soc_codec_conf),
+				      GFP_KERNEL);
+	if (!priv->dai_conf)
+		return -ENOMEM;
+
+	priv->num_dapm_routes = 3 * num_dai;
+	priv->dapm_routes = devm_kzalloc(&pdev->dev, priv->num_dapm_routes *
+					 sizeof(struct snd_soc_dapm_route),
+					 GFP_KERNEL);
+	if (!priv->dapm_routes)
+		return -ENOMEM;
+
+	for (i = 0; i < num_dai; i++) {
+		ret = of_parse_phandle_with_args(audmix_np, "dais", NULL, i,
+						 &args);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "of_parse_phandle_with_args failed\n");
+			return ret;
+		}
+
+		cpu_pdev = of_find_device_by_node(args.np);
+		if (!cpu_pdev) {
+			dev_err(&pdev->dev, "failed to find SAI platform device\n");
+			return -EINVAL;
+		}
+
+		dai_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s%s",
+					  fe_name_pref, args.np->full_name + 1);
+
+		dev_info(&pdev->dev, "DAI FE name:%s\n", dai_name);
+
+		if (i == 0) {
+			out_cpu_np = args.np;
+			capture_dai_name =
+				devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s %s",
+					       dai_name, "CPU-Capture");
+		}
+
+		priv->dai[i].name = dai_name;
+		priv->dai[i].stream_name = "HiFi-AUDMIX-FE";
+		priv->dai[i].codec_dai_name = "snd-soc-dummy-dai";
+		priv->dai[i].codec_name = "snd-soc-dummy";
+		priv->dai[i].cpu_of_node = args.np;
+		priv->dai[i].cpu_dai_name = dev_name(&cpu_pdev->dev);
+		priv->dai[i].platform_of_node = args.np;
+		priv->dai[i].dynamic = 1;
+		priv->dai[i].dpcm_playback = 1;
+		priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0);
+		priv->dai[i].ignore_pmdown_time = 1;
+		priv->dai[i].ops = &imx_audmix_fe_ops;
+
+		/* Add AUDMIX Backend */
+		be_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+					 "audmix-%d", i);
+		be_pb = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+				       "AUDMIX-Playback-%d", i);
+		be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+				       "AUDMIX-Capture-%d", i);
+
+		priv->dai[num_dai + i].name = be_name;
+		priv->dai[num_dai + i].codec_dai_name = "snd-soc-dummy-dai";
+		priv->dai[num_dai + i].codec_name = "snd-soc-dummy";
+		priv->dai[num_dai + i].cpu_of_node = audmix_np;
+		priv->dai[num_dai + i].cpu_dai_name = be_name;
+		priv->dai[num_dai + i].platform_name = "snd-soc-dummy";
+		priv->dai[num_dai + i].no_pcm = 1;
+		priv->dai[num_dai + i].dpcm_playback = 1;
+		priv->dai[num_dai + i].dpcm_capture  = 1;
+		priv->dai[num_dai + i].ignore_pmdown_time = 1;
+		priv->dai[num_dai + i].ops = &imx_audmix_be_ops;
+
+		priv->dai_conf[i].of_node = args.np;
+		priv->dai_conf[i].name_prefix = dai_name;
+
+		priv->dapm_routes[i].source =
+			devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s %s",
+				       dai_name, "CPU-Playback");
+		priv->dapm_routes[i].sink = be_pb;
+		priv->dapm_routes[num_dai + i].source   = be_pb;
+		priv->dapm_routes[num_dai + i].sink     = be_cp;
+		priv->dapm_routes[2 * num_dai + i].source = be_cp;
+		priv->dapm_routes[2 * num_dai + i].sink   = capture_dai_name;
+	}
+
+	cpu_pdev = of_find_device_by_node(out_cpu_np);
+	if (!cpu_pdev) {
+		dev_err(&pdev->dev, "failed to find SAI platform device\n");
+		return -EINVAL;
+	}
+	priv->cpu_mclk = devm_clk_get(&cpu_pdev->dev, "mclk1");
+	if (IS_ERR(priv->cpu_mclk)) {
+		ret = PTR_ERR(priv->cpu_mclk);
+		dev_err(&cpu_pdev->dev, "failed to get DAI mclk1: %d\n", ret);
+		return -EINVAL;
+	}
+
+	priv->audmix_pdev = audmix_pdev;
+	priv->out_pdev  = cpu_pdev;
+
+	priv->card.dai_link = priv->dai;
+	priv->card.num_links = priv->num_dai;
+	priv->card.codec_conf = priv->dai_conf;
+	priv->card.num_configs = priv->num_dai_conf;
+	priv->card.dapm_routes = priv->dapm_routes;
+	priv->card.num_dapm_routes = priv->num_dapm_routes;
+	priv->card.dev = &pdev->dev;
+	priv->card.owner = THIS_MODULE;
+
+	ret = snd_soc_of_parse_card_name(&priv->card, "model");
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_of_parse_card_name failed\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, &priv->card);
+	snd_soc_card_set_drvdata(&priv->card, priv);
+
+	ret = devm_snd_soc_register_card(&pdev->dev, &priv->card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static const struct of_device_id imx_audmix_dt_ids[] = {
+	{ .compatible = "fsl,imx-audmix", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_audmix_dt_ids);
+
+static struct platform_driver imx_audmix_driver = {
+	.probe = imx_audmix_probe,
+	.driver = {
+		.name = "imx-audmix",
+		.of_match_table = imx_audmix_dt_ids,
+		.pm = &snd_soc_pm_ops,
+	},
+};
+module_platform_driver(imx_audmix_driver);
+
+MODULE_DESCRIPTION("NXP AUDMIX ASoC machine driver");
+MODULE_AUTHOR("Viorel Suman <viorel.suman@nxp.com>");
+MODULE_ALIAS("platform:imx-audmix");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4


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

* [PATCH v3 4/4] ASoC: add imx-audmix DT binding documentation
  2019-01-17 12:46 [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Viorel Suman
                   ` (2 preceding siblings ...)
  2019-01-17 12:46 ` [PATCH v3 3/4] ASoC: fsl: Add Audio Mixer machine driver Viorel Suman
@ 2019-01-17 12:46 ` Viorel Suman
  2019-01-17 16:18 ` [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Rob Herring
  2019-01-17 22:22 ` Nicolin Chen
  5 siblings, 0 replies; 14+ messages in thread
From: Viorel Suman @ 2019-01-17 12:46 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Jaroslav Kysela, Takashi Iwai, Timur Tabi, Nicolin Chen,
	Xiubo Li, Fabio Estevam, Viorel Suman, S.j. Wang, Daniel Baluta,
	Cosmin Samoila
  Cc: alsa-devel, devicetree, linux-kernel, linuxppc-dev, dl-linux-imx,
	Viorel Suman

Add the DT binding documentation for Audio Mixer
machine driver.

Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
---
 Documentation/devicetree/bindings/sound/imx-audmix.txt | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audmix.txt

diff --git a/Documentation/devicetree/bindings/sound/imx-audmix.txt b/Documentation/devicetree/bindings/sound/imx-audmix.txt
new file mode 100644
index 0000000..c840ed5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audmix.txt
@@ -0,0 +1,18 @@
+NXP Audio Mixer (AUDMIX) machine driver.
+
+Required properties:
+===================================
+  - compatible		: Compatible list, contains "fsl,imx-audmix"
+
+  - model		: Short audio card description.
+
+  - audmix-controller	: Must contain the phandle to the AUDMIX device node.
+
+Machine driver configuration example:
+====================================
+  sound-audmix-sai {
+    compatible = "fsl,imx-audmix";
+    model = "audmix-sai";
+    audmix-controller = <&audmix>;
+  };
+
-- 
2.7.4


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

* Re: [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers
  2019-01-17 12:46 [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Viorel Suman
                   ` (3 preceding siblings ...)
  2019-01-17 12:46 ` [PATCH v3 4/4] ASoC: add imx-audmix DT binding documentation Viorel Suman
@ 2019-01-17 16:18 ` Rob Herring
  2019-01-18 13:16   ` Viorel Suman
  2019-01-17 22:22 ` Nicolin Chen
  5 siblings, 1 reply; 14+ messages in thread
From: Rob Herring @ 2019-01-17 16:18 UTC (permalink / raw)
  To: Viorel Suman
  Cc: Liam Girdwood, Mark Brown, Mark Rutland, Jaroslav Kysela,
	Takashi Iwai, Timur Tabi, Nicolin Chen, Xiubo Li, Fabio Estevam,
	S.j. Wang, Daniel Baluta, Cosmin Samoila, alsa-devel, devicetree,
	linux-kernel, linuxppc-dev, dl-linux-imx, Viorel Suman

On Thu, Jan 17, 2019 at 12:46:25PM +0000, Viorel Suman wrote:
> The patchset adds NXP Audio Mixer (AUDMIX) device and machine
> drivers and related DT bindings documentation.
> 
> Changes since V2:
> 1. Moved "dais" node from machine driver DTS node to device driver DTS node
>   as suggested by Rob.

That was not what I suggested. You still have a virtual node which looks 
to me to be unnecessary.

> 
> Changes since V1:
> 1. Original patch split into distinct patches for the device driver and
>   DT binding documentation.
> 2. Replaced AMIX with AUDMIX in both code and file names as it looks more
>   RM-compliant.
> 3. Removed polarity control from CPU DAI driver as suggested by Nicolin.
> 4. Added machine driver and related DT binding documentation.
> 
> Viorel Suman (4):
>   ASoC: fsl: Add Audio Mixer CPU DAI driver
>   ASoC: add fsl_audmix DT binding documentation
>   ASoC: fsl: Add Audio Mixer machine driver
>   ASoC: add imx-audmix DT binding documentation
> 
>  .../devicetree/bindings/sound/fsl,audmix.txt       |  50 ++
>  .../devicetree/bindings/sound/imx-audmix.txt       |  18 +
>  sound/soc/fsl/Kconfig                              |  16 +
>  sound/soc/fsl/Makefile                             |   5 +
>  sound/soc/fsl/fsl_audmix.c                         | 551 +++++++++++++++++++++
>  sound/soc/fsl/fsl_audmix.h                         | 102 ++++
>  sound/soc/fsl/imx-audmix.c                         | 334 +++++++++++++
>  7 files changed, 1076 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/fsl,audmix.txt
>  create mode 100644 Documentation/devicetree/bindings/sound/imx-audmix.txt
>  create mode 100644 sound/soc/fsl/fsl_audmix.c
>  create mode 100644 sound/soc/fsl/fsl_audmix.h
>  create mode 100644 sound/soc/fsl/imx-audmix.c
> 
> -- 
> 2.7.4
> 

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

* Re: [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers
  2019-01-17 12:46 [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Viorel Suman
                   ` (4 preceding siblings ...)
  2019-01-17 16:18 ` [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Rob Herring
@ 2019-01-17 22:22 ` Nicolin Chen
  2019-01-17 22:24   ` Nicolin Chen
  5 siblings, 1 reply; 14+ messages in thread
From: Nicolin Chen @ 2019-01-17 22:22 UTC (permalink / raw)
  To: Viorel Suman
  Cc: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Jaroslav Kysela, Takashi Iwai, Timur Tabi, Xiubo Li,
	Fabio Estevam, S.j. Wang, Daniel Baluta, Cosmin Samoila,
	alsa-devel, devicetree, linux-kernel, linuxppc-dev, dl-linux-imx,
	Viorel Suman

On Thu, Jan 17, 2019 at 12:46:25PM +0000, Viorel Suman wrote:
> The patchset adds NXP Audio Mixer (AUDMIX) device and machine
> drivers and related DT bindings documentation.
> 
> Changes since V2:
> 1. Moved "dais" node from machine driver DTS node to device driver DTS node
>   as suggested by Rob.

Yea, it makes a lot of sense. Otherwise, since the connection
between IP blocks is fixed inside the SoC, the virtual sound
node would need to be put in the soc-level dtsi, which sounds
odd to me.

> Changes since V1:
> 1. Original patch split into distinct patches for the device driver and
>   DT binding documentation.
> 2. Replaced AMIX with AUDMIX in both code and file names as it looks more
>   RM-compliant.
> 3. Removed polarity control from CPU DAI driver as suggested by Nicolin.
> 4. Added machine driver and related DT binding documentation.
> 
> Viorel Suman (4):
>   ASoC: fsl: Add Audio Mixer CPU DAI driver
>   ASoC: add fsl_audmix DT binding documentation
>   ASoC: fsl: Add Audio Mixer machine driver
>   ASoC: add imx-audmix DT binding documentation

Reviewed-by: Nicolin Chen <nicoleotsuka@gmail.com>

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

* Re: [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers
  2019-01-17 22:22 ` Nicolin Chen
@ 2019-01-17 22:24   ` Nicolin Chen
  0 siblings, 0 replies; 14+ messages in thread
From: Nicolin Chen @ 2019-01-17 22:24 UTC (permalink / raw)
  To: Viorel Suman
  Cc: Liam Girdwood, Mark Brown, Rob Herring, Mark Rutland,
	Jaroslav Kysela, Takashi Iwai, Timur Tabi, Xiubo Li,
	Fabio Estevam, S.j. Wang, Daniel Baluta, Cosmin Samoila,
	alsa-devel, devicetree, linux-kernel, linuxppc-dev, dl-linux-imx,
	Viorel Suman

On Thu, Jan 17, 2019 at 02:22:18PM -0800, Nicolin Chen wrote:
> On Thu, Jan 17, 2019 at 12:46:25PM +0000, Viorel Suman wrote:
> > The patchset adds NXP Audio Mixer (AUDMIX) device and machine
> > drivers and related DT bindings documentation.
> > 
> > Changes since V2:
> > 1. Moved "dais" node from machine driver DTS node to device driver DTS node
> >   as suggested by Rob.
> 
> Yea, it makes a lot of sense. Otherwise, since the connection
> between IP blocks is fixed inside the SoC, the virtual sound
> node would need to be put in the soc-level dtsi, which sounds
> odd to me.
> 
> > Changes since V1:
> > 1. Original patch split into distinct patches for the device driver and
> >   DT binding documentation.
> > 2. Replaced AMIX with AUDMIX in both code and file names as it looks more
> >   RM-compliant.
> > 3. Removed polarity control from CPU DAI driver as suggested by Nicolin.
> > 4. Added machine driver and related DT binding documentation.
> > 
> > Viorel Suman (4):
> >   ASoC: fsl: Add Audio Mixer CPU DAI driver
> >   ASoC: add fsl_audmix DT binding documentation
> >   ASoC: fsl: Add Audio Mixer machine driver
> >   ASoC: add imx-audmix DT binding documentation
> 
> Reviewed-by: Nicolin Chen <nicoleotsuka@gmail.com>

Oops. Just saw Rob's new reply. The drivers look good to me though.

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

* Re: [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers
  2019-01-17 16:18 ` [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Rob Herring
@ 2019-01-18 13:16   ` Viorel Suman
  2019-01-18 19:46     ` Nicolin Chen
  0 siblings, 1 reply; 14+ messages in thread
From: Viorel Suman @ 2019-01-18 13:16 UTC (permalink / raw)
  To: robh, nicoleotsuka
  Cc: dl-linux-imx, Cosmin Samoila, linux-kernel, linuxppc-dev, timur,
	devicetree, Xiubo.Lee, viorel.suman, Fabio Estevam, broonie,
	mark.rutland, tiwai, lgirdwood, S.j. Wang, Daniel Baluta, perex,
	alsa-devel

Hi Rob, Nicolin, All,

On Jo, 2019-01-17 at 10:18 -0600, Rob Herring wrote:
> On Thu, Jan 17, 2019 at 12:46:25PM +0000, Viorel Suman wrote:
> > 
> > The patchset adds NXP Audio Mixer (AUDMIX) device and machine
> > drivers and related DT bindings documentation.
> > 
> > Changes since V2:
> > 1. Moved "dais" node from machine driver DTS node to device driver
> > DTS node
> >   as suggested by Rob.
> That was not what I suggested. You still have a virtual node which
> looks to me to be unnecessary.

To me removing virtual node implies that AUDMIX machine driver (imx-
audmix.c + virtual node) shall be removed and machine driver code
merged into device driver (fsl_audmix.c + device node) - please let me
know if my understanding is wrong.

The implication is that this makes AUDMIX device driver bounded to a
particular DAI type of interface - SAI. The original intention is to
keep AUDMIX device driver DAI-agnostic.

Indeed, currently the connection between AUDMIX and SAI IP blocks in
i.MX8QM and i.MX8QXP is fixed inside the SoC, but on other platforms we
may expect AUDMIX to be connected inside the SoC to other IP blocks -
to ESAI interface for instance.

At this moment it's a bit difficult for me to evaluate how critical is
to keep the device driver DAI-agnostic, so if you think it's better to
go now with a SAI bounded AUDMIX device driver - please confirm, I'll
merge machine driver code into device driver.

Thank you,
Viorel

> 
> > 
> > 
> > Changes since V1:
> > 1. Original patch split into distinct patches for the device driver
> > and
> >   DT binding documentation.
> > 2. Replaced AMIX with AUDMIX in both code and file names as it
> > looks more
> >   RM-compliant.
> > 3. Removed polarity control from CPU DAI driver as suggested by
> > Nicolin.
> > 4. Added machine driver and related DT binding documentation.
> > 
> > Viorel Suman (4):
> >   ASoC: fsl: Add Audio Mixer CPU DAI driver
> >   ASoC: add fsl_audmix DT binding documentation
> >   ASoC: fsl: Add Audio Mixer machine driver
> >   ASoC: add imx-audmix DT binding documentation
> > 
> >  .../devicetree/bindings/sound/fsl,audmix.txt       |  50 ++
> >  .../devicetree/bindings/sound/imx-audmix.txt       |  18 +
> >  sound/soc/fsl/Kconfig                              |  16 +
> >  sound/soc/fsl/Makefile                             |   5 +
> >  sound/soc/fsl/fsl_audmix.c                         | 551
> > +++++++++++++++++++++
> >  sound/soc/fsl/fsl_audmix.h                         | 102 ++++
> >  sound/soc/fsl/imx-audmix.c                         | 334
> > +++++++++++++
> >  7 files changed, 1076 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/sound/fsl,audmix.txt
> >  create mode 100644 Documentation/devicetree/bindings/sound/imx-
> > audmix.txt
> >  create mode 100644 sound/soc/fsl/fsl_audmix.c
> >  create mode 100644 sound/soc/fsl/fsl_audmix.h
> >  create mode 100644 sound/soc/fsl/imx-audmix.c
> > 

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

* Re: [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers
  2019-01-18 13:16   ` Viorel Suman
@ 2019-01-18 19:46     ` Nicolin Chen
  2019-01-21 15:23       ` Rob Herring
  2019-01-22 11:19       ` Viorel Suman
  0 siblings, 2 replies; 14+ messages in thread
From: Nicolin Chen @ 2019-01-18 19:46 UTC (permalink / raw)
  To: Viorel Suman
  Cc: robh, dl-linux-imx, Cosmin Samoila, linux-kernel, linuxppc-dev,
	timur, devicetree, Xiubo.Lee, viorel.suman, Fabio Estevam,
	broonie, mark.rutland, tiwai, lgirdwood, S.j. Wang,
	Daniel Baluta, perex, alsa-devel

On Fri, Jan 18, 2019 at 01:16:24PM +0000, Viorel Suman wrote:
> > > 1. Moved "dais" node from machine driver DTS node to device driver
> > > DTS node
> > >   as suggested by Rob.
> > That was not what I suggested. You still have a virtual node which
> > looks to me to be unnecessary.
> 
> To me removing virtual node implies that AUDMIX machine driver (imx-
> audmix.c + virtual node) shall be removed and machine driver code
> merged into device driver (fsl_audmix.c + device node) - please let me
> know if my understanding is wrong.

We could use a non-DT configuration right? From the driver logic,
DT just registers a device corresponding to the machine driver so
that it can probe(). We could register one in fsl_audmix instead.
Please refer to how fsl_ssi registers the sound card device. The
machine driver can get audmix_np from the parent device pointer,
and I think that's all you need.

Or maybe someone else would provide a better way. But it'd work.

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

* Re: [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers
  2019-01-18 19:46     ` Nicolin Chen
@ 2019-01-21 15:23       ` Rob Herring
  2019-01-22 11:39         ` Viorel Suman
  2019-01-22 11:19       ` Viorel Suman
  1 sibling, 1 reply; 14+ messages in thread
From: Rob Herring @ 2019-01-21 15:23 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: Viorel Suman, dl-linux-imx, Cosmin Samoila, linux-kernel,
	linuxppc-dev, timur, devicetree, Xiubo.Lee, viorel.suman,
	Fabio Estevam, broonie, mark.rutland, tiwai, lgirdwood,
	S.j. Wang, Daniel Baluta, perex, alsa-devel

On Fri, Jan 18, 2019 at 11:46:42AM -0800, Nicolin Chen wrote:
> On Fri, Jan 18, 2019 at 01:16:24PM +0000, Viorel Suman wrote:
> > > > 1. Moved "dais" node from machine driver DTS node to device driver
> > > > DTS node
> > > >   as suggested by Rob.
> > > That was not what I suggested. You still have a virtual node which
> > > looks to me to be unnecessary.
> > 
> > To me removing virtual node implies that AUDMIX machine driver (imx-
> > audmix.c + virtual node) shall be removed and machine driver code
> > merged into device driver (fsl_audmix.c + device node) - please let me
> > know if my understanding is wrong.
> 
> We could use a non-DT configuration right? From the driver logic,
> DT just registers a device corresponding to the machine driver so
> that it can probe(). We could register one in fsl_audmix instead.
> Please refer to how fsl_ssi registers the sound card device. The
> machine driver can get audmix_np from the parent device pointer,
> and I think that's all you need.

Yes.

> Or maybe someone else would provide a better way. But it'd work.

Or the machine driver could create the audmix device. That probably 
makes less sense, but either way there doesn't have to be a 1-1 
correspondence of DT nodes and (platform) devices.

I'm not an ASoC expert, but why can't the machine driver just control 
the audmix directly (with DAIs as separate drivers)? Is the audmix ever 
going to a be a component for a different machine driver?

Rob


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

* Re: [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers
  2019-01-18 19:46     ` Nicolin Chen
  2019-01-21 15:23       ` Rob Herring
@ 2019-01-22 11:19       ` Viorel Suman
  1 sibling, 0 replies; 14+ messages in thread
From: Viorel Suman @ 2019-01-22 11:19 UTC (permalink / raw)
  To: nicoleotsuka
  Cc: dl-linux-imx, linux-kernel, Cosmin Samoila, linuxppc-dev, timur,
	devicetree, Xiubo.Lee, viorel.suman, Fabio Estevam, broonie,
	mark.rutland, tiwai, robh, lgirdwood, S.j. Wang, Daniel Baluta,
	perex, alsa-devel

Hi Nicolin,

On Vi, 2019-01-18 at 11:46 -0800, Nicolin Chen wrote:
> On Fri, Jan 18, 2019 at 01:16:24PM +0000, Viorel Suman wrote:
> > 
> > > 
> > > > 
> > > > 1. Moved "dais" node from machine driver DTS node to device
> > > > driver
> > > > DTS node
> > > >   as suggested by Rob.
> > > That was not what I suggested. You still have a virtual node
> > > which
> > > looks to me to be unnecessary.
> > To me removing virtual node implies that AUDMIX machine driver
> > (imx-
> > audmix.c + virtual node) shall be removed and machine driver code
> > merged into device driver (fsl_audmix.c + device node) - please let
> > me
> > know if my understanding is wrong.
> We could use a non-DT configuration right? From the driver logic,
> DT just registers a device corresponding to the machine driver so
> that it can probe(). We could register one in fsl_audmix instead.
> Please refer to how fsl_ssi registers the sound card device. The
> machine driver can get audmix_np from the parent device pointer,
> and I think that's all you need.
> 
> Or maybe someone else would provide a better way. But it'd work.

Sent V4 - it implements the approach you suggested. Thank you for the
hint, works well indeed.

Regards,
Viorel


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

* Re: [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers
  2019-01-21 15:23       ` Rob Herring
@ 2019-01-22 11:39         ` Viorel Suman
  0 siblings, 0 replies; 14+ messages in thread
From: Viorel Suman @ 2019-01-22 11:39 UTC (permalink / raw)
  To: robh, nicoleotsuka
  Cc: dl-linux-imx, linux-kernel, Cosmin Samoila, linuxppc-dev, timur,
	viorel.suman, Xiubo.Lee, devicetree, Fabio Estevam, broonie,
	mark.rutland, tiwai, lgirdwood, S.j. Wang, Daniel Baluta, perex,
	alsa-devel

Hi Rob,

On Lu, 2019-01-21 at 09:23 -0600, Rob Herring wrote:
> On Fri, Jan 18, 2019 at 11:46:42AM -0800, Nicolin Chen wrote:
> > 
> > On Fri, Jan 18, 2019 at 01:16:24PM +0000, Viorel Suman wrote:
> > > 
> > > > 
> > > > > 
> > > > > 1. Moved "dais" node from machine driver DTS node to device
> > > > > driver
> > > > > DTS node
> > > > >   as suggested by Rob.
> > > > That was not what I suggested. You still have a virtual node
> > > > which
> > > > looks to me to be unnecessary.
> > > To me removing virtual node implies that AUDMIX machine driver
> > > (imx-
> > > audmix.c + virtual node) shall be removed and machine driver code
> > > merged into device driver (fsl_audmix.c + device node) - please
> > > let me
> > > know if my understanding is wrong.
> > We could use a non-DT configuration right? From the driver logic,
> > DT just registers a device corresponding to the machine driver so
> > that it can probe(). We could register one in fsl_audmix instead.
> > Please refer to how fsl_ssi registers the sound card device. The
> > machine driver can get audmix_np from the parent device pointer,
> > and I think that's all you need.
> Yes.

Thank you, sent V4 which implements the approach suggested by Nicolin.

> 
> > 
> > Or maybe someone else would provide a better way. But it'd work.
> Or the machine driver could create the audmix device. That probably 
> makes less sense, but either way there doesn't have to be a 1-1 
> correspondence of DT nodes and (platform) devices.
> 
> I'm not an ASoC expert, but why can't the machine driver just control
> the audmix directly (with DAIs as separate drivers)? Is the audmix
> ever going to a be a component for a different machine driver?
> 
> Rob

Currently I'm not aware of any information with regard to if audmix is
ever going to work with other DAIs than SAI. Howerver from audmix IP
block integration perspective the only requirement is that the input
DAI must be connected to audmix over I2S bus, possible DAI options are
SAI, ESAI, etc - I think the approach to mix both device and machine
drivers into a single entity is not the best way to go.

/Viorel

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

* Re: [PATCH v3 2/4] ASoC: add fsl_audmix DT binding documentation
  2019-01-17 12:46 ` [PATCH v3 2/4] ASoC: add fsl_audmix DT binding documentation Viorel Suman
@ 2019-01-26  1:49   ` Nicolin Chen
  0 siblings, 0 replies; 14+ messages in thread
From: Nicolin Chen @ 2019-01-26  1:49 UTC (permalink / raw)
  To: Viorel Suman, Rob Herring
  Cc: Liam Girdwood, Mark Brown, Mark Rutland, Jaroslav Kysela,
	Takashi Iwai, Timur Tabi, Xiubo Li, Fabio Estevam, S.j. Wang,
	Daniel Baluta, Cosmin Samoila, alsa-devel, devicetree,
	linux-kernel, linuxppc-dev, dl-linux-imx, Viorel Suman

On Thu, Jan 17, 2019 at 12:46:29PM +0000, Viorel Suman wrote:

> +  - dais		: Must contain a list of phandles to AUDMIX connected
> +			  DAIs. The current implementation requires two phandles
> +			  to SAI interfaces to be provided, the first SAI in the
> +			  list being used to route the AUDMIX output.

Another small thing, that I just noticed, is this list. It forces
the first input source to be the output source without giving any
chance. I feel that we could have some flexibility here: one node
for two input sources, and one node for the output source.

Well, there is no critical problem with the current binding since
it follows the SoC design. Yet I doubt if this routing logic will
never break.

Any suggestion, Rob?

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

end of thread, other threads:[~2019-01-26  1:49 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-17 12:46 [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Viorel Suman
2019-01-17 12:46 ` [PATCH v3 1/4] ASoC: fsl: Add Audio Mixer CPU DAI driver Viorel Suman
2019-01-17 12:46 ` [PATCH v3 2/4] ASoC: add fsl_audmix DT binding documentation Viorel Suman
2019-01-26  1:49   ` Nicolin Chen
2019-01-17 12:46 ` [PATCH v3 3/4] ASoC: fsl: Add Audio Mixer machine driver Viorel Suman
2019-01-17 12:46 ` [PATCH v3 4/4] ASoC: add imx-audmix DT binding documentation Viorel Suman
2019-01-17 16:18 ` [PATCH v3 0/4] Add NXP AUDMIX device and machine drivers Rob Herring
2019-01-18 13:16   ` Viorel Suman
2019-01-18 19:46     ` Nicolin Chen
2019-01-21 15:23       ` Rob Herring
2019-01-22 11:39         ` Viorel Suman
2019-01-22 11:19       ` Viorel Suman
2019-01-17 22:22 ` Nicolin Chen
2019-01-17 22:24   ` Nicolin Chen

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).