audio: Add pcm slots configs [1/1]

PD#SWPL-4711

Problem:
BT pcm record doesn't work.

Solution:
Add pcm configs in DTS.

Verify:
ampere

Change-Id: I87c2cb62fb803527da089c5a2aea33752939e000
Signed-off-by: Shuai Li <shuai.li@amlogic.com>
This commit is contained in:
Shuai Li
2019-06-06 17:25:03 +08:00
committed by Luan Yuan
parent 55e0efaf45
commit 302473ef5e
14 changed files with 167 additions and 61 deletions

View File

@@ -862,6 +862,11 @@
"pcm_mclk",
"pcm_sclk";
pcm_mode = <1>; /* 0=slave mode, 1=master mode */
dai-format = "dsp_a";
dai-tdm-slot-tx-mask = <1>;
dai-tdm-slot-rx-mask = <1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
i2s_plat: i2s_platform {
compatible = "amlogic, aml-i2s";

View File

@@ -828,6 +828,11 @@
"pcm_mclk",
"pcm_sclk";
pcm_mode = <1>; /* 0=slave mode, 1=master mode */
dai-format = "dsp_a";
dai-tdm-slot-tx-mask = <1>;
dai-tdm-slot-rx-mask = <1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
i2s_plat: i2s_platform {
compatible = "amlogic, aml-i2s";

View File

@@ -848,6 +848,11 @@
"pcm_mclk",
"pcm_sclk";
pcm_mode = <1>; /* 0=slave mode, 1=master mode */
dai-format = "dsp_a";
dai-tdm-slot-tx-mask = <1>;
dai-tdm-slot-rx-mask = <1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
i2s_plat: i2s_platform {
compatible = "amlogic, aml-i2s";

View File

@@ -869,6 +869,11 @@
"pcm_mclk",
"pcm_sclk";
pcm_mode = <1>; /* 0=slave mode, 1=master mode */
dai-format = "dsp_a";
dai-tdm-slot-tx-mask = <1>;
dai-tdm-slot-rx-mask = <1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
i2s_plat: i2s_platform {
compatible = "amlogic, aml-i2s";

View File

@@ -828,6 +828,11 @@
"pcm_mclk",
"pcm_sclk";
pcm_mode = <1>; /* 0=slave mode, 1=master mode */
dai-format = "dsp_a";
dai-tdm-slot-tx-mask = <1>;
dai-tdm-slot-rx-mask = <1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
i2s_plat: i2s_platform {
compatible = "amlogic, aml-i2s";

View File

@@ -858,6 +858,11 @@
"pcm_mclk",
"pcm_sclk";
pcm_mode = <1>; /* 0=slave mode, 1=master mode */
dai-format = "dsp_a";
dai-tdm-slot-tx-mask = <1>;
dai-tdm-slot-rx-mask = <1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
i2s_plat: i2s_platform {
compatible = "amlogic, aml-i2s";

View File

@@ -827,6 +827,11 @@
"pcm_mclk",
"pcm_sclk";
pcm_mode = <1>; /* 0=slave mode, 1=master mode */
dai-format = "dsp_a";
dai-tdm-slot-tx-mask = <1>;
dai-tdm-slot-rx-mask = <1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
i2s_plat: i2s_platform {
compatible = "amlogic, aml-i2s";

View File

@@ -847,6 +847,11 @@
"pcm_mclk",
"pcm_sclk";
pcm_mode = <1>; /* 0=slave mode, 1=master mode */
dai-format = "dsp_a";
dai-tdm-slot-tx-mask = <1>;
dai-tdm-slot-rx-mask = <1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
i2s_plat: i2s_platform {
compatible = "amlogic, aml-i2s";

View File

@@ -866,6 +866,11 @@
"pcm_mclk",
"pcm_sclk";
pcm_mode = <1>; /* 0=slave mode, 1=master mode */
dai-format = "dsp_a";
dai-tdm-slot-tx-mask = <1>;
dai-tdm-slot-rx-mask = <1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
i2s_plat: i2s_platform {
compatible = "amlogic, aml-i2s";

View File

@@ -828,6 +828,11 @@
"pcm_mclk",
"pcm_sclk";
pcm_mode = <1>; /* 0=slave mode, 1=master mode */
dai-format = "dsp_a";
dai-tdm-slot-tx-mask = <1>;
dai-tdm-slot-rx-mask = <1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
};
i2s_plat: i2s_platform {
compatible = "amlogic, aml-i2s";

View File

@@ -58,15 +58,6 @@ static int valid_channel[] = {
/* counter for pcm clk used */
static int aml_pcm_clk_count;
static unsigned int aml_pcm_format = SND_SOC_DAIFMT_DSP_B;
void aml_set_pcm_format(int pcm_mode)
{
pr_info(" %s, pcm format:0x%x\n", __func__, pcm_mode);
aml_pcm_format = pcm_mode;
}
static uint32_t aml_audin_read_bits(uint32_t reg, const uint32_t start,
const uint32_t len)
{
@@ -94,16 +85,18 @@ static void pcm_in_register_show(void)
aml_audin_read(PCMIN_CTRL1));
}
void pcm_master_in_enable(struct snd_pcm_substream *substream, int flag)
void pcm_master_in_enable(struct snd_pcm_substream *substream,
struct tdm_config cfg, int enable)
{
unsigned int fs_offset;
unsigned int slots = cfg.slots;
if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A)
if (cfg.fmt == SND_SOC_DAIFMT_DSP_A)
fs_offset = 1;
else {
fs_offset = 0;
if (aml_pcm_format != SND_SOC_DAIFMT_DSP_B)
if (cfg.fmt != SND_SOC_DAIFMT_DSP_B)
pr_err("Unsupport DSP mode\n");
}
@@ -127,13 +120,17 @@ RESET_FIFO:
/* disable pcmin */
aml_audin_update_bits(PCMIN_CTRL0, 1 << 31, 0 << 31);
if (flag) {
if (enable) {
unsigned int pcm_mode = 1, pcm_wlen = 16;
unsigned int num_slot = substream->runtime->channels;
unsigned int valid_slot = valid_channel[num_slot - 1];
unsigned int max_bits;
unsigned int valid_bits;
/* if no slots is set, use the channel num */
if (slots == 0)
slots = num_slot;
/* whatever pcm out is enable */
aml_pcm_clk_count++;
@@ -226,12 +223,12 @@ RESET_FIFO:
unsigned int bit_offset_s = 0, slot_offset_s = 0,
bit_offset_e = 0, slot_offset_e = 0;
if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) {
if (cfg.fmt == SND_SOC_DAIFMT_DSP_A) {
bit_offset_s = pcm_wlen - 1;
slot_offset_s = num_slot - 1;
slot_offset_s = slots - 1;
bit_offset_e = 0;
slot_offset_e = 0;
} else if (aml_pcm_format == SND_SOC_DAIFMT_DSP_B) {
} else if (cfg.fmt == SND_SOC_DAIFMT_DSP_B) {
bit_offset_s = 0;
slot_offset_s = 0;
bit_offset_e = 1;
@@ -248,7 +245,7 @@ RESET_FIFO:
/* underrun use mute constant */
(0 << 29) |
/* pcmo max slot number in one frame*/
((num_slot - 1) << 22) |
((slots - 1) << 22) |
/* pcmo max bit number in one slot*/
(valid_bits << 16) |
(valid_slot << 0)
@@ -286,21 +283,22 @@ RESET_FIFO:
}
}
pr_debug("PCMIN %s\n", flag ? "enable" : "disable");
pr_debug("PCMIN %s\n", enable ? "enable" : "disable");
pcm_in_register_show();
}
void pcm_in_enable(struct snd_pcm_substream *substream, int flag)
void pcm_in_enable(struct snd_pcm_substream *substream,
struct tdm_config cfg, int enable)
{
unsigned int fs_offset;
if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A)
if (cfg.fmt == SND_SOC_DAIFMT_DSP_A)
fs_offset = 1;
else {
fs_offset = 0;
if (aml_pcm_format != SND_SOC_DAIFMT_DSP_B)
if (cfg.fmt != SND_SOC_DAIFMT_DSP_B)
pr_err("Unsupport DSP mode\n");
}
/* reset fifo */
@@ -322,7 +320,7 @@ void pcm_in_enable(struct snd_pcm_substream *substream, int flag)
/* disable pcmin */
aml_audin_update_bits(PCMIN_CTRL0, 1 << 31, 0 << 31);
if (flag) {
if (enable) {
unsigned int pcm_mode = 1;
unsigned int num_slot = substream->runtime->channels;
unsigned int valid_slot = valid_channel[num_slot - 1];
@@ -414,7 +412,7 @@ void pcm_in_enable(struct snd_pcm_substream *substream, int flag)
(1 << 0)); /* left justified */
}
pr_debug("PCMIN %s\n", flag ? "enable" : "disable");
pr_debug("PCMIN %s\n", enable ? "enable" : "disable");
pcm_in_register_show();
}
@@ -505,7 +503,8 @@ static void pcm_out_register_show(void)
aml_audin_read(PCMOUT_CTRL3));
}
void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
void pcm_master_out_enable(struct snd_pcm_substream *substream,
struct tdm_config cfg, int enable)
{
unsigned int pcm_mode = 1, pcm_wlen = 16;
unsigned int num_slot = substream->runtime->channels;
@@ -513,6 +512,11 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
unsigned int valid_bits;
unsigned int bit_offset_s = 0, slot_offset_s = 0,
bit_offset_e = 0, slot_offset_e = 0;
unsigned int slots = cfg.slots;
/* if no slots is set, use the channel num */
if (slots == 0)
slots = num_slot;
switch (substream->runtime->format) {
case SNDRV_PCM_FORMAT_S32_LE:
@@ -532,12 +536,12 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
pcm_mode = (pcm_wlen >> 3) - 1;
valid_bits = pcm_wlen - 1;
if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) {
if (cfg.fmt == SND_SOC_DAIFMT_DSP_A) {
bit_offset_s = pcm_wlen - 1;
slot_offset_s = num_slot - 1;
slot_offset_s = slots - 1;
bit_offset_e = 0;
slot_offset_e = 0;
} else if (aml_pcm_format == SND_SOC_DAIFMT_DSP_B) {
} else if (cfg.fmt == SND_SOC_DAIFMT_DSP_B) {
bit_offset_s = 0;
slot_offset_s = 0;
bit_offset_e = 1;
@@ -545,10 +549,12 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
} else
pr_err("Unsupport DSP mode\n");
pr_info("pcm master out, pcm mode:%d, valid bits:0x%x, valid slot:0x%x\n",
pr_info("%s(), mode:%d, valid bits:0x%x, valid slot:0x%x, slots:%d\n",
__func__,
pcm_mode,
valid_bits,
valid_slot);
valid_slot,
slots);
/* reset fifo */
aml_audin_update_bits(AUDOUT_CTRL, 1 << 30, 1 << 30);
@@ -564,7 +570,7 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
aml_audin_update_bits(PCMOUT_CTRL0, 1 << 31, 0 << 31);
}
if (flag) {
if (enable) {
/* set buffer start ptr end */
aml_audin_write(AUDOUT_BUF0_STA, pcmout_buffer_addr);
aml_audin_write(AUDOUT_BUF0_WPTR, pcmout_buffer_addr);
@@ -617,7 +623,7 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
/* underrun use mute constant */
(0 << 29) |
/* pcmo max slot number in one frame */
((num_slot - 1) << 22) |
((slots - 1) << 22) |
/* pcmo max bit number in one slot */
(valid_bits << 16) |
/* pcmo valid slot. each bit for one slot */
@@ -680,11 +686,12 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag)
}
}
pr_debug("PCMOUT %s\n", flag ? "enable" : "disable");
pr_debug("PCMOUT %s\n", enable ? "enable" : "disable");
pcm_out_register_show();
}
void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
void pcm_out_enable(struct snd_pcm_substream *substream,
struct tdm_config cfg, int enable)
{
unsigned int pcm_mode = 1;
unsigned int num_slot = substream->runtime->channels;
@@ -692,13 +699,13 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
unsigned int valid_bits = 0xf;
unsigned int bit_offset_s, slot_offset_s, bit_offset_e, slot_offset_e;
if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) {
if (cfg.fmt == SND_SOC_DAIFMT_DSP_A) {
bit_offset_s = 0xF;
slot_offset_s = num_slot - 1;
bit_offset_e = 0;
slot_offset_e = 0;
} else {
if (aml_pcm_format != SND_SOC_DAIFMT_DSP_B)
if (cfg.fmt != SND_SOC_DAIFMT_DSP_B)
pr_err("Unsupport DSP mode\n");
bit_offset_s = 0;
@@ -711,7 +718,7 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
case SNDRV_PCM_FORMAT_S32_LE:
pcm_mode = 3;
valid_bits = 0x1f;
if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) {
if (cfg.fmt == SND_SOC_DAIFMT_DSP_A) {
bit_offset_s = 0xF;
slot_offset_s = (num_slot << 1) - 1;
bit_offset_e = 0;
@@ -721,7 +728,7 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
case SNDRV_PCM_FORMAT_S24_LE:
pcm_mode = 2;
valid_bits = 0x1f;
if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) {
if (cfg.fmt == SND_SOC_DAIFMT_DSP_A) {
bit_offset_s = 0xF;
slot_offset_s = (num_slot << 1) - 8 - 1;
bit_offset_e = 0;
@@ -735,7 +742,7 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
case SNDRV_PCM_FORMAT_S8:
pcm_mode = 0;
valid_bits = 0x7;
if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) {
if (cfg.fmt == SND_SOC_DAIFMT_DSP_A) {
bit_offset_s = 0x7;
slot_offset_s = (num_slot >> 1) - 1;
bit_offset_e = 0;
@@ -763,7 +770,7 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
/* disable pcmout */
aml_audin_update_bits(PCMOUT_CTRL0, 1 << 31, 0 << 31);
if (flag) {
if (enable) {
/* set buffer start ptr end */
aml_audin_write(AUDOUT_BUF0_STA, pcmout_buffer_addr);
aml_audin_write(AUDOUT_BUF0_WPTR, pcmout_buffer_addr);
@@ -848,7 +855,7 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag)
(0 << 0));
}
pr_debug("PCMOUT %s\n", flag ? "enable" : "disable");
pr_debug("PCMOUT %s\n", enable ? "enable" : "disable");
pcm_out_register_show();
}

View File

@@ -23,8 +23,16 @@
#include "audio_hw.h"
void aml_set_pcm_format(int pcm_mode);
void pcm_in_enable(struct snd_pcm_substream *substream, int flag);
struct tdm_config {
unsigned int fmt;
unsigned int tx_slot_mask;
unsigned int rx_slot_mask;
unsigned int slots;
unsigned int slot_width;
};
void pcm_in_enable(struct snd_pcm_substream *substream,
struct tdm_config cfg, int enable);
void pcm_in_set_buf(unsigned int addr, unsigned int size);
int pcm_in_is_enable(void);
unsigned int pcm_in_rd_ptr(void);
@@ -32,7 +40,8 @@ unsigned int pcm_in_wr_ptr(void);
unsigned int pcm_in_set_rd_ptr(unsigned int value);
unsigned int pcm_in_fifo_int(void);
void pcm_out_enable(struct snd_pcm_substream *substream, int flag);
void pcm_out_enable(struct snd_pcm_substream *substream,
struct tdm_config cfg, int enable);
void pcm_out_mute(int flag);
void pcm_out_set_buf(unsigned int addr, unsigned int size);
int pcm_out_is_enable(void);
@@ -41,6 +50,8 @@ unsigned int pcm_out_rd_ptr(void);
unsigned int pcm_out_wr_ptr(void);
unsigned int pcm_out_set_wr_ptr(unsigned int value);
void pcm_master_in_enable(struct snd_pcm_substream *substream, int flag);
void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag);
void pcm_master_in_enable(struct snd_pcm_substream *substream,
struct tdm_config cfg, int enable);
void pcm_master_out_enable(struct snd_pcm_substream *substream,
struct tdm_config cfg, int enable);
#endif

View File

@@ -25,6 +25,7 @@
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/of.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -34,10 +35,9 @@
#include "pcm_dai.h"
#include "pcm.h"
#include "i2s.h"
//#include "i2s.h"
#include "audio_hw_pcm.h"
#include <linux/of.h>
#define DEV_NAME "aml-pcm-dai"
@@ -94,8 +94,13 @@ static int aml_pcm_dai_prepare(struct snd_pcm_substream *substream,
struct aml_pcm_runtime_data *prtd = runtime->private_data;
struct aml_pcm *pcm = snd_soc_dai_get_drvdata(dai);
int mclk_rate, pcm_bit;
unsigned int slots = pcm->cfg.slots;
pr_debug("***Entered %s\n", __func__);
pr_debug("***Entered %s, slots %d\n", __func__, slots);
/* if no slots is set, use the channel num */
if (slots == 0)
slots = runtime->channels;
/* set bclk */
if (runtime->format == SNDRV_PCM_FORMAT_S32_LE)
@@ -105,12 +110,12 @@ static int aml_pcm_dai_prepare(struct snd_pcm_substream *substream,
else
pcm_bit = 16;
mclk_rate = runtime->rate * pcm_bit * runtime->channels;
pr_info("%s rate:%d, bits:%d, channels:%d, mclk:%d\n",
mclk_rate = runtime->rate * pcm_bit * slots;
pr_info("%s rate:%d, bits:%d, slots:%d, mclk:%d\n",
__func__,
runtime->rate,
pcm_bit,
runtime->channels,
slots,
mclk_rate);
aml_pcm_set_clk(pcm, mclk_rate);
@@ -149,16 +154,16 @@ static int aml_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
pr_info("aiu pcm master stream %d enable\n\n",
substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
pcm_master_out_enable(substream, 1);
pcm_master_out_enable(substream, pcm_p->cfg, 1);
else
pcm_master_in_enable(substream, 1);
pcm_master_in_enable(substream, pcm_p->cfg, 1);
} else {
pr_info("aiu slave pcm stream %d enable\n\n",
substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
pcm_out_enable(substream, 1);
pcm_out_enable(substream, pcm_p->cfg, 1);
else
pcm_in_enable(substream, 1);
pcm_in_enable(substream, pcm_p->cfg, 1);
}
break;
case SNDRV_PCM_TRIGGER_STOP:
@@ -168,16 +173,16 @@ static int aml_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
pr_info("aiu master pcm stream %d disable\n\n",
substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
pcm_master_out_enable(substream, 0);
pcm_master_out_enable(substream, pcm_p->cfg, 0);
else
pcm_master_in_enable(substream, 0);
pcm_master_in_enable(substream, pcm_p->cfg, 0);
} else {
pr_info("aiu slave pcm stream %d disable\n\n",
substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
pcm_out_enable(substream, 0);
pcm_out_enable(substream, pcm_p->cfg, 0);
else
pcm_in_enable(substream, 0);
pcm_in_enable(substream, pcm_p->cfg, 0);
}
break;
default:
@@ -199,8 +204,6 @@ static int aml_pcm_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
pr_debug("***Entered %s\n", __func__);
aml_set_pcm_format(fmt & SND_SOC_DAIFMT_FORMAT_MASK);
return 0;
}
@@ -265,6 +268,36 @@ static const struct snd_soc_component_driver aml_component = {
.name = DEV_NAME,
};
static int parse_tdm_configs(struct device_node *node, struct aml_pcm *pcm_p)
{
struct tdm_config *cfg = &pcm_p->cfg;
unsigned int fmt = 0;
fmt = snd_soc_of_parse_daifmt(node, NULL, NULL, NULL);
cfg->fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
snd_soc_of_parse_tdm_slot(node,
&cfg->tx_slot_mask,
&cfg->rx_slot_mask,
&cfg->slots,
&cfg->slot_width);
pr_info("tdm config: %#x, %#x, %d, %d\n",
cfg->tx_slot_mask,
cfg->rx_slot_mask,
cfg->slots,
cfg->slot_width);
if (cfg->fmt == 0)
cfg->fmt = SND_SOC_DAIFMT_DSP_A;
if (cfg->tx_slot_mask != cfg->rx_slot_mask) {
pr_info("%s(), rx equals to tx\n", __func__);
cfg->rx_slot_mask = cfg->tx_slot_mask;
}
return 0;
}
static int aml_pcm_dai_probe(struct platform_device *pdev)
{
struct pinctrl *pin_ctl;
@@ -335,6 +368,7 @@ static int aml_pcm_dai_probe(struct platform_device *pdev)
"Can't enable pcm clk_pcm_sync clock: %d\n", ret);
goto err;
}
parse_tdm_configs((&pdev->dev)->of_node, pcm_p);
}
ret = snd_soc_register_component(&pdev->dev, &aml_component,

View File

@@ -18,10 +18,14 @@
#ifndef AML_DAI_H
#define AML_DAI_H
#include <sound/soc.h>
#include "audio_hw_pcm.h"
struct aml_pcm {
struct clk *clk_mpll;
struct clk *clk_pcm_mclk;
struct clk *clk_pcm_sync;
int pcm_mode;
struct tdm_config cfg;
};
#endif