From 9e10709f831408d948be66bc8f6329fa37a3dc82 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 14 Nov 2025 07:58:51 +0000 Subject: [PATCH] ASoC: renesas: rz-ssi: Add support for 24 bits sample width Add support for 24 bits sample format width for RZ/G2L SoCs. Signed-off-by: Biju Das Link: https://patch.msgid.link/20251114075856.4751-5-biju.das.jz@bp.renesas.com Signed-off-by: Mark Brown --- sound/soc/renesas/rz-ssi.c | 75 +++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 55aefff8857d2..3ec7c9875b431 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -38,6 +38,7 @@ #define SSICR_MST BIT(14) #define SSICR_BCKP BIT(13) #define SSICR_LRCKP BIT(12) +#define SSICR_PDTA BIT(9) #define SSICR_CKDV(x) (((x) & 0xf) << 4) #define SSICR_TEN BIT(1) #define SSICR_REN BIT(0) @@ -74,7 +75,7 @@ #define PREALLOC_BUFFER_MAX (SZ_32K) #define SSI_RATES SNDRV_PCM_RATE_8000_48000 /* 8k-48kHz */ -#define SSI_FMTS SNDRV_PCM_FMTBIT_S16_LE +#define SSI_FMTS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) #define SSI_CHAN_MIN 2 #define SSI_CHAN_MAX 2 #define SSI_FIFO_DEPTH 32 @@ -294,11 +295,24 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate, } /* - * DWL: Data Word Length = 16 bits + * DWL: Data Word Length = {16, 24} bits * SWL: System Word Length = 32 bits */ ssicr |= SSICR_CKDV(clk_ckdv); - ssicr |= SSICR_DWL(1) | SSICR_SWL(3); + switch (ssi->hw_params_cache.sample_width) { + case 16: + ssicr |= SSICR_DWL(1); + break; + case 24: + ssicr |= SSICR_DWL(5) | SSICR_PDTA; + break; + default: + dev_err(ssi->dev, "Not support %u data width", + ssi->hw_params_cache.sample_width); + return -EINVAL; + } + + ssicr |= SSICR_SWL(3); rz_ssi_reg_writel(ssi, SSICR, ssicr); rz_ssi_reg_writel(ssi, SSIFCR, SSIFCR_AUCKE | SSIFCR_FIFO_RST); @@ -455,7 +469,6 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { struct snd_pcm_substream *substream = strm->substream; struct snd_pcm_runtime *runtime; - u16 *buf; int fifo_samples; int frames_left; int samples; @@ -490,12 +503,23 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) break; /* calculate new buffer index */ - buf = (u16 *)runtime->dma_area; - buf += strm->buffer_pos * runtime->channels; + if (ssi->hw_params_cache.sample_width == 16) { + u16 *buf; - /* Note, only supports 16-bit samples */ - for (i = 0; i < samples; i++) - *buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16); + buf = (u16 *)runtime->dma_area; + buf += strm->buffer_pos * runtime->channels; + + for (i = 0; i < samples; i++) + *buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16); + } else { + u32 *buf; + + buf = (u32 *)runtime->dma_area; + buf += strm->buffer_pos * runtime->channels; + + for (i = 0; i < samples; i++) + *buf++ = rz_ssi_reg_readl(ssi, SSIFRDR); + } rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); rz_ssi_pointer_update(strm, samples / runtime->channels); @@ -513,7 +537,6 @@ static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) int frames_left; int i; u32 ssifsr; - u16 *buf; if (!rz_ssi_stream_is_valid(ssi, strm)) return -EINVAL; @@ -542,12 +565,23 @@ static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) return 0; /* calculate new buffer index */ - buf = (u16 *)(runtime->dma_area); - buf += strm->buffer_pos * runtime->channels; + if (ssi->hw_params_cache.sample_width == 16) { + u16 *buf; + + buf = (u16 *)(runtime->dma_area); + buf += strm->buffer_pos * runtime->channels; + + for (i = 0; i < samples; i++) + rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16)); + } else { + u32 *buf; - /* Note, only supports 16-bit samples */ - for (i = 0; i < samples; i++) - rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16)); + buf = (u32 *)(runtime->dma_area); + buf += strm->buffer_pos * runtime->channels; + + for (i = 0; i < samples; i++) + rz_ssi_reg_writel(ssi, SSIFTDR, *buf++); + } rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_TDE, 0); rz_ssi_pointer_update(strm, samples / runtime->channels); @@ -658,8 +692,13 @@ static int rz_ssi_dma_slave_config(struct rz_ssi_priv *ssi, cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; cfg.dst_addr = ssi->phys + SSIFTDR; cfg.src_addr = ssi->phys + SSIFRDR; - cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + if (ssi->hw_params_cache.sample_width == 16) { + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + } else { + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + } return dmaengine_slave_config(dma_ch, &cfg); } @@ -977,7 +1016,7 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, unsigned int rate = params_rate(params); int ret; - if (sample_bits != 16) { + if (!(sample_bits == 16 || sample_bits == 24)) { dev_err(ssi->dev, "Unsupported sample width: %d\n", sample_bits); return -EINVAL; -- 2.47.3