[PATCH v2 3/3] ASoC: fsl-asoc-card: Support Headphone and Microphone Jack detection

2020-07-15 Thread Shengjiu Wang
Use asoc_simple_init_jack function from simple card to implement
the Headphone and Microphone detection.
Register notifier to disable Speaker when Headphone is plugged in
and enable Speaker when Headphone is unplugged.
Register notifier to disable Digital Microphone when Analog Microphone
is plugged in and enable DMIC when Analog Microphone is unplugged.

Signed-off-by: Shengjiu Wang 
Acked-by: Nicolin Chen 
---
 sound/soc/fsl/Kconfig |  1 +
 sound/soc/fsl/fsl-asoc-card.c | 77 ++-
 2 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index ea7b4787a8af..1c4ca5ec8caf 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -315,6 +315,7 @@ config SND_SOC_FSL_ASOC_CARD
depends on OF && I2C
# enforce SND_SOC_FSL_ASOC_CARD=m if SND_AC97_CODEC=m:
depends on SND_AC97_CODEC || SND_AC97_CODEC=n
+   select SND_SIMPLE_CARD_UTILS
select SND_SOC_IMX_AUDMUX
select SND_SOC_IMX_PCM_DMA
select SND_SOC_FSL_ESAI
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index faac6ce9a82c..f0cde3ecb5b7 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -15,6 +15,8 @@
 #endif
 #include 
 #include 
+#include 
+#include 
 
 #include "fsl_esai.h"
 #include "fsl_sai.h"
@@ -65,6 +67,8 @@ struct cpu_priv {
 /**
  * struct fsl_asoc_card_priv - Freescale Generic ASOC card private data
  * @dai_link: DAI link structure including normal one and DPCM link
+ * @hp_jack: Headphone Jack structure
+ * @mic_jack: Microphone Jack structure
  * @pdev: platform device pointer
  * @codec_priv: CODEC private data
  * @cpu_priv: CPU private data
@@ -79,6 +83,8 @@ struct cpu_priv {
 
 struct fsl_asoc_card_priv {
struct snd_soc_dai_link dai_link[3];
+   struct asoc_simple_jack hp_jack;
+   struct asoc_simple_jack mic_jack;
struct platform_device *pdev;
struct codec_priv codec_priv;
struct cpu_priv cpu_priv;
@@ -445,6 +451,44 @@ static int fsl_asoc_card_audmux_init(struct device_node 
*np,
return 0;
 }
 
+static int hp_jack_event(struct notifier_block *nb, unsigned long event,
+void *data)
+{
+   struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
+   struct snd_soc_dapm_context *dapm = >card->dapm;
+
+   if (event & SND_JACK_HEADPHONE)
+   /* Disable speaker if headphone is plugged in */
+   snd_soc_dapm_disable_pin(dapm, "Ext Spk");
+   else
+   snd_soc_dapm_enable_pin(dapm, "Ext Spk");
+
+   return 0;
+}
+
+static struct notifier_block hp_jack_nb = {
+   .notifier_call = hp_jack_event,
+};
+
+static int mic_jack_event(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+   struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
+   struct snd_soc_dapm_context *dapm = >card->dapm;
+
+   if (event & SND_JACK_MICROPHONE)
+   /* Disable dmic if microphone is plugged in */
+   snd_soc_dapm_disable_pin(dapm, "DMIC");
+   else
+   snd_soc_dapm_enable_pin(dapm, "DMIC");
+
+   return 0;
+}
+
+static struct notifier_block mic_jack_nb = {
+   .notifier_call = mic_jack_event,
+};
+
 static int fsl_asoc_card_late_probe(struct snd_soc_card *card)
 {
struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
@@ -745,8 +789,37 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
snd_soc_card_set_drvdata(>card, priv);
 
ret = devm_snd_soc_register_card(>dev, >card);
-   if (ret && ret != -EPROBE_DEFER)
-   dev_err(>dev, "snd_soc_register_card failed (%d)\n", ret);
+   if (ret) {
+   if (ret != -EPROBE_DEFER)
+   dev_err(>dev, "snd_soc_register_card failed 
(%d)\n", ret);
+   goto asrc_fail;
+   }
+
+   /*
+* Properties "hp-det-gpio" and "mic-det-gpio" are optional, and
+* asoc_simple_init_jack uses these properties for creating
+* Headphone Jack and Microphone Jack.
+*
+* The notifier is initialized in snd_soc_card_jack_new(), then
+* snd_soc_jack_notifier_register can be called.
+*/
+   if (of_property_read_bool(np, "hp-det-gpio")) {
+   ret = asoc_simple_init_jack(>card, >hp_jack,
+   1, NULL, "Headphone Jack");
+   if (ret)
+   goto asrc_fail;
+
+   snd_soc_jack_notifier_register(>hp_jack.jack, 
_jack_nb);
+   }
+
+   if (of_property_read_bool(np, "mic-det-gpio")) {
+   ret = asoc_simple_init_jack(>card, >mic_jack,
+ 

[PATCH v2 2/3] ASoC: bindings: fsl-asoc-card: Support hp-det-gpio and mic-det-gpio

2020-07-15 Thread Shengjiu Wang
Add headphone and microphone detection GPIO support.
These properties are optional.

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

diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt 
b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
index 133d7e14a4d0..8a6a3d0fda5e 100644
--- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
+++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
@@ -69,6 +69,9 @@ Optional properties:
coexisting in order to support the old bindings
of wm8962 and sgtl5000.
 
+  - hp-det-gpio: The GPIO that detect headphones are plugged in
+  - mic-det-gpio   : The GPIO that detect microphones are plugged in
+
 Optional unless SSI is selected as a CPU DAI:
 
   - mux-int-port   : The internal port of the i.MX audio muxer (AUDMUX)
-- 
2.27.0



[PATCH v2 1/3] ASoC: simple-card-utils: Support configure pin_name for asoc_simple_init_jack

2020-07-15 Thread Shengjiu Wang
Currently the pin_name is fixed in asoc_simple_init_jack, but some driver
may use a different pin_name. So add a new parameter in
asoc_simple_init_jack for configuring pin_name.

If this parameter is NULL, then the default pin_name is used.

Signed-off-by: Shengjiu Wang 
Acked-by: Nicolin Chen 
---
 include/sound/simple_card_utils.h | 6 +++---
 sound/soc/generic/simple-card-utils.c | 7 ---
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/sound/simple_card_utils.h 
b/include/sound/simple_card_utils.h
index bbdd1542d6f1..86a1e956991e 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -12,9 +12,9 @@
 #include 
 
 #define asoc_simple_init_hp(card, sjack, prefix) \
-   asoc_simple_init_jack(card, sjack, 1, prefix)
+   asoc_simple_init_jack(card, sjack, 1, prefix, NULL)
 #define asoc_simple_init_mic(card, sjack, prefix) \
-   asoc_simple_init_jack(card, sjack, 0, prefix)
+   asoc_simple_init_jack(card, sjack, 0, prefix, NULL)
 
 struct asoc_simple_dai {
const char *name;
@@ -131,7 +131,7 @@ int asoc_simple_parse_pin_switches(struct snd_soc_card 
*card,
 
 int asoc_simple_init_jack(struct snd_soc_card *card,
   struct asoc_simple_jack *sjack,
-  int is_hp, char *prefix);
+  int is_hp, char *prefix, char *pin);
 int asoc_simple_init_priv(struct asoc_simple_priv *priv,
   struct link_info *li);
 
diff --git a/sound/soc/generic/simple-card-utils.c 
b/sound/soc/generic/simple-card-utils.c
index 8c54dc6710fe..b408cb5ed644 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -540,7 +540,8 @@ EXPORT_SYMBOL_GPL(asoc_simple_parse_pin_switches);
 
 int asoc_simple_init_jack(struct snd_soc_card *card,
  struct asoc_simple_jack *sjack,
- int is_hp, char *prefix)
+ int is_hp, char *prefix,
+ char *pin)
 {
struct device *dev = card->dev;
enum of_gpio_flags flags;
@@ -557,12 +558,12 @@ int asoc_simple_init_jack(struct snd_soc_card *card,
 
if (is_hp) {
snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
-   pin_name= "Headphones";
+   pin_name= pin ? pin : "Headphones";
gpio_name   = "Headphone detection";
mask= SND_JACK_HEADPHONE;
} else {
snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
-   pin_name= "Mic Jack";
+   pin_name= pin ? pin : "Mic Jack";
gpio_name   = "Mic detection";
mask= SND_JACK_MICROPHONE;
}
-- 
2.27.0



[PATCH v2 0/3] ASoC: fsl-asoc-card: Support hp and mic detection

2020-07-15 Thread Shengjiu Wang
Support hp and mic detection.
Add a parameter for asoc_simple_init_jack.

Shengjiu Wang (3):
  ASoC: simple-card-utils: Support configure pin_name for
asoc_simple_init_jack
  ASoC: bindings: fsl-asoc-card: Support hp-det-gpio and mic-det-gpio
  ASoC: fsl-asoc-card: Support Headphone and Microphone Jack detection

changes in v2:
- Add more comments in third commit
- Add Acked-by Nicolin.

 .../bindings/sound/fsl-asoc-card.txt  |  3 +
 include/sound/simple_card_utils.h |  6 +-
 sound/soc/fsl/Kconfig |  1 +
 sound/soc/fsl/fsl-asoc-card.c | 77 ++-
 sound/soc/generic/simple-card-utils.c |  7 +-
 5 files changed, 86 insertions(+), 8 deletions(-)

-- 
2.27.0



Re: [PATCH 3/3] ASoC: fsl-asoc-card: Support Headphone and Microphone Jack detection

2020-07-14 Thread Shengjiu Wang
On Wed, Jul 15, 2020 at 5:16 AM Nicolin Chen  wrote:
>
> Hi Shengjiu,
>
> The whole series looks good to me. Just a couple of small
> questions inline:
>
> On Tue, Jul 14, 2020 at 05:05:36PM +0800, Shengjiu Wang wrote:
> > Use asoc_simple_init_jack function from simple card to implement
> > the Headphone and Microphone detection.
> > Register notifier to disable Speaker when Headphone is plugged in
> > and enable Speaker when Headphone is unplugged.
> > Register notifier to disable Digital Microphone when Analog Microphone
> > is plugged in and enable DMIC when Analog Microphone is unplugged.
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
> >  sound/soc/fsl/Kconfig |  1 +
> >  sound/soc/fsl/fsl-asoc-card.c | 69 ++-
> >  2 files changed, 68 insertions(+), 2 deletions(-)
>
> >  static int fsl_asoc_card_late_probe(struct snd_soc_card *card)
> >  {
> >   struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
> > @@ -745,8 +789,29 @@ static int fsl_asoc_card_probe(struct platform_device 
> > *pdev)
> >   snd_soc_card_set_drvdata(>card, priv);
> >
> >   ret = devm_snd_soc_register_card(>dev, >card);
> > - if (ret && ret != -EPROBE_DEFER)
> > - dev_err(>dev, "snd_soc_register_card failed (%d)\n", 
> > ret);
> > + if (ret) {
> > + if (ret != -EPROBE_DEFER)
> > + dev_err(>dev, "snd_soc_register_card failed 
> > (%d)\n", ret);
>
> I think we may move this EPROBE_DEFER to the asrc_fail label.

If we move this to asrc_fail label, then it will be hard to define the
error message.
There are many places that goto asrc_fail.

>
> > + goto asrc_fail;
> > + }
> > +
> > + if (of_property_read_bool(np, "hp-det-gpio")) {
>
> Could we move this check inside asoc_simple_init_jack? There's no
> problem with doing it here though, yet I got a bit confused by it
> as I thought it's a boolean type property, which would be against
> the DT bindings until I saw asoc_simple_init_jack() uses the same
> string to get the GPIO. Just it probably would be a bit tricky as
> we need it to be optional here.
>
> Otherwise, I think we may add a line of comments to indicate that
> the API would use the same string to get the GPIO.

In asoc_simple_init_jack, gpio_is_valid() will be invalid when there is
no "hp-det-gpio" property, and asoc_simple_init_jack will return 0.

The reason why I add a check here is mostly for
snd_soc_jack_notifier_register().
when there is no jack created, there will be a kernel dump.

or I can use this code:

-   if (of_property_read_bool(np, "hp-det-gpio")) {
-   ret = asoc_simple_init_jack(>card, >hp_jack,
-   1, NULL, "Headphone Jack");
-   if (ret)
-   goto asrc_fail;
+   ret = asoc_simple_init_jack(>card, >hp_jack,
+   1, NULL, "Headphone Jack");
+   if (ret)
+   goto asrc_fail;

+   if (priv->hp_jack.jack.jack)
snd_soc_jack_notifier_register(>hp_jack.jack,
_jack_nb);
-   }

what do you think?

best regards
wang shengjiu


[PATCH 3/3] ASoC: fsl-asoc-card: Support Headphone and Microphone Jack detection

2020-07-14 Thread Shengjiu Wang
Use asoc_simple_init_jack function from simple card to implement
the Headphone and Microphone detection.
Register notifier to disable Speaker when Headphone is plugged in
and enable Speaker when Headphone is unplugged.
Register notifier to disable Digital Microphone when Analog Microphone
is plugged in and enable DMIC when Analog Microphone is unplugged.

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

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index ea7b4787a8af..1c4ca5ec8caf 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -315,6 +315,7 @@ config SND_SOC_FSL_ASOC_CARD
depends on OF && I2C
# enforce SND_SOC_FSL_ASOC_CARD=m if SND_AC97_CODEC=m:
depends on SND_AC97_CODEC || SND_AC97_CODEC=n
+   select SND_SIMPLE_CARD_UTILS
select SND_SOC_IMX_AUDMUX
select SND_SOC_IMX_PCM_DMA
select SND_SOC_FSL_ESAI
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index faac6ce9a82c..313058789ea9 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -15,6 +15,8 @@
 #endif
 #include 
 #include 
+#include 
+#include 
 
 #include "fsl_esai.h"
 #include "fsl_sai.h"
@@ -65,6 +67,8 @@ struct cpu_priv {
 /**
  * struct fsl_asoc_card_priv - Freescale Generic ASOC card private data
  * @dai_link: DAI link structure including normal one and DPCM link
+ * @hp_jack: Headphone Jack structure
+ * @mic_jack: Microphone Jack structure
  * @pdev: platform device pointer
  * @codec_priv: CODEC private data
  * @cpu_priv: CPU private data
@@ -79,6 +83,8 @@ struct cpu_priv {
 
 struct fsl_asoc_card_priv {
struct snd_soc_dai_link dai_link[3];
+   struct asoc_simple_jack hp_jack;
+   struct asoc_simple_jack mic_jack;
struct platform_device *pdev;
struct codec_priv codec_priv;
struct cpu_priv cpu_priv;
@@ -445,6 +451,44 @@ static int fsl_asoc_card_audmux_init(struct device_node 
*np,
return 0;
 }
 
+static int hp_jack_event(struct notifier_block *nb, unsigned long event,
+void *data)
+{
+   struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
+   struct snd_soc_dapm_context *dapm = >card->dapm;
+
+   if (event & SND_JACK_HEADPHONE)
+   /* Disable speaker if headphone is plugged in */
+   snd_soc_dapm_disable_pin(dapm, "Ext Spk");
+   else
+   snd_soc_dapm_enable_pin(dapm, "Ext Spk");
+
+   return 0;
+}
+
+static struct notifier_block hp_jack_nb = {
+   .notifier_call = hp_jack_event,
+};
+
+static int mic_jack_event(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+   struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
+   struct snd_soc_dapm_context *dapm = >card->dapm;
+
+   if (event & SND_JACK_MICROPHONE)
+   /* Disable dmic if microphone is plugged in */
+   snd_soc_dapm_disable_pin(dapm, "DMIC");
+   else
+   snd_soc_dapm_enable_pin(dapm, "DMIC");
+
+   return 0;
+}
+
+static struct notifier_block mic_jack_nb = {
+   .notifier_call = mic_jack_event,
+};
+
 static int fsl_asoc_card_late_probe(struct snd_soc_card *card)
 {
struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
@@ -745,8 +789,29 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
snd_soc_card_set_drvdata(>card, priv);
 
ret = devm_snd_soc_register_card(>dev, >card);
-   if (ret && ret != -EPROBE_DEFER)
-   dev_err(>dev, "snd_soc_register_card failed (%d)\n", ret);
+   if (ret) {
+   if (ret != -EPROBE_DEFER)
+   dev_err(>dev, "snd_soc_register_card failed 
(%d)\n", ret);
+   goto asrc_fail;
+   }
+
+   if (of_property_read_bool(np, "hp-det-gpio")) {
+   ret = asoc_simple_init_jack(>card, >hp_jack,
+   1, NULL, "Headphone Jack");
+   if (ret)
+   goto asrc_fail;
+
+   snd_soc_jack_notifier_register(>hp_jack.jack, 
_jack_nb);
+   }
+
+   if (of_property_read_bool(np, "mic-det-gpio")) {
+   ret = asoc_simple_init_jack(>card, >mic_jack,
+   0, NULL, "Mic Jack");
+   if (ret)
+   goto asrc_fail;
+
+   snd_soc_jack_notifier_register(>mic_jack.jack, 
_jack_nb);
+   }
 
 asrc_fail:
of_node_put(asrc_np);
-- 
2.27.0



[PATCH 2/3] ASoC: bindings: fsl-asoc-card: Support hp-det-gpio and mic-det-gpio

2020-07-14 Thread Shengjiu Wang
Add headphone and microphone detection GPIO support.

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

diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt 
b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
index 133d7e14a4d0..8a6a3d0fda5e 100644
--- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
+++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
@@ -69,6 +69,9 @@ Optional properties:
coexisting in order to support the old bindings
of wm8962 and sgtl5000.
 
+  - hp-det-gpio: The GPIO that detect headphones are plugged in
+  - mic-det-gpio   : The GPIO that detect microphones are plugged in
+
 Optional unless SSI is selected as a CPU DAI:
 
   - mux-int-port   : The internal port of the i.MX audio muxer (AUDMUX)
-- 
2.27.0



[PATCH 1/3] ASoC: simple-card-utils: Support configure pin_name for asoc_simple_init_jack

2020-07-14 Thread Shengjiu Wang
Currently the pin_name is fixed in asoc_simple_init_jack, but some driver
may use a different pin_name. So add a new parameter in
asoc_simple_init_jack for configuring pin_name.

If this parameter is NULL, then the default pin_name is used.

Signed-off-by: Shengjiu Wang 
---
 include/sound/simple_card_utils.h | 6 +++---
 sound/soc/generic/simple-card-utils.c | 7 ---
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/sound/simple_card_utils.h 
b/include/sound/simple_card_utils.h
index bbdd1542d6f1..86a1e956991e 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -12,9 +12,9 @@
 #include 
 
 #define asoc_simple_init_hp(card, sjack, prefix) \
-   asoc_simple_init_jack(card, sjack, 1, prefix)
+   asoc_simple_init_jack(card, sjack, 1, prefix, NULL)
 #define asoc_simple_init_mic(card, sjack, prefix) \
-   asoc_simple_init_jack(card, sjack, 0, prefix)
+   asoc_simple_init_jack(card, sjack, 0, prefix, NULL)
 
 struct asoc_simple_dai {
const char *name;
@@ -131,7 +131,7 @@ int asoc_simple_parse_pin_switches(struct snd_soc_card 
*card,
 
 int asoc_simple_init_jack(struct snd_soc_card *card,
   struct asoc_simple_jack *sjack,
-  int is_hp, char *prefix);
+  int is_hp, char *prefix, char *pin);
 int asoc_simple_init_priv(struct asoc_simple_priv *priv,
   struct link_info *li);
 
diff --git a/sound/soc/generic/simple-card-utils.c 
b/sound/soc/generic/simple-card-utils.c
index 8c54dc6710fe..b408cb5ed644 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -540,7 +540,8 @@ EXPORT_SYMBOL_GPL(asoc_simple_parse_pin_switches);
 
 int asoc_simple_init_jack(struct snd_soc_card *card,
  struct asoc_simple_jack *sjack,
- int is_hp, char *prefix)
+ int is_hp, char *prefix,
+ char *pin)
 {
struct device *dev = card->dev;
enum of_gpio_flags flags;
@@ -557,12 +558,12 @@ int asoc_simple_init_jack(struct snd_soc_card *card,
 
if (is_hp) {
snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
-   pin_name= "Headphones";
+   pin_name= pin ? pin : "Headphones";
gpio_name   = "Headphone detection";
mask= SND_JACK_HEADPHONE;
} else {
snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
-   pin_name= "Mic Jack";
+   pin_name= pin ? pin : "Mic Jack";
gpio_name   = "Mic detection";
mask= SND_JACK_MICROPHONE;
}
-- 
2.27.0



[PATCH 0/3] ASoC: fsl-asoc-card: Support hp and mic detection

2020-07-14 Thread Shengjiu Wang
Support hp and mic detection.
Add a parameter for asoc_simple_init_jack.

Shengjiu Wang (3):
  ASoC: simple-card-utils: Support configure pin_name for
asoc_simple_init_jack
  ASoC: bindings: fsl-asoc-card: Support hp-det-gpio and mic-det-gpio
  ASoC: fsl-asoc-card: Support Headphone and Microphone Jack detection

 .../bindings/sound/fsl-asoc-card.txt  |  3 +
 include/sound/simple_card_utils.h |  6 +-
 sound/soc/fsl/Kconfig |  1 +
 sound/soc/fsl/fsl-asoc-card.c | 69 ++-
 sound/soc/generic/simple-card-utils.c |  7 +-
 5 files changed, 78 insertions(+), 8 deletions(-)

-- 
2.27.0



[PATCH 2/2] ASoC: fsl_spdif: Add kctl for configuring TX validity bit

2020-07-07 Thread Shengjiu Wang
Add one kctl for configuring TX validity bit from user
space.

The type of this kctl is boolean:
on - Outgoing validity always set
off - Outgoing validity always clear

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_spdif.c | 47 +++
 1 file changed, 43 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 576370dc6e70..37053e8f29d0 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -776,8 +776,8 @@ static int fsl_spdif_vbit_info(struct snd_kcontrol 
*kcontrol,
 }
 
 /* Get valid good bit from interrupt status register */
-static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol,
-   struct snd_ctl_elem_value *ucontrol)
+static int fsl_spdif_rx_vbit_get(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
 {
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
@@ -791,6 +791,35 @@ static int fsl_spdif_vbit_get(struct snd_kcontrol 
*kcontrol,
return 0;
 }
 
+static int fsl_spdif_tx_vbit_get(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+   struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+   struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
+   struct regmap *regmap = spdif_priv->regmap;
+   u32 val;
+
+   regmap_read(regmap, REG_SPDIF_SCR, );
+   val = (val & SCR_VAL_MASK) >> SCR_VAL_OFFSET;
+   val = 1 - val;
+   ucontrol->value.integer.value[0] = val;
+
+   return 0;
+}
+
+static int fsl_spdif_tx_vbit_put(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+   struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+   struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
+   struct regmap *regmap = spdif_priv->regmap;
+   u32 val = (1 - ucontrol->value.integer.value[0]) << SCR_VAL_OFFSET;
+
+   regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_VAL_MASK, val);
+
+   return 0;
+}
+
 /* DPLL lock information */
 static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
@@ -948,11 +977,21 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
/* Valid bit error controller */
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
-   .name = "IEC958 V-Bit Errors",
+   .name = "IEC958 RX V-Bit Errors",
.access = SNDRV_CTL_ELEM_ACCESS_READ |
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = fsl_spdif_vbit_info,
-   .get = fsl_spdif_vbit_get,
+   .get = fsl_spdif_rx_vbit_get,
+   },
+   {
+   .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+   .name = "IEC958 TX V-Bit",
+   .access = SNDRV_CTL_ELEM_ACCESS_READ |
+   SNDRV_CTL_ELEM_ACCESS_WRITE |
+   SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+   .info = fsl_spdif_vbit_info,
+   .get = fsl_spdif_tx_vbit_get,
+   .put = fsl_spdif_tx_vbit_put,
},
/* DPLL lock info get controller */
{
-- 
2.21.0



[PATCH 0/2] ASoC: fsl_spdif: Clear the validity bit for TX

2020-07-07 Thread Shengjiu Wang
Clear the validity bit for TX
Add kctl for configuring TX validity bit

Shengjiu Wang (2):
  ASoC: fsl_spdif: Clear the validity bit for TX
  ASoC: fsl_spdif: Add kctl for configuring TX validity bit

 sound/soc/fsl/fsl_spdif.c | 51 ---
 1 file changed, 47 insertions(+), 4 deletions(-)

-- 
2.21.0



[PATCH 1/2] ASoC: fsl_spdif: Clear the validity bit for TX

2020-07-07 Thread Shengjiu Wang
In IEC958 spec, "The validity bit is logical "0" if the
information in the main data field is reliable, and it
is logical "1" if it is not".

The default value of "ValCtrl" is zero, which means
"Outgoing Validity always set", then all the data is not
reliable, then some spdif sink device will drop the data.

So set "ValCtrl" to 1, that is to clear "Outgoing Validity"
in default.

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

diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 9fb95c6ee7ba..576370dc6e70 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -985,6 +985,10 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai)
 
snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, 
ARRAY_SIZE(fsl_spdif_ctrls));
 
+   /*Clear the val bit for Tx*/
+   regmap_update_bits(spdif_private->regmap, REG_SPDIF_SCR,
+  SCR_VAL_MASK, SCR_VAL_CLEAR);
+
return 0;
 }
 
-- 
2.21.0



Re: [PATCH] MAINTAINERS: Add Shengjiu to reviewer list of sound/soc/fsl

2020-07-06 Thread Shengjiu Wang
On Fri, Jul 3, 2020 at 3:33 AM Nicolin Chen  wrote:
>
> Add Shengjiu who's actively working on the latest fsl/nxp audio drivers.
>
> Signed-off-by: Nicolin Chen 
> Cc: Shengjiu Wang 
> ---
> To Shengjiu, please ack if you feel okay with this (your email address too).

Thanks Nicolin for nominating me as a reviewer.

I'd like to use my gmail address "shengjiu.w...@gmail.com".
with this then

Acked-by: Shengjiu Wang 

best regards
wang shengjiu

>
>  MAINTAINERS | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 496fd4eafb68..54aab083bb88 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6956,6 +6956,7 @@ M:Timur Tabi 
>  M: Nicolin Chen 
>  M: Xiubo Li 
>  R: Fabio Estevam 
> +R: Shengjiu Wang 
>  L: alsa-de...@alsa-project.org (moderated for non-subscribers)
>  L: linuxppc-dev@lists.ozlabs.org
>  S: Maintained
> --
> 2.17.1
>


[PATCH v3] ASoC: fsl_asrc: Add an option to select internal ratio mode

2020-06-30 Thread Shengjiu Wang
The ASRC not only supports ideal ratio mode, but also supports
internal ratio mode.

For internal rato mode, the rate of clock source should be divided
with no remainder by sample rate, otherwise there is sound
distortion.

Add function fsl_asrc_select_clk() to find proper clock source for
internal ratio mode, if the clock source is available then internal
ratio mode will be selected.

With change, the ideal ratio mode is not the only option for user.

Signed-off-by: Shengjiu Wang 
---
changes in v3
- convert fsl_asrc_select_clk to void type

changes in v2
- update according to Nicolin's comments

 sound/soc/fsl/fsl_asrc.c | 46 ++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 95f6a9617b0b..462ce9f9ab48 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -582,11 +582,51 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream 
*substream,
SNDRV_PCM_HW_PARAM_RATE, _asrc_rate_constraints);
 }
 
+/* Select proper clock source for internal ratio mode */
+static void fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv,
+   struct fsl_asrc_pair *pair,
+   int in_rate,
+   int out_rate)
+{
+   struct fsl_asrc_pair_priv *pair_priv = pair->private;
+   struct asrc_config *config = pair_priv->config;
+   int rate[2], select_clk[2]; /* Array size 2 means IN and OUT */
+   int clk_rate, clk_index;
+   int i = 0, j = 0;
+
+   rate[IN] = in_rate;
+   rate[OUT] = out_rate;
+
+   /* Select proper clock source for internal ratio mode */
+   for (j = 0; j < 2; j++) {
+   for (i = 0; i < ASRC_CLK_MAP_LEN; i++) {
+   clk_index = asrc_priv->clk_map[j][i];
+   clk_rate = 
clk_get_rate(asrc_priv->asrck_clk[clk_index]);
+   /* Only match a perfect clock source with no remainder 
*/
+   if (clk_rate != 0 && (clk_rate / rate[j]) <= 1024 &&
+   (clk_rate % rate[j]) == 0)
+   break;
+   }
+
+   select_clk[j] = i;
+   }
+
+   /* Switch to ideal ratio mode if there is no proper clock source */
+   if (select_clk[IN] == ASRC_CLK_MAP_LEN || select_clk[OUT] == 
ASRC_CLK_MAP_LEN) {
+   select_clk[IN] = INCLK_NONE;
+   select_clk[OUT] = OUTCLK_ASRCK1_CLK;
+   }
+
+   config->inclk = select_clk[IN];
+   config->outclk = select_clk[OUT];
+}
+
 static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
  struct snd_pcm_hw_params *params,
  struct snd_soc_dai *dai)
 {
struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai);
+   struct fsl_asrc_priv *asrc_priv = asrc->private;
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
struct fsl_asrc_pair_priv *pair_priv = pair->private;
@@ -605,8 +645,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream 
*substream,
 
config.pair = pair->index;
config.channel_num = channels;
-   config.inclk = INCLK_NONE;
-   config.outclk = OUTCLK_ASRCK1_CLK;
 
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
config.input_format   = params_format(params);
@@ -620,6 +658,10 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream 
*substream,
config.output_sample_rate = rate;
}
 
+   fsl_asrc_select_clk(asrc_priv, pair,
+   config.input_sample_rate,
+   config.output_sample_rate);
+
ret = fsl_asrc_config_pair(pair, false);
if (ret) {
dev_err(dai->dev, "fail to config asrc pair\n");
-- 
2.21.0



Re: [PATCH] ASoC: fsl_asrc: Add an option to select internal ratio mode

2020-06-30 Thread Shengjiu Wang
On Tue, Jun 30, 2020 at 8:38 PM Fabio Estevam  wrote:
>
> Hi Shengjiu,
>
> On Mon, Jun 29, 2020 at 11:10 AM Shengjiu Wang  wrote:
>
> > +/**
>
> "/**" notation may confuse 'make htmldocs". Since this is a single
> line comment you could do:
>
> /* Select proper clock source for internal ratio mode */
>
>
> > + * Select proper clock source for internal ratio mode
> > + */
> > +static int fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv,
> > +  struct fsl_asrc_pair *pair,
> > +  int in_rate,
> > +  int out_rate)
> > +{
> > +   struct fsl_asrc_pair_priv *pair_priv = pair->private;
> > +   struct asrc_config *config = pair_priv->config;
> > +   int rate[2], select_clk[2]; /* Array size 2 means IN and OUT */
> > +   int clk_rate, clk_index;
> > +   int i = 0, j = 0;
> > +   bool clk_sel[2];
> > +
> > +   rate[0] = in_rate;
> > +   rate[1] = out_rate;
> > +
> > +   /* Select proper clock source for internal ratio mode */
> > +   for (j = 0; j < 2; j++) {
> > +   for (i = 0; i < ASRC_CLK_MAP_LEN; i++) {
> > +   clk_index = asrc_priv->clk_map[j][i];
> > +   clk_rate = 
> > clk_get_rate(asrc_priv->asrck_clk[clk_index]);
> > +   if (clk_rate != 0 && (clk_rate / rate[j]) <= 1024 &&
> > +   (clk_rate % rate[j]) == 0)
> > +   break;
> > +   }
> > +
> > +   if (i == ASRC_CLK_MAP_LEN) {
> > +   select_clk[j] = OUTCLK_ASRCK1_CLK;
> > +   clk_sel[j] = false;
> > +   } else {
> > +   select_clk[j] = i;
> > +   clk_sel[j] = true;
> > +   }
> > +   }
> > +
> > +   /* Switch to ideal ratio mode if there is no proper clock source */
> > +   if (!clk_sel[IN] || !clk_sel[OUT])
> > +   select_clk[IN] = INCLK_NONE;
> > +
> > +   config->inclk = select_clk[IN];
> > +   config->outclk = select_clk[OUT];
> > +
> > +   return 0;
>
> This new function always returns 0. Should it be converted to 'void'
> type instead?
>
> > +   ret = fsl_asrc_select_clk(asrc_priv, pair,
> > + config.input_sample_rate,
> > + config.output_sample_rate);
> > +   if (ret) {
> > +   dev_err(dai->dev, "fail to select clock\n");
>
> fsl_asrc_select_clk() does not return error, so you could skip the
> error checking.

ok, will update the patch

best regards
wang shengjiu


[PATCH v2] ASoC: fsl_asrc: Add an option to select internal ratio mode

2020-06-30 Thread Shengjiu Wang
The ASRC not only supports ideal ratio mode, but also supports
internal ratio mode.

For internal rato mode, the rate of clock source should be divided
with no remainder by sample rate, otherwise there is sound
distortion.

Add function fsl_asrc_select_clk() to find proper clock source for
internal ratio mode, if the clock source is available then internal
ratio mode will be selected.

With change, the ideal ratio mode is not the only option for user.

Signed-off-by: Shengjiu Wang 
---
changes in v2
- update according to Nicolin's comments

 sound/soc/fsl/fsl_asrc.c | 54 ++--
 1 file changed, 52 insertions(+), 2 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 95f6a9617b0b..4105ef2c4f99 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -582,11 +582,55 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream 
*substream,
SNDRV_PCM_HW_PARAM_RATE, _asrc_rate_constraints);
 }
 
+/**
+ * Select proper clock source for internal ratio mode
+ */
+static int fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv,
+  struct fsl_asrc_pair *pair,
+  int in_rate,
+  int out_rate)
+{
+   struct fsl_asrc_pair_priv *pair_priv = pair->private;
+   struct asrc_config *config = pair_priv->config;
+   int rate[2], select_clk[2]; /* Array size 2 means IN and OUT */
+   int clk_rate, clk_index;
+   int i = 0, j = 0;
+
+   rate[0] = in_rate;
+   rate[1] = out_rate;
+
+   /* Select proper clock source for internal ratio mode */
+   for (j = 0; j < 2; j++) {
+   for (i = 0; i < ASRC_CLK_MAP_LEN; i++) {
+   clk_index = asrc_priv->clk_map[j][i];
+   clk_rate = 
clk_get_rate(asrc_priv->asrck_clk[clk_index]);
+   /* Only match a perfect clock source with no remainder 
*/
+   if (clk_rate != 0 && (clk_rate / rate[j]) <= 1024 &&
+   (clk_rate % rate[j]) == 0)
+   break;
+   }
+
+   select_clk[j] = i;
+   }
+
+   /* Switch to ideal ratio mode if there is no proper clock source */
+   if (select_clk[IN] == ASRC_CLK_MAP_LEN || select_clk[OUT] == 
ASRC_CLK_MAP_LEN) {
+   select_clk[IN] = INCLK_NONE;
+   select_clk[OUT] = OUTCLK_ASRCK1_CLK;
+   }
+
+   config->inclk = select_clk[IN];
+   config->outclk = select_clk[OUT];
+
+   return 0;
+}
+
 static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
  struct snd_pcm_hw_params *params,
  struct snd_soc_dai *dai)
 {
struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai);
+   struct fsl_asrc_priv *asrc_priv = asrc->private;
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
struct fsl_asrc_pair_priv *pair_priv = pair->private;
@@ -605,8 +649,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream 
*substream,
 
config.pair = pair->index;
config.channel_num = channels;
-   config.inclk = INCLK_NONE;
-   config.outclk = OUTCLK_ASRCK1_CLK;
 
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
config.input_format   = params_format(params);
@@ -620,6 +662,14 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream 
*substream,
config.output_sample_rate = rate;
}
 
+   ret = fsl_asrc_select_clk(asrc_priv, pair,
+ config.input_sample_rate,
+ config.output_sample_rate);
+   if (ret) {
+   dev_err(dai->dev, "fail to select clock\n");
+   return ret;
+   }
+
ret = fsl_asrc_config_pair(pair, false);
if (ret) {
dev_err(dai->dev, "fail to config asrc pair\n");
-- 
2.21.0



Re: [PATCH] ASoC: fsl_asrc: Add an option to select internal ratio mode

2020-06-29 Thread Shengjiu Wang
On Tue, Jun 30, 2020 at 4:09 AM Nicolin Chen  wrote:
>
> On Mon, Jun 29, 2020 at 09:58:35PM +0800, Shengjiu Wang wrote:
> > The ASRC not only supports ideal ratio mode, but also supports
> > internal ratio mode.
> >
> > For internal rato mode, the rate of clock source should be divided
> > with no remainder by sample rate, otherwise there is sound
> > distortion.
> >
> > Add function fsl_asrc_select_clk() to find proper clock source for
> > internal ratio mode, if the clock source is available then internal
> > ratio mode will be selected.
> >
> > With change, the ideal ratio mode is not the only option for user.
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
>
> > +static int fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv,
> > +struct fsl_asrc_pair *pair,
> > +int in_rate,
> > +int out_rate)
> > +{
> > + struct fsl_asrc_pair_priv *pair_priv = pair->private;
> > + struct asrc_config *config = pair_priv->config;
> > + int rate[2], select_clk[2]; /* Array size 2 means IN and OUT */
> > + int clk_rate, clk_index;
> > + int i = 0, j = 0;
> > + bool clk_sel[2];
> > +
> > + rate[0] = in_rate;
> > + rate[1] = out_rate;
> > +
> > + /* Select proper clock source for internal ratio mode */
> > + for (j = 0; j < 2; j++) {
> > + for (i = 0; i < ASRC_CLK_MAP_LEN; i++) {
> > + clk_index = asrc_priv->clk_map[j][i];
> > + clk_rate = 
> > clk_get_rate(asrc_priv->asrck_clk[clk_index]);
>
> +   /* Only match a perfect clock source with no 
> remainder */
>
> > + if (clk_rate != 0 && (clk_rate / rate[j]) <= 1024 &&
> > + (clk_rate % rate[j]) == 0)
> > + break;
> > + }
> > +
> > + if (i == ASRC_CLK_MAP_LEN) {
> > + select_clk[j] = OUTCLK_ASRCK1_CLK;
> > + clk_sel[j] = false;
> > + } else {
> > + select_clk[j] = i;
> > + clk_sel[j] = true;
> > + }
> > + }
> > +
> > + /* Switch to ideal ratio mode if there is no proper clock source */
> > + if (!clk_sel[IN] || !clk_sel[OUT])
> > + select_clk[IN] = INCLK_NONE;
>
> Could get rid of clk_set:
>
> for (j) {
> for (i) {
> if (match)
> break;
> }
>
> clk[j] = i;
> }
>
> if (clk[IN] == ASRC_CLK_MAP_LEN || clk[OUT] == ASRC_CLK_MAP_LEN)
>
> And it only overrides clk[IN] setting but leaving clk[OUT] to
> to the searching result. This means that clk[OUT] may be using
> a clock source other than OUTCLK_ASRCK1_CLK if sel[IN] happens
> to be false while sel[OUT] happens to be true. Not sure if it
> is intended...but I feel it would probably be safer to use the
> previous settings: INCLK_NONE + OUTCLK_ASRCK1_CLK?

ok, will update the patch.

best regards
wang shengjiu


[PATCH] ASoC: fsl_asrc: Add an option to select internal ratio mode

2020-06-29 Thread Shengjiu Wang
The ASRC not only supports ideal ratio mode, but also supports
internal ratio mode.

For internal rato mode, the rate of clock source should be divided
with no remainder by sample rate, otherwise there is sound
distortion.

Add function fsl_asrc_select_clk() to find proper clock source for
internal ratio mode, if the clock source is available then internal
ratio mode will be selected.

With change, the ideal ratio mode is not the only option for user.

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

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 95f6a9617b0b..fcafc8ecb131 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -582,11 +582,59 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream 
*substream,
SNDRV_PCM_HW_PARAM_RATE, _asrc_rate_constraints);
 }
 
+/**
+ * Select proper clock source for internal ratio mode
+ */
+static int fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv,
+  struct fsl_asrc_pair *pair,
+  int in_rate,
+  int out_rate)
+{
+   struct fsl_asrc_pair_priv *pair_priv = pair->private;
+   struct asrc_config *config = pair_priv->config;
+   int rate[2], select_clk[2]; /* Array size 2 means IN and OUT */
+   int clk_rate, clk_index;
+   int i = 0, j = 0;
+   bool clk_sel[2];
+
+   rate[0] = in_rate;
+   rate[1] = out_rate;
+
+   /* Select proper clock source for internal ratio mode */
+   for (j = 0; j < 2; j++) {
+   for (i = 0; i < ASRC_CLK_MAP_LEN; i++) {
+   clk_index = asrc_priv->clk_map[j][i];
+   clk_rate = 
clk_get_rate(asrc_priv->asrck_clk[clk_index]);
+   if (clk_rate != 0 && (clk_rate / rate[j]) <= 1024 &&
+   (clk_rate % rate[j]) == 0)
+   break;
+   }
+
+   if (i == ASRC_CLK_MAP_LEN) {
+   select_clk[j] = OUTCLK_ASRCK1_CLK;
+   clk_sel[j] = false;
+   } else {
+   select_clk[j] = i;
+   clk_sel[j] = true;
+   }
+   }
+
+   /* Switch to ideal ratio mode if there is no proper clock source */
+   if (!clk_sel[IN] || !clk_sel[OUT])
+   select_clk[IN] = INCLK_NONE;
+
+   config->inclk = select_clk[IN];
+   config->outclk = select_clk[OUT];
+
+   return 0;
+}
+
 static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
  struct snd_pcm_hw_params *params,
  struct snd_soc_dai *dai)
 {
struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai);
+   struct fsl_asrc_priv *asrc_priv = asrc->private;
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
struct fsl_asrc_pair_priv *pair_priv = pair->private;
@@ -605,8 +653,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream 
*substream,
 
