[PATCH] ASoC: ak4458: enable daisy chain

2021-04-20 Thread Shengjiu Wang
From: Viorel Suman 

Enable Daisy Chain if in TDM mode and the number of played
channels is bigger than the maximum supported number of channels.

Signed-off-by: Viorel Suman 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/codecs/ak4458.c | 47 ++-
 sound/soc/codecs/ak4458.h |  1 +
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c
index 3088128816bb..29eb78702bf3 100644
--- a/sound/soc/codecs/ak4458.c
+++ b/sound/soc/codecs/ak4458.c
@@ -306,6 +306,20 @@ static const struct snd_soc_dapm_route ak4497_intercon[] = 
{
 
 };
 
+static int ak4458_get_tdm_mode(struct ak4458_priv *ak4458)
+{
+   switch (ak4458->slots * ak4458->slot_width) {
+   case 128:
+   return 1;
+   case 256:
+   return 2;
+   case 512:
+   return 3;
+   default:
+   return 0;
+   }
+}
+
 static int ak4458_rstn_control(struct snd_soc_component *component, int bit)
 {
int ret;
@@ -333,13 +347,16 @@ static int ak4458_hw_params(struct snd_pcm_substream 
*substream,
struct snd_soc_component *component = dai->component;
struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
int pcm_width = max(params_physical_width(params), ak4458->slot_width);
-   u8 format, dsdsel0, dsdsel1;
-   int nfs1, dsd_bclk, ret;
+   u8 format, dsdsel0, dsdsel1, dchn;
+   int nfs1, dsd_bclk, ret, channels, channels_max;
 
nfs1 = params_rate(params);
ak4458->fs = nfs1;
 
/* calculate bit clock */
+   channels = params_channels(params);
+   channels_max = dai->driver->playback.channels_max;
+
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_DSD_U8:
case SNDRV_PCM_FORMAT_DSD_U16_LE:
@@ -419,6 +436,17 @@ static int ak4458_hw_params(struct snd_pcm_substream 
*substream,
snd_soc_component_update_bits(component, AK4458_00_CONTROL1,
AK4458_DIF_MASK, format);
 
+   /*
+* Enable/disable Daisy Chain if in TDM mode and the number of played
+* channels is bigger than the maximum supported number of channels
+*/
+   dchn = ak4458_get_tdm_mode(ak4458) &&
+   (ak4458->fmt == SND_SOC_DAIFMT_DSP_B) &&
+   (channels > channels_max) ? AK4458_DCHAIN_MASK : 0;
+
+   snd_soc_component_update_bits(component, AK4458_0B_CONTROL7,
+ AK4458_DCHAIN_MASK, dchn);
+
ret = ak4458_rstn_control(component, 0);
if (ret)
return ret;
@@ -519,20 +547,7 @@ static int ak4458_set_tdm_slot(struct snd_soc_dai *dai, 
unsigned int tx_mask,
ak4458->slots = slots;
ak4458->slot_width = slot_width;
 
-   switch (slots * slot_width) {
-   case 128:
-   mode = AK4458_MODE_TDM128;
-   break;
-   case 256:
-   mode = AK4458_MODE_TDM256;
-   break;
-   case 512:
-   mode = AK4458_MODE_TDM512;
-   break;
-   default:
-   mode = AK4458_MODE_NORMAL;
-   break;
-   }
+   mode = ak4458_get_tdm_mode(ak4458) << AK4458_MODE_SHIFT;
 
snd_soc_component_update_bits(component, AK4458_0A_CONTROL6,
AK4458_MODE_MASK,
diff --git a/sound/soc/codecs/ak4458.h b/sound/soc/codecs/ak4458.h
index 9548c5d78621..9ad869575f8d 100644
--- a/sound/soc/codecs/ak4458.h
+++ b/sound/soc/codecs/ak4458.h
@@ -82,6 +82,7 @@
  * */
 #define AK4458_ATS_SHIFT   6
 #define AK4458_ATS_MASKGENMASK(7, 6)
+#define AK4458_DCHAIN_MASK (0x1 << 1)
 
 #define AK4458_DSDSEL_MASK (0x1 << 0)
 #define AK4458_DP_MASK (0x1 << 7)
-- 
2.27.0



[PATCH v2] ASoC: ak4458: check reset control status

2021-04-19 Thread Shengjiu Wang
From: Viorel Suman 

check the return value of ak4458_rstn_control.

Signed-off-by: Viorel Suman 
Signed-off-by: Shengjiu Wang 
---
changes in v2:
- fix "use of undeclared identifier 'ret'" reported by kernel test robot

 sound/soc/codecs/ak4458.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c
index 85a1d00894a9..3088128816bb 100644
--- a/sound/soc/codecs/ak4458.c
+++ b/sound/soc/codecs/ak4458.c
@@ -334,7 +334,7 @@ static int ak4458_hw_params(struct snd_pcm_substream 
*substream,
struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
int pcm_width = max(params_physical_width(params), ak4458->slot_width);
u8 format, dsdsel0, dsdsel1;
-   int nfs1, dsd_bclk;
+   int nfs1, dsd_bclk, ret;
 
nfs1 = params_rate(params);
ak4458->fs = nfs1;
@@ -419,8 +419,13 @@ static int ak4458_hw_params(struct snd_pcm_substream 
*substream,
snd_soc_component_update_bits(component, AK4458_00_CONTROL1,
AK4458_DIF_MASK, format);
 
-   ak4458_rstn_control(component, 0);
-   ak4458_rstn_control(component, 1);
+   ret = ak4458_rstn_control(component, 0);
+   if (ret)
+   return ret;
+
+   ret = ak4458_rstn_control(component, 1);
+   if (ret)
+   return ret;
 
return 0;
 }
@@ -429,6 +434,7 @@ static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, 
unsigned int fmt)
 {
struct snd_soc_component *component = dai->component;
struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
+   int ret;
 
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS: /* Slave Mode */
@@ -461,8 +467,13 @@ static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, 
unsigned int fmt)
  ak4458->fmt == SND_SOC_DAIFMT_PDM ?
  AK4458_DP_MASK : 0);
 
-   ak4458_rstn_control(component, 0);
-   ak4458_rstn_control(component, 1);
+   ret = ak4458_rstn_control(component, 0);
+   if (ret)
+   return ret;
+
+   ret = ak4458_rstn_control(component, 1);
+   if (ret)
+   return ret;
 
return 0;
 }
-- 
2.27.0



[PATCH] ASoC: ak4458: check reset control status

2021-04-16 Thread Shengjiu Wang
From: Viorel Suman 

check the return value of ak4458_rstn_control.

Signed-off-by: Viorel Suman 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/codecs/ak4458.c | 19 +++
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c
index 85a1d00894a9..0a94973889a1 100644
--- a/sound/soc/codecs/ak4458.c
+++ b/sound/soc/codecs/ak4458.c
@@ -419,8 +419,13 @@ static int ak4458_hw_params(struct snd_pcm_substream 
*substream,
snd_soc_component_update_bits(component, AK4458_00_CONTROL1,
AK4458_DIF_MASK, format);
 
-   ak4458_rstn_control(component, 0);
-   ak4458_rstn_control(component, 1);
+   ret = ak4458_rstn_control(component, 0);
+   if (ret)
+   return ret;
+
+   ret = ak4458_rstn_control(component, 1);
+   if (ret)
+   return ret;
 
return 0;
 }
@@ -429,6 +434,7 @@ static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, 
unsigned int fmt)
 {
struct snd_soc_component *component = dai->component;
struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
+   int ret;
 
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS: /* Slave Mode */
@@ -461,8 +467,13 @@ static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, 
unsigned int fmt)
  ak4458->fmt == SND_SOC_DAIFMT_PDM ?
  AK4458_DP_MASK : 0);
 
-   ak4458_rstn_control(component, 0);
-   ak4458_rstn_control(component, 1);
+   ret = ak4458_rstn_control(component, 0);
+   if (ret)
+   return ret;
+
+   ret = ak4458_rstn_control(component, 1);
+   if (ret)
+   return ret;
 
return 0;
 }
-- 
2.27.0



[PATCH v2 -next 1/2] ASoC: ak5558: correct reset polarity

2021-04-14 Thread Shengjiu Wang
Reset (aka power off) happens when the reset gpio is made active.
The reset gpio is GPIO_ACTIVE_LOW

Fixes: 920884777480 ("ASoC: ak5558: Add support for AK5558 ADC driver")
Signed-off-by: Shengjiu Wang 
---
changes in v2:
- split the patch to two patches.

 sound/soc/codecs/ak5558.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c
index 8e4dca753f0b..f24d91b728dd 100644
--- a/sound/soc/codecs/ak5558.c
+++ b/sound/soc/codecs/ak5558.c
@@ -323,7 +323,7 @@ static void ak5558_power_off(struct ak5558_priv *ak5558)
if (!ak5558->reset_gpiod)
return;
 
-   gpiod_set_value_cansleep(ak5558->reset_gpiod, 0);
+   gpiod_set_value_cansleep(ak5558->reset_gpiod, 1);
usleep_range(1000, 2000);
 }
 
@@ -332,7 +332,7 @@ static void ak5558_power_on(struct ak5558_priv *ak5558)
if (!ak5558->reset_gpiod)
return;
 
-   gpiod_set_value_cansleep(ak5558->reset_gpiod, 1);
+   gpiod_set_value_cansleep(ak5558->reset_gpiod, 0);
usleep_range(1000, 2000);
 }
 
-- 
2.27.0



[PATCH v2 -next 2/2] ASoC: ak5558: change function name to ak5558_reset

2021-04-14 Thread Shengjiu Wang
Change function name to ak5558_reset to match devicetree property
"reset-gpios".

Signed-off-by: Shengjiu Wang 
---
changes in v2:
- split patches to two patches

 sound/soc/codecs/ak5558.c | 23 +++
 1 file changed, 7 insertions(+), 16 deletions(-)

diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c
index f24d91b728dd..34aed80db0eb 100644
--- a/sound/soc/codecs/ak5558.c
+++ b/sound/soc/codecs/ak5558.c
@@ -318,21 +318,12 @@ static struct snd_soc_dai_driver ak5552_dai = {
.ops = _dai_ops,
 };
 
-static void ak5558_power_off(struct ak5558_priv *ak5558)
+static void ak5558_reset(struct ak5558_priv *ak5558, bool active)
 {
if (!ak5558->reset_gpiod)
return;
 
-   gpiod_set_value_cansleep(ak5558->reset_gpiod, 1);
-   usleep_range(1000, 2000);
-}
-
-static void ak5558_power_on(struct ak5558_priv *ak5558)
-{
-   if (!ak5558->reset_gpiod)
-   return;
-
-   gpiod_set_value_cansleep(ak5558->reset_gpiod, 0);
+   gpiod_set_value_cansleep(ak5558->reset_gpiod, active);
usleep_range(1000, 2000);
 }
 
@@ -340,7 +331,7 @@ static int ak5558_probe(struct snd_soc_component *component)
 {
struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component);
 
-   ak5558_power_on(ak5558);
+   ak5558_reset(ak5558, false);
return ak5558_set_mcki(component);
 }
 
@@ -348,7 +339,7 @@ static void ak5558_remove(struct snd_soc_component 
*component)
 {
struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component);
 
-   ak5558_power_off(ak5558);
+   ak5558_reset(ak5558, true);
 }
 
 static int __maybe_unused ak5558_runtime_suspend(struct device *dev)
@@ -356,7 +347,7 @@ static int __maybe_unused ak5558_runtime_suspend(struct 
device *dev)
struct ak5558_priv *ak5558 = dev_get_drvdata(dev);
 
regcache_cache_only(ak5558->regmap, true);
-   ak5558_power_off(ak5558);
+   ak5558_reset(ak5558, true);
 
regulator_bulk_disable(ARRAY_SIZE(ak5558->supplies),
   ak5558->supplies);
@@ -375,8 +366,8 @@ static int __maybe_unused ak5558_runtime_resume(struct 
device *dev)
return ret;
}
 
-   ak5558_power_off(ak5558);
-   ak5558_power_on(ak5558);
+   ak5558_reset(ak5558, true);
+   ak5558_reset(ak5558, false);
 
regcache_cache_only(ak5558->regmap, false);
regcache_mark_dirty(ak5558->regmap);
-- 
2.27.0



[PATCH] ASoC: ak5558: correct reset polarity

2021-04-13 Thread Shengjiu Wang
Reset (aka power off) happens when the reset gpio is made active.
Change function name to ak5558_reset to match devicetree property
"reset-gpios".

Signed-off-by: Shengjiu Wang 
---
 sound/soc/codecs/ak5558.c | 30 ++
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c
index 8e4dca753f0b..5c3f15827423 100644
--- a/sound/soc/codecs/ak5558.c
+++ b/sound/soc/codecs/ak5558.c
@@ -318,29 +318,19 @@ static struct snd_soc_dai_driver ak5552_dai = {
.ops = _dai_ops,
 };
 
-static void ak5558_power_off(struct ak5558_priv *ak5558)
+static void ak5558_reset(struct ak5558_priv *ak5558, bool active)
 {
-   if (!ak5558->reset_gpiod)
-   return;
-
-   gpiod_set_value_cansleep(ak5558->reset_gpiod, 0);
-   usleep_range(1000, 2000);
-}
-
-static void ak5558_power_on(struct ak5558_priv *ak5558)
-{
-   if (!ak5558->reset_gpiod)
-   return;
-
-   gpiod_set_value_cansleep(ak5558->reset_gpiod, 1);
-   usleep_range(1000, 2000);
+   if (ak5558->reset_gpiod) {
+   gpiod_set_value_cansleep(ak5558->reset_gpiod, active);
+   usleep_range(1000, 2000);
+   }
 }
 
 static int ak5558_probe(struct snd_soc_component *component)
 {
struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component);
 
-   ak5558_power_on(ak5558);
+   ak5558_reset(ak5558, false);
return ak5558_set_mcki(component);
 }
 
@@ -348,7 +338,7 @@ static void ak5558_remove(struct snd_soc_component 
*component)
 {
struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component);
 
-   ak5558_power_off(ak5558);
+   ak5558_reset(ak5558, true);
 }
 
 static int __maybe_unused ak5558_runtime_suspend(struct device *dev)
@@ -356,7 +346,7 @@ static int __maybe_unused ak5558_runtime_suspend(struct 
device *dev)
struct ak5558_priv *ak5558 = dev_get_drvdata(dev);
 
regcache_cache_only(ak5558->regmap, true);
-   ak5558_power_off(ak5558);
+   ak5558_reset(ak5558, true);
 
regulator_bulk_disable(ARRAY_SIZE(ak5558->supplies),
   ak5558->supplies);
@@ -375,8 +365,8 @@ static int __maybe_unused ak5558_runtime_resume(struct 
device *dev)
return ret;
}
 
-   ak5558_power_off(ak5558);
-   ak5558_power_on(ak5558);
+   ak5558_reset(ak5558, true);
+   ak5558_reset(ak5558, false);
 
regcache_cache_only(ak5558->regmap, false);
regcache_mark_dirty(ak5558->regmap);
-- 
2.27.0



Re: [PATCH] ASoC: fsl_sai: Don't use devm_regmap_init_mmio_clk

