From f38acf74087224e1154b63cd230df44d12eb394d Mon Sep 17 00:00:00 2001 From: denglei Date: Fri, 6 Dec 2024 14:04:05 +0800 Subject: [PATCH 331/416] WIN2030-16445:fix:audio driver add 24 bits support. Changelogs: 1.audio driver add 24 bits support. 2.resolve the issue of 16 bits audio recording. Change-Id: I13cd2acbefde3e4e02d5ead5c0ea1d53586c0a7d Signed-off-by: denglei --- sound/soc/codecs/eswin/es8328.c | 1 + sound/soc/eswin/esw-dma.c | 71 +++++++++++++++++++++++++-------- sound/soc/eswin/esw-i2s.c | 6 ++- sound/soc/eswin/esw-i2s.h | 1 + 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/sound/soc/codecs/eswin/es8328.c b/sound/soc/codecs/eswin/es8328.c index af8f18d1057d..1ceb706a9f9a 100644 --- a/sound/soc/codecs/eswin/es8328.c +++ b/sound/soc/codecs/eswin/es8328.c @@ -98,6 +98,7 @@ static const char * const supply_names[ES8328_SUPPLY_NUM] = { SNDRV_PCM_FMTBIT_S18_3LE | \ SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | \ SNDRV_PCM_FMTBIT_S32_LE) #define EVB_BOARD 1 diff --git a/sound/soc/eswin/esw-dma.c b/sound/soc/eswin/esw-dma.c index 80590ef8c07e..cb7bbfca3de5 100644 --- a/sound/soc/eswin/esw-dma.c +++ b/sound/soc/eswin/esw-dma.c @@ -159,6 +159,11 @@ int esw_pcm_dma_open(struct snd_soc_component *component, substream->runtime->hw = hw; substream->runtime->private_data = chip; + chip->conv_buf[substream->stream] = kzalloc(hw.period_bytes_max, GFP_KERNEL); + if (!chip->conv_buf[substream->stream]) { + return -ENOMEM; + } + return 0; } @@ -252,6 +257,13 @@ int esw_pcm_dma_close(struct snd_soc_component *component, struct i2s_dev *chip = dev_get_drvdata(component->dev); dmaengine_synchronize(chip->chan[substream->stream]); + + dev_dbg(chip->dev, "%s\n", __func__); + + if (chip->conv_buf[substream->stream]) { + kfree(chip->conv_buf[substream->stream]); + } + return 0; } @@ -263,7 +275,7 @@ int esw_pcm_dma_trigger(struct snd_soc_component *component, struct dma_chan *chan = chip->chan[substream->stream]; int ret; - dev_dbg(chip->dev, "%s, cmd:%d\n", __func__, cmd); + dev_dbg(chip->dev, "%s, cmd:%d, sample bits:%d\n", __func__, cmd, runtime->sample_bits); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -309,38 +321,63 @@ static int esw_pcm_dma_process(struct snd_soc_component *component, int channel, unsigned long hwoff, struct iov_iter *iter, unsigned long bytes) { + struct i2s_dev *chip = container_of(component, struct i2s_dev, pcm_component); struct snd_pcm_runtime *runtime = substream->runtime; bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; char *dma_ptr = (char *)runtime->dma_area + hwoff * 64 / runtime->frame_bits + channel * (runtime->dma_bytes / runtime->channels); snd_pcm_uframes_t frames; u16 *ptr_16; + u8 *ptr_24_raw; + u32 *ptr_24; u32 *ptr_32; int i; if (is_playback) { - if (copy_from_iter(dma_ptr, bytes, iter) != bytes) + if (runtime->sample_bits == 32) { + if (copy_from_iter(dma_ptr, bytes, iter) != bytes) + return -EFAULT; + } else { + if (copy_from_iter(chip->conv_buf[0], bytes, iter) != bytes) return -EFAULT; - if (runtime->sample_bits == 16) { - ptr_16 = (u16 *)dma_ptr; - ptr_32 = (u32 *)dma_ptr; - frames = bytes_to_frames(runtime, bytes); - for (i = 2 * frames - 1; i >= 0; i--) { - ptr_32[i] = (u32)ptr_16[i]; + if (runtime->sample_bits == 16) { + ptr_16 = (u16 *)chip->conv_buf[0]; + ptr_32 = (u32 *)dma_ptr; + frames = bytes_to_frames(runtime, bytes); + for (i = 0; i < 2 * frames; i++) { + ptr_32[i] = (u32)ptr_16[i]; + } + } else if (runtime->sample_bits == 24) { + ptr_24_raw = (u8 *)chip->conv_buf[0]; + ptr_32 = (u32 *)dma_ptr; + for (i = 0; i < bytes / 3; i++) { + ptr_24 = (u32 *)(ptr_24_raw + i * 3); + ptr_32[i] = (*ptr_24) & 0xffffff; + } } } } else { - if (runtime->sample_bits == 16) { - frames = bytes_to_frames(runtime, bytes); - ptr_16 = (u16 *)dma_ptr; - ptr_32 = (u32 *)dma_ptr; - - for (i = 2 * frames - 1; i >= 0; i--) { - ptr_16[i] = ptr_32[i]; + if (runtime->sample_bits == 32) { + if (copy_to_iter(dma_ptr, bytes, iter) != bytes) + return -EFAULT; + } else { + if (runtime->sample_bits == 16) { + frames = bytes_to_frames(runtime, bytes); + ptr_16 = (u16 *)chip->conv_buf[1]; + ptr_32 = (u32 *)dma_ptr; + for (i = 0; i < 2 * frames; i++) { + ptr_16[i] = ptr_32[i]; + } + } else if (runtime->sample_bits == 24) { + ptr_24_raw = (u8 *)chip->conv_buf[1]; + ptr_32 = (u32 *)dma_ptr; + for (i = 0; i < bytes / 3; i++) { + memcpy(&ptr_24_raw[i * 3], &ptr_32[i], 3); + } } + if (copy_to_iter(chip->conv_buf[1], bytes, iter) != bytes) + return -EFAULT; } - if (copy_to_iter(dma_ptr, bytes, iter) != bytes) - return -EFAULT; } return 0; diff --git a/sound/soc/eswin/esw-i2s.c b/sound/soc/eswin/esw-i2s.c index 24b2ebed75dd..8fc5a00472d3 100755 --- a/sound/soc/eswin/esw-i2s.c +++ b/sound/soc/eswin/esw-i2s.c @@ -80,7 +80,10 @@ SNDRV_PCM_RATE_32000 | \ SNDRV_PCM_RATE_16000 | \ SNDRV_PCM_RATE_8000) -#define ESW_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) +#define ESW_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S24_3LE) #define DIE0_I2S0_IO_ADDR 0x51600124 #define DIE1_I2S0_IO_ADDR 0x71600124 @@ -459,6 +462,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, i2s_drvdata->xfer_resolution = RESOLUTION_16_BIT; break; case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S24_3LE: config->data_width = 24; i2s_drvdata->ccr = CLOCK_CYCLES_32 << CCR_WSS_POS | NO_CLOCK_GATING; diff --git a/sound/soc/eswin/esw-i2s.h b/sound/soc/eswin/esw-i2s.h index 1cc88ed411e3..63f12992236f 100644 --- a/sound/soc/eswin/esw-i2s.h +++ b/sound/soc/eswin/esw-i2s.h @@ -199,6 +199,7 @@ struct i2s_dev { unsigned int pcm_pos[2]; struct snd_soc_component pcm_component; + void *conv_buf[2]; }; #endif /* __I2S_H */ -- 2.47.0