config.pair = pair->index;
config.channel_num = channels;
-   config.inclk = INCLK_NONE;
-   config.outclk = OUTCLK_ASRCK1_CLK;
 
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
config.input_format   = params_format(params);
@@ -620,6 +666,14 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream 
*substream,
config.output_sample_rate = rate;
}
 
+   ret = fsl_asrc_select_clk(asrc_priv, pair,
+ config.input_sample_rate,
+ config.output_sample_rate);
+   if (ret) {
+   dev_err(dai->dev, "fail to select clock\n");
+   return ret;
+   }
+
ret = fsl_asrc_config_pair(pair, false);
if (ret) {
dev_err(dai->dev, "fail to config asrc pair\n");
-- 
2.21.0



[PATCH] ASoC: fsl_sai: Refine regcache usage with pm runtime

2020-06-29 Thread Shengjiu Wang
When there is dedicated power domain bound with device, after probing
the power will be disabled, then registers are not accessible in
fsl_sai_dai_probe(), so regcache only need to be enabled in end of
probe() and regcache_mark_dirty should be moved to pm runtime resume
callback function.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_sai.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 9d436b0c5718..a22562f2df47 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -1016,6 +1016,7 @@ static int fsl_sai_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, sai);
 
pm_runtime_enable(>dev);
+   regcache_cache_only(sai->regmap, true);
 
ret = devm_snd_soc_register_component(>dev, _component,
_sai_dai, 1);
@@ -1107,7 +1108,6 @@ static int fsl_sai_runtime_suspend(struct device *dev)
clk_disable_unprepare(sai->bus_clk);
 
regcache_cache_only(sai->regmap, true);
-   regcache_mark_dirty(sai->regmap);
 
return 0;
 }
@@ -1137,6 +1137,7 @@ static int fsl_sai_runtime_resume(struct device *dev)
}
 
regcache_cache_only(sai->regmap, false);
+   regcache_mark_dirty(sai->regmap);
regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
usleep_range(1000, 2000);
-- 
2.21.0



Re: [PATCH v2 1/2] ASoC: fsl_mqs: Don't check clock is NULL before calling clk API

2020-06-23 Thread Shengjiu Wang
On Tue, Jun 23, 2020 at 4:55 PM Markus Elfring  wrote:
>
> > clk_prepare_enable and clk_disable_unprepare check the input
> > clock parameter in the beginning of the function,
>
> These functions call further functions which perform null pointer checks.
>
>
> >   if the parameter
> > is NULL, clk_prepare_enable and clk_disable_unprepare will
> > return immediately.
>
> The interpretation of these function implementations seems to be reasonable.
> Would you like to achieve any improvements for the corresponding software 
> documentation?

Which document do you mean?

>
>
> > So Don't need to check input clock parameters before calling clk API.
>
> What do you find imperative in this wording?
>
> Another wording alternative:
>Thus omit extra null pointer checks before four function calls.
>
> Regards,
> Markus


Re: [PATCH v2 1/2] ASoC: fsl_mqs: Don't check clock is NULL before calling clk API

2020-06-23 Thread Shengjiu Wang
On Tue, Jun 23, 2020 at 3:38 PM Markus Elfring  wrote:
>
> > In-Reply-To: 
>
> I guess that it should be sufficient to specify such a field once
> for the header information.

seems it's caused by my "git format-patch" command, I will update
it, hope it is better next time.

>
>
> > Because clk_prepare_enable and clk_disable_unprepare should
> > check input clock parameter is NULL or not internally,
>
> I find this change description unclear.

clk_prepare_enable and clk_disable_unprepare check the input
clock parameter in the beginning of the function, if the parameter
is NULL, clk_prepare_enable and clk_disable_unprepare will
return immediately.

So Don't need to check input clock parameters before calling clk
API.

Do you think this commit message is better?

best regards
wang shengjiu


[PATCH 1/2] ASoC: fsl-asoc-card: Add WM8524 support

2020-06-23 Thread Shengjiu Wang
WM8524 only supports playback mode, and only works at
slave mode.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl-asoc-card.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index d0543a53764e..57ea1b072326 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -611,6 +611,15 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
priv->dai_link[2].dpcm_capture = 0;
priv->card.dapm_routes = audio_map_tx;
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
+   } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8524")) {
+   codec_dai_name = "wm8524-hifi";
+   priv->card.set_bias_level = NULL;
+   priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
+   priv->dai_link[1].dpcm_capture = 0;
+   priv->dai_link[2].dpcm_capture = 0;
+   priv->cpu_priv.slot_width = 32;
+   priv->card.dapm_routes = audio_map_tx;
+   priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
} else {
dev_err(>dev, "unknown Device Tree compatible\n");
ret = -EINVAL;
@@ -760,6 +769,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = {
{ .compatible = "fsl,imx-audio-wm8962", },
{ .compatible = "fsl,imx-audio-wm8960", },
{ .compatible = "fsl,imx-audio-mqs", },
+   { .compatible = "fsl,imx-audio-wm8524", },
{}
 };
 MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids);
-- 
2.21.0



[PATCH 2/2] ASoC: bindings: fsl-asoc-card: Add compatible string for wm8524

2020-06-23 Thread Shengjiu Wang
In order to support wm8524 codec with fsl-asoc-card machine
driver, add compatible string "fsl,imx-audio-wm8524".

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 ca9a3a43adfd..133d7e14a4d0 100644
--- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
+++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
@@ -36,6 +36,8 @@ The compatible list for this generic sound card currently:
 
  "fsl,imx-audio-mqs"
 
+ "fsl,imx-audio-wm8524"
+
 Required properties:
 
   - compatible : Contains one of entries in the compatible list.
-- 
2.21.0



[PATCH v2 2/2] ASoC: fsl_mqs: Fix unchecked return value for clk_prepare_enable

2020-06-23 Thread Shengjiu Wang
Fix unchecked return value for clk_prepare_enable, add error
handler in fsl_mqs_runtime_resume.