2021-04-12 Thread Shengjiu Wang
On Sun, Apr 11, 2021 at 10:43 PM Guenter Roeck  wrote:
>
> On Fri, Mar 19, 2021 at 04:06:43PM +0800, Shengjiu Wang wrote:
> > When there is power domain bind with bus clock,
> >
> > The call flow:
> > devm_regmap_init_mmio_clk
> >- clk_prepare()
> >   - clk_pm_runtime_get()
> >
> > cause the power domain of clock always be enabled after
> > regmap_init(). which impact the power consumption.
> >
> > So use devm_regmap_init_mmio instead of
> > devm_regmap_init_mmio_clk, then explicitly enable clock when
> > using by pm_runtime_get(), if CONFIG_PM=n, then
> > fsl_sai_runtime_resume will be explicitly called.
> >
> > Signed-off-by: Shengjiu Wang 
> > Signed-off-by: Viorel Suman 
>
> This patch results in a crash when running mcimx6ul-evk in qemu.
> Reverting it fixes the problem.
>
> Crash and bisect logs attached.
>
> Guenter
>
> ---
> [   19.196778] 8<--- cut here ---
> [   19.197011] Unhandled fault: external abort on non-linefetch (0x808) at 
> 0xd1588000
> [   19.197135] pgd = (ptrval)
> [   19.197203] [d1588000] *pgd=824da811, *pte=0202c653, *ppte=0202c453
> [   19.197764] Internal error: : 808 [#1] SMP ARM
> [   19.197953] Modules linked in:
> [   19.198108] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 
> 5.12.0-rc6-next-20210409 #1
> [   19.198234] Hardware name: Freescale i.MX6 Ultralite (Device Tree)
> [   19.198354] PC is at regmap_mmio_write32le+0x24/0x2c
> [   19.198482] LR is at regmap_mmio_write32le+0x1c/0x2c
> [   19.198544] pc : []lr : []psr: 6093
> [   19.198611] sp : c20b5cf0  ip :   fp : c017a344
> [   19.198669] r10: c217c1b0  r9 : c20b4000  r8 : c26fcc00
> [   19.198729] r7 : 0100  r6 : c26ff580  r5 :   r4 : 0100
> [   19.198801] r3 : d1588000  r2 : 0100  r1 : d1588000  r0 : c26ff580
> [   19.198896] Flags: nZCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment 
> none
> [   19.198982] Control: 10c5387d  Table: 826bc06a  DAC: 0051
> [   19.199060] Register r0 information: slab kmalloc-64 start c26ff580 
> pointer offset 0 size 64
> [   19.199421] Register r1 information: 0-page vmalloc region starting at 
> 0xd1588000 allocated at __devm_ioremap+0x90/0xa4
> [   19.199587] Register r2 information: non-paged memory
> [   19.199667] Register r3 information: 0-page vmalloc region starting at 
> 0xd1588000 allocated at __devm_ioremap+0x90/0xa4
> [   19.199774] Register r4 information: non-paged memory
> [   19.199832] Register r5 information: NULL pointer
> [   19.199888] Register r6 information: slab kmalloc-64 start c26ff580 
> pointer offset 0 size 64
> [   19.18] Register r7 information: non-paged memory
> [   19.200056] Register r8 information: slab kmalloc-1k start c26fcc00 
> pointer offset 0 size 1024
> [   19.200167] Register r9 information: non-slab/vmalloc memory
> [   19.200252] Register r10 information: slab kmalloc-1k start c217c000 
> pointer offset 432 size 1024
> [   19.200367] Register r11 information: non-slab/vmalloc memory
> [   19.200431] Register r12 information: NULL pointer
> [   19.200495] Process swapper/0 (pid: 1, stack limit = 0x(ptrval))
> [   19.200596] Stack: (0xc20b5cf0 to 0xc20b6000)
> [   19.200755] 5ce0: c26ff580  
> 0100 c0965f40
> [   19.200932] 5d00: c26fcc00   c095f3cc c20c c26fcc00 
>  0100
> [   19.201096] 5d20: c269b840  c20b4000 c217c1b0 c017a344 c0961130 
> 0080 c217c010
> [   19.201259] 5d40: c26ff5c0 c0d21354 c217c010 c0946e24  c0946e24 
> c217c114 c094a894
> [   19.201420] 5d60: c217c010 c0946e24 c2173810 c217c114 c2173914 c20b4000 
> c217c1b0 c094a930
> [   19.201582] 5d80: c217c010 c0946e24 c2173810 c094a468 c20c c20b4000 
> c094a6a0 6013
> [   19.201744] 5da0: 0002 cbdc8024 c217c114 5bdc6b72 6013 6013 
> c217c114 0004
> [   19.201906] 5dc0: 0002 cbdc8024 c20b4000 c269b880  c094a6b4 
> c269b840 c217c010
> [   19.202067] 5de0: c217c000 c0d2176c     
> c2176340 c21d5c00
> [   19.202228] 5e00:  6b6c636d 0033 5bdc6b72   
> c217c010 c18d47fc
> [   19.202389] 5e20: c1f70c20  c18d47fc   c093f540 
> c217c010 c1f70c1c
> [   19.202551] 5e40:  c1f70c20  c093cdec c217c010 c18d47fc 
> c18d47fc c20b4000
> [   19.202712] 5e60:  c166e854 c20af880 c093d0fc c217c010  
> c18d47fc c093d418
> [   19.202873] 5e80:  c18d47fc c217c010 c093d484  c18d47fc 
> c093d420 c093aefc
> [   19.203035] 5ea0: c26fe980 c20ae2b0 c214be94 5bdc6b72 c20ae2e4 c18d47fc 
> c26fe980 
> [   19.203196] 5ec0: c187b

[PATCH] ASoC: ak5558: Fix s/show/slow/ typo

2021-04-03 Thread Shengjiu Wang
s/show/slow/

Fixes: 920884777480 ("ASoC: ak5558: Add support for AK5558 ADC driver")
Signed-off-by: Shengjiu Wang 
---
 sound/soc/codecs/ak5558.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c
index 3ac62a281807..8e4dca753f0b 100644
--- a/sound/soc/codecs/ak5558.c
+++ b/sound/soc/codecs/ak5558.c
@@ -75,8 +75,8 @@ static const struct soc_enum ak5552_mono_enum[] = {
 };
 
 static const char * const digfil_texts[] = {
-   "Sharp Roll-Off", "Show Roll-Off",
-   "Short Delay Sharp Roll-Off", "Short Delay Show Roll-Off",
+   "Sharp Roll-Off", "Slow Roll-Off",
+   "Short Delay Sharp Roll-Off", "Short Delay Slow Roll-Off",
 };
 
 static const struct soc_enum ak5558_adcset_enum[] = {
-- 
2.27.0



[PATCH v2 2/2] ASoC: dt-bindings: ak5558: Add compatible string for ak5552

2021-03-31 Thread Shengjiu Wang
Add compatible string "asahi-kasei,ak5552" for ak5552

Signed-off-by: Shengjiu Wang 
Acked-by: Rob Herring 
---
 Documentation/devicetree/bindings/sound/ak5558.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/ak5558.txt 
b/Documentation/devicetree/bindings/sound/ak5558.txt
index 36934098170c..e28708db6686 100644
--- a/Documentation/devicetree/bindings/sound/ak5558.txt
+++ b/Documentation/devicetree/bindings/sound/ak5558.txt
@@ -4,7 +4,7 @@ This device supports I2C mode only.
 
 Required properties:
 
-- compatible : "asahi-kasei,ak5558"
+- compatible : "asahi-kasei,ak5558" or "asahi-kasei,ak5552".
 - reg : The I2C address of the device.
 
 Optional properties:
-- 
2.27.0



[PATCH v2 1/2] ASoC: ak5558: Add support for ak5552

2021-03-31 Thread Shengjiu Wang
From: Viorel Suman 

AK5552 is a 32-bit 2ch ADC and has the same register
map as AK5558.

Signed-off-by: Viorel Suman 
Signed-off-by: Shengjiu Wang 
---
changes in v2
- refine the control name.

 sound/soc/codecs/ak5558.c | 97 ---
 1 file changed, 90 insertions(+), 7 deletions(-)

diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c
index 85bdd0534180..3ac62a281807 100644
--- a/sound/soc/codecs/ak5558.c
+++ b/sound/soc/codecs/ak5558.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,6 +24,11 @@
 
 #include "ak5558.h"
 
+enum ak555x_type {
+   AK5558,
+   AK5552,
+};
+
 #define AK5558_NUM_SUPPLIES 2
 static const char *ak5558_supply_names[AK5558_NUM_SUPPLIES] = {
"DVDD",
@@ -59,6 +65,15 @@ static const struct soc_enum ak5558_mono_enum[] = {
ARRAY_SIZE(mono_texts), mono_texts),
 };
 
+static const char * const mono_5552_texts[] = {
+   "2 Slot", "1 Slot (Fixed)", "2 Slot", "1 Slot (Optimal)",
+};
+
+static const struct soc_enum ak5552_mono_enum[] = {
+   SOC_ENUM_SINGLE(AK5558_01_POWER_MANAGEMENT2, 1,
+   ARRAY_SIZE(mono_5552_texts), mono_5552_texts),
+};
+
 static const char * const digfil_texts[] = {
"Sharp Roll-Off", "Show Roll-Off",
"Short Delay Sharp Roll-Off", "Short Delay Show Roll-Off",
@@ -70,8 +85,13 @@ static const struct soc_enum ak5558_adcset_enum[] = {
 };
 
 static const struct snd_kcontrol_new ak5558_snd_controls[] = {
-   SOC_ENUM("AK5558 Monaural Mode", ak5558_mono_enum[0]),
-   SOC_ENUM("AK5558 Digital Filter", ak5558_adcset_enum[0]),
+   SOC_ENUM("Monaural Mode", ak5558_mono_enum[0]),
+   SOC_ENUM("Digital Filter", ak5558_adcset_enum[0]),
+};
+
+static const struct snd_kcontrol_new ak5552_snd_controls[] = {
+   SOC_ENUM("Monaural Mode", ak5552_mono_enum[0]),
+   SOC_ENUM("Digital Filter", ak5558_adcset_enum[0]),
 };
 
 static const struct snd_soc_dapm_widget ak5558_dapm_widgets[] = {
@@ -97,6 +117,17 @@ static const struct snd_soc_dapm_widget 
ak5558_dapm_widgets[] = {
SND_SOC_DAPM_AIF_OUT("SDTO", "Capture", 0, SND_SOC_NOPM, 0, 0),
 };
 
+static const struct snd_soc_dapm_widget ak5552_dapm_widgets[] = {
+   /* Analog Input */
+   SND_SOC_DAPM_INPUT("AIN1"),
+   SND_SOC_DAPM_INPUT("AIN2"),
+
+   SND_SOC_DAPM_ADC("ADC Ch1", NULL, AK5558_00_POWER_MANAGEMENT1, 0, 0),
+   SND_SOC_DAPM_ADC("ADC Ch2", NULL, AK5558_00_POWER_MANAGEMENT1, 1, 0),
+
+   SND_SOC_DAPM_AIF_OUT("SDTO", "Capture", 0, SND_SOC_NOPM, 0, 0),
+};
+
 static const struct snd_soc_dapm_route ak5558_intercon[] = {
{"ADC Ch1", NULL, "AIN1"},
{"SDTO", NULL, "ADC Ch1"},
@@ -123,6 +154,14 @@ static const struct snd_soc_dapm_route ak5558_intercon[] = 
{
{"SDTO", NULL, "ADC Ch8"},
 };
 
+static const struct snd_soc_dapm_route ak5552_intercon[] = {
+   {"ADC Ch1", NULL, "AIN1"},
+   {"SDTO", NULL, "ADC Ch1"},
+
+   {"ADC Ch2", NULL, "AIN2"},
+   {"SDTO", NULL, "ADC Ch2"},
+};
+
 static int ak5558_set_mcki(struct snd_soc_component *component)
 {
return snd_soc_component_update_bits(component, AK5558_02_CONTROL1, 
AK5558_CKS,
@@ -267,6 +306,18 @@ static struct snd_soc_dai_driver ak5558_dai = {
.ops = _dai_ops,
 };
 
+static struct snd_soc_dai_driver ak5552_dai = {
+   .name = "ak5558-aif",
+   .capture = {
+   .stream_name = "Capture",
+   .channels_min = 1,
+   .channels_max = 2,
+   .rates = SNDRV_PCM_RATE_KNOT,
+   .formats = AK5558_FORMATS,
+   },
+   .ops = _dai_ops,
+};
+
 static void ak5558_power_off(struct ak5558_priv *ak5558)
 {
if (!ak5558->reset_gpiod)
@@ -354,6 +405,21 @@ static const struct snd_soc_component_driver 
soc_codec_dev_ak5558 = {
.non_legacy_dai_naming  = 1,
 };
 
+static const struct snd_soc_component_driver soc_codec_dev_ak5552 = {
+   .probe  = ak5558_probe,
+   .remove = ak5558_remove,
+   .controls   = ak5552_snd_controls,
+   .num_controls   = ARRAY_SIZE(ak5552_snd_controls),
+   .dapm_widgets   = ak5552_dapm_widgets,
+   .num_dapm_widgets   = ARRAY_SIZE(ak5552_dapm_widgets),
+   .dapm_routes= ak5552_intercon,
+   .num_dapm_routes= ARRAY_SIZE(ak5552_intercon),
+   .idle_bias_on   = 1,
+   .use_pmdown_time= 1,
+   .endianness = 1,
+   .non_legacy_dai_naming  = 1,
+};
+
 st

Re: [PATCH 1/2] ASoC: ak5558: Add support for ak5552

2021-03-30 Thread Shengjiu Wang
On Tue, Mar 30, 2021 at 11:06 PM Mark Brown  wrote:
>
> On Tue, Mar 30, 2021 at 02:32:51PM +0800, Shengjiu Wang wrote:
>
> > +static const struct snd_kcontrol_new ak5552_snd_controls[] = {
> > + SOC_ENUM("AK5552 Monaural Mode", ak5552_mono_enum[0]),
> > + SOC_ENUM("AK5552 Digital Filter", ak5558_adcset_enum[0]),
> > +};
>
> It's a bit weird to have AK5552 in the control name - any reason for
> that?

Just to distinguish ak5558 and ak5552, but I think it can be removed.
will update it in v2

Best regards
wang shengjiu


[PATCH 2/2] ASoC: dt-bindings: ak5558: Add compatible string for ak5552

2021-03-30 Thread Shengjiu Wang
Add compatible string "asahi-kasei,ak5552" for ak5552

Signed-off-by: Shengjiu Wang 
---
 Documentation/devicetree/bindings/sound/ak5558.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/ak5558.txt 
b/Documentation/devicetree/bindings/sound/ak5558.txt
index 36934098170c..e28708db6686 100644
--- a/Documentation/devicetree/bindings/sound/ak5558.txt
+++ b/Documentation/devicetree/bindings/sound/ak5558.txt
@@ -4,7 +4,7 @@ This device supports I2C mode only.
 
 Required properties:
 
-- compatible : "asahi-kasei,ak5558"
+- compatible : "asahi-kasei,ak5558" or "asahi-kasei,ak5552".
 - reg : The I2C address of the device.
 
 Optional properties:
-- 
2.27.0



[PATCH 1/2] ASoC: ak5558: Add support for ak5552

2021-03-30 Thread Shengjiu Wang
From: Viorel Suman 

AK5552 is a 32-bit 2ch ADC and has the same register
map as AK5558.

Signed-off-by: Viorel Suman 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/codecs/ak5558.c | 93 ---
 1 file changed, 88 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c
index 85bdd0534180..af12afa83b4f 100644
--- a/sound/soc/codecs/ak5558.c
+++ b/sound/soc/codecs/ak5558.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,6 +24,11 @@
 
 #include "ak5558.h"
 
+enum ak555x_type {
+   AK5558,
+   AK5552,
+};
+
 #define AK5558_NUM_SUPPLIES 2
 static const char *ak5558_supply_names[AK5558_NUM_SUPPLIES] = {
"DVDD",
@@ -59,6 +65,15 @@ static const struct soc_enum ak5558_mono_enum[] = {
ARRAY_SIZE(mono_texts), mono_texts),
 };
 
+static const char * const mono_5552_texts[] = {
+   "2 Slot", "1 Slot (Fixed)", "2 Slot", "1 Slot (Optimal)",
+};
+
+static const struct soc_enum ak5552_mono_enum[] = {
+   SOC_ENUM_SINGLE(AK5558_01_POWER_MANAGEMENT2, 1,
+   ARRAY_SIZE(mono_5552_texts), mono_5552_texts),
+};
+
 static const char * const digfil_texts[] = {
"Sharp Roll-Off", "Show Roll-Off",
"Short Delay Sharp Roll-Off", "Short Delay Show Roll-Off",
@@ -74,6 +89,11 @@ static const struct snd_kcontrol_new ak5558_snd_controls[] = 
{
SOC_ENUM("AK5558 Digital Filter", ak5558_adcset_enum[0]),
 };
 
+static const struct snd_kcontrol_new ak5552_snd_controls[] = {
+   SOC_ENUM("AK5552 Monaural Mode", ak5552_mono_enum[0]),
+   SOC_ENUM("AK5552 Digital Filter", ak5558_adcset_enum[0]),
+};
+
 static const struct snd_soc_dapm_widget ak5558_dapm_widgets[] = {
/* Analog Input */
SND_SOC_DAPM_INPUT("AIN1"),
@@ -97,6 +117,17 @@ static const struct snd_soc_dapm_widget 
ak5558_dapm_widgets[] = {
SND_SOC_DAPM_AIF_OUT("SDTO", "Capture", 0, SND_SOC_NOPM, 0, 0),
 };
 
+static const struct snd_soc_dapm_widget ak5552_dapm_widgets[] = {
+   /* Analog Input */
+   SND_SOC_DAPM_INPUT("AIN1"),
+   SND_SOC_DAPM_INPUT("AIN2"),
+
+   SND_SOC_DAPM_ADC("ADC Ch1", NULL, AK5558_00_POWER_MANAGEMENT1, 0, 0),
+   SND_SOC_DAPM_ADC("ADC Ch2", NULL, AK5558_00_POWER_MANAGEMENT1, 1, 0),
+
+   SND_SOC_DAPM_AIF_OUT("SDTO", "Capture", 0, SND_SOC_NOPM, 0, 0),
+};
+
 static const struct snd_soc_dapm_route ak5558_intercon[] = {
{"ADC Ch1", NULL, "AIN1"},
{"SDTO", NULL, "ADC Ch1"},
@@ -123,6 +154,14 @@ static const struct snd_soc_dapm_route ak5558_intercon[] = 
{
{"SDTO", NULL, "ADC Ch8"},
 };
 
+static const struct snd_soc_dapm_route ak5552_intercon[] = {
+   {"ADC Ch1", NULL, "AIN1"},
+   {"SDTO", NULL, "ADC Ch1"},
+
+   {"ADC Ch2", NULL, "AIN2"},
+   {"SDTO", NULL, "ADC Ch2"},
+};
+
 static int ak5558_set_mcki(struct snd_soc_component *component)
 {
return snd_soc_component_update_bits(component, AK5558_02_CONTROL1, 
AK5558_CKS,
@@ -267,6 +306,18 @@ static struct snd_soc_dai_driver ak5558_dai = {
.ops = _dai_ops,
 };
 
+static struct snd_soc_dai_driver ak5552_dai = {
+   .name = "ak5558-aif",
+   .capture = {
+   .stream_name = "Capture",
+   .channels_min = 1,
+   .channels_max = 2,
+   .rates = SNDRV_PCM_RATE_KNOT,
+   .formats = AK5558_FORMATS,
+   },
+   .ops = _dai_ops,
+};
+
 static void ak5558_power_off(struct ak5558_priv *ak5558)
 {
if (!ak5558->reset_gpiod)
@@ -354,6 +405,21 @@ static const struct snd_soc_component_driver 
soc_codec_dev_ak5558 = {
.non_legacy_dai_naming  = 1,
 };
 
+static const struct snd_soc_component_driver soc_codec_dev_ak5552 = {
+   .probe  = ak5558_probe,
+   .remove = ak5558_remove,
+   .controls   = ak5552_snd_controls,
+   .num_controls   = ARRAY_SIZE(ak5552_snd_controls),
+   .dapm_widgets   = ak5552_dapm_widgets,
+   .num_dapm_widgets   = ARRAY_SIZE(ak5552_dapm_widgets),
+   .dapm_routes= ak5552_intercon,
+   .num_dapm_routes= ARRAY_SIZE(ak5552_intercon),
+   .idle_bias_on   = 1,
+   .use_pmdown_time= 1,
+   .endianness = 1,
+   .non_legacy_dai_naming  = 1,
+};
+
 static const struct regmap_config ak5558_regmap = {
.reg_bits = 8,
.val_bits = 8,
@@ -368,6 +434,7 @@ static int ak5558_i2c_probe(struct i2c_client *i2c)
 {
struct ak5558_priv *ak5558;
   

[PATCH] ASoC: fsl_rpmsg: initialise pointers to NULL

2021-03-28 Thread Shengjiu Wang
This fixes the following sparse warnings:

sound/soc/fsl/fsl_rpmsg.c:45:45: sparse: sparse: Using plain integer as NULL 
pointer
sound/soc/fsl/fsl_rpmsg.c:45:56: sparse: sparse: Using plain integer as NULL 
pointer

Fixes: b73d9e6225e8 ("ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on 
rpmsg")
Signed-off-by: Shengjiu Wang 
Reported-by: kernel test robot 
---
 sound/soc/fsl/fsl_rpmsg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c
index 2d09d8850e2c..ea5c973e2e84 100644
--- a/sound/soc/fsl/fsl_rpmsg.c
+++ b/sound/soc/fsl/fsl_rpmsg.c
@@ -42,7 +42,7 @@ static int fsl_rpmsg_hw_params(struct snd_pcm_substream 
*substream,
   struct snd_soc_dai *dai)
 {
struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai);
-   struct clk *p = rpmsg->mclk, *pll = 0, *npll = 0;
+   struct clk *p = rpmsg->mclk, *pll = NULL, *npll = NULL;
u64 rate = params_rate(params);
int ret = 0;
 
-- 
2.17.1



[PATCH 0/6] ASoC: fsl: Don't use devm_regmap_init_mmio_clk

2021-03-24 Thread Shengjiu Wang
When there is power domain bind with ipg clock,

The call flow:
devm_regmap_init_mmio_clk
- clk_prepare()
- clk_pm_runtime_get()

cause the power domain of clock always be enabled after
regmap_init(). which impact the power consumption.

So use devm_regmap_init_mmio instead of
devm_regmap_init_mmio_clk.

Shengjiu Wang (6):
  ASoC: fsl_esai: Don't use devm_regmap_init_mmio_clk
  ASoC: fsl_spdif: Don't use devm_regmap_init_mmio_clk
  ASoC: fsl_asrc: Don't use devm_regmap_init_mmio_clk
  ASoC: fsl_easrc: Don't use devm_regmap_init_mmio_clk
  ASoC: fsl_audmix: Don't use devm_regmap_init_mmio_clk
  ASoC: fsl_micfil: Don't use devm_regmap_init_mmio_clk

 sound/soc/fsl/fsl_asrc.c   | 57 +-
 sound/soc/fsl/fsl_audmix.c |  3 +-
 sound/soc/fsl/fsl_easrc.c  |  3 +-
 sound/soc/fsl/fsl_esai.c   | 48 
 sound/soc/fsl/fsl_micfil.c | 25 +
 sound/soc/fsl/fsl_spdif.c  |  3 +-
 6 files changed, 103 insertions(+), 36 deletions(-)

-- 
2.27.0



[PATCH 4/6] ASoC: fsl_easrc: Don't use devm_regmap_init_mmio_clk

2021-03-24 Thread Shengjiu Wang
When there is power domain bind with mem clock,

The call flow:
devm_regmap_init_mmio_clk
  - clk_prepare()
  - clk_pm_runtime_get()

cause the power domain of clock always be enabled after
regmap_init(). which impact the power consumption.

So use devm_regmap_init_mmio instead of
devm_regmap_init_mmio_clk,but explicitly enable
clock when it is used.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_easrc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 600e0d670ca6..5e33afe87c4a 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1896,8 +1896,7 @@ static int fsl_easrc_probe(struct platform_device *pdev)
 
easrc->paddr = res->start;
 
-   easrc->regmap = devm_regmap_init_mmio_clk(dev, "mem", regs,
- _easrc_regmap_config);
+   easrc->regmap = devm_regmap_init_mmio(dev, regs, 
_easrc_regmap_config);
if (IS_ERR(easrc->regmap)) {
dev_err(dev, "failed to init regmap");
return PTR_ERR(easrc->regmap);
-- 
2.27.0



[PATCH 6/6] ASoC: fsl_micfil: Don't use devm_regmap_init_mmio_clk

2021-03-24 Thread Shengjiu Wang
When there is power domain bind with ipg_clk clock,

The call flow:
devm_regmap_init_mmio_clk
   - clk_prepare()
  - clk_pm_runtime_get()

cause the power domain of clock always be enabled after
regmap_init(). which impact the power consumption.

So use devm_regmap_init_mmio instead of
devm_regmap_init_mmio_clk,but explicitly enable
clock when it is used.

Signed-off-by: Shengjiu Wang 
Reviewed-by: Viorel Suman 
---
 sound/soc/fsl/fsl_micfil.c | 25 -
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
index 2b9edd4bb94d..3cf789ed6cbe 100644
--- a/sound/soc/fsl/fsl_micfil.c
+++ b/sound/soc/fsl/fsl_micfil.c
@@ -31,6 +31,7 @@ struct fsl_micfil {
struct platform_device *pdev;
struct regmap *regmap;
const struct fsl_micfil_soc_data *soc;
+   struct clk *busclk;
struct clk *mclk;
struct snd_dmaengine_dai_dma_data dma_params_rx;
unsigned int dataline;
@@ -660,16 +661,22 @@ static int fsl_micfil_probe(struct platform_device *pdev)
return PTR_ERR(micfil->mclk);
}
 
+   micfil->busclk = devm_clk_get(>dev, "ipg_clk");
+   if (IS_ERR(micfil->busclk)) {
+   dev_err(>dev, "failed to get ipg clock: %ld\n",
+   PTR_ERR(micfil->busclk));
+   return PTR_ERR(micfil->busclk);
+   }
+
/* init regmap */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(>dev, res);
if (IS_ERR(regs))
return PTR_ERR(regs);
 
-   micfil->regmap = devm_regmap_init_mmio_clk(>dev,
-  "ipg_clk",
-  regs,
-  _micfil_regmap_config);
+   micfil->regmap = devm_regmap_init_mmio(>dev,
+  regs,
+  _micfil_regmap_config);
if (IS_ERR(micfil->regmap)) {
dev_err(>dev, "failed to init MICFIL regmap: %ld\n",
PTR_ERR(micfil->regmap));
@@ -729,6 +736,7 @@ static int fsl_micfil_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, micfil);
 
pm_runtime_enable(>dev);
+   regcache_cache_only(micfil->regmap, true);
 
ret = devm_snd_soc_register_component(>dev, _micfil_component,
  _micfil_dai, 1);
@@ -752,6 +760,7 @@ static int __maybe_unused fsl_micfil_runtime_suspend(struct 
device *dev)
regcache_cache_only(micfil->regmap, true);
 
clk_disable_unprepare(micfil->mclk);
+   clk_disable_unprepare(micfil->busclk);
 
return 0;
 }
@@ -761,10 +770,16 @@ static int __maybe_unused 
fsl_micfil_runtime_resume(struct device *dev)
struct fsl_micfil *micfil = dev_get_drvdata(dev);
int ret;
 
-   ret = clk_prepare_enable(micfil->mclk);
+   ret = clk_prepare_enable(micfil->busclk);
if (ret < 0)
return ret;
 
+   ret = clk_prepare_enable(micfil->mclk);
+   if (ret < 0) {
+   clk_disable_unprepare(micfil->busclk);
+   return ret;
+   }
+
regcache_cache_only(micfil->regmap, false);
regcache_mark_dirty(micfil->regmap);
regcache_sync(micfil->regmap);
-- 
2.27.0



[PATCH 2/6] ASoC: fsl_spdif: Don't use devm_regmap_init_mmio_clk

2021-03-24 Thread Shengjiu Wang
When there is power domain bind with core clock,

The call flow:
devm_regmap_init_mmio_clk
   - clk_prepare()
   - clk_pm_runtime_get()

cause the power domain of clock always be enabled after
regmap_init(). which impact the power consumption.

So use devm_regmap_init_mmio instead of
devm_regmap_init_mmio_clk,but explicitly enable
clock when it is used.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_spdif.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 1cd3441d1c03..c631de325a6e 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -1294,8 +1294,7 @@ static int fsl_spdif_probe(struct platform_device *pdev)
if (IS_ERR(regs))
return PTR_ERR(regs);
 
-   spdif_priv->regmap = devm_regmap_init_mmio_clk(>dev,
-   "core", regs, _spdif_regmap_config);
+   spdif_priv->regmap = devm_regmap_init_mmio(>dev, regs, 
_spdif_regmap_config);
if (IS_ERR(spdif_priv->regmap)) {
dev_err(>dev, "regmap init failed\n");
return PTR_ERR(spdif_priv->regmap);
-- 
2.27.0



[PATCH 1/6] ASoC: fsl_esai: Don't use devm_regmap_init_mmio_clk

2021-03-24 Thread Shengjiu Wang
When there is power domain bind with bus clock,

The call flow:
devm_regmap_init_mmio_clk
- clk_prepare()
   - clk_pm_runtime_get()

cause the power domain of clock always be enabled after
regmap_init(). which impact the power consumption.

So use devm_regmap_init_mmio instead of
devm_regmap_init_mmio_clk,but explicitly enable
clock when it is used.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_esai.c | 48 ++--
 1 file changed, 36 insertions(+), 12 deletions(-)

diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 41b154417b92..c0d4f3c5dbb1 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -945,6 +945,9 @@ static const struct regmap_config fsl_esai_regmap_config = {
.cache_type = REGCACHE_FLAT,
 };
 
+static int fsl_esai_runtime_resume(struct device *dev);
+static int fsl_esai_runtime_suspend(struct device *dev);
+
 static int fsl_esai_probe(struct platform_device *pdev)
 {
struct device_node *np = pdev->dev.of_node;
@@ -969,8 +972,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
if (IS_ERR(regs))
return PTR_ERR(regs);
 
-   esai_priv->regmap = devm_regmap_init_mmio_clk(>dev,
-   "core", regs, _esai_regmap_config);
+   esai_priv->regmap = devm_regmap_init_mmio(>dev, regs, 
_esai_regmap_config);
if (IS_ERR(esai_priv->regmap)) {
dev_err(>dev, "failed to init regmap: %ld\n",
PTR_ERR(esai_priv->regmap));
@@ -1039,11 +1041,23 @@ static int fsl_esai_probe(struct platform_device *pdev)
}
 
dev_set_drvdata(>dev, esai_priv);
-
spin_lock_init(_priv->lock);
+   pm_runtime_enable(>dev);
+   if (!pm_runtime_enabled(>dev)) {
+   ret = fsl_esai_runtime_resume(>dev);
+   if (ret)
+   goto err_pm_disable;
+   }
+
+   ret = pm_runtime_get_sync(>dev);
+   if (ret < 0) {
+   pm_runtime_put_noidle(>dev);
+   goto err_pm_get_sync;
+   }
+
ret = fsl_esai_hw_init(esai_priv);
if (ret)
-   return ret;
+   goto err_pm_get_sync;
 
esai_priv->tx_mask = 0x;
esai_priv->rx_mask = 0x;
@@ -1054,24 +1068,33 @@ static int fsl_esai_probe(struct platform_device *pdev)
regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0);
regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0);
 
+   ret = pm_runtime_put_sync(>dev);
+   if (ret < 0)
+   goto err_pm_get_sync;
+
ret = devm_snd_soc_register_component(>dev, _esai_component,
  _esai_dai, 1);
if (ret) {
dev_err(>dev, "failed to register DAI: %d\n", ret);
-   return ret;
+   goto err_pm_get_sync;
}
 
INIT_WORK(_priv->work, fsl_esai_hw_reset);
 
-   pm_runtime_enable(>dev);
-
-   regcache_cache_only(esai_priv->regmap, true);
-
ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE);
-   if (ret)
+   if (ret) {
dev_err(>dev, "failed to init imx pcm dma: %d\n", ret);
+   goto err_pm_get_sync;
+   }
 
return ret;
+
+err_pm_get_sync:
+   if (!pm_runtime_status_suspended(>dev))
+   fsl_esai_runtime_suspend(>dev);
+err_pm_disable:
+   pm_runtime_disable(>dev);
+   return ret;
 }
 
 static int fsl_esai_remove(struct platform_device *pdev)
@@ -1079,6 +1102,9 @@ static int fsl_esai_remove(struct platform_device *pdev)
struct fsl_esai *esai_priv = platform_get_drvdata(pdev);
 
pm_runtime_disable(>dev);
+   if (!pm_runtime_status_suspended(>dev))
+   fsl_esai_runtime_suspend(>dev);
+
cancel_work_sync(_priv->work);
 
return 0;
@@ -1092,7 +1118,6 @@ static const struct of_device_id fsl_esai_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
 
-#ifdef CONFIG_PM
 static int fsl_esai_runtime_resume(struct device *dev)
 {
struct fsl_esai *esai = dev_get_drvdata(dev);
@@ -1160,7 +1185,6 @@ static int fsl_esai_runtime_suspend(struct device *dev)
 
return 0;
 }
-#endif /* CONFIG_PM */
 
 static const struct dev_pm_ops fsl_esai_pm_ops = {
SET_RUNTIME_PM_OPS(fsl_esai_runtime_suspend,
-- 
2.27.0



[PATCH 5/6] ASoC: fsl_audmix: Don't use devm_regmap_init_mmio_clk

2021-03-24 Thread Shengjiu Wang
When there is power domain bind with ipg clock,

The call flow:
devm_regmap_init_mmio_clk
   - clk_prepare()
   - clk_pm_runtime_get()

cause the power domain of clock always be enabled after
regmap_init(). which impact the power consumption.

So use devm_regmap_init_mmio instead of
devm_regmap_init_mmio_clk,but explicitly enable
clock when it is used.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_audmix.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c
index 8dc44dec7956..f931288e256c 100644
--- a/sound/soc/fsl/fsl_audmix.c
+++ b/sound/soc/fsl/fsl_audmix.c
@@ -476,8 +476,7 @@ static int fsl_audmix_probe(struct platform_device *pdev)
if (IS_ERR(regs))
return PTR_ERR(regs);
 
-   priv->regmap = devm_regmap_init_mmio_clk(dev, "ipg", regs,
-_audmix_regmap_config);
+   priv->regmap = devm_regmap_init_mmio(dev, regs, 
_audmix_regmap_config);
if (IS_ERR(priv->regmap)) {
dev_err(dev, "failed to init regmap\n");
return PTR_ERR(priv->regmap);
-- 
2.27.0



[PATCH 3/6] ASoC: fsl_asrc: Don't use devm_regmap_init_mmio_clk

2021-03-24 Thread Shengjiu Wang
When there is power domain bind with mem clock,

The call flow:
devm_regmap_init_mmio_clk
   - clk_prepare()
   - clk_pm_runtime_get()

cause the power domain of clock always be enabled after
regmap_init(). which impact the power consumption.

So use devm_regmap_init_mmio instead of
devm_regmap_init_mmio_clk,but explicitly enable
clock when it is used.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_asrc.c | 57 +++-
 1 file changed, 44 insertions(+), 13 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 63d236ef5c4d..0e1ad8efebd3 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1008,6 +1008,9 @@ static int fsl_asrc_get_fifo_addr(u8 dir, enum 
asrc_pair_index index)
return REG_ASRDx(dir, index);
 }
 
+static int fsl_asrc_runtime_resume(struct device *dev);
+static int fsl_asrc_runtime_suspend(struct device *dev);
+
 static int fsl_asrc_probe(struct platform_device *pdev)
 {
struct device_node *np = pdev->dev.of_node;
@@ -1039,8 +1042,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
 
asrc->paddr = res->start;
 
-   asrc->regmap = devm_regmap_init_mmio_clk(>dev, "mem", regs,
-_asrc_regmap_config);
+   asrc->regmap = devm_regmap_init_mmio(>dev, regs, 
_asrc_regmap_config);
if (IS_ERR(asrc->regmap)) {
dev_err(>dev, "failed to init regmap\n");
return PTR_ERR(asrc->regmap);
@@ -1117,12 +1119,6 @@ static int fsl_asrc_probe(struct platform_device *pdev)
}
}
 
-   ret = fsl_asrc_init(asrc);
-   if (ret) {
-   dev_err(>dev, "failed to init asrc %d\n", ret);
-   return ret;
-   }
-
asrc->channel_avail = 10;
 
ret = of_property_read_u32(np, "fsl,asrc-rate",
@@ -1161,21 +1157,56 @@ static int fsl_asrc_probe(struct platform_device *pdev)
}
 
platform_set_drvdata(pdev, asrc);
-   pm_runtime_enable(>dev);
spin_lock_init(>lock);
-   regcache_cache_only(asrc->regmap, true);
+   pm_runtime_enable(>dev);
+   if (!pm_runtime_enabled(>dev)) {
+   ret = fsl_asrc_runtime_resume(>dev);
+   if (ret)
+   goto err_pm_disable;
+   }
+
+   ret = pm_runtime_get_sync(>dev);
+   if (ret < 0) {
+   pm_runtime_put_noidle(>dev);
+   goto err_pm_get_sync;
+   }
+
+   ret = fsl_asrc_init(asrc);
+   if (ret) {
+   dev_err(>dev, "failed to init asrc %d\n", ret);
+   goto err_pm_get_sync;
+   }
+
+   ret = pm_runtime_put_sync(>dev);
+   if (ret < 0)
+   goto err_pm_get_sync;
 
ret = devm_snd_soc_register_component(>dev, _asrc_component,
  _asrc_dai, 1);
if (ret) {
dev_err(>dev, "failed to register ASoC DAI\n");
-   return ret;
+   goto err_pm_get_sync;
}
 
return 0;
+
+err_pm_get_sync:
+   if (!pm_runtime_status_suspended(>dev))
+   fsl_asrc_runtime_suspend(>dev);
+err_pm_disable:
+   pm_runtime_disable(>dev);
+   return ret;
+}
+
+static int fsl_asrc_remove(struct platform_device *pdev)
+{
+   pm_runtime_disable(>dev);
+   if (!pm_runtime_status_suspended(>dev))
+   fsl_asrc_runtime_suspend(>dev);
+
+   return 0;
 }
 
-#ifdef CONFIG_PM
 static int fsl_asrc_runtime_resume(struct device *dev)
 {
struct fsl_asrc *asrc = dev_get_drvdata(dev);
@@ -1252,7 +1283,6 @@ static int fsl_asrc_runtime_suspend(struct device *dev)
 
return 0;
 }
-#endif /* CONFIG_PM */
 
 static const struct dev_pm_ops fsl_asrc_pm = {
SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, 
NULL)
@@ -1291,6 +1321,7 @@ MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
 
 static struct platform_driver fsl_asrc_driver = {
.probe = fsl_asrc_probe,
+   .remove = fsl_asrc_remove,
.driver = {
.name = "fsl-asrc",
.of_match_table = fsl_asrc_ids,
-- 
2.27.0



Re: [RESEND PATCH v2] ASoC: wm8960: Remove bitclk relax condition in wm8960_configure_sysclk

2021-03-23 Thread Shengjiu Wang
Hi Mark

On Wed, Mar 10, 2021 at 9:26 PM Mark Brown  wrote:
>
> On Wed, Mar 10, 2021 at 10:00:42AM +0800, Shengjiu Wang wrote:
>
> > changes in resend v2
> > - Add acked-by Charles
>
> Please don't resend for acks, it just makes for more noise.

ok, but could you please review this patch?

Best regards
wang shengjiu


[PATCH] ASoC: wm8960: Fix wrong bclk and lrclk with pll enabled for some chips

2021-03-19 Thread Shengjiu Wang
The input MCLK is 12.288MHz, the desired output sysclk is 11.2896MHz
and sample rate is 44100Hz, with the configuration pllprescale=2,
postscale=sysclkdiv=1, some chip may have wrong bclk
and lrclk output with pll enabled in master mode, but with the
configuration pllprescale=1, postscale=2, the output clock is correct.

>From Datasheet, the PLL performs best when f2 is between
90MHz and 100MHz when the desired sysclk output is 11.2896MHz
or 12.288MHz, so sysclkdiv = 2 (f2/8) is the best choice.

So search available sysclk_divs from 2 to 1 other than from 1 to 2.

Fixes: 84fdc00d519f ("ASoC: codec: wm9860: Refactor PLL out freq search")
Signed-off-by: Shengjiu Wang 
---
 sound/soc/codecs/wm8960.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index df351519a3a6..cda9cd935d4f 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -707,7 +707,13 @@ int wm8960_configure_pll(struct snd_soc_component 
*component, int freq_in,
best_freq_out = -EINVAL;
*sysclk_idx = *dac_idx = *bclk_idx = -1;
 
-   for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
+   /*
+* From Datasheet, the PLL performs best when f2 is between
+* 90MHz and 100MHz, the desired sysclk output is 11.2896MHz
+* or 12.288MHz, then sysclkdiv = 2 is the best choice.
+* So search sysclk_divs from 2 to 1 other than from 1 to 2.
+*/
+   for (i = ARRAY_SIZE(sysclk_divs) - 1; i >= 0; --i) {
if (sysclk_divs[i] == -1)
continue;
for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {
-- 
2.17.1



[PATCH] ASoC: fsl_sai: Don't use devm_regmap_init_mmio_clk

2021-03-19 Thread Shengjiu Wang
When there is power domain bind with bus clock,

The call flow:
devm_regmap_init_mmio_clk
   - clk_prepare()
  - clk_pm_runtime_get()

cause the power domain of clock always be enabled after
regmap_init(). which impact the power consumption.

So use devm_regmap_init_mmio instead of
devm_regmap_init_mmio_clk, then explicitly enable clock when
using by pm_runtime_get(), if CONFIG_PM=n, then
fsl_sai_runtime_resume will be explicitly called.

Signed-off-by: Shengjiu Wang 
Signed-off-by: Viorel Suman 
---
 sound/soc/fsl/fsl_sai.c | 48 +++--
 1 file changed, 32 insertions(+), 16 deletions(-)

diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 9e7893f91882..f2c70a31c7bb 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -987,6 +987,9 @@ static int fsl_sai_check_version(struct device *dev)
return 0;
 }
 
+static int fsl_sai_runtime_suspend(struct device *dev);
+static int fsl_sai_runtime_resume(struct device *dev);
+
 static int fsl_sai_probe(struct platform_device *pdev)
 {
struct device_node *np = pdev->dev.of_node;
@@ -1019,24 +1022,21 @@ static int fsl_sai_probe(struct platform_device *pdev)
ARRAY_SIZE(fsl_sai_reg_defaults_ofs8);
}
 
-   sai->regmap = devm_regmap_init_mmio_clk(>dev,
-   "bus", base, _sai_regmap_config);
-
-   /* Compatible with old DTB cases */
-   if (IS_ERR(sai->regmap) && PTR_ERR(sai->regmap) != -EPROBE_DEFER)
-   sai->regmap = devm_regmap_init_mmio_clk(>dev,
-   "sai", base, _sai_regmap_config);
+   sai->regmap = devm_regmap_init_mmio(>dev, base, 
_sai_regmap_config);
if (IS_ERR(sai->regmap)) {
dev_err(>dev, "regmap init failed\n");
return PTR_ERR(sai->regmap);
}
 
-   /* No error out for old DTB cases but only mark the clock NULL */
sai->bus_clk = devm_clk_get(>dev, "bus");
+   /* Compatible with old DTB cases */
+   if (IS_ERR(sai->bus_clk) && PTR_ERR(sai->bus_clk) != -EPROBE_DEFER)
+   sai->bus_clk = devm_clk_get(>dev, "sai");
if (IS_ERR(sai->bus_clk)) {
dev_err(>dev, "failed to get bus clock: %ld\n",
PTR_ERR(sai->bus_clk));
-   sai->bus_clk = NULL;
+   /* -EPROBE_DEFER */
+   return PTR_ERR(sai->bus_clk);
}
 
for (i = 1; i < FSL_SAI_MCLK_MAX; i++) {
@@ -1117,6 +1117,18 @@ static int fsl_sai_probe(struct platform_device *pdev)
sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
 
platform_set_drvdata(pdev, sai);
+   pm_runtime_enable(>dev);
+   if (!pm_runtime_enabled(>dev)) {
+   ret = fsl_sai_runtime_resume(>dev);
+   if (ret)
+   goto err_pm_disable;
+   }
+
+   ret = pm_runtime_get_sync(>dev);
+   if (ret < 0) {
+   pm_runtime_put_noidle(>dev);
+   goto err_pm_get_sync;
+   }
 
/* Get sai version */
ret = fsl_sai_check_version(>dev);
@@ -1130,26 +1142,30 @@ static int fsl_sai_probe(struct platform_device *pdev)
   FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
}
 
-   pm_runtime_enable(>dev);
-   regcache_cache_only(sai->regmap, true);
+   ret = pm_runtime_put_sync(>dev);
+   if (ret < 0)
+   goto err_pm_get_sync;
 
ret = devm_snd_soc_register_component(>dev, _component,
  >cpu_dai_drv, 1);
if (ret)
-   goto err_pm_disable;
+   goto err_pm_get_sync;
 
if (sai->soc_data->use_imx_pcm) {
ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
if (ret)
-   goto err_pm_disable;
+   goto err_pm_get_sync;
} else {
ret = devm_snd_dmaengine_pcm_register(>dev, NULL, 0);
if (ret)
-   goto err_pm_disable;
+   goto err_pm_get_sync;
}
 
return ret;
 
+err_pm_get_sync:
+   if (!pm_runtime_status_suspended(>dev))
+   fsl_sai_runtime_suspend(>dev);
 err_pm_disable:
pm_runtime_disable(>dev);
 
@@ -1159,6 +1175,8 @@ static int fsl_sai_probe(struct platform_device *pdev)
 static int fsl_sai_remove(struct platform_device *pdev)
 {
pm_runtime_disable(>dev);
+   if (!pm_runtime_status_suspended(>dev))
+   fsl_sai_runtime_suspend(>dev);
 
return 0;
 }
@@ -1219,7 +1237,6 @@ static const struct of_device_id fsl_sai_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, fsl_sai_ids);
 
-#ifdef CONFIG_PM
 static int fsl_sai_runtime_suspen

Re: [PATCH] ASoC: fsl_sai: remove reset code from dai_probe

2021-03-18 Thread Shengjiu Wang
Hi Mark

On Tue, Mar 16, 2021 at 9:51 PM Mark Brown  wrote:
>
> On Tue, Mar 16, 2021 at 01:42:40PM +, Viorel Suman wrote:
>
> > To me it makes sense to manage the clocks and reset from the same place.
> > Currently we have the clocks management moved completely into runtime PM
> > fsl_sai_runtime_resume and fsl_sai_runtime_suspend callbacks.
>
> Usually the pattern is to have probe() leave everything powered up then
> let runtime PM power things down if it's enabled, you can often do the
> power up by having an open coded call to the resume callback in probe().

It seems some drivers very depend on runtime PM, if the CONFIG_PM=n,
the drivers should not work.  What's the strategy for this?
Do we need to support both cases, or only one case is also acceptable?

Best regards
Wang Shengjiu


[PATCH 2/2] ASoC: bindings: fsl-asoc-card: add compatible string for WM8958 codec

2021-03-17 Thread Shengjiu Wang
The WM8958 codec is used on i.MX7D val board.

Signed-off-by: Shengjiu Wang 
---
 Documentation/devicetree/bindings/sound/fsl-asoc-card.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt 
b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
index 90d9e9d81624..23d83fa7609f 100644
--- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
+++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
@@ -42,6 +42,8 @@ The compatible list for this generic sound card currently:
 
  "fsl,imx-audio-si476x"
 
+ "fsl,imx-audio-wm8958"
+
 Required properties:
 
   - compatible : Contains one of entries in the compatible list.
-- 
2.27.0



[PATCH 1/2] ASoC: fsl-asoc-card: Add support for WM8958 codec

2021-03-17 Thread Shengjiu Wang
WM8958 codec is used on some i.MX based platform.
So add it support in this generic driver.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |  2 ++
 sound/soc/fsl/fsl-asoc-card.c | 17 +++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index c71c6024320b..0917d65d6921 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -310,6 +310,8 @@ config SND_SOC_FSL_ASOC_CARD
select SND_SOC_FSL_ESAI
select SND_SOC_FSL_SAI
select SND_SOC_FSL_SSI
+   select SND_SOC_WM8994
+   select MFD_WM8994
help
 ALSA SoC Audio support with ASRC feature for Freescale SoCs that have
 ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888,
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index f62f81ceab0d..c62bfd1c3ac7 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -25,6 +25,7 @@
 #include "../codecs/sgtl5000.h"
 #include "../codecs/wm8962.h"
 #include "../codecs/wm8960.h"
+#include "../codecs/wm8994.h"
 
 #define CS427x_SYSCLK_MCLK 0
 
@@ -37,12 +38,14 @@
 /**
  * struct codec_priv - CODEC private data
  * @mclk_freq: Clock rate of MCLK
+ * @free_freq: Clock rate of MCLK for hw_free()
  * @mclk_id: MCLK (or main clock) id for set_sysclk()
  * @fll_id: FLL (or secordary clock) id for set_sysclk()
  * @pll_id: PLL id for set_pll()
  */
 struct codec_priv {
unsigned long mclk_freq;
+   unsigned long free_freq;
u32 mclk_id;
u32 fll_id;
u32 pll_id;
@@ -235,10 +238,10 @@ static int fsl_asoc_card_hw_free(struct snd_pcm_substream 
*substream)
priv->streams &= ~BIT(substream->stream);
 
if (!priv->streams && codec_priv->pll_id && codec_priv->fll_id) {
-   /* Force freq to be 0 to avoid error message in codec */
+   /* Force freq to be free_freq to avoid error message in codec */
ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0),
 codec_priv->mclk_id,
-0,
+codec_priv->free_freq,
 SND_SOC_CLOCK_IN);
if (ret) {
dev_err(dev, "failed to switch away from FLL: %d\n", 
ret);
@@ -665,6 +668,15 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
priv->card.dapm_routes = audio_map_rx;
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_rx);
+   } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8958")) {
+   codec_dai_name = "wm8994-aif1";
+   priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
+   priv->codec_priv.mclk_id = WM8994_FLL_SRC_MCLK1;
+   priv->codec_priv.fll_id = WM8994_SYSCLK_FLL1;
+   priv->codec_priv.pll_id = WM8994_FLL1;
+   priv->codec_priv.free_freq = priv->codec_priv.mclk_freq;
+   priv->card.dapm_routes = NULL;
+   priv->card.num_dapm_routes = 0;
} else {
dev_err(>dev, "unknown Device Tree compatible\n");
ret = -EINVAL;
@@ -882,6 +894,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = {
{ .compatible = "fsl,imx-audio-mqs", },
{ .compatible = "fsl,imx-audio-wm8524", },
{ .compatible = "fsl,imx-audio-si476x", },
+   { .compatible = "fsl,imx-audio-wm8958", },
{}
 };
 MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids);
-- 
2.27.0



Re: [PATCH] ASoC: fsl_sai: remove reset code from dai_probe

2021-03-16 Thread Shengjiu Wang
On Tue, Mar 16, 2021 at 9:01 PM Mark Brown  wrote:
>
> On Tue, Mar 16, 2021 at 05:27:06PM +0800, Shengjiu Wang wrote:
> > From: Viorel Suman 
> >
> > SAI software reset is done in runtime resume,
> > there is no need to do it in fsl_sai_dai_probe.
>
> People can disable runtime PM in their configurations - do you not still
> need a reset on probe in case there's no runtime PM?  It'd probably make
> sense to factor the rest code out itno a function though.

Right, didn't consider the case of disable runtime PM.
Will move the reset code to a function.

Best regards
wang shengjiu


[PATCH] ASoC: fsl_spdif: use snd_ctl_boolean_mono_info

2021-03-16 Thread Shengjiu Wang
From: Viorel Suman 

Remove redundant code and use snd_ctl_boolean_mono_info
instead.

Signed-off-by: Viorel Suman 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_spdif.c | 30 +++---
 1 file changed, 3 insertions(+), 27 deletions(-)

diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 174e558224d8..1cd3441d1c03 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -801,18 +801,6 @@ static int fsl_spdif_qget(struct snd_kcontrol *kcontrol,
return ret;
 }
 
-/* Valid bit information */
-static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol,
-   struct snd_ctl_elem_info *uinfo)
-{
-   uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-   uinfo->count = 1;
-   uinfo->value.integer.min = 0;
-   uinfo->value.integer.max = 1;
-
-   return 0;
-}
-
 /* Get valid good bit from interrupt status register */
 static int fsl_spdif_rx_vbit_get(struct snd_kcontrol *kcontrol,
 struct snd_ctl_elem_value *ucontrol)
@@ -925,18 +913,6 @@ static int fsl_spdif_rxrate_get(struct snd_kcontrol 
*kcontrol,
return 0;
 }
 
-/* User bit sync mode info */
-static int fsl_spdif_usync_info(struct snd_kcontrol *kcontrol,
-   struct snd_ctl_elem_info *uinfo)
-{
-   uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-   uinfo->count = 1;
-   uinfo->value.integer.min = 0;
-   uinfo->value.integer.max = 1;
-
-   return 0;
-}
-
 /*
  * User bit sync mode:
  * 1 CD User channel subcode
@@ -1018,7 +994,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
.name = "IEC958 RX V-Bit Errors",
.access = SNDRV_CTL_ELEM_ACCESS_READ |
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
-   .info = fsl_spdif_vbit_info,
+   .info = snd_ctl_boolean_mono_info,
.get = fsl_spdif_rx_vbit_get,
},
{
@@ -1027,7 +1003,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ |
SNDRV_CTL_ELEM_ACCESS_WRITE |
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
-   .info = fsl_spdif_vbit_info,
+   .info = snd_ctl_boolean_mono_info,
.get = fsl_spdif_tx_vbit_get,
.put = fsl_spdif_tx_vbit_put,
},
@@ -1047,7 +1023,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ |
SNDRV_CTL_ELEM_ACCESS_WRITE |
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
-   .info = fsl_spdif_usync_info,
+   .info = snd_ctl_boolean_mono_info,
.get = fsl_spdif_usync_get,
.put = fsl_spdif_usync_put,
},
-- 
2.27.0



[PATCH] ASoC: fsl_sai: remove reset code from dai_probe

2021-03-16 Thread Shengjiu Wang
From: Viorel Suman 

SAI software reset is done in runtime resume,
there is no need to do it in fsl_sai_dai_probe.

Signed-off-by: Viorel Suman 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_sai.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 6ef2ce348232..9e7893f91882 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -711,13 +711,6 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
unsigned int ofs = sai->soc_data->reg_offset;
 
-   /* Software Reset for both Tx and Rx */
-   regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
-   regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
-   /* Clear SR bit to finish the reset */
-   regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
-   regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
-
regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs),
   FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
   sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX);
-- 
2.27.0



[PATCH] ASoC: dt-bindings: fsl_spdif: Add compatible string for new platforms

2021-03-16 Thread Shengjiu Wang
Add compatible string for new added platforms which support spdif module.
They are i.MX8QXP, i.MX8MM, i.MX8MN, i.MX8MQ.

Signed-off-by: Shengjiu Wang 
---
 Documentation/devicetree/bindings/sound/fsl,spdif.yaml | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml 
b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml
index 50449b6d1048..4454aca34d56 100644
--- a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml
@@ -21,6 +21,10 @@ properties:
   - fsl,vf610-spdif
   - fsl,imx6sx-spdif
   - fsl,imx8qm-spdif
+  - fsl,imx8qxp-spdif
+  - fsl,imx8mq-spdif
+  - fsl,imx8mm-spdif
+  - fsl,imx8mn-spdif
 
   reg:
 maxItems: 1
-- 
2.27.0



[PATCH v5 5/6] ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg

2021-03-11 Thread Shengjiu Wang
Platform driver based on rpmsg is the interface for sending and
receiving rpmsg to and from M core. It will tell the Cortex-M core
sound format/rate/channel, where is the data buffer, where is
the period size, when to start, when to stop and when suspend
or resume happen, each this behavior there is defined rpmsg
command.

Especially we designed the low power audio case, that is to
allocate a large buffer and fill the data, then Cortex-A core can go
to sleep mode, Cortex-M core continue to play the sound, when the
buffer is consumed, Cortex-M core will trigger the Cortex-A core to
wake up.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |   5 +
 sound/soc/fsl/Makefile|   1 +
 sound/soc/fsl/imx-pcm-rpmsg.c | 918 ++
 sound/soc/fsl/imx-pcm-rpmsg.h | 512 +++
 4 files changed, 1436 insertions(+)
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 8dbdc0c5ba58..3d3d14f3793e 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -133,6 +133,11 @@ config SND_SOC_IMX_AUDIO_RPMSG
tristate
depends on RPMSG
 
+config SND_SOC_IMX_PCM_RPMSG
+   tristate
+   depends on SND_SOC_IMX_AUDIO_RPMSG
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+
 config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index f08f3cd07ff5..ce4f4324c3a2 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
 obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
+obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
new file mode 100644
index ..875c0d6df339
--- /dev/null
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -0,0 +1,918 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2021 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "imx-pcm.h"
+#include "fsl_rpmsg.h"
+#include "imx-pcm-rpmsg.h"
+
+static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
+   .info = SNDRV_PCM_INFO_INTERLEAVED |
+   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+   SNDRV_PCM_INFO_MMAP |
+   SNDRV_PCM_INFO_MMAP_VALID |
+   SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
+   SNDRV_PCM_INFO_PAUSE |
+   SNDRV_PCM_INFO_RESUME,
+   .buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE,
+   .period_bytes_min = 512,
+   .period_bytes_max = 65536,
+   .periods_min = 2,
+   .periods_max = 6000,
+   .fifo_size = 0,
+};
+
+static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
+ struct rpmsg_info *info)
+{
+   struct rpmsg_device *rpdev = info->rpdev;
+   int ret = 0;
+
+   mutex_lock(>msg_lock);
+   if (!rpdev) {
+   dev_err(info->dev, "rpmsg channel not ready\n");
+   mutex_unlock(>msg_lock);
+   return -EINVAL;
+   }
+
+   dev_dbg(>dev, "send cmd %d\n", msg->s_msg.header.cmd);
+
+   if (!(msg->s_msg.header.type == MSG_TYPE_C))
+   reinit_completion(>cmd_complete);
+
+   ret = rpmsg_send(rpdev->ept, (void *)>s_msg,
+sizeof(struct rpmsg_s_msg));
+   if (ret) {
+   dev_err(>dev, "rpmsg_send failed: %d\n", ret);
+   mutex_unlock(>msg_lock);
+   return ret;
+   }
+
+   /* No receive msg for TYPE_C command */
+   if (msg->s_msg.header.type == MSG_TYPE_C) {
+   mutex_unlock(>msg_lock);
+   return 0;
+   }
+
+   /* wait response from rpmsg */
+   ret = wait_for_completion_timeout(>cmd_complete,
+ msecs_to_jiffies(RPMSG_TIMEOUT));
+   if (!ret) {
+   dev_err(>dev, "rpmsg_send cmd %d timeout!\n",
+   msg->s_msg.header.cmd);
+   mutex_unlock(>msg_lock);
+   return -ETIMEDOUT;
+   }
+
+   memcpy(>r_msg, >r_msg, sizeof(struct rpmsg_r_msg));
+   memcpy(>msg[msg->r_msg.header.cmd].r_msg,
+  >r_msg, sizeof(struct rpmsg_r_msg));
+
+   /*
+* Reset the buffer pointer to be zero, actully we have
+* set the buffer pointer to be zero in imx_rpmsg_terminate_all
+* But if there is timer task queued in queue, after it is
+* executed the buffer pointer will be

[PATCH v5 3/6] ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg audio device

2021-03-11 Thread Shengjiu Wang
fsl_rpmsg is a virtual audio device. Mapping to real hardware
devices are SAI, DMA controlled by Cortex M core. What we see from
Linux side is a device which provides audio service by rpmsg channel.

Signed-off-by: Shengjiu Wang 
---
 .../devicetree/bindings/sound/fsl,rpmsg.yaml  | 108 ++
 1 file changed, 108 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml

diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml 
b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
new file mode 100644
index ..b4c190bddd84
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
@@ -0,0 +1,108 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/fsl,rpmsg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP Audio RPMSG CPU DAI Controller
+
+maintainers:
+  - Shengjiu Wang 
+
+description: |
+  fsl_rpmsg is a virtual audio device. Mapping to real hardware devices
+  are SAI, DMA controlled by Cortex M core. What we see from Linux
+  side is a device which provides audio service by rpmsg channel.
+
+properties:
+  compatible:
+enum:
+  - fsl,imx7ulp-rpmsg-audio
+  - fsl,imx8mn-rpmsg-audio
+  - fsl,imx8mm-rpmsg-audio
+  - fsl,imx8mp-rpmsg-audio
+
+  model:
+$ref: /schemas/types.yaml#/definitions/string
+description: User specified audio sound card name
+
+  clocks:
+items:
+  - description: Peripheral clock for register access
+  - description: Master clock
+  - description: DMA clock for DMA register access
+  - description: Parent clock for multiple of 8kHz sample rates
+  - description: Parent clock for multiple of 11kHz sample rates
+
+  clock-names:
+items:
+  - const: ipg
+  - const: mclk
+  - const: dma
+  - const: pll8k
+  - const: pll11k
+
+  power-domains:
+description:
+  List of phandle and PM domain specifier as documented in
+  Documentation/devicetree/bindings/power/power_domain.txt
+maxItems: 1
+
+  memory-region:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  phandle to a node describing reserved memory (System RAM memory)
+  The M core can't access all the DDR memory space on some platform,
+  So reserved a specific memory for dma buffer which M core can
+  access.
+  (see bindings/reserved-memory/reserved-memory.txt)
+
+  audio-codec:
+$ref: /schemas/types.yaml#/definitions/phandle
+description: The phandle to a node of audio codec
+
+  audio-routing:
+$ref: /schemas/types.yaml#/definitions/non-unique-string-array
+description: |
+  A list of the connections between audio components. Each entry is a
+  pair of strings, the first being the connection's sink, the second
+  being the connection's source.
+
+  fsl,enable-lpa:
+$ref: /schemas/types.yaml#/definitions/flag
+description: enable low power audio path.
+
+  fsl,rpmsg-out:
+$ref: /schemas/types.yaml#/definitions/flag
+description: |
+  This is a boolean property. If present, the transmitting function
+  will be enabled.
+
+  fsl,rpmsg-in:
+$ref: /schemas/types.yaml#/definitions/flag
+description: |
+  This is a boolean property. If present, the receiving function
+  will be enabled.
+
+required:
+  - compatible
+  - model
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+
+rpmsg_audio: rpmsg_audio {
+compatible = "fsl,imx8mn-rpmsg-audio";
+model = "wm8524-audio";
+fsl,enable-lpa;
+fsl,rpmsg-out;
+clocks = < IMX8MN_CLK_SAI3_IPG>,
+ < IMX8MN_CLK_SAI3_ROOT>,
+ < IMX8MN_CLK_SDMA3_ROOT>,
+ < IMX8MN_AUDIO_PLL1_OUT>,
+ < IMX8MN_AUDIO_PLL2_OUT>;
+clock-names = "ipg", "mclk", "dma", "pll8k", "pll11k";
+};
-- 
2.27.0



[PATCH v5 6/6] ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg

2021-03-11 Thread Shengjiu Wang
The platform device is not registered by device tree or
cpu dai driver, it is registered by the rpmsg channel,
So add a dedicated machine driver to handle this case.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |  11 +++
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/imx-rpmsg.c | 150 ++
 3 files changed, 163 insertions(+)
 create mode 100644 sound/soc/fsl/imx-rpmsg.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 3d3d14f3793e..c71c6024320b 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -337,6 +337,17 @@ config SND_SOC_IMX_HDMI
  Say Y if you want to add support for SoC audio on an i.MX board with
  IMX HDMI.
 
+config SND_SOC_IMX_RPMSG
+   tristate "SoC Audio support for i.MX boards with rpmsg"
+   depends on RPMSG
+   select SND_SOC_IMX_PCM_RPMSG
+   select SND_SOC_IMX_AUDIO_RPMSG
+   help
+ SoC Audio support for i.MX boards with rpmsg.
+ There should be rpmsg devices defined in other core (M core)
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a rpmsg devices.
+
 endif # SND_IMX_SOC
 
 endmenu
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index ce4f4324c3a2..f146ce464acd 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -70,6 +70,7 @@ snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
 snd-soc-imx-spdif-objs := imx-spdif.o
 snd-soc-imx-audmix-objs := imx-audmix.o
 snd-soc-imx-hdmi-objs := imx-hdmi.o
+snd-soc-imx-rpmsg-objs := imx-rpmsg.o
 
 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
 obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o
@@ -77,3 +78,4 @@ 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_AUDMIX) += snd-soc-imx-audmix.o
 obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o
+obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o
diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c
new file mode 100644
index ..5a9a470d203f
--- /dev/null
+++ b/sound/soc/fsl/imx-rpmsg.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2020 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "imx-pcm-rpmsg.h"
+
+struct imx_rpmsg {
+   struct snd_soc_dai_link dai;
+   struct snd_soc_card card;
+};
+
+static const struct snd_soc_dapm_widget imx_rpmsg_dapm_widgets[] = {
+   SND_SOC_DAPM_HP("Headphone Jack", NULL),
+   SND_SOC_DAPM_SPK("Ext Spk", NULL),
+   SND_SOC_DAPM_MIC("Mic Jack", NULL),
+   SND_SOC_DAPM_MIC("Main MIC", NULL),
+};
+
+static int imx_rpmsg_probe(struct platform_device *pdev)
+{
+   struct snd_soc_dai_link_component *dlc;
+   struct device *dev = pdev->dev.parent;
+   /* rpmsg_pdev is the platform device for the rpmsg node that probed us 
*/
+   struct platform_device *rpmsg_pdev = to_platform_device(dev);
+   struct device_node *np = rpmsg_pdev->dev.of_node;
+   struct of_phandle_args args;
+   struct imx_rpmsg *data;
+   int ret = 0;
+
+   dlc = devm_kzalloc(>dev, 3 * sizeof(*dlc), GFP_KERNEL);
+   if (!dlc)
+   return -ENOMEM;
+
+   data = devm_kzalloc(>dev, sizeof(*data), GFP_KERNEL);
+   if (!data) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+
+   ret = of_reserved_mem_device_init_by_idx(>dev, np, 0);
+   if (ret)
+   dev_warn(>dev, "no reserved DMA memory\n");
+
+   data->dai.cpus = [0];
+   data->dai.num_cpus = 1;
+   data->dai.platforms = [1];
+   data->dai.num_platforms = 1;
+   data->dai.codecs = [2];
+   data->dai.num_codecs = 1;
+
+   data->dai.name = "rpmsg hifi";
+   data->dai.stream_name = "rpmsg hifi";
+   data->dai.dai_fmt = SND_SOC_DAIFMT_I2S |
+   SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS;
+
+   /* Optional codec node */
+   ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, );
+   if (ret) {
+   data->dai.codecs->dai_name = "snd-soc-dummy-dai";
+   data->dai.codecs->name = "snd-soc-dummy";
+   } else {
+   data->dai.codecs->of_node = args.np;
+   ret = snd_soc_get_dai_name(, >dai.codecs->dai_name);
+   if (ret) {
+   dev_err(>dev, "Unable to get codec_dai_name\n");
+   goto fail;
+   }
+   }
+
+   data->dai.cpus->dai_name = dev_name(_pdev->dev);
+   data->dai.platforms->name = IMX_PCM_DRV_NAME;
+   da

[PATCH v5 4/6] ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel

2021-03-11 Thread Shengjiu Wang
This driver is used to accept the message from rpmsg audio
channel, and if this driver is probed, it will help to register
the platform driver, the platform driver will use this
audio channel to send and receive messages to and from Cortex-M
core.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig   |   4 +
 sound/soc/fsl/Makefile  |   1 +
 sound/soc/fsl/imx-audio-rpmsg.c | 140 
 3 files changed, 145 insertions(+)
 create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 3326f30e28f6..8dbdc0c5ba58 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -129,6 +129,10 @@ config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
 
+config SND_SOC_IMX_AUDIO_RPMSG
+   tristate
+   depends on RPMSG
+
 config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index b63802f345cc..f08f3cd07ff5 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 
 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
+obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c
new file mode 100644
index ..50099bcaa9cd
--- /dev/null
+++ b/sound/soc/fsl/imx-audio-rpmsg.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2020 NXP
+
+#include 
+#include 
+#include "imx-pcm-rpmsg.h"
+
+/*
+ * struct imx_audio_rpmsg: private data
+ *
+ * @rpmsg_pdev: pointer of platform device
+ */
+struct imx_audio_rpmsg {
+   struct platform_device *rpmsg_pdev;
+};
+
+static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
+ void *priv, u32 src)
+{
+   struct imx_audio_rpmsg *rpmsg = dev_get_drvdata(>dev);
+   struct rpmsg_r_msg *r_msg = (struct rpmsg_r_msg *)data;
+   struct rpmsg_info *info;
+   struct rpmsg_msg *msg;
+   unsigned long flags;
+
+   if (!rpmsg->rpmsg_pdev)
+   return 0;
+
+   info = platform_get_drvdata(rpmsg->rpmsg_pdev);
+
+   dev_dbg(>dev, "get from%d: cmd:%d. %d\n",
+   src, r_msg->header.cmd, r_msg->param.resp);
+
+   switch (r_msg->header.type) {
+   case MSG_TYPE_C:
+   /* TYPE C is notification from M core */
+   switch (r_msg->header.cmd) {
+   case TX_PERIOD_DONE:
+   spin_lock_irqsave(>lock[TX], flags);
+   msg = >msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
+   msg->r_msg.param.buffer_tail =
+   r_msg->param.buffer_tail;
+   msg->r_msg.param.buffer_tail %= info->num_period[TX];
+   spin_unlock_irqrestore(>lock[TX], flags);
+   info->callback[TX](info->callback_param[TX]);
+   break;
+   case RX_PERIOD_DONE:
+   spin_lock_irqsave(>lock[RX], flags);
+   msg = >msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
+   msg->r_msg.param.buffer_tail =
+   r_msg->param.buffer_tail;
+   msg->r_msg.param.buffer_tail %= info->num_period[1];
+   spin_unlock_irqrestore(>lock[RX], flags);
+   info->callback[RX](info->callback_param[RX]);
+   break;
+   default:
+   dev_warn(>dev, "unknown msg command\n");
+   break;
+   }
+   break;
+   case MSG_TYPE_B:
+   /* TYPE B is response msg */
+   memcpy(>r_msg, r_msg, sizeof(struct rpmsg_r_msg));
+   complete(>cmd_complete);
+   break;
+   default:
+   dev_warn(>dev, "unknown msg type\n");
+   break;
+   }
+
+   return 0;
+}
+
+static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev)
+{
+   struct imx_audio_rpmsg *data;
+   int ret = 0;
+
+   dev_info(>dev, "new channel: 0x%x -> 0x%x!\n",
+rpdev->src, rpdev->dst);
+
+   data = devm_kzalloc(>dev, sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   dev_set_drvdata(>dev, data);
+
+   /* Register platform driver for rpmsg routine */
+   data->rpmsg_pdev = platform_device_register_data(>dev,
+IMX_PCM_DRV_

[PATCH v5 2/6] ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg

2021-03-11 Thread Shengjiu Wang
This is a cpu dai driver for rpmsg audio use case,
which is mainly used for getting the user's configuration
from devicetree and configure the clocks which is used by
Cortex-M core.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |  10 ++
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/fsl_rpmsg.c | 279 ++
 sound/soc/fsl/fsl_rpmsg.h |  35 +
 4 files changed, 326 insertions(+)
 create mode 100644 sound/soc/fsl/fsl_rpmsg.c
 create mode 100644 sound/soc/fsl/fsl_rpmsg.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index d7f30036d434..3326f30e28f6 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -115,6 +115,16 @@ config SND_SOC_FSL_AUD2HTX
 config SND_SOC_FSL_UTILS
tristate
 
+config SND_SOC_FSL_RPMSG
+   tristate "NXP Audio Base On RPMSG support"
+   depends on COMMON_CLK
+   depends on RPMSG
+   select SND_SOC_IMX_RPMSG if SND_IMX_SOC != n
+   help
+ Say Y if you want to add rpmsg audio support for the Freescale CPUs.
+ This option is only useful for out-of-tree drivers since
+ in-tree drivers select it automatically.
+
 config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 8c5fa8a859c0..b63802f345cc 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -27,6 +27,7 @@ snd-soc-fsl-mqs-objs := fsl_mqs.o
 snd-soc-fsl-easrc-objs := fsl_easrc.o
 snd-soc-fsl-xcvr-objs := fsl_xcvr.o
 snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o
+snd-soc-fsl-rpmsg-objs := fsl_rpmsg.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
@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_SOC_FSL_EASRC) += snd-soc-fsl-easrc.o
 obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
 obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o
 obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o
+obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o
 
 # MPC5200 Platform Support
 obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c
new file mode 100644
index ..2d09d8850e2c
--- /dev/null
+++ b/sound/soc/fsl/fsl_rpmsg.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2018-2021 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "fsl_rpmsg.h"
+#include "imx-pcm.h"
+
+#define FSL_RPMSG_RATES(SNDRV_PCM_RATE_8000 | \
+   SNDRV_PCM_RATE_16000 | \
+   SNDRV_PCM_RATE_48000)
+#define FSL_RPMSG_FORMATS  SNDRV_PCM_FMTBIT_S16_LE
+
+/* 192kHz/32bit/2ch/60s size is 0x574e00 */
+#define LPA_LARGE_BUFFER_SIZE  (0x600)
+
+static const unsigned int fsl_rpmsg_rates[] = {
+   8000, 11025, 16000, 22050, 44100,
+   32000, 48000, 96000, 88200, 176400, 192000,
+   352800, 384000, 705600, 768000, 1411200, 2822400,
+};
+
+static const struct snd_pcm_hw_constraint_list fsl_rpmsg_rate_constraints = {
+   .count = ARRAY_SIZE(fsl_rpmsg_rates),
+   .list = fsl_rpmsg_rates,
+};
+
+static int fsl_rpmsg_hw_params(struct snd_pcm_substream *substream,
+  struct snd_pcm_hw_params *params,
+  struct snd_soc_dai *dai)
+{
+   struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai);
+   struct clk *p = rpmsg->mclk, *pll = 0, *npll = 0;
+   u64 rate = params_rate(params);
+   int ret = 0;
+
+   /* Get current pll parent */
+   while (p && rpmsg->pll8k && rpmsg->pll11k) {
+   struct clk *pp = clk_get_parent(p);
+
+   if (clk_is_match(pp, rpmsg->pll8k) ||
+   clk_is_match(pp, rpmsg->pll11k)) {
+   pll = pp;
+   break;
+   }
+   p = pp;
+   }
+
+   /* Switch to another pll parent if needed. */
+   if (pll) {
+   npll = (do_div(rate, 8000) ? rpmsg->pll11k : rpmsg->pll8k);
+   if (!clk_is_match(pll, npll)) {
+   ret = clk_set_parent(p, npll);
+   if (ret < 0)
+   dev_warn(dai->dev, "failed to set parent %s: 
%d\n",
+__clk_get_name(npll), ret);
+   }
+   }
+
+   if (!(rpmsg->mclk_streams & BIT(substream->stream))) {
+   ret = clk_prepare_enable(rpmsg->mclk);
+   if (ret) {
+   dev_err(dai->dev, "failed to enable mclk: %d\n", ret);
+   return ret;
+   }
+
+   rpmsg->mclk_streams |= BIT(substream->stream);
+   }
+
+   return ret;
+}
+
+sta

[PATCH v5 0/6] Add audio driver base on rpmsg on i.MX platform

2021-03-11 Thread Shengjiu Wang
On Asymmetric multiprocessor, there is Cortex-A core and Cortex-M core,
Linux is running on A core, RTOS is running on M core.
The audio hardware device can be controlled by Cortex-M device,
So audio playback/capture can be handled by M core.

Rpmsg is the interface for sending and receiving msg to and from M
core, that we can create a virtual sound on Cortex-A core side.

A core will tell the Cortex-M core sound format/rate/channel,
where is the data buffer, what is the period size, when to start,
when to stop and when suspend or resume happen, each of this behavior
there is defined rpmsg command.

Especially we designed the low power audio case, that is to
allocate a large buffer and fill the data, then Cortex-A core can go
to sleep mode, Cortex-M core continue to play the sound, when the
buffer is consumed, Cortex-M core will trigger the Cortex-A core to
wakeup to fill data.

changes in v5:
- remove unneeded property in binding doc and driver
- update binding doc according to Rob's comments.
- Fix link issue reported by kernel test robot

changes in v4:
- remove the sound card node, merge the property to cpu dai node
  according to Rob's comments.
- sound card device will be registered by cpu dai driver.
- Fix do_div issue reported by kernel test robot

changes in v3:
- add local refcount for clk enablement in hw_params()
- update the document according Rob's comments

changes in v2:
- update codes and comments according to Mark's comments

Shengjiu Wang (6):
  ASoC: soc-component: Add snd_soc_pcm_component_ack
  ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg
  ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg audio device
  ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel
  ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg
  ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg

 .../devicetree/bindings/sound/fsl,rpmsg.yaml  | 108 +++
 include/sound/soc-component.h |   3 +
 sound/soc/fsl/Kconfig |  30 +
 sound/soc/fsl/Makefile|   6 +
 sound/soc/fsl/fsl_rpmsg.c | 279 ++
 sound/soc/fsl/fsl_rpmsg.h |  35 +
 sound/soc/fsl/imx-audio-rpmsg.c   | 140 +++
 sound/soc/fsl/imx-pcm-rpmsg.c | 918 ++
 sound/soc/fsl/imx-pcm-rpmsg.h | 512 ++
 sound/soc/fsl/imx-rpmsg.c | 150 +++
 sound/soc/soc-component.c |  14 +
 sound/soc/soc-pcm.c   |   2 +
 12 files changed, 2197 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
 create mode 100644 sound/soc/fsl/fsl_rpmsg.c
 create mode 100644 sound/soc/fsl/fsl_rpmsg.h
 create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h
 create mode 100644 sound/soc/fsl/imx-rpmsg.c

-- 
2.27.0



[PATCH v5 1/6] ASoC: soc-component: Add snd_soc_pcm_component_ack

2021-03-11 Thread Shengjiu Wang
Add snd_soc_pcm_component_ack back, which can be used to get an
updated buffer pointer in the platform driver.
On Asymmetric multiprocessor, this pointer can be sent to Cortex-M
core for audio processing.

Signed-off-by: Shengjiu Wang 
---
 include/sound/soc-component.h |  3 +++
 sound/soc/soc-component.c | 14 ++
 sound/soc/soc-pcm.c   |  2 ++
 3 files changed, 19 insertions(+)

diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 7dc75b39287f..722cfab28d29 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -146,6 +146,8 @@ struct snd_soc_component_driver {
int (*mmap)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
+   int (*ack)(struct snd_soc_component *component,
+  struct snd_pcm_substream *substream);
 
const struct snd_compress_ops *compress_ops;
 
@@ -498,5 +500,6 @@ int snd_soc_pcm_component_pm_runtime_get(struct 
snd_soc_pcm_runtime *rtd,
 void *stream);
 void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
  void *stream, int rollback);
+int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream);
 
 #endif /* __SOC_COMPONENT_H */
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 8415e9bd2932..3a5e84e16a87 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -1212,3 +1212,17 @@ void snd_soc_pcm_component_pm_runtime_put(struct 
snd_soc_pcm_runtime *rtd,
soc_component_mark_pop(component, stream, pm);
}
 }
+
+int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+   struct snd_soc_component *component;
+   int i;
+
+   /* FIXME: use 1st pointer */
+   for_each_rtd_components(rtd, i, component)
+   if (component->driver->ack)
+   return component->driver->ack(component, substream);
+
+   return 0;
+}
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ba8ffbf8a5d3..e75b404a9f36 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2826,6 +2826,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->ops.page   = snd_soc_pcm_component_page;
if (drv->mmap)
rtd->ops.mmap   = snd_soc_pcm_component_mmap;
+   if (drv->ack)
+   rtd->ops.ack= snd_soc_pcm_component_ack;
}
 
if (playback)
-- 
2.27.0



Re: [PATCH v4 3/6] ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver

2021-03-11 Thread Shengjiu Wang
Hi Rob

On Thu, Mar 11, 2021 at 5:12 AM Rob Herring  wrote:
>
> On Wed, Mar 10, 2021 at 6:33 AM Shengjiu Wang  wrote:
> >
> > Hi Rob
> >
> > On Wed, Mar 10, 2021 at 10:49 AM Rob Herring  wrote:
> > >
> > > On Mon, Mar 08, 2021 at 09:22:27PM +0800, Shengjiu Wang wrote:
> > > > fsl_rpmsg cpu dai driver is driver for rpmsg audio, which is mainly used
> > >
> > > Bindings describe h/w blocks, not drivers.
> >
> > I will modify the descriptions. but here it is a virtual device.  the
> > mapping in real h/w is cortex M core, Cortex M core controls the SAI,
> > DMA interface. What we see from Linux side is a audio service
> > through rpmsg channel.
>
> It's describing the h/w from the view of the OS. It's not important
> that it's a Cortex-M, but how you interface to it whether that's
> shared registers, mailbox, etc. And it's what resources the block uses
> that the OS controls.

ok.

>
> > > > for getting the user's configuration from device tree and configure the
> > > > clocks which is used by Cortex-M core. So in this document define the
> > > > needed property.
> > > >
> > > > Signed-off-by: Shengjiu Wang 
> > > > ---
> > > >  .../devicetree/bindings/sound/fsl,rpmsg.yaml  | 118 ++
> > > >  1 file changed, 118 insertions(+)
> > > >  create mode 100644 
> > > > Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml 
> > > > b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
> > > > new file mode 100644
> > > > index ..5731c1fbc0a6
> > > > --- /dev/null
> > > > +++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
> > > > @@ -0,0 +1,118 @@
> > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > +%YAML 1.2
> > > > +---
> > > > +$id: http://devicetree.org/schemas/sound/fsl,rpmsg.yaml#
> > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > +
> > > > +title: NXP Audio RPMSG CPU DAI Controller
> > > > +
> > > > +maintainers:
> > > > +  - Shengjiu Wang 
> > > > +
> > > > +description: |
> > > > +  fsl_rpmsg cpu dai driver is virtual driver for rpmsg audio, which 
> > > > doesn't
> > > > +  touch hardware. It is mainly used for getting the user's 
> > > > configuration
> > > > +  from device tree and configure the clocks which is used by Cortex-M 
> > > > core.
> > > > +  So in this document define the needed property.
> > > > +
> > > > +properties:
> > > > +  compatible:
> > > > +enum:
> > > > +  - fsl,imx7ulp-rpmsg
> > > > +  - fsl,imx8mn-rpmsg
> > > > +  - fsl,imx8mm-rpmsg
> > > > +  - fsl,imx8mp-rpmsg
> > > > +
> > > > +  model:
> > > > +$ref: /schemas/types.yaml#/definitions/string
> > > > +description: User specified audio sound card name
> > > > +
> > > > +  clocks:
> > > > +items:
> > > > +  - description: Peripheral clock for register access
> > > > +  - description: Master clock
> > > > +  - description: DMA clock for DMA register access
> > > > +  - description: Parent clock for multiple of 8kHz sample rates
> > > > +  - description: Parent clock for multiple of 11kHz sample rates
> > > > +minItems: 5
> > >
> > > If this doesn't touch hardware, what are these clocks for?
> >
> > When the cortex-M core support audio service, these clock
> > needed prepared & enabled by ALSA driver.
> >
> > >
> > > You don't need 'minItems' unless it's less than the number of 'items'.
> >
> > Ok, I will remove this minItems.
> >
> > >
> > > > +
> > > > +  clock-names:
> > > > +items:
> > > > +  - const: ipg
> > > > +  - const: mclk
> > > > +  - const: dma
> > > > +  - const: pll8k
> > > > +  - const: pll11k
> > > > +minItems: 5
> > > > +
> > > > +  power-domains:
> > > > +maxItems: 1
> > > > +
> > > > +  fsl,audioindex:
> > > > +$ref: /schemas/types.yaml#/definitions/uint32
> > > > +enum

Re: [PATCH v4 3/6] ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver

2021-03-10 Thread Shengjiu Wang
Hi Rob

On Wed, Mar 10, 2021 at 10:49 AM Rob Herring  wrote:
>
> On Mon, Mar 08, 2021 at 09:22:27PM +0800, Shengjiu Wang wrote:
> > fsl_rpmsg cpu dai driver is driver for rpmsg audio, which is mainly used
>
> Bindings describe h/w blocks, not drivers.

I will modify the descriptions. but here it is a virtual device.  the
mapping in real h/w is cortex M core, Cortex M core controls the SAI,
DMA interface. What we see from Linux side is a audio service
through rpmsg channel.

>
> > for getting the user's configuration from device tree and configure the
> > clocks which is used by Cortex-M core. So in this document define the
> > needed property.
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
> >  .../devicetree/bindings/sound/fsl,rpmsg.yaml  | 118 ++
> >  1 file changed, 118 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml 
> > b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
> > new file mode 100644
> > index ..5731c1fbc0a6
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
> > @@ -0,0 +1,118 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/fsl,rpmsg.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: NXP Audio RPMSG CPU DAI Controller
> > +
> > +maintainers:
> > +  - Shengjiu Wang 
> > +
> > +description: |
> > +  fsl_rpmsg cpu dai driver is virtual driver for rpmsg audio, which doesn't
> > +  touch hardware. It is mainly used for getting the user's configuration
> > +  from device tree and configure the clocks which is used by Cortex-M core.
> > +  So in this document define the needed property.
> > +
> > +properties:
> > +  compatible:
> > +enum:
> > +  - fsl,imx7ulp-rpmsg
> > +  - fsl,imx8mn-rpmsg
> > +  - fsl,imx8mm-rpmsg
> > +  - fsl,imx8mp-rpmsg
> > +
> > +  model:
> > +$ref: /schemas/types.yaml#/definitions/string
> > +description: User specified audio sound card name
> > +
> > +  clocks:
> > +items:
> > +  - description: Peripheral clock for register access
> > +  - description: Master clock
> > +  - description: DMA clock for DMA register access
> > +  - description: Parent clock for multiple of 8kHz sample rates
> > +  - description: Parent clock for multiple of 11kHz sample rates
> > +minItems: 5
>
> If this doesn't touch hardware, what are these clocks for?

When the cortex-M core support audio service, these clock
needed prepared & enabled by ALSA driver.

>
> You don't need 'minItems' unless it's less than the number of 'items'.

Ok, I will remove this minItems.

>
> > +
> > +  clock-names:
> > +items:
> > +  - const: ipg
> > +  - const: mclk
> > +  - const: dma
> > +  - const: pll8k
> > +  - const: pll11k
> > +minItems: 5
> > +
> > +  power-domains:
> > +maxItems: 1
> > +
> > +  fsl,audioindex:
> > +$ref: /schemas/types.yaml#/definitions/uint32
> > +enum: [0, 1]
> > +default: 0
> > +description: Instance index for sound card in
> > + M core side, which share one rpmsg
> > + channel.
>
> We don't do indexes in DT. What's this numbering tied to?

I will remove it. it is not necessary

>
> > +
> > +  fsl,version:
>
> version of what?
>
> This seems odd at best.
>

I will remove it.  it is not necessary

> > +$ref: /schemas/types.yaml#/definitions/uint32
> > +enum: [1, 2]
>
> You're going to update this with every new firmware version?
>
> > +default: 2
> > +description: The version of M core image, which is
> > + to make driver compatible with different image.
> > +
> > +  fsl,buffer-size:
> > +$ref: /schemas/types.yaml#/definitions/uint32
> > +description: pre allocate dma buffer size
>
> How can you have DMA, this doesn't touch h/w?

The DMA is handled by M core image for sound playback
and capture. we need to allocated buffer in Linux side.
here just make the buffer size to be configurable.
>
> > +
> > +  fsl,enable-lpa:
> > +$ref: /schemas/types.yaml#/definitions/flag
> > +description: enable low power audio path.
> > +
> > +  fsl,rpmsg-out:
> > +$ref: /schemas/types.yaml#/def

[RESEND PATCH v2] ASoC: wm8960: Remove bitclk relax condition in wm8960_configure_sysclk

2021-03-09 Thread Shengjiu Wang
The call sequence in wm8960_configure_clocking is

   ret = wm8960_configure_sysclk();
   if (ret >= 0)
goto configure_clock;

   

   ret = wm8960_configure_pll();

configure_clock:
   ...

wm8960_configure_sysclk is called before wm8960_configure_pll, as
there is bitclk relax on both functions, so wm8960_configure_sysclk
always return success, then wm8960_configure_pll() never be called.

With this case:
aplay -Dhw:0,0 -d 5 -r 48000 -f S24_LE -c 2 audio48k24b2c.wav
the required bitclk is 48000 * 24 * 2 = 2304000, bitclk got from
wm8960_configure_sysclk is 3072000, but if go to wm8960_configure_pll.
it can get correct bitclk 2304000.

So bitclk relax condition should be removed in wm8960_configure_sysclk,
then wm8960_configure_pll can be called, and there is also bitclk relax
function in wm8960_configure_pll.

Fixes: 3c01b9ee2ab9 ("ASoC: codec: wm8960: Relax bit clock computation")
Signed-off-by: Shengjiu Wang 
Signed-off-by: Daniel Baluta 
Acked-by: Charles Keepax 
---
changes in resend v2
- Add acked-by Charles

changes in v2:
- Find the real reason for the case, just patially remove bitclk relax

 sound/soc/codecs/wm8960.c | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index df351519a3a6..847ca16b9841 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -608,10 +608,6 @@ static const int bclk_divs[] = {
  * - lrclk  = sysclk / dac_divs
  * - 10 * bclk  = sysclk / bclk_divs
  *
- * If we cannot find an exact match for (sysclk, lrclk, bclk)
- * triplet, we relax the bclk such that bclk is chosen as the
- * closest available frequency greater than expected bclk.
- *
  * @wm8960: codec private data
  * @mclk: MCLK used to derive sysclk
  * @sysclk_idx: sysclk_divs index for found sysclk
@@ -629,7 +625,7 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int 
mclk,
 {
int sysclk, bclk, lrclk;
int i, j, k;
-   int diff, closest = mclk;
+   int diff;
 
/* marker for no match */
*bclk_idx = -1;
@@ -653,12 +649,6 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, 
int mclk,
*bclk_idx = k;
break;
}
-   if (diff > 0 && closest > diff) {
-   *sysclk_idx = i;
-   *dac_idx = j;
-   *bclk_idx = k;
-   closest = diff;
-   }
}
if (k != ARRAY_SIZE(bclk_divs))
break;
-- 
2.27.0



[PATCH v4 4/6] ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel

2021-03-08 Thread Shengjiu Wang
This driver is used to accept the message from rpmsg audio
channel, and if this driver is probed, it will help to register
the platform driver, the platform driver will use this
audio channel to send and receive messages to and from Cortex-M
core.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig   |   4 +
 sound/soc/fsl/Makefile  |   1 +
 sound/soc/fsl/imx-audio-rpmsg.c | 151 
 3 files changed, 156 insertions(+)
 create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index f833856f6de0..cc81f6b917be 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -126,6 +126,10 @@ config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
 
+config SND_SOC_IMX_AUDIO_RPMSG
+   tristate
+   depends on RPMSG
+
 config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index b63802f345cc..f08f3cd07ff5 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 
 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
+obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c
new file mode 100644
index ..145edb1492b4
--- /dev/null
+++ b/sound/soc/fsl/imx-audio-rpmsg.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2020 NXP
+
+#include 
+#include 
+#include "imx-pcm-rpmsg.h"
+
+/*
+ * struct imx_audio_rpmsg: private data
+ *
+ * @rpmsg_pdev: pointer of platform device
+ */
+struct imx_audio_rpmsg {
+   struct platform_device *rpmsg_pdev;
+};
+
+static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
+ void *priv, u32 src)
+{
+   struct imx_audio_rpmsg *rpmsg = dev_get_drvdata(>dev);
+   struct rpmsg_info *info = platform_get_drvdata(rpmsg->rpmsg_pdev);
+   struct rpmsg_r_msg *r_msg = (struct rpmsg_r_msg *)data;
+   struct rpmsg_msg *msg;
+   unsigned long flags;
+
+   dev_dbg(>dev, "get from%d: cmd:%d. %d\n",
+   src, r_msg->header.cmd, r_msg->param.resp);
+
+   switch (r_msg->header.type) {
+   case MSG_TYPE_C:
+   /* TYPE C is notification from M core */
+   switch (r_msg->header.cmd) {
+   case TX_PERIOD_DONE:
+   spin_lock_irqsave(>lock[TX], flags);
+   msg = >msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
+
+   /*
+* Low power mode: get the buffer pointer from
+* receive msg.
+*/
+   if (r_msg->header.major == 1 &&
+   r_msg->header.minor == 2)
+   msg->r_msg.param.buffer_tail =
+   r_msg->param.buffer_tail;
+   else
+   msg->r_msg.param.buffer_tail++;
+
+   msg->r_msg.param.buffer_tail %= info->num_period[TX];
+   spin_unlock_irqrestore(>lock[TX], flags);
+   info->callback[TX](info->callback_param[TX]);
+   break;
+   case RX_PERIOD_DONE:
+   spin_lock_irqsave(>lock[RX], flags);
+   msg = >msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
+
+   if (r_msg->header.major == 1 &&
+   r_msg->header.minor == 2)
+   msg->r_msg.param.buffer_tail =
+   r_msg->param.buffer_tail;
+   else
+   msg->r_msg.param.buffer_tail++;
+
+   msg->r_msg.param.buffer_tail %= info->num_period[1];
+   spin_unlock_irqrestore(>lock[RX], flags);
+   info->callback[RX](info->callback_param[RX]);
+   break;
+   default:
+   dev_warn(>dev, "unknown msg command\n");
+   break;
+   }
+   break;
+   case MSG_TYPE_B:
+   /* TYPE B is response msg */
+   memcpy(>r_msg, r_msg, sizeof(struct rpmsg_r_msg));
+   complete(>cmd_complete);
+   break;
+   default:
+   dev_warn(>dev, "unknown msg type\n");
+   break;
+   }
+
+   return 0;
+}
+
+static int imx_audio_rpmsg_probe(struct rpmsg_de

[PATCH v4 3/6] ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver

2021-03-08 Thread Shengjiu Wang
fsl_rpmsg cpu dai driver is driver for rpmsg audio, which is mainly used
for getting the user's configuration from device tree and configure the
clocks which is used by Cortex-M core. So in this document define the
needed property.

Signed-off-by: Shengjiu Wang 
---
 .../devicetree/bindings/sound/fsl,rpmsg.yaml  | 118 ++
 1 file changed, 118 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml

diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml 
b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
new file mode 100644
index ..5731c1fbc0a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/fsl,rpmsg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP Audio RPMSG CPU DAI Controller
+
+maintainers:
+  - Shengjiu Wang 
+
+description: |
+  fsl_rpmsg cpu dai driver is virtual driver for rpmsg audio, which doesn't
+  touch hardware. It is mainly used for getting the user's configuration
+  from device tree and configure the clocks which is used by Cortex-M core.
+  So in this document define the needed property.
+
+properties:
+  compatible:
+enum:
+  - fsl,imx7ulp-rpmsg
+  - fsl,imx8mn-rpmsg
+  - fsl,imx8mm-rpmsg
+  - fsl,imx8mp-rpmsg
+
+  model:
+$ref: /schemas/types.yaml#/definitions/string
+description: User specified audio sound card name
+
+  clocks:
+items:
+  - description: Peripheral clock for register access
+  - description: Master clock
+  - description: DMA clock for DMA register access
+  - description: Parent clock for multiple of 8kHz sample rates
+  - description: Parent clock for multiple of 11kHz sample rates
+minItems: 5
+
+  clock-names:
+items:
+  - const: ipg
+  - const: mclk
+  - const: dma
+  - const: pll8k
+  - const: pll11k
+minItems: 5
+
+  power-domains:
+maxItems: 1
+
+  fsl,audioindex:
+$ref: /schemas/types.yaml#/definitions/uint32
+enum: [0, 1]
+default: 0
+description: Instance index for sound card in
+ M core side, which share one rpmsg
+ channel.
+
+  fsl,version:
+$ref: /schemas/types.yaml#/definitions/uint32
+enum: [1, 2]
+default: 2
+description: The version of M core image, which is
+ to make driver compatible with different image.
+
+  fsl,buffer-size:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: pre allocate dma buffer size
+
+  fsl,enable-lpa:
+$ref: /schemas/types.yaml#/definitions/flag
+description: enable low power audio path.
+
+  fsl,rpmsg-out:
+$ref: /schemas/types.yaml#/definitions/flag
+description: |
+  This is a boolean property. If present, the transmitting function
+  will be enabled.
+
+  fsl,rpmsg-in:
+$ref: /schemas/types.yaml#/definitions/flag
+description: |
+  This is a boolean property. If present, the receiving function
+  will be enabled.
+
+  fsl,codec-type:
+$ref: /schemas/types.yaml#/definitions/uint32
+enum: [0, 1, 2]
+default: 0
+description: Sometimes the codec is registered by
+ driver not by the device tree, this items
+ can be used to distinguish codecs.
+
+  audio-codec:
+$ref: /schemas/types.yaml#/definitions/phandle
+description: The phandle of the audio codec
+
+  memory-region:
+$ref: /schemas/types.yaml#/definitions/phandle
+description: phandle to the reserved memory nodes
+
+required:
+  - compatible
+  - fsl,audioindex
+  - fsl,version
+  - fsl,buffer-size
+
+additionalProperties: false
+
+examples:
+  - |
+rpmsg_audio: rpmsg_audio {
+compatible = "fsl,imx8mn-rpmsg";
+fsl,audioindex = <0> ;
+fsl,version = <2>;
+fsl,buffer-size = <0x600>;
+fsl,enable-lpa;
+};
-- 
2.27.0



[PATCH v4 5/6] ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg

2021-03-08 Thread Shengjiu Wang
Platform driver based on rpmsg is the interface for sending and
receiving rpmsg to and from M core. It will tell the Cortex-M core
sound format/rate/channel, where is the data buffer, where is
the period size, when to start, when to stop and when suspend
or resume happen, each this behavior there is defined rpmsg
command.

Especially we designed the low power audio case, that is to
allocate a large buffer and fill the data, then Cortex-A core can go
to sleep mode, Cortex-M core continue to play the sound, when the
buffer is consumed, Cortex-M core will trigger the Cortex-A core to
wake up.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |   5 +
 sound/soc/fsl/Makefile|   1 +
 sound/soc/fsl/imx-pcm-rpmsg.c | 919 ++
 sound/soc/fsl/imx-pcm-rpmsg.h | 512 +++
 4 files changed, 1437 insertions(+)
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index cc81f6b917be..3b94882aee99 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -130,6 +130,11 @@ config SND_SOC_IMX_AUDIO_RPMSG
tristate
depends on RPMSG
 
+config SND_SOC_IMX_PCM_RPMSG
+   tristate
+   depends on SND_SOC_IMX_AUDIO_RPMSG
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+
 config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index f08f3cd07ff5..ce4f4324c3a2 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
 obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
+obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
new file mode 100644
index ..f05d5d489560
--- /dev/null
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -0,0 +1,919 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2021 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "imx-pcm.h"
+#include "fsl_rpmsg.h"
+#include "imx-pcm-rpmsg.h"
+
+static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
+   .info = SNDRV_PCM_INFO_INTERLEAVED |
+   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+   SNDRV_PCM_INFO_MMAP |
+   SNDRV_PCM_INFO_MMAP_VALID |
+   SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
+   SNDRV_PCM_INFO_PAUSE |
+   SNDRV_PCM_INFO_RESUME,
+   .buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE,
+   .period_bytes_min = 512,
+   .period_bytes_max = 65536,
+   .periods_min = 2,
+   .periods_max = 6000,
+   .fifo_size = 0,
+};
+
+static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
+ struct rpmsg_info *info)
+{
+   struct rpmsg_device *rpdev = info->rpdev;
+   int ret = 0;
+
+   mutex_lock(>msg_lock);
+   if (!rpdev) {
+   dev_err(info->dev, "rpmsg channel not ready\n");
+   mutex_unlock(>msg_lock);
+   return -EINVAL;
+   }
+
+   dev_dbg(>dev, "send cmd %d\n", msg->s_msg.header.cmd);
+
+   if (!(msg->s_msg.header.type == MSG_TYPE_C))
+   reinit_completion(>cmd_complete);
+
+   ret = rpmsg_send(rpdev->ept, (void *)>s_msg,
+sizeof(struct rpmsg_s_msg));
+   if (ret) {
+   dev_err(>dev, "rpmsg_send failed: %d\n", ret);
+   mutex_unlock(>msg_lock);
+   return ret;
+   }
+
+   /* No receive msg for TYPE_C command */
+   if (msg->s_msg.header.type == MSG_TYPE_C) {
+   mutex_unlock(>msg_lock);
+   return 0;
+   }
+
+   /* wait response from rpmsg */
+   ret = wait_for_completion_timeout(>cmd_complete,
+ msecs_to_jiffies(RPMSG_TIMEOUT));
+   if (!ret) {
+   dev_err(>dev, "rpmsg_send cmd %d timeout!\n",
+   msg->s_msg.header.cmd);
+   mutex_unlock(>msg_lock);
+   return -ETIMEDOUT;
+   }
+
+   memcpy(>r_msg, >r_msg, sizeof(struct rpmsg_r_msg));
+   memcpy(>msg[msg->r_msg.header.cmd].r_msg,
+  >r_msg, sizeof(struct rpmsg_r_msg));
+
+   /*
+* Reset the buffer pointer to be zero, actully we have
+* set the buffer pointer to be zero in imx_rpmsg_terminate_all
+* But if there is timer task queued in queue, after it is
+* executed the buffer pointer will be

[PATCH v4 2/6] ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg

2021-03-08 Thread Shengjiu Wang
This is a cpu dai driver for rpmsg audio use case,
which is mainly used for getting the user's configuration
from devicetree and configure the clocks which is used by
Cortex-M core.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |   7 +
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/fsl_rpmsg.c | 283 ++
 sound/soc/fsl/fsl_rpmsg.h |  42 ++
 4 files changed, 334 insertions(+)
 create mode 100644 sound/soc/fsl/fsl_rpmsg.c
 create mode 100644 sound/soc/fsl/fsl_rpmsg.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index d7f30036d434..f833856f6de0 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -115,6 +115,13 @@ config SND_SOC_FSL_AUD2HTX
 config SND_SOC_FSL_UTILS
tristate
 
+config SND_SOC_FSL_RPMSG
+   tristate "NXP Audio Base On RPMSG support"
+   help
+ Say Y if you want to add rpmsg audio support for the Freescale CPUs.
+ This option is only useful for out-of-tree drivers since
+ in-tree drivers select it automatically.
+
 config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 8c5fa8a859c0..b63802f345cc 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -27,6 +27,7 @@ snd-soc-fsl-mqs-objs := fsl_mqs.o
 snd-soc-fsl-easrc-objs := fsl_easrc.o
 snd-soc-fsl-xcvr-objs := fsl_xcvr.o
 snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o
+snd-soc-fsl-rpmsg-objs := fsl_rpmsg.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
@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_SOC_FSL_EASRC) += snd-soc-fsl-easrc.o
 obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
 obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o
 obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o
+obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o
 
 # MPC5200 Platform Support
 obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c
new file mode 100644
index ..35b3ee376338
--- /dev/null
+++ b/sound/soc/fsl/fsl_rpmsg.c
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2018-2021 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "fsl_rpmsg.h"
+#include "imx-pcm.h"
+
+#define FSL_RPMSG_RATES(SNDRV_PCM_RATE_8000 | \
+   SNDRV_PCM_RATE_16000 | \
+   SNDRV_PCM_RATE_48000)
+#define FSL_RPMSG_FORMATS  SNDRV_PCM_FMTBIT_S16_LE
+
+static const unsigned int fsl_rpmsg_rates[] = {
+   8000, 11025, 16000, 22050, 44100,
+   32000, 48000, 96000, 88200, 176400, 192000,
+   352800, 384000, 705600, 768000, 1411200, 2822400,
+};
+
+static const struct snd_pcm_hw_constraint_list fsl_rpmsg_rate_constraints = {
+   .count = ARRAY_SIZE(fsl_rpmsg_rates),
+   .list = fsl_rpmsg_rates,
+};
+
+static int fsl_rpmsg_hw_params(struct snd_pcm_substream *substream,
+  struct snd_pcm_hw_params *params,
+  struct snd_soc_dai *dai)
+{
+   struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai);
+   struct clk *p = rpmsg->mclk, *pll = 0, *npll = 0;
+   u64 rate = params_rate(params);
+   int ret = 0;
+
+   /* Get current pll parent */
+   while (p && rpmsg->pll8k && rpmsg->pll11k) {
+   struct clk *pp = clk_get_parent(p);
+
+   if (clk_is_match(pp, rpmsg->pll8k) ||
+   clk_is_match(pp, rpmsg->pll11k)) {
+   pll = pp;
+   break;
+   }
+   p = pp;
+   }
+
+   /* Switch to another pll parent if needed. */
+   if (pll) {
+   npll = (do_div(rate, 8000) ? rpmsg->pll11k : rpmsg->pll8k);
+   if (!clk_is_match(pll, npll)) {
+   ret = clk_set_parent(p, npll);
+   if (ret < 0)
+   dev_warn(dai->dev, "failed to set parent %s: 
%d\n",
+__clk_get_name(npll), ret);
+   }
+   }
+
+   if (!(rpmsg->mclk_streams & BIT(substream->stream))) {
+   ret = clk_prepare_enable(rpmsg->mclk);
+   if (ret) {
+   dev_err(dai->dev, "failed to enable mclk: %d\n", ret);
+   return ret;
+   }
+
+   rpmsg->mclk_streams |= BIT(substream->stream);
+   }
+
+   return ret;
+}
+
+static int fsl_rpmsg_hw_free(struct snd_pcm_substream *substream,
+struct snd_soc_dai *dai)
+{
+   struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai);
+
+   if (rpmsg-

[PATCH v4 6/6] ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg

2021-03-08 Thread Shengjiu Wang
The platform device is not registered by device tree or
cpu dai driver, it is registered by the rpmsg channel,
So add a dedicated machine driver to handle this case.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |  12 
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/imx-rpmsg.c | 127 ++
 3 files changed, 141 insertions(+)
 create mode 100644 sound/soc/fsl/imx-rpmsg.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 3b94882aee99..ad69026a7fd1 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -334,6 +334,18 @@ config SND_SOC_IMX_HDMI
  Say Y if you want to add support for SoC audio on an i.MX board with
  IMX HDMI.
 
+config SND_SOC_IMX_RPMSG
+   tristate "SoC Audio support for i.MX boards with rpmsg"
+   depends on RPMSG
+   select SND_SOC_IMX_PCM_RPMSG
+   select SND_SOC_IMX_AUDIO_RPMSG
+   select SND_SOC_FSL_RPMSG
+   help
+ SoC Audio support for i.MX boards with rpmsg.
+ There should be rpmsg devices defined in other core (M core)
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a rpmsg devices.
+
 endif # SND_IMX_SOC
 
 endmenu
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index ce4f4324c3a2..f146ce464acd 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -70,6 +70,7 @@ snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
 snd-soc-imx-spdif-objs := imx-spdif.o
 snd-soc-imx-audmix-objs := imx-audmix.o
 snd-soc-imx-hdmi-objs := imx-hdmi.o
+snd-soc-imx-rpmsg-objs := imx-rpmsg.o
 
 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
 obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o
@@ -77,3 +78,4 @@ 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_AUDMIX) += snd-soc-imx-audmix.o
 obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o
+obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o
diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c
new file mode 100644
index ..c26531525a7b
--- /dev/null
+++ b/sound/soc/fsl/imx-rpmsg.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2020 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "imx-pcm-rpmsg.h"
+
+struct imx_rpmsg {
+   struct snd_soc_dai_link dai;
+   struct snd_soc_card card;
+};
+
+static int imx_rpmsg_probe(struct platform_device *pdev)
+{
+   struct snd_soc_dai_link_component *dlc;
+   struct device *dev = pdev->dev.parent;
+   /* rpmsg_pdev is the platform device for the rpmsg node that probed us 
*/
+   struct platform_device *rpmsg_pdev = to_platform_device(dev);
+   struct device_node *np = rpmsg_pdev->dev.of_node;
+   struct of_phandle_args args;
+   struct imx_rpmsg *data;
+   int ret = 0;
+
+   dlc = devm_kzalloc(>dev, 3 * sizeof(*dlc), GFP_KERNEL);
+   if (!dlc)
+   return -ENOMEM;
+
+   data = devm_kzalloc(>dev, sizeof(*data), GFP_KERNEL);
+   if (!data) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+
+   ret = of_reserved_mem_device_init_by_idx(>dev, np, 0);
+   if (ret)
+   dev_warn(>dev, "no reserved DMA memory\n");
+
+   data->dai.cpus = [0];
+   data->dai.num_cpus = 1;
+   data->dai.platforms = [1];
+   data->dai.num_platforms = 1;
+   data->dai.codecs = [2];
+   data->dai.num_codecs = 1;
+
+   data->dai.name = "rpmsg hifi";
+   data->dai.stream_name = "rpmsg hifi";
+   data->dai.dai_fmt = SND_SOC_DAIFMT_I2S |
+   SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS;
+
+   /* Optional codec node */
+   ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, );
+   if (ret) {
+   data->dai.codecs->dai_name = "snd-soc-dummy-dai";
+   data->dai.codecs->name = "snd-soc-dummy";
+   } else {
+   data->dai.codecs->of_node = args.np;
+   ret = snd_soc_get_dai_name(, >dai.codecs->dai_name);
+   if (ret) {
+   dev_err(>dev, "Unable to get codec_dai_name\n");
+   goto fail;
+   }
+   }
+
+   data->dai.cpus->dai_name = dev_name(_pdev->dev);
+   data->dai.platforms->name = IMX_PCM_DRV_NAME;
+   data->dai.playback_only = true;
+   data->dai.capture_only = true;
+   data->card.num_links = 1;
+   data->card.dai_link = >dai;
+
+   if (of_property_read_bool(np, "fsl,rpmsg-out"))
+   data->dai.capture_only = fal

[PATCH v4 0/6] Add audio driver base on rpmsg on i.MX platform

2021-03-08 Thread Shengjiu Wang
On Asymmetric multiprocessor, there is Cortex-A core and Cortex-M core,
Linux is running on A core, RTOS is running on M core.
The audio hardware device can be controlled by Cortex-M device,
So audio playback/capture can be handled by M core.

Rpmsg is the interface for sending and receiving msg to and from M
core, that we can create a virtual sound on Cortex-A core side.

A core will tell the Cortex-M core sound format/rate/channel,
where is the data buffer, what is the period size, when to start,
when to stop and when suspend or resume happen, each of this behavior
there is defined rpmsg command.

Especially we designed the low power audio case, that is to
allocate a large buffer and fill the data, then Cortex-A core can go
to sleep mode, Cortex-M core continue to play the sound, when the
buffer is consumed, Cortex-M core will trigger the Cortex-A core to
wakeup to fill data.

changes in v4:
- remove the sound card node, merge the property to cpu dai node
  according to Rob's comments.
- sound card device will be registered by cpu dai driver.
- Fix do_div issue reported by kernel test robot

changes in v3:
- add local refcount for clk enablement in hw_params()
- update the document according Rob's comments

changes in v2:
- update codes and comments according to Mark's comments

Shengjiu Wang (6):
  ASoC: soc-component: Add snd_soc_pcm_component_ack
  ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg
  ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver
  ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel
  ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg
  ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg

 .../devicetree/bindings/sound/fsl,rpmsg.yaml  | 118 +++
 include/sound/soc-component.h |   3 +
 sound/soc/fsl/Kconfig |  28 +
 sound/soc/fsl/Makefile|   6 +
 sound/soc/fsl/fsl_rpmsg.c | 283 ++
 sound/soc/fsl/fsl_rpmsg.h |  42 +
 sound/soc/fsl/imx-audio-rpmsg.c   | 151 +++
 sound/soc/fsl/imx-pcm-rpmsg.c | 919 ++
 sound/soc/fsl/imx-pcm-rpmsg.h | 512 ++
 sound/soc/fsl/imx-rpmsg.c | 127 +++
 sound/soc/soc-component.c |  14 +
 sound/soc/soc-pcm.c   |   2 +
 12 files changed, 2205 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
 create mode 100644 sound/soc/fsl/fsl_rpmsg.c
 create mode 100644 sound/soc/fsl/fsl_rpmsg.h
 create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h
 create mode 100644 sound/soc/fsl/imx-rpmsg.c

-- 
2.27.0



[PATCH v4 1/6] ASoC: soc-component: Add snd_soc_pcm_component_ack

2021-03-08 Thread Shengjiu Wang
Add snd_soc_pcm_component_ack back, which can be used to get an
updated buffer pointer in the platform driver.
On Asymmetric multiprocessor, this pointer can be sent to Cortex-M
core for audio processing.

Signed-off-by: Shengjiu Wang 
---
 include/sound/soc-component.h |  3 +++
 sound/soc/soc-component.c | 14 ++
 sound/soc/soc-pcm.c   |  2 ++
 3 files changed, 19 insertions(+)

diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 7dc75b39287f..722cfab28d29 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -146,6 +146,8 @@ struct snd_soc_component_driver {
int (*mmap)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
+   int (*ack)(struct snd_soc_component *component,
+  struct snd_pcm_substream *substream);
 
const struct snd_compress_ops *compress_ops;
 
@@ -498,5 +500,6 @@ int snd_soc_pcm_component_pm_runtime_get(struct 
snd_soc_pcm_runtime *rtd,
 void *stream);
 void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
  void *stream, int rollback);
+int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream);
 
 #endif /* __SOC_COMPONENT_H */
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 8415e9bd2932..3a5e84e16a87 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -1212,3 +1212,17 @@ void snd_soc_pcm_component_pm_runtime_put(struct 
snd_soc_pcm_runtime *rtd,
soc_component_mark_pop(component, stream, pm);
}
 }
+
+int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+   struct snd_soc_component *component;
+   int i;
+
+   /* FIXME: use 1st pointer */
+   for_each_rtd_components(rtd, i, component)
+   if (component->driver->ack)
+   return component->driver->ack(component, substream);
+
+   return 0;
+}
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ba8ffbf8a5d3..e75b404a9f36 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2826,6 +2826,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->ops.page   = snd_soc_pcm_component_page;
if (drv->mmap)
rtd->ops.mmap   = snd_soc_pcm_component_mmap;
+   if (drv->ack)
+   rtd->ops.ack= snd_soc_pcm_component_ack;
}
 
