2023-12-13 12:36:27

by Jianhua Lu

[permalink] [raw]
Subject: [PATCH v3 1/4] ASoC: qcom: common: Add qcom_snd_tdm_hw_params function

Add qcom TDM setup function to support TDM ports for qcom platform.

Signed-off-by: Jianhua Lu <[email protected]>
---
Changes in v3:
1. new patch
2. split qcom_snd_tdm_hw_params function from [Patch v2 1/2] to here

sound/soc/qcom/common.c | 69 +++++++++++++++++++++++++++++++++++++++++
sound/soc/qcom/common.h | 2 ++
2 files changed, 71 insertions(+)

diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c
index 483bbf53a541..c0ab201416ef 100644
--- a/sound/soc/qcom/common.c
+++ b/sound/soc/qcom/common.c
@@ -5,6 +5,7 @@
#include <dt-bindings/sound/qcom,q6afe.h>
#include <linux/module.h>
#include <sound/jack.h>
+#include <sound/pcm_params.h>
#include <linux/input-event-codes.h>
#include "common.h"

@@ -13,6 +14,8 @@ static const struct snd_soc_dapm_widget qcom_jack_snd_widgets[] = {
SND_SOC_DAPM_MIC("Mic Jack", NULL),
};

+static unsigned int tdm_slot_offset[8] = { 0, 4, 8, 12, 16, 20, 24, 28 };
+
int qcom_snd_parse_of(struct snd_soc_card *card)
{
struct device_node *np;
@@ -239,4 +242,70 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
EXPORT_SYMBOL_GPL(qcom_snd_wcd_jack_setup);
+
+int qcom_snd_tdm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ int slots = ARRAY_SIZE(tdm_slot_offset);
+ int channels, slot_width, tx_mask, rx_mask;
+ int ret;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ slot_width = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ slot_width = 24;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ slot_width = 32;
+ break;
+ default:
+ dev_err(rtd->dev, "%s: invalid param format 0x%x\n", __func__,
+ params_format(params));
+ return -EINVAL;
+ }
+
+ channels = params_channels(params);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ tx_mask = 0;
+ rx_mask = BIT(channels) - 1;
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, rx_mask, slots, slot_width);
+ if (ret < 0) {
+ dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL, channels,
+ tdm_slot_offset);
+ if (ret < 0) {
+ dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
+ __func__, ret);
+ return ret;
+ }
+ } else {
+ tx_mask = 0xf;
+ rx_mask = 0;
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, rx_mask, slots, slot_width);
+ if (ret < 0) {
+ dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
+ tdm_slot_offset, 0, NULL);
+ if (ret < 0) {
+ dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_snd_tdm_hw_params);
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/qcom/common.h b/sound/soc/qcom/common.h
index d7f80ee5ae26..b583110f556e 100644
--- a/sound/soc/qcom/common.h
+++ b/sound/soc/qcom/common.h
@@ -9,5 +9,7 @@
int qcom_snd_parse_of(struct snd_soc_card *card);
int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_jack *jack, bool *jack_setup);
+int qcom_snd_tdm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params);

#endif
--
2.41.0


2023-12-13 12:36:36

by Jianhua Lu

[permalink] [raw]
Subject: [PATCH v3 2/4] ASoC: qcom: sdm845: switch to qcom_snd_tdm_hw_params helper

Use qcom_snd_tdm_hw_params helper to setup TDM ports.

Signed-off-by: Jianhua Lu <[email protected]>
---
Changes in v3:
1. new patch

sound/soc/qcom/sdm845.c | 46 +++++++----------------------------------
1 file changed, 7 insertions(+), 39 deletions(-)

diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index 252a0f0819be..5052c1410723 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -53,8 +53,6 @@ static struct snd_soc_jack_pin sdm845_jack_pins[] = {
},
};

-static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28};
-
static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -99,10 +97,9 @@ static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai;
int ret = 0, j;
- int channels, slot_width;
+ int slot_width;

switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
@@ -114,39 +111,11 @@ static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}

- channels = params_channels(params);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0x3,
- 8, slot_width);
- if (ret < 0) {
- dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
- __func__, ret);
- goto end;
- }
-
- ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
- channels, tdm_slot_offset);
- if (ret < 0) {
- dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
- __func__, ret);
- goto end;
- }
- } else {
- ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0,
- 8, slot_width);
- if (ret < 0) {
- dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
- __func__, ret);
- goto end;
- }
-
- ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
- tdm_slot_offset, 0, NULL);
- if (ret < 0) {
- dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
- __func__, ret);
- goto end;
- }
+ ret = qcom_snd_tdm_hw_params(substream, params);
+ if (ret < 0) {
+ dev_err(rtd->dev, "%s: failed to setup TDM err:%d\n",
+ __func__, ret);
+ return ret;
}