Fixes: 9e28f6532c61 ("ASoC: fsl_mqs: Add MQS component driver")
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_mqs.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c
index b44b134390a3..69aeb0e71844 100644
--- a/sound/soc/fsl/fsl_mqs.c
+++ b/sound/soc/fsl/fsl_mqs.c
@@ -265,10 +265,20 @@ static int fsl_mqs_remove(struct platform_device *pdev)
 static int fsl_mqs_runtime_resume(struct device *dev)
 {
struct fsl_mqs *mqs_priv = dev_get_drvdata(dev);
+   int ret;
 
-   clk_prepare_enable(mqs_priv->ipg);
+   ret = clk_prepare_enable(mqs_priv->ipg);
+   if (ret) {
+   dev_err(dev, "failed to enable ipg clock\n");
+   return ret;
+   }
 
-   clk_prepare_enable(mqs_priv->mclk);
+   ret = clk_prepare_enable(mqs_priv->mclk);
+   if (ret) {
+   dev_err(dev, "failed to enable mclk clock\n");
+   clk_disable_unprepare(mqs_priv->ipg);
+   return ret;
+   }
 
if (mqs_priv->use_gpr)
regmap_write(mqs_priv->regmap, IOMUXC_GPR2,
-- 
2.21.0



[PATCH v2 1/2] ASoC: fsl_mqs: Don't check clock is NULL before calling clk API

2020-06-23 Thread Shengjiu Wang
Because clk_prepare_enable and clk_disable_unprepare should
check input clock parameter is NULL or not internally, then
we don't need to check them before calling the function.

Fixes: 9e28f6532c61 ("ASoC: fsl_mqs: Add MQS component driver")
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_mqs.c | 13 -
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c
index 0c813a45bba7..b44b134390a3 100644
--- a/sound/soc/fsl/fsl_mqs.c
+++ b/sound/soc/fsl/fsl_mqs.c
@@ -266,11 +266,9 @@ static int fsl_mqs_runtime_resume(struct device *dev)
 {
struct fsl_mqs *mqs_priv = dev_get_drvdata(dev);
 
-   if (mqs_priv->ipg)
-   clk_prepare_enable(mqs_priv->ipg);
+   clk_prepare_enable(mqs_priv->ipg);
 
-   if (mqs_priv->mclk)
-   clk_prepare_enable(mqs_priv->mclk);
+   clk_prepare_enable(mqs_priv->mclk);
 
if (mqs_priv->use_gpr)
regmap_write(mqs_priv->regmap, IOMUXC_GPR2,
@@ -292,11 +290,8 @@ static int fsl_mqs_runtime_suspend(struct device *dev)
regmap_read(mqs_priv->regmap, REG_MQS_CTRL,
_priv->reg_mqs_ctrl);
 
-   if (mqs_priv->mclk)
-   clk_disable_unprepare(mqs_priv->mclk);
-
-   if (mqs_priv->ipg)
-   clk_disable_unprepare(mqs_priv->ipg);
+   clk_disable_unprepare(mqs_priv->mclk);
+   clk_disable_unprepare(mqs_priv->ipg);
 
return 0;
 }
-- 
2.21.0



[PATCH v2 0/2] Fix unchecked return value for clk_prepare_enable

2020-06-23 Thread Shengjiu Wang
First patch is to remove the check of clock pointer before calling
clk API.

Second patch is to fix the issue that the return value of
clk_prepare_enable is not checked.

changes in v2:
- split the patch to separate patches

Shengjiu Wang (2):
  ASoC: fsl_mqs: Don't check clock is NULL before calling clk API
  ASoC: fsl_mqs: Fix unchecked return value for clk_prepare_enable

 sound/soc/fsl/fsl_mqs.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

-- 
2.21.0



Re: [PATCH] ASoC: fsl_mqs: Fix unchecked return value for clk_prepare_enable

2020-06-22 Thread Shengjiu Wang
On Tue, Jun 23, 2020 at 12:08 AM Markus Elfring  wrote:
>
> > Fix unchecked return value for clk_prepare_enable.
> >
> > And because clk_prepare_enable and clk_disable_unprepare should
> > check input clock parameter is NULL or not, then we don't need
> > to check it before calling the function.
>
> I propose to split the adjustment of two function implementations
> into separate update steps for a small patch series.
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?id=625d3449788f85569096780592549d0340e9c0c7#n138
>
> I suggest to improve the change descriptions accordingly.

ok, will update the patches in v2.

best regards
wang shengjiu


[PATCH] ASoC: fsl_easrc: Fix uninitialized scalar variable in fsl_easrc_set_ctx_format

2020-06-22 Thread Shengjiu Wang
The "ret" in fsl_easrc_set_ctx_format is not initialized, then
the unknown value maybe returned by this function.

Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers")
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_easrc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 2f6b3d8bfcfc..03b3aef41d34 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1132,7 +1132,7 @@ static int fsl_easrc_set_ctx_format(struct fsl_asrc_pair 
*ctx,
struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
struct fsl_easrc_data_fmt *in_fmt = _priv->in_params.fmt;
struct fsl_easrc_data_fmt *out_fmt = _priv->out_params.fmt;
-   int ret;
+   int ret = 0;
 
/* Get the bitfield values for input data format */
if (in_raw_format && out_raw_format) {
-- 
2.21.0



[PATCH] ASoC: fsl_mqs: Fix unchecked return value for clk_prepare_enable

2020-06-22 Thread Shengjiu Wang
Fix unchecked return value for clk_prepare_enable.

And because clk_prepare_enable and clk_disable_unprepare should
check input clock parameter is NULL or not, then we don't need
to check it before calling the function.

Fixes: 9e28f6532c61 ("ASoC: fsl_mqs: Add MQS component driver")
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_mqs.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c
index 0c813a45bba7..69aeb0e71844 100644
--- a/sound/soc/fsl/fsl_mqs.c
+++ b/sound/soc/fsl/fsl_mqs.c
@@ -265,12 +265,20 @@ static int fsl_mqs_remove(struct platform_device *pdev)
 static int fsl_mqs_runtime_resume(struct device *dev)
 {
struct fsl_mqs *mqs_priv = dev_get_drvdata(dev);
+   int ret;
 
-   if (mqs_priv->ipg)
-   clk_prepare_enable(mqs_priv->ipg);
+   ret = clk_prepare_enable(mqs_priv->ipg);
+   if (ret) {
+   dev_err(dev, "failed to enable ipg clock\n");
+   return ret;
+   }
 
-   if (mqs_priv->mclk)
-   clk_prepare_enable(mqs_priv->mclk);
+   ret = clk_prepare_enable(mqs_priv->mclk);
+   if (ret) {
+   dev_err(dev, "failed to enable mclk clock\n");
+   clk_disable_unprepare(mqs_priv->ipg);
+   return ret;
+   }
 
if (mqs_priv->use_gpr)
regmap_write(mqs_priv->regmap, IOMUXC_GPR2,
@@ -292,11 +300,8 @@ static int fsl_mqs_runtime_suspend(struct device *dev)
regmap_read(mqs_priv->regmap, REG_MQS_CTRL,
_priv->reg_mqs_ctrl);
 
-   if (mqs_priv->mclk)
-   clk_disable_unprepare(mqs_priv->mclk);
-
-   if (mqs_priv->ipg)
-   clk_disable_unprepare(mqs_priv->ipg);
+   clk_disable_unprepare(mqs_priv->mclk);
+   clk_disable_unprepare(mqs_priv->ipg);
 
return 0;
 }
-- 
2.21.0



[PATCH v2] ASoC: fsl_spdif: Add pm runtime function

2020-06-19 Thread Shengjiu Wang
Add pm runtime support and move clock handling there.
Close the clocks at suspend to reduce the power consumption.

fsl_spdif_suspend is replaced by pm_runtime_force_suspend.
fsl_spdif_resume is replaced by pm_runtime_force_resume.

Signed-off-by: Shengjiu Wang 
Acked-by: Nicolin Chen 
---
changes in v2
- remove goto in startup()
- remove goto disable_spba_clk
- Add Acked-by: Nicolin Chen

 sound/soc/fsl/fsl_spdif.c | 117 ++
 1 file changed, 67 insertions(+), 50 deletions(-)

diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 5bc0e4729341..5b2689ae63d4 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -495,29 +496,14 @@ static int fsl_spdif_startup(struct snd_pcm_substream 
*substream,
struct platform_device *pdev = spdif_priv->pdev;
struct regmap *regmap = spdif_priv->regmap;
u32 scr, mask;
-   int i;
int ret;
 
/* Reset module and interrupts only for first initialization */
if (!snd_soc_dai_active(cpu_dai)) {
-   ret = clk_prepare_enable(spdif_priv->coreclk);
-   if (ret) {
-   dev_err(>dev, "failed to enable core clock\n");
-   return ret;
-   }
-
-   if (!IS_ERR(spdif_priv->spbaclk)) {
-   ret = clk_prepare_enable(spdif_priv->spbaclk);
-   if (ret) {
-   dev_err(>dev, "failed to enable spba 
clock\n");
-   goto err_spbaclk;
-   }
-   }
-
ret = spdif_softreset(spdif_priv);
if (ret) {
dev_err(>dev, "failed to soft reset\n");
-   goto err;
+   return ret;
}
 
/* Disable all the interrupts */
@@ -531,18 +517,10 @@ static int fsl_spdif_startup(struct snd_pcm_substream 
*substream,
mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK |
SCR_TXSEL_MASK | SCR_USRC_SEL_MASK |
SCR_TXFIFO_FSEL_MASK;
-   for (i = 0; i < SPDIF_TXRATE_MAX; i++) {
-   ret = clk_prepare_enable(spdif_priv->txclk[i]);
-   if (ret)
-   goto disable_txclk;
-   }
} else {
scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC;
mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK|
SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK;
-   ret = clk_prepare_enable(spdif_priv->rxclk);
-   if (ret)
-   goto err;
}
regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr);
 
@@ -550,17 +528,6 @@ static int fsl_spdif_startup(struct snd_pcm_substream 
*substream,
regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_LOW_POWER, 0);
 
return 0;
-
-disable_txclk:
-   for (i--; i >= 0; i--)
-   clk_disable_unprepare(spdif_priv->txclk[i]);
-err:
-   if (!IS_ERR(spdif_priv->spbaclk))
-   clk_disable_unprepare(spdif_priv->spbaclk);
-err_spbaclk:
-   clk_disable_unprepare(spdif_priv->coreclk);
-
-   return ret;
 }
 
 static void fsl_spdif_shutdown(struct snd_pcm_substream *substream,
@@ -569,20 +536,17 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream 
*substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_spdif_priv *spdif_priv = 
snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
struct regmap *regmap = spdif_priv->regmap;
-   u32 scr, mask, i;
+   u32 scr, mask;
 
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
scr = 0;
mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK |
SCR_TXSEL_MASK | SCR_USRC_SEL_MASK |
SCR_TXFIFO_FSEL_MASK;
-   for (i = 0; i < SPDIF_TXRATE_MAX; i++)
-   clk_disable_unprepare(spdif_priv->txclk[i]);
} else {
scr = SCR_RXFIFO_OFF | SCR_RXFIFO_CTL_ZERO;
mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK|
SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK;
-   clk_disable_unprepare(spdif_priv->rxclk);
}
regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr);
 
@@ -591,9 +555,6 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream 
*substream,
spdif_intr_status_clear(spdif_priv);
regmap_update_bits(regmap, REG_SPDIF_SCR,
SCR_LOW_POWER, SCR_LOW_POWER);
-   if (!IS_ERR(spdif_priv->spbaclk))
-   cl

Re: [PATCH] ASoC: fsl_spdif: Add pm runtime function

2020-06-19 Thread Shengjiu Wang
On Fri, Jun 19, 2020 at 1:51 PM Nicolin Chen  wrote:
>
> On Thu, Jun 18, 2020 at 07:55:34PM +0800, Shengjiu Wang wrote:
> > Add pm runtime support and move clock handling there.
> > Close the clocks at suspend to reduce the power consumption.
> >
> > fsl_spdif_suspend is replaced by pm_runtime_force_suspend.
> > fsl_spdif_resume is replaced by pm_runtime_force_resume.
> >
> > Signed-off-by: Shengjiu Wang 
>
> LGTM, yet some nits, please add my ack after fixing:
>
> Acked-by: Nicolin Chen 
>
> > @@ -495,25 +496,10 @@ static int fsl_spdif_startup(struct snd_pcm_substream 
> > *substream,
>
> >
> > -disable_txclk:
> > - for (i--; i >= 0; i--)
> > - clk_disable_unprepare(spdif_priv->txclk[i]);
> >  err:
> > - if (!IS_ERR(spdif_priv->spbaclk))
> > - clk_disable_unprepare(spdif_priv->spbaclk);
> > -err_spbaclk:
> > - clk_disable_unprepare(spdif_priv->coreclk);
> > -
> >   return ret;
>
> Only "return ret;" remains now. We could clean the goto away.
>
> > -static int fsl_spdif_resume(struct device *dev)
> > +static int fsl_spdif_runtime_resume(struct device *dev)
>
> > +disable_rx_clk:
> > + clk_disable_unprepare(spdif_priv->rxclk);
> > +disable_tx_clk:
> > +disable_spba_clk:
>
> Why have two duplicated ones? Could probably drop the 2nd one.

seems can drop one, will send an update.

best regards
wang shengjiu


[PATCH] ASoC: fsl_spdif: Add pm runtime function

2020-06-18 Thread Shengjiu Wang
Add pm runtime support and move clock handling there.
Close the clocks at suspend to reduce the power consumption.

fsl_spdif_suspend is replaced by pm_runtime_force_suspend.
fsl_spdif_resume is replaced by pm_runtime_force_resume.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_spdif.c | 113 ++
 1 file changed, 67 insertions(+), 46 deletions(-)

diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 5bc0e4729341..46719fd2f1ec 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -495,25 +496,10 @@ static int fsl_spdif_startup(struct snd_pcm_substream 
*substream,
struct platform_device *pdev = spdif_priv->pdev;
struct regmap *regmap = spdif_priv->regmap;
u32 scr, mask;
-   int i;
int ret;
 
/* Reset module and interrupts only for first initialization */
if (!snd_soc_dai_active(cpu_dai)) {
-   ret = clk_prepare_enable(spdif_priv->coreclk);
-   if (ret) {
-   dev_err(>dev, "failed to enable core clock\n");
-   return ret;
-   }
-
-   if (!IS_ERR(spdif_priv->spbaclk)) {
-   ret = clk_prepare_enable(spdif_priv->spbaclk);
-   if (ret) {
-   dev_err(>dev, "failed to enable spba 
clock\n");
-   goto err_spbaclk;
-   }
-   }
-
ret = spdif_softreset(spdif_priv);
if (ret) {
dev_err(>dev, "failed to soft reset\n");
@@ -531,18 +517,10 @@ static int fsl_spdif_startup(struct snd_pcm_substream 
*substream,
mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK |
SCR_TXSEL_MASK | SCR_USRC_SEL_MASK |
SCR_TXFIFO_FSEL_MASK;
-   for (i = 0; i < SPDIF_TXRATE_MAX; i++) {
-   ret = clk_prepare_enable(spdif_priv->txclk[i]);
-   if (ret)
-   goto disable_txclk;
-   }
} else {
scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC;
mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK|
SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK;
-   ret = clk_prepare_enable(spdif_priv->rxclk);
-   if (ret)
-   goto err;
}
regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr);
 
@@ -551,15 +529,7 @@ static int fsl_spdif_startup(struct snd_pcm_substream 
*substream,
 
return 0;
 
-disable_txclk:
-   for (i--; i >= 0; i--)
-   clk_disable_unprepare(spdif_priv->txclk[i]);
 err:
-   if (!IS_ERR(spdif_priv->spbaclk))
-   clk_disable_unprepare(spdif_priv->spbaclk);
-err_spbaclk:
-   clk_disable_unprepare(spdif_priv->coreclk);
-
return ret;
 }
 
@@ -569,20 +539,17 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream 
*substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_spdif_priv *spdif_priv = 
snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
struct regmap *regmap = spdif_priv->regmap;
-   u32 scr, mask, i;
+   u32 scr, mask;
 
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
scr = 0;
mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK |
SCR_TXSEL_MASK | SCR_USRC_SEL_MASK |
SCR_TXFIFO_FSEL_MASK;
-   for (i = 0; i < SPDIF_TXRATE_MAX; i++)
-   clk_disable_unprepare(spdif_priv->txclk[i]);
} else {
scr = SCR_RXFIFO_OFF | SCR_RXFIFO_CTL_ZERO;
mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK|
SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK;
-   clk_disable_unprepare(spdif_priv->rxclk);
}
regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr);
 
@@ -591,9 +558,6 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream 
*substream,
spdif_intr_status_clear(spdif_priv);
regmap_update_bits(regmap, REG_SPDIF_SCR,
SCR_LOW_POWER, SCR_LOW_POWER);
-   if (!IS_ERR(spdif_priv->spbaclk))
-   clk_disable_unprepare(spdif_priv->spbaclk);
-   clk_disable_unprepare(spdif_priv->coreclk);
}
 }
 
@@ -1350,6 +1314,8 @@ static int fsl_spdif_probe(struct platform_device *pdev)
 
/* Register with ASoC */
dev_set_drvdata(>dev, spdif_priv);
+   pm_runtime_enable(>dev);
+   regcache_cache_only(spdif_priv->regmap, true);
 
ret = devm_snd_

[PATCH v3 2/2] ASoC: fsl_spdif: Add support for imx6sx platform

2020-06-17 Thread Shengjiu Wang
The one difference on imx6sx platform is that the root clock
is shared with ASRC module, so we add a new flags
"shared_root_clock" which means the root clock is not independent,
then we will not do the clk_set_rate and clk_round_rate to avoid
impact ASRC module usage.

As add a new flags, we include the soc specific data struct.

Signed-off-by: Shengjiu Wang 
Reviewed-by: Nicolin Chen 
---
changes in v3
- refine some comments
- add Reviewed-by: Nicolin Chen

changes in v2
- use shared_root_clk instead ind_root_clk.
- add fsl_spdif_can_set_clk_rate function.

 sound/soc/fsl/fsl_spdif.c | 50 +++
 1 file changed, 45 insertions(+), 5 deletions(-)

diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 1b2e516f9162..5bc0e4729341 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -42,6 +42,18 @@ static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 
0xa, 0xb };
 
 #define DEFAULT_RXCLK_SRC  1
 
+/**
+ * struct fsl_spdif_soc_data: soc specific data
+ *
+ * @imx: for imx platform
+ * @shared_root_clock: flag of sharing a clock source with others;
+ * so the driver shouldn't set root clock rate
+ */
+struct fsl_spdif_soc_data {
+   bool imx;
+   bool shared_root_clock;
+};
+
 /*
  * SPDIF control structure
  * Defines channel status, subcode and Q sub
@@ -89,6 +101,7 @@ struct spdif_mixer_control {
  * @dma_params_rx: DMA parameters for receive channel
  */
 struct fsl_spdif_priv {
+   const struct fsl_spdif_soc_data *soc;
struct spdif_mixer_control fsl_spdif_control;
struct snd_soc_dai_driver cpu_dai_drv;
struct platform_device *pdev;
@@ -110,6 +123,27 @@ struct fsl_spdif_priv {
u32 regcache_srpc;
 };
 
+static struct fsl_spdif_soc_data fsl_spdif_vf610 = {
+   .imx = false,
+   .shared_root_clock = false,
+};
+
+static struct fsl_spdif_soc_data fsl_spdif_imx35 = {
+   .imx = true,
+   .shared_root_clock = false,
+};
+
+static struct fsl_spdif_soc_data fsl_spdif_imx6sx = {
+   .imx = true,
+   .shared_root_clock = true,
+};
+
+/* Check if clk is a root clock that does not share clock source with others */
+static inline bool fsl_spdif_can_set_clk_rate(struct fsl_spdif_priv *spdif, 
int clk)
+{
+   return (clk == STC_TXCLK_SPDIF_ROOT) && !spdif->soc->shared_root_clock;
+}
+
 /* DPLL locked and lock loss interrupt handler */
 static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv)
 {
@@ -420,8 +454,7 @@ static int spdif_set_sample_rate(struct snd_pcm_substream 
*substream,
 
sysclk_df = spdif_priv->sysclk_df[rate];
 
-   /* Don't mess up the clocks from other modules */
-   if (clk != STC_TXCLK_SPDIF_ROOT)
+   if (!fsl_spdif_can_set_clk_rate(spdif_priv, clk))
goto clk_set_bypass;
 
/* The S/PDIF block needs a clock of 64 * fs * txclk_df */
@@ -1186,7 +1219,7 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv 
*spdif_priv,
continue;
 
ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index,
-i == STC_TXCLK_SPDIF_ROOT);
+
fsl_spdif_can_set_clk_rate(spdif_priv, i));
if (savesub == ret)
continue;
 
@@ -1230,6 +1263,12 @@ static int fsl_spdif_probe(struct platform_device *pdev)
 
spdif_priv->pdev = pdev;
 
+   spdif_priv->soc = of_device_get_match_data(>dev);
+   if (!spdif_priv->soc) {
+   dev_err(>dev, "failed to get soc data\n");
+   return -ENODEV;
+   }
+
/* Initialize this copy of the CPU DAI driver structure */
memcpy(_priv->cpu_dai_drv, _spdif_dai, sizeof(fsl_spdif_dai));
spdif_priv->cpu_dai_drv.name = dev_name(>dev);
@@ -1359,8 +1398,9 @@ static const struct dev_pm_ops fsl_spdif_pm = {
 };
 
 static const struct of_device_id fsl_spdif_dt_ids[] = {
-   { .compatible = "fsl,imx35-spdif", },
-   { .compatible = "fsl,vf610-spdif", },
+   { .compatible = "fsl,imx35-spdif", .data = _spdif_imx35, },
+   { .compatible = "fsl,vf610-spdif", .data = _spdif_vf610, },
+   { .compatible = "fsl,imx6sx-spdif", .data = _spdif_imx6sx, },
{}
 };
 MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids);
-- 
2.21.0



[PATCH v3 1/2] ASoC: bindings: fsl_spdif: Add new compatible string for imx6sx

2020-06-17 Thread Shengjiu Wang
Add new compatible string "fsl,imx6sx-spdif" in the binding document.
And add compatible string "fsl,vf610-spdif" which was missed before.

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

diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt 
b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
index 8b324f82a782..e1365b0ee1e9 100644
--- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
@@ -6,7 +6,11 @@ a fibre cable.
 
 Required properties:
 
-  - compatible : Compatible list, must contain "fsl,imx35-spdif".
+  - compatible : Compatible list, should contain one of the following
+ compatibles:
+ "fsl,imx35-spdif",
+ "fsl,vf610-spdif",
+ "fsl,imx6sx-spdif",
 
   - reg: Offset and length of the register set for the 
device.
 
-- 
2.21.0



Re: [PATCH v2 2/2] ASoC: fsl_spdif: Add support for imx6sx platform

2020-06-17 Thread Shengjiu Wang
On Wed, Jun 17, 2020 at 2:27 PM Nicolin Chen  wrote:
>
> On Wed, Jun 17, 2020 at 12:30:17PM +0800, Shengjiu Wang wrote:
> > The one difference on imx6sx platform is that the root clock
> > is shared with ASRC module, so we add a new flags
> > "shared_root_clock" which means the root clock is independent,
>
> "shared" means "not independent", against "independent" ;)
>
> > then we will not do the clk_set_rate and clk_round_rate to avoid
> > impact ASRC module usage.
> >
> > As add a new flags, we include the soc specific data struct.
> >
> > Signed-off-by: Shengjiu Wang 
>
> Can add this once fixing the remaining comments:
>
> Reviewed-by: Nicolin Chen 
>
> > +static inline bool fsl_spdif_can_set_clk_rate(struct fsl_spdif_priv *spdif,
> > +   int clk)
>
> Can actually merge into single line as kernel has 100-character
> limit now, though 80-char is still preferable for a good coding
> style. But I think this one wouldn't be too bad at all.
>
> > @@ -421,7 +456,7 @@ static int spdif_set_sample_rate(struct 
> > snd_pcm_substream *substream,
> >   sysclk_df = spdif_priv->sysclk_df[rate];
> >
> >   /* Don't mess up the clocks from other modules */
>
> We can drop this comments now as it's out-of-date and the name of
> the new helper function is straightforward enough.
>

ok, will send v3.

best regards
wang shengjiu


[PATCH v2 2/2] ASoC: fsl-asoc-card: Add MQS support

2020-06-16 Thread Shengjiu Wang
The MQS codec isn't an i2c device, so use of_find_device_by_node
to get platform device pointer.

Because MQS only support playback, then add a new audio map.

And there maybe "model" property or no "audio-routing" property in
devicetree, so add some enhancement for these two property.

Signed-off-by: Shengjiu Wang 
---
changes in v2
- update according Nicolin's comments.

 sound/soc/fsl/fsl-asoc-card.c | 78 +--
 1 file changed, 57 insertions(+), 21 deletions(-)

diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 00be73900888..d0543a53764e 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -119,6 +119,13 @@ static const struct snd_soc_dapm_route audio_map_ac97[] = {
{"ASRC-Capture",  NULL, "AC97 Capture"},
 };
 
+static const struct snd_soc_dapm_route audio_map_tx[] = {
+   /* 1st half -- Normal DAPM routes */
+   {"Playback",  NULL, "CPU-Playback"},
+   /* 2nd half -- ASRC DAPM routes */
+   {"CPU-Playback",  NULL, "ASRC-Playback"},
+};
+
 /* Add all possible widgets into here without being redundant */
 static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = {
SND_SOC_DAPM_LINE("Line Out Jack", NULL),
@@ -485,8 +492,9 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
struct platform_device *asrc_pdev = NULL;
struct platform_device *cpu_pdev;
struct fsl_asoc_card_priv *priv;
-   struct i2c_client *codec_dev;
+   struct device *codec_dev = NULL;
const char *codec_dai_name;
+   const char *codec_dev_name;
u32 width;
int ret;
 
@@ -512,10 +520,23 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
}
 
codec_np = of_parse_phandle(np, "audio-codec", 0);
-   if (codec_np)
-   codec_dev = of_find_i2c_device_by_node(codec_np);
-   else
-   codec_dev = NULL;
+   if (codec_np) {
+   struct platform_device *codec_pdev;
+   struct i2c_client *codec_i2c;
+
+   codec_i2c = of_find_i2c_device_by_node(codec_np);
+   if (codec_i2c) {
+   codec_dev = _i2c->dev;
+   codec_dev_name = codec_i2c->name;
+   }
+   if (!codec_dev) {
+   codec_pdev = of_find_device_by_node(codec_np);
+   if (codec_pdev) {
+   codec_dev = _pdev->dev;
+   codec_dev_name = codec_pdev->name;
+   }
+   }
+   }
 
asrc_np = of_parse_phandle(np, "audio-asrc", 0);
if (asrc_np)
@@ -523,7 +544,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
 
/* Get the MCLK rate only, and leave it controlled by CODEC drivers */
if (codec_dev) {
-   struct clk *codec_clk = clk_get(_dev->dev, NULL);
+   struct clk *codec_clk = clk_get(codec_dev, NULL);
 
if (!IS_ERR(codec_clk)) {
priv->codec_priv.mclk_freq = clk_get_rate(codec_clk);
@@ -538,6 +559,11 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
/* Assign a default DAI format, and allow each card to overwrite it */
priv->dai_fmt = DAI_FMT_BASE;
 
+   memcpy(priv->dai_link, fsl_asoc_card_dai,
+  sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link));
+
+   priv->card.dapm_routes = audio_map;
+   priv->card.num_dapm_routes = ARRAY_SIZE(audio_map);
/* Diversify the card configurations */
if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) {
codec_dai_name = "cs42888";
@@ -573,6 +599,18 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
codec_dai_name = "ac97-hifi";
priv->card.set_bias_level = NULL;
priv->dai_fmt = SND_SOC_DAIFMT_AC97;
+   priv->card.dapm_routes = audio_map_ac97;
+   priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97);
+   } else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) {
+   codec_dai_name = "fsl-mqs-dai";
+   priv->card.set_bias_level = NULL;
+   priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J |
+   SND_SOC_DAIFMT_CBS_CFS |
+   SND_SOC_DAIFMT_NB_NF;
+   priv->dai_link[1].dpcm_capture = 0;
+   priv->dai_link[2].dpcm_capture = 0;
+   priv->card.dapm_routes = audio_map_tx;
+   priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
} else {
dev_err(>dev, "unknown Device Tree compatible\n");

[PATCH v2 1/2] ASoC: bindings: fsl-asoc-card: Add compatible string for MQS

2020-06-16 Thread Shengjiu Wang
Add compatible string "fsl,imx-audio-mqs" for MQS, and move
"audio-routing" property to be optional for MQS doesn't need
such property.

Signed-off-by: Shengjiu Wang 
---
changes in v2
- Move "audio-routing" to optional.

 .../devicetree/bindings/sound/fsl-asoc-card.txt  | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt 
b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
index c60a5732d29c..ca9a3a43adfd 100644
--- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
+++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
@@ -34,6 +34,8 @@ The compatible list for this generic sound card currently:
 
  "fsl,imx-audio-wm8960"
 
+ "fsl,imx-audio-mqs"
+
 Required properties:
 
   - compatible : Contains one of entries in the compatible list.
@@ -44,6 +46,11 @@ Required properties:
 
   - audio-codec: The phandle of an audio codec
 
+Optional properties:
+
+  - audio-asrc : The phandle of ASRC. It can be absent if there's no
+ need to add ASRC support via DPCM.
+
   - audio-routing  : 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
@@ -60,11 +67,6 @@ Required properties:
coexisting in order to support the old bindings
of wm8962 and sgtl5000.
 
-Optional properties:
-
-  - audio-asrc : The phandle of ASRC. It can be absent if there's no
- need to add ASRC support via DPCM.
-
 Optional unless SSI is selected as a CPU DAI:
 
   - mux-int-port   : The internal port of the i.MX audio muxer (AUDMUX)
-- 
2.21.0



[PATCH v2 2/2] ASoC: fsl_spdif: Add support for imx6sx platform

2020-06-16 Thread Shengjiu Wang
The one difference on imx6sx platform is that the root clock
is shared with ASRC module, so we add a new flags
"shared_root_clock" which means the root clock is independent,
then we will not do the clk_set_rate and clk_round_rate to avoid
impact ASRC module usage.

As add a new flags, we include the soc specific data struct.

Signed-off-by: Shengjiu Wang 
---
changes in v2
- use shared_root_clk instead ind_root_clk.
- add fsl_spdif_can_set_clk_rate function.

 sound/soc/fsl/fsl_spdif.c | 50 +++
 1 file changed, 46 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 1b2e516f9162..8dc1959d0463 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -42,6 +42,18 @@ static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 
0xa, 0xb };
 
 #define DEFAULT_RXCLK_SRC  1
 
+/**
+ * struct fsl_spdif_soc_data: soc specific data
+ *
+ * @imx: for imx platform
+ * @shared_root_clock: flag of sharing a clock source with others;
+ * so the driver shouldn't set root clock rate
+ */
+struct fsl_spdif_soc_data {
+   bool imx;
+   bool shared_root_clock;
+};
+
 /*
  * SPDIF control structure
  * Defines channel status, subcode and Q sub
@@ -89,6 +101,7 @@ struct spdif_mixer_control {
  * @dma_params_rx: DMA parameters for receive channel
  */
 struct fsl_spdif_priv {
+   const struct fsl_spdif_soc_data *soc;
struct spdif_mixer_control fsl_spdif_control;
struct snd_soc_dai_driver cpu_dai_drv;
struct platform_device *pdev;
@@ -110,6 +123,28 @@ struct fsl_spdif_priv {
u32 regcache_srpc;
 };
 
+static struct fsl_spdif_soc_data fsl_spdif_vf610 = {
+   .imx = false,
+   .shared_root_clock = false,
+};
+
+static struct fsl_spdif_soc_data fsl_spdif_imx35 = {
+   .imx = true,
+   .shared_root_clock = false,
+};
+
+static struct fsl_spdif_soc_data fsl_spdif_imx6sx = {
+   .imx = true,
+   .shared_root_clock = true,
+};
+
+/* Check if clk is a root clock that does not share clock source with others */
+static inline bool fsl_spdif_can_set_clk_rate(struct fsl_spdif_priv *spdif,
+ int clk)
+{
+   return (clk == STC_TXCLK_SPDIF_ROOT) && !spdif->soc->shared_root_clock;
+}
+
 /* DPLL locked and lock loss interrupt handler */
 static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv)
 {
@@ -421,7 +456,7 @@ static int spdif_set_sample_rate(struct snd_pcm_substream 
*substream,
sysclk_df = spdif_priv->sysclk_df[rate];
 
/* Don't mess up the clocks from other modules */
-   if (clk != STC_TXCLK_SPDIF_ROOT)
+   if (!fsl_spdif_can_set_clk_rate(spdif_priv, clk))
goto clk_set_bypass;
 
/* The S/PDIF block needs a clock of 64 * fs * txclk_df */
@@ -1186,7 +1221,7 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv 
*spdif_priv,
continue;
 
ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index,
-i == STC_TXCLK_SPDIF_ROOT);
+
fsl_spdif_can_set_clk_rate(spdif_priv, i));
if (savesub == ret)
continue;
 
@@ -1230,6 +1265,12 @@ static int fsl_spdif_probe(struct platform_device *pdev)
 
spdif_priv->pdev = pdev;
 
+   spdif_priv->soc = of_device_get_match_data(>dev);
+   if (!spdif_priv->soc) {
+   dev_err(>dev, "failed to get soc data\n");
+   return -ENODEV;
+   }
+
/* Initialize this copy of the CPU DAI driver structure */
memcpy(_priv->cpu_dai_drv, _spdif_dai, sizeof(fsl_spdif_dai));
spdif_priv->cpu_dai_drv.name = dev_name(>dev);
@@ -1359,8 +1400,9 @@ static const struct dev_pm_ops fsl_spdif_pm = {
 };
 
 static const struct of_device_id fsl_spdif_dt_ids[] = {
-   { .compatible = "fsl,imx35-spdif", },
-   { .compatible = "fsl,vf610-spdif", },
+   { .compatible = "fsl,imx35-spdif", .data = _spdif_imx35, },
+   { .compatible = "fsl,vf610-spdif", .data = _spdif_vf610, },
+   { .compatible = "fsl,imx6sx-spdif", .data = _spdif_imx6sx, },
{}
 };
 MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids);
-- 
2.21.0



[PATCH v2 1/2] ASoC: bindings: fsl_spdif: Add new compatible string for imx6sx

2020-06-16 Thread Shengjiu Wang
Add new compatible string "fsl,imx6sx-spdif" in the binding document.
And add compatible string "fsl,vf610-spdif" which was missed before.

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

diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt 
b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
index 8b324f82a782..e1365b0ee1e9 100644
--- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
@@ -6,7 +6,11 @@ a fibre cable.
 
 Required properties:
 
-  - compatible : Compatible list, must contain "fsl,imx35-spdif".
+  - compatible : Compatible list, should contain one of the following
+ compatibles:
+ "fsl,imx35-spdif",
+ "fsl,vf610-spdif",
+ "fsl,imx6sx-spdif",
 
   - reg: Offset and length of the register set for the 
device.
 
-- 
2.21.0



Re: [PATCH 2/2] ASoC: fsl_spdif: Add support for imx6sx platform

2020-06-16 Thread Shengjiu Wang
On Wed, Jun 17, 2020 at 7:30 AM Nicolin Chen  wrote:
>
> On Tue, Jun 16, 2020 at 02:42:41PM +0800, Shengjiu Wang wrote:
> > The one difference on imx6sx platform is that the root clock
> > is shared with ASRC module, so we add a new flags "ind_root_clk"
> > which means the root clock is independent, then we will not
> > do the clk_set_rate and clk_round_rate to avoid impact ASRC
> > module usage.
> >
> > As add a new flags, we include the soc specific data struct.
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
> >  sound/soc/fsl/fsl_spdif.c | 43 +++
> >  1 file changed, 39 insertions(+), 4 deletions(-)
> >
> > diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
> > index 1b2e516f9162..00e06803d32f 100644
> > --- a/sound/soc/fsl/fsl_spdif.c
> > +++ b/sound/soc/fsl/fsl_spdif.c
> > @@ -42,6 +42,17 @@ static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 
> > 0x4, 0xa, 0xb };
> >
> >  #define DEFAULT_RXCLK_SRC1
> >
> > +/**
> > + * struct fsl_spdif_soc_data: soc specific data
> > + *
> > + * @imx: for imx platform
> > + * @ind_root_clk: flag for round clk rate
> > + */
> > +struct fsl_spdif_soc_data {
> > + bool imx;
> > + bool ind_root_clk;
>
> "ind" doesn't look very straightforward; maybe "shared_root_clock"?
>
> And for its comments:
> * @shared_root_clock: flag of sharing a clock source with others;
> * so the driver shouldn't set root clock rate
>
> > +};
> > +
> >  /*
> >   * SPDIF control structure
> >   * Defines channel status, subcode and Q sub
> > @@ -93,6 +104,7 @@ struct fsl_spdif_priv {
> >   struct snd_soc_dai_driver cpu_dai_drv;
> >   struct platform_device *pdev;
> >   struct regmap *regmap;
> > + const struct fsl_spdif_soc_data *soc;
>
> Looks better if we move it to the top of the list :)
>
> > @@ -421,7 +448,7 @@ static int spdif_set_sample_rate(struct 
> > snd_pcm_substream *substream,
> >   sysclk_df = spdif_priv->sysclk_df[rate];
> >
> >   /* Don't mess up the clocks from other modules */
> > - if (clk != STC_TXCLK_SPDIF_ROOT)
> > + if (clk != STC_TXCLK_SPDIF_ROOT || !spdif_priv->soc->ind_root_clk)
> >   goto clk_set_bypass;
> >
> >   /* The S/PDIF block needs a clock of 64 * fs * txclk_df */
> > @@ -1186,7 +1213,8 @@ static int fsl_spdif_probe_txclk(struct 
> > fsl_spdif_priv *spdif_priv,
> >   continue;
> >
> >   ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index,
> > -  i == STC_TXCLK_SPDIF_ROOT);
> > +  i == STC_TXCLK_SPDIF_ROOT &&
> > +  spdif_priv->soc->ind_root_clk);
>
> Having more than one place that checks the condition, we can add:
>
> /* Check if clk is a root clock that does not share clock source with others 
> */
> static inline bool fsl_spdif_can_set_clk_rate(struct fsl_spdif_priv *spdif, 
> int clk)
> {
> return (clk == STC_TXCLK_SPDIF_ROOT) && 
> !spdif->soc->shared_root_clock;
> }

will update them in v2

best regards
wang shengjiu


Re: [PATCH 2/2] ASoC: fsl-asoc-card: Add MQS support