if (playback)
-- 
2.27.0



Re: [PATCH v3 7/7] ASoC: dt-bindings: imx-rpmsg: Add binding doc for rpmsg machine driver

2021-03-08 Thread Shengjiu Wang
On Sun, Mar 7, 2021 at 4:37 AM Rob Herring  wrote:
>
> On Thu, Feb 25, 2021 at 10:52:43AM +0800, Shengjiu Wang wrote:
> > Imx-rpmsg is a new added machine driver for supporting audio on Cortex-M
> > core. The Cortex-M core will control the audio interface, DMA and audio
> > codec, setup the pipeline, the audio driver on Cortex-A core side is just
> > to communitcate with M core, it is a virtual sound card and don't touch
> > the hardware.
>
> This sounds like 1 h/w block (the interface to the cortex-M), your DT
> should be 1 node. If you need 2 drivers to satisfy the needs of the OS,
> then instantiate one device from the other device's driver.
>

Ok, I will change it in v4.

best regards
wang shengjiu


[PATCH v2] ASoC: wm8962: Relax bit clock divider searching

2021-03-07 Thread Shengjiu Wang
With S20_3LE format case, the sysclk = rate * 384,
the bclk = rate * 20 * 2, there is no proper bclk divider
for 384 / 40, because current condition needs exact match.
So driver fails to configure the clocking:

wm8962 3-001a: Unsupported BCLK ratio 9

Fix this by relaxing bitclk divider searching, so that when
no exact value can be derived from sysclk pick the closest
value greater than expected bitclk.

Signed-off-by: Shengjiu Wang 
Reviewed-by: Daniel Baluta 
---
changes in v2:
- Add debug message according to Charles's comments

 sound/soc/codecs/wm8962.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index ce4666a74793..34080f497584 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2403,6 +2403,7 @@ static const int sysclk_rates[] = {
 static void wm8962_configure_bclk(struct snd_soc_component *component)
 {
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
+   int best, min_diff, diff;
int dspclk, i;
int clocking2 = 0;
int clocking4 = 0;
@@ -2473,23 +2474,25 @@ static void wm8962_configure_bclk(struct 
snd_soc_component *component)
 
dev_dbg(component->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, 
wm8962->bclk);
 
-   /* We're expecting an exact match */
+   /* Search a proper bclk, not exact match. */
+   best = 0;
+   min_diff = INT_MAX;
for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
if (bclk_divs[i] < 0)
continue;
 
-   if (dspclk / bclk_divs[i] == wm8962->bclk) {
-   dev_dbg(component->dev, "Selected BCLK_DIV %d for 
%dHz\n",
-   bclk_divs[i], wm8962->bclk);
-   clocking2 |= i;
+   diff = (dspclk / bclk_divs[i]) - wm8962->bclk;
+   if (diff < 0) /* Table is sorted */
break;
+   if (diff < min_diff) {
+   best = i;
+   min_diff = diff;
}
}
-   if (i == ARRAY_SIZE(bclk_divs)) {
-   dev_err(component->dev, "Unsupported BCLK ratio %d\n",
-   dspclk / wm8962->bclk);
-   return;
-   }
+   wm8962->bclk = dspclk / bclk_divs[best];
+   clocking2 |= best;
+   dev_dbg(component->dev, "Selected BCLK_DIV %d for %dHz\n",
+   bclk_divs[best], wm8962->bclk);
 
aif2 |= wm8962->bclk / wm8962->lrclk;
dev_dbg(component->dev, "Selected LRCLK divisor %d for %dHz\n",
-- 
2.27.0



[PATCH] ASoC: fsl_asrc_dma: request dma channel from specific controller

2021-03-05 Thread Shengjiu Wang
From: Robin Gong 

Request dma channel from specific dma controller instead of generic
dma controller list, otherwise, may get the wrong dma controller
if there are multi dma controllers such as i.MX8MP.

Signed-off-by: Robin Gong 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_asrc_dma.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index 29f91cdecbc3..c313a26c8f95 100644
--- a/sound/soc/fsl/fsl_asrc_dma.c
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -141,6 +141,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
struct dma_slave_config config_fe, config_be;
enum asrc_pair_index index = pair->index;
struct device *dev = component->dev;
+   struct device_node *of_dma_node;
int stream = substream->stream;
struct imx_dma_data *tmp_data;
struct snd_soc_dpcm *dpcm;
@@ -231,8 +232,10 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
pair->dma_data.priority = tmp_data->priority;
dma_release_channel(tmp_chan);
 
+   of_dma_node = pair->dma_chan[!dir]->device->dev->of_node;
pair->dma_chan[dir] =
-   dma_request_channel(mask, filter, >dma_data);
+   __dma_request_channel(, filter, >dma_data,
+ of_dma_node);
pair->req_dma_chan = true;
} else {
pair->dma_chan[dir] = tmp_chan;
-- 
2.27.0



Re: [PATCH v2 7/7] ASoC: dt-bindings: imx-rpmsg: Add binding doc for rpmsg machine driver

2021-03-04 Thread Shengjiu Wang
Hi

On Fri, Mar 5, 2021 at 4:05 AM Rob Herring  wrote:
>
> On Thu, Feb 18, 2021 at 1:23 AM Shengjiu Wang  wrote:
> >
> > On Thu, Feb 11, 2021 at 6:18 AM Rob Herring  wrote:
> > >
> > > On Sun, Feb 07, 2021 at 06:23:55PM +0800, Shengjiu Wang wrote:
> > > > Imx-rpmsg is a new added machine driver for supporting audio on Cortex-M
> > > > core. The Cortex-M core will control the audio interface, DMA and audio
> > > > codec, setup the pipeline, the audio driver on Cortex-A core side is 
> > > > just
> > > > to communitcate with M core, it is a virtual sound card and don't touch
> > > > the hardware.
> > >
> > > I don't understand why there are 2 nodes for this other than you happen
> > > to want to split this into 2 Linux drivers. It's 1 h/w thing.
> >
> > This one is for the sound card machine driver.  Another one is
> > for the sound card cpu dai driver. so there are 2 nodes.
>
> You are explaining this to me in terms of drivers. Explain it in terms
> of h/w blocks.
>

Yes, there is only 1 h/w block, which is (MU) message unit

As the sound card needs a cpu dai node and sound card node,
so from the driver's perspective, I use two nodes.

Seems It is hard to only use one node for my case.
or do you have any suggestions?

Best regards
Wang shengjiu


[PATCH] ASoC: wm8962: Relax bit clock divider searching

2021-03-03 Thread Shengjiu Wang
With S20_3LE format case, the sysclk = rate * 384,
the bclk = rate * 20 * 2, there is no proper bclk divider
for 384 / 40, because current condition needs exact match.
So driver fails to configure the clocking:

wm8962 3-001a: Unsupported BCLK ratio 9

Fix this by relaxing bitclk divider searching, so that when
no exact value can be derived from sysclk pick the closest
value greater than expected bitclk.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/codecs/wm8962.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index ce4666a74793..f5cd22450190 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2403,6 +2403,7 @@ static const int sysclk_rates[] = {
 static void wm8962_configure_bclk(struct snd_soc_component *component)
 {
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
+   int best, min_diff, diff;
int dspclk, i;
int clocking2 = 0;
int clocking4 = 0;
@@ -2473,23 +2474,23 @@ static void wm8962_configure_bclk(struct 
snd_soc_component *component)
 
dev_dbg(component->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, 
wm8962->bclk);
 
-   /* We're expecting an exact match */
+   /* Search a proper bclk, not exact match. */
+   best = 0;
+   min_diff = INT_MAX;
for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
if (bclk_divs[i] < 0)
continue;
 
-   if (dspclk / bclk_divs[i] == wm8962->bclk) {
-   dev_dbg(component->dev, "Selected BCLK_DIV %d for 
%dHz\n",
-   bclk_divs[i], wm8962->bclk);
-   clocking2 |= i;
+   diff = (dspclk / bclk_divs[i]) - wm8962->bclk;
+   if (diff < 0) /* Table is sorted */
break;
+   if (diff < min_diff) {
+   best = i;
+   min_diff = diff;
}
}
-   if (i == ARRAY_SIZE(bclk_divs)) {
-   dev_err(component->dev, "Unsupported BCLK ratio %d\n",
-   dspclk / wm8962->bclk);
-   return;
-   }
+   wm8962->bclk = dspclk / bclk_divs[best];
+   clocking2 |= best;
 
aif2 |= wm8962->bclk / wm8962->lrclk;
dev_dbg(component->dev, "Selected LRCLK divisor %d for %dHz\n",
-- 
2.27.0



[PATCH v2] ASoC: wm8960: Remove bitclk relax condition in wm8960_configure_sysclk

2021-03-03 Thread Shengjiu Wang
The call sequence in wm8960_configure_clocking is

   ret = wm8960_configure_sysclk();
   if (ret >= 0)
goto configure_clock;

   

   ret = wm8960_configure_pll();

configure_clock:
   ...

wm8960_configure_sysclk is called before wm8960_configure_pll, as
there is bitclk relax on both functions, so wm8960_configure_sysclk
always return success, then wm8960_configure_pll() never be called.

With this case:
aplay -Dhw:0,0 -d 5 -r 48000 -f S24_LE -c 2 audio48k24b2c.wav
the required bitclk is 48000 * 24 * 2 = 2304000, bitclk got from
wm8960_configure_sysclk is 3072000, but if go to wm8960_configure_pll.
it can get correct bitclk 2304000.

So bitclk relax condition should be removed in wm8960_configure_sysclk,
then wm8960_configure_pll can be called, and there is also bitclk relax
function in wm8960_configure_pll.

Fixes: 3c01b9ee2ab9 ("ASoC: codec: wm8960: Relax bit clock computation")
Signed-off-by: Shengjiu Wang 
Signed-off-by: Daniel Baluta 
---
changes in v2:
- Find the real reason for the case, just patially remove bitclk relax

 sound/soc/codecs/wm8960.c | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index df351519a3a6..847ca16b9841 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -608,10 +608,6 @@ static const int bclk_divs[] = {
  * - lrclk  = sysclk / dac_divs
  * - 10 * bclk  = sysclk / bclk_divs
  *
- * If we cannot find an exact match for (sysclk, lrclk, bclk)
- * triplet, we relax the bclk such that bclk is chosen as the
- * closest available frequency greater than expected bclk.
- *
  * @wm8960: codec private data
  * @mclk: MCLK used to derive sysclk
  * @sysclk_idx: sysclk_divs index for found sysclk
@@ -629,7 +625,7 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int 
mclk,
 {
int sysclk, bclk, lrclk;
int i, j, k;
-   int diff, closest = mclk;
+   int diff;
 
/* marker for no match */
*bclk_idx = -1;
@@ -653,12 +649,6 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, 
int mclk,
*bclk_idx = k;
break;
}
-   if (diff > 0 && closest > diff) {
-   *sysclk_idx = i;
-   *dac_idx = j;
-   *bclk_idx = k;
-   closest = diff;
-   }
}
if (k != ARRAY_SIZE(bclk_divs))
break;
-- 
2.27.0



[PATCH] ASoC: wm8960: Remove bitclk relax condition

2021-03-02 Thread Shengjiu Wang
From: Daniel Baluta 

Using a higher bitclk then expected doesn't always work.
Here is an example:

aplay -Dhw:0,0 -d 5 -r 48000 -f S24_LE -c 2 audio48k24b2c.wav

In this case, the required bitclk is 48000 * 24 * 2 = 2304000
but the closest bitclk that can be derived is 3072000. Since
the clock is faster than expected, it will start to send bytes
from the next channel so the sound will be corrupted.

Fixes: 82bab88910ee ("ASoC: codec: wm8960: Relax bit clock computation when 
using PLL")
Fixes: 3c01b9ee2ab9 ("ASoC: codec: wm8960: Relax bit clock computation")
Signed-off-by: Daniel Baluta 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/codecs/wm8960.c | 29 +++--
 1 file changed, 3 insertions(+), 26 deletions(-)

diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index df351519a3a6..368bec1dfbdb 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -608,10 +608,6 @@ static const int bclk_divs[] = {
  * - lrclk  = sysclk / dac_divs
  * - 10 * bclk  = sysclk / bclk_divs
  *
- * If we cannot find an exact match for (sysclk, lrclk, bclk)
- * triplet, we relax the bclk such that bclk is chosen as the
- * closest available frequency greater than expected bclk.
- *
  * @wm8960: codec private data
  * @mclk: MCLK used to derive sysclk
  * @sysclk_idx: sysclk_divs index for found sysclk
@@ -629,7 +625,7 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int 
mclk,
 {
int sysclk, bclk, lrclk;
int i, j, k;
-   int diff, closest = mclk;
+   int diff;
 
/* marker for no match */
*bclk_idx = -1;
@@ -653,12 +649,6 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, 
int mclk,
*bclk_idx = k;
break;
}
-   if (diff > 0 && closest > diff) {
-   *sysclk_idx = i;
-   *dac_idx = j;
-   *bclk_idx = k;
-   closest = diff;
-   }
}
if (k != ARRAY_SIZE(bclk_divs))
break;
@@ -676,10 +666,6 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, 
int mclk,
  * - freq_out= sysclk * sysclk_divs
  * - 10 * sysclk = bclk * bclk_divs
  *
- * If we cannot find an exact match for (sysclk, lrclk, bclk)
- * triplet, we relax the bclk such that bclk is chosen as the
- * closest available frequency greater than expected bclk.
- *
  * @component: component structure
  * @freq_in: input frequency used to derive freq out via PLL
  * @sysclk_idx: sysclk_divs index for found sysclk
@@ -697,14 +683,12 @@ int wm8960_configure_pll(struct snd_soc_component 
*component, int freq_in,
 {
struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);
int sysclk, bclk, lrclk, freq_out;
-   int diff, closest, best_freq_out;
+   int diff;
int i, j, k;
 
bclk = wm8960->bclk;
lrclk = wm8960->lrclk;
-   closest = freq_in;
 
-   best_freq_out = -EINVAL;
*sysclk_idx = *dac_idx = *bclk_idx = -1;
 
for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
@@ -725,18 +709,11 @@ int wm8960_configure_pll(struct snd_soc_component 
*component, int freq_in,
*bclk_idx = k;
return freq_out;
}
-   if (diff > 0 && closest > diff) {
-   *sysclk_idx = i;
-   *dac_idx = j;
-   *bclk_idx = k;
-   closest = diff;
-   best_freq_out = freq_out;
-   }
}
}
}
 
-   return best_freq_out;
+   return -EINVAL;
 }
 static int wm8960_configure_clocking(struct snd_soc_component *component)
 {
-- 
2.27.0



Re: [PATCH] ASoC: simple-card: Add dummy dai support simple sound card

2021-02-25 Thread Shengjiu Wang
On Thu, Feb 25, 2021 at 9:17 PM Mark Brown  wrote:
>
> On Thu, Feb 25, 2021 at 08:08:32PM +0800, Shengjiu Wang wrote:
>
> > If sound card doesn't need specific codec device, just
> > dummy codec is enough, then we can link the dummy component
> > directly.
>
> This is a big red flag - what circumstances are these?  If it's a simple
> CODEC with no control then the general approach is to provide a driver
> which announces the capabilities of the CODEC and can be bound to as
> normal, the dummy component should never actively be used.

For the DMIC, SPDIF, HDMI ARC device or other
similar device that there is no codec connected,  then dummy codec is
just used for registering the sound card.

best regards
wang shengjiu


[PATCH] ASoC: simple-card: Add dummy dai support simple sound card

2021-02-25 Thread Shengjiu Wang
If sound card doesn't need specific codec device, just
dummy codec is enough, then we can link the dummy component
directly.

In this case, user needs to specify below setting in
devicetree. Previously the sound-dai is a node of codec,
now we check if it is zero before parsing the node, zero
means dummy component is specified.

simple-audio-card,codec {
sound-dai = <0>;
};

Signed-off-by: Shengjiu Wang 
---
 sound/soc/generic/simple-card.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index c262281bc64d..8b0cabd1bad1 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -34,10 +34,19 @@ static int asoc_simple_parse_dai(struct device_node *node,
 {
struct of_phandle_args args;
int ret;
+   u32 val;
 
if (!node)
return 0;
 
+   ret = of_property_read_u32(node, DAI, );
+   if (val == 0) {
+   dlc->of_node   = NULL;
+   dlc->dai_name  = "snd-soc-dummy-dai";
+   dlc->name  = "snd-soc-dummy";
+   return 0;
+   }
+
/*
 * Get node via "sound-dai = < port>"
 * it will be used as xxx_of_node on soc_bind_dai_link()
-- 
2.27.0



[PATCH v3 5/7] ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg

2021-02-24 Thread Shengjiu Wang
platform driver base on rpmsg is the interface for sending and
receiving rpmsg to and from M core. It will tell the Cortex-M core
sound format/rate/channel, where is the data buffer, where is
the period size, when to start, when to stop and when suspend
or resume happen, each this behavior there is defined rpmsg
command.

Especially we designed the low power audio case, that is to
allocate a large buffer and fill the data, then Cortex-A core can go
to sleep mode, Cortex-M core continue to play the sound, when the
buffer is consumed, Cortex-M core will trigger the Cortex-A core to
wakeup.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |   5 +
 sound/soc/fsl/Makefile|   1 +
 sound/soc/fsl/imx-pcm-rpmsg.c | 919 ++
 sound/soc/fsl/imx-pcm-rpmsg.h | 512 +++
 4 files changed, 1437 insertions(+)
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 84d9f0f1f75b..749c44fc0759 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -130,6 +130,11 @@ config SND_SOC_IMX_AUDIO_RPMSG
tristate
depends on RPMSG
 
+config SND_SOC_IMX_PCM_RPMSG
+   tristate
+   depends on SND_SOC_IMX_AUDIO_RPMSG
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+
 config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index f08f3cd07ff5..ce4f4324c3a2 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
 obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
+obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
new file mode 100644
index ..f05d5d489560
--- /dev/null
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -0,0 +1,919 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2021 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "imx-pcm.h"
+#include "fsl_rpmsg.h"
+#include "imx-pcm-rpmsg.h"
+
+static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
+   .info = SNDRV_PCM_INFO_INTERLEAVED |
+   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+   SNDRV_PCM_INFO_MMAP |
+   SNDRV_PCM_INFO_MMAP_VALID |
+   SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
+   SNDRV_PCM_INFO_PAUSE |
+   SNDRV_PCM_INFO_RESUME,
+   .buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE,
+   .period_bytes_min = 512,
+   .period_bytes_max = 65536,
+   .periods_min = 2,
+   .periods_max = 6000,
+   .fifo_size = 0,
+};
+
+static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
+ struct rpmsg_info *info)
+{
+   struct rpmsg_device *rpdev = info->rpdev;
+   int ret = 0;
+
+   mutex_lock(>msg_lock);
+   if (!rpdev) {
+   dev_err(info->dev, "rpmsg channel not ready\n");
+   mutex_unlock(>msg_lock);
+   return -EINVAL;
+   }
+
+   dev_dbg(>dev, "send cmd %d\n", msg->s_msg.header.cmd);
+
+   if (!(msg->s_msg.header.type == MSG_TYPE_C))
+   reinit_completion(>cmd_complete);
+
+   ret = rpmsg_send(rpdev->ept, (void *)>s_msg,
+sizeof(struct rpmsg_s_msg));
+   if (ret) {
+   dev_err(>dev, "rpmsg_send failed: %d\n", ret);
+   mutex_unlock(>msg_lock);
+   return ret;
+   }
+
+   /* No receive msg for TYPE_C command */
+   if (msg->s_msg.header.type == MSG_TYPE_C) {
+   mutex_unlock(>msg_lock);
+   return 0;
+   }
+
+   /* wait response from rpmsg */
+   ret = wait_for_completion_timeout(>cmd_complete,
+ msecs_to_jiffies(RPMSG_TIMEOUT));
+   if (!ret) {
+   dev_err(>dev, "rpmsg_send cmd %d timeout!\n",
+   msg->s_msg.header.cmd);
+   mutex_unlock(>msg_lock);
+   return -ETIMEDOUT;
+   }
+
+   memcpy(>r_msg, >r_msg, sizeof(struct rpmsg_r_msg));
+   memcpy(>msg[msg->r_msg.header.cmd].r_msg,
+  >r_msg, sizeof(struct rpmsg_r_msg));
+
+   /*
+* Reset the buffer pointer to be zero, actully we have
+* set the buffer pointer to be zero in imx_rpmsg_terminate_all
+* But if there is timer task queued in queue, after it is
+* executed the buffer pointer will be

[PATCH v3 6/7] ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg

2021-02-24 Thread Shengjiu Wang
The platform device is not registered by device tree or
cpu dai driver, it is registered by the rpmsg channel,
So add a dedicated machine driver to handle this case.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |  12 
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/imx-rpmsg.c | 148 ++
 3 files changed, 162 insertions(+)
 create mode 100644 sound/soc/fsl/imx-rpmsg.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 749c44fc0759..3557866d3fa2 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -334,6 +334,18 @@ config SND_SOC_IMX_HDMI
  Say Y if you want to add support for SoC audio on an i.MX board with
  IMX HDMI.
 
+config SND_SOC_IMX_RPMSG
+   tristate "SoC Audio support for i.MX boards with rpmsg"
+   depends on RPMSG
+   select SND_SOC_IMX_PCM_RPMSG
+   select SND_SOC_IMX_AUDIO_RPMSG
+   select SND_SOC_FSL_RPMSG
+   help
+ SoC Audio support for i.MX boards with rpmsg.
+ There should be rpmsg devices defined in other core (M core)
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a rpmsg devices.
+
 endif # SND_IMX_SOC
 
 endmenu
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index ce4f4324c3a2..f146ce464acd 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -70,6 +70,7 @@ snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
 snd-soc-imx-spdif-objs := imx-spdif.o
 snd-soc-imx-audmix-objs := imx-audmix.o
 snd-soc-imx-hdmi-objs := imx-hdmi.o
+snd-soc-imx-rpmsg-objs := imx-rpmsg.o
 
 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
 obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o
@@ -77,3 +78,4 @@ 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_AUDMIX) += snd-soc-imx-audmix.o
 obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o
+obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o
diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c
new file mode 100644
index ..a87dcbce4f36
--- /dev/null
+++ b/sound/soc/fsl/imx-rpmsg.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2020 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "imx-pcm-rpmsg.h"
+
+struct imx_rpmsg {
+   struct snd_soc_dai_link dai;
+   struct snd_soc_card card;
+};
+
+static int imx_rpmsg_probe(struct platform_device *pdev)
+{
+   struct snd_soc_dai_link_component *dlc;
+   struct platform_device *cpu_pdev;
+   struct of_phandle_args args;
+   struct device_node *cpu_np;
+   struct imx_rpmsg *data;
+   int ret;
+
+   dlc = devm_kzalloc(>dev, 3 * sizeof(*dlc), GFP_KERNEL);
+   if (!dlc)
+   return -ENOMEM;
+
+   cpu_np = of_parse_phandle(pdev->dev.of_node, "audio-cpu", 0);
+   if (!cpu_np) {
+   dev_err(>dev, "cpu dai phandle missing or invalid\n");
+   ret = -EINVAL;
+   goto fail;
+   }
+
+   data = devm_kzalloc(>dev, sizeof(*data), GFP_KERNEL);
+   if (!data) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+
+   cpu_pdev = of_find_device_by_node(cpu_np);
+   if (!cpu_pdev) {
+   dev_err(>dev, "failed to find rpmsg platform device\n");
+   ret = -EINVAL;
+   goto fail;
+   }
+
+   ret = of_reserved_mem_device_init_by_idx(>dev, pdev->dev.of_node, 
0);
+   if (ret)
+   dev_warn(>dev, "no reserved DMA memory\n");
+
+   data->dai.cpus = [0];
+   data->dai.num_cpus = 1;
+   data->dai.platforms = [1];
+   data->dai.num_platforms = 1;
+   data->dai.codecs = [2];
+   data->dai.num_codecs = 1;
+
+   data->dai.name = "rpmsg hifi";
+   data->dai.stream_name = "rpmsg hifi";
+   data->dai.dai_fmt = SND_SOC_DAIFMT_I2S |
+   SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS;
+
+   /* Optional codec node */
+   ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
+  "audio-codec", 0, 0, );
+   if (ret) {
+   data->dai.codecs->dai_name = "snd-soc-dummy-dai";
+   data->dai.codecs->name = "snd-soc-dummy";
+   } else {
+   data->dai.codecs->of_node = args.np;
+   ret = snd_soc_get_dai_name(, >dai.codecs->dai_name);
+   if (ret) {
+   dev_err(>dev, "Unable to get codec_dai_name\n");
+   goto fail;
+   }
+   }
+
+   data->dai.

[PATCH v3 7/7] ASoC: dt-bindings: imx-rpmsg: Add binding doc for rpmsg machine driver

2021-02-24 Thread Shengjiu Wang
Imx-rpmsg is a new added machine driver for supporting audio on Cortex-M
core. The Cortex-M core will control the audio interface, DMA and audio
codec, setup the pipeline, the audio driver on Cortex-A core side is just
to communitcate with M core, it is a virtual sound card and don't touch
the hardware.

Signed-off-by: Shengjiu Wang 
---
 .../bindings/sound/imx-audio-rpmsg.yaml   | 55 +++
 1 file changed, 55 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml

diff --git a/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml 
b/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
new file mode 100644
index ..ff9b3fc69dae
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/imx-audio-rpmsg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX audio complex with rpmsg
+
+maintainers:
+  - Shengjiu Wang 
+
+description: |
+  imx-rpmsg is a machine driver for supporting audio by rpmsg.
+  The Cortex-M core will control the audio interface, DMA and audio
+  codec, setup the pipeline, the audio driver on Cortex-A core side
+  is just to communitcate with M core, it is a virtual sound card
+  and don't touch the hardware.
+
+properties:
+  compatible:
+enum:
+  - fsl,imx-audio-rpmsg
+
+  model:
+$ref: /schemas/types.yaml#/definitions/string
+description: User specified audio sound card name
+
+  audio-cpu:
+description: The phandle of an CPU DAI controller
+
+  rpmsg-out:
+description: |
+  This is a boolean property. If present, the transmitting function
+  will be enabled,
+
+  rpmsg-in:
+description: |
+  This is a boolean property. If present, the receiving function
+  will be enabled.
+
+required:
+  - compatible
+  - model
+  - audio-cpu
+
+additionalProperties: false
+
+examples:
+  - |
+sound-rpmsg {
+compatible = "fsl,imx-audio-rpmsg";
+model = "ak4497-audio";
+audio-cpu = <_audio>;
+rpmsg-out;
+};
-- 
2.27.0



[PATCH v3 4/7] ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel

2021-02-24 Thread Shengjiu Wang
This driver is used to accept the message from rpmsg audio
channel, and if this driver is probed, it will help to register
the platform driver, the platform driver will use this
audio channel to send and receive message to and from Cortex-M
core.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig   |   4 +
 sound/soc/fsl/Makefile  |   1 +
 sound/soc/fsl/imx-audio-rpmsg.c | 151 
 3 files changed, 156 insertions(+)
 create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index a688c3c2efbc..84d9f0f1f75b 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -126,6 +126,10 @@ config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
 
+config SND_SOC_IMX_AUDIO_RPMSG
+   tristate
+   depends on RPMSG
+
 config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index b63802f345cc..f08f3cd07ff5 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 
 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
+obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c
new file mode 100644
index ..145edb1492b4
--- /dev/null
+++ b/sound/soc/fsl/imx-audio-rpmsg.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2020 NXP
+
+#include 
+#include 
+#include "imx-pcm-rpmsg.h"
+
+/*
+ * struct imx_audio_rpmsg: private data
+ *
+ * @rpmsg_pdev: pointer of platform device
+ */
+struct imx_audio_rpmsg {
+   struct platform_device *rpmsg_pdev;
+};
+
+static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
+ void *priv, u32 src)
+{
+   struct imx_audio_rpmsg *rpmsg = dev_get_drvdata(>dev);
+   struct rpmsg_info *info = platform_get_drvdata(rpmsg->rpmsg_pdev);
+   struct rpmsg_r_msg *r_msg = (struct rpmsg_r_msg *)data;
+   struct rpmsg_msg *msg;
+   unsigned long flags;
+
+   dev_dbg(>dev, "get from%d: cmd:%d. %d\n",
+   src, r_msg->header.cmd, r_msg->param.resp);
+
+   switch (r_msg->header.type) {
+   case MSG_TYPE_C:
+   /* TYPE C is notification from M core */
+   switch (r_msg->header.cmd) {
+   case TX_PERIOD_DONE:
+   spin_lock_irqsave(>lock[TX], flags);
+   msg = >msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
+
+   /*
+* Low power mode: get the buffer pointer from
+* receive msg.
+*/
+   if (r_msg->header.major == 1 &&
+   r_msg->header.minor == 2)
+   msg->r_msg.param.buffer_tail =
+   r_msg->param.buffer_tail;
+   else
+   msg->r_msg.param.buffer_tail++;
+
+   msg->r_msg.param.buffer_tail %= info->num_period[TX];
+   spin_unlock_irqrestore(>lock[TX], flags);
+   info->callback[TX](info->callback_param[TX]);
+   break;
+   case RX_PERIOD_DONE:
+   spin_lock_irqsave(>lock[RX], flags);
+   msg = >msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
+
+   if (r_msg->header.major == 1 &&
+   r_msg->header.minor == 2)
+   msg->r_msg.param.buffer_tail =
+   r_msg->param.buffer_tail;
+   else
+   msg->r_msg.param.buffer_tail++;
+
+   msg->r_msg.param.buffer_tail %= info->num_period[1];
+   spin_unlock_irqrestore(>lock[RX], flags);
+   info->callback[RX](info->callback_param[RX]);
+   break;
+   default:
+   dev_warn(>dev, "unknown msg command\n");
+   break;
+   }
+   break;
+   case MSG_TYPE_B:
+   /* TYPE B is response msg */
+   memcpy(>r_msg, r_msg, sizeof(struct rpmsg_r_msg));
+   complete(>cmd_complete);
+   break;
+   default:
+   dev_warn(>dev, "unknown msg type\n");
+   break;
+   }
+
+   return 0;
+}
+
+static int imx_audio_rpmsg_probe(struct rpmsg_de

[PATCH v3 3/7] ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver

2021-02-24 Thread Shengjiu Wang
fsl_rpmsg cpu dai driver is driver for rpmsg audio, which is mainly used
for getting the user's configuration from device tree and configure the
clocks which is used by Cortex-M core. So in this document define the
needed property.

Signed-off-by: Shengjiu Wang 
---
 .../devicetree/bindings/sound/fsl,rpmsg.yaml  | 94 +++
 1 file changed, 94 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml

diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml 
b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
new file mode 100644
index ..ab6d3b8d0d38
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/fsl,rpmsg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP Audio RPMSG CPU DAI Controller
+
+maintainers:
+  - Shengjiu Wang 
+
+description: |
+  fsl_rpmsg cpu dai driver is virtual driver for rpmsg audio, which doesn't
+  touch hardware. It is mainly used for getting the user's configuration
+  from device tree and configure the clocks which is used by Cortex-M core.
+  So in this document define the needed property.
+
+properties:
+  compatible:
+enum:
+  - fsl,imx7ulp-rpmsg
+  - fsl,imx8mn-rpmsg
+  - fsl,imx8mm-rpmsg
+  - fsl,imx8mp-rpmsg
+
+  clocks:
+items:
+  - description: Peripheral clock for register access
+  - description: Master clock
+  - description: DMA clock for DMA register access
+  - description: Parent clock for multiple of 8kHz sample rates
+  - description: Parent clock for multiple of 11kHz sample rates
+minItems: 5
+
+  clock-names:
+items:
+  - const: ipg
+  - const: mclk
+  - const: dma
+  - const: pll8k
+  - const: pll11k
+minItems: 5
+
+  power-domains:
+maxItems: 1
+
+  fsl,audioindex:
+$ref: /schemas/types.yaml#/definitions/uint32
+enum: [0, 1]
+default: 0
+description: Instance index for sound card in
+ M core side, which share one rpmsg
+ channel.
+
+  fsl,version:
+$ref: /schemas/types.yaml#/definitions/uint32
+enum: [1, 2]
+default: 2
+description: The version of M core image, which is
+ to make driver compatible with different image.
+
+  fsl,buffer-size:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: pre allocate dma buffer size
+
+  fsl,enable-lpa:
+$ref: /schemas/types.yaml#/definitions/flag
+description: enable low power audio path.
+
+  fsl,codec-type:
+$ref: /schemas/types.yaml#/definitions/uint32
+enum: [0, 1, 2]
+default: 0
+description: Sometimes the codec is registered by
+ driver not the device tree, this items
+ can be used to distinguish codecs.
+
+required:
+  - compatible
+  - fsl,audioindex
+  - fsl,version
+  - fsl,buffer-size
+
+additionalProperties: false
+
+examples:
+  - |
+rpmsg_audio: rpmsg_audio {
+compatible = "fsl,imx8mn-rpmsg";
+fsl,audioindex = <0> ;
+fsl,version = <2>;
+fsl,buffer-size = <0x600>;
+fsl,enable-lpa;
+};
-- 
2.27.0



[PATCH v3 0/7] Add audio driver base on rpmsg on i.MX platform

2021-02-24 Thread Shengjiu Wang
On Asymmetric multiprocessor, there is Cortex-A core and Cortex-M core,
Linux is running on A core, RTOS is running on M core.
The audio hardware device can be controlled by Cortex-M device,
So audio playback/capture can be handled by M core.

Rpmsg is the interface for sending and receiving msg to and from M
core, that we can create a virtual sound on Cortex-A core side.

A core will tell the Cortex-M core sound format/rate/channel,
where is the data buffer, what is the period size, when to start,
when to stop and when suspend or resume happen, each of this behavior
there is defined rpmsg command.

Especially we designed the low power audio case, that is to
allocate a large buffer and fill the data, then Cortex-A core can go
to sleep mode, Cortex-M core continue to play the sound, when the
buffer is consumed, Cortex-M core will trigger the Cortex-A core to
wakeup to fill data.

changes in v3:
- add local refcount for clk enablement in hw_params()
- update the document according Rob's comments

changes in v2:
- update codes and comments according to Mark's comments

Shengjiu Wang (7):
  ASoC: soc-component: Add snd_soc_pcm_component_ack
  ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg
  ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver
  ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel
  ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg
  ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg
  ASoC: dt-bindings: imx-rpmsg: Add binding doc for rpmsg machine driver

 .../devicetree/bindings/sound/fsl,rpmsg.yaml  |  94 ++
 .../bindings/sound/imx-audio-rpmsg.yaml   |  55 ++
 include/sound/soc-component.h |   3 +
 sound/soc/fsl/Kconfig |  28 +
 sound/soc/fsl/Makefile|   6 +
 sound/soc/fsl/fsl_rpmsg.c | 261 +
 sound/soc/fsl/fsl_rpmsg.h |  40 +
 sound/soc/fsl/imx-audio-rpmsg.c   | 151 +++
 sound/soc/fsl/imx-pcm-rpmsg.c | 919 ++
 sound/soc/fsl/imx-pcm-rpmsg.h | 512 ++
 sound/soc/fsl/imx-rpmsg.c | 148 +++
 sound/soc/soc-component.c |  14 +
 sound/soc/soc-pcm.c   |   2 +
 13 files changed, 2233 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
 create mode 100644 sound/soc/fsl/fsl_rpmsg.c
 create mode 100644 sound/soc/fsl/fsl_rpmsg.h
 create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h
 create mode 100644 sound/soc/fsl/imx-rpmsg.c

-- 
2.27.0



[PATCH v3 1/7] ASoC: soc-component: Add snd_soc_pcm_component_ack

2021-02-24 Thread Shengjiu Wang
Add snd_soc_pcm_component_ack back, which can be used to get updated
buffer pointer in platform driver.
On Asymmetric multiprocessor, this pointer can be sent to Cortex-M
core for audio processing.

Signed-off-by: Shengjiu Wang 
---
 include/sound/soc-component.h |  3 +++
 sound/soc/soc-component.c | 14 ++
 sound/soc/soc-pcm.c   |  2 ++
 3 files changed, 19 insertions(+)

diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 5b47768222b7..2dc8c7e3d1a6 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -146,6 +146,8 @@ struct snd_soc_component_driver {
int (*mmap)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
+   int (*ack)(struct snd_soc_component *component,
+  struct snd_pcm_substream *substream);
 
const struct snd_compress_ops *compress_ops;
 
@@ -498,5 +500,6 @@ int snd_soc_pcm_component_pm_runtime_get(struct 
snd_soc_pcm_runtime *rtd,
 void *stream);
 void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
  void *stream, int rollback);
+int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream);
 
 #endif /* __SOC_COMPONENT_H */
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 159bf88b9f8c..a9fbb2d26412 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -1212,3 +1212,17 @@ void snd_soc_pcm_component_pm_runtime_put(struct 
snd_soc_pcm_runtime *rtd,
soc_component_mark_pop(component, stream, pm);
}
 }
+
+int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+   struct snd_soc_component *component;
+   int i;
+
+   /* FIXME: use 1st pointer */
+   for_each_rtd_components(rtd, i, component)
+   if (component->driver->ack)
+   return component->driver->ack(component, substream);
+
+   return 0;
+}
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 14d85ca1e435..a1b81d4d678c 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2833,6 +2833,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->ops.page   = snd_soc_pcm_component_page;
if (drv->mmap)
rtd->ops.mmap   = snd_soc_pcm_component_mmap;
+   if (drv->ack)
+   rtd->ops.ack= snd_soc_pcm_component_ack;
}
 
if (playback)
-- 
2.27.0



[PATCH v3 2/7] ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg

2021-02-24 Thread Shengjiu Wang
This is a cpu dai driver for rpmsg audio use case,
which is mainly used for getting the user's configuration
from devicetree and configure the clocks which is used by
Cortex-M core.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |   7 +
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/fsl_rpmsg.c | 261 ++
 sound/soc/fsl/fsl_rpmsg.h |  40 ++
 4 files changed, 310 insertions(+)
 create mode 100644 sound/soc/fsl/fsl_rpmsg.c
 create mode 100644 sound/soc/fsl/fsl_rpmsg.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index d7f30036d434..a688c3c2efbc 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -115,6 +115,13 @@ config SND_SOC_FSL_AUD2HTX
 config SND_SOC_FSL_UTILS
tristate
 
+config SND_SOC_FSL_RPMSG
+   tristate "Audio Base on RPMSG support"
+   help
+ Say Y if you want to add rpmsg audio support for the Freescale CPUs.
+ This option is only useful for out-of-tree drivers since
+ in-tree drivers select it automatically.
+
 config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 8c5fa8a859c0..b63802f345cc 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -27,6 +27,7 @@ snd-soc-fsl-mqs-objs := fsl_mqs.o
 snd-soc-fsl-easrc-objs := fsl_easrc.o
 snd-soc-fsl-xcvr-objs := fsl_xcvr.o
 snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o
+snd-soc-fsl-rpmsg-objs := fsl_rpmsg.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
@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_SOC_FSL_EASRC) += snd-soc-fsl-easrc.o
 obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
 obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o
 obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o
+obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o
 
 # MPC5200 Platform Support
 obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c
new file mode 100644
index ..1082a3b3a18d
--- /dev/null
+++ b/sound/soc/fsl/fsl_rpmsg.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2018-2021 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "fsl_rpmsg.h"
+#include "imx-pcm.h"
+
+#define FSL_RPMSG_RATES(SNDRV_PCM_RATE_8000 | \
+   SNDRV_PCM_RATE_16000 | \
+   SNDRV_PCM_RATE_48000)
+#define FSL_RPMSG_FORMATS  SNDRV_PCM_FMTBIT_S16_LE
+
+static const unsigned int fsl_rpmsg_rates[] = {
+   8000, 11025, 16000, 22050, 44100,
+   32000, 48000, 96000, 88200, 176400, 192000,
+   352800, 384000, 705600, 768000, 1411200, 2822400,
+};
+
+static const struct snd_pcm_hw_constraint_list fsl_rpmsg_rate_constraints = {
+   .count = ARRAY_SIZE(fsl_rpmsg_rates),
+   .list = fsl_rpmsg_rates,
+};
+
+static int fsl_rpmsg_hw_params(struct snd_pcm_substream *substream,
+  struct snd_pcm_hw_params *params,
+  struct snd_soc_dai *dai)
+{
+   struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai);
+   struct clk *p = rpmsg->mclk, *pll = 0, *npll = 0;
+   unsigned int rate = params_rate(params);
+   int ret = 0;
+
+   /* Get current pll parent */
+   while (p && rpmsg->pll8k && rpmsg->pll11k) {
+   struct clk *pp = clk_get_parent(p);
+
+   if (clk_is_match(pp, rpmsg->pll8k) ||
+   clk_is_match(pp, rpmsg->pll11k)) {
+   pll = pp;
+   break;
+   }
+   p = pp;
+   }
+
+   /* Switch to another pll parent if needed. */
+   if (pll) {
+   npll = (do_div(rate, 8000) ? rpmsg->pll11k : rpmsg->pll8k);
+   if (!clk_is_match(pll, npll)) {
+   ret = clk_set_parent(p, npll);
+   if (ret < 0)
+   dev_warn(dai->dev, "failed to set parent %s: 
%d\n",
+__clk_get_name(npll), ret);
+   }
+   }
+
+   if (!(rpmsg->mclk_streams & BIT(substream->stream))) {
+   ret = clk_prepare_enable(rpmsg->mclk);
+   if (ret) {
+   dev_err(dai->dev, "failed to enable mclk: %d\n", ret);
+   return ret;
+   }
+
+   rpmsg->mclk_streams |= BIT(substream->stream);
+   }
+
+   return ret;
+}
+
+static int fsl_rpmsg_hw_free(struct snd_pcm_substream *substream,
+struct snd_soc_dai *dai)
+{
+   struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(da

[PATCH 2/2] ASoC: ak5558: Add MODULE_DEVICE_TABLE

2021-02-23 Thread Shengjiu Wang
Add missed MODULE_DEVICE_TABLE for the driver can be loaded
automatically at boot.

Fixes: 920884777480 ("ASoC: ak5558: Add support for AK5558 ADC driver")
Cc: 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/codecs/ak5558.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c
index 8a32b0139cb0..85bdd0534180 100644
--- a/sound/soc/codecs/ak5558.c
+++ b/sound/soc/codecs/ak5558.c
@@ -419,6 +419,7 @@ static const struct of_device_id ak5558_i2c_dt_ids[] 
__maybe_unused = {
{ .compatible = "asahi-kasei,ak5558"},
{ }
 };
+MODULE_DEVICE_TABLE(of, ak5558_i2c_dt_ids);
 
 static struct i2c_driver ak5558_i2c_driver = {
.driver = {
-- 
2.27.0



[PATCH 1/2] ASoC: ak4458: Add MODULE_DEVICE_TABLE

2021-02-23 Thread Shengjiu Wang
Add missed MODULE_DEVICE_TABLE for the driver can be loaded
automatically at boot.

Fixes: 08660086eff9 ("ASoC: ak4458: Add support for AK4458 DAC driver")
Cc: 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/codecs/ak4458.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c
index 472caad17012..85a1d00894a9 100644
--- a/sound/soc/codecs/ak4458.c
+++ b/sound/soc/codecs/ak4458.c
@@ -812,6 +812,7 @@ static const struct of_device_id ak4458_of_match[] = {
{ .compatible = "asahi-kasei,ak4497", .data = _drvdata},
{ },
 };
+MODULE_DEVICE_TABLE(of, ak4458_of_match);
 
 static struct i2c_driver ak4458_i2c_driver = {
.driver = {
-- 
2.27.0



[PATCH] ASoC: fsl_xcvr: move reset assert into runtime_resume

2021-02-22 Thread Shengjiu Wang
From: Viorel Suman 

Move reset assert into runtime_resume since we
cannot rely on reset assert state when the device
is put out from suspend.

Signed-off-by: Viorel Suman 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_xcvr.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
index dd228b421e2c..4857e0df8681 100644
--- a/sound/soc/fsl/fsl_xcvr.c
+++ b/sound/soc/fsl/fsl_xcvr.c
@@ -1243,10 +1243,6 @@ static __maybe_unused int 
fsl_xcvr_runtime_suspend(struct device *dev)
if (ret < 0)
dev_err(dev, "Failed to assert M0+ core: %d\n", ret);
 
-   ret = reset_control_assert(xcvr->reset);
-   if (ret < 0)
-   dev_err(dev, "Failed to assert M0+ reset: %d\n", ret);
-
regcache_cache_only(xcvr->regmap, true);
 
clk_disable_unprepare(xcvr->spba_clk);
@@ -1262,6 +1258,12 @@ static __maybe_unused int fsl_xcvr_runtime_resume(struct 
device *dev)
struct fsl_xcvr *xcvr = dev_get_drvdata(dev);
int ret;
 
+   ret = reset_control_assert(xcvr->reset);
+   if (ret < 0) {
+   dev_err(dev, "Failed to assert M0+ reset: %d\n", ret);
+   return ret;
+   }
+
ret = clk_prepare_enable(xcvr->ipg_clk);
if (ret) {
dev_err(dev, "failed to start IPG clock.\n");
-- 
2.27.0



[PATCH] ASoC: fsl_sai: Add pm qos cpu latency support

2021-02-22 Thread Shengjiu Wang
On SoCs such as i.MX7ULP, cpuidle has some levels which
may disable system/bus clocks, so need to add pm_qos to
prevent cpuidle from entering low level idles and make sure
system/bus clocks are enabled when sai is active.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_sai.c | 12 
 sound/soc/fsl/fsl_sai.h |  4 
 2 files changed, 16 insertions(+)

diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 5e65b456d3e2..a22679dea578 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1177,6 +1178,7 @@ static const struct fsl_sai_soc_data fsl_sai_vf610_data = 
{
.fifo_depth = 32,
.reg_offset = 0,
.mclk0_is_mclk1 = false,
+   .flags = 0,
 };
 
 static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
@@ -1185,6 +1187,7 @@ static const struct fsl_sai_soc_data fsl_sai_imx6sx_data 
= {
.fifo_depth = 32,
.reg_offset = 0,
.mclk0_is_mclk1 = true,
+   .flags = 0,
 };
 
 static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = {
@@ -1193,6 +1196,7 @@ static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data 
= {
.fifo_depth = 16,
.reg_offset = 8,
.mclk0_is_mclk1 = false,
+   .flags = PMQOS_CPU_LATENCY,
 };
 
 static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = {
@@ -1201,6 +1205,7 @@ static const struct fsl_sai_soc_data fsl_sai_imx8mq_data 
= {
.fifo_depth = 128,
.reg_offset = 8,
.mclk0_is_mclk1 = false,
+   .flags = 0,
 };
 
 static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = {
@@ -1209,6 +1214,7 @@ static const struct fsl_sai_soc_data fsl_sai_imx8qm_data 
= {
.fifo_depth = 64,
.reg_offset = 0,
.mclk0_is_mclk1 = false,
+   .flags = 0,
 };
 
 static const struct of_device_id fsl_sai_ids[] = {
@@ -1235,6 +1241,9 @@ static int fsl_sai_runtime_suspend(struct device *dev)
 
clk_disable_unprepare(sai->bus_clk);
 
+   if (sai->soc_data->flags & PMQOS_CPU_LATENCY)
+   cpu_latency_qos_remove_request(>pm_qos_req);
+
regcache_cache_only(sai->regmap, true);
 
return 0;
@@ -1264,6 +1273,9 @@ static int fsl_sai_runtime_resume(struct device *dev)
goto disable_tx_clk;
}
 
+   if (sai->soc_data->flags & PMQOS_CPU_LATENCY)
+   cpu_latency_qos_add_request(>pm_qos_req, 0);
+
regcache_cache_only(sai->regmap, false);
regcache_mark_dirty(sai->regmap);
regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index ff2619f1b214..bc60030967dd 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -216,12 +216,15 @@
 #define FSL_SAI_MAXBURST_TX 6
 #define FSL_SAI_MAXBURST_RX 6
 
+#define PMQOS_CPU_LATENCY   BIT(0)
+
 struct fsl_sai_soc_data {
bool use_imx_pcm;
bool use_edma;
bool mclk0_is_mclk1;
unsigned int fifo_depth;
unsigned int reg_offset;
+   unsigned int flags;
 };
 
 /**
@@ -273,6 +276,7 @@ struct fsl_sai {
struct snd_dmaengine_dai_dma_data dma_params_tx;
struct fsl_sai_verid verid;
struct fsl_sai_param param;
+   struct pm_qos_request pm_qos_req;
 };
 
 #define TX 1
-- 
2.27.0



Re: [PATCH v2 2/7] ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg

2021-02-18 Thread Shengjiu Wang
On Wed, Feb 10, 2021 at 11:39 PM Mark Brown  wrote:
>
> On Wed, Feb 10, 2021 at 02:35:29PM +0800, Shengjiu Wang wrote:
> > On Wed, Feb 10, 2021 at 6:30 AM Mark Brown  wrote:
>
> > > Like I say I'd actually recommend moving this control to DAPM.
>
> > I may understand your point, you suggest to use the .set_bias_level
> > interface. But in my case I need to enable the clock in earlier stage
> > and keep the clock on when system go to suspend.
>
> The device can be kept alive over system suspend if that's needed, or
> possibly it sounds like runtime PM is a better fit?  There's callbacks
> in the core to keep the device runtime PM enabled while it's open which
> is probably about the time range you're looking for.

Before enabling the clock, I need to reparent the clock according to
the sample rate,  Maybe the hw_params is the right place to do
these things.

Can I add a flag:
"rpmsg->mclk_streams & BIT(substream->stream)"
for avoiding multiple calls of hw_params function before enabling
clock?


Re: [PATCH v2 7/7] ASoC: dt-bindings: imx-rpmsg: Add binding doc for rpmsg machine driver

2021-02-18 Thread Shengjiu Wang
On Thu, Feb 11, 2021 at 6:18 AM Rob Herring  wrote:
>
> On Sun, Feb 07, 2021 at 06:23:55PM +0800, Shengjiu Wang wrote:
> > Imx-rpmsg is a new added machine driver for supporting audio on Cortex-M
> > core. The Cortex-M core will control the audio interface, DMA and audio
> > codec, setup the pipeline, the audio driver on Cortex-A core side is just
> > to communitcate with M core, it is a virtual sound card and don't touch
> > the hardware.
>
> I don't understand why there are 2 nodes for this other than you happen
> to want to split this into 2 Linux drivers. It's 1 h/w thing.

This one is for the sound card machine driver.  Another one is
for the sound card cpu dai driver. so there are 2 nodes.

>
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
> >  .../bindings/sound/imx-audio-rpmsg.yaml   | 48 +++
> >  1 file changed, 48 insertions(+)
> >  create mode 100644 
> > Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml 
> > b/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
> > new file mode 100644
> > index ..b941aeb80678
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
> > @@ -0,0 +1,48 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/imx-audio-rpmsg.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: NXP i.MX audio complex with rpmsg
> > +
> > +maintainers:
> > +  - Shengjiu Wang 
> > +
> > +properties:
> > +  compatible:
> > +enum:
> > +  - fsl,imx-audio-rpmsg
> > +
> > +  model:
> > +$ref: /schemas/types.yaml#/definitions/string
> > +description: User specified audio sound card name
> > +
> > +  audio-cpu:
> > +description: The phandle of an CPU DAI controller
> > +
> > +  rpmsg-out:
> > +description: |
> > +  This is a boolean property. If present, the transmitting function
> > +  will be enabled,
> > +
> > +  rpmsg-in:
> > +description: |
> > +  This is a boolean property. If present, the receiving function
> > +  will be enabled.
> > +
> > +required:
> > +  - compatible
> > +  - model
> > +  - audio-cpu
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +sound-rpmsg {
> > +compatible = "fsl,imx-audio-rpmsg";
> > +model = "ak4497-audio";
> > +audio-cpu = <_audio>;
> > +rpmsg-out;
> > +};
> > --
> > 2.27.0
> >


Re: [PATCH v2 3/7] ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver

2021-02-18 Thread Shengjiu Wang
On Thu, Feb 11, 2021 at 6:13 AM Rob Herring  wrote:
>
> On Sun, Feb 07, 2021 at 06:23:51PM +0800, Shengjiu Wang wrote:
> > fsl_rpmsg cpu dai driver is driver for rpmsg audio, which is mainly used
> > for getting the user's configuration from device tree and configure the
> > clocks which is used by Cortex-M core. So in this document define the
> > needed property.
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
> >  .../devicetree/bindings/sound/fsl,rpmsg.yaml  | 80 +++
> >  1 file changed, 80 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml 
> > b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
> > new file mode 100644
> > index ..2d3ce10d42fc
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
> > @@ -0,0 +1,80 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/fsl,rpmsg.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: NXP Audio RPMSG CPU DAI Controller
> > +
> > +maintainers:
> > +  - Shengjiu Wang 
> > +
> > +properties:
> > +  compatible:
> > +enum:
> > +  - fsl,imx7ulp-rpmsg
> > +  - fsl,imx8mn-rpmsg
> > +  - fsl,imx8mm-rpmsg
> > +  - fsl,imx8mp-rpmsg
>
> rpmsg is a protocol. What's the h/w block?

On Linux side this driver is a virtual driver, it is running
on Arm Cortex-A core. The h/w block is controlled by
another core (cortex-M core). so this driver actually
doesn't touch any hardware, it just does configuration
for rpmsg channel.

>
> > +
> > +  clocks:
> > +items:
> > +  - description: Peripheral clock for register access
> > +  - description: Master clock
> > +  - description: DMA clock for DMA register access
> > +  - description: Parent clock for multiple of 8kHz sample rates
> > +  - description: Parent clock for multiple of 11kHz sample rates
> > +minItems: 5
> > +
> > +  clock-names:
> > +items:
> > +  - const: ipg
> > +  - const: mclk
> > +  - const: dma
> > +  - const: pll8k
> > +  - const: pll11k
> > +minItems: 5
> > +
> > +  power-domains:
> > +maxItems: 1
> > +
> > +  fsl,audioindex:
> > +$ref: /schemas/types.yaml#/definitions/uint32
> > +description: instance index for rpmsg image
> > +
> > +  fsl,version:
> > +$ref: /schemas/types.yaml#/definitions/uint32
> > +description: rpmsg image version index
>
> What are these 2 used for?

fsl,audioindex: As we may support multiple instance, for example
two sound card with one rpmsg channel, this is the instance index.

fsl,version: There are maybe different image running on M core, this
is the image version, different image has different function.


>
> > +
> > +  fsl,buffer-size:
> > +$ref: /schemas/types.yaml#/definitions/uint32
> > +description: pre allocate dma buffer size
> > +
> > +  fsl,enable-lpa:
> > +$ref: /schemas/types.yaml#/definitions/flag
> > +description: enable low power audio path.
> > +
> > +  fsl,codec-type:
> > +$ref: /schemas/types.yaml#/definitions/uint32
> > +description: Sometimes the codec is registered by
> > + driver not the device tree, this items
> > + can be used to distinguish codecs
>
> 0-2^32 are valid values?

I should add range for it.

>
> > +
> > +required:
> > +  - compatible
> > +  - fsl,audioindex
> > +  - fsl,version
> > +  - fsl,buffer-size
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +rpmsg_audio: rpmsg_audio {
> > +compatible = "fsl,imx8mn-rpmsg";
> > +fsl,audioindex = <0> ;
> > +fsl,version = <2>;
> > +fsl,buffer-size = <0x600>;
> > +fsl,enable-lpa;
> > +status = "okay";
>
> Don't show status in examples.

ok, will remove it.

>
> > +};
> > --
> > 2.27.0
> >


Re: [PATCH v2 2/7] ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg

2021-02-09 Thread Shengjiu Wang
On Wed, Feb 10, 2021 at 6:30 AM Mark Brown  wrote:
>
> On Tue, Feb 09, 2021 at 05:16:16PM +0800, Shengjiu Wang wrote:
> > On Mon, Feb 8, 2021 at 7:53 PM Mark Brown  wrote:
>
> > > hw_params() can be called multiple times and there's no need for it to
> > > be balanced with hw_free(), I'd move this to a different callback (DAPM
> > > should work well).
>
> > Which callback should I use? Is there an example?
>
> Like I say I'd actually recommend moving this control to DAPM.

I may understand your point, you suggest to use the .set_bias_level
interface. But in my case I need to enable the clock in earlier stage
and keep the clock on when system go to suspend.

I am not sure .set_bias_level can met my requirement. we start
the Chinese new year holiday now, so currently I can't do test for this
recommendation.

Maybe we can keep current implementation, can we?
Later after I do the test, I can submit another patch for it.

Best regards
Wang Shengjiu


Re: [PATCH v2 2/7] ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg

2021-02-09 Thread Shengjiu Wang
On Mon, Feb 8, 2021 at 7:53 PM Mark Brown  wrote:
>
> On Sun, Feb 07, 2021 at 06:23:50PM +0800, Shengjiu Wang wrote:
>
> > +static int fsl_rpmsg_hw_params(struct snd_pcm_substream *substream,
> > +struct snd_pcm_hw_params *params,
> > +struct snd_soc_dai *dai)
> > +{
>
> ...
>
> > + ret = clk_prepare_enable(rpmsg->mclk);
> > + if (ret)
> > + dev_err(dai->dev, "failed to enable mclk: %d\n", ret);
> > +
> > + return ret;
> > +}
> > +
> > +static int fsl_rpmsg_hw_free(struct snd_pcm_substream *substream,
> > +  struct snd_soc_dai *dai)
> > +{
> > + struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai);
> > +
> > + clk_disable_unprepare(rpmsg->mclk);
>
> hw_params() can be called multiple times and there's no need for it to
> be balanced with hw_free(), I'd move this to a different callback (DAPM
> should work well).

Which callback should I use? Is there an example?

best regards
wang shengjiu


Re: [PATCH] ASoC: soc-pcm: change error message to debug message

2021-02-08 Thread Shengjiu Wang
On Tue, Feb 9, 2021 at 12:39 AM Pierre-Louis Bossart
 wrote:
>
>
>
> On 2/8/21 2:12 AM, Shengjiu Wang wrote:
> > This log message should be a debug message, because it
> > doesn't return directly but continue next loop.
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
> >   sound/soc/soc-pcm.c | 4 ++--
> >   1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
> > index 605acec48971..cd9e919d7b99 100644
> > --- a/sound/soc/soc-pcm.c
> > +++ b/sound/soc/soc-pcm.c
> > @@ -1344,8 +1344,8 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime 
> > *fe, int stream,
> >   /* is there a valid BE rtd for this widget */
> >   be = dpcm_get_be(card, widget, stream);
> >   if (!be) {
> > - dev_err(fe->dev, "ASoC: no BE found for %s\n",
> > - widget->name);
> > + dev_dbg(fe->dev, "ASoC: no BE found for %s\n",
> > + widget->name);
>
> Do we really want to do this?
>
> This error message has historically been the means by which we detect
> that userspace didn't set the right mixers (e.g. on Intel Baytrail) or
> the topology was incorrect. And it's really an error in the sense that
> you will not get audio in or out.
>
> If you demote this to dev_dbg, we'll have to ask every single user who
> reports 'sound is broken' to enable dynamic debug traces. I really don't
> see the benefit, this is a clear case of 'fail big and fail early',
> partly concealing the problem doesn't make it go away but harder to
> diagnose.

Thanks for the explanation,  it seems I misunderstood this error message.

Best regards
Wang shengjiu


[PATCH] ASoC: soc-pcm: change error message to debug message

2021-02-08 Thread Shengjiu Wang
This log message should be a debug message, because it
doesn't return directly but continue next loop.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/soc-pcm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 605acec48971..cd9e919d7b99 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1344,8 +1344,8 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, 
int stream,
/* is there a valid BE rtd for this widget */
be = dpcm_get_be(card, widget, stream);
if (!be) {
-   dev_err(fe->dev, "ASoC: no BE found for %s\n",
-   widget->name);
+   dev_dbg(fe->dev, "ASoC: no BE found for %s\n",
+   widget->name);
continue;
}
 
-- 
2.27.0



[PATCH v2 5/7] ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg

2021-02-07 Thread Shengjiu Wang
platform driver base on rpmsg is the interface for sending and
receiving rpmsg to and from M core. It will tell the Cortex-M core
sound format/rate/channel, where is the data buffer, where is
the period size, when to start, when to stop and when suspend
or resume happen, each this behavior there is defined rpmsg
command.

Especially we designed the low power audio case, that is to
allocate a large buffer and fill the data, then Cortex-A core can go
to sleep mode, Cortex-M core continue to play the sound, when the
buffer is consumed, Cortex-M core will trigger the Cortex-A core to
wakeup.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |   5 +
 sound/soc/fsl/Makefile|   1 +
 sound/soc/fsl/imx-pcm-rpmsg.c | 919 ++
 sound/soc/fsl/imx-pcm-rpmsg.h | 512 +++
 4 files changed, 1437 insertions(+)
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 84d9f0f1f75b..749c44fc0759 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -130,6 +130,11 @@ config SND_SOC_IMX_AUDIO_RPMSG
tristate
depends on RPMSG
 
+config SND_SOC_IMX_PCM_RPMSG
+   tristate
+   depends on SND_SOC_IMX_AUDIO_RPMSG
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+
 config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index f08f3cd07ff5..ce4f4324c3a2 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
 obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
+obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
new file mode 100644
index ..f05d5d489560
--- /dev/null
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -0,0 +1,919 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2021 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "imx-pcm.h"
+#include "fsl_rpmsg.h"
+#include "imx-pcm-rpmsg.h"
+
+static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
+   .info = SNDRV_PCM_INFO_INTERLEAVED |
+   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+   SNDRV_PCM_INFO_MMAP |
+   SNDRV_PCM_INFO_MMAP_VALID |
+   SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
+   SNDRV_PCM_INFO_PAUSE |
+   SNDRV_PCM_INFO_RESUME,
+   .buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE,
+   .period_bytes_min = 512,
+   .period_bytes_max = 65536,
+   .periods_min = 2,
+   .periods_max = 6000,
+   .fifo_size = 0,
+};
+
+static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
+ struct rpmsg_info *info)
+{
+   struct rpmsg_device *rpdev = info->rpdev;
+   int ret = 0;
+
+   mutex_lock(>msg_lock);
+   if (!rpdev) {
+   dev_err(info->dev, "rpmsg channel not ready\n");
+   mutex_unlock(>msg_lock);
+   return -EINVAL;
+   }
+
+   dev_dbg(>dev, "send cmd %d\n", msg->s_msg.header.cmd);
+
+   if (!(msg->s_msg.header.type == MSG_TYPE_C))
+   reinit_completion(>cmd_complete);
+
+   ret = rpmsg_send(rpdev->ept, (void *)>s_msg,
+sizeof(struct rpmsg_s_msg));
+   if (ret) {
+   dev_err(>dev, "rpmsg_send failed: %d\n", ret);
+   mutex_unlock(>msg_lock);
+   return ret;
+   }
+
+   /* No receive msg for TYPE_C command */
+   if (msg->s_msg.header.type == MSG_TYPE_C) {
+   mutex_unlock(>msg_lock);
+   return 0;
+   }
+
+   /* wait response from rpmsg */
+   ret = wait_for_completion_timeout(>cmd_complete,
+ msecs_to_jiffies(RPMSG_TIMEOUT));
+   if (!ret) {
+   dev_err(>dev, "rpmsg_send cmd %d timeout!\n",
+   msg->s_msg.header.cmd);
+   mutex_unlock(>msg_lock);
+   return -ETIMEDOUT;
+   }
+
+   memcpy(>r_msg, >r_msg, sizeof(struct rpmsg_r_msg));
+   memcpy(>msg[msg->r_msg.header.cmd].r_msg,
+  >r_msg, sizeof(struct rpmsg_r_msg));
+
+   /*
+* Reset the buffer pointer to be zero, actully we have
+* set the buffer pointer to be zero in imx_rpmsg_terminate_all
+* But if there is timer task queued in queue, after it is
+* executed the buffer pointer will be

Re: [PATCH] ASoC: fsl: constify static snd_soc_dai_ops structs

2021-02-07 Thread Shengjiu Wang
On Sun, Feb 7, 2021 at 6:58 AM Rikard Falkeborn
 wrote:
>
> The only usage of these is to assign their address to the 'ops' field in
> the snd_soc_dai_driver struct, which is a pointer to const. Make them
> const to allow the compiler to put them in read-only memory.
>
> Signed-off-by: Rikard Falkeborn 

Acked-by: Shengjiu Wang 


[PATCH v2 7/7] ASoC: dt-bindings: imx-rpmsg: Add binding doc for rpmsg machine driver

2021-02-07 Thread Shengjiu Wang
Imx-rpmsg is a new added machine driver for supporting audio on Cortex-M
core. The Cortex-M core will control the audio interface, DMA and audio
codec, setup the pipeline, the audio driver on Cortex-A core side is just
to communitcate with M core, it is a virtual sound card and don't touch
the hardware.

Signed-off-by: Shengjiu Wang 
---
 .../bindings/sound/imx-audio-rpmsg.yaml   | 48 +++
 1 file changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml

diff --git a/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml 
b/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
new file mode 100644
index ..b941aeb80678
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/imx-audio-rpmsg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX audio complex with rpmsg
+
+maintainers:
+  - Shengjiu Wang 
+
+properties:
+  compatible:
+enum:
+  - fsl,imx-audio-rpmsg
+
+  model:
+$ref: /schemas/types.yaml#/definitions/string
+description: User specified audio sound card name
+
+  audio-cpu:
+description: The phandle of an CPU DAI controller
+
+  rpmsg-out:
+description: |
+  This is a boolean property. If present, the transmitting function
+  will be enabled,
+
+  rpmsg-in:
+description: |
+  This is a boolean property. If present, the receiving function
+  will be enabled.
+
+required:
+  - compatible
+  - model
+  - audio-cpu
+
+additionalProperties: false
+
+examples:
+  - |
+sound-rpmsg {
+compatible = "fsl,imx-audio-rpmsg";
+model = "ak4497-audio";
+audio-cpu = <_audio>;
+rpmsg-out;
+};
-- 
2.27.0



[PATCH v2 4/7] ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel

2021-02-07 Thread Shengjiu Wang
This driver is used to accept the message from rpmsg audio
channel, and if this driver is probed, it will help to register
the platform driver, the platform driver will use this
audio channel to send and receive message to and from Cortex-M
core.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig   |   4 +
 sound/soc/fsl/Makefile  |   1 +
 sound/soc/fsl/imx-audio-rpmsg.c | 151 
 3 files changed, 156 insertions(+)
 create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index a688c3c2efbc..84d9f0f1f75b 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -126,6 +126,10 @@ config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
 
+config SND_SOC_IMX_AUDIO_RPMSG
+   tristate
+   depends on RPMSG
+
 config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index b63802f345cc..f08f3cd07ff5 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 
 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
+obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c
new file mode 100644
index ..145edb1492b4
--- /dev/null
+++ b/sound/soc/fsl/imx-audio-rpmsg.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2020 NXP
+
+#include 
+#include 
+#include "imx-pcm-rpmsg.h"
+
+/*
+ * struct imx_audio_rpmsg: private data
+ *
+ * @rpmsg_pdev: pointer of platform device
+ */
+struct imx_audio_rpmsg {
+   struct platform_device *rpmsg_pdev;
+};
+
+static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
+ void *priv, u32 src)
+{
+   struct imx_audio_rpmsg *rpmsg = dev_get_drvdata(>dev);
+   struct rpmsg_info *info = platform_get_drvdata(rpmsg->rpmsg_pdev);
+   struct rpmsg_r_msg *r_msg = (struct rpmsg_r_msg *)data;
+   struct rpmsg_msg *msg;
+   unsigned long flags;
+
+   dev_dbg(>dev, "get from%d: cmd:%d. %d\n",
+   src, r_msg->header.cmd, r_msg->param.resp);
+
+   switch (r_msg->header.type) {
+   case MSG_TYPE_C:
+   /* TYPE C is notification from M core */
+   switch (r_msg->header.cmd) {
+   case TX_PERIOD_DONE:
+   spin_lock_irqsave(>lock[TX], flags);
+   msg = >msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
+
+   /*
+* Low power mode: get the buffer pointer from
+* receive msg.
+*/
+   if (r_msg->header.major == 1 &&
+   r_msg->header.minor == 2)
+   msg->r_msg.param.buffer_tail =
+   r_msg->param.buffer_tail;
+   else
+   msg->r_msg.param.buffer_tail++;
+
+   msg->r_msg.param.buffer_tail %= info->num_period[TX];
+   spin_unlock_irqrestore(>lock[TX], flags);
+   info->callback[TX](info->callback_param[TX]);
+   break;
+   case RX_PERIOD_DONE:
+   spin_lock_irqsave(>lock[RX], flags);
+   msg = >msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
+
+   if (r_msg->header.major == 1 &&
+   r_msg->header.minor == 2)
+   msg->r_msg.param.buffer_tail =
+   r_msg->param.buffer_tail;
+   else
+   msg->r_msg.param.buffer_tail++;
+
+   msg->r_msg.param.buffer_tail %= info->num_period[1];
+   spin_unlock_irqrestore(>lock[RX], flags);
+   info->callback[RX](info->callback_param[RX]);
+   break;
+   default:
+   dev_warn(>dev, "unknown msg command\n");
+   break;
+   }
+   break;
+   case MSG_TYPE_B:
+   /* TYPE B is response msg */
+   memcpy(>r_msg, r_msg, sizeof(struct rpmsg_r_msg));
+   complete(>cmd_complete);
+   break;
+   default:
+   dev_warn(>dev, "unknown msg type\n");
+   break;
+   }
+
+   return 0;
+}
+
+static int imx_audio_rpmsg_probe(struct rpmsg_de

[PATCH v2 6/7] ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg

2021-02-07 Thread Shengjiu Wang
The platform device is not registered by device tree or
cpu dai driver, it is registered by the rpmsg channel,
So add a dedicated machine driver to handle this case.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |  12 
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/imx-rpmsg.c | 148 ++
 3 files changed, 162 insertions(+)
 create mode 100644 sound/soc/fsl/imx-rpmsg.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 749c44fc0759..3557866d3fa2 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -334,6 +334,18 @@ config SND_SOC_IMX_HDMI
  Say Y if you want to add support for SoC audio on an i.MX board with
  IMX HDMI.
 
+config SND_SOC_IMX_RPMSG
+   tristate "SoC Audio support for i.MX boards with rpmsg"
+   depends on RPMSG
+   select SND_SOC_IMX_PCM_RPMSG
+   select SND_SOC_IMX_AUDIO_RPMSG
+   select SND_SOC_FSL_RPMSG
+   help
+ SoC Audio support for i.MX boards with rpmsg.
+ There should be rpmsg devices defined in other core (M core)
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a rpmsg devices.
+
 endif # SND_IMX_SOC
 
 endmenu
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index ce4f4324c3a2..f146ce464acd 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -70,6 +70,7 @@ snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
 snd-soc-imx-spdif-objs := imx-spdif.o
 snd-soc-imx-audmix-objs := imx-audmix.o
 snd-soc-imx-hdmi-objs := imx-hdmi.o
+snd-soc-imx-rpmsg-objs := imx-rpmsg.o
 
 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
 obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o
@@ -77,3 +78,4 @@ 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_AUDMIX) += snd-soc-imx-audmix.o
 obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o
+obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o
diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c
new file mode 100644
index ..a87dcbce4f36
--- /dev/null
+++ b/sound/soc/fsl/imx-rpmsg.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2020 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "imx-pcm-rpmsg.h"
+
+struct imx_rpmsg {
+   struct snd_soc_dai_link dai;
+   struct snd_soc_card card;
+};
+
+static int imx_rpmsg_probe(struct platform_device *pdev)
+{
+   struct snd_soc_dai_link_component *dlc;
+   struct platform_device *cpu_pdev;
+   struct of_phandle_args args;
+   struct device_node *cpu_np;
+   struct imx_rpmsg *data;
+   int ret;
+
+   dlc = devm_kzalloc(>dev, 3 * sizeof(*dlc), GFP_KERNEL);
+   if (!dlc)
+   return -ENOMEM;
+
+   cpu_np = of_parse_phandle(pdev->dev.of_node, "audio-cpu", 0);
+   if (!cpu_np) {
+   dev_err(>dev, "cpu dai phandle missing or invalid\n");
+   ret = -EINVAL;
+   goto fail;
+   }
+
+   data = devm_kzalloc(>dev, sizeof(*data), GFP_KERNEL);
+   if (!data) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+
+   cpu_pdev = of_find_device_by_node(cpu_np);
+   if (!cpu_pdev) {
+   dev_err(>dev, "failed to find rpmsg platform device\n");
+   ret = -EINVAL;
+   goto fail;
+   }
+
+   ret = of_reserved_mem_device_init_by_idx(>dev, pdev->dev.of_node, 
0);
+   if (ret)
+   dev_warn(>dev, "no reserved DMA memory\n");
+
+   data->dai.cpus = [0];
+   data->dai.num_cpus = 1;
+   data->dai.platforms = [1];
+   data->dai.num_platforms = 1;
+   data->dai.codecs = [2];
+   data->dai.num_codecs = 1;
+
+   data->dai.name = "rpmsg hifi";
+   data->dai.stream_name = "rpmsg hifi";
+   data->dai.dai_fmt = SND_SOC_DAIFMT_I2S |
+   SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS;
+
+   /* Optional codec node */
+   ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
+  "audio-codec", 0, 0, );
+   if (ret) {
+   data->dai.codecs->dai_name = "snd-soc-dummy-dai";
+   data->dai.codecs->name = "snd-soc-dummy";
+   } else {
+   data->dai.codecs->of_node = args.np;
+   ret = snd_soc_get_dai_name(, >dai.codecs->dai_name);
+   if (ret) {
+   dev_err(>dev, "Unable to get codec_dai_name\n");
+   goto fail;
+   }
+   }
+
+   data->dai.

[PATCH v2 1/7] ASoC: soc-component: Add snd_soc_pcm_component_ack

2021-02-07 Thread Shengjiu Wang
Add snd_soc_pcm_component_ack back, which can be used to get updated
buffer pointer in platform driver.
On Asymmetric multiprocessor, this pointer can be sent to Cortex-M
core for audio processing.

Signed-off-by: Shengjiu Wang 
---
 include/sound/soc-component.h |  3 +++
 sound/soc/soc-component.c | 14 ++
 sound/soc/soc-pcm.c   |  2 ++
 3 files changed, 19 insertions(+)

diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 5b47768222b7..2dc8c7e3d1a6 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -146,6 +146,8 @@ struct snd_soc_component_driver {
int (*mmap)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
+   int (*ack)(struct snd_soc_component *component,
+  struct snd_pcm_substream *substream);
 
const struct snd_compress_ops *compress_ops;
 
@@ -498,5 +500,6 @@ int snd_soc_pcm_component_pm_runtime_get(struct 
snd_soc_pcm_runtime *rtd,
 void *stream);
 void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
  void *stream, int rollback);
+int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream);
 
 #endif /* __SOC_COMPONENT_H */
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 159bf88b9f8c..a9fbb2d26412 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -1212,3 +1212,17 @@ void snd_soc_pcm_component_pm_runtime_put(struct 
snd_soc_pcm_runtime *rtd,
soc_component_mark_pop(component, stream, pm);
}
 }
+
+int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+   struct snd_soc_component *component;
+   int i;
+
+   /* FIXME: use 1st pointer */
+   for_each_rtd_components(rtd, i, component)
+   if (component->driver->ack)
+   return component->driver->ack(component, substream);
+
+   return 0;
+}
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index b79f064887d4..605acec48971 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2830,6 +2830,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->ops.page   = snd_soc_pcm_component_page;
if (drv->mmap)
rtd->ops.mmap   = snd_soc_pcm_component_mmap;
+   if (drv->ack)
+   rtd->ops.ack= snd_soc_pcm_component_ack;
}
 
if (playback)
-- 
2.27.0



[PATCH v2 3/7] ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver

2021-02-07 Thread Shengjiu Wang
fsl_rpmsg cpu dai driver is driver for rpmsg audio, which is mainly used
for getting the user's configuration from device tree and configure the
clocks which is used by Cortex-M core. So in this document define the
needed property.

Signed-off-by: Shengjiu Wang 
---
 .../devicetree/bindings/sound/fsl,rpmsg.yaml  | 80 +++
 1 file changed, 80 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml

diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml 
b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
new file mode 100644
index ..2d3ce10d42fc
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/fsl,rpmsg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP Audio RPMSG CPU DAI Controller
+
+maintainers:
+  - Shengjiu Wang 
+
+properties:
+  compatible:
+enum:
+  - fsl,imx7ulp-rpmsg
+  - fsl,imx8mn-rpmsg
+  - fsl,imx8mm-rpmsg
+  - fsl,imx8mp-rpmsg
+
+  clocks:
+items:
+  - description: Peripheral clock for register access
+  - description: Master clock
+  - description: DMA clock for DMA register access
+  - description: Parent clock for multiple of 8kHz sample rates
+  - description: Parent clock for multiple of 11kHz sample rates
+minItems: 5
+
+  clock-names:
+items:
+  - const: ipg
+  - const: mclk
+  - const: dma
+  - const: pll8k
+  - const: pll11k
+minItems: 5
+
+  power-domains:
+maxItems: 1
+
+  fsl,audioindex:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: instance index for rpmsg image
+
+  fsl,version:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: rpmsg image version index
+
+  fsl,buffer-size:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: pre allocate dma buffer size
+
+  fsl,enable-lpa:
+$ref: /schemas/types.yaml#/definitions/flag
+description: enable low power audio path.
+
+  fsl,codec-type:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: Sometimes the codec is registered by
+ driver not the device tree, this items
+ can be used to distinguish codecs
+
+required:
+  - compatible
+  - fsl,audioindex
+  - fsl,version
+  - fsl,buffer-size
+
+additionalProperties: false
+
+examples:
+  - |
+rpmsg_audio: rpmsg_audio {
+compatible = "fsl,imx8mn-rpmsg";
+fsl,audioindex = <0> ;
+fsl,version = <2>;
+fsl,buffer-size = <0x600>;
+fsl,enable-lpa;
+status = "okay";
+};
-- 
2.27.0



[PATCH v2 2/7] ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg

2021-02-07 Thread Shengjiu Wang
This is a cpu dai driver for rpmsg audio use case,
which is mainly used for getting the user's configuration
from devicetree and configure the clocks which is used by
Cortex-M core.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |   7 ++
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/fsl_rpmsg.c | 252 ++
 sound/soc/fsl/fsl_rpmsg.h |  38 ++
 4 files changed, 299 insertions(+)
 create mode 100644 sound/soc/fsl/fsl_rpmsg.c
 create mode 100644 sound/soc/fsl/fsl_rpmsg.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index d7f30036d434..a688c3c2efbc 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -115,6 +115,13 @@ config SND_SOC_FSL_AUD2HTX
 config SND_SOC_FSL_UTILS
tristate
 
+config SND_SOC_FSL_RPMSG
+   tristate "Audio Base on RPMSG support"
+   help
+ Say Y if you want to add rpmsg audio support for the Freescale CPUs.
+ This option is only useful for out-of-tree drivers since
+ in-tree drivers select it automatically.
+
 config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 8c5fa8a859c0..b63802f345cc 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -27,6 +27,7 @@ snd-soc-fsl-mqs-objs := fsl_mqs.o
 snd-soc-fsl-easrc-objs := fsl_easrc.o
 snd-soc-fsl-xcvr-objs := fsl_xcvr.o
 snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o
+snd-soc-fsl-rpmsg-objs := fsl_rpmsg.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
@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_SOC_FSL_EASRC) += snd-soc-fsl-easrc.o
 obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
 obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o
 obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o
+obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o
 
 # MPC5200 Platform Support
 obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c
new file mode 100644
index ..6e218344df0d
--- /dev/null
+++ b/sound/soc/fsl/fsl_rpmsg.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2018-2021 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "fsl_rpmsg.h"
+#include "imx-pcm.h"
+
+#define FSL_RPMSG_RATES(SNDRV_PCM_RATE_8000 | \
+   SNDRV_PCM_RATE_16000 | \
+   SNDRV_PCM_RATE_48000)
+#define FSL_RPMSG_FORMATS  SNDRV_PCM_FMTBIT_S16_LE
+
+static const unsigned int fsl_rpmsg_rates[] = {
+   8000, 11025, 16000, 22050, 44100,
+   32000, 48000, 96000, 88200, 176400, 192000,
+   352800, 384000, 705600, 768000, 1411200, 2822400,
+};
+
+static const struct snd_pcm_hw_constraint_list fsl_rpmsg_rate_constraints = {
+   .count = ARRAY_SIZE(fsl_rpmsg_rates),
+   .list = fsl_rpmsg_rates,
+};
+
+static int fsl_rpmsg_hw_params(struct snd_pcm_substream *substream,
+  struct snd_pcm_hw_params *params,
+  struct snd_soc_dai *dai)
+{
+   struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai);
+   struct clk *p = rpmsg->mclk, *pll = 0, *npll = 0;
+   unsigned int rate = params_rate(params);
+   int ret;
+
+   /* Get current pll parent */
+   while (p && rpmsg->pll8k && rpmsg->pll11k) {
+   struct clk *pp = clk_get_parent(p);
+
+   if (clk_is_match(pp, rpmsg->pll8k) ||
+   clk_is_match(pp, rpmsg->pll11k)) {
+   pll = pp;
+   break;
+   }
+   p = pp;
+   }
+
+   /* Switch to another pll parent if needed. */
+   if (pll) {
+   npll = (do_div(rate, 8000) ? rpmsg->pll11k : rpmsg->pll8k);
+   if (!clk_is_match(pll, npll)) {
+   ret = clk_set_parent(p, npll);
+   if (ret < 0)
+   dev_warn(dai->dev, "failed to set parent %s: 
%d\n",
+__clk_get_name(npll), ret);
+   }
+   }
+
+   ret = clk_prepare_enable(rpmsg->mclk);
+   if (ret)
+   dev_err(dai->dev, "failed to enable mclk: %d\n", ret);
+
+   return ret;
+}
+
+static int fsl_rpmsg_hw_free(struct snd_pcm_substream *substream,
+struct snd_soc_dai *dai)
+{
+   struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai);
+
+   clk_disable_unprepare(rpmsg->mclk);
+
+   return 0;
+}
+
+static int fsl_rpmsg_startup(struct snd_pcm_substream *substream,
+struct snd_soc_dai *cpu_dai)
+{
+   int ret;
+
+   ret = snd_pcm_hw_c

[PATCH v2 0/7] Add audio driver base on rpmsg on i.MX platform

2021-02-07 Thread Shengjiu Wang
On Asymmetric multiprocessor, there is Cortex-A core and Cortex-M core,
Linux is running on A core, RTOS is running on M core.
The audio hardware device can be controlled by Cortex-M device,
So audio playback/capture can be handled by M core.

Rpmsg is the interface for sending and receiving msg to and from M
core, that we can create a virtual sound on Cortex-A core side.

A core will tell the Cortex-M core sound format/rate/channel,
where is the data buffer, what is the period size, when to start,
when to stop and when suspend or resume happen, each of this behavior
there is defined rpmsg command.

Especially we designed the low power audio case, that is to
allocate a large buffer and fill the data, then Cortex-A core can go
to sleep mode, Cortex-M core continue to play the sound, when the
buffer is consumed, Cortex-M core will trigger the Cortex-A core to
wakeup to fill data.

changes in v2:
- update codes and comments according to Mark's comments

Shengjiu Wang (7):
  ASoC: soc-component: Add snd_soc_pcm_component_ack
  ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg
  ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver
  ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel
  ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg
  ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg
  ASoC: dt-bindings: imx-rpmsg: Add binding doc for rpmsg machine driver

 .../devicetree/bindings/sound/fsl,rpmsg.yaml  |  80 ++
 .../bindings/sound/imx-audio-rpmsg.yaml   |  48 +
 include/sound/soc-component.h |   3 +
 sound/soc/fsl/Kconfig |  28 +
 sound/soc/fsl/Makefile|   6 +
 sound/soc/fsl/fsl_rpmsg.c | 252 +
 sound/soc/fsl/fsl_rpmsg.h |  38 +
 sound/soc/fsl/imx-audio-rpmsg.c   | 151 +++
 sound/soc/fsl/imx-pcm-rpmsg.c | 919 ++
 sound/soc/fsl/imx-pcm-rpmsg.h | 512 ++
 sound/soc/fsl/imx-rpmsg.c | 148 +++
 sound/soc/soc-component.c |  14 +
 sound/soc/soc-pcm.c   |   2 +
 13 files changed, 2201 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
 create mode 100644 sound/soc/fsl/fsl_rpmsg.c
 create mode 100644 sound/soc/fsl/fsl_rpmsg.h
 create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h
 create mode 100644 sound/soc/fsl/imx-rpmsg.c

-- 
2.27.0



Re: [PATCH 5/7] ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg

2021-02-07 Thread Shengjiu Wang
On Fri, Feb 5, 2021 at 11:00 PM Mark Brown  wrote:
>
> On Fri, Feb 05, 2021 at 02:57:28PM +0800, Shengjiu Wang wrote:
>
> > + if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE)
> > + msg->s_msg.param.format   = RPMSG_S16_LE;
> > + else if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE)
>
> Again this should be a switch statement.
>
> > + if (params_channels(params) == 1)
> > + msg->s_msg.param.channels = RPMSG_CH_LEFT;
> > + else
> > + msg->s_msg.param.channels = RPMSG_CH_STEREO;
>
> Shouldn't this be reporting an error if the number of channels is more
> than 2?
>
> > + /*
> > +  * if the data in the buffer is less than one period
> > +  * send message immediately.
> > +  * if there is more than one period data, delay one
> > +  * period (timer) to send the message.
> > +  */
> > + if ((avail - writen_num * period_size) <= period_size) {
> > + imx_rpmsg_insert_workqueue(substream, msg, info);
> > + } else if (rpmsg->force_lpa && !timer_pending(timer)) {
> > + int time_msec;
> > +
> > + time_msec = (int)(runtime->period_size * 1000 / 
> > runtime->rate);
> > + mod_timer(timer, jiffies + 
> > msecs_to_jiffies(time_msec));
> > + }
>
> The comment here is at least confusing - why would we not send a full
> buffer immediately if we have one?  This sounds like it's the opposite
> way round to what we'd do if we were trying to cut down the number of
> messages.  It might help to say which buffer and where?
>
> > + /**
> > +  * Every work in the work queue, first we check if there
>
> /** comments are only for kerneldoc.

Thanks Mark, I will update them.

Best regards
wang shengjiu


Re: [PATCH 4/7] ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel

2021-02-07 Thread Shengjiu Wang
On Fri, Feb 5, 2021 at 10:27 PM Mark Brown  wrote:
>
> On Fri, Feb 05, 2021 at 02:57:27PM +0800, Shengjiu Wang wrote:
>
> > + /* TYPE C is notification from M core */
> > + if (r_msg->header.type == MSG_TYPE_C) {
> > + if (r_msg->header.cmd == TX_PERIOD_DONE) {
>
> > + } else if (r_msg->header.cmd == RX_PERIOD_DONE) {
>
> A switch statement would be clearer and more extensible...
>
> > + /* TYPE B is response msg */
> > + if (r_msg->header.type == MSG_TYPE_B) {
> > + memcpy(>r_msg, r_msg, sizeof(struct rpmsg_r_msg));
> > + complete(>cmd_complete);
> > + }
>
> ...and make this flow clearer for example.  Do we need to warn on
> unknown messages?

Thanks for reviewing. I will update them.

Best regards
wang shengjiu


Re: [PATCH 2/7] ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg

2021-02-07 Thread Shengjiu Wang
On Fri, Feb 5, 2021 at 10:04 PM Mark Brown  wrote:
>
> On Fri, Feb 05, 2021 at 02:57:25PM +0800, Shengjiu Wang wrote:
> > This is a dummy cpu dai driver for rpmsg audio use case,
> > which is mainly used for getting the user's configuration
>
> This is actually doing stuff, it's not a dummy driver.
>
> > +static int fsl_rpmsg_remove(struct platform_device *pdev)
> > +{
> > + return 0;
> > +}
>
> If this isn't needed just remove it.

Thanks Mark. I will update them.

Best regards
Wang shengjiu


[RESEND PATH] ASoC: dmaengine_pcm: add peripheral configuration

2021-02-04 Thread Shengjiu Wang
The commit e7bbb7acabf4 ("dmaengine: add peripheral configuration")
adds peripheral configuration for dma_slave_config.

This configuration is useful for some audio peripherals, for
example, the peripheral supports multi fifos, we can
let the DMA know which fifos are selected. So also add
this configuration for snd_dmaengine_dai_dma_data.

Signed-off-by: Shengjiu Wang 
---
 include/sound/dmaengine_pcm.h | 5 +
 sound/core/pcm_dmaengine.c| 2 ++
 2 files changed, 7 insertions(+)

diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index 8c5e38180fb0..9efddb39 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -66,6 +66,9 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct 
snd_pcm_substream *substream)
  * @chan_name: Custom channel name to use when requesting DMA channel.
  * @fifo_size: FIFO size of the DAI controller in bytes
  * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now
+ * @peripheral_config: peripheral configuration for programming peripheral
+ * for dmaengine transfer
+ * @peripheral_size: peripheral configuration buffer size
  */
 struct snd_dmaengine_dai_dma_data {
dma_addr_t addr;
@@ -76,6 +79,8 @@ struct snd_dmaengine_dai_dma_data {
const char *chan_name;
unsigned int fifo_size;
unsigned int flags;
+   void *peripheral_config;
+   size_t peripheral_size;
 };
 
 void snd_dmaengine_pcm_set_config_from_dai_data(
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 4d0e8fe535a1..1fc2fa077574 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -125,6 +125,8 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
}
 
slave_config->slave_id = dma_data->slave_id;
+   slave_config->peripheral_config = dma_data->peripheral_config;
+   slave_config->peripheral_size = dma_data->peripheral_size;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
 
-- 
2.27.0



[PATCH 2/7] ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg

2021-02-04 Thread Shengjiu Wang
This is a dummy cpu dai driver for rpmsg audio use case,
which is mainly used for getting the user's configuration
from devicetree and configure the clocks which is used by
Cortex-M core.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |   7 ++
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/fsl_rpmsg.c | 258 ++
 sound/soc/fsl/fsl_rpmsg.h |  38 ++
 4 files changed, 305 insertions(+)
 create mode 100644 sound/soc/fsl/fsl_rpmsg.c
 create mode 100644 sound/soc/fsl/fsl_rpmsg.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index d7f30036d434..a688c3c2efbc 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -115,6 +115,13 @@ config SND_SOC_FSL_AUD2HTX
 config SND_SOC_FSL_UTILS
tristate
 
+config SND_SOC_FSL_RPMSG
+   tristate "Audio Base on RPMSG support"
+   help
+ Say Y if you want to add rpmsg audio support for the Freescale CPUs.
+ This option is only useful for out-of-tree drivers since
+ in-tree drivers select it automatically.
+
 config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 8c5fa8a859c0..b63802f345cc 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -27,6 +27,7 @@ snd-soc-fsl-mqs-objs := fsl_mqs.o
 snd-soc-fsl-easrc-objs := fsl_easrc.o
 snd-soc-fsl-xcvr-objs := fsl_xcvr.o
 snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o
+snd-soc-fsl-rpmsg-objs := fsl_rpmsg.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
@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_SOC_FSL_EASRC) += snd-soc-fsl-easrc.o
 obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
 obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o
 obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o
+obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o
 
 # MPC5200 Platform Support
 obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c
new file mode 100644
index ..8a5e770ea34b
--- /dev/null
+++ b/sound/soc/fsl/fsl_rpmsg.c
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2018-2021 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "fsl_rpmsg.h"
+#include "imx-pcm.h"
+
+#define FSL_RPMSG_RATES(SNDRV_PCM_RATE_8000 | \
+   SNDRV_PCM_RATE_16000 | \
+   SNDRV_PCM_RATE_48000)
+#define FSL_RPMSG_FORMATS  SNDRV_PCM_FMTBIT_S16_LE
+
+static const unsigned int fsl_rpmsg_rates[] = {
+   8000, 11025, 16000, 22050, 44100,
+   32000, 48000, 96000, 88200, 176400, 192000,
+   352800, 384000, 705600, 768000, 1411200, 2822400,
+};
+
+static const struct snd_pcm_hw_constraint_list fsl_rpmsg_rate_constraints = {
+   .count = ARRAY_SIZE(fsl_rpmsg_rates),
+   .list = fsl_rpmsg_rates,
+};
+
+static int fsl_rpmsg_hw_params(struct snd_pcm_substream *substream,
+  struct snd_pcm_hw_params *params,
+  struct snd_soc_dai *dai)
+{
+   struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai);
+   struct clk *p = rpmsg->mclk, *pll = 0, *npll = 0;
+   unsigned int rate = params_rate(params);
+   int ret;
+
+   /* Get current pll parent */
+   while (p && rpmsg->pll8k && rpmsg->pll11k) {
+   struct clk *pp = clk_get_parent(p);
+
+   if (clk_is_match(pp, rpmsg->pll8k) ||
+   clk_is_match(pp, rpmsg->pll11k)) {
+   pll = pp;
+   break;
+   }
+   p = pp;
+   }
+
+   /* Switch to another pll parent if needed. */
+   if (pll) {
+   npll = (do_div(rate, 8000) ? rpmsg->pll11k : rpmsg->pll8k);
+   if (!clk_is_match(pll, npll)) {
+   ret = clk_set_parent(p, npll);
+   if (ret < 0)
+   dev_warn(dai->dev, "failed to set parent %s: 
%d\n",
+__clk_get_name(npll), ret);
+   }
+   }
+
+   ret = clk_prepare_enable(rpmsg->mclk);
+   if (ret)
+   dev_err(dai->dev, "failed to enable mclk: %d\n", ret);
+
+   return ret;
+}
+
+static int fsl_rpmsg_hw_free(struct snd_pcm_substream *substream,
+struct snd_soc_dai *dai)
+{
+   struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai);
+
+   clk_disable_unprepare(rpmsg->mclk);
+
+   return 0;
+}
+
+static int fsl_rpmsg_startup(struct snd_pcm_substream *substream,
+struct snd_soc_dai *cpu_dai)
+{
+   int ret;
+
+   ret = snd_pcm_hw_c

[PATCH 4/7] ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel

2021-02-04 Thread Shengjiu Wang
This driver is used to accept the message from rpmsg audio
channel, and if this driver is probed, it will help to register
the platform driver, the platform driver will use this
audio channel to send and receive message to and from Cortex-M
core.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig   |   4 +
 sound/soc/fsl/Makefile  |   1 +
 sound/soc/fsl/imx-audio-rpmsg.c | 142 
 3 files changed, 147 insertions(+)
 create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index a688c3c2efbc..84d9f0f1f75b 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -126,6 +126,10 @@ config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
 
+config SND_SOC_IMX_AUDIO_RPMSG
+   tristate
+   depends on RPMSG
+
 config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index b63802f345cc..f08f3cd07ff5 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 
 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
+obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c
new file mode 100644
index ..c88af99ec4d9
--- /dev/null
+++ b/sound/soc/fsl/imx-audio-rpmsg.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2020 NXP
+
+#include 
+#include 
+#include "imx-pcm-rpmsg.h"
+
+/**
+ * struct imx_audio_rpmsg: private data
+ *
+ * @rpmsg_pdev: pointer of platform device
+ */
+struct imx_audio_rpmsg {
+   struct platform_device *rpmsg_pdev;
+};
+
+static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
+ void *priv, u32 src)
+{
+   struct imx_audio_rpmsg *rpmsg = dev_get_drvdata(>dev);
+   struct rpmsg_info *info = platform_get_drvdata(rpmsg->rpmsg_pdev);
+   struct rpmsg_r_msg *r_msg = (struct rpmsg_r_msg *)data;
+   struct rpmsg_msg *msg;
+   unsigned long flags;
+
+   dev_dbg(>dev, "get from%d: cmd:%d. %d\n",
+   src, r_msg->header.cmd, r_msg->param.resp);
+
+   /* TYPE C is notification from M core */
+   if (r_msg->header.type == MSG_TYPE_C) {
+   if (r_msg->header.cmd == TX_PERIOD_DONE) {
+   spin_lock_irqsave(>lock[TX], flags);
+   msg = >msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
+
+   /**
+* Low power mode: get the buffer pointer from
+* receive msg.
+*/
+   if (r_msg->header.major == 1 &&
+   r_msg->header.minor == 2)
+   msg->r_msg.param.buffer_tail =
+   r_msg->param.buffer_tail;
+   else
+   msg->r_msg.param.buffer_tail++;
+
+   msg->r_msg.param.buffer_tail %= info->num_period[TX];
+   spin_unlock_irqrestore(>lock[TX], flags);
+   info->callback[TX](info->callback_param[TX]);
+
+   } else if (r_msg->header.cmd == RX_PERIOD_DONE) {
+   spin_lock_irqsave(>lock[RX], flags);
+   msg = >msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
+
+   if (r_msg->header.major == 1 &&
+   r_msg->header.minor == 2)
+   msg->r_msg.param.buffer_tail =
+   r_msg->param.buffer_tail;
+   else
+   msg->r_msg.param.buffer_tail++;
+
+   msg->r_msg.param.buffer_tail %= info->num_period[1];
+   spin_unlock_irqrestore(>lock[RX], flags);
+   info->callback[RX](info->callback_param[RX]);
+   }
+   }
+
+   /* TYPE B is response msg */
+   if (r_msg->header.type == MSG_TYPE_B) {
+   memcpy(>r_msg, r_msg, sizeof(struct rpmsg_r_msg));
+   complete(>cmd_complete);
+   }
+
+   return 0;
+}
+
+static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev)
+{
+   struct imx_audio_rpmsg *data;
+   int ret = 0;
+
+   dev_info(>dev, "new channel: 0x%x -> 0x%x!\n",
+rpdev->src, rpdev->dst);
+
+   data = devm_kzalloc(>dev, sizeof(*data), GFP_KERNEL);
+   if (!data)
+  

[PATCH 5/7] ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg

2021-02-04 Thread Shengjiu Wang
platform driver base on rpmsg is the interface for sending and
receiving rpmsg to and from M core. It will tell the Cortex-M core
sound format/rate/channel, where is the data buffer, where is
the period size, when to start, when to stop and when suspend
or resume happen, each this behavior there is defined rpmsg
command.

Especially we designed the low power audio case, that is to
allocate a large buffer and fill the data, then Cortex-A core can go
to sleep mode, Cortex-M core continue to play the sound, when the
buffer is consumed, Cortex-M core will trigger the Cortex-A core to
wakeup.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |   5 +
 sound/soc/fsl/Makefile|   1 +
 sound/soc/fsl/imx-pcm-rpmsg.c | 898 ++
 sound/soc/fsl/imx-pcm-rpmsg.h | 512 +++
 4 files changed, 1416 insertions(+)
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 84d9f0f1f75b..749c44fc0759 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -130,6 +130,11 @@ config SND_SOC_IMX_AUDIO_RPMSG
tristate
depends on RPMSG
 
+config SND_SOC_IMX_PCM_RPMSG
+   tristate
+   depends on SND_SOC_IMX_AUDIO_RPMSG
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+
 config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index f08f3cd07ff5..ce4f4324c3a2 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
 obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
 obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o
+obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
new file mode 100644
index ..48df864bc092
--- /dev/null
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -0,0 +1,898 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2021 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "imx-pcm.h"
+#include "fsl_rpmsg.h"
+#include "imx-pcm-rpmsg.h"
+
+static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
+   .info = SNDRV_PCM_INFO_INTERLEAVED |
+   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+   SNDRV_PCM_INFO_MMAP |
+   SNDRV_PCM_INFO_MMAP_VALID |
+   SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
+   SNDRV_PCM_INFO_PAUSE |
+   SNDRV_PCM_INFO_RESUME,
+   .buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE,
+   .period_bytes_min = 512,
+   .period_bytes_max = 65536,
+   .periods_min = 2,
+   .periods_max = 6000,
+   .fifo_size = 0,
+};
+
+static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
+ struct rpmsg_info *info)
+{
+   struct rpmsg_device *rpdev = info->rpdev;
+   int ret = 0;
+
+   mutex_lock(>msg_lock);
+   if (!rpdev) {
+   dev_err(info->dev, "rpmsg channel not ready\n");
+   mutex_unlock(>msg_lock);
+   return -EINVAL;
+   }
+
+   dev_dbg(>dev, "send cmd %d\n", msg->s_msg.header.cmd);
+
+   if (!(msg->s_msg.header.type == MSG_TYPE_C))
+   reinit_completion(>cmd_complete);
+
+   ret = rpmsg_send(rpdev->ept, (void *)>s_msg,
+sizeof(struct rpmsg_s_msg));
+   if (ret) {
+   dev_err(>dev, "rpmsg_send failed: %d\n", ret);
+   mutex_unlock(>msg_lock);
+   return ret;
+   }
+
+   /* No receive msg for TYPE_C command */
+   if (msg->s_msg.header.type == MSG_TYPE_C) {
+   mutex_unlock(>msg_lock);
+   return 0;
+   }
+
+   /* wait response from rpmsg */
+   ret = wait_for_completion_timeout(>cmd_complete,
+ msecs_to_jiffies(RPMSG_TIMEOUT));
+   if (!ret) {
+   dev_err(>dev, "rpmsg_send cmd %d timeout!\n",
+   msg->s_msg.header.cmd);
+   mutex_unlock(>msg_lock);
+   return -ETIMEDOUT;
+   }
+
+   memcpy(>r_msg, >r_msg, sizeof(struct rpmsg_r_msg));
+   memcpy(>msg[msg->r_msg.header.cmd].r_msg,
+  >r_msg, sizeof(struct rpmsg_r_msg));
+
+   /*
+* Reset the buffer pointer to be zero, actully we have
+* set the buffer pointer to be zero in imx_rpmsg_terminate_all
+* But if there is timer task queued in queue, after it is
+* executed the buffer pointer will be

[PATCH 7/7] ASoC: dt-bindings: imx-rpmsg: Add binding doc for rpmsg machine driver

2021-02-04 Thread Shengjiu Wang
Imx-rpmsg is a new added machine driver for supporting audio on Cortex-M
core. The Cortex-M core will control the audio interface, DMA and audio
codec, setup the pipeline, the audio driver on Cortex-A core side is just
to communitcate with M core, it is a virtual sound card and don't touch
the hardware.

Signed-off-by: Shengjiu Wang 
---
 .../bindings/sound/imx-audio-rpmsg.yaml   | 48 +++
 1 file changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml

diff --git a/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml 
b/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
new file mode 100644
index ..b941aeb80678
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/imx-audio-rpmsg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX audio complex with rpmsg
+
+maintainers:
+  - Shengjiu Wang 
+
+properties:
+  compatible:
+enum:
+  - fsl,imx-audio-rpmsg
+
+  model:
+$ref: /schemas/types.yaml#/definitions/string
+description: User specified audio sound card name
+
+  audio-cpu:
+description: The phandle of an CPU DAI controller
+
+  rpmsg-out:
+description: |
+  This is a boolean property. If present, the transmitting function
+  will be enabled,
+
+  rpmsg-in:
+description: |
+  This is a boolean property. If present, the receiving function
+  will be enabled.
+
+required:
+  - compatible
+  - model
+  - audio-cpu
+
+additionalProperties: false
+
+examples:
+  - |
+sound-rpmsg {
+compatible = "fsl,imx-audio-rpmsg";
+model = "ak4497-audio";
+audio-cpu = <_audio>;
+rpmsg-out;
+};
-- 
2.27.0



[PATCH 3/7] ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver

2021-02-04 Thread Shengjiu Wang
fsl_rpmsg cpu dai driver is dummy driver, which is mainly used for
getting the user's configuration from device tree and configure the
clocks which is used by Cortex-M core. So in this document define the
needed property.

Signed-off-by: Shengjiu Wang 
---
 .../devicetree/bindings/sound/fsl,rpmsg.yaml  | 80 +++
 1 file changed, 80 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml

diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml 
b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
new file mode 100644
index ..1c2679fac31e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/fsl,rpmsg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP Audio RPMSG Dummy Controller
+
+maintainers:
+  - Shengjiu Wang 
+
+properties:
+  compatible:
+enum:
+  - fsl,imx7ulp-rpmsg
+  - fsl,imx8mn-rpmsg
+  - fsl,imx8mm-rpmsg
+  - fsl,imx8mp-rpmsg
+
+  clocks:
+items:
+  - description: Peripheral clock for register access
+  - description: Master clock
+  - description: DMA clock for DMA register access
+  - description: Parent clock for multiple of 8kHz sample rates
+  - description: Parent clock for multiple of 11kHz sample rates
+minItems: 5
+
+  clock-names:
+items:
+  - const: ipg
+  - const: mclk
+  - const: dma
+  - const: pll8k
+  - const: pll11k
+minItems: 5
+
+  power-domains:
+maxItems: 1
+
+  fsl,audioindex:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: instance index for rpmsg image
+
+  fsl,version:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: rpmsg image version index
+
+  fsl,buffer-size:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: pre allocate dma buffer size
+
+  fsl,enable-lpa:
+$ref: /schemas/types.yaml#/definitions/flag
+description: enable low power audio path.
+
+  fsl,codec-type:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: Sometimes the codec is registered by
+ driver not the device tree, this items
+ can be used to distinguish codecs
+
+required:
+  - compatible
+  - fsl,audioindex
+  - fsl,version
+  - fsl,buffer-size
+
+additionalProperties: false
+
+examples:
+  - |
+rpmsg_audio: rpmsg_audio {
+compatible = "fsl,imx8mn-rpmsg";
+fsl,audioindex = <0> ;
+fsl,version = <2>;
+fsl,buffer-size = <0x600>;
+fsl,enable-lpa;
+status = "okay";
+};
-- 
2.27.0



[PATCH 6/7] ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg

2021-02-04 Thread Shengjiu Wang
The platform device is not registered by device tree or
cpu dai driver, it is registered by the rpmsg channel,
So add a dedicated machine driver to handle this case.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/Kconfig |  12 
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/imx-rpmsg.c | 148 ++
 3 files changed, 162 insertions(+)
 create mode 100644 sound/soc/fsl/imx-rpmsg.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 749c44fc0759..3557866d3fa2 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -334,6 +334,18 @@ config SND_SOC_IMX_HDMI
  Say Y if you want to add support for SoC audio on an i.MX board with
  IMX HDMI.
 
+config SND_SOC_IMX_RPMSG
+   tristate "SoC Audio support for i.MX boards with rpmsg"
+   depends on RPMSG
+   select SND_SOC_IMX_PCM_RPMSG
+   select SND_SOC_IMX_AUDIO_RPMSG
+   select SND_SOC_FSL_RPMSG
+   help
+ SoC Audio support for i.MX boards with rpmsg.
+ There should be rpmsg devices defined in other core (M core)
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a rpmsg devices.
+
 endif # SND_IMX_SOC
 
 endmenu
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index ce4f4324c3a2..f146ce464acd 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -70,6 +70,7 @@ snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
 snd-soc-imx-spdif-objs := imx-spdif.o
 snd-soc-imx-audmix-objs := imx-audmix.o
 snd-soc-imx-hdmi-objs := imx-hdmi.o
+snd-soc-imx-rpmsg-objs := imx-rpmsg.o
 
 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
 obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o
@@ -77,3 +78,4 @@ 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_AUDMIX) += snd-soc-imx-audmix.o
 obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o
+obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o
diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c
new file mode 100644
index ..a87dcbce4f36
--- /dev/null
+++ b/sound/soc/fsl/imx-rpmsg.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2020 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "imx-pcm-rpmsg.h"
+
+struct imx_rpmsg {
+   struct snd_soc_dai_link dai;
+   struct snd_soc_card card;
+};
+
+static int imx_rpmsg_probe(struct platform_device *pdev)
+{
+   struct snd_soc_dai_link_component *dlc;
+   struct platform_device *cpu_pdev;
+   struct of_phandle_args args;
+   struct device_node *cpu_np;
+   struct imx_rpmsg *data;
+   int ret;
+
+   dlc = devm_kzalloc(>dev, 3 * sizeof(*dlc), GFP_KERNEL);
+   if (!dlc)
+   return -ENOMEM;
+
+   cpu_np = of_parse_phandle(pdev->dev.of_node, "audio-cpu", 0);
+   if (!cpu_np) {
+   dev_err(>dev, "cpu dai phandle missing or invalid\n");
+   ret = -EINVAL;
+   goto fail;
+   }
+
+   data = devm_kzalloc(>dev, sizeof(*data), GFP_KERNEL);
+   if (!data) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+
+   cpu_pdev = of_find_device_by_node(cpu_np);
+   if (!cpu_pdev) {
+   dev_err(>dev, "failed to find rpmsg platform device\n");
+   ret = -EINVAL;
+   goto fail;
+   }
+
+   ret = of_reserved_mem_device_init_by_idx(>dev, pdev->dev.of_node, 
0);
+   if (ret)
+   dev_warn(>dev, "no reserved DMA memory\n");
+
+   data->dai.cpus = [0];
+   data->dai.num_cpus = 1;
+   data->dai.platforms = [1];
+   data->dai.num_platforms = 1;
+   data->dai.codecs = [2];
+   data->dai.num_codecs = 1;
+
+   data->dai.name = "rpmsg hifi";
+   data->dai.stream_name = "rpmsg hifi";
+   data->dai.dai_fmt = SND_SOC_DAIFMT_I2S |
+   SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS;
+
+   /* Optional codec node */
+   ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
+  "audio-codec", 0, 0, );
+   if (ret) {
+   data->dai.codecs->dai_name = "snd-soc-dummy-dai";
+   data->dai.codecs->name = "snd-soc-dummy";
+   } else {
+   data->dai.codecs->of_node = args.np;
+   ret = snd_soc_get_dai_name(, >dai.codecs->dai_name);
+   if (ret) {
+   dev_err(>dev, "Unable to get codec_dai_name\n");
+   goto fail;
+   }
+   }
+
+   data->dai.