for_each_rtd_codec_dais(rtd, j, codec_dai) {
@@ -176,8 +145,7 @@ static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
}
}

-end:
- return ret;
+ return 0;
}

static int sdm845_snd_hw_params(struct snd_pcm_substream *substream,
--
2.41.0

2023-12-13 12:36:50

by Jianhua Lu

[permalink] [raw]
Subject: [PATCH v3 3/4] Asoc: qcom: sdw: Add TDM support

Setup TDM ports when dai id is matched to *_TDM_*.

Signed-off-by: Jianhua Lu <[email protected]>
---
Changes in v3:
1. split qcom_snd_tdm_hw_params function to common.c

Changes in v2:
1. remove EXPORT_SYMBOL_GPL
2. remove static modifier

sound/soc/qcom/sdw.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
index 77dbe0c28b29..c07d878a1c18 100644
--- a/sound/soc/qcom/sdw.c
+++ b/sound/soc/qcom/sdw.c
@@ -5,6 +5,7 @@
#include <dt-bindings/sound/qcom,q6afe.h>
#include <linux/module.h>
#include <sound/soc.h>
+#include "common.h"
#include "sdw.h"

/**
@@ -109,7 +110,7 @@ int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct sdw_stream_runtime *sruntime;
- int i;
+ int ret, i;

switch (cpu_dai->id) {
case WSA_CODEC_DMA_RX_0:
@@ -125,6 +126,14 @@ int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
*psruntime = sruntime;
}
break;
+ case PRIMARY_TDM_RX_0...QUINARY_TDM_TX_7:
+ ret = qcom_snd_tdm_hw_params(substream, params);
+ if (ret < 0) {
+ dev_err(rtd->dev, "%s: failed to setup TDM err:%d\n",
+ __func__, ret);
+ return ret;
+ }
+ break;
}

return 0;
--
2.41.0

2023-12-13 12:37:05

by Jianhua Lu

[permalink] [raw]
Subject: [PATCH v3 4/4] ASoC: qcom: sm8250: Add TERTIARY_TDM_RX_0 support

Add TERTIARY_TDM_RX_0 case to make speaker amplifiers working
on Xiaomi Pad 5 Pro tablet.

Signed-off-by: Jianhua Lu <[email protected]>
---
No changes in v3.

No changes in v2.

sound/soc/qcom/sm8250.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c
index f298167c2a23..00c89c073e72 100644
--- a/sound/soc/qcom/sm8250.c
+++ b/sound/soc/qcom/sm8250.c
@@ -16,6 +16,7 @@

#define DRIVER_NAME "sm8250"
#define MI2S_BCLK_RATE 1536000
+#define TDM_BCLK_RATE 12288000

struct sm8250_snd_data {
bool stream_prepared[AFE_PORT_MAX];
@@ -53,6 +54,7 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
+ int ret, j;

switch (cpu_dai->id) {
case TERTIARY_MI2S_RX:
@@ -63,6 +65,23 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream)
snd_soc_dai_set_fmt(cpu_dai, fmt);
snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
break;
+ case TERTIARY_TDM_RX_0:
+ codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_DSP_A;
+ snd_soc_dai_set_sysclk(cpu_dai,
+ Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT,
+ TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
+
+ for_each_rtd_codec_dais(rtd, j, codec_dai) {
+ ret = snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
+ snd_soc_dai_set_sysclk(codec_dai,
+ 0,
+ TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret < 0) {
+ dev_err(rtd->dev, "TDM fmt err:%d\n", ret);
+ return ret;
+ }
+ }
+ break;
default:
break;
}
--
2.41.0

2023-12-14 11:11:45

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] ASoC: qcom: common: Add qcom_snd_tdm_hw_params function

On Wed, Dec 13, 2023 at 08:35:53PM +0800, Jianhua Lu wrote:

> Add qcom TDM setup function to support TDM ports for qcom platform.

> +int qcom_snd_tdm_hw_params(struct snd_pcm_substream *substream,
> + struct snd_pcm_hw_params *params)
> +{

...

> + ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, rx_mask, slots, slot_width);
> + if (ret < 0) {

The expectation is that TDM is set up by the machine driver, not from
hw_params - if the TDM setup can be changed from within hw_params then
it's hard to see how it's going to interact well with other TDM users on
the bus. More usually hw_params() would be influenced by the setup done
in set_tdm_slot().


Attachments:
(No filename) (681.00 B)
signature.asc (499.00 B)
Download all attachments

2023-12-14 15:52:20

by Jianhua Lu

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] ASoC: qcom: common: Add qcom_snd_tdm_hw_params function

On Thu, Dec 14, 2023 at 11:11:06AM +0000, Mark Brown wrote:
> On Wed, Dec 13, 2023 at 08:35:53PM +0800, Jianhua Lu wrote:
>
> > Add qcom TDM setup function to support TDM ports for qcom platform.
>
> > +int qcom_snd_tdm_hw_params(struct snd_pcm_substream *substream,
> > + struct snd_pcm_hw_params *params)
> > +{
>
> ...
>
> > + ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, rx_mask, slots, slot_width);
> > + if (ret < 0) {
>
> The expectation is that TDM is set up by the machine driver, not from
> hw_params - if the TDM setup can be changed from within hw_params then
> it's hard to see how it's going to interact well with other TDM users on
> the bus. More usually hw_params() would be influenced by the setup done
> in set_tdm_slot().

Currently, qcom TDM setup need to read hw_params, if we want to move it
to machine driver, we must hardcode some params, but it will reduce reduce
readability.

2023-12-14 15:57:12

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] ASoC: qcom: common: Add qcom_snd_tdm_hw_params function

On Thu, Dec 14, 2023 at 11:51:50PM +0800, Jianhua Lu wrote:
> On Thu, Dec 14, 2023 at 11:11:06AM +0000, Mark Brown wrote:

> > The expectation is that TDM is set up by the machine driver, not from
> > hw_params - if the TDM setup can be changed from within hw_params then
> > it's hard to see how it's going to interact well with other TDM users on
> > the bus. More usually hw_params() would be influenced by the setup done
> > in set_tdm_slot().

> Currently, qcom TDM setup need to read hw_params, if we want to move it
> to machine driver, we must hardcode some params, but it will reduce reduce
> readability.

What makes you say that TDM setup needs to read hw_params?


Attachments:
(No filename) (690.00 B)
signature.asc (495.00 B)
Download all attachments

2023-12-14 16:55:59

by Jianhua Lu

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] ASoC: qcom: common: Add qcom_snd_tdm_hw_params function

On Thu, Dec 14, 2023 at 03:56:52PM +0000, Mark Brown wrote:
> On Thu, Dec 14, 2023 at 11:51:50PM +0800, Jianhua Lu wrote:
> > On Thu, Dec 14, 2023 at 11:11:06AM +0000, Mark Brown wrote:
>
> > > The expectation is that TDM is set up by the machine driver, not from
> > > hw_params - if the TDM setup can be changed from within hw_params then
> > > it's hard to see how it's going to interact well with other TDM users on
> > > the bus. More usually hw_params() would be influenced by the setup done
> > > in set_tdm_slot().
>
> > Currently, qcom TDM setup need to read hw_params, if we want to move it
> > to machine driver, we must hardcode some params, but it will reduce reduce
> > readability.
>
> What makes you say that TDM setup needs to read hw_params?

qcom_snd_tdm_hw_params function read PCM_FORMAT to set slot_width value, read
channels to set rx_mask value.


2023-12-14 17:05:23

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] ASoC: qcom: common: Add qcom_snd_tdm_hw_params function

On Fri, Dec 15, 2023 at 12:55:08AM +0800, Jianhua Lu wrote:
> On Thu, Dec 14, 2023 at 03:56:52PM +0000, Mark Brown wrote:
> > On Thu, Dec 14, 2023 at 11:51:50PM +0800, Jianhua Lu wrote:

> > > Currently, qcom TDM setup need to read hw_params, if we want to move it
> > > to machine driver, we must hardcode some params, but it will reduce reduce
> > > readability.

> > What makes you say that TDM setup needs to read hw_params?

> qcom_snd_tdm_hw_params function read PCM_FORMAT to set slot_width value, read
> channels to set rx_mask value.

A large part of the purpose of doing TDM configuration is to fix the
slot width and assign which slots are in use by this interface - the TDM
configuration is a constraint on what hardware paramters can be set and
should always be followed regardless of what is being done with the
audio stream. If you're just trying to configure the sample size for
DSP modes then that shouldn't go through the TDM configuration API,
that's just normal hw_params() so should be done directly. Possibly the
hardware doesn't support manual TDM configuration?


Attachments:
(No filename) (1.08 kB)
signature.asc (499.00 B)
Download all attachments