2020-06-16 Thread Shengjiu Wang
On Wed, Jun 17, 2020 at 8:50 AM Nicolin Chen  wrote:
>
> On Tue, Jun 16, 2020 at 03:30:37PM +0800, Shengjiu Wang wrote:
> > The MQS codec isn't an i2c device, so add a new platform device for it.
> >
> > MQS only support playback, so add a new audio map.
> >
> > Add there maybe "model" property or no "audio-routing" property insertions
>
> "Add" => "And"
>
> > devicetree, so add some enhancement for these two property.
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
> >  sound/soc/fsl/fsl-asoc-card.c | 70 ++-
> >  1 file changed, 52 insertions(+), 18 deletions(-)
> >
> > diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
> > index 00be73900888..2ac8cb9ddd10 100644
> > --- a/sound/soc/fsl/fsl-asoc-card.c
> > +++ b/sound/soc/fsl/fsl-asoc-card.c
>
> > @@ -482,6 +489,7 @@ static int fsl_asoc_card_probe(struct platform_device 
> > *pdev)
> >  {
> >   struct device_node *cpu_np, *codec_np, *asrc_np;
> >   struct device_node *np = pdev->dev.of_node;
> > + struct platform_device *codec_pdev = NULL; /* used for non i2c 
> > device*/
>
> Having both codec_pdev and codec_dev duplicates things. Actually
> only a couple of places really need "codec_dev" -- most of them
> need codec_dev->dev pointer instead. So we could have a cleanup:
>
> -   struct i2c_client *codec_dev;
> +   struct device *codec_dev = NULL;
>
> > @@ -512,10 +520,13 @@ static int fsl_asoc_card_probe(struct platform_device 
> > *pdev)
> >   }
> >
> >   codec_np = of_parse_phandle(np, "audio-codec", 0);
> > - if (codec_np)
> > + if (codec_np) {
> >   codec_dev = of_find_i2c_device_by_node(codec_np);
> > - else
> > + if (!codec_dev)
> > + codec_pdev = of_find_device_by_node(codec_np);
> > + } else {
> >   codec_dev = NULL;
> > + }
>
> Here can have something like (feel free to simplify):
>
> if (codec_np) {
> struct platform_device *codec_pdev;
> struct i2c_client *codec_i2c;
>
> codec_i2c = of_find_i2c_device_by_node(codec_np);
> if (codec_i2c)
> codec_dev = _i2c->dev;
>
> if (!codec_dev) {
> codec_pdev = of_find_device_by_node(codec_np);
> codec_dev = _pdev->dev;
> }
> }
> >   asrc_np = of_parse_phandle(np, "audio-asrc", 0);
> >   if (asrc_np)
> > @@ -525,6 +536,13 @@ static int fsl_asoc_card_probe(struct platform_device 
> > *pdev)
> >   if (codec_dev) {
> >   struct clk *codec_clk = clk_get(_dev->dev, NULL);
>
> Then here:
>
> -   struct clk *codec_clk = clk_get(_dev->dev, NULL);
> +   struct clk *codec_clk = clk_get(codec_dev, NULL);
>
> > @@ -538,6 +556,11 @@ static int fsl_asoc_card_probe(struct platform_device 
> > *pdev)
> >   /* Assign a default DAI format, and allow each card to overwrite it */
> >   priv->dai_fmt = DAI_FMT_BASE;
> >
> > + memcpy(priv->dai_link, fsl_asoc_card_dai,
> > +sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link));
>
> > @@ -573,13 +596,25 @@ static int fsl_asoc_card_probe(struct platform_device 
> > *pdev)
> >   codec_dai_name = "ac97-hifi";
> >   priv->card.set_bias_level = NULL;
> >   priv->dai_fmt = SND_SOC_DAIFMT_AC97;
> > + priv->card.dapm_routes = audio_map_ac97;
> > + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97);
> > + } else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) {
> > + codec_dai_name = "fsl-mqs-dai";
> > + priv->card.set_bias_level = NULL;
> > + priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J |
> > + SND_SOC_DAIFMT_CBS_CFS |
> > + SND_SOC_DAIFMT_NB_NF;
> > + priv->dai_link[1].dpcm_playback = 1;
> > + priv->dai_link[2].dpcm_playback = 1;
>
> dpcm_playback = 1? That's the default value in fsl_asoc_card_dai.

ah,  should be dpcm_capture = 0.

>
> > @@ -601,19 +636,18 @@ static int fsl_asoc_card_probe(struct platform_device 
> > *pdev)
> >   priv->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1;
> >   }
> >
>

[PATCH 2/2] ASoC: fsl-asoc-card: Add MQS support

2020-06-16 Thread Shengjiu Wang
The MQS codec isn't an i2c device, so add a new platform device for it.

MQS only support playback, so add a new audio map.

Add there maybe "model" property or no "audio-routing" property in
devicetree, so add some enhancement for these two property.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl-asoc-card.c | 70 ++-
 1 file changed, 52 insertions(+), 18 deletions(-)

diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 00be73900888..2ac8cb9ddd10 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -119,6 +119,13 @@ static const struct snd_soc_dapm_route audio_map_ac97[] = {
{"ASRC-Capture",  NULL, "AC97 Capture"},
 };
 
+static const struct snd_soc_dapm_route audio_map_tx[] = {
+   /* 1st half -- Normal DAPM routes */
+   {"Playback",  NULL, "CPU-Playback"},
+   /* 2nd half -- ASRC DAPM routes */
+   {"CPU-Playback",  NULL, "ASRC-Playback"},
+};
+
 /* Add all possible widgets into here without being redundant */
 static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = {
SND_SOC_DAPM_LINE("Line Out Jack", NULL),
@@ -482,6 +489,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
 {
struct device_node *cpu_np, *codec_np, *asrc_np;
struct device_node *np = pdev->dev.of_node;
+   struct platform_device *codec_pdev = NULL; /* used for non i2c device*/
struct platform_device *asrc_pdev = NULL;
struct platform_device *cpu_pdev;
struct fsl_asoc_card_priv *priv;
@@ -512,10 +520,13 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
}
 
codec_np = of_parse_phandle(np, "audio-codec", 0);
-   if (codec_np)
+   if (codec_np) {
codec_dev = of_find_i2c_device_by_node(codec_np);
-   else
+   if (!codec_dev)
+   codec_pdev = of_find_device_by_node(codec_np);
+   } else {
codec_dev = NULL;
+   }
 
asrc_np = of_parse_phandle(np, "audio-asrc", 0);
if (asrc_np)
@@ -525,6 +536,13 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
if (codec_dev) {
struct clk *codec_clk = clk_get(_dev->dev, NULL);
 
+   if (!IS_ERR(codec_clk)) {
+   priv->codec_priv.mclk_freq = clk_get_rate(codec_clk);
+   clk_put(codec_clk);
+   }
+   } else if (codec_pdev) {
+   struct clk *codec_clk = clk_get(_pdev->dev, NULL);
+
if (!IS_ERR(codec_clk)) {
priv->codec_priv.mclk_freq = clk_get_rate(codec_clk);
clk_put(codec_clk);
@@ -538,6 +556,11 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
/* Assign a default DAI format, and allow each card to overwrite it */
priv->dai_fmt = DAI_FMT_BASE;
 
+   memcpy(priv->dai_link, fsl_asoc_card_dai,
+  sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link));
+
+   priv->card.dapm_routes = audio_map;
+   priv->card.num_dapm_routes = ARRAY_SIZE(audio_map);
/* Diversify the card configurations */
if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) {
codec_dai_name = "cs42888";
@@ -573,13 +596,25 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
codec_dai_name = "ac97-hifi";
priv->card.set_bias_level = NULL;
priv->dai_fmt = SND_SOC_DAIFMT_AC97;
+   priv->card.dapm_routes = audio_map_ac97;
+   priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97);
+   } else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) {
+   codec_dai_name = "fsl-mqs-dai";
+   priv->card.set_bias_level = NULL;
+   priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J |
+   SND_SOC_DAIFMT_CBS_CFS |
+   SND_SOC_DAIFMT_NB_NF;
+   priv->dai_link[1].dpcm_playback = 1;
+   priv->dai_link[2].dpcm_playback = 1;
+   priv->card.dapm_routes = audio_map_tx;
+   priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
} else {
dev_err(>dev, "unknown Device Tree compatible\n");
ret = -EINVAL;
goto asrc_fail;
}
 
-   if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) {
+   if (!fsl_asoc_card_is_ac97(priv) && !codec_dev && !codec_pdev) {
dev_err(>dev, "failed to find codec device\n");
ret = -EPROBE_DEFER;
goto asrc_fail;
@@ -601,19 +636,18 @@ static int fsl_aso

[PATCH 1/2] ASoC: bindings: fsl-asoc-card: Add compatible string for MQS

2020-06-16 Thread Shengjiu Wang
Add compatible string "fsl,imx-audio-mqs" for MQS

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 c60a5732d29c..6417c5dffa9a 100644
--- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
+++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
@@ -34,6 +34,8 @@ The compatible list for this generic sound card currently:
 
  "fsl,imx-audio-wm8960"
 
+ "fsl,imx-audio-mqs"
+
 Required properties:
 
   - compatible : Contains one of entries in the compatible list.
-- 
2.21.0



[PATCH 2/2] ASoC: fsl_spdif: Add support for imx6sx platform

2020-06-16 Thread Shengjiu Wang
The one difference on imx6sx platform is that the root clock
is shared with ASRC module, so we add a new flags "ind_root_clk"
which means the root clock is independent, then we will not
do the clk_set_rate and clk_round_rate to avoid impact ASRC
module usage.

As add a new flags, we include the soc specific data struct.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_spdif.c | 43 +++
 1 file changed, 39 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 1b2e516f9162..00e06803d32f 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -42,6 +42,17 @@ static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 
0xa, 0xb };
 
 #define DEFAULT_RXCLK_SRC  1
 
+/**
+ * struct fsl_spdif_soc_data: soc specific data
+ *
+ * @imx: for imx platform
+ * @ind_root_clk: flag for round clk rate
+ */
+struct fsl_spdif_soc_data {
+   bool imx;
+   bool ind_root_clk;
+};
+
 /*
  * SPDIF control structure
  * Defines channel status, subcode and Q sub
@@ -93,6 +104,7 @@ struct fsl_spdif_priv {
struct snd_soc_dai_driver cpu_dai_drv;
struct platform_device *pdev;
struct regmap *regmap;
+   const struct fsl_spdif_soc_data *soc;
bool dpll_locked;
u32 txrate[SPDIF_TXRATE_MAX];
u8 txclk_df[SPDIF_TXRATE_MAX];
@@ -110,6 +122,21 @@ struct fsl_spdif_priv {
u32 regcache_srpc;
 };
 
+static struct fsl_spdif_soc_data fsl_spdif_vf610 = {
+   .imx = false,
+   .ind_root_clk = true,
+};
+
+static struct fsl_spdif_soc_data fsl_spdif_imx35 = {
+   .imx = true,
+   .ind_root_clk = true,
+};
+
+static struct fsl_spdif_soc_data fsl_spdif_imx6sx = {
+   .imx = true,
+   .ind_root_clk = false,
+};
+
 /* DPLL locked and lock loss interrupt handler */
 static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv)
 {
@@ -421,7 +448,7 @@ static int spdif_set_sample_rate(struct snd_pcm_substream 
*substream,
sysclk_df = spdif_priv->sysclk_df[rate];
 
/* Don't mess up the clocks from other modules */
-   if (clk != STC_TXCLK_SPDIF_ROOT)
+   if (clk != STC_TXCLK_SPDIF_ROOT || !spdif_priv->soc->ind_root_clk)
goto clk_set_bypass;
 
/* The S/PDIF block needs a clock of 64 * fs * txclk_df */
@@ -1186,7 +1213,8 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv 
*spdif_priv,
continue;
 
ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index,
-i == STC_TXCLK_SPDIF_ROOT);
+i == STC_TXCLK_SPDIF_ROOT &&
+spdif_priv->soc->ind_root_clk);
if (savesub == ret)
continue;
 
@@ -1230,6 +1258,12 @@ static int fsl_spdif_probe(struct platform_device *pdev)
 
spdif_priv->pdev = pdev;
 
+   spdif_priv->soc = of_device_get_match_data(>dev);
+   if (!spdif_priv->soc) {
+   dev_err(>dev, "failed to get soc data\n");
+   return -ENODEV;
+   }
+
/* Initialize this copy of the CPU DAI driver structure */
memcpy(_priv->cpu_dai_drv, _spdif_dai, sizeof(fsl_spdif_dai));
spdif_priv->cpu_dai_drv.name = dev_name(>dev);
@@ -1359,8 +1393,9 @@ static const struct dev_pm_ops fsl_spdif_pm = {
 };
 
 static const struct of_device_id fsl_spdif_dt_ids[] = {
-   { .compatible = "fsl,imx35-spdif", },
-   { .compatible = "fsl,vf610-spdif", },
+   { .compatible = "fsl,imx35-spdif", .data = _spdif_imx35, },
+   { .compatible = "fsl,vf610-spdif", .data = _spdif_vf610, },
+   { .compatible = "fsl,imx6sx-spdif", .data = _spdif_imx6sx, },
{}
 };
 MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids);
-- 
2.21.0



[PATCH 1/2] ASoC: bindings: fsl_spdif: Add new compatible string for imx6sx

2020-06-16 Thread Shengjiu Wang
Add new compatible string "fsl,imx6sx-spdif" in the binding document.
And add compatible string "fsl,vf610-spdif" which was missed before.

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

diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt 
b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
index 8b324f82a782..e1365b0ee1e9 100644
--- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
@@ -6,7 +6,11 @@ a fibre cable.
 
 Required properties:
 
-  - compatible : Compatible list, must contain "fsl,imx35-spdif".
+  - compatible : Compatible list, should contain one of the following
+ compatibles:
+ "fsl,imx35-spdif",
+ "fsl,vf610-spdif",
+ "fsl,imx6sx-spdif",
 
   - reg: Offset and length of the register set for the 
device.
 
-- 
2.21.0



[PATCH v3] ASoC: fsl_ssi: Fix bclk calculation for mono channel

2020-06-15 Thread Shengjiu Wang
For mono channel, SSI will switch to Normal mode.

In Normal mode and Network mode, the Word Length Control bits
control the word length divider in clock generator, which is
different with I2S Master mode (the word length is fixed to
32bit), it should be the value of params_width(hw_params).

The condition "slots == 2" is not good for I2S Master mode,
because for Network mode and Normal mode, the slots can also
be 2. Then we need to use (ssi->i2s_net & SSI_SCR_I2S_MODE_MASK)
to check if it is I2S Master mode.

So we refine the formula for mono channel, otherwise there
will be sound issue for S24_LE.