[PATCH 0/7] Add audio driver base on rpmsg on i.MX platform

2021-02-04 Thread Shengjiu Wang
On Asymmetric multiprocessor, there is Cortex-A core and Cortex-M core,
Linux is running on A core, RTOS is running on M core.
The audio hardware device can be controlled by Cortex-M device,
So audio playback/capture can be handled by M core.

Rpmsg is the interface for sending and receiving msg to and from M
core, that we can create a virtual sound on Cortex-A core side.

A core will tell the Cortex-M core sound format/rate/channel,
where is the data buffer, what is the period size, when to start,
when to stop and when suspend or resume happen, each of this behavior
there is defined rpmsg command.

Especially we designed the low power audio case, that is to
allocate a large buffer and fill the data, then Cortex-A core can go
to sleep mode, Cortex-M core continue to play the sound, when the
buffer is consumed, Cortex-M core will trigger the Cortex-A core to
wakeup to fill data.

Shengjiu Wang (7):
  ASoC: soc-component: Add snd_soc_pcm_component_ack
  ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg
  ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg cpu dai driver
  ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel
  ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg
  ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg
  ASoC: dt-bindings: imx-rpmsg: Add binding doc for rpmsg machine driver

 .../devicetree/bindings/sound/fsl,rpmsg.yaml  |  80 ++
 .../bindings/sound/imx-audio-rpmsg.yaml   |  48 +
 include/sound/soc-component.h |   3 +
 sound/soc/fsl/Kconfig |  28 +
 sound/soc/fsl/Makefile|   6 +
 sound/soc/fsl/fsl_rpmsg.c | 258 +
 sound/soc/fsl/fsl_rpmsg.h |  38 +
 sound/soc/fsl/imx-audio-rpmsg.c   | 142 +++
 sound/soc/fsl/imx-pcm-rpmsg.c | 898 ++
 sound/soc/fsl/imx-pcm-rpmsg.h | 512 ++
 sound/soc/fsl/imx-rpmsg.c | 148 +++
 sound/soc/soc-component.c |  14 +
 sound/soc/soc-pcm.c   |   2 +
 13 files changed, 2177 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-rpmsg.yaml
 create mode 100644 sound/soc/fsl/fsl_rpmsg.c
 create mode 100644 sound/soc/fsl/fsl_rpmsg.h
 create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c
 create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h
 create mode 100644 sound/soc/fsl/imx-rpmsg.c

