diff --git a/sound/soc/amlogic/aml_audio_hw_pcm.c b/sound/soc/amlogic/aml_audio_hw_pcm.c index f6af2980380b..e3bba87d8d64 100644 --- a/sound/soc/amlogic/aml_audio_hw_pcm.c +++ b/sound/soc/amlogic/aml_audio_hw_pcm.c @@ -58,6 +58,15 @@ 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_read_cbus_bits(uint32_t reg, const uint32_t start, const uint32_t len) { @@ -87,15 +96,14 @@ static void pcm_in_register_show(void) void pcm_master_in_enable(struct snd_pcm_substream *substream, int flag) { - unsigned int dsp_mode = SND_SOC_DAIFMT_DSP_B; unsigned int fs_offset; - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) + if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) fs_offset = 1; else { fs_offset = 0; - if (dsp_mode != SND_SOC_DAIFMT_DSP_B) + if (aml_pcm_format != SND_SOC_DAIFMT_DSP_B) pr_err("Unsupport DSP mode\n"); } @@ -119,38 +127,33 @@ RESET_FIFO: aml_cbus_update_bits(PCMIN_CTRL0, 1 << 31, 0 << 31); if (flag) { - unsigned int pcm_mode = 1; + 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 = 0xf; - unsigned int valid_bits = 0xf; + unsigned int max_bits; + unsigned int valid_bits; /* whatever pcm out is enable */ aml_pcm_clk_count++; switch (substream->runtime->format) { case SNDRV_PCM_FORMAT_S32_LE: - pcm_mode = 3; - max_bits = 0x1f; - valid_bits = 0x1f; + pcm_wlen = 32; break; case SNDRV_PCM_FORMAT_S24_LE: - pcm_mode = 2; - max_bits = 0x17; - valid_bits = 0x17; + pcm_wlen = 24; break; case SNDRV_PCM_FORMAT_S16_LE: - pcm_mode = 1; - max_bits = 0xf; - valid_bits = 0xf; + pcm_wlen = 16; break; case SNDRV_PCM_FORMAT_S8: - max_bits = 0x7; - valid_bits = 0x7; - pcm_mode = 0; + pcm_wlen = 8; break; } + pcm_mode = (pcm_wlen >> 3) - 1; + max_bits = pcm_wlen - 1; + valid_bits = pcm_wlen - 1; /* set buffer start ptr end */ aml_write_cbus(AUDIN_FIFO1_START, pcmin_buffer_addr); aml_write_cbus(AUDIN_FIFO1_PTR, pcmin_buffer_addr); @@ -186,8 +189,8 @@ RESET_FIFO: (0 << 29) | /* pcmin clock sel */ (1 << 28) | - /* using negedge of PCM clock to latch the input data */ - (1 << 27) | + /* using posedge of PCM clock to latch the input data */ + (0 << 27) | /* max slot number in one frame */ (max_bits << 21) | /* valid bit number in one slot */ @@ -219,51 +222,22 @@ RESET_FIFO: ); if (!pcm_out_is_enable()) { - unsigned int bit_offset_s, slot_offset_s, - bit_offset_e, slot_offset_e; + unsigned int bit_offset_s = 0, slot_offset_s = 0, + bit_offset_e = 0, slot_offset_e = 0; - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) { - bit_offset_s = 0xF; + if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) { + bit_offset_s = pcm_wlen - 1; slot_offset_s = num_slot - 1; bit_offset_e = 0; slot_offset_e = 0; - } else { - if (dsp_mode != SND_SOC_DAIFMT_DSP_B) - pr_err("Unsupport DSP mode\n"); - + } else if (aml_pcm_format == SND_SOC_DAIFMT_DSP_B) { bit_offset_s = 0; slot_offset_s = 0; - bit_offset_e = 0; - slot_offset_e = 1; - } - switch (substream->runtime->format) { - case SNDRV_PCM_FORMAT_S32_LE: - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) { - bit_offset_s = 0xF; - slot_offset_s = (num_slot << 1) - 1; - bit_offset_e = 0; - slot_offset_e = 0; - } - break; - case SNDRV_PCM_FORMAT_S24_LE: - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) { - bit_offset_s = 0xF; - slot_offset_s = (num_slot << 1) - 8 - 1; - bit_offset_e = 0; - slot_offset_e = 0; - } - break; - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S8: - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) { - bit_offset_s = 0x7; - slot_offset_s = (num_slot >> 1) - 1; - bit_offset_e = 0; - slot_offset_e = 0; - } - break; - } + bit_offset_e = 1; + slot_offset_e = 0; + } else + pr_err("Unsupport DSP mode\n"); + pr_info("pcm master in, pcm mode:%d, valid bits:0x%x, valid slot:0x%x\n", pcm_mode, valid_bits, @@ -283,8 +257,8 @@ RESET_FIFO: * 01: 16bits. 10: 24bits. 11: 32bits */ (pcm_mode << 30) | - /* use posedge of PCM clock to output data*/ - (0 << 28) | + /* use negedge of PCM clock to output data*/ + (1 << 28) | /* invert fs phase */ (1 << 26) | /* invert the fs_o for master mode */ @@ -292,16 +266,17 @@ RESET_FIFO: /* fs_o start postion frame * slot counter number */ - (bit_offset_s << 18) | + (slot_offset_s << 18) | /*fs_o start postion slot bit counter number*/ - (slot_offset_s << 12) | + (bit_offset_s << 12) | /*fs_o end postion frame slot counter number.*/ - (bit_offset_e << 6) | + (slot_offset_e << 6) | /* fs_o end postion slot bit counter number.*/ - (slot_offset_e << 0) + (bit_offset_e << 0) ); aml_cbus_update_bits(PCMOUT_CTRL0, 1 << 31, 1 << 31); aml_cbus_update_bits(PCMOUT_CTRL0, 1 << 29, 1 << 29); + aml_cbus_update_bits(PCMOUT_CTRL0, 1 << 28, 0 << 28); } } else { aml_pcm_clk_count--; @@ -318,15 +293,14 @@ RESET_FIFO: void pcm_in_enable(struct snd_pcm_substream *substream, int flag) { - unsigned int dsp_mode = SND_SOC_DAIFMT_DSP_B; unsigned int fs_offset; - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) + if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) fs_offset = 1; else { fs_offset = 0; - if (dsp_mode != SND_SOC_DAIFMT_DSP_B) + if (aml_pcm_format != SND_SOC_DAIFMT_DSP_B) pr_err("Unsupport DSP mode\n"); } /* reset fifo */ @@ -524,65 +498,44 @@ static void pcm_out_register_show(void) void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag) { - unsigned int pcm_mode = 1; + 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 valid_bits = 0xf; - unsigned int dsp_mode = SND_SOC_DAIFMT_DSP_B; - unsigned int bit_offset_s, slot_offset_s, bit_offset_e, slot_offset_e; - - if (dsp_mode == 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 (dsp_mode != SND_SOC_DAIFMT_DSP_B) - pr_err("Unsupport DSP mode\n"); - - bit_offset_s = 0; - slot_offset_s = 0; - bit_offset_e = 0; - slot_offset_e = 1; - } + unsigned int valid_bits; + unsigned int bit_offset_s = 0, slot_offset_s = 0, + bit_offset_e = 0, slot_offset_e = 0; switch (substream->runtime->format) { case SNDRV_PCM_FORMAT_S32_LE: - pcm_mode = 3; - valid_bits = 0x1f; - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) { - bit_offset_s = 0xF; - slot_offset_s = (num_slot << 1) - 1; - bit_offset_e = 0; - slot_offset_e = 0; - } + pcm_wlen = 32; break; case SNDRV_PCM_FORMAT_S24_LE: - pcm_mode = 2; - valid_bits = 0x17; - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) { - bit_offset_s = 0xF; - slot_offset_s = (num_slot << 1) - 8 - 1; - bit_offset_e = 0; - slot_offset_e = 0; - } + pcm_wlen = 24; break; case SNDRV_PCM_FORMAT_S16_LE: - pcm_mode = 1; - valid_bits = 0xf; + pcm_wlen = 16; break; case SNDRV_PCM_FORMAT_S8: - pcm_mode = 0; - valid_bits = 0x7; - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) { - bit_offset_s = 0x7; - slot_offset_s = (num_slot >> 1) - 1; - bit_offset_e = 0; - slot_offset_e = 0; - } + pcm_wlen = 8; break; } + pcm_mode = (pcm_wlen >> 3) - 1; + valid_bits = pcm_wlen - 1; + + if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) { + bit_offset_s = pcm_wlen - 1; + slot_offset_s = num_slot - 1; + bit_offset_e = 0; + slot_offset_e = 0; + } else if (aml_pcm_format == SND_SOC_DAIFMT_DSP_B) { + bit_offset_s = 0; + slot_offset_s = 0; + bit_offset_e = 1; + slot_offset_e = 0; + } else + pr_err("Unsupport DSP mode\n"); + pr_info("pcm master out, pcm mode:%d, valid bits:0x%x, valid slot:0x%x\n", pcm_mode, valid_bits, @@ -666,8 +619,8 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag) * 01: 16bits. 10: 24bits. 11: 32bits */ (pcm_mode << 30) | - /* use posedge of PCM clock to output data */ - (0 << 28) | + /* use negedge of PCM clock to output data */ + (1 << 28) | /* pcmo slave parts clock invert */ (0 << 27) | /* invert fs phase */ @@ -675,20 +628,20 @@ void pcm_master_out_enable(struct snd_pcm_substream *substream, int flag) /* invert the fs_o for master mode */ (1 << 25) | /* fs_o start postion frame slot counter number */ - (bit_offset_s << 18) | + (slot_offset_s << 18) | /* fs_o start postion slot bit counter number.*/ - (slot_offset_s << 12) | + (bit_offset_s << 12) | /* fs_o end postion frame slot counter number. */ - (bit_offset_e << 6) | + (slot_offset_e << 6) | /* fs_o end postion slot bit counter number. */ - (slot_offset_e << 0) + (bit_offset_e << 0) ); /* pcmout control0 */ aml_write_cbus(PCMOUT_CTRL0, (1 << 31) | /* enable */ (1 << 29) | /* master */ - (1 << 28) | /* sync on clock rising edge */ + (0 << 28) | /* sync on clock negedge edge */ /* system clock sync at clock edge of pcmout clock. * 0 = sync on clock counter. */ @@ -726,16 +679,15 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag) unsigned int num_slot = substream->runtime->channels; unsigned int valid_slot = valid_channel[num_slot - 1]; unsigned int valid_bits = 0xf; - unsigned int dsp_mode = SND_SOC_DAIFMT_DSP_A; unsigned int bit_offset_s, slot_offset_s, bit_offset_e, slot_offset_e; - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) { + if (aml_pcm_format == 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 (dsp_mode != SND_SOC_DAIFMT_DSP_B) + if (aml_pcm_format != SND_SOC_DAIFMT_DSP_B) pr_err("Unsupport DSP mode\n"); bit_offset_s = 0; @@ -748,7 +700,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 (dsp_mode == SND_SOC_DAIFMT_DSP_A) { + if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) { bit_offset_s = 0xF; slot_offset_s = (num_slot << 1) - 1; bit_offset_e = 0; @@ -758,7 +710,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 (dsp_mode == SND_SOC_DAIFMT_DSP_A) { + if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) { bit_offset_s = 0xF; slot_offset_s = (num_slot << 1) - 8 - 1; bit_offset_e = 0; @@ -772,7 +724,7 @@ void pcm_out_enable(struct snd_pcm_substream *substream, int flag) case SNDRV_PCM_FORMAT_S8: pcm_mode = 0; valid_bits = 0x7; - if (dsp_mode == SND_SOC_DAIFMT_DSP_A) { + if (aml_pcm_format == SND_SOC_DAIFMT_DSP_A) { bit_offset_s = 0x7; slot_offset_s = (num_slot >> 1) - 1; bit_offset_e = 0; diff --git a/sound/soc/amlogic/aml_audio_hw_pcm.h b/sound/soc/amlogic/aml_audio_hw_pcm.h index 06e3e7c8087e..304eaf36ae2a 100644 --- a/sound/soc/amlogic/aml_audio_hw_pcm.h +++ b/sound/soc/amlogic/aml_audio_hw_pcm.h @@ -23,6 +23,7 @@ #include "aml_audio_hw.h" +void aml_set_pcm_format(int pcm_mode); void pcm_in_enable(struct snd_pcm_substream *substream, int flag); void pcm_in_set_buf(unsigned int addr, unsigned int size); int pcm_in_is_enable(void); diff --git a/sound/soc/amlogic/aml_pcm.c b/sound/soc/amlogic/aml_pcm.c index 8d2008cdcd17..1a546c4a7d5f 100644 --- a/sound/soc/amlogic/aml_pcm.c +++ b/sound/soc/amlogic/aml_pcm.c @@ -249,8 +249,15 @@ aml_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct aml_pcm_runtime_data *prtd = runtime->private_data; int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int channels, width; - pr_info("enter %s\n", __func__); + pr_info("enter %s cpu_dai->name: %s cpu_dai->id: %d\n", __func__, + cpu_dai->name, cpu_dai->id); + pr_info("enter %s codec_dai->name: %s codec_dai->id: %d\n", __func__, + codec_dai->name, codec_dai->id); snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); @@ -258,7 +265,37 @@ aml_pcm_hw_params(struct snd_pcm_substream *substream, prtd->buffer_start = runtime->dma_addr; prtd->buffer_size = runtime->dma_bytes; - return ret; + channels = params_channels(params); + width = snd_pcm_format_physical_width(params_format(params)); + + pr_info("%s:channels=0x%04x, width:0x%04x\n", + __func__, channels, width); + + /* set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) { + pr_err("set cpu dai fmt wrong\n"); + return ret; + } + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) { + pr_err("set codec dai fmt wrong\n"); + return ret; + } + + /* each codec set its slot offset itself */ + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xff, 0xff, channels, width); + if (ret < 0) { + pr_err("set codec dai tdm slot wrong\n"); + return ret; + } + + return 0; + } static int aml_pcm_hw_free(struct snd_pcm_substream *substream) diff --git a/sound/soc/amlogic/aml_pcm_dai.c b/sound/soc/amlogic/aml_pcm_dai.c index 69223e6a0388..b58c8ce8df4c 100644 --- a/sound/soc/amlogic/aml_pcm_dai.c +++ b/sound/soc/amlogic/aml_pcm_dai.c @@ -199,6 +199,9 @@ static int aml_pcm_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) pr_debug("***Entered %s\n", __func__); if (fmt & SND_SOC_DAIFMT_CBS_CFS) snd_soc_dai_get_drvdata(dai); + + aml_set_pcm_format(fmt & SND_SOC_DAIFMT_FORMAT_MASK); + return 0; } diff --git a/sound/soc/codecs/amlogic/pcm2bt.c b/sound/soc/codecs/amlogic/pcm2bt.c index ee3046c3f134..24d9eb912c43 100644 --- a/sound/soc/codecs/amlogic/pcm2bt.c +++ b/sound/soc/codecs/amlogic/pcm2bt.c @@ -54,6 +54,13 @@ static int pcm2bt_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; } +static int pcm2bt_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + return 0; +} + static int pcm2bt_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { @@ -69,6 +76,7 @@ static int pcm2bt_set_bias_level(struct snd_soc_codec *codec, struct snd_soc_dai_ops pcm2bt_dai_ops = { .hw_params = pcm2bt_hw_params, .set_fmt = pcm2bt_set_fmt, + .set_tdm_slot = pcm2bt_set_tdm_slot, .set_sysclk = pcm2bt_set_sysclk, .set_sysclk = pcm2bt_set_sysclk, };