Fixes: b0a7043d5c2c ("ASoC: fsl_ssi: Caculate bit clock rate using slot number 
and width")
Signed-off-by: Shengjiu Wang 
---
changes in v3
- update according to Nicolin's comments

changes in v2
- refine patch for Network mode and Normal mode.

 sound/soc/fsl/fsl_ssi.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index bad89b0d129e..1a2fa7f18142 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -678,8 +678,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
struct regmap *regs = ssi->regs;
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
unsigned long clkrate, baudrate, tmprate;
-   unsigned int slots = params_channels(hw_params);
-   unsigned int slot_width = 32;
+   unsigned int channels = params_channels(hw_params);
+   unsigned int slot_width = params_width(hw_params);
+   unsigned int slots = 2;
u64 sub, savesub = 10;
unsigned int freq;
bool baudclk_is_used;
@@ -688,10 +689,14 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
/* Override slots and slot_width if being specifically set... */
if (ssi->slots)
slots = ssi->slots;
-   /* ...but keep 32 bits if slots is 2 -- I2S Master mode */
-   if (ssi->slot_width && slots != 2)
+   if (ssi->slot_width)
slot_width = ssi->slot_width;
 
+   /* ...but force 32 bits for stereo audio using I2S Master Mode */
+   if (channels == 2 &&
+   (ssi->i2s_net & SSI_SCR_I2S_MODE_MASK) == SSI_SCR_I2S_MODE_MASTER)
+   slot_width = 32;
+
/* Generate bit clock based on the slot number and slot width */
freq = slots * slot_width * params_rate(hw_params);
 
-- 
2.21.0



Re: [PATCH v2] ASoC: fsl_ssi: Fix bclk calculation for mono channel

2020-06-15 Thread Shengjiu Wang
On Tue, Jun 16, 2020 at 9:59 AM Nicolin Chen  wrote:
>
> On Tue, Jun 16, 2020 at 09:48:39AM +0800, Shengjiu Wang wrote:
> > On Tue, Jun 16, 2020 at 7:11 AM Nicolin Chen  wrote:
> > >
> > > On Mon, Jun 15, 2020 at 01:56:18PM +0800, Shengjiu Wang wrote:
> > > > For mono channel, SSI will switch to Normal mode.
> > > >
> > > > In Normal mode and Network mode, the Word Length Control bits
> > > > control the word length divider in clock generator, which is
> > > > different with I2S Master mode (the word length is fixed to
> > > > 32bit), it should be the value of params_width(hw_params).
> > > >
> > > > The condition "slots == 2" is not good for I2S Master mode,
> > > > because for Network mode and Normal mode, the slots can also
> > > > be 2. Then we need to use (ssi->i2s_net & SSI_SCR_I2S_MODE_MASK)
> > > > to check if it is I2S Master mode.
> > >
> > > The fsl_ssi_set_bclk is only called when fsl_ssi_is_i2s_master,
> > > though I agree that that line of comments sounds confusing now.
> >
> > Actually I think fsl_ssi_is_i2s_master is not accurate, it just checks
> > the Master mode,  but didn't check the I2S mode.
> >
> > >
> > > > So we refine the famula for mono channel, otherwise there
> > >
> > > famula => formula?
> > >
> > > > will be sound issue for S24_LE.
> > > >
> > > > Fixes: b0a7043d5c2c ("ASoC: fsl_ssi: Caculate bit clock rate using slot 
> > > > number and width")
> > > > Signed-off-by: Shengjiu Wang 
> > > > ---
> > > > changes in v2
> > > > - refine patch for Network mode and Normal mode.
> > > >
> > > >  sound/soc/fsl/fsl_ssi.c | 15 +++
> > > >  1 file changed, 11 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
> > > > index bad89b0d129e..cbf67d132fda 100644
> > > > --- a/sound/soc/fsl/fsl_ssi.c
> > > > +++ b/sound/soc/fsl/fsl_ssi.c
> > > > @@ -678,7 +678,8 @@ static int fsl_ssi_set_bclk(struct 
> > > > snd_pcm_substream *substream,
> > > >   struct regmap *regs = ssi->regs;
> > > >   u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
> > > >   unsigned long clkrate, baudrate, tmprate;
> > > > - unsigned int slots = params_channels(hw_params);
> > > > + unsigned int channels = params_channels(hw_params);
> > > > + unsigned int slots;
> > > >   unsigned int slot_width = 32;
> > > >   u64 sub, savesub = 10;
> > > >   unsigned int freq;
> > > > @@ -688,9 +689,15 @@ static int fsl_ssi_set_bclk(struct 
> > > > snd_pcm_substream *substream,
> > > >   /* Override slots and slot_width if being specifically set... */
> > > >   if (ssi->slots)
> > > >   slots = ssi->slots;
> > > > - /* ...but keep 32 bits if slots is 2 -- I2S Master mode */
> > > > - if (ssi->slot_width && slots != 2)
> > > > - slot_width = ssi->slot_width;
> > > > + else
> > > > + /* Apply two slots for mono channel, because DC = 2 */
> > > > + slots = (channels == 1) ? 2 : channels;
> > > > +
> > > > + /* ...but keep 32 bits if I2S Master mode */
> > > > + if ((ssi->i2s_net & SSI_SCR_I2S_MODE_MASK) != 
> > > > SSI_SCR_I2S_MODE_MASTER ||
> > > > + channels == 1)
> > > > + slot_width = ssi->slot_width ? ssi->slot_width :
> > >
> > > This looks very complicated...can you review and try mine?
> > > (Basically, take 32-bit out of default but force it later)
> > >
> > > @@ -678,8 +678,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
> > > *substream,
> > > struct regmap *regs = ssi->regs;
> > > u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
> > > unsigned long clkrate, baudrate, tmprate;
> > > -   unsigned int slots = params_channels(hw_params);
> > > -   unsigned int slot_width = 32;
> > > +   unsigned int channels = params_channels(hw_params);
> > > +   unsigned int slot_width = params_width(hw_params);
> > > +   unsigned int slots = 2;
> > > u64 sub, savesub = 1

Re: [PATCH v2] ASoC: fsl_ssi: Fix bclk calculation for mono channel

2020-06-15 Thread Shengjiu Wang
On Tue, Jun 16, 2020 at 7:11 AM Nicolin Chen  wrote:
>
> On Mon, Jun 15, 2020 at 01:56:18PM +0800, Shengjiu Wang wrote:
> > For mono channel, SSI will switch to Normal mode.
> >
> > In Normal mode and Network mode, the Word Length Control bits
> > control the word length divider in clock generator, which is
> > different with I2S Master mode (the word length is fixed to
> > 32bit), it should be the value of params_width(hw_params).
> >
> > The condition "slots == 2" is not good for I2S Master mode,
> > because for Network mode and Normal mode, the slots can also
> > be 2. Then we need to use (ssi->i2s_net & SSI_SCR_I2S_MODE_MASK)
> > to check if it is I2S Master mode.
>
> The fsl_ssi_set_bclk is only called when fsl_ssi_is_i2s_master,
> though I agree that that line of comments sounds confusing now.

Actually I think fsl_ssi_is_i2s_master is not accurate, it just checks
the Master mode,  but didn't check the I2S mode.

>
> > So we refine the famula for mono channel, otherwise there
>
> famula => formula?
>
> > will be sound issue for S24_LE.
> >
> > Fixes: b0a7043d5c2c ("ASoC: fsl_ssi: Caculate bit clock rate using slot 
> > number and width")
> > Signed-off-by: Shengjiu Wang 
> > ---
> > changes in v2
> > - refine patch for Network mode and Normal mode.
> >
> >  sound/soc/fsl/fsl_ssi.c | 15 +++
> >  1 file changed, 11 insertions(+), 4 deletions(-)
> >
> > diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
> > index bad89b0d129e..cbf67d132fda 100644
> > --- a/sound/soc/fsl/fsl_ssi.c
> > +++ b/sound/soc/fsl/fsl_ssi.c
> > @@ -678,7 +678,8 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
> > *substream,
> >   struct regmap *regs = ssi->regs;
> >   u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
> >   unsigned long clkrate, baudrate, tmprate;
> > - unsigned int slots = params_channels(hw_params);
> > + unsigned int channels = params_channels(hw_params);
> > + unsigned int slots;
> >   unsigned int slot_width = 32;
> >   u64 sub, savesub = 10;
> >   unsigned int freq;
> > @@ -688,9 +689,15 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
> > *substream,
> >   /* Override slots and slot_width if being specifically set... */
> >   if (ssi->slots)
> >   slots = ssi->slots;
> > - /* ...but keep 32 bits if slots is 2 -- I2S Master mode */
> > - if (ssi->slot_width && slots != 2)
> > - slot_width = ssi->slot_width;
> > + else
> > + /* Apply two slots for mono channel, because DC = 2 */
> > + slots = (channels == 1) ? 2 : channels;
> > +
> > + /* ...but keep 32 bits if I2S Master mode */
> > + if ((ssi->i2s_net & SSI_SCR_I2S_MODE_MASK) != SSI_SCR_I2S_MODE_MASTER 
> > ||
> > + channels == 1)
> > + slot_width = ssi->slot_width ? ssi->slot_width :
>
> This looks very complicated...can you review and try mine?
> (Basically, take 32-bit out of default but force it later)
>
> @@ -678,8 +678,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
> *substream,
> struct regmap *regs = ssi->regs;
> u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
> unsigned long clkrate, baudrate, tmprate;
> -   unsigned int slots = params_channels(hw_params);
> -   unsigned int slot_width = 32;
> +   unsigned int channels = params_channels(hw_params);
> +   unsigned int slot_width = params_width(hw_params);
> +   unsigned int slots = 2;
> u64 sub, savesub = 10;
> unsigned int freq;
> bool baudclk_is_used;
> @@ -688,10 +689,16 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
> *substream,
> /* Override slots and slot_width if being specifically set... */
> if (ssi->slots)
> slots = ssi->slots;
> -   /* ...but keep 32 bits if slots is 2 -- I2S Master mode */
> -   if (ssi->slot_width && slots != 2)
> +   if (ssi->slot_width)
> slot_width = ssi->slot_width;
>
> +   /*
> +* ...but force 32 bits for stereo audio. Note that mono audio is also
> +* sent in 2 slots via NORMAL mode, so check both slots and channels.
> +*/
> +   if (slots == 2 && channels == 2)
> +   slot_width = 32;

slots ==2 && channels ==2 does not mean the I2S Master mode.
For LEFT_J, it is also slots =2 & channels = 2, then the slot_width
should be params_width(hw_params).
and DSP_A/B also supports stereo.


[PATCH v2] ASoC: fsl_ssi: Fix bclk calculation for mono channel

2020-06-15 Thread Shengjiu Wang
For mono channel, SSI will switch to Normal mode.

In Normal mode and Network mode, the Word Length Control bits
control the word length divider in clock generator, which is
different with I2S Master mode (the word length is fixed to
32bit), it should be the value of params_width(hw_params).

The condition "slots == 2" is not good for I2S Master mode,
because for Network mode and Normal mode, the slots can also
be 2. Then we need to use (ssi->i2s_net & SSI_SCR_I2S_MODE_MASK)
to check if it is I2S Master mode.

So we refine the famula for mono channel, otherwise there
will be sound issue for S24_LE.

Fixes: b0a7043d5c2c ("ASoC: fsl_ssi: Caculate bit clock rate using slot number 
and width")
Signed-off-by: Shengjiu Wang 
---
changes in v2
- refine patch for Network mode and Normal mode.

 sound/soc/fsl/fsl_ssi.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index bad89b0d129e..cbf67d132fda 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -678,7 +678,8 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
struct regmap *regs = ssi->regs;
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
unsigned long clkrate, baudrate, tmprate;
-   unsigned int slots = params_channels(hw_params);
+   unsigned int channels = params_channels(hw_params);
+   unsigned int slots;
unsigned int slot_width = 32;
u64 sub, savesub = 10;
unsigned int freq;
@@ -688,9 +689,15 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
/* Override slots and slot_width if being specifically set... */
if (ssi->slots)
slots = ssi->slots;
-   /* ...but keep 32 bits if slots is 2 -- I2S Master mode */
-   if (ssi->slot_width && slots != 2)
-   slot_width = ssi->slot_width;
+   else
+   /* Apply two slots for mono channel, because DC = 2 */
+   slots = (channels == 1) ? 2 : channels;
+
+   /* ...but keep 32 bits if I2S Master mode */
+   if ((ssi->i2s_net & SSI_SCR_I2S_MODE_MASK) != SSI_SCR_I2S_MODE_MASTER ||
+   channels == 1)
+   slot_width = ssi->slot_width ? ssi->slot_width :
+params_width(hw_params);
 
/* Generate bit clock based on the slot number and slot width */
freq = slots * slot_width * params_rate(hw_params);
-- 
2.21.0



[RFC PATCH v3 4/4] ASoC: fsl_asrc_dma: Fix data copying speed issue with EDMA

2020-06-12 Thread Shengjiu Wang
With EDMA, there is two dma channels can be used for dev_to_dev,
one is from ASRC, one is from another peripheral (ESAI or SAI).

If we select the dma channel of ASRC, there is an issue for ideal
ratio case, the speed of copy data is faster than sample
frequency, because ASRC output data is very fast in ideal ratio
mode.

So it is reasonable to use the dma channel of Back-End peripheral.
then copying speed of DMA is controlled by data consumption
speed in the peripheral FIFO,

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_asrc_common.h |  2 ++
 sound/soc/fsl/fsl_asrc_dma.c| 26 +++---
 2 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h
index 77665b15c8db..7e1c13ca37f1 100644
--- a/sound/soc/fsl/fsl_asrc_common.h
+++ b/sound/soc/fsl/fsl_asrc_common.h
@@ -32,6 +32,7 @@ enum asrc_pair_index {
  * @dma_chan: inputer and output DMA channels
  * @dma_data: private dma data
  * @pos: hardware pointer position
+ * @req_dma_chan: flag to release dev_to_dev chan
  * @private: pair private area
  */
 struct fsl_asrc_pair {
@@ -45,6 +46,7 @@ struct fsl_asrc_pair {
struct dma_chan *dma_chan[2];
struct imx_dma_data dma_data;
unsigned int pos;
+   bool req_dma_chan;
 
void *private;
 };
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index d88e6343e0a2..5f01a58f422a 100644
--- a/sound/soc/fsl/fsl_asrc_dma.c
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -233,11 +233,11 @@ static int fsl_asrc_dma_hw_params(struct 
snd_soc_component *component,
 
pair->dma_chan[dir] =
dma_request_channel(mask, filter, >dma_data);
+   pair->req_dma_chan = true;
} else {
-   if (!be_chan)
-   dma_release_channel(tmp_chan);
-   pair->dma_chan[dir] =
-   asrc->get_dma_channel(pair, dir);
+   pair->dma_chan[dir] = tmp_chan;
+   /* Do not flag to release if we are reusing the Back-End one */
+   pair->req_dma_chan = !be_chan;
}
 
if (!pair->dma_chan[dir]) {
@@ -276,7 +276,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
ret = dmaengine_slave_config(pair->dma_chan[dir], _be);
if (ret) {
dev_err(dev, "failed to config DMA channel for Back-End\n");
-   dma_release_channel(pair->dma_chan[dir]);
+   if (pair->req_dma_chan)
+   dma_release_channel(pair->dma_chan[dir]);
return ret;
}
 
@@ -288,19 +289,22 @@ static int fsl_asrc_dma_hw_params(struct 
snd_soc_component *component,
 static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
 {
+   bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
+   u8 dir = tx ? OUT : IN;
 
snd_pcm_set_runtime_buffer(substream, NULL);
 
-   if (pair->dma_chan[IN])
-   dma_release_channel(pair->dma_chan[IN]);
+   if (pair->dma_chan[!dir])
+   dma_release_channel(pair->dma_chan[!dir]);
 
-   if (pair->dma_chan[OUT])
-   dma_release_channel(pair->dma_chan[OUT]);
+   /* release dev_to_dev chan if we aren't reusing the Back-End one */
+   if (pair->dma_chan[dir] && pair->req_dma_chan)
+   dma_release_channel(pair->dma_chan[dir]);
 
-   pair->dma_chan[IN] = NULL;
-   pair->dma_chan[OUT] = NULL;
+   pair->dma_chan[!dir] = NULL;
+   pair->dma_chan[dir] = NULL;
 
return 0;
 }
-- 
2.21.0



[RFC PATCH v3 3/4] ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End

2020-06-12 Thread Shengjiu Wang
The dma channel has been requested by Back-End cpu dai driver already.
If fsl_asrc_dma requests dma chan with same dma:tx symlink, then
there will be below warning with SDMA.

[   48.174236] fsl-esai-dai 2024000.esai: Cannot create DMA dma:tx symlink

So if we can reuse the dma channel of Back-End, then the issue can be
fixed.

In order to get the dma channel which is already requested in Back-End.
we use the exported two functions (snd_soc_lookup_component_nolocked
and soc_component_to_pcm). If we can get the dma channel, then reuse it,
if can't, then request a new one.

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

diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index d6a3fc5f87e5..d88e6343e0a2 100644
--- a/sound/soc/fsl/fsl_asrc_dma.c
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -135,6 +135,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
+   struct dma_chan *tmp_chan = NULL, *be_chan = NULL;
+   struct snd_soc_component *component_be = NULL;
struct fsl_asrc *asrc = pair->asrc;
struct dma_slave_config config_fe, config_be;
enum asrc_pair_index index = pair->index;
@@ -142,7 +144,6 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
int stream = substream->stream;
struct imx_dma_data *tmp_data;
struct snd_soc_dpcm *dpcm;
-   struct dma_chan *tmp_chan;
struct device *dev_be;
u8 dir = tx ? OUT : IN;
dma_cap_mask_t mask;
@@ -197,18 +198,30 @@ static int fsl_asrc_dma_hw_params(struct 
snd_soc_component *component,
dma_cap_set(DMA_SLAVE, mask);
dma_cap_set(DMA_CYCLIC, mask);
 
+   /*
+* The Back-End device might have already requested a DMA channel,
+* so try to reuse it first, and then request a new one upon NULL.
+*/
+   component_be = snd_soc_lookup_component_nolocked(dev_be, 
SND_DMAENGINE_PCM_DRV_NAME);
+   if (component_be) {
+   be_chan = 
soc_component_to_pcm(component_be)->chan[substream->stream];
+   tmp_chan = be_chan;
+   }
+   if (!tmp_chan)
+   tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
+
/*
 * An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each
 * peripheral, unlike SDMA channel that is allocated dynamically. So no
-* need to configure dma_request and dma_request2, but get dma_chan via
-* dma_request_slave_channel directly with dma name of Front-End device
+* need to configure dma_request and dma_request2, but get dma_chan of
+* Back-End device directly via dma_request_slave_channel.
 */
if (!asrc->use_edma) {
/* Get DMA request of Back-End */
-   tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
tmp_data = tmp_chan->private;
pair->dma_data.dma_request = tmp_data->dma_request;
-   dma_release_channel(tmp_chan);
+   if (!be_chan)
+   dma_release_channel(tmp_chan);
 
/* Get DMA request of Front-End */
tmp_chan = asrc->get_dma_channel(pair, dir);
@@ -221,6 +234,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
pair->dma_chan[dir] =
dma_request_channel(mask, filter, >dma_data);
} else {
+   if (!be_chan)
+   dma_release_channel(tmp_chan);
pair->dma_chan[dir] =
asrc->get_dma_channel(pair, dir);
}
-- 
2.21.0



[RFC PATCH v3 2/4] ASoC: dmaengine_pcm: export soc_component_to_pcm

2020-06-12 Thread Shengjiu Wang
In DPCM case, Front-End needs to get the dma chan which has
been requested by Back-End and reuse it.

Signed-off-by: Shengjiu Wang 
---
 include/sound/dmaengine_pcm.h | 11 +++
 sound/soc/soc-generic-dmaengine-pcm.c | 12 
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index b65220685920..8c5e38180fb0 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -161,4 +161,15 @@ int snd_dmaengine_pcm_prepare_slave_config(struct 
snd_pcm_substream *substream,
 
 #define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm"
 
+struct dmaengine_pcm {
+   struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
+   const struct snd_dmaengine_pcm_config *config;
+   struct snd_soc_component component;
+   unsigned int flags;
+};
+
+static inline struct dmaengine_pcm *soc_component_to_pcm(struct 
snd_soc_component *p)
+{
+   return container_of(p, struct dmaengine_pcm, component);
+}
 #endif
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c 
b/sound/soc/soc-generic-dmaengine-pcm.c
index f728309a0833..80a4e71f2d95 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -21,18 +21,6 @@
  */
 #define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(31)
 
-struct dmaengine_pcm {
-   struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
-   const struct snd_dmaengine_pcm_config *config;
-   struct snd_soc_component component;
-   unsigned int flags;
-};
-
-static struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p)
-{
-   return container_of(p, struct dmaengine_pcm, component);
-}
-
 static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
struct snd_pcm_substream *substream)
 {
-- 
2.21.0



[RFC PATCH v3 1/4] ASoC: soc-card: export snd_soc_lookup_component_nolocked

2020-06-12 Thread Shengjiu Wang
snd_soc_lookup_component_nolocked can be used for the DPCM case
that Front-End needs to get the unused platform component but
added by Back-End cpu dai driver.

If the component is gotten, then we can get the dma chan created
by Back-End component and reused it in Front-End.

Signed-off-by: Shengjiu Wang 
---
 include/sound/soc.h  | 2 ++
 sound/soc/soc-core.c | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 74868436ac79..565612a8d690 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -444,6 +444,8 @@ int devm_snd_soc_register_component(struct device *dev,
 const struct snd_soc_component_driver 
*component_driver,
 struct snd_soc_dai_driver *dai_drv, int num_dai);
 void snd_soc_unregister_component(struct device *dev);
+struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev,
+   const char 
*driver_name);
 struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
   const char *driver_name);
 
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b07eca2c6ccc..d4c73e86d058 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -310,7 +310,7 @@ struct snd_soc_component *snd_soc_rtdcom_lookup(struct 
snd_soc_pcm_runtime *rtd,
 }
 EXPORT_SYMBOL_GPL(snd_soc_rtdcom_lookup);
 
-static struct snd_soc_component
+struct snd_soc_component
 *snd_soc_lookup_component_nolocked(struct device *dev, const char *driver_name)
 {
struct snd_soc_component *component;
@@ -329,6 +329,7 @@ static struct snd_soc_component
 
return found_component;
 }
+EXPORT_SYMBOL_GPL(snd_soc_lookup_component_nolocked);
 
 struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
   const char *driver_name)
-- 
2.21.0



[RFC PATCH v3 0/4] Reuse the dma channel if available in Back-End

2020-06-12 Thread Shengjiu Wang
Reuse the dma channel if available in Back-End

Shengjiu Wang (4):
  ASoC: soc-card: export snd_soc_lookup_component_nolocked
  ASoC: dmaengine_pcm: export soc_component_to_pcm
  ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End
  ASoC: fsl_asrc_dma: Fix data copying speed issue with EDMA

changes in v3:
- update according to Nicolin's comments
- split previous 0003 patch to two patches

changes in v2:
- update according to Mark's comments and split the patch

 include/sound/dmaengine_pcm.h | 11 +++
 include/sound/soc.h   |  2 ++
 sound/soc/fsl/fsl_asrc_common.h   |  2 ++
 sound/soc/fsl/fsl_asrc_dma.c  | 47 +++
 sound/soc/soc-core.c  |  3 +-
 sound/soc/soc-generic-dmaengine-pcm.c | 12 ---
 6 files changed, 50 insertions(+), 27 deletions(-)

-- 
2.21.0



Re: [RFC PATCH v2 3/3] ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End

2020-06-11 Thread Shengjiu Wang
On Fri, Jun 12, 2020 at 8:33 AM Nicolin Chen  wrote:
>
> On Wed, Jun 10, 2020 at 06:05:49PM +0800, Shengjiu Wang wrote:
> > The dma channel has been requested by Back-End cpu dai driver already.
> > If fsl_asrc_dma requests dma chan with same dma:tx symlink, then
> > there will be below warning with SDMA.
> >
> > [   48.174236] fsl-esai-dai 2024000.esai: Cannot create DMA dma:tx symlink
> >
> > or with EDMA the request operation will fail for EDMA channel
> > can only be requested once.
> >
> > So If we can reuse the dma channel of Back-End, then the issue can be
> > fixed.
> >
> > In order to get the dma channel which is already requested in Back-End.
> > we use the exported two functions (snd_soc_lookup_component_nolocked
> > and soc_component_to_pcm). If we can get the dma channel, then reuse it,
> > if can't, then request a new one.
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
> >  sound/soc/fsl/fsl_asrc_common.h |  2 ++
> >  sound/soc/fsl/fsl_asrc_dma.c| 52 +
> >  2 files changed, 42 insertions(+), 12 deletions(-)
>
> > diff --git a/sound/soc/fsl/fsl_asrc_common.h 
> > b/sound/soc/fsl/fsl_asrc_common.h
> > index 77665b15c8db..09512bc79b80 100644
> > --- a/sound/soc/fsl/fsl_asrc_common.h
> > +++ b/sound/soc/fsl/fsl_asrc_common.h
> > @@ -32,6 +32,7 @@ enum asrc_pair_index {
> >   * @dma_chan: inputer and output DMA channels
> >   * @dma_data: private dma data
> >   * @pos: hardware pointer position
> > + * @req_dma_chan_dev_to_dev: flag for release dev_to_dev chan
>
> Since we only have dma_request call for back-end only:
> + * @req_dma_chan: flag to release back-end dma chan

I prefer to use the description "flag to release dev_to_dev chan"
because we won't release the dma chan of the back-end. if the chan
is from the back-end, it is owned by the back-end component.

>
> > diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
> > index d6a3fc5f87e5..5ecb77d466d3 100644
> > --- a/sound/soc/fsl/fsl_asrc_dma.c
> > +++ b/sound/soc/fsl/fsl_asrc_dma.c
> > @@ -160,6 +161,9 @@ static int fsl_asrc_dma_hw_params(struct 
> > snd_soc_component *component,
> >   substream_be = snd_soc_dpcm_get_substream(be, stream);
> >   dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be);
> >   dev_be = dai->dev;
> > + component_be = snd_soc_lookup_component_nolocked(dev_be, 
> > SND_DMAENGINE_PCM_DRV_NAME);
> > + if (component_be)
> > + tmp_chan = 
> > soc_component_to_pcm(component_be)->chan[substream->stream];
>
> Should we use substream_be->stream or just substream->stream?

substream_be->stream should be better.

>
> And would be better to add these lines right before we really use
> tmp_chan because there's still some distance till it reaches that
> point. And would be better to have a line of comments too.

ok.

>
> > @@ -205,10 +209,14 @@ static int fsl_asrc_dma_hw_params(struct 
> > snd_soc_component *component,
> >*/
> >   if (!asrc->use_edma) {
> >   /* Get DMA request of Back-End */
> > - tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : 
> > "rx");
> > + if (!tmp_chan) {
> > + tmp_chan_new = dma_request_slave_channel(dev_be, tx ? 
> > "tx" : "rx");
> > + tmp_chan = tmp_chan_new;
>
> This is a bit confusing...though I finally got it :)
> So probably better to have a line of comments.

ok.

>
> > @@ -220,9 +228,26 @@ static int fsl_asrc_dma_hw_params(struct 
> > snd_soc_component *component,
> >
> >   pair->dma_chan[dir] =
> >   dma_request_channel(mask, filter, >dma_data);
> > + pair->req_dma_chan_dev_to_dev = true;
> >   } else {
> > - pair->dma_chan[dir] =
> > - asrc->get_dma_channel(pair, dir);
> > + /*
> > +  * With EDMA, there is two dma channels can be used for p2p,
> > +  * one is from ASRC, one is from another peripheral
> > +  * (ESAI or SAI). Previously we select the dma channel of 
> > ASRC,
> > +  * but find an issue for ideal ratio case, there is no control
> > +  * for data copy speed, the speed is faster than sample
> > +  * frequency.
> > +  *
> > +  * So we switch to use dma channel of peripheral 

[RFC PATCH v2 3/3] ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End

2020-06-10 Thread Shengjiu Wang
The dma channel has been requested by Back-End cpu dai driver already.
If fsl_asrc_dma requests dma chan with same dma:tx symlink, then
there will be below warning with SDMA.

[   48.174236] fsl-esai-dai 2024000.esai: Cannot create DMA dma:tx symlink

or with EDMA the request operation will fail for EDMA channel
can only be requested once.

So If we can reuse the dma channel of Back-End, then the issue can be
fixed.

In order to get the dma channel which is already requested in Back-End.
we use the exported two functions (snd_soc_lookup_component_nolocked
and soc_component_to_pcm). If we can get the dma channel, then reuse it,
if can't, then request a new one.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_asrc_common.h |  2 ++
 sound/soc/fsl/fsl_asrc_dma.c| 52 +
 2 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h
index 77665b15c8db..09512bc79b80 100644
--- a/sound/soc/fsl/fsl_asrc_common.h
+++ b/sound/soc/fsl/fsl_asrc_common.h
@@ -32,6 +32,7 @@ enum asrc_pair_index {
  * @dma_chan: inputer and output DMA channels
  * @dma_data: private dma data
  * @pos: hardware pointer position
+ * @req_dma_chan_dev_to_dev: flag for release dev_to_dev chan
  * @private: pair private area
  */
 struct fsl_asrc_pair {
@@ -45,6 +46,7 @@ struct fsl_asrc_pair {
struct dma_chan *dma_chan[2];
struct imx_dma_data dma_data;
unsigned int pos;
+   bool req_dma_chan_dev_to_dev;
 
void *private;
 };
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index d6a3fc5f87e5..5ecb77d466d3 100644
--- a/sound/soc/fsl/fsl_asrc_dma.c
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -133,6 +133,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL;
struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
+   struct dma_chan *tmp_chan = NULL, *tmp_chan_new = NULL;
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
struct fsl_asrc *asrc = pair->asrc;
@@ -142,7 +143,6 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
int stream = substream->stream;
struct imx_dma_data *tmp_data;
struct snd_soc_dpcm *dpcm;
-   struct dma_chan *tmp_chan;
struct device *dev_be;
u8 dir = tx ? OUT : IN;
dma_cap_mask_t mask;
@@ -152,6 +152,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
for_each_dpcm_be(rtd, stream, dpcm) {
struct snd_soc_pcm_runtime *be = dpcm->be;
struct snd_pcm_substream *substream_be;
+   struct snd_soc_component *component_be;
struct snd_soc_dai *dai = asoc_rtd_to_cpu(be, 0);
 
if (dpcm->fe != rtd)
@@ -160,6 +161,9 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
substream_be = snd_soc_dpcm_get_substream(be, stream);
dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be);
dev_be = dai->dev;
+   component_be = snd_soc_lookup_component_nolocked(dev_be, 
SND_DMAENGINE_PCM_DRV_NAME);
+   if (component_be)
+   tmp_chan = 
soc_component_to_pcm(component_be)->chan[substream->stream];
break;
}
 
@@ -205,10 +209,14 @@ static int fsl_asrc_dma_hw_params(struct 
snd_soc_component *component,
 */
if (!asrc->use_edma) {
/* Get DMA request of Back-End */
-   tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
+   if (!tmp_chan) {
+   tmp_chan_new = dma_request_slave_channel(dev_be, tx ? 
"tx" : "rx");
+   tmp_chan = tmp_chan_new;
+   }
tmp_data = tmp_chan->private;
pair->dma_data.dma_request = tmp_data->dma_request;
-   dma_release_channel(tmp_chan);
+   if (tmp_chan_new)
+   dma_release_channel(tmp_chan_new);
 
/* Get DMA request of Front-End */
tmp_chan = asrc->get_dma_channel(pair, dir);
@@ -220,9 +228,26 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component 
*component,
 
pair->dma_chan[dir] =
dma_request_channel(mask, filter, >dma_data);
+   pair->req_dma_chan_dev_to_dev = true;
} else {
-   pair->dma_chan[dir] =
-   asrc->get_dma_channel(pair, dir);
+   /*
+* With EDMA, there is two dma channels can be used for p2p,
+* one is from ASRC, one is fr

[RFC PATCH v2 2/3] ASoC: dmaengine_pcm: export soc_component_to_pcm

2020-06-10 Thread Shengjiu Wang
In DPCM case, Front-End needs to get the dma chan which has
been requested by Back-End and reuse it.

Signed-off-by: Shengjiu Wang 
---
 include/sound/dmaengine_pcm.h | 11 +++
 sound/soc/soc-generic-dmaengine-pcm.c | 12 
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index b65220685920..8c5e38180fb0 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -161,4 +161,15 @@ int snd_dmaengine_pcm_prepare_slave_config(struct 
snd_pcm_substream *substream,
 
 #define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm"
 
+struct dmaengine_pcm {
+   struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
+   const struct snd_dmaengine_pcm_config *config;
+   struct snd_soc_component component;
+   unsigned int flags;
+};
+
+static inline struct dmaengine_pcm *soc_component_to_pcm(struct 
snd_soc_component *p)
+{
+   return container_of(p, struct dmaengine_pcm, component);
+}
 #endif
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c 
b/sound/soc/soc-generic-dmaengine-pcm.c
index f728309a0833..80a4e71f2d95 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -21,18 +21,6 @@
  */
 #define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(31)
 
-struct dmaengine_pcm {
-   struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
-   const struct snd_dmaengine_pcm_config *config;
-   struct snd_soc_component component;
-   unsigned int flags;
-};
-
-static struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p)
-{
-   return container_of(p, struct dmaengine_pcm, component);
-}
-
 static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
struct snd_pcm_substream *substream)
 {
-- 
2.21.0



[RFC PATCH v2 0/3] ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End

2020-06-10 Thread Shengjiu Wang
Reuse the dma channel if available in Back-End

Shengjiu Wang (3):
  ASoC: soc-card: export snd_soc_lookup_component_nolocked
  ASoC: dmaengine_pcm: export soc_component_to_pcm
  ASoC: fsl_asrc_dma: Reuse the dma channel if available in Back-End

changes in v2:
- update according to Mark's comments and split the patch


 include/sound/dmaengine_pcm.h | 11 ++
 include/sound/soc.h   |  2 ++
 sound/soc/fsl/fsl_asrc_common.h   |  2 ++
 sound/soc/fsl/fsl_asrc_dma.c  | 52 ---
 sound/soc/soc-core.c  |  3 +-
 sound/soc/soc-generic-dmaengine-pcm.c | 12 ---
 6 files changed, 57 insertions(+), 25 deletions(-)

-- 
2.21.0



[RFC PATCH v2 1/3] ASoC: soc-card: export snd_soc_lookup_component_nolocked

2020-06-10 Thread Shengjiu Wang
snd_soc_lookup_component_nolocked can be used for the DPCM case
that Front-End needs to get the unused platform component but
added by Back-End cpu dai driver.

If the component is gotten, then we can get the dma chan created
by Back-End component and reused it in Front-End.

Signed-off-by: Shengjiu Wang 
---
 include/sound/soc.h  | 2 ++
 sound/soc/soc-core.c | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 74868436ac79..565612a8d690 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -444,6 +444,8 @@ int devm_snd_soc_register_component(struct device *dev,
 const struct snd_soc_component_driver 
*component_driver,
 struct snd_soc_dai_driver *dai_drv, int num_dai);
 void snd_soc_unregister_component(struct device *dev);
+struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev,
+   const char 
*driver_name);
 struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
   const char *driver_name);
 
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b07eca2c6ccc..d4c73e86d058 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -310,7 +310,7 @@ struct snd_soc_component *snd_soc_rtdcom_lookup(struct 
snd_soc_pcm_runtime *rtd,
 }
 EXPORT_SYMBOL_GPL(snd_soc_rtdcom_lookup);
 
-static struct snd_soc_component
+struct snd_soc_component
 *snd_soc_lookup_component_nolocked(struct device *dev, const char *driver_name)
 {
struct snd_soc_component *component;
@@ -329,6 +329,7 @@ static struct snd_soc_component
 
return found_component;
 }
+EXPORT_SYMBOL_GPL(snd_soc_lookup_component_nolocked);
 
 struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
   const char *driver_name)
-- 
2.21.0



[PATCH] ASoC: fsl_ssi: Fix bclk calculation for mono channel

2020-06-09 Thread Shengjiu Wang
For mono channel, ssi will switch to normal mode. In normal
mode, the Word Length Control bits control the word length
divider in clock generator, which is different with I2S master
mode, the word length is fixed to 32bit.

So we refine the famula for mono channel, otherwise there
will be sound issue for S24_LE.

Fixes: b0a7043d5c2c ("ASoC: fsl_ssi: Caculate bit clock rate using slot number 
and width")
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_ssi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index bad89b0d129e..e347776590f7 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -695,6 +695,11 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
/* Generate bit clock based on the slot number and slot width */
freq = slots * slot_width * params_rate(hw_params);
 
+   /* The slot_width is not fixed to 32 for normal mode */
+   if (params_channels(hw_params) == 1)
+   freq = (slots <= 1 ? 2 : slots) * params_width(hw_params) *
+  params_rate(hw_params);
+
/* Don't apply it to any non-baudclk circumstance */
if (IS_ERR(ssi->baudclk))
return -EINVAL;
-- 
2.21.0



[RFC PATCH] ASoC: fsl_asrc_dma: Fix warning "Cannot create DMA dma:tx symlink"

2020-06-08 Thread Shengjiu Wang
The issue log is:

[   48.021506] CPU: 0 PID: 664 Comm: aplay Not tainted 
5.7.0-rc1-13120-g12b434cbbea0 #343
[   48.031063] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[   48.037638] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[   48.045413] [] (show_stack) from [] 
(dump_stack+0xe4/0x118)
[   48.052757] [] (dump_stack) from [] 
(sysfs_warn_dup+0x50/0x64)
[   48.060357] [] (sysfs_warn_dup) from [] 
(sysfs_do_create_link_sd+0xc8/0xd4)
[   48.069086] [] (sysfs_do_create_link_sd) from [] 
(dma_request_chan+0xb0/0x210)
[   48.078068] [] (dma_request_chan) from [] 
(dma_request_slave_channel+0x8/0x14)
[   48.087060] [] (dma_request_slave_channel) from [] 
(fsl_asrc_dma_hw_params+0x1dc/0x434)
[   48.096831] [] (fsl_asrc_dma_hw_params) from [] 
(soc_pcm_hw_params+0x4b0/0x650)
[   48.105903] [] (soc_pcm_hw_params) from [] 
(dpcm_fe_dai_hw_params+0x70/0xe4)
[   48.114715] [] (dpcm_fe_dai_hw_params) from [] 
(snd_pcm_hw_params+0x158/0x418)
[   48.123701] [] (snd_pcm_hw_params) from [] 
(snd_pcm_ioctl+0x734/0x183c)
[   48.132079] [] (snd_pcm_ioctl) from [] 
(ksys_ioctl+0x2ac/0xb98)
[   48.139765] [] (ksys_ioctl) from [] 
(ret_fast_syscall+0x0/0x28)
[   48.147440] Exception stack(0xed3c5fa8 to 0xed3c5ff0)
[   48.152515] 5fa0:   bec28670 00e92870 0004 c25c4111 
bec28670 0002000f
[   48.160716] 5fc0: bec28670 00e92870 00e92820 0036 bb80  
0002c2f8 0003
[   48.168913] 5fe0: b6f4d3fc bec2853c b6ee7655 b6e22cf8
[   48.174236] fsl-esai-dai 2024000.esai: Cannot create DMA dma:tx symlink

The dma channel is already requested by Back-End cpu dai driver,
if fsl_asrc_dma requests dma chan with same dma:tx symlink, then
this warning comes out.

The warning is added by
commit 71723a96b8b1 ("dmaengine: Create symlinks between DMA channels and 
slaves")
commit bad83565eafe ("dmaengine: Cleanups for the slave <-> channel symlink 
support")

As the dma channel is requested by Back-End, we need to reuse the channel
and avoid to request a new one, then the issue can be fixed.

In order to get the dma channel which is already requested in Back-End.
we export two functions (snd_soc_lookup_component_nolocked and
soc_component_to_pcm), if we can get the dma channel, then reuse it.
if can't, then request a new one.

Signed-off-by: Shengjiu Wang 
---
 include/sound/dmaengine_pcm.h | 11 ++
 include/sound/soc.h   |  2 ++
 sound/soc/fsl/fsl_asrc_common.h   |  2 ++
 sound/soc/fsl/fsl_asrc_dma.c  | 49 +--
 sound/soc/soc-core.c  |  3 +-
 sound/soc/soc-generic-dmaengine-pcm.c | 12 ---
 6 files changed, 55 insertions(+), 24 deletions(-)

diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index b65220685920..8c5e38180fb0 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -161,4 +161,15 @@ int snd_dmaengine_pcm_prepare_slave_config(struct 
snd_pcm_substream *substream,
 
 #define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm"
 
+struct dmaengine_pcm {
+   struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
+   const struct snd_dmaengine_pcm_config *config;
+   struct snd_soc_component component;
+   unsigned int flags;
+};
+
+static inline struct dmaengine_pcm *soc_component_to_pcm(struct 
snd_soc_component *p)
+{
+   return container_of(p, struct dmaengine_pcm, component);
+}
 #endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 74868436ac79..565612a8d690 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -444,6 +444,8 @@ int devm_snd_soc_register_component(struct device *dev,
 const struct snd_soc_component_driver 
*component_driver,
 struct snd_soc_dai_driver *dai_drv, int num_dai);
 void snd_soc_unregister_component(struct device *dev);
+struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev,
+   const char 
*driver_name);
 struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
   const char *driver_name);
 
diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h
index 77665b15c8db..09512bc79b80 100644
--- a/sound/soc/fsl/fsl_asrc_common.h
+++ b/sound/soc/fsl/fsl_asrc_common.h
@@ -32,6 +32,7 @@ enum asrc_pair_index {
  * @dma_chan: inputer and output DMA channels
  * @dma_data: private dma data
  * @pos: hardware pointer position
+ * @req_dma_chan_dev_to_dev: flag for release dev_to_dev chan
  * @private: pair private area
  */
 struct fsl_asrc_pair {
@@ -45,6 +46,7 @@ struct fsl_asrc_pair {
struct dma_chan *dma_chan[2];
struct imx_dma_data dma_data;
unsigned int pos;
+   bool req_dma_chan_dev_to_dev;
 
void *private;
 };
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index d6a3fc5f87e5..3ad

[PATCH] ASoC: fsl-asoc-card: Defer probe when fail to find codec device

2020-06-04 Thread Shengjiu Wang
Defer probe when fail to find codec device, because the codec
device maybe probed later than machine driver.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl-asoc-card.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index cf4feb835743..00be73900888 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -581,7 +581,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
 
if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) {
dev_err(>dev, "failed to find codec device\n");
-   ret = -EINVAL;
+   ret = -EPROBE_DEFER;
goto asrc_fail;
}
 
-- 
2.21.0



[PATCH 3/3] ASoC: fsl_easrc: Fix "Function parameter not described" warnings

2020-06-02 Thread Shengjiu Wang
Obtained with:
$ make W=1

sound/soc/fsl/fsl_easrc.c:403: warning: Function parameter or member 'easrc' 
not described in 'fsl_easrc_normalize_filter'
sound/soc/fsl/fsl_easrc.c:403: warning: Function parameter or member 'infilter' 
not described in 'fsl_easrc_normalize_filter'
sound/soc/fsl/fsl_easrc.c:403: warning: Function parameter or member 
'outfilter' not described in 'fsl_easrc_normalize_filter'
sound/soc/fsl/fsl_easrc.c:403: warning: Function parameter or member 'shift' 
not described in 'fsl_easrc_normalize_filter'

Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers")
Signed-off-by: Shengjiu Wang 
Reported-by: kbuild test robot 
---
 sound/soc/fsl/fsl_easrc.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 7d8bf9d47842..2f6b3d8bfcfc 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -389,11 +389,11 @@ static int fsl_easrc_resampler_config(struct fsl_asrc 
*easrc)
  *  For input int[16, 24, 32] -> output float32
  *  scale it by multiplying filter coefficients by 2^-15, 2^-23, 2^-31
  *  input:
- *  asrc:  Structure pointer of fsl_asrc
- *  infilter : Pointer to non-scaled input filter
- *  shift:  The multiply factor
+ *  @easrc:  Structure pointer of fsl_asrc
+ *  @infilter : Pointer to non-scaled input filter
+ *  @shift:  The multiply factor
  *  output:
- *  outfilter: scaled filter
+ *  @outfilter: scaled filter
  */
 static int fsl_easrc_normalize_filter(struct fsl_asrc *easrc,
  u64 *infilter,
-- 
2.21.0



[PATCH 2/3] ASoC: fsl_easrc: Fix -Wunused-but-set-variable

2020-06-02 Thread Shengjiu Wang
Obtained with:
$ make W=1

sound/soc/fsl/fsl_easrc.c: In function 'fsl_easrc_set_rs_ratio':
sound/soc/fsl/fsl_easrc.c:182:15: warning: variable 'int_bits' set but not used 
[-Wunused-but-set-variable]
  unsigned int int_bits;
   ^
sound/soc/fsl/fsl_easrc.c: In function 'fsl_easrc_set_ctx_organziation':
sound/soc/fsl/fsl_easrc.c:1204:17: warning: variable 'dev' set but not used 
[-Wunused-but-set-variable]
  struct device *dev;
 ^
sound/soc/fsl/fsl_easrc.c: In function 'fsl_easrc_release_context':
sound/soc/fsl/fsl_easrc.c:1294:17: warning: variable 'dev' set but not used 
[-Wunused-but-set-variable]
  struct device *dev;
 ^
Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers")
Signed-off-by: Shengjiu Wang 
Reported-by: kbuild test robot 
---
 sound/soc/fsl/fsl_easrc.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index f227308a50e2..7d8bf9d47842 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -179,22 +179,21 @@ static int fsl_easrc_set_rs_ratio(struct fsl_asrc_pair 
*ctx)
struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
unsigned int in_rate = ctx_priv->in_params.norm_rate;
unsigned int out_rate = ctx_priv->out_params.norm_rate;
-   unsigned int int_bits;
unsigned int frac_bits;
u64 val;
u32 *r;
 
switch (easrc_priv->rs_num_taps) {
case EASRC_RS_32_TAPS:
-   int_bits = 5;
+   /* integer bits = 5; */
frac_bits = 39;
break;
case EASRC_RS_64_TAPS:
-   int_bits = 6;
+   /* integer bits = 6; */
frac_bits = 38;
break;
case EASRC_RS_128_TAPS:
-   int_bits = 7;
+   /* integer bits = 7; */
frac_bits = 37;
break;
default:
@@ -1201,7 +1200,6 @@ static int fsl_easrc_set_ctx_format(struct fsl_asrc_pair 
*ctx,
 static int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx)
 {
struct fsl_easrc_ctx_priv *ctx_priv;
-   struct device *dev;
struct fsl_asrc *easrc;
 
if (!ctx)
@@ -1209,7 +1207,6 @@ static int fsl_easrc_set_ctx_organziation(struct 
fsl_asrc_pair *ctx)
 
easrc = ctx->asrc;
ctx_priv = ctx->private;
-   dev = >pdev->dev;
 
/* input interleaving parameters */
regmap_update_bits(easrc->regmap, REG_EASRC_CIA(ctx->index),
@@ -1291,13 +1288,11 @@ static void fsl_easrc_release_context(struct 
fsl_asrc_pair *ctx)
 {
unsigned long lock_flags;
struct fsl_asrc *easrc;
-   struct device *dev;
 
if (!ctx)
return;
 
easrc = ctx->asrc;
-   dev = >pdev->dev;
 
spin_lock_irqsave(>lock, lock_flags);
 
-- 
2.21.0



[PATCH 0/3] ASoC: fsl_easrc: Fix several warnings

2020-06-02 Thread Shengjiu Wang
Fix several warnings with "make W=1"

Shengjiu Wang (3):
  ASoC: fsl_easrc: Fix -Wmissing-prototypes warning
  ASoC: fsl_easrc: Fix -Wunused-but-set-variable
  ASoC: fsl_easrc: Fix "Function parameter not described" warnings

 sound/soc/fsl/fsl_easrc.c | 42 +--
 1 file changed, 18 insertions(+), 24 deletions(-)

-- 
2.21.0



[PATCH 1/3] ASoC: fsl_easrc: Fix -Wmissing-prototypes warning

2020-06-02 Thread Shengjiu Wang
Obtained with:
$ make W=1

sound/soc/fsl/fsl_easrc.c:967:5: warning: no previous prototype for function 
'fsl_easrc_config_context' [-Wmissing-prototypes]
int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id)
^
sound/soc/fsl/fsl_easrc.c:967:1: note: declare 'static' if the function is not 
intended to be used outside of this translation unit
int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id)
^
static
sound/soc/fsl/fsl_easrc.c:1128:5: warning: no previous prototype for function 
'fsl_easrc_set_ctx_format' [-Wmissing-prototypes]
int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx,
^
sound/soc/fsl/fsl_easrc.c:1128:1: note: declare 'static' if the function is not 
intended to be used outside of this translation unit
int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx,
^
static
sound/soc/fsl/fsl_easrc.c:1201:5: warning: no previous prototype for function 
'fsl_easrc_set_ctx_organziation' [-Wmissing-prototypes]
int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx)
^
sound/soc/fsl/fsl_easrc.c:1201:1: note: declare 'static' if the function is not 
intended to be used outside of this translation unit
int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx)
^
static
sound/soc/fsl/fsl_easrc.c:1245:5: warning: no previous prototype for function 
'fsl_easrc_request_context' [-Wmissing-prototypes]
int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx)
^
sound/soc/fsl/fsl_easrc.c:1245:1: note: declare 'static' if the function is not 
intended to be used outside of this translation unit
int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx)
^
static
sound/soc/fsl/fsl_easrc.c:1290:6: warning: no previous prototype for function 
'fsl_easrc_release_context' [-Wmissing-prototypes]
void fsl_easrc_release_context(struct fsl_asrc_pair *ctx)
 ^
sound/soc/fsl/fsl_easrc.c:1290:1: note: declare 'static' if the function is not 
intended to be used outside of this translation unit
void fsl_easrc_release_context(struct fsl_asrc_pair *ctx)
^
static
sound/soc/fsl/fsl_easrc.c:1317:5: warning: no previous prototype for function 
'fsl_easrc_start_context' [-Wmissing-prototypes]
int fsl_easrc_start_context(struct fsl_asrc_pair *ctx)
^
sound/soc/fsl/fsl_easrc.c:1317:1: note: declare 'static' if the function is not 
intended to be used outside of this translation unit
int fsl_easrc_start_context(struct fsl_asrc_pair *ctx)
^
static
sound/soc/fsl/fsl_easrc.c:1335:5: warning: no previous prototype for function 
'fsl_easrc_stop_context' [-Wmissing-prototypes]
int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx)
^
sound/soc/fsl/fsl_easrc.c:1335:1: note: declare 'static' if the function is not 
intended to be used outside of this translation unit
int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx)
^
static
sound/soc/fsl/fsl_easrc.c:1382:18: warning: no previous prototype for function 
'fsl_easrc_get_dma_channel' [-Wmissing-prototypes]
struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx,
 ^
sound/soc/fsl/fsl_easrc.c:1382:1: note: declare 'static' if the function is not 
intended to be used outside of this translation unit
struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx,
^
static

Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers")
Signed-off-by: Shengjiu Wang 
Reported-by: kbuild test robot 
---
 sound/soc/fsl/fsl_easrc.c | 23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index c6b5eb2d2af7..f227308a50e2 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -964,7 +964,7 @@ static int fsl_easrc_release_slot(struct fsl_asrc *easrc, 
unsigned int ctx_id)
  *
  * Configure the register relate with context.
  */
-int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id)
+static int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int 
ctx_id)
 {
struct fsl_easrc_ctx_priv *ctx_priv;
struct fsl_asrc_pair *ctx;
@@ -1125,9 +1125,9 @@ static int fsl_easrc_process_format(struct fsl_asrc_pair 
*ctx,
return 0;
 }
 
-int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx,
-snd_pcm_format_t *in_raw_format,
-snd_pcm_format_t *out_raw_format)
+static int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx,
+   snd_pcm_format_t *in_raw_format,
+   snd_pcm_format_t *out_raw_format)
 {
struct fsl_asrc *easrc = ctx->asrc;
struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
@@ -1198,7 +1198,7 @@ int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx,
  * to conform with this format. Interleaving parameters are accessed
  * through the ASRC_CTRL_IN_ACCESSa and ASRC_CTRL_OUT_ACCESSa registers
  */
-int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *

[PATCH] ASoC: fsl_asrc: Fix -Wmissing-prototypes warning

2020-05-25 Thread Shengjiu Wang
From: shengjiu wang 

COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64

sound/soc/fsl/fsl_asrc.c:557:18: warning: no previous prototype for function 
'fsl_asrc_get_dma_channel' [-Wmissing-prototypes]
struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir)
 ^
sound/soc/fsl/fsl_asrc.c:557:1: note: declare 'static' if the function is not 
intended to be used outside of this translation unit
struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir)
^
static

Fixes: be7bd03f0201 ("ASoC: fsl_asrc: Move common definition to 
fsl_asrc_common")
Reported-by: kbuild test robot 
Signed-off-by: shengjiu wang 
---
 sound/soc/fsl/fsl_asrc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 7e2d598ffb81..d79d2c7f8d36 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -554,7 +554,8 @@ static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair)
 /**
  * Get DMA channel according to the pair and direction.
  */
-struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir)
+static struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair,
+bool dir)
 {
struct fsl_asrc *asrc = pair->asrc;
enum asrc_pair_index index = pair->index;
@@ -564,7 +565,6 @@ struct dma_chan *fsl_asrc_get_dma_channel(struct 
fsl_asrc_pair *pair, bool dir)
 
return dma_request_slave_channel(>pdev->dev, name);
 }
-EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel);
 
 static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
-- 
2.21.0



Re: [PATCH] ASoC: fsl_asrc: Merge suspend/resume function to runtime_suspend/resume

2020-05-25 Thread Shengjiu Wang
On Mon, May 25, 2020 at 1:12 PM Nicolin Chen  wrote:
>
> On Fri, May 22, 2020 at 05:57:24PM +0800, Shengjiu Wang wrote:
> > With dedicated power domain for asrc, power can be disabled after
> > probe and pm runtime suspend, then the value of all registers need to
> > be restored in pm runtime resume. So we can merge suspend/resume function
> > to runtime_suspend/resume function and enable regcache only in end of
> > probe.
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
> >  sound/soc/fsl/fsl_asrc.c | 70 
> >  1 file changed, 27 insertions(+), 43 deletions(-)
> >
> > diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
> > index 432936039de4..3ebbe15ac378 100644
> > --- a/sound/soc/fsl/fsl_asrc.c
> > +++ b/sound/soc/fsl/fsl_asrc.c
> > @@ -1100,6 +1100,7 @@ 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);
> >
> >   ret = devm_snd_soc_register_component(>dev, _asrc_component,
> > _asrc_dai, 1);
> > @@ -1117,6 +1118,7 @@ static int fsl_asrc_runtime_resume(struct device *dev)
> >   struct fsl_asrc *asrc = dev_get_drvdata(dev);
> >   struct fsl_asrc_priv *asrc_priv = asrc->private;
> >   int i, ret;
> > + u32 asrctr;
> >
> >   ret = clk_prepare_enable(asrc->mem_clk);
> >   if (ret)
> > @@ -1135,6 +1137,24 @@ static int fsl_asrc_runtime_resume(struct device 
> > *dev)
> >   goto disable_asrck_clk;
> >   }
> >
> > + /* Stop all pairs provisionally */
> > + regmap_read(asrc->regmap, REG_ASRCTR, );
> > + regmap_update_bits(asrc->regmap, REG_ASRCTR,
> > +ASRCTR_ASRCEi_ALL_MASK, 0);
> > +
> > + /* Restore all registers */
> > + regcache_cache_only(asrc->regmap, false);
> > + regcache_mark_dirty(asrc->regmap);
>
>
> I see you doing regcache_mark_dirty() in the resume() now,
> being different from previously doing in suspend()?
>
> Thanks
> Nic