-- 
2.27.0



[PATCH 1/7] ASoC: soc-component: Add snd_soc_pcm_component_ack

2021-02-04 Thread Shengjiu Wang
Add snd_soc_pcm_component_ack back, which can be used to get updated
buffer pointer in platform driver.
On Asymmetric multiprocessor, this pointer can be sent to Cortex-M
core for audio processing.

Signed-off-by: Shengjiu Wang 
---
 include/sound/soc-component.h |  3 +++
 sound/soc/soc-component.c | 14 ++
 sound/soc/soc-pcm.c   |  2 ++
 3 files changed, 19 insertions(+)

diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 5b47768222b7..2dc8c7e3d1a6 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -146,6 +146,8 @@ struct snd_soc_component_driver {
int (*mmap)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
+   int (*ack)(struct snd_soc_component *component,
+  struct snd_pcm_substream *substream);
 
const struct snd_compress_ops *compress_ops;
 
@@ -498,5 +500,6 @@ int snd_soc_pcm_component_pm_runtime_get(struct 
snd_soc_pcm_runtime *rtd,
 void *stream);
 void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
  void *stream, int rollback);
+int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream);
 
 #endif /* __SOC_COMPONENT_H */
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 159bf88b9f8c..a9fbb2d26412 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -1212,3 +1212,17 @@ void snd_soc_pcm_component_pm_runtime_put(struct 
snd_soc_pcm_runtime *rtd,
soc_component_mark_pop(component, stream, pm);
}
 }
