Loading sound/soc/renesas/rz-ssi.c +77 −42 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -74,7 +75,8 @@ #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 | \ SNDRV_PCM_FMTBIT_S32_LE) #define SSI_CHAN_MIN 2 #define SSI_CHAN_MAX 2 #define SSI_FIFO_DEPTH 32 Loading Loading @@ -294,11 +296,27 @@ 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, 32} 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; case 32: ssicr |= SSICR_DWL(6); 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); Loading Loading @@ -455,7 +473,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; Loading Loading @@ -490,12 +507,23 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) break; /* calculate new buffer index */ if (ssi->hw_params_cache.sample_width == 16) { u16 *buf; buf = (u16 *)runtime->dma_area; buf += strm->buffer_pos * runtime->channels; /* Note, only supports 16-bit samples */ 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); Loading @@ -513,7 +541,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; Loading Loading @@ -542,12 +569,23 @@ static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) return 0; /* calculate new buffer index */ if (ssi->hw_params_cache.sample_width == 16) { u16 *buf; buf = (u16 *)(runtime->dma_area); buf += strm->buffer_pos * runtime->channels; /* Note, only supports 16-bit samples */ for (i = 0; i < samples; i++) rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16)); } else { u32 *buf; 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); Loading Loading @@ -658,8 +696,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; 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); } Loading Loading @@ -774,14 +817,6 @@ static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev) if (!rz_ssi_is_dma_enabled(ssi)) goto no_dma; if (ssi->playback.dma_ch && (rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, true) < 0)) goto no_dma; if (ssi->capture.dma_ch && (rz_ssi_dma_slave_config(ssi, ssi->capture.dma_ch, false) < 0)) goto no_dma; return 0; no_dma: Loading Loading @@ -829,23 +864,26 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (cmd == SNDRV_PCM_TRIGGER_START) rz_ssi_stream_init(strm, substream); if (ssi->dma_rt) { bool is_playback; if (rz_ssi_is_dma_enabled(ssi)) { bool is_playback = rz_ssi_stream_is_play(substream); is_playback = rz_ssi_stream_is_play(substream); if (ssi->dma_rt) ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, is_playback); else ret = rz_ssi_dma_slave_config(ssi, strm->dma_ch, is_playback); /* Fallback to pio */ if (ret < 0) { ssi->playback.transfer = rz_ssi_pio_send; ssi->capture.transfer = rz_ssi_pio_recv; rz_ssi_release_dma_channels(ssi); } } } else { /* For DMA, queue up multiple DMA descriptors */ if (rz_ssi_is_dma_enabled(ssi)) num_transfer = 4; } } for (i = 0; i < num_transfer; i++) { ret = strm->transfer(ssi, strm); Loading Loading @@ -982,7 +1020,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 || sample_bits == 32)) { dev_err(ssi->dev, "Unsupported sample width: %d\n", sample_bits); return -EINVAL; Loading Loading @@ -1119,19 +1157,16 @@ static int rz_ssi_probe(struct platform_device *pdev) audio_clk = devm_clk_get(dev, "audio_clk1"); if (IS_ERR(audio_clk)) return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk), "no audio clk1"); return dev_err_probe(dev, PTR_ERR(audio_clk), "no audio clk1"); ssi->audio_clk_1 = clk_get_rate(audio_clk); audio_clk = devm_clk_get(dev, "audio_clk2"); if (IS_ERR(audio_clk)) return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk), "no audio clk2"); return dev_err_probe(dev, PTR_ERR(audio_clk), "no audio clk2"); ssi->audio_clk_2 = clk_get_rate(audio_clk); if (!(ssi->audio_clk_1 || ssi->audio_clk_2)) return dev_err_probe(&pdev->dev, -EINVAL, "no audio clk1 or audio clk2"); return dev_err_probe(dev, -EINVAL, "no audio clk1 or audio clk2"); ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2; Loading Loading @@ -1247,7 +1282,7 @@ static void rz_ssi_remove(struct platform_device *pdev) static const struct of_device_id rz_ssi_of_match[] = { { .compatible = "renesas,rz-ssi", }, {/* Sentinel */}, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, rz_ssi_of_match); Loading Loading
sound/soc/renesas/rz-ssi.c +77 −42 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -74,7 +75,8 @@ #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 | \ SNDRV_PCM_FMTBIT_S32_LE) #define SSI_CHAN_MIN 2 #define SSI_CHAN_MAX 2 #define SSI_FIFO_DEPTH 32 Loading Loading @@ -294,11 +296,27 @@ 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, 32} 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; case 32: ssicr |= SSICR_DWL(6); 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); Loading Loading @@ -455,7 +473,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; Loading Loading @@ -490,12 +507,23 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) break; /* calculate new buffer index */ if (ssi->hw_params_cache.sample_width == 16) { u16 *buf; buf = (u16 *)runtime->dma_area; buf += strm->buffer_pos * runtime->channels; /* Note, only supports 16-bit samples */ 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); Loading @@ -513,7 +541,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; Loading Loading @@ -542,12 +569,23 @@ static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) return 0; /* calculate new buffer index */ if (ssi->hw_params_cache.sample_width == 16) { u16 *buf; buf = (u16 *)(runtime->dma_area); buf += strm->buffer_pos * runtime->channels; /* Note, only supports 16-bit samples */ for (i = 0; i < samples; i++) rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16)); } else { u32 *buf; 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); Loading Loading @@ -658,8 +696,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; 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); } Loading Loading @@ -774,14 +817,6 @@ static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev) if (!rz_ssi_is_dma_enabled(ssi)) goto no_dma; if (ssi->playback.dma_ch && (rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, true) < 0)) goto no_dma; if (ssi->capture.dma_ch && (rz_ssi_dma_slave_config(ssi, ssi->capture.dma_ch, false) < 0)) goto no_dma; return 0; no_dma: Loading Loading @@ -829,23 +864,26 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (cmd == SNDRV_PCM_TRIGGER_START) rz_ssi_stream_init(strm, substream); if (ssi->dma_rt) { bool is_playback; if (rz_ssi_is_dma_enabled(ssi)) { bool is_playback = rz_ssi_stream_is_play(substream); is_playback = rz_ssi_stream_is_play(substream); if (ssi->dma_rt) ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, is_playback); else ret = rz_ssi_dma_slave_config(ssi, strm->dma_ch, is_playback); /* Fallback to pio */ if (ret < 0) { ssi->playback.transfer = rz_ssi_pio_send; ssi->capture.transfer = rz_ssi_pio_recv; rz_ssi_release_dma_channels(ssi); } } } else { /* For DMA, queue up multiple DMA descriptors */ if (rz_ssi_is_dma_enabled(ssi)) num_transfer = 4; } } for (i = 0; i < num_transfer; i++) { ret = strm->transfer(ssi, strm); Loading Loading @@ -982,7 +1020,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 || sample_bits == 32)) { dev_err(ssi->dev, "Unsupported sample width: %d\n", sample_bits); return -EINVAL; Loading Loading @@ -1119,19 +1157,16 @@ static int rz_ssi_probe(struct platform_device *pdev) audio_clk = devm_clk_get(dev, "audio_clk1"); if (IS_ERR(audio_clk)) return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk), "no audio clk1"); return dev_err_probe(dev, PTR_ERR(audio_clk), "no audio clk1"); ssi->audio_clk_1 = clk_get_rate(audio_clk); audio_clk = devm_clk_get(dev, "audio_clk2"); if (IS_ERR(audio_clk)) return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk), "no audio clk2"); return dev_err_probe(dev, PTR_ERR(audio_clk), "no audio clk2"); ssi->audio_clk_2 = clk_get_rate(audio_clk); if (!(ssi->audio_clk_1 || ssi->audio_clk_2)) return dev_err_probe(&pdev->dev, -EINVAL, "no audio clk1 or audio clk2"); return dev_err_probe(dev, -EINVAL, "no audio clk1 or audio clk2"); ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2; Loading Loading @@ -1247,7 +1282,7 @@ static void rz_ssi_remove(struct platform_device *pdev) static const struct of_device_id rz_ssi_of_match[] = { { .compatible = "renesas,rz-ssi", }, {/* Sentinel */}, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, rz_ssi_of_match); Loading