Which is for probe -> runtime_resume case.
After probe, the power may be disabled, so move mark_dirtry
to runtime_resume, then regcache can re-write all the registers.

best regards
wang shengjiu

>
>
> > + regcache_sync(asrc->regmap);
> > +
> > + regmap_update_bits(asrc->regmap, REG_ASRCFG,
> > +ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK |
> > +ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg);
> > +
> > + /* Restart enabled pairs */
> > + regmap_update_bits(asrc->regmap, REG_ASRCTR,
> > +ASRCTR_ASRCEi_ALL_MASK, asrctr);
> > +
> >   return 0;
> >
> >  disable_asrck_clk:
> > @@ -1155,6 +1175,11 @@ static int fsl_asrc_runtime_suspend(struct device 
> > *dev)
> >   struct fsl_asrc_priv *asrc_priv = asrc->private;
> >   int i;
> >
> > + regmap_read(asrc->regmap, REG_ASRCFG,
> > + _priv->regcache_cfg);
> > +
> > + regcache_cache_only(asrc->regmap, true);
> > +
> >   for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
> >   clk_disable_unprepare(asrc_priv->asrck_clk[i]);
> >   if (!IS_ERR(asrc->spba_clk))
> > @@ -1166,51 +1191,10 @@ static int fsl_asrc_runtime_suspend(struct device 
> > *dev)
> >  }
> >  #endif /* CONFIG_PM */
> >
> > -#ifdef CONFIG_PM_SLEEP
> > -static int fsl_asrc_suspend(struct device *dev)
> > -{
> > - struct fsl_asrc *asrc = dev_get_drvdata(dev);
> > - struct fsl_asrc_priv *asrc_priv = asrc->private;
> > -
> > - regmap_read(asrc->regmap, REG_ASRCFG,
> > - _priv->regcache_cfg);
> > -
> > - regcache_cache_only(asrc->regmap, true);
> > - regcache_mark_dirty(asrc->regmap);
> > -
> > - return 0;
> > -}
> > -
> > -static int fsl_asrc_resume(struct device *dev)
> > -{
> > - struct fsl_asrc *asrc = dev_get_drvdata(dev);
> > - struct fsl_asrc_priv *asrc_priv = asrc->private;
> > - u32 asrctr;
> > -
> > - /* Stop all pairs provisionally */
> > - regmap_read(asrc->regmap, REG_ASRCTR, );
> > - regmap_update_bits(asrc->regmap, REG_ASRCTR,
> > -ASRCTR_ASRCEi_ALL_MASK, 0);
&g

[PATCH] ASoC: fsl_asrc: Merge suspend/resume function to runtime_suspend/resume

2020-05-22 Thread Shengjiu Wang
With dedicated power domain for asrc, power can be disabled after
probe and pm runtime suspend, then the value of all registers need to
be restored in pm runtime resume. So we can merge suspend/resume function
to runtime_suspend/resume function and enable regcache only in end of
probe.

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

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 432936039de4..3ebbe15ac378 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1100,6 +1100,7 @@ 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);
 
ret = devm_snd_soc_register_component(>dev, _asrc_component,
  _asrc_dai, 1);
@@ -1117,6 +1118,7 @@ static int fsl_asrc_runtime_resume(struct device *dev)
struct fsl_asrc *asrc = dev_get_drvdata(dev);
struct fsl_asrc_priv *asrc_priv = asrc->private;
int i, ret;
+   u32 asrctr;
 
ret = clk_prepare_enable(asrc->mem_clk);
if (ret)
@@ -1135,6 +1137,24 @@ static int fsl_asrc_runtime_resume(struct device *dev)
goto disable_asrck_clk;
}
 
+   /* Stop all pairs provisionally */
+   regmap_read(asrc->regmap, REG_ASRCTR, );
+   regmap_update_bits(asrc->regmap, REG_ASRCTR,
+  ASRCTR_ASRCEi_ALL_MASK, 0);
+
+   /* Restore all registers */
+   regcache_cache_only(asrc->regmap, false);
+   regcache_mark_dirty(asrc->regmap);
+   regcache_sync(asrc->regmap);
+
+   regmap_update_bits(asrc->regmap, REG_ASRCFG,
+  ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK |
+  ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg);
+
+   /* Restart enabled pairs */
+   regmap_update_bits(asrc->regmap, REG_ASRCTR,
+  ASRCTR_ASRCEi_ALL_MASK, asrctr);
+
return 0;
 
 disable_asrck_clk:
@@ -1155,6 +1175,11 @@ static int fsl_asrc_runtime_suspend(struct device *dev)
struct fsl_asrc_priv *asrc_priv = asrc->private;
int i;
 
+   regmap_read(asrc->regmap, REG_ASRCFG,
+   _priv->regcache_cfg);
+
+   regcache_cache_only(asrc->regmap, true);
+
for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
clk_disable_unprepare(asrc_priv->asrck_clk[i]);
if (!IS_ERR(asrc->spba_clk))
@@ -1166,51 +1191,10 @@ static int fsl_asrc_runtime_suspend(struct device *dev)
 }
 #endif /* CONFIG_PM */
 
-#ifdef CONFIG_PM_SLEEP
-static int fsl_asrc_suspend(struct device *dev)
-{
-   struct fsl_asrc *asrc = dev_get_drvdata(dev);
-   struct fsl_asrc_priv *asrc_priv = asrc->private;
-
-   regmap_read(asrc->regmap, REG_ASRCFG,
-   _priv->regcache_cfg);
-
-   regcache_cache_only(asrc->regmap, true);
-   regcache_mark_dirty(asrc->regmap);
-
-   return 0;
-}
-
-static int fsl_asrc_resume(struct device *dev)
-{
-   struct fsl_asrc *asrc = dev_get_drvdata(dev);
-   struct fsl_asrc_priv *asrc_priv = asrc->private;
-   u32 asrctr;
-
-   /* Stop all pairs provisionally */
-   regmap_read(asrc->regmap, REG_ASRCTR, );
-   regmap_update_bits(asrc->regmap, REG_ASRCTR,
-  ASRCTR_ASRCEi_ALL_MASK, 0);
-
-   /* Restore all registers */
-   regcache_cache_only(asrc->regmap, false);
-   regcache_sync(asrc->regmap);
-
-   regmap_update_bits(asrc->regmap, REG_ASRCFG,
-  ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK |
-  ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg);
-
-   /* Restart enabled pairs */
-   regmap_update_bits(asrc->regmap, REG_ASRCTR,
-  ASRCTR_ASRCEi_ALL_MASK, asrctr);
-
-   return 0;
-}
-#endif /* CONFIG_PM_SLEEP */
-
 static const struct dev_pm_ops fsl_asrc_pm = {
SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, 
NULL)
-   SET_SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume)
+   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+   pm_runtime_force_resume)
 };
 
 static const struct fsl_asrc_soc_data fsl_asrc_imx35_data = {
-- 
2.21.0



Re: [PATCH] ASoC: fsl: imx-pcm-dma: Don't request dma channel in probe

2020-05-21 Thread Shengjiu Wang
On Wed, May 20, 2020 at 8:38 PM Mark Brown  wrote:
>
> On Wed, May 20, 2020 at 07:22:19PM +0800, Shengjiu Wang wrote:
>
> > I see some driver also request dma channel in open() or hw_params().
> > how can they avoid the defer probe issue?
> > for example:
> > sound/arm/pxa2xx-pcm-lib.c
> > sound/soc/sprd/sprd-pcm-dma.c
>
> Other drivers having problems means those drivers should be fixed, not
> that we should copy the problems.  In the case of the PXA driver that's
> very old code which predates deferred probe by I'd guess a decade.

Thanks.

For the FE-BE case, do you have any suggestion for how fix it?

With DMA1->ASRC->DMA2->ESAI case, the DMA1->ASRC->DMA2
is in FE,  ESAI is in BE.  When ESAI drvier probe,  DMA3 channel is
created with ESAI's "dma:tx" (DMA3 channel
is not used in this FE-BE case).When FE-BE startup, DMA2
channel is created, it needs the ESAI's "dma:tx", so the warning
comes out.

best regards
wang shengjiu


Re: [PATCH] ASoC: fsl: imx-pcm-dma: Don't request dma channel in probe

2020-05-20 Thread Shengjiu Wang
Hi

On Wed, May 20, 2020 at 5:42 PM Lucas Stach  wrote:
>
> Am Mittwoch, den 20.05.2020, 16:20 +0800 schrieb Shengjiu Wang:
> > Hi
> >
> > On Tue, May 19, 2020 at 6:04 PM Lucas Stach  wrote:
> > > Am Dienstag, den 19.05.2020, 17:41 +0800 schrieb Shengjiu Wang:
> > > > There are two requirements that we need to move the request
> > > > of dma channel from probe to open.
> > >
> > > How do you handle -EPROBE_DEFER return code from the channel request if
> > > you don't do it in probe?
> >
> > I use the dma_request_slave_channel or dma_request_channel instead
> > of dmaengine_pcm_request_chan_of. so there should be not -EPROBE_DEFER
> > return code.
>
> This is a pretty weak argument. The dmaengine device might probe after
> you try to get the channel. Using a function to request the channel
> that doesn't allow you to handle probe deferral is IMHO a bug and
> should be fixed, instead of building even more assumptions on top of
> it.
>

I see some driver also request dma channel in open() or hw_params().
how can they avoid the defer probe issue?
for example:
sound/arm/pxa2xx-pcm-lib.c
sound/soc/sprd/sprd-pcm-dma.c

> > > > - When dma device binds with power-domains, the power will
> > > > be enabled when we request dma channel. If the request of dma
> > > > channel happen on probe, then the power-domains will be always
> > > > enabled after kernel boot up,  which is not good for power
> > > > saving,  so we need to move the request of dma channel to .open();
> > >
> > > This is certainly something which could be fixed in the dmaengine
> > > driver.
> >
> > Dma driver always call the pm_runtime_get_sync in
> > device_alloc_chan_resources, the device_alloc_chan_resources is
> > called when channel is requested. so power is enabled on channel
> > request.
>
> So why can't you fix the dmaengine driver to do that RPM call at a
> later time when the channel is actually going to be used? This will
> allow further power savings with other slave devices than the audio
> PCM.
>
> Regards,
> Lucas
>

It seems the best place for calling pm_runtime_get_sync is the
device_alloc_chan_resources, and calling pm_runtime_put_sync
in the .device_free_chan_resources

For the slave_sg mode, the .device_prep_slave_sg and
.device_issue_pending  will be called many times after
.device_alloc_chan_resources. so it is not good to call
pm_runtime_get_sync in .device_prep_slave_sg or
.device_issue_pending

best regards
wang shengjiu


Re: [PATCH] ASoC: fsl: imx-pcm-dma: Don't request dma channel in probe

2020-05-20 Thread Shengjiu Wang
Hi

On Tue, May 19, 2020 at 6:04 PM Lucas Stach  wrote:
>
> Am Dienstag, den 19.05.2020, 17:41 +0800 schrieb Shengjiu Wang:
> > There are two requirements that we need to move the request
> > of dma channel from probe to open.
>
> How do you handle -EPROBE_DEFER return code from the channel request if
> you don't do it in probe?

I use the dma_request_slave_channel or dma_request_channel instead
of dmaengine_pcm_request_chan_of. so there should be not -EPROBE_DEFER
return code.

>
> > - When dma device binds with power-domains, the power will
> > be enabled when we request dma channel. If the request of dma
> > channel happen on probe, then the power-domains will be always
> > enabled after kernel boot up,  which is not good for power
> > saving,  so we need to move the request of dma channel to .open();
>
> This is certainly something which could be fixed in the dmaengine
> driver.

Dma driver always call the pm_runtime_get_sync in
device_alloc_chan_resources, the device_alloc_chan_resources is
called when channel is requested. so power is enabled on channel
request.

>
> > - With FE-BE case, if the dma channel is requested in probe,
> > then there will be below issue, which is caused by that the
> > dma channel will be requested duplicately
>
> Why is this requested a second time? Is this just some missing cleanup
> on a deferred probe path?

Not relate with deferred probe.  With DMA1->ASRC->DMA2->ESAI case,
the DMA1->ASRC->DMA2 is in FE,  ESAI is in BE.  When ESAI drvier
probe,  DMA3 channel is created with ESAI's "dma:tx" (DMA3 channel
is not used in this FE-BE case).When FE-BE startup, DMA2
channel is created, it needs the ESAI's "dma:tx", so below warning
comes out.

>
> Regards,
> Lucas
>
> > [  638.906268] sysfs: cannot create duplicate filename 
> > '/devices/soc0/soc/200.bus/200.spba-bus/2024000.esai/dma:tx'
> > [  638.919061] CPU: 1 PID: 673 Comm: aplay Not tainted 
> > 5.7.0-rc1-12956-gfc64b2585593 #287
> > [  638.927113] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
> > [  638.933690] [] (unwind_backtrace) from [] 
> > (show_stack+0x10/0x14)
> > [  638.941464] [] (show_stack) from [] 
> > (dump_stack+0xe4/0x118)
> > [  638.948808] [] (dump_stack) from [] 
> > (sysfs_warn_dup+0x50/0x64)
> > [  638.956406] [] (sysfs_warn_dup) from [] 
> > (sysfs_do_create_link_sd+0xc8/0xd4)
> > [  638.965134] [] (sysfs_do_create_link_sd) from [] 
> > (dma_request_chan+0xb0/0x210)
> > [  638.974120] [] (dma_request_chan) from [] 
> > (dma_request_slave_channel+0x8/0x14)
> > [  638.983111] [] (dma_request_slave_channel) from [] 
> > (fsl_asrc_dma_hw_params+0x1e0/0x438)
> > [  638.992881] [] (fsl_asrc_dma_hw_params) from [] 
> > (soc_pcm_hw_params+0x4a0/0x6a8)
> > [  639.001952] [] (soc_pcm_hw_params) from [] 
> > (dpcm_fe_dai_hw_params+0x70/0xe4)
> > [  639.010765] [] (dpcm_fe_dai_hw_params) from [] 
> > (snd_pcm_hw_params+0x158/0x418)
> > [  639.019750] [] (snd_pcm_hw_params) from [] 
> > (snd_pcm_ioctl+0x734/0x183c)
> > [  639.028129] [] (snd_pcm_ioctl) from [] 
> > (ksys_ioctl+0x2ac/0xb98)
> > [  639.035812] [] (ksys_ioctl) from [] 
> > (ret_fast_syscall+0x0/0x28)
> > [  639.043490] Exception stack(0xec529fa8 to 0xec529ff0)
> > [  639.048565] 9fa0:       bee84650 01321870 0004 c25c4111 
> > bee84650 0002000f
> > [  639.056766] 9fc0: bee84650 01321870 01321820 0036 1f40  
> > 0002c2f8 0003
> > [  639.064964] 9fe0: b6f483fc bee8451c b6ee2655 b6e1dcf8
> > [  639.070339] fsl-esai-dai 2024000.esai: Cannot create DMA dma:tx symlink
> >
> > Signed-off-by: Shengjiu Wang 
> > ---
> >  sound/soc/fsl/imx-pcm-dma.c | 173 +---
> >  1 file changed, 159 insertions(+), 14 deletions(-)
> >
> > diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
> > index 04a9bc749016..dae53b384df4 100644
> > --- a/sound/soc/fsl/imx-pcm-dma.c
> > +++ b/sound/soc/fsl/imx-pcm-dma.c
> > @@ -11,6 +11,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  #include 
> >  #include 
> > @@ -29,24 +30,168 @@ static bool filter(struct dma_chan *chan, void *param)
> >   return true;
> >  }
> >
> > -static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
> > - .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
> > - .compat_filter_fn = filter,
> > -};
> > +static int imx_pcm_hw_params(struct snd_soc_component *component,
> > +   

[PATCH] ASoC: fsl: imx-pcm-dma: Don't request dma channel in probe

2020-05-19 Thread Shengjiu Wang
There are two requirements that we need to move the request
of dma channel from probe to open.

- When dma device binds with power-domains, the power will
be enabled when we request dma channel. If the request of dma
channel happen on probe, then the power-domains will be always
enabled after kernel boot up,  which is not good for power
saving,  so we need to move the request of dma channel to .open();

- With FE-BE case, if the dma channel is requested in probe,
then there will be below issue, which is caused by that the
dma channel will be requested duplicately

[  638.906268] sysfs: cannot create duplicate filename 
'/devices/soc0/soc/200.bus/200.spba-bus/2024000.esai/dma:tx'
[  638.919061] CPU: 1 PID: 673 Comm: aplay Not tainted 
5.7.0-rc1-12956-gfc64b2585593 #287
[  638.927113] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[  638.933690] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[  638.941464] [] (show_stack) from [] 
(dump_stack+0xe4/0x118)
[  638.948808] [] (dump_stack) from [] 
(sysfs_warn_dup+0x50/0x64)
[  638.956406] [] (sysfs_warn_dup) from [] 
(sysfs_do_create_link_sd+0xc8/0xd4)
[  638.965134] [] (sysfs_do_create_link_sd) from [] 
(dma_request_chan+0xb0/0x210)
[  638.974120] [] (dma_request_chan) from [] 
(dma_request_slave_channel+0x8/0x14)
[  638.983111] [] (dma_request_slave_channel) from [] 
(fsl_asrc_dma_hw_params+0x1e0/0x438)
[  638.992881] [] (fsl_asrc_dma_hw_params) from [] 
(soc_pcm_hw_params+0x4a0/0x6a8)
[  639.001952] [] (soc_pcm_hw_params) from [] 
(dpcm_fe_dai_hw_params+0x70/0xe4)
[  639.010765] [] (dpcm_fe_dai_hw_params) from [] 
(snd_pcm_hw_params+0x158/0x418)
[  639.019750] [] (snd_pcm_hw_params) from [] 
(snd_pcm_ioctl+0x734/0x183c)
[  639.028129] [] (snd_pcm_ioctl) from [] 
(ksys_ioctl+0x2ac/0xb98)
[  639.035812] [] (ksys_ioctl) from [] 
(ret_fast_syscall+0x0/0x28)
[  639.043490] Exception stack(0xec529fa8 to 0xec529ff0)
[  639.048565] 9fa0:   bee84650 01321870 0004 c25c4111 
bee84650 0002000f
[  639.056766] 9fc0: bee84650 01321870 01321820 0036 1f40  
0002c2f8 0003
[  639.064964] 9fe0: b6f483fc bee8451c b6ee2655 b6e1dcf8
[  639.070339] fsl-esai-dai 2024000.esai: Cannot create DMA dma:tx symlink

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/imx-pcm-dma.c | 173 +---
 1 file changed, 159 insertions(+), 14 deletions(-)

diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index 04a9bc749016..dae53b384df4 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -29,24 +30,168 @@ static bool filter(struct dma_chan *chan, void *param)
return true;
 }
 
