kernel/0331-WIN2030-16445-fix-audio-driver-add-24-bits-support.patch
2025-02-23 12:25:17 -05:00

189 lines
6.1 KiB
Diff

From edafe65af4efa1d76b05e62c55fd2c9c8b6026e7 Mon Sep 17 00:00:00 2001
From: denglei <denglei@eswincomputing.com>
Date: Fri, 6 Dec 2024 14:04:05 +0800
Subject: [PATCH 331/413] 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 <denglei@eswincomputing.com>
---
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