189 lines
6.1 KiB
Diff
189 lines
6.1 KiB
Diff
From f38acf74087224e1154b63cd230df44d12eb394d Mon Sep 17 00:00:00 2001
|
|
From: denglei <denglei@eswincomputing.com>
|
|
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 <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
|
|
|