+
+int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+   struct snd_soc_component *component;
+   int i;
+
+   /* FIXME: use 1st pointer */
+   for_each_rtd_components(rtd, i, component)
+   if (component->driver->ack)
+   return component->driver->ack(component, substream);
+
+   return 0;
+}
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index b79f064887d4..605acec48971 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2830,6 +2830,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->ops.page   = snd_soc_pcm_component_page;
if (drv->mmap)
rtd->ops.mmap   = snd_soc_pcm_component_mmap;
+   if (drv->ack)
+   rtd->ops.ack= snd_soc_pcm_component_ack;
}
 
if (playback)
-- 
2.27.0



Re: [PATCH] ASoC: fsl_spdif: Utilize the defined parameter to clear code

2021-02-01 Thread Shengjiu Wang
On Thu, Jan 28, 2021 at 7:28 PM Tang Bin  wrote:
>
> Utilize the defined parameter 'dev' to make the code cleaner.
>
> Signed-off-by: Tang Bin 

Acked-by: Shengjiu Wang 


Re: [PATCH] ASoC: fsl_xcvr: remove unneeded semicolon

2021-02-01 Thread Shengjiu Wang
On Mon, Feb 1, 2021 at 4:08 PM Yang Li  wrote:
>
> Eliminate the following coccicheck warning:
> ./sound/soc/fsl/fsl_xcvr.c:739:2-3: Unneeded semicolon
>
> Reported-by: Abaci Robot 
> Signed-off-by: Yang Li 

Acked-by: Shengjiu Wang 


[PATCH] ASoC: dmaengine_pcm: add peripheral configuration

2021-01-26 Thread Shengjiu Wang
The commit e7bbb7acabf4 ("dmaengine: add peripheral configuration")
adds peripheral configuration for dma_slave_config.

This configuration is useful for some audio peripherals, for
example, the peripheral supports multi fifos, we can
let the DMA know which fifos are selected. So also add
this configuration for snd_dmaengine_dai_dma_data.

Signed-off-by: Shengjiu Wang 
---
 include/sound/dmaengine_pcm.h | 5 +
 sound/core/pcm_dmaengine.c| 2 ++
 2 files changed, 7 insertions(+)

diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index 8c5e38180fb0..9efddb39 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -66,6 +66,9 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct 
snd_pcm_substream *substream)
  * @chan_name: Custom channel name to use when requesting DMA channel.
  * @fifo_size: FIFO size of the DAI controller in bytes
  * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now
+ * @peripheral_config: peripheral configuration for programming peripheral
+ * for dmaengine transfer
+ * @peripheral_size: peripheral configuration buffer size
  */
 struct snd_dmaengine_dai_dma_data {
dma_addr_t addr;
@@ -76,6 +79,8 @@ struct snd_dmaengine_dai_dma_data {
const char *chan_name;
unsigned int fifo_size;
unsigned int flags;
+   void *peripheral_config;
+   size_t peripheral_size;
 };
 
 void snd_dmaengine_pcm_set_config_from_dai_data(
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 4d0e8fe535a1..1fc2fa077574 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -125,6 +125,8 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
}
 
slave_config->slave_id = dma_data->slave_id;
+   slave_config->peripheral_config = dma_data->peripheral_config;
+   slave_config->peripheral_size = dma_data->peripheral_size;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
 
-- 
2.27.0



  1   2   3   4   5   6   >