-static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
-   .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
-   .compat_filter_fn = filter,
-};
+static int imx_pcm_hw_params(struct snd_soc_component *component,
+struct snd_pcm_substream *substream,
+struct snd_pcm_hw_params *params)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+   struct snd_dmaengine_dai_dma_data *dma_data;
+   struct dma_slave_config config;
+   struct dma_chan *chan;
+   int ret = 0;
 
-int imx_pcm_dma_init(struct platform_device *pdev, size_t size)
+   snd_pcm_set_runtime_buffer(substream, >dma_buffer);
+   runtime->dma_bytes = params_buffer_bytes(params);
+
+   chan = snd_dmaengine_pcm_get_chan(substream);
+   if (!chan)
+   return -EINVAL;
+
+   ret = snd_hwparams_to_dma_slave_config(substream, params, );
+   if (ret)
+   return ret;
+
+   dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
+   if (!dma_data)
+   return -EINVAL;
+
+   snd_dmaengine_pcm_set_config_from_dai_data(substream,
+  dma_data,
+  );
+   return dmaengine_slave_config(chan, );
+}
+
+static int imx_pcm_hw_free(struct snd_soc_component *component,
+  struct snd_pcm_substream *substream)
 {
-   struct snd_dmaengine_pcm_config *config;
+   snd_pcm_set_runtime_buffer(substream, NULL);
+   return 0;
+}
+
+static snd_pcm_uframes_t imx_pcm_pointer(struct snd_soc_component *component,
+struct snd_pcm_substream *substream)
+{
+   return snd_dmaengine_pcm_pointer(substream);
+}
+
+static int imx_pcm_trigger(struct snd_soc_component *component,
+  struct snd_pcm_substream *substream, int cmd)
+{
+   return snd_dmaengine_pcm_trigger(substream, cmd);
+}
+
+static int imx_pcm_open(struct snd_soc_componen

[PATCH v2 2/2] ASoC: fsl_esai: Add new compatible string for imx8qm

2020-05-15 Thread Shengjiu Wang
Add new compatible string "fsl,imx8qm-esai" in the binding document.

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

diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt 
b/Documentation/devicetree/bindings/sound/fsl,esai.txt
index 0e6e2166f76c..0a2480aeecf0 100644
--- a/Documentation/devicetree/bindings/sound/fsl,esai.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt
@@ -12,6 +12,7 @@ Required properties:
  "fsl,imx35-esai",
  "fsl,vf610-esai",
  "fsl,imx6ull-esai",
+ "fsl,imx8qm-esai",
 
   - reg: Offset and length of the register set for the 
device.
 
-- 
2.21.0



[PATCH v2 0/2] ASoC: fsl_esai: Add support for imx8qm

2020-05-15 Thread Shengjiu Wang
Add support for imx8qm.

Shengjiu Wang (2):
  ASoC: fsl_esai: introduce SoC specific data
  ASoC: fsl_esai: Add new compatible string for imx8qm

Changes in v2
- drop the 0002 patch in v1, the dma relate limitation should
  be done in dma driver, or define a new DMA API for it.


 .../devicetree/bindings/sound/fsl,esai.txt|  1 +
 sound/soc/fsl/fsl_esai.c  | 46 +++
 2 files changed, 38 insertions(+), 9 deletions(-)

-- 
2.21.0



[PATCH v2 1/2] ASoC: fsl_esai: introduce SoC specific data

2020-05-15 Thread Shengjiu Wang
Introduce a SoC specific data structure which contains the
differences between the different SoCs.
This makes it easier to support more differences without having
to introduce a new if/else each time.

Signed-off-by: Shengjiu Wang 
Acked-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_esai.c | 46 
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 84290be778f0..bac65ba7fbad 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -21,6 +21,17 @@
SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE)
 
+/**
+ * fsl_esai_soc_data: soc specific data
+ *
+ * @imx: for imx platform
+ * @reset_at_xrun: flags for enable reset operaton
+ */
+struct fsl_esai_soc_data {
+   bool imx;
+   bool reset_at_xrun;
+};
+
 /**
  * fsl_esai: ESAI private data
  *
@@ -33,6 +44,7 @@
  * @fsysclk: system clock source to derive HCK, SCK and FS
  * @spbaclk: SPBA clock (optional, depending on SoC design)
  * @task: tasklet to handle the reset operation
+ * @soc: soc specific data
  * @lock: spin lock between hw_reset() and trigger()
  * @fifo_depth: depth of tx/rx FIFO
  * @slot_width: width of each DAI slot
@@ -44,7 +56,6 @@
  * @sck_div: if using PSR/PM dividers for SCKx clock
  * @slave_mode: if fully using DAI slave mode
  * @synchronous: if using tx/rx synchronous mode
- * @reset_at_xrun: flags for enable reset operaton
  * @name: driver name
  */
 struct fsl_esai {
@@ -57,6 +68,7 @@ struct fsl_esai {
struct clk *fsysclk;
struct clk *spbaclk;
struct tasklet_struct task;
+   const struct fsl_esai_soc_data *soc;
spinlock_t lock; /* Protect hw_reset and trigger */
u32 fifo_depth;
u32 slot_width;
@@ -70,10 +82,24 @@ struct fsl_esai {
bool sck_div[2];
bool slave_mode;
bool synchronous;
-   bool reset_at_xrun;
char name[32];
 };
 
+static struct fsl_esai_soc_data fsl_esai_vf610 = {
+   .imx = false,
+   .reset_at_xrun = true,
+};
+
+static struct fsl_esai_soc_data fsl_esai_imx35 = {
+   .imx = true,
+   .reset_at_xrun = true,
+};
+
+static struct fsl_esai_soc_data fsl_esai_imx6ull = {
+   .imx = true,
+   .reset_at_xrun = false,
+};
+
 static irqreturn_t esai_isr(int irq, void *devid)
 {
struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
@@ -85,7 +111,7 @@ static irqreturn_t esai_isr(int irq, void *devid)
regmap_read(esai_priv->regmap, REG_ESAI_SAISR, );
 
if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) &&
-   esai_priv->reset_at_xrun) {
+   esai_priv->soc->reset_at_xrun) {
dev_dbg(>dev, "reset module for xrun\n");
regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR,
   ESAI_xCR_xEIE_MASK, 0);
@@ -936,9 +962,11 @@ static int fsl_esai_probe(struct platform_device *pdev)
esai_priv->pdev = pdev;
snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np);
 
-   if (of_device_is_compatible(np, "fsl,vf610-esai") ||
-   of_device_is_compatible(np, "fsl,imx35-esai"))
-   esai_priv->reset_at_xrun = true;
+   esai_priv->soc = of_device_get_match_data(>dev);
+   if (!esai_priv->soc) {
+   dev_err(>dev, "failed to get soc data\n");
+   return -ENODEV;
+   }
 
/* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1063,9 +1091,9 @@ static int fsl_esai_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id fsl_esai_dt_ids[] = {
-   { .compatible = "fsl,imx35-esai", },
-   { .compatible = "fsl,vf610-esai", },
-   { .compatible = "fsl,imx6ull-esai", },
+   { .compatible = "fsl,imx35-esai", .data = _esai_imx35 },
+   { .compatible = "fsl,vf610-esai", .data = _esai_vf610 },
+   { .compatible = "fsl,imx6ull-esai", .data = _esai_imx6ull },
{}
 };
 MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
-- 
2.21.0



Re: [PATCH 2/3] ASoC: fsl_esai: Add support for imx8qm

2020-05-15 Thread Shengjiu Wang
On Tue, May 12, 2020 at 8:38 PM Mark Brown  wrote:
>
> On Tue, May 12, 2020 at 10:48:41AM +0800, Shengjiu Wang wrote:
> > On Wed, May 6, 2020 at 10:33 AM Shengjiu Wang  
> > wrote:
> > > On Fri, May 1, 2020 at 6:23 PM Mark Brown  wrote:
>
> > > > > EDMA requires the period size to be multiple of maxburst. Otherwise
> > > > > the remaining bytes are not transferred and thus noise is produced.
>
> > > > If this constraint comes from the DMA controller then normally you'd
> > > > expect the DMA controller integration to be enforcing this - is there no
> > > > information in the DMA API that lets us know that this constraint is
> > > > there?
>
> > > No, I can't find one API for this.
> > > Do you have a recommendation?
>
> > could you please recommend which DMA API can I use?
>
> Not off-hand, you'd probably need to extend the API to export the
> information.

Thanks.  I will think about if I can find a better solution.
And I will drop this change and send v2 of this patch-set.


[PATCH] ASoC: fsl_asrc: Set ASR76K and ASR56K based on processing clock

2020-05-12 Thread Shengjiu Wang
The processing clock is different for platforms, so it is better
to set ASR76K and ASR56K based on processing clock, rather than
hard coding the value for them.

Signed-off-by: Shengjiu Wang 
Signed-off-by: Mihai Serban 
---
 sound/soc/fsl/fsl_asrc.c | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 067a54ab554f..ca926915068f 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -858,6 +858,8 @@ static const struct regmap_config fsl_asrc_regmap_config = {
  */
 static int fsl_asrc_init(struct fsl_asrc *asrc)
 {
+   unsigned long ipg_rate;
+
/* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */
regmap_write(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEN);
 
@@ -875,11 +877,14 @@ static int fsl_asrc_init(struct fsl_asrc *asrc)
regmap_update_bits(asrc->regmap, REG_ASRTFR1,
   ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc));
 
-   /* Set the processing clock for 76KHz to 133M */
-   regmap_write(asrc->regmap, REG_ASR76K, 0x06D6);
-
-   /* Set the processing clock for 56KHz to 133M */
-   return regmap_write(asrc->regmap, REG_ASR56K, 0x0947);
+   /*
+* Set the period of the 76KHz and 56KHz sampling clocks based on
+* the ASRC processing clock.
+* On iMX6, ipg_clk = 133MHz, REG_ASR76K = 0x06D6, REG_ASR56K = 0x0947
+*/
+   ipg_rate = clk_get_rate(asrc->ipg_clk);
+   regmap_write(asrc->regmap, REG_ASR76K, ipg_rate / 76000);
+   return regmap_write(asrc->regmap, REG_ASR56K, ipg_rate / 56000);
 }
 
 /**
-- 
2.21.0



Re: [PATCH 2/3] ASoC: fsl_esai: Add support for imx8qm

2020-05-11 Thread Shengjiu Wang
Hi Mark, Nicolin

On Wed, May 6, 2020 at 10:33 AM Shengjiu Wang  wrote:
>
> Hi
>
> On Fri, May 1, 2020 at 6:23 PM Mark Brown  wrote:
> >
> > On Fri, May 01, 2020 at 04:12:05PM +0800, Shengjiu Wang wrote:
> > > The difference for esai on imx8qm is that DMA device is EDMA.
> > >
> > > EDMA requires the period size to be multiple of maxburst. Otherwise
> > > the remaining bytes are not transferred and thus noise is produced.
> >
> > If this constraint comes from the DMA controller then normally you'd
> > expect the DMA controller integration to be enforcing this - is there no
> > information in the DMA API that lets us know that this constraint is
> > there?
>
> No, I can't find one API for this.
> Do you have a recommendation?
>
could you please recommend which DMA API can I use?

best regards
wang shengjiu


Re: [PATCH 2/3] ASoC: fsl_esai: Add support for imx8qm

2020-05-05 Thread Shengjiu Wang
Hi

On Fri, May 1, 2020 at 6:23 PM Mark Brown  wrote:
>
> On Fri, May 01, 2020 at 04:12:05PM +0800, Shengjiu Wang wrote:
> > The difference for esai on imx8qm is that DMA device is EDMA.
> >
> > EDMA requires the period size to be multiple of maxburst. Otherwise
> > the remaining bytes are not transferred and thus noise is produced.
>
> If this constraint comes from the DMA controller then normally you'd
> expect the DMA controller integration to be enforcing this - is there no
> information in the DMA API that lets us know that this constraint is
> there?

No, I can't find one API for this.
Do you have a recommendation?

best regards
wang shengjiu


[PATCH 1/3] ASoC: fsl_esai: introduce SoC specific data

2020-05-01 Thread Shengjiu Wang
Introduce a SoC specific data structure which contains the
differences between the different SoCs.
This makes it easier to support more differences without having
to introduce a new if/else each time.

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

diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 84290be778f0..bac65ba7fbad 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -21,6 +21,17 @@
SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE)
 
+/**
+ * fsl_esai_soc_data: soc specific data
+ *
+ * @imx: for imx platform
+ * @reset_at_xrun: flags for enable reset operaton
+ */
+struct fsl_esai_soc_data {
+   bool imx;
+   bool reset_at_xrun;
+};
+
 /**
  * fsl_esai: ESAI private data
  *
@@ -33,6 +44,7 @@
  * @fsysclk: system clock source to derive HCK, SCK and FS
  * @spbaclk: SPBA clock (optional, depending on SoC design)
  * @task: tasklet to handle the reset operation
+ * @soc: soc specific data
  * @lock: spin lock between hw_reset() and trigger()
  * @fifo_depth: depth of tx/rx FIFO
  * @slot_width: width of each DAI slot
@@ -44,7 +56,6 @@
  * @sck_div: if using PSR/PM dividers for SCKx clock
  * @slave_mode: if fully using DAI slave mode
  * @synchronous: if using tx/rx synchronous mode
- * @reset_at_xrun: flags for enable reset operaton
  * @name: driver name
  */
 struct fsl_esai {
@@ -57,6 +68,7 @@ struct fsl_esai {
struct clk *fsysclk;
struct clk *spbaclk;
struct tasklet_struct task;
+   const struct fsl_esai_soc_data *soc;
spinlock_t lock; /* Protect hw_reset and trigger */
u32 fifo_depth;
u32 slot_width;
@@ -70,10 +82,24 @@ struct fsl_esai {
bool sck_div[2];
bool slave_mode;
bool synchronous;
-   bool reset_at_xrun;
char name[32];
 };
 
+static struct fsl_esai_soc_data fsl_esai_vf610 = {
+   .imx = false,
+   .reset_at_xrun = true,
+};
+
+static struct fsl_esai_soc_data fsl_esai_imx35 = {
+   .imx = true,
+   .reset_at_xrun = true,
+};
+
+static struct fsl_esai_soc_data fsl_esai_imx6ull = {
+   .imx = true,
+   .reset_at_xrun = false,
+};
+
 static irqreturn_t esai_isr(int irq, void *devid)
 {
struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
@@ -85,7 +111,7 @@ static irqreturn_t esai_isr(int irq, void *devid)
regmap_read(esai_priv->regmap, REG_ESAI_SAISR, );
 
if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) &&
-   esai_priv->reset_at_xrun) {
+   esai_priv->soc->reset_at_xrun) {
dev_dbg(>dev, "reset module for xrun\n");
regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR,
   ESAI_xCR_xEIE_MASK, 0);
@@ -936,9 +962,11 @@ static int fsl_esai_probe(struct platform_device *pdev)
esai_priv->pdev = pdev;
snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np);
 
-   if (of_device_is_compatible(np, "fsl,vf610-esai") ||
-   of_device_is_compatible(np, "fsl,imx35-esai"))
-   esai_priv->reset_at_xrun = true;
+   esai_priv->soc = of_device_get_match_data(>dev);
+   if (!esai_priv->soc) {
+   dev_err(>dev, "failed to get soc data\n");
+   return -ENODEV;
+   }
 
/* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1063,9 +1091,9 @@ static int fsl_esai_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id fsl_esai_dt_ids[] = {
-   { .compatible = "fsl,imx35-esai", },
-   { .compatible = "fsl,vf610-esai", },
-   { .compatible = "fsl,imx6ull-esai", },
+   { .compatible = "fsl,imx35-esai", .data = _esai_imx35 },
+   { .compatible = "fsl,vf610-esai", .data = _esai_vf610 },
+   { .compatible = "fsl,imx6ull-esai", .data = _esai_imx6ull },
{}
 };
 MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
-- 
2.21.0



[PATCH 2/3] ASoC: fsl_esai: Add support for imx8qm

2020-05-01 Thread Shengjiu Wang
The difference for esai on imx8qm is that DMA device is EDMA.

EDMA requires the period size to be multiple of maxburst. Otherwise
the remaining bytes are not transferred and thus noise is produced.

We can handle this issue by adding a constraint on
SNDRV_PCM_HW_PARAM_PERIOD_SIZE to be multiple of tx/rx maxburst value.

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

diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index bac65ba7fbad..61b5c0bde788 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -26,10 +26,12 @@
  *
  * @imx: for imx platform
  * @reset_at_xrun: flags for enable reset operaton
+ * @use_edma: edma is used.
  */
 struct fsl_esai_soc_data {
bool imx;
bool reset_at_xrun;
+   bool use_edma;
 };
 
 /**
@@ -88,16 +90,25 @@ struct fsl_esai {
 static struct fsl_esai_soc_data fsl_esai_vf610 = {
.imx = false,
.reset_at_xrun = true,
+   .use_edma = false,
 };
 
 static struct fsl_esai_soc_data fsl_esai_imx35 = {
.imx = true,
.reset_at_xrun = true,
+   .use_edma = false,
 };
 
 static struct fsl_esai_soc_data fsl_esai_imx6ull = {
.imx = true,
.reset_at_xrun = false,
+   .use_edma = false,
+};
+
+static struct fsl_esai_soc_data fsl_esai_imx8qm = {
+   .imx = true,
+   .reset_at_xrun = false,
+   .use_edma = true,
 };
 
 static irqreturn_t esai_isr(int irq, void *devid)
@@ -513,6 +524,7 @@ static int fsl_esai_startup(struct snd_pcm_substream 
*substream,
struct snd_soc_dai *dai)
 {
struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+   bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
if (!dai->active) {
/* Set synchronous mode */
@@ -527,6 +539,12 @@ static int fsl_esai_startup(struct snd_pcm_substream 
*substream,
   ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
}
 
+   if (esai_priv->soc->use_edma)
+   snd_pcm_hw_constraint_step(substream->runtime, 0,
+  SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+  tx ? 
esai_priv->dma_params_tx.maxburst :
+  esai_priv->dma_params_rx.maxburst);
+
return 0;
 
 }
@@ -1094,6 +1112,7 @@ static const struct of_device_id fsl_esai_dt_ids[] = {
{ .compatible = "fsl,imx35-esai", .data = _esai_imx35 },
{ .compatible = "fsl,vf610-esai", .data = _esai_vf610 },
{ .compatible = "fsl,imx6ull-esai", .data = _esai_imx6ull },
+   { .compatible = "fsl,imx8qm-esai", .data = _esai_imx8qm },
{}
 };
 MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
-- 
2.21.0



[PATCH 3/3] ASoC: fsl_esai: Add new compatible string for imx8qm

2020-05-01 Thread Shengjiu Wang
Add new compatible string "fsl,imx8qm-esai" in the binding document.

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

diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt 
b/Documentation/devicetree/bindings/sound/fsl,esai.txt
index 0e6e2166f76c..0a2480aeecf0 100644
--- a/Documentation/devicetree/bindings/sound/fsl,esai.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt
@@ -12,6 +12,7 @@ Required properties:
  "fsl,imx35-esai",
  "fsl,vf610-esai",
  "fsl,imx6ull-esai",
+ "fsl,imx8qm-esai",
 
   - reg: Offset and length of the register set for the 
device.
 
-- 
2.21.0



[PATCH 0/3] ASoC: fsl_esai: Add support for imx8qm

2020-05-01 Thread Shengjiu Wang
Add support for imx8qm.

Shengjiu Wang (3):
  ASoC: fsl_esai: introduce SoC specific data
  ASoC: fsl_esai: Add support for imx8qm
  ASoC: fsl_esai: Add new compatible string for imx8qm

 .../devicetree/bindings/sound/fsl,esai.txt|  1 +
 sound/soc/fsl/fsl_esai.c  | 65 ---
 2 files changed, 57 insertions(+), 9 deletions(-)

-- 
2.21.0



[PATCH v2] ASoC: fsl_esai: Disable exception interrupt before scheduling tasklet

2020-04-27 Thread Shengjiu Wang
Disable exception interrupt before scheduling tasklet, otherwise if
the tasklet isn't handled immediately, there will be endless xrun
interrupt.

Fixes: 7ccafa2b3879 ("ASoC: fsl_esai: recover the channel swap after xrun")
Signed-off-by: Shengjiu Wang 
---
changes in v2
- Disable exception interrupt instead of remove tasklet.

 sound/soc/fsl/fsl_esai.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index c7a49d03463a..84290be778f0 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -87,6 +87,10 @@ static irqreturn_t esai_isr(int irq, void *devid)
if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) &&
esai_priv->reset_at_xrun) {
dev_dbg(>dev, "reset module for xrun\n");
+   regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR,
+  ESAI_xCR_xEIE_MASK, 0);
+   regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR,
+  ESAI_xCR_xEIE_MASK, 0);
tasklet_schedule(_priv->task);
}
 
-- 
2.21.0



Re: [PATCH] ASoC: fsl_esai: Remove the tasklet

2020-04-27 Thread Shengjiu Wang
On Fri, Apr 24, 2020 at 5:17 PM Nicolin Chen  wrote:
>
> On Fri, Apr 24, 2020 at 02:54:06PM +0800, Shengjiu Wang wrote:
> > Remove tasklet for it may cause the reset operation
> > can't be handled immediately, then there will be
> > endless xrun interrupt.
>
> The reset routine is really long and expensive, so not sure
> if it'd be good to do it completely inside HW ISR. Have you
> tried to clear xEIE bits to disable xrun interrupts, before
> scheduling the tasklet? If that does not solve the problem,
> we may go for this change.

Good idea, will send v2

best regards
wang shengjiu


Re: [PATCH v2] ASoC: fsl_easrc: Check for null pointer before dereferencing "ctx" in fsl_easrc_hw_free()

2020-04-25 Thread Shengjiu Wang
On Sat, Apr 25, 2020 at 3:30 PM Shengjiu Wang  wrote:
>
> The patch 955ac624058f: "ASoC: fsl_easrc: Add EASRC ASoC CPU DAI
> drivers" from Apr 16, 2020, leads to the following Smatch complaint:
>
> sound/soc/fsl/fsl_easrc.c:1529 fsl_easrc_hw_free()
> warn: variable dereferenced before check 'ctx' (see line 1527)
>
> sound/soc/fsl/fsl_easrc.c
>   1526  struct fsl_asrc_pair *ctx = runtime->private_data;
>   1527  struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
>   ^
> Dereference
>
>   1528
>   1529  if (ctx && (ctx_priv->ctx_streams & BIT(substream->stream))) {
> ^^^
> This check is too late, to prevent a NULL dereference.
>
>   1530  ctx_priv->ctx_streams &= ~BIT(substream->stream);
>   1531  fsl_easrc_release_context(ctx);
>
> Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers")
> Reported-by: Dan Carpenter 
> Signed-off-by: Shengjiu Wang 
> ---

Sorry,I forgot the changes:
changes in v2:
- refine the commit subject.

best regards
Wang shengjiu

>  sound/soc/fsl/fsl_easrc.c | 9 +++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
> index 97658e1f4989..20326bffab64 100644
> --- a/sound/soc/fsl/fsl_easrc.c
> +++ b/sound/soc/fsl/fsl_easrc.c
> @@ -1524,9 +1524,14 @@ static int fsl_easrc_hw_free(struct snd_pcm_substream 
> *substream,
>  {
> struct snd_pcm_runtime *runtime = substream->runtime;
> struct fsl_asrc_pair *ctx = runtime->private_data;
> -   struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
> +   struct fsl_easrc_ctx_priv *ctx_priv;
>
> -   if (ctx && (ctx_priv->ctx_streams & BIT(substream->stream))) {
> +   if (!ctx)
> +   return -EINVAL;
> +
> +   ctx_priv = ctx->private;
> +
> +   if (ctx_priv->ctx_streams & BIT(substream->stream)) {
> ctx_priv->ctx_streams &= ~BIT(substream->stream);
> fsl_easrc_release_context(ctx);
> }
> --
> 2.21.0
>


[PATCH v2] ASoC: fsl_easrc: Check for null pointer before dereferencing "ctx" in fsl_easrc_hw_free()

2020-04-25 Thread Shengjiu Wang
The patch 955ac624058f: "ASoC: fsl_easrc: Add EASRC ASoC CPU DAI
drivers" from Apr 16, 2020, leads to the following Smatch complaint:

sound/soc/fsl/fsl_easrc.c:1529 fsl_easrc_hw_free()
warn: variable dereferenced before check 'ctx' (see line 1527)

sound/soc/fsl/fsl_easrc.c
  1526  struct fsl_asrc_pair *ctx = runtime->private_data;
  1527  struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
  ^
Dereference

  1528
  1529  if (ctx && (ctx_priv->ctx_streams & BIT(substream->stream))) {
^^^
This check is too late, to prevent a NULL dereference.

  1530  ctx_priv->ctx_streams &= ~BIT(substream->stream);
  1531  fsl_easrc_release_context(ctx);

Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers")
Reported-by: Dan Carpenter 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_easrc.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 97658e1f4989..20326bffab64 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1524,9 +1524,14 @@ static int fsl_easrc_hw_free(struct snd_pcm_substream 
*substream,
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *ctx = runtime->private_data;
-   struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
+   struct fsl_easrc_ctx_priv *ctx_priv;
 
-   if (ctx && (ctx_priv->ctx_streams & BIT(substream->stream))) {
+   if (!ctx)
+   return -EINVAL;
+
+   ctx_priv = ctx->private;
+
+   if (ctx_priv->ctx_streams & BIT(substream->stream)) {
ctx_priv->ctx_streams &= ~BIT(substream->stream);
fsl_easrc_release_context(ctx);
}
-- 
2.21.0



[PATCH] ASoC: fsl_easrc: Check NULL pinter before dereference

2020-04-24 Thread Shengjiu Wang
The patch 955ac624058f: "ASoC: fsl_easrc: Add EASRC ASoC CPU DAI
drivers" from Apr 16, 2020, leads to the following Smatch complaint:

sound/soc/fsl/fsl_easrc.c:1529 fsl_easrc_hw_free()
warn: variable dereferenced before check 'ctx' (see line 1527)

sound/soc/fsl/fsl_easrc.c
  1526  struct fsl_asrc_pair *ctx = runtime->private_data;
  1527  struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
  ^
Dereference

  1528
  1529  if (ctx && (ctx_priv->ctx_streams & BIT(substream->stream))) {
^^^
This check is too late, to prevent a NULL dereference.

  1530  ctx_priv->ctx_streams &= ~BIT(substream->stream);
  1531  fsl_easrc_release_context(ctx);

Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers")
Reported-by: Dan Carpenter 
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_easrc.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 97658e1f4989..20326bffab64 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1524,9 +1524,14 @@ static int fsl_easrc_hw_free(struct snd_pcm_substream 
*substream,
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *ctx = runtime->private_data;
-   struct fsl_easrc_ctx_priv *ctx_priv = ctx->private;
+   struct fsl_easrc_ctx_priv *ctx_priv;
+
+   if (!ctx)
+   return -EINVAL;
+
+   ctx_priv = ctx->private;
 
-   if (ctx && (ctx_priv->ctx_streams & BIT(substream->stream))) {
+   if (ctx_priv->ctx_streams & BIT(substream->stream)) {
ctx_priv->ctx_streams &= ~BIT(substream->stream);
fsl_easrc_release_context(ctx);
}
-- 
2.21.0



[PATCH] ASoC: fsl_esai: Remove the tasklet

2020-04-24 Thread Shengjiu Wang
Remove tasklet for it may cause the reset operation
can't be handled immediately, then there will be
endless xrun interrupt.

Fixes: 7ccafa2b3879 ("ASoC: fsl_esai: recover the channel swap after xrun")
Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_esai.c | 15 ---
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index c7a49d03463a..1ad0859da5e2 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -32,7 +32,6 @@
  * @extalclk: esai clock source to derive HCK, SCK and FS
  * @fsysclk: system clock source to derive HCK, SCK and FS
  * @spbaclk: SPBA clock (optional, depending on SoC design)
- * @task: tasklet to handle the reset operation
  * @lock: spin lock between hw_reset() and trigger()
  * @fifo_depth: depth of tx/rx FIFO
  * @slot_width: width of each DAI slot
@@ -56,7 +55,6 @@ struct fsl_esai {
struct clk *extalclk;
struct clk *fsysclk;
struct clk *spbaclk;
-   struct tasklet_struct task;
spinlock_t lock; /* Protect hw_reset and trigger */
u32 fifo_depth;
u32 slot_width;
@@ -74,6 +72,8 @@ struct fsl_esai {
char name[32];
 };
 
+static void fsl_esai_hw_reset(struct fsl_esai *esai_priv);
+
 static irqreturn_t esai_isr(int irq, void *devid)
 {
struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
@@ -87,7 +87,7 @@ static irqreturn_t esai_isr(int irq, void *devid)
if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) &&
esai_priv->reset_at_xrun) {
dev_dbg(>dev, "reset module for xrun\n");
-   tasklet_schedule(_priv->task);
+   fsl_esai_hw_reset(esai_priv);
}
 
if (esr & ESAI_ESR_TINIT_MASK)
@@ -674,9 +674,8 @@ static void fsl_esai_trigger_stop(struct fsl_esai 
*esai_priv, bool tx)
   ESAI_xFCR_xFR, 0);
 }
 
-static void fsl_esai_hw_reset(unsigned long arg)
+static void fsl_esai_hw_reset(struct fsl_esai *esai_priv)
 {
-   struct fsl_esai *esai_priv = (struct fsl_esai *)arg;
bool tx = true, rx = false, enabled[2];
unsigned long lock_flags;
u32 tfcr, rfcr;
@@ -1034,9 +1033,6 @@ static int fsl_esai_probe(struct platform_device *pdev)
return ret;
}
 
-   tasklet_init(_priv->task, fsl_esai_hw_reset,
-(unsigned long)esai_priv);
-
pm_runtime_enable(>dev);
 
regcache_cache_only(esai_priv->regmap, true);
@@ -1050,10 +1046,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
 
 static int fsl_esai_remove(struct platform_device *pdev)
 {
-   struct fsl_esai *esai_priv = platform_get_drvdata(pdev);
-
pm_runtime_disable(>dev);
-   tasklet_kill(_priv->task);
 
return 0;
 }
-- 
2.21.0



Re: [PATCH] ASoC: fsl_esai: Remove expensive print in irq handler

2020-04-21 Thread Shengjiu Wang
Hi

On Tue, Apr 21, 2020 at 5:53 PM Mark Brown  wrote:
>
> On Tue, Apr 21, 2020 at 04:41:23PM +0800, Shengjiu Wang wrote:
> > Use dev_dbg instead of dev_err in irq handler, the dev_err
> > is expensive, we don't need the message to be printed everytime,
> > which is almost a debug option.
>
> >   if (esr & ESAI_ESR_RFF_MASK)
> > - dev_warn(>dev, "isr: Receiving overrun\n");
> > + dev_dbg(>dev, "isr: Receiving overrun\n");
> >
> >   if (esr & ESAI_ESR_TFE_MASK)
> > - dev_warn(>dev, "isr: Transmission underrun\n");
> > + dev_dbg(>dev, "isr: Transmission underrun\n");
>
> These are error messages which would suggest a problem that'd lead to
> data corruption, it seems bad not to try to flag that to the user -
> surely we've got bigger problems than performance if this happens?
> Perhaps convert to a ratelimited print if the issue is that when errors
> happen they happen a lot?

Thanks for review, I will rethink about this.

best regards
wang shengjiu


[PATCH] ASoC: fsl_esai: Remove expensive print in irq handler

2020-04-21 Thread Shengjiu Wang
Use dev_dbg instead of dev_err in irq handler, the dev_err
is expensive, we don't need the message to be printed everytime,
which is almost a debug option.

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

diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index c7a49d03463a..453392a9cd68 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -94,10 +94,10 @@ static irqreturn_t esai_isr(int irq, void *devid)
dev_dbg(>dev, "isr: Transmission Initialized\n");
 
if (esr & ESAI_ESR_RFF_MASK)
-   dev_warn(>dev, "isr: Receiving overrun\n");
+   dev_dbg(>dev, "isr: Receiving overrun\n");
 
if (esr & ESAI_ESR_TFE_MASK)
-   dev_warn(>dev, "isr: Transmission underrun\n");
+   dev_dbg(>dev, "isr: Transmission underrun\n");
 
if (esr & ESAI_ESR_TLS_MASK)
dev_dbg(>dev, "isr: Just transmitted the last slot\n");
-- 
2.21.0



[PATCH v9 7/7] ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers

2020-04-16 Thread Shengjiu Wang
EASRC (Enhanced Asynchronous Sample Rate Converter) is a new IP module
found on i.MX8MN. It is different with old ASRC module.

The primary features for the EASRC are as follows:
- 4 Contexts - groups of channels with an independent time base
- Fully independent and concurrent context control
- Simultaneous processing of up to 32 audio channels
- Programmable filter charachteristics for each context
- 32, 24, 20, and 16-bit fixed point audio sample support
- 32-bit floating point audio sample support
- 8kHz to 384kHz sample rate
- 1/16 to 8x sample rate conversion ratio

Signed-off-by: Shengjiu Wang 
Signed-off-by: Cosmin-Gabriel Samoila 
Acked-by: Nicolin Chen 
---
 sound/soc/fsl/Kconfig |   11 +
 sound/soc/fsl/Makefile|2 +
 sound/soc/fsl/fsl_easrc.c | 2114 +
 sound/soc/fsl/fsl_easrc.h |  651 
 4 files changed, 2778 insertions(+)
 create mode 100644 sound/soc/fsl/fsl_easrc.c
 create mode 100644 sound/soc/fsl/fsl_easrc.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 65e8cd4be930..ea7b4787a8af 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -84,6 +84,17 @@ config SND_SOC_FSL_MICFIL
  Say Y if you want to add Pulse Density Modulation microphone
  interface (MICFIL) support for NXP.
 
+config SND_SOC_FSL_EASRC
+   tristate "Enhanced Asynchronous Sample Rate Converter (EASRC) module 
support"
+   depends on SND_SOC_FSL_ASRC
+   select REGMAP_MMIO
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   help
+ Say Y if you want to add Enhanced ASRC support for NXP. The ASRC is
+ a digital module that converts audio from a source sample rate to a
+ destination sample rate. It is a new design module compare with the
+ old ASRC.
+
 config SND_SOC_FSL_UTILS
tristate
 
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 8cde88c72d93..b835eebf8825 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -24,6 +24,7 @@ snd-soc-fsl-micfil-objs := fsl_micfil.o
 snd-soc-fsl-utils-objs := fsl_utils.o
 snd-soc-fsl-dma-objs := fsl_dma.o
 snd-soc-fsl-mqs-objs := fsl_mqs.o
+snd-soc-fsl-easrc-objs := fsl_easrc.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
@@ -35,6 +36,7 @@ obj-$(CONFIG_SND_SOC_FSL_ESAI) += snd-soc-fsl-esai.o
 obj-$(CONFIG_SND_SOC_FSL_MICFIL) += snd-soc-fsl-micfil.o
 obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o
 obj-$(CONFIG_SND_SOC_FSL_MQS) += snd-soc-fsl-mqs.o
+obj-$(CONFIG_SND_SOC_FSL_EASRC) += snd-soc-fsl-easrc.o
 obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
 
 # MPC5200 Platform Support
diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
new file mode 100644
index ..233f26ff885c
--- /dev/null
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -0,0 +1,2114 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright 2019 NXP
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "fsl_easrc.h"
+#include "imx-pcm.h"
+
+#define FSL_EASRC_FORMATS   (SNDRV_PCM_FMTBIT_S16_LE | \
+SNDRV_PCM_FMTBIT_U16_LE | \
+SNDRV_PCM_FMTBIT_S24_LE | \
+SNDRV_PCM_FMTBIT_S24_3LE | \
+SNDRV_PCM_FMTBIT_U24_LE | \
+SNDRV_PCM_FMTBIT_U24_3LE | \
+SNDRV_PCM_FMTBIT_S32_LE | \
+SNDRV_PCM_FMTBIT_U32_LE | \
+SNDRV_PCM_FMTBIT_S20_3LE | \
+SNDRV_PCM_FMTBIT_U20_3LE | \
+SNDRV_PCM_FMTBIT_FLOAT_LE)
+
+static int fsl_easrc_iec958_put_bits(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+   struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+   struct fsl_asrc *easrc = snd_soc_component_get_drvdata(comp);
+   struct fsl_easrc_priv *easrc_priv = easrc->private;
+   struct soc_mreg_control *mc =
+   (struct soc_mreg_control *)kcontrol->private_value;
+   unsigned int regval = ucontrol->value.integer.value[0];
+
+   easrc_priv->bps_iec958[mc->regbase] = regval;
+
+   return 0;
+}
+
+static int fsl_easrc_iec958_get_bits(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+   struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+   struct fsl_asrc *easrc = snd_soc_component_get_drvdata(comp);
+   struct fsl_easrc_priv *easrc_priv = easrc->private;
+   struc

[PATCH v9 6/7] ASoC: dt-bindings: fsl_easrc: Add document for EASRC

2020-04-16 Thread Shengjiu Wang
EASRC (Enhanced Asynchronous Sample Rate Converter) is a new
IP module found on i.MX8MN.

Signed-off-by: Shengjiu Wang 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/sound/fsl,easrc.yaml  | 101 ++
 1 file changed, 101 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,easrc.yaml

diff --git a/Documentation/devicetree/bindings/sound/fsl,easrc.yaml 
b/Documentation/devicetree/bindings/sound/fsl,easrc.yaml
new file mode 100644
index ..73cdcf053a9c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,easrc.yaml
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/fsl,easrc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP Asynchronous Sample Rate Converter (ASRC) Controller
+
+maintainers:
+  - Shengjiu Wang 
+
+properties:
+  $nodename:
+pattern: "^easrc@.*"
+
+  compatible:
+const: fsl,imx8mn-easrc
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  clocks:
+items:
+  - description: Peripheral clock
+
+  clock-names:
+items:
+  - const: mem
+
+  dmas:
+maxItems: 8
+
+  dma-names:
+items:
+  - const: ctx0_rx
+  - const: ctx0_tx
+  - const: ctx1_rx
+  - const: ctx1_tx
+  - const: ctx2_rx
+  - const: ctx2_tx
+  - const: ctx3_rx
+  - const: ctx3_tx
+
+  firmware-name:
+allOf:
+  - $ref: /schemas/types.yaml#/definitions/string
+  - const: imx/easrc/easrc-imx8mn.bin
+description: The coefficient table for the filters
+
+  fsl,asrc-rate:
+allOf:
+  - $ref: /schemas/types.yaml#/definitions/uint32
+  - minimum: 8000
+  - maximum: 192000
+description: Defines a mutual sample rate used by DPCM Back Ends
+
+  fsl,asrc-format:
+allOf:
+  - $ref: /schemas/types.yaml#/definitions/uint32
+  - enum: [2, 6, 10, 32, 36]
+default: 2
+description:
+  Defines a mutual sample format used by DPCM Back Ends
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+  - firmware-name
+  - fsl,asrc-rate
+  - fsl,asrc-format
+
+examples:
+  - |
+#include 
+
+easrc: easrc@300c {
+   compatible = "fsl,imx8mn-easrc";
+   reg = <0x0 0x300c 0x0 0x1>;
+   interrupts = <0x0 122 0x4>;
+   clocks = < IMX8MN_CLK_ASRC_ROOT>;
+   clock-names = "mem";
+   dmas = < 16 23 0> , < 17 23 0>,
+  < 18 23 0> , < 19 23 0>,
+  < 20 23 0> , < 21 23 0>,
+  < 22 23 0> , < 23 23 0>;
+   dma-names = "ctx0_rx", "ctx0_tx",
+   "ctx1_rx", "ctx1_tx",
+   "ctx2_rx", "ctx2_tx",
+   "ctx3_rx", "ctx3_tx";
+   firmware-name = "imx/easrc/easrc-imx8mn.bin";
+   fsl,asrc-rate  = <8000>;
+   fsl,asrc-format = <2>;
+};
-- 
2.21.0



[PATCH v9 5/7] ASoC: fsl_asrc: Move common definition to fsl_asrc_common

2020-04-16 Thread Shengjiu Wang
There is a new ASRC included in i.MX serial platform, there
are some common definition can be shared with each other.
So move the common definition to a separate header file.

And add fsl_asrc_pair_priv and fsl_asrc_priv for
the variable specific for the module, which can be used
internally.

Signed-off-by: Shengjiu Wang 
Acked-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_asrc.c|  82 +++-
 sound/soc/fsl/fsl_asrc.h|  74 ++
 sound/soc/fsl/fsl_asrc_common.h | 106 
 sound/soc/fsl/fsl_asrc_dma.c|  25 
 4 files changed, 178 insertions(+), 109 deletions(-)
 create mode 100644 sound/soc/fsl/fsl_asrc_common.h

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index a9458fe268bc..067a54ab554f 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -308,8 +308,10 @@ static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair 
*pair,
  */
 static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool 
use_ideal_rate)
 {
-   struct asrc_config *config = pair->config;
+   struct fsl_asrc_pair_priv *pair_priv = pair->private;
+   struct asrc_config *config = pair_priv->config;
struct fsl_asrc *asrc = pair->asrc;
+   struct fsl_asrc_priv *asrc_priv = asrc->private;
enum asrc_pair_index index = pair->index;
enum asrc_word_width input_word_width;
enum asrc_word_width output_word_width;
@@ -392,11 +394,11 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair 
*pair, bool use_ideal_rate)
}
 
/* Validate input and output clock sources */
-   clk_index[IN] = asrc->clk_map[IN][config->inclk];
-   clk_index[OUT] = asrc->clk_map[OUT][config->outclk];
+   clk_index[IN] = asrc_priv->clk_map[IN][config->inclk];
+   clk_index[OUT] = asrc_priv->clk_map[OUT][config->outclk];
 
/* We only have output clock for ideal ratio mode */
-   clk = asrc->asrck_clk[clk_index[ideal ? OUT : IN]];
+   clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]];
 
clk_rate = clk_get_rate(clk);
rem[IN] = do_div(clk_rate, inrate);
@@ -417,7 +419,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, 
bool use_ideal_rate)
 
div[IN] = min_t(u32, 1024, div[IN]);
 
-   clk = asrc->asrck_clk[clk_index[OUT]];
+   clk = asrc_priv->asrck_clk[clk_index[OUT]];
clk_rate = clk_get_rate(clk);
if (ideal && use_ideal_rate)
rem[OUT] = do_div(clk_rate, IDEAL_RATIO_RATE);
@@ -437,13 +439,13 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair 
*pair, bool use_ideal_rate)
/* Set the channel number */
channels = config->channel_num;
 
-   if (asrc->soc->channel_bits < 4)
+   if (asrc_priv->soc->channel_bits < 4)
channels /= 2;
 
/* Update channels for current pair */
regmap_update_bits(asrc->regmap, REG_ASRCNCR,
-  ASRCNCR_ANCi_MASK(index, asrc->soc->channel_bits),
-  ASRCNCR_ANCi(index, channels, 
asrc->soc->channel_bits));
+  ASRCNCR_ANCi_MASK(index, 
asrc_priv->soc->channel_bits),
+  ASRCNCR_ANCi(index, channels, 
asrc_priv->soc->channel_bits));
 
/* Default setting: Automatic selection for processing mode */
regmap_update_bits(asrc->regmap, REG_ASRCTR,
@@ -568,9 +570,10 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream 
*substream,
struct snd_soc_dai *dai)
 {
struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai);
+   struct fsl_asrc_priv *asrc_priv = asrc->private;
 
/* Odd channel number is not valid for older ASRC (channel_bits==3) */
-   if (asrc->soc->channel_bits == 3)
+   if (asrc_priv->soc->channel_bits == 3)
snd_pcm_hw_constraint_step(substream->runtime, 0,
   SNDRV_PCM_HW_PARAM_CHANNELS, 2);
 
@@ -586,6 +589,7 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream 
*substream,
struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai);
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
+   struct fsl_asrc_pair_priv *pair_priv = pair->private;
unsigned int channels = params_channels(params);
unsigned int rate = params_rate(params);
struct asrc_config config;
@@ -597,7 +601,7 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream 
*substream,
return ret;
}
 
-   pair->config = 
+   pair_priv->config = 
 
config.pair = pair->index;
config.channel_num = channels;
@@ -931,9 +935,15 @@ static irqreturn_t fsl_asrc_isr(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
+

[PATCH v9 4/7] ASoC: fsl_asrc: Support new property fsl,asrc-format

2020-04-16 Thread Shengjiu Wang
In order to align with new ESARC, we add new property fsl,asrc-format.
The fsl,asrc-format can replace the fsl,asrc-width, driver
can accept format from devicetree, don't need to convert it to
format through width.

Signed-off-by: Shengjiu Wang 
Acked-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_asrc.c | 41 +++-
 sound/soc/fsl/fsl_asrc.h |  4 ++--
 sound/soc/fsl/fsl_asrc_dma.c | 15 ++---
 3 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 4d3e51bfa949..a9458fe268bc 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -589,7 +589,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream 
*substream,
unsigned int channels = params_channels(params);
unsigned int rate = params_rate(params);
struct asrc_config config;
-   snd_pcm_format_t format;
int ret;
 
ret = fsl_asrc_request_pair(channels, pair);
@@ -600,11 +599,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream 
*substream,
 
pair->config = 
 
-   if (asrc->asrc_width == 16)
-   format = SNDRV_PCM_FORMAT_S16_LE;
-   else
-   format = SNDRV_PCM_FORMAT_S24_LE;
-
config.pair = pair->index;
config.channel_num = channels;
config.inclk = INCLK_NONE;
@@ -612,11 +606,11 @@ static int fsl_asrc_dai_hw_params(struct 
snd_pcm_substream *substream,
 
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
config.input_format   = params_format(params);
-   config.output_format  = format;
+   config.output_format  = asrc->asrc_format;
config.input_sample_rate  = rate;
config.output_sample_rate = asrc->asrc_rate;
} else {
-   config.input_format   = format;
+   config.input_format   = asrc->asrc_format;
config.output_format  = params_format(params);
config.input_sample_rate  = asrc->asrc_rate;
config.output_sample_rate = rate;
@@ -946,6 +940,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
int irq, ret, i;
u32 map_idx;
char tmp[16];
+   u32 width;
 
asrc = devm_kzalloc(>dev, sizeof(*asrc), GFP_KERNEL);
if (!asrc)
@@ -1052,16 +1047,32 @@ static int fsl_asrc_probe(struct platform_device *pdev)
return ret;
}
 
-   ret = of_property_read_u32(np, "fsl,asrc-width",
-  >asrc_width);
+   ret = of_property_read_u32(np, "fsl,asrc-format", >asrc_format);
if (ret) {
-   dev_err(>dev, "failed to get output width\n");
-   return ret;
+   ret = of_property_read_u32(np, "fsl,asrc-width", );
+   if (ret) {
+   dev_err(>dev, "failed to decide output format\n");
+   return ret;
+   }
+
+   switch (width) {
+   case 16:
+   asrc->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
+   break;
+   case 24:
+   asrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
+   break;
+   default:
+   dev_warn(>dev,
+"unsupported width, use default S24_LE\n");
+   asrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
+   break;
+   }
}
 
-   if (asrc->asrc_width != 16 && asrc->asrc_width != 24) {
-   dev_warn(>dev, "unsupported width, switching to 24bit\n");
-   asrc->asrc_width = 24;
+   if (!(FSL_ASRC_FORMATS & (1ULL << asrc->asrc_format))) {
+   dev_warn(>dev, "unsupported width, use default S24_LE\n");
+   asrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
}
 
platform_set_drvdata(pdev, asrc);
diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h
index 95d62c45afde..3b0f156af2c3 100644
--- a/sound/soc/fsl/fsl_asrc.h
+++ b/sound/soc/fsl/fsl_asrc.h
@@ -493,7 +493,7 @@ struct fsl_asrc_pair {
  * @channel_avail: non-occupied channel numbers
  * @clk_map: clock map for input/output clock
  * @asrc_rate: default sample rate for ASoC Back-Ends
- * @asrc_width: default sample width for ASoC Back-Ends
+ * @asrc_format: default sample format for ASoC Back-Ends
  * @regcache_cfg: store register value of REG_ASRCFG
  */
 struct fsl_asrc {
@@ -514,7 +514,7 @@ struct fsl_asrc {
unsigned char *clk_map[2];
 
int asrc_rate;
-   int asrc_width;
+   snd_pcm_format_t asrc_format;
 
u32 regcache_cfg;
 };
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index 5fe83aece25b

[PATCH v9 1/7] ASoC: fsl_asrc: rename asrc_priv to asrc

2020-04-16 Thread Shengjiu Wang
In order to move common structure to fsl_asrc_common.h
we change the name of asrc_priv to asrc, the asrc_priv
will be used by new struct fsl_asrc_priv.

Signed-off-by: Shengjiu Wang 
Acked-by: Nicolin Chen 
---
 sound/soc/fsl/fsl_asrc.c | 298 +--
 sound/soc/fsl/fsl_asrc.h |   4 +-
 sound/soc/fsl/fsl_asrc_dma.c |  24 +--
 3 files changed, 163 insertions(+), 163 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 0dcebc24c312..4d3e51bfa949 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -21,10 +21,10 @@
 #define IDEAL_RATIO_DECIMAL_DEPTH 26
 
 #define pair_err(fmt, ...) \
-   dev_err(_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, 
##__VA_ARGS__)
+   dev_err(>pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
 
 #define pair_dbg(fmt, ...) \
-   dev_dbg(_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, 
##__VA_ARGS__)
+   dev_dbg(>pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
 
 /* Corresponding to process_option */
 static unsigned int supported_asrc_rate[] = {
@@ -157,15 +157,15 @@ static void fsl_asrc_sel_proc(int inrate, int outrate,
 int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
 {
enum asrc_pair_index index = ASRC_INVALID_PAIR;
-   struct fsl_asrc *asrc_priv = pair->asrc_priv;
-   struct device *dev = _priv->pdev->dev;
+   struct fsl_asrc *asrc = pair->asrc;
+   struct device *dev = >pdev->dev;
unsigned long lock_flags;
int i, ret = 0;
 
-   spin_lock_irqsave(_priv->lock, lock_flags);
+   spin_lock_irqsave(>lock, lock_flags);
 
for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) {
-   if (asrc_priv->pair[i] != NULL)
+   if (asrc->pair[i] != NULL)
continue;
 
index = i;
@@ -177,17 +177,17 @@ int fsl_asrc_request_pair(int channels, struct 
fsl_asrc_pair *pair)
if (index == ASRC_INVALID_PAIR) {
dev_err(dev, "all pairs are busy now\n");
ret = -EBUSY;
-   } else if (asrc_priv->channel_avail < channels) {
+   } else if (asrc->channel_avail < channels) {
dev_err(dev, "can't afford required channels: %d\n", channels);
ret = -EINVAL;
} else {
-   asrc_priv->channel_avail -= channels;
-   asrc_priv->pair[index] = pair;
+   asrc->channel_avail -= channels;
+   asrc->pair[index] = pair;
pair->channels = channels;
pair->index = index;
}
 
-   spin_unlock_irqrestore(_priv->lock, lock_flags);
+   spin_unlock_irqrestore(>lock, lock_flags);
 
return ret;
 }
@@ -195,25 +195,25 @@ int fsl_asrc_request_pair(int channels, struct 
fsl_asrc_pair *pair)
 /**
  * Release ASRC pair
  *
- * It clears the resource from asrc_priv and releases the occupied channels.
+ * It clears the resource from asrc and releases the occupied channels.
  */
 void fsl_asrc_release_pair(struct fsl_asrc_pair *pair)
 {
-   struct fsl_asrc *asrc_priv = pair->asrc_priv;
+   struct fsl_asrc *asrc = pair->asrc;
enum asrc_pair_index index = pair->index;
unsigned long lock_flags;
 
/* Make sure the pair is disabled */
-   regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
+   regmap_update_bits(asrc->regmap, REG_ASRCTR,
   ASRCTR_ASRCEi_MASK(index), 0);
 
-   spin_lock_irqsave(_priv->lock, lock_flags);
+   spin_lock_irqsave(>lock, lock_flags);
 
-   asrc_priv->channel_avail += pair->channels;
-   asrc_priv->pair[index] = NULL;
+   asrc->channel_avail += pair->channels;
+   asrc->pair[index] = NULL;
pair->error = 0;
 
-   spin_unlock_irqrestore(_priv->lock, lock_flags);
+   spin_unlock_irqrestore(>lock, lock_flags);
 }
 
 /**
@@ -221,10 +221,10 @@ void fsl_asrc_release_pair(struct fsl_asrc_pair *pair)
  */
 static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 
out)
 {
-   struct fsl_asrc *asrc_priv = pair->asrc_priv;
+   struct fsl_asrc *asrc = pair->asrc;
enum asrc_pair_index index = pair->index;
 
-   regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
+   regmap_update_bits(asrc->regmap, REG_ASRMCR(index),
   ASRMCRi_EXTTHRSHi_MASK |
   ASRMCRi_INFIFO_THRESHOLD_MASK |
   ASRMCRi_OUTFIFO_THRESHOLD_MASK,
@@ -257,7 +257,7 @@ static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair 
*pair, u32 div)
 static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair,
int inrate, int outrate)
 {
-   struct fsl_asrc *asrc_priv = p

[PATCH v9 0/7] ASoC: Add new module driver for new ASRC

2020-04-16 Thread Shengjiu Wang
Add new module driver for new ASRC in i.MX8MN, several commits
are added for new property fsl,asrc-format

Shengjiu Wang (7):
  ASoC: fsl_asrc: rename asrc_priv to asrc
  ASoC: dt-bindings: fsl_asrc: Add new property fsl,asrc-format
  ASoC: fsl-asoc-card: Support new property fsl,asrc-format
  ASoC: fsl_asrc: Support new property fsl,asrc-format
  ASoC: fsl_asrc: Move common definition to fsl_asrc_common
  ASoC: dt-bindings: fsl_easrc: Add document for EASRC
  ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers

changes in v9
- use lowercase for dt example.

changes in v8
- change get_pair_priv_size to pair_priv_size variable

changes in v7
- updated according to Nicoin's comments.
- add get_pair_priv_size to replace PAIR_PRIVATE_SIZE

changes in v6
- updated according to Nicoin's and Rob's comments.

changes in v5
- Add new property fsl,asrc-format, rather than change fsl,asrc-width
  to fsl,asrc-formt.
- code change for above change.

changes in v4
- Add several commit for changing DT binding asrc-width to asrc-format
- rename asrc_priv to asrc

changes in v3
- add new commit "ASoC: fsl_asrc: Change asrc_width to asrc_format"
- modify binding doc to yaml format
- remove fsl_easrc_dma.c, make fsl_asrc_dma.c useable for easrc.

changes in v2
- change i.MX815 to i.MX8MN
- Add changes in Kconfig and Makefile

 .../devicetree/bindings/sound/fsl,asrc.txt|4 +
 .../devicetree/bindings/sound/fsl,easrc.yaml  |  101 +
 sound/soc/fsl/Kconfig |   11 +
 sound/soc/fsl/Makefile|2 +
 sound/soc/fsl/fsl-asoc-card.c |   24 +-
 sound/soc/fsl/fsl_asrc.c  |  305 +--
 sound/soc/fsl/fsl_asrc.h  |   74 +-
 sound/soc/fsl/fsl_asrc_common.h   |  106 +
 sound/soc/fsl/fsl_asrc_dma.c  |   54 +-
 sound/soc/fsl/fsl_easrc.c | 2114 +
 sound/soc/fsl/fsl_easrc.h |  651 +
 11 files changed, 3212 insertions(+), 234 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,easrc.yaml
 create mode 100644 sound/soc/fsl/fsl_asrc_common.h
 create mode 100644 sound/soc/fsl/fsl_easrc.c
 create mode 100644 sound/soc/fsl/fsl_easrc.h

-- 
2.21.0



[PATCH v9 3/7] ASoC: fsl-asoc-card: Support new property fsl, asrc-format

2020-04-16 Thread Shengjiu Wang
In order to align with new ESARC, we add new property fsl,asrc-format.
The fsl,asrc-format can replace the fsl,asrc-width, driver
can accept format from devicetree, don't need to convert it to
format through width.

Signed-off-by: Shengjiu Wang 
Acked-by: Nicolin Chen 
---
 sound/soc/fsl/fsl-asoc-card.c | 24 +++-
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index bb33601fab84..cf4feb835743 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -680,17 +680,23 @@ static int fsl_asoc_card_probe(struct platform_device 
*pdev)
goto asrc_fail;
}
 
-   ret = of_property_read_u32(asrc_np, "fsl,asrc-width", );
+   ret = of_property_read_u32(asrc_np, "fsl,asrc-format",
+  >asrc_format);
if (ret) {
-   dev_err(>dev, "failed to get output rate\n");
-   ret = -EINVAL;
-   goto asrc_fail;
-   }
+   /* Fallback to old binding; translate to asrc_format */
+   ret = of_property_read_u32(asrc_np, "fsl,asrc-width",
+  );
+   if (ret) {
+   dev_err(>dev,
+   "failed to decide output format\n");
+   goto asrc_fail;
+   }
 
-   if (width == 24)
-   priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
-   else
-   priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
+   if (width == 24)
+   priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
+   else
+   priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
+   }
}
 
/* Finish card registering */
-- 
2.21.0



[PATCH v9 2/7] ASoC: dt-bindings: fsl_asrc: Add new property fsl, asrc-format

2020-04-16 Thread Shengjiu Wang
In order to support new EASRC and simplify the code structure,
We decide to share the common structure between them. This bring
a problem that EASRC accept format directly from devicetree, but
ASRC accept width from devicetree.

In order to align with new ESARC, we add new property fsl,asrc-format.
The fsl,asrc-format can replace the fsl,asrc-width, then driver
can accept format from devicetree, don't need to convert it to
format through width.

Signed-off-by: Shengjiu Wang 
Acked-by: Nicolin Chen 
Acked-by: Rob Herring 
---
 Documentation/devicetree/bindings/sound/fsl,asrc.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/fsl,asrc.txt 
b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
index cb9a25165503..998b4c8a7f78 100644
--- a/Documentation/devicetree/bindings/sound/fsl,asrc.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
@@ -51,6 +51,10 @@ Optional properties:
  will be in use as default. Otherwise, the big endian
  mode will be in use for all the device registers.
 
+   - fsl,asrc-format   : Defines a mutual sample format used by DPCM Back
+ Ends, which can replace the fsl,asrc-width.
+ The value is 2 (S16_LE), or 6 (S24_LE).
+
 Example:
 
 asrc: asrc@2034000 {
-- 
2.21.0



  1   2   3   >