summaryrefslogtreecommitdiff
path: root/sound/soc/sh
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sh')
-rw-r--r--sound/soc/sh/Kconfig75
-rw-r--r--sound/soc/sh/Makefile28
-rw-r--r--sound/soc/sh/dma-sh7760.c334
-rw-r--r--sound/soc/sh/fsi.c2119
-rw-r--r--sound/soc/sh/hac.c344
-rw-r--r--sound/soc/sh/migor.c205
-rw-r--r--sound/soc/sh/rcar/Makefile3
-rw-r--r--sound/soc/sh/rcar/adg.c775
-rw-r--r--sound/soc/sh/rcar/cmd.c195
-rw-r--r--sound/soc/sh/rcar/core.c2114
-rw-r--r--sound/soc/sh/rcar/ctu.c393
-rw-r--r--sound/soc/sh/rcar/debugfs.c96
-rw-r--r--sound/soc/sh/rcar/dma.c946
-rw-r--r--sound/soc/sh/rcar/dvc.c396
-rw-r--r--sound/soc/sh/rcar/gen.c562
-rw-r--r--sound/soc/sh/rcar/mix.c360
-rw-r--r--sound/soc/sh/rcar/rsnd.h916
-rw-r--r--sound/soc/sh/rcar/src.c736
-rw-r--r--sound/soc/sh/rcar/ssi.c1260
-rw-r--r--sound/soc/sh/rcar/ssiu.c609
-rw-r--r--sound/soc/sh/rz-ssi.c1107
-rw-r--r--sound/soc/sh/sh7760-ac97.c72
-rw-r--r--sound/soc/sh/siu.h180
-rw-r--r--sound/soc/sh/siu_dai.c800
-rw-r--r--sound/soc/sh/siu_pcm.c553
-rw-r--r--sound/soc/sh/ssi.c403
26 files changed, 0 insertions, 15581 deletions
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
deleted file mode 100644
index 7bddfd5e38d6..000000000000
--- a/sound/soc/sh/Kconfig
+++ /dev/null
@@ -1,75 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-menu "SoC Audio support for Renesas SoCs"
- depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
-
-config SND_SOC_PCM_SH7760
- tristate "SoC Audio support for Renesas SH7760"
- depends on CPU_SUBTYPE_SH7760 && SH_DMABRG
- help
- Enable this option for SH7760 AC97/I2S audio support.
-
-
-##
-## Audio unit modules
-##
-
-config SND_SOC_SH4_HAC
- tristate
- select AC97_BUS
- select SND_SOC_AC97_BUS
-
-config SND_SOC_SH4_SSI
- tristate
-
-config SND_SOC_SH4_FSI
- tristate "SH4 FSI support"
- depends on SUPERH || COMMON_CLK
- select SND_SIMPLE_CARD
- help
- This option enables FSI sound support
-
-config SND_SOC_SH4_SIU
- tristate
- depends on ARCH_SHMOBILE && HAVE_CLK
- depends on DMADEVICES
- select DMA_ENGINE
- select SH_DMAE
- select FW_LOADER
-
-config SND_SOC_RCAR
- tristate "R-Car series SRU/SCU/SSIU/SSI support"
- depends on COMMON_CLK
- depends on OF
- select SND_SIMPLE_CARD_UTILS
- select REGMAP_MMIO
- help
- This option enables R-Car SRU/SCU/SSIU/SSI sound support
-
-config SND_SOC_RZ
- tristate "RZ/G2L series SSIF-2 support"
- depends on ARCH_RZG2L || COMPILE_TEST
- help
- This option enables RZ/G2L SSIF-2 sound support.
-
-##
-## Boards
-##
-
-config SND_SH7760_AC97
- tristate "SH7760 AC97 sound support"
- depends on CPU_SUBTYPE_SH7760 && SND_SOC_PCM_SH7760
- select SND_SOC_SH4_HAC
- select SND_SOC_AC97_CODEC
- help
- This option enables generic sound support for the first
- AC97 unit of the SH7760.
-
-config SND_SIU_MIGOR
- tristate "SIU sound support on Migo-R"
- depends on SH_MIGOR && I2C
- select SND_SOC_SH4_SIU
- select SND_SOC_WM8978
- help
- This option enables sound support for the SH7722 Migo-R board
-
-endmenu
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
deleted file mode 100644
index f6fd79948f6a..000000000000
--- a/sound/soc/sh/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-## DMA engines
-snd-soc-dma-sh7760-objs := dma-sh7760.o
-obj-$(CONFIG_SND_SOC_PCM_SH7760) += snd-soc-dma-sh7760.o
-
-## audio units found on some SH-4
-snd-soc-hac-objs := hac.o
-snd-soc-ssi-objs := ssi.o
-snd-soc-fsi-objs := fsi.o
-snd-soc-siu-objs := siu_pcm.o siu_dai.o
-obj-$(CONFIG_SND_SOC_SH4_HAC) += snd-soc-hac.o
-obj-$(CONFIG_SND_SOC_SH4_SSI) += snd-soc-ssi.o
-obj-$(CONFIG_SND_SOC_SH4_FSI) += snd-soc-fsi.o
-obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o
-
-## audio units for R-Car
-obj-$(CONFIG_SND_SOC_RCAR) += rcar/
-
-## boards
-snd-soc-sh7760-ac97-objs := sh7760-ac97.o
-snd-soc-migor-objs := migor.o
-
-obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
-obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o
-
-# RZ/G2L
-snd-soc-rz-ssi-objs := rz-ssi.o
-obj-$(CONFIG_SND_SOC_RZ) += snd-soc-rz-ssi.o
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
deleted file mode 100644
index c53539482c20..000000000000
--- a/sound/soc/sh/dma-sh7760.c
+++ /dev/null
@@ -1,334 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// SH7760 ("camelot") DMABRG audio DMA unit support
-//
-// Copyright (C) 2007 Manuel Lauss <mano@roarinelk.homelinux.net>
-//
-// The SH7760 DMABRG provides 4 dma channels (2x rec, 2x play), which
-// trigger an interrupt when one half of the programmed transfer size
-// has been xmitted.
-//
-// FIXME: little-endian only for now
-
-#include <linux/module.h>
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <asm/dmabrg.h>
-
-
-/* registers and bits */
-#define BRGATXSAR 0x00
-#define BRGARXDAR 0x04
-#define BRGATXTCR 0x08
-#define BRGARXTCR 0x0C
-#define BRGACR 0x10
-#define BRGATXTCNT 0x14
-#define BRGARXTCNT 0x18
-
-#define ACR_RAR (1 << 18)
-#define ACR_RDS (1 << 17)
-#define ACR_RDE (1 << 16)
-#define ACR_TAR (1 << 2)
-#define ACR_TDS (1 << 1)
-#define ACR_TDE (1 << 0)
-
-/* receiver/transmitter data alignment */
-#define ACR_RAM_NONE (0 << 24)
-#define ACR_RAM_4BYTE (1 << 24)
-#define ACR_RAM_2WORD (2 << 24)
-#define ACR_TAM_NONE (0 << 8)
-#define ACR_TAM_4BYTE (1 << 8)
-#define ACR_TAM_2WORD (2 << 8)
-
-
-struct camelot_pcm {
- unsigned long mmio; /* DMABRG audio channel control reg MMIO */
- unsigned int txid; /* ID of first DMABRG IRQ for this unit */
-
- struct snd_pcm_substream *tx_ss;
- unsigned long tx_period_size;
- unsigned int tx_period;
-
- struct snd_pcm_substream *rx_ss;
- unsigned long rx_period_size;
- unsigned int rx_period;
-
-} cam_pcm_data[2] = {
- {
- .mmio = 0xFE3C0040,
- .txid = DMABRGIRQ_A0TXF,
- },
- {
- .mmio = 0xFE3C0060,
- .txid = DMABRGIRQ_A1TXF,
- },
-};
-
-#define BRGREG(x) (*(unsigned long *)(cam->mmio + (x)))
-
-/*
- * set a minimum of 16kb per period, to avoid interrupt-"storm" and
- * resulting skipping. In general, the bigger the minimum size, the
- * better for overall system performance. (The SH7760 is a puny CPU
- * with a slow SDRAM interface and poor internal bus bandwidth,
- * *especially* when the LCDC is active). The minimum for the DMAC
- * is 8 bytes; 16kbytes are enough to get skip-free playback of a
- * 44kHz/16bit/stereo MP3 on a lightly loaded system, and maintain
- * reasonable responsiveness in MPlayer.
- */
-#define DMABRG_PERIOD_MIN 16 * 1024
-#define DMABRG_PERIOD_MAX 0x03fffffc
-#define DMABRG_PREALLOC_BUFFER 32 * 1024
-#define DMABRG_PREALLOC_BUFFER_MAX 32 * 1024
-
-static const struct snd_pcm_hardware camelot_pcm_hardware = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_BATCH),
- .buffer_bytes_max = DMABRG_PERIOD_MAX,
- .period_bytes_min = DMABRG_PERIOD_MIN,
- .period_bytes_max = DMABRG_PERIOD_MAX / 2,
- .periods_min = 2,
- .periods_max = 2,
- .fifo_size = 128,
-};
-
-static void camelot_txdma(void *data)
-{
- struct camelot_pcm *cam = data;
- cam->tx_period ^= 1;
- snd_pcm_period_elapsed(cam->tx_ss);
-}
-
-static void camelot_rxdma(void *data)
-{
- struct camelot_pcm *cam = data;
- cam->rx_period ^= 1;
- snd_pcm_period_elapsed(cam->rx_ss);
-}
-
-static int camelot_pcm_open(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct camelot_pcm *cam = &cam_pcm_data[snd_soc_rtd_to_cpu(rtd, 0)->id];
- int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
- int ret, dmairq;
-
- snd_soc_set_runtime_hwparams(substream, &camelot_pcm_hardware);
-
- /* DMABRG buffer half/full events */
- dmairq = (recv) ? cam->txid + 2 : cam->txid;
- if (recv) {
- cam->rx_ss = substream;
- ret = dmabrg_request_irq(dmairq, camelot_rxdma, cam);
- if (unlikely(ret)) {
- pr_debug("audio unit %d irqs already taken!\n",
- snd_soc_rtd_to_cpu(rtd, 0)->id);
- return -EBUSY;
- }
- (void)dmabrg_request_irq(dmairq + 1,camelot_rxdma, cam);
- } else {
- cam->tx_ss = substream;
- ret = dmabrg_request_irq(dmairq, camelot_txdma, cam);
- if (unlikely(ret)) {
- pr_debug("audio unit %d irqs already taken!\n",
- snd_soc_rtd_to_cpu(rtd, 0)->id);
- return -EBUSY;
- }
- (void)dmabrg_request_irq(dmairq + 1, camelot_txdma, cam);
- }
- return 0;
-}
-
-static int camelot_pcm_close(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct camelot_pcm *cam = &cam_pcm_data[snd_soc_rtd_to_cpu(rtd, 0)->id];
- int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
- int dmairq;
-
- dmairq = (recv) ? cam->txid + 2 : cam->txid;
-
- if (recv)
- cam->rx_ss = NULL;
- else
- cam->tx_ss = NULL;
-
- dmabrg_free_irq(dmairq + 1);
- dmabrg_free_irq(dmairq);
-
- return 0;
-}
-
-static int camelot_hw_params(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct camelot_pcm *cam = &cam_pcm_data[snd_soc_rtd_to_cpu(rtd, 0)->id];
- int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
-
- if (recv) {
- cam->rx_period_size = params_period_bytes(hw_params);
- cam->rx_period = 0;
- } else {
- cam->tx_period_size = params_period_bytes(hw_params);
- cam->tx_period = 0;
- }
- return 0;
-}
-
-static int camelot_prepare(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct camelot_pcm *cam = &cam_pcm_data[snd_soc_rtd_to_cpu(rtd, 0)->id];
-
- pr_debug("PCM data: addr %pad len %zu\n", &runtime->dma_addr,
- runtime->dma_bytes);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- BRGREG(BRGATXSAR) = (unsigned long)runtime->dma_area;
- BRGREG(BRGATXTCR) = runtime->dma_bytes;
- } else {
- BRGREG(BRGARXDAR) = (unsigned long)runtime->dma_area;
- BRGREG(BRGARXTCR) = runtime->dma_bytes;
- }
-
- return 0;
-}
-
-static inline void dmabrg_play_dma_start(struct camelot_pcm *cam)
-{
- unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS);
- /* start DMABRG engine: XFER start, auto-addr-reload */
- BRGREG(BRGACR) = acr | ACR_TDE | ACR_TAR | ACR_TAM_2WORD;
-}
-
-static inline void dmabrg_play_dma_stop(struct camelot_pcm *cam)
-{
- unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS);
- /* forcibly terminate data transmission */
- BRGREG(BRGACR) = acr | ACR_TDS;
-}
-
-static inline void dmabrg_rec_dma_start(struct camelot_pcm *cam)
-{
- unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS);
- /* start DMABRG engine: recv start, auto-reload */
- BRGREG(BRGACR) = acr | ACR_RDE | ACR_RAR | ACR_RAM_2WORD;
-}
-
-static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam)
-{
- unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS);
- /* forcibly terminate data receiver */
- BRGREG(BRGACR) = acr | ACR_RDS;
-}
-
-static int camelot_trigger(struct snd_soc_component *component,
- struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct camelot_pcm *cam = &cam_pcm_data[snd_soc_rtd_to_cpu(rtd, 0)->id];
- int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- if (recv)
- dmabrg_rec_dma_start(cam);
- else
- dmabrg_play_dma_start(cam);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- if (recv)
- dmabrg_rec_dma_stop(cam);
- else
- dmabrg_play_dma_stop(cam);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static snd_pcm_uframes_t camelot_pos(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct camelot_pcm *cam = &cam_pcm_data[snd_soc_rtd_to_cpu(rtd, 0)->id];
- int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
- unsigned long pos;
-
- /* cannot use the DMABRG pointer register: under load, by the
- * time ALSA comes around to read the register, it is already
- * far ahead (or worse, already done with the fragment) of the
- * position at the time the IRQ was triggered, which results in
- * fast-playback sound in my test application (ScummVM)
- */
- if (recv)
- pos = cam->rx_period ? cam->rx_period_size : 0;
- else
- pos = cam->tx_period ? cam->tx_period_size : 0;
-
- return bytes_to_frames(runtime, pos);
-}
-
-static int camelot_pcm_new(struct snd_soc_component *component,
- struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_pcm *pcm = rtd->pcm;
-
- /* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
- * in MMAP mode (i.e. aplay -M)
- */
- snd_pcm_set_managed_buffer_all(pcm,
- SNDRV_DMA_TYPE_CONTINUOUS,
- NULL,
- DMABRG_PREALLOC_BUFFER, DMABRG_PREALLOC_BUFFER_MAX);
-
- return 0;
-}
-
-static const struct snd_soc_component_driver sh7760_soc_component = {
- .open = camelot_pcm_open,
- .close = camelot_pcm_close,
- .hw_params = camelot_hw_params,
- .prepare = camelot_prepare,
- .trigger = camelot_trigger,
- .pointer = camelot_pos,
- .pcm_construct = camelot_pcm_new,
-};
-
-static int sh7760_soc_platform_probe(struct platform_device *pdev)
-{
- return devm_snd_soc_register_component(&pdev->dev, &sh7760_soc_component,
- NULL, 0);
-}
-
-static struct platform_driver sh7760_pcm_driver = {
- .driver = {
- .name = "sh7760-pcm-audio",
- },
-
- .probe = sh7760_soc_platform_probe,
-};
-
-module_platform_driver(sh7760_pcm_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
-MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
deleted file mode 100644
index 84601ba43b7d..000000000000
--- a/sound/soc/sh/fsi.c
+++ /dev/null
@@ -1,2119 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Fifo-attached Serial Interface (FSI) support for SH7724
-//
-// Copyright (C) 2009 Renesas Solutions Corp.
-// Kuninori Morimoto <morimoto.kuninori@renesas.com>
-//
-// Based on ssi.c
-// Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net>
-
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/pm_runtime.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/scatterlist.h>
-#include <linux/sh_dma.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/workqueue.h>
-#include <sound/soc.h>
-#include <sound/pcm_params.h>
-#include <sound/sh_fsi.h>
-
-/* PortA/PortB register */
-#define REG_DO_FMT 0x0000
-#define REG_DOFF_CTL 0x0004
-#define REG_DOFF_ST 0x0008
-#define REG_DI_FMT 0x000C
-#define REG_DIFF_CTL 0x0010
-#define REG_DIFF_ST 0x0014
-#define REG_CKG1 0x0018
-#define REG_CKG2 0x001C
-#define REG_DIDT 0x0020
-#define REG_DODT 0x0024
-#define REG_MUTE_ST 0x0028
-#define REG_OUT_DMAC 0x002C
-#define REG_OUT_SEL 0x0030
-#define REG_IN_DMAC 0x0038
-
-/* master register */
-#define MST_CLK_RST 0x0210
-#define MST_SOFT_RST 0x0214
-#define MST_FIFO_SZ 0x0218
-
-/* core register (depend on FSI version) */
-#define A_MST_CTLR 0x0180
-#define B_MST_CTLR 0x01A0
-#define CPU_INT_ST 0x01F4
-#define CPU_IEMSK 0x01F8
-#define CPU_IMSK 0x01FC
-#define INT_ST 0x0200
-#define IEMSK 0x0204
-#define IMSK 0x0208
-
-/* DO_FMT */
-/* DI_FMT */
-#define CR_BWS_MASK (0x3 << 20) /* FSI2 */
-#define CR_BWS_24 (0x0 << 20) /* FSI2 */
-#define CR_BWS_16 (0x1 << 20) /* FSI2 */
-#define CR_BWS_20 (0x2 << 20) /* FSI2 */
-
-#define CR_DTMD_PCM (0x0 << 8) /* FSI2 */
-#define CR_DTMD_SPDIF_PCM (0x1 << 8) /* FSI2 */
-#define CR_DTMD_SPDIF_STREAM (0x2 << 8) /* FSI2 */
-
-#define CR_MONO (0x0 << 4)
-#define CR_MONO_D (0x1 << 4)
-#define CR_PCM (0x2 << 4)
-#define CR_I2S (0x3 << 4)
-#define CR_TDM (0x4 << 4)
-#define CR_TDM_D (0x5 << 4)
-
-/* OUT_DMAC */
-/* IN_DMAC */
-#define VDMD_MASK (0x3 << 4)
-#define VDMD_FRONT (0x0 << 4) /* Package in front */
-#define VDMD_BACK (0x1 << 4) /* Package in back */
-#define VDMD_STREAM (0x2 << 4) /* Stream mode(16bit * 2) */
-
-#define DMA_ON (0x1 << 0)
-
-/* DOFF_CTL */
-/* DIFF_CTL */
-#define IRQ_HALF 0x00100000
-#define FIFO_CLR 0x00000001
-
-/* DOFF_ST */
-#define ERR_OVER 0x00000010
-#define ERR_UNDER 0x00000001
-#define ST_ERR (ERR_OVER | ERR_UNDER)
-
-/* CKG1 */
-#define ACKMD_MASK 0x00007000
-#define BPFMD_MASK 0x00000700
-#define DIMD (1 << 4)
-#define DOMD (1 << 0)
-
-/* A/B MST_CTLR */
-#define BP (1 << 4) /* Fix the signal of Biphase output */
-#define SE (1 << 0) /* Fix the master clock */
-
-/* CLK_RST */
-#define CRB (1 << 4)
-#define CRA (1 << 0)
-
-/* IO SHIFT / MACRO */
-#define BI_SHIFT 12
-#define BO_SHIFT 8
-#define AI_SHIFT 4
-#define AO_SHIFT 0
-#define AB_IO(param, shift) (param << shift)
-
-/* SOFT_RST */
-#define PBSR (1 << 12) /* Port B Software Reset */
-#define PASR (1 << 8) /* Port A Software Reset */
-#define IR (1 << 4) /* Interrupt Reset */
-#define FSISR (1 << 0) /* Software Reset */
-
-/* OUT_SEL (FSI2) */
-#define DMMD (1 << 4) /* SPDIF output timing 0: Biphase only */
- /* 1: Biphase and serial */
-
-/* FIFO_SZ */
-#define FIFO_SZ_MASK 0x7
-
-#define FSI_RATES SNDRV_PCM_RATE_8000_96000
-
-#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
-
-/*
- * bus options
- *
- * 0x000000BA
- *
- * A : sample widtht 16bit setting
- * B : sample widtht 24bit setting
- */
-
-#define SHIFT_16DATA 0
-#define SHIFT_24DATA 4
-
-#define PACKAGE_24BITBUS_BACK 0
-#define PACKAGE_24BITBUS_FRONT 1
-#define PACKAGE_16BITBUS_STREAM 2
-
-#define BUSOP_SET(s, a) ((a) << SHIFT_ ## s ## DATA)
-#define BUSOP_GET(s, a) (((a) >> SHIFT_ ## s ## DATA) & 0xF)
-
-/*
- * FSI driver use below type name for variable
- *
- * xxx_num : number of data
- * xxx_pos : position of data
- * xxx_capa : capacity of data
- */
-
-/*
- * period/frame/sample image
- *
- * ex) PCM (2ch)
- *
- * period pos period pos
- * [n] [n + 1]
- * |<-------------------- period--------------------->|
- * ==|============================================ ... =|==
- * | |
- * ||<----- frame ----->|<------ frame ----->| ... |
- * |+--------------------+--------------------+- ... |
- * ||[ sample ][ sample ]|[ sample ][ sample ]| ... |
- * |+--------------------+--------------------+- ... |
- * ==|============================================ ... =|==
- */
-
-/*
- * FSI FIFO image
- *
- * | |
- * | |
- * | [ sample ] |
- * | [ sample ] |
- * | [ sample ] |
- * | [ sample ] |
- * --> go to codecs
- */
-
-/*
- * FSI clock
- *
- * FSIxCLK [CPG] (ick) -------> |
- * |-> FSI_DIV (div)-> FSI2
- * FSIxCK [external] (xck) ---> |
- */
-
-/*
- * struct
- */
-
-struct fsi_stream_handler;
-struct fsi_stream {
-
- /*
- * these are initialized by fsi_stream_init()
- */
- struct snd_pcm_substream *substream;
- int fifo_sample_capa; /* sample capacity of FSI FIFO */
- int buff_sample_capa; /* sample capacity of ALSA buffer */
- int buff_sample_pos; /* sample position of ALSA buffer */
- int period_samples; /* sample number / 1 period */
- int period_pos; /* current period position */
- int sample_width; /* sample width */
- int uerr_num;
- int oerr_num;
-
- /*
- * bus options
- */
- u32 bus_option;
-
- /*
- * these are initialized by fsi_handler_init()
- */
- struct fsi_stream_handler *handler;
- struct fsi_priv *priv;
-
- /*
- * these are for DMAEngine
- */
- struct dma_chan *chan;
- int dma_id;
-};
-
-struct fsi_clk {
- /* see [FSI clock] */
- struct clk *own;
- struct clk *xck;
- struct clk *ick;
- struct clk *div;
- int (*set_rate)(struct device *dev,
- struct fsi_priv *fsi);
-
- unsigned long rate;
- unsigned int count;
-};
-
-struct fsi_priv {
- void __iomem *base;
- phys_addr_t phys;
- struct fsi_master *master;
-
- struct fsi_stream playback;
- struct fsi_stream capture;
-
- struct fsi_clk clock;
-
- u32 fmt;
-
- int chan_num:16;
- unsigned int clk_master:1;
- unsigned int clk_cpg:1;
- unsigned int spdif:1;
- unsigned int enable_stream:1;
- unsigned int bit_clk_inv:1;
- unsigned int lr_clk_inv:1;
-};
-
-struct fsi_stream_handler {
- int (*init)(struct fsi_priv *fsi, struct fsi_stream *io);
- int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io);
- int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev);
- int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
- int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
- int (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
- int enable);
-};
-#define fsi_stream_handler_call(io, func, args...) \
- (!(io) ? -ENODEV : \
- !((io)->handler->func) ? 0 : \
- (io)->handler->func(args))
-
-struct fsi_core {
- int ver;
-
- u32 int_st;
- u32 iemsk;
- u32 imsk;
- u32 a_mclk;
- u32 b_mclk;
-};
-
-struct fsi_master {
- void __iomem *base;
- struct fsi_priv fsia;
- struct fsi_priv fsib;
- const struct fsi_core *core;
- spinlock_t lock;
-};
-
-static inline int fsi_stream_is_play(struct fsi_priv *fsi,
- struct fsi_stream *io)
-{
- return &fsi->playback == io;
-}
-
-
-/*
- * basic read write function
- */
-
-static void __fsi_reg_write(u32 __iomem *reg, u32 data)
-{
- /* valid data area is 24bit */
- data &= 0x00ffffff;
-
- __raw_writel(data, reg);
-}
-
-static u32 __fsi_reg_read(u32 __iomem *reg)
-{
- return __raw_readl(reg);
-}
-
-static void __fsi_reg_mask_set(u32 __iomem *reg, u32 mask, u32 data)
-{
- u32 val = __fsi_reg_read(reg);
-
- val &= ~mask;
- val |= data & mask;
-
- __fsi_reg_write(reg, val);
-}
-
-#define fsi_reg_write(p, r, d)\
- __fsi_reg_write((p->base + REG_##r), d)
-
-#define fsi_reg_read(p, r)\
- __fsi_reg_read((p->base + REG_##r))
-
-#define fsi_reg_mask_set(p, r, m, d)\
- __fsi_reg_mask_set((p->base + REG_##r), m, d)
-
-#define fsi_master_read(p, r) _fsi_master_read(p, MST_##r)
-#define fsi_core_read(p, r) _fsi_master_read(p, p->core->r)
-static u32 _fsi_master_read(struct fsi_master *master, u32 reg)
-{
- u32 ret;
- unsigned long flags;
-
- spin_lock_irqsave(&master->lock, flags);
- ret = __fsi_reg_read(master->base + reg);
- spin_unlock_irqrestore(&master->lock, flags);
-
- return ret;
-}
-
-#define fsi_master_mask_set(p, r, m, d) _fsi_master_mask_set(p, MST_##r, m, d)
-#define fsi_core_mask_set(p, r, m, d) _fsi_master_mask_set(p, p->core->r, m, d)
-static void _fsi_master_mask_set(struct fsi_master *master,
- u32 reg, u32 mask, u32 data)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&master->lock, flags);
- __fsi_reg_mask_set(master->base + reg, mask, data);
- spin_unlock_irqrestore(&master->lock, flags);
-}
-
-/*
- * basic function
- */
-static int fsi_version(struct fsi_master *master)
-{
- return master->core->ver;
-}
-
-static struct fsi_master *fsi_get_master(struct fsi_priv *fsi)
-{
- return fsi->master;
-}
-
-static int fsi_is_clk_master(struct fsi_priv *fsi)
-{
- return fsi->clk_master;
-}
-
-static int fsi_is_port_a(struct fsi_priv *fsi)
-{
- return fsi->master->base == fsi->base;
-}
-
-static int fsi_is_spdif(struct fsi_priv *fsi)
-{
- return fsi->spdif;
-}
-
-static int fsi_is_enable_stream(struct fsi_priv *fsi)
-{
- return fsi->enable_stream;
-}
-
-static int fsi_is_play(struct snd_pcm_substream *substream)
-{
- return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-}
-
-static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
-
- return snd_soc_rtd_to_cpu(rtd, 0);
-}
-
-static struct fsi_priv *fsi_get_priv_frm_dai(struct snd_soc_dai *dai)
-{
- struct fsi_master *master = snd_soc_dai_get_drvdata(dai);
-
- if (dai->id == 0)
- return &master->fsia;
- else
- return &master->fsib;
-}
-
-static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
-{
- return fsi_get_priv_frm_dai(fsi_get_dai(substream));
-}
-
-static u32 fsi_get_port_shift(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- int is_play = fsi_stream_is_play(fsi, io);
- int is_porta = fsi_is_port_a(fsi);
- u32 shift;
-
- if (is_porta)
- shift = is_play ? AO_SHIFT : AI_SHIFT;
- else
- shift = is_play ? BO_SHIFT : BI_SHIFT;
-
- return shift;
-}
-
-static int fsi_frame2sample(struct fsi_priv *fsi, int frames)
-{
- return frames * fsi->chan_num;
-}
-
-static int fsi_sample2frame(struct fsi_priv *fsi, int samples)
-{
- return samples / fsi->chan_num;
-}
-
-static int fsi_get_current_fifo_samples(struct fsi_priv *fsi,
- struct fsi_stream *io)
-{
- int is_play = fsi_stream_is_play(fsi, io);
- u32 status;
- int frames;
-
- status = is_play ?
- fsi_reg_read(fsi, DOFF_ST) :
- fsi_reg_read(fsi, DIFF_ST);
-
- frames = 0x1ff & (status >> 8);
-
- return fsi_frame2sample(fsi, frames);
-}
-
-static void fsi_count_fifo_err(struct fsi_priv *fsi)
-{
- u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
- u32 istatus = fsi_reg_read(fsi, DIFF_ST);
-
- if (ostatus & ERR_OVER)
- fsi->playback.oerr_num++;
-
- if (ostatus & ERR_UNDER)
- fsi->playback.uerr_num++;
-
- if (istatus & ERR_OVER)
- fsi->capture.oerr_num++;
-
- if (istatus & ERR_UNDER)
- fsi->capture.uerr_num++;
-
- fsi_reg_write(fsi, DOFF_ST, 0);
- fsi_reg_write(fsi, DIFF_ST, 0);
-}
-
-/*
- * fsi_stream_xx() function
- */
-static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi,
- struct snd_pcm_substream *substream)
-{
- return fsi_is_play(substream) ? &fsi->playback : &fsi->capture;
-}
-
-static int fsi_stream_is_working(struct fsi_priv *fsi,
- struct fsi_stream *io)
-{
- struct fsi_master *master = fsi_get_master(fsi);
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&master->lock, flags);
- ret = !!(io->substream && io->substream->runtime);
- spin_unlock_irqrestore(&master->lock, flags);
-
- return ret;
-}
-
-static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io)
-{
- return io->priv;
-}
-
-static void fsi_stream_init(struct fsi_priv *fsi,
- struct fsi_stream *io,
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct fsi_master *master = fsi_get_master(fsi);
- unsigned long flags;
-
- spin_lock_irqsave(&master->lock, flags);
- io->substream = substream;
- io->buff_sample_capa = fsi_frame2sample(fsi, runtime->buffer_size);
- io->buff_sample_pos = 0;
- io->period_samples = fsi_frame2sample(fsi, runtime->period_size);
- io->period_pos = 0;
- io->sample_width = samples_to_bytes(runtime, 1);
- io->bus_option = 0;
- io->oerr_num = -1; /* ignore 1st err */
- io->uerr_num = -1; /* ignore 1st err */
- fsi_stream_handler_call(io, init, fsi, io);
- spin_unlock_irqrestore(&master->lock, flags);
-}
-
-static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- struct snd_soc_dai *dai = fsi_get_dai(io->substream);
- struct fsi_master *master = fsi_get_master(fsi);
- unsigned long flags;
-
- spin_lock_irqsave(&master->lock, flags);
-
- if (io->oerr_num > 0)
- dev_err(dai->dev, "over_run = %d\n", io->oerr_num);
-
- if (io->uerr_num > 0)
- dev_err(dai->dev, "under_run = %d\n", io->uerr_num);
-
- fsi_stream_handler_call(io, quit, fsi, io);
- io->substream = NULL;
- io->buff_sample_capa = 0;
- io->buff_sample_pos = 0;
- io->period_samples = 0;
- io->period_pos = 0;
- io->sample_width = 0;
- io->bus_option = 0;
- io->oerr_num = 0;
- io->uerr_num = 0;
- spin_unlock_irqrestore(&master->lock, flags);
-}
-
-static int fsi_stream_transfer(struct fsi_stream *io)
-{
- struct fsi_priv *fsi = fsi_stream_to_priv(io);
- if (!fsi)
- return -EIO;
-
- return fsi_stream_handler_call(io, transfer, fsi, io);
-}
-
-#define fsi_stream_start(fsi, io)\
- fsi_stream_handler_call(io, start_stop, fsi, io, 1)
-
-#define fsi_stream_stop(fsi, io)\
- fsi_stream_handler_call(io, start_stop, fsi, io, 0)
-
-static int fsi_stream_probe(struct fsi_priv *fsi, struct device *dev)
-{
- struct fsi_stream *io;
- int ret1, ret2;
-
- io = &fsi->playback;
- ret1 = fsi_stream_handler_call(io, probe, fsi, io, dev);
-
- io = &fsi->capture;
- ret2 = fsi_stream_handler_call(io, probe, fsi, io, dev);
-
- if (ret1 < 0)
- return ret1;
- if (ret2 < 0)
- return ret2;
-
- return 0;
-}
-
-static int fsi_stream_remove(struct fsi_priv *fsi)
-{
- struct fsi_stream *io;
- int ret1, ret2;
-
- io = &fsi->playback;
- ret1 = fsi_stream_handler_call(io, remove, fsi, io);
-
- io = &fsi->capture;
- ret2 = fsi_stream_handler_call(io, remove, fsi, io);
-
- if (ret1 < 0)
- return ret1;
- if (ret2 < 0)
- return ret2;
-
- return 0;
-}
-
-/*
- * format/bus/dma setting
- */
-static void fsi_format_bus_setup(struct fsi_priv *fsi, struct fsi_stream *io,
- u32 bus, struct device *dev)
-{
- struct fsi_master *master = fsi_get_master(fsi);
- int is_play = fsi_stream_is_play(fsi, io);
- u32 fmt = fsi->fmt;
-
- if (fsi_version(master) >= 2) {
- u32 dma = 0;
-
- /*
- * FSI2 needs DMA/Bus setting
- */
- switch (bus) {
- case PACKAGE_24BITBUS_FRONT:
- fmt |= CR_BWS_24;
- dma |= VDMD_FRONT;
- dev_dbg(dev, "24bit bus / package in front\n");
- break;
- case PACKAGE_16BITBUS_STREAM:
- fmt |= CR_BWS_16;
- dma |= VDMD_STREAM;
- dev_dbg(dev, "16bit bus / stream mode\n");
- break;
- case PACKAGE_24BITBUS_BACK:
- default:
- fmt |= CR_BWS_24;
- dma |= VDMD_BACK;
- dev_dbg(dev, "24bit bus / package in back\n");
- break;
- }
-
- if (is_play)
- fsi_reg_write(fsi, OUT_DMAC, dma);
- else
- fsi_reg_write(fsi, IN_DMAC, dma);
- }
-
- if (is_play)
- fsi_reg_write(fsi, DO_FMT, fmt);
- else
- fsi_reg_write(fsi, DI_FMT, fmt);
-}
-
-/*
- * irq function
- */
-
-static void fsi_irq_enable(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
- struct fsi_master *master = fsi_get_master(fsi);
-
- fsi_core_mask_set(master, imsk, data, data);
- fsi_core_mask_set(master, iemsk, data, data);
-}
-
-static void fsi_irq_disable(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
- struct fsi_master *master = fsi_get_master(fsi);
-
- fsi_core_mask_set(master, imsk, data, 0);
- fsi_core_mask_set(master, iemsk, data, 0);
-}
-
-static u32 fsi_irq_get_status(struct fsi_master *master)
-{
- return fsi_core_read(master, int_st);
-}
-
-static void fsi_irq_clear_status(struct fsi_priv *fsi)
-{
- u32 data = 0;
- struct fsi_master *master = fsi_get_master(fsi);
-
- data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->playback));
- data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->capture));
-
- /* clear interrupt factor */
- fsi_core_mask_set(master, int_st, data, 0);
-}
-
-/*
- * SPDIF master clock function
- *
- * These functions are used later FSI2
- */
-static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
-{
- struct fsi_master *master = fsi_get_master(fsi);
- u32 mask, val;
-
- mask = BP | SE;
- val = enable ? mask : 0;
-
- fsi_is_port_a(fsi) ?
- fsi_core_mask_set(master, a_mclk, mask, val) :
- fsi_core_mask_set(master, b_mclk, mask, val);
-}
-
-/*
- * clock function
- */
-static int fsi_clk_init(struct device *dev,
- struct fsi_priv *fsi,
- int xck,
- int ick,
- int div,
- int (*set_rate)(struct device *dev,
- struct fsi_priv *fsi))
-{
- struct fsi_clk *clock = &fsi->clock;
- int is_porta = fsi_is_port_a(fsi);
-
- clock->xck = NULL;
- clock->ick = NULL;
- clock->div = NULL;
- clock->rate = 0;
- clock->count = 0;
- clock->set_rate = set_rate;
-
- clock->own = devm_clk_get(dev, NULL);
- if (IS_ERR(clock->own))
- return -EINVAL;
-
- /* external clock */
- if (xck) {
- clock->xck = devm_clk_get(dev, is_porta ? "xcka" : "xckb");
- if (IS_ERR(clock->xck)) {
- dev_err(dev, "can't get xck clock\n");
- return -EINVAL;
- }
- if (clock->xck == clock->own) {
- dev_err(dev, "cpu doesn't support xck clock\n");
- return -EINVAL;
- }
- }
-
- /* FSIACLK/FSIBCLK */
- if (ick) {
- clock->ick = devm_clk_get(dev, is_porta ? "icka" : "ickb");
- if (IS_ERR(clock->ick)) {
- dev_err(dev, "can't get ick clock\n");
- return -EINVAL;
- }
- if (clock->ick == clock->own) {
- dev_err(dev, "cpu doesn't support ick clock\n");
- return -EINVAL;
- }
- }
-
- /* FSI-DIV */
- if (div) {
- clock->div = devm_clk_get(dev, is_porta ? "diva" : "divb");
- if (IS_ERR(clock->div)) {
- dev_err(dev, "can't get div clock\n");
- return -EINVAL;
- }
- if (clock->div == clock->own) {
- dev_err(dev, "cpu doesn't support div clock\n");
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-#define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0)
-static void fsi_clk_valid(struct fsi_priv *fsi, unsigned long rate)
-{
- fsi->clock.rate = rate;
-}
-
-static int fsi_clk_is_valid(struct fsi_priv *fsi)
-{
- return fsi->clock.set_rate &&
- fsi->clock.rate;
-}
-
-static int fsi_clk_enable(struct device *dev,
- struct fsi_priv *fsi)
-{
- struct fsi_clk *clock = &fsi->clock;
- int ret = -EINVAL;
-
- if (!fsi_clk_is_valid(fsi))
- return ret;
-
- if (0 == clock->count) {
- ret = clock->set_rate(dev, fsi);
- if (ret < 0) {
- fsi_clk_invalid(fsi);
- return ret;
- }
-
- ret = clk_enable(clock->xck);
- if (ret)
- goto err;
- ret = clk_enable(clock->ick);
- if (ret)
- goto disable_xck;
- ret = clk_enable(clock->div);
- if (ret)
- goto disable_ick;
-
- clock->count++;
- }
-
- return ret;
-
-disable_ick:
- clk_disable(clock->ick);
-disable_xck:
- clk_disable(clock->xck);
-err:
- return ret;
-}
-
-static int fsi_clk_disable(struct device *dev,
- struct fsi_priv *fsi)
-{
- struct fsi_clk *clock = &fsi->clock;
-
- if (!fsi_clk_is_valid(fsi))
- return -EINVAL;
-
- if (1 == clock->count--) {
- clk_disable(clock->xck);
- clk_disable(clock->ick);
- clk_disable(clock->div);
- }
-
- return 0;
-}
-
-static int fsi_clk_set_ackbpf(struct device *dev,
- struct fsi_priv *fsi,
- int ackmd, int bpfmd)
-{
- u32 data = 0;
-
- /* check ackmd/bpfmd relationship */
- if (bpfmd > ackmd) {
- dev_err(dev, "unsupported rate (%d/%d)\n", ackmd, bpfmd);
- return -EINVAL;
- }
-
- /* ACKMD */
- switch (ackmd) {
- case 512:
- data |= (0x0 << 12);
- break;
- case 256:
- data |= (0x1 << 12);
- break;
- case 128:
- data |= (0x2 << 12);
- break;
- case 64:
- data |= (0x3 << 12);
- break;
- case 32:
- data |= (0x4 << 12);
- break;
- default:
- dev_err(dev, "unsupported ackmd (%d)\n", ackmd);
- return -EINVAL;
- }
-
- /* BPFMD */
- switch (bpfmd) {
- case 32:
- data |= (0x0 << 8);
- break;
- case 64:
- data |= (0x1 << 8);
- break;
- case 128:
- data |= (0x2 << 8);
- break;
- case 256:
- data |= (0x3 << 8);
- break;
- case 512:
- data |= (0x4 << 8);
- break;
- case 16:
- data |= (0x7 << 8);
- break;
- default:
- dev_err(dev, "unsupported bpfmd (%d)\n", bpfmd);
- return -EINVAL;
- }
-
- dev_dbg(dev, "ACKMD/BPFMD = %d/%d\n", ackmd, bpfmd);
-
- fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data);
- udelay(10);
-
- return 0;
-}
-
-static int fsi_clk_set_rate_external(struct device *dev,
- struct fsi_priv *fsi)
-{
- struct clk *xck = fsi->clock.xck;
- struct clk *ick = fsi->clock.ick;
- unsigned long rate = fsi->clock.rate;
- unsigned long xrate;
- int ackmd, bpfmd;
- int ret = 0;
-
- /* check clock rate */
- xrate = clk_get_rate(xck);
- if (xrate % rate) {
- dev_err(dev, "unsupported clock rate\n");
- return -EINVAL;
- }
-
- clk_set_parent(ick, xck);
- clk_set_rate(ick, xrate);
-
- bpfmd = fsi->chan_num * 32;
- ackmd = xrate / rate;
-
- dev_dbg(dev, "external/rate = %ld/%ld\n", xrate, rate);
-
- ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd);
- if (ret < 0)
- dev_err(dev, "%s failed", __func__);
-
- return ret;
-}
-
-static int fsi_clk_set_rate_cpg(struct device *dev,
- struct fsi_priv *fsi)
-{
- struct clk *ick = fsi->clock.ick;
- struct clk *div = fsi->clock.div;
- unsigned long rate = fsi->clock.rate;
- unsigned long target = 0; /* 12288000 or 11289600 */
- unsigned long actual, cout;
- unsigned long diff, min;
- unsigned long best_cout, best_act;
- int adj;
- int ackmd, bpfmd;
- int ret = -EINVAL;
-
- if (!(12288000 % rate))
- target = 12288000;
- if (!(11289600 % rate))
- target = 11289600;
- if (!target) {
- dev_err(dev, "unsupported rate\n");
- return ret;
- }
-
- bpfmd = fsi->chan_num * 32;
- ackmd = target / rate;
- ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd);
- if (ret < 0) {
- dev_err(dev, "%s failed", __func__);
- return ret;
- }
-
- /*
- * The clock flow is
- *
- * [CPG] = cout => [FSI_DIV] = audio => [FSI] => [codec]
- *
- * But, it needs to find best match of CPG and FSI_DIV
- * combination, since it is difficult to generate correct
- * frequency of audio clock from ick clock only.
- * Because ick is created from its parent clock.
- *
- * target = rate x [512/256/128/64]fs
- * cout = round(target x adjustment)
- * actual = cout / adjustment (by FSI-DIV) ~= target
- * audio = actual
- */
- min = ~0;
- best_cout = 0;
- best_act = 0;
- for (adj = 1; adj < 0xffff; adj++) {
-
- cout = target * adj;
- if (cout > 100000000) /* max clock = 100MHz */
- break;
-
- /* cout/actual audio clock */
- cout = clk_round_rate(ick, cout);
- actual = cout / adj;
-
- /* find best frequency */
- diff = abs(actual - target);
- if (diff < min) {
- min = diff;
- best_cout = cout;
- best_act = actual;
- }
- }
-
- ret = clk_set_rate(ick, best_cout);
- if (ret < 0) {
- dev_err(dev, "ick clock failed\n");
- return -EIO;
- }
-
- ret = clk_set_rate(div, clk_round_rate(div, best_act));
- if (ret < 0) {
- dev_err(dev, "div clock failed\n");
- return -EIO;
- }
-
- dev_dbg(dev, "ick/div = %ld/%ld\n",
- clk_get_rate(ick), clk_get_rate(div));
-
- return ret;
-}
-
-static void fsi_pointer_update(struct fsi_stream *io, int size)
-{
- io->buff_sample_pos += size;
-
- if (io->buff_sample_pos >=
- io->period_samples * (io->period_pos + 1)) {
- struct snd_pcm_substream *substream = io->substream;
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- io->period_pos++;
-
- if (io->period_pos >= runtime->periods) {
- io->buff_sample_pos = 0;
- io->period_pos = 0;
- }
-
- snd_pcm_period_elapsed(substream);
- }
-}
-
-/*
- * pio data transfer handler
- */
-static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
-{
- int i;
-
- if (fsi_is_enable_stream(fsi)) {
- /*
- * stream mode
- * see
- * fsi_pio_push_init()
- */
- u32 *buf = (u32 *)_buf;
-
- for (i = 0; i < samples / 2; i++)
- fsi_reg_write(fsi, DODT, buf[i]);
- } else {
- /* normal mode */
- u16 *buf = (u16 *)_buf;
-
- for (i = 0; i < samples; i++)
- fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
- }
-}
-
-static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
-{
- u16 *buf = (u16 *)_buf;
- int i;
-
- for (i = 0; i < samples; i++)
- *(buf + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
-}
-
-static void fsi_pio_push32(struct fsi_priv *fsi, u8 *_buf, int samples)
-{
- u32 *buf = (u32 *)_buf;
- int i;
-
- for (i = 0; i < samples; i++)
- fsi_reg_write(fsi, DODT, *(buf + i));
-}
-
-static void fsi_pio_pop32(struct fsi_priv *fsi, u8 *_buf, int samples)
-{
- u32 *buf = (u32 *)_buf;
- int i;
-
- for (i = 0; i < samples; i++)
- *(buf + i) = fsi_reg_read(fsi, DIDT);
-}
-
-static u8 *fsi_pio_get_area(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- struct snd_pcm_runtime *runtime = io->substream->runtime;
-
- return runtime->dma_area +
- samples_to_bytes(runtime, io->buff_sample_pos);
-}
-
-static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
- void (*run16)(struct fsi_priv *fsi, u8 *buf, int samples),
- void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples),
- int samples)
-{
- u8 *buf;
-
- if (!fsi_stream_is_working(fsi, io))
- return -EINVAL;
-
- buf = fsi_pio_get_area(fsi, io);
-
- switch (io->sample_width) {
- case 2:
- run16(fsi, buf, samples);
- break;
- case 4:
- run32(fsi, buf, samples);
- break;
- default:
- return -EINVAL;
- }
-
- fsi_pointer_update(io, samples);
-
- return 0;
-}
-
-static int fsi_pio_pop(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- int sample_residues; /* samples in FSI fifo */
- int sample_space; /* ALSA free samples space */
- int samples;
-
- sample_residues = fsi_get_current_fifo_samples(fsi, io);
- sample_space = io->buff_sample_capa - io->buff_sample_pos;
-
- samples = min(sample_residues, sample_space);
-
- return fsi_pio_transfer(fsi, io,
- fsi_pio_pop16,
- fsi_pio_pop32,
- samples);
-}
-
-static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- int sample_residues; /* ALSA residue samples */
- int sample_space; /* FSI fifo free samples space */
- int samples;
-
- sample_residues = io->buff_sample_capa - io->buff_sample_pos;
- sample_space = io->fifo_sample_capa -
- fsi_get_current_fifo_samples(fsi, io);
-
- samples = min(sample_residues, sample_space);
-
- return fsi_pio_transfer(fsi, io,
- fsi_pio_push16,
- fsi_pio_push32,
- samples);
-}
-
-static int fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
- int enable)
-{
- struct fsi_master *master = fsi_get_master(fsi);
- u32 clk = fsi_is_port_a(fsi) ? CRA : CRB;
-
- if (enable)
- fsi_irq_enable(fsi, io);
- else
- fsi_irq_disable(fsi, io);
-
- if (fsi_is_clk_master(fsi))
- fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
-
- return 0;
-}
-
-static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- /*
- * we can use 16bit stream mode
- * when "playback" and "16bit data"
- * and platform allows "stream mode"
- * see
- * fsi_pio_push16()
- */
- if (fsi_is_enable_stream(fsi))
- io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
- BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
- else
- io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
- BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
- return 0;
-}
-
-static int fsi_pio_pop_init(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- /*
- * always 24bit bus, package back when "capture"
- */
- io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
- BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
- return 0;
-}
-
-static struct fsi_stream_handler fsi_pio_push_handler = {
- .init = fsi_pio_push_init,
- .transfer = fsi_pio_push,
- .start_stop = fsi_pio_start_stop,
-};
-
-static struct fsi_stream_handler fsi_pio_pop_handler = {
- .init = fsi_pio_pop_init,
- .transfer = fsi_pio_pop,
- .start_stop = fsi_pio_start_stop,
-};
-
-static irqreturn_t fsi_interrupt(int irq, void *data)
-{
- struct fsi_master *master = data;
- u32 int_st = fsi_irq_get_status(master);
-
- /* clear irq status */
- fsi_master_mask_set(master, SOFT_RST, IR, 0);
- fsi_master_mask_set(master, SOFT_RST, IR, IR);
-
- if (int_st & AB_IO(1, AO_SHIFT))
- fsi_stream_transfer(&master->fsia.playback);
- if (int_st & AB_IO(1, BO_SHIFT))
- fsi_stream_transfer(&master->fsib.playback);
- if (int_st & AB_IO(1, AI_SHIFT))
- fsi_stream_transfer(&master->fsia.capture);
- if (int_st & AB_IO(1, BI_SHIFT))
- fsi_stream_transfer(&master->fsib.capture);
-
- fsi_count_fifo_err(&master->fsia);
- fsi_count_fifo_err(&master->fsib);
-
- fsi_irq_clear_status(&master->fsia);
- fsi_irq_clear_status(&master->fsib);
-
- return IRQ_HANDLED;
-}
-
-/*
- * dma data transfer handler
- */
-static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- /*
- * 24bit data : 24bit bus / package in back
- * 16bit data : 16bit bus / stream mode
- */
- io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
- BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
-
- return 0;
-}
-
-static void fsi_dma_complete(void *data)
-{
- struct fsi_stream *io = (struct fsi_stream *)data;
- struct fsi_priv *fsi = fsi_stream_to_priv(io);
-
- fsi_pointer_update(io, io->period_samples);
-
- fsi_count_fifo_err(fsi);
-}
-
-static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- struct snd_soc_dai *dai = fsi_get_dai(io->substream);
- struct snd_pcm_substream *substream = io->substream;
- struct dma_async_tx_descriptor *desc;
- int is_play = fsi_stream_is_play(fsi, io);
- enum dma_transfer_direction dir;
- int ret = -EIO;
-
- if (is_play)
- dir = DMA_MEM_TO_DEV;
- else
- dir = DMA_DEV_TO_MEM;
-
- desc = dmaengine_prep_dma_cyclic(io->chan,
- substream->runtime->dma_addr,
- snd_pcm_lib_buffer_bytes(substream),
- snd_pcm_lib_period_bytes(substream),
- dir,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- dev_err(dai->dev, "dmaengine_prep_dma_cyclic() fail\n");
- goto fsi_dma_transfer_err;
- }
-
- desc->callback = fsi_dma_complete;
- desc->callback_param = io;
-
- if (dmaengine_submit(desc) < 0) {
- dev_err(dai->dev, "tx_submit() fail\n");
- goto fsi_dma_transfer_err;
- }
-
- dma_async_issue_pending(io->chan);
-
- /*
- * FIXME
- *
- * In DMAEngine case, codec and FSI cannot be started simultaneously
- * since FSI is using the scheduler work queue.
- * Therefore, in capture case, probably FSI FIFO will have got
- * overflow error in this point.
- * in that case, DMA cannot start transfer until error was cleared.
- */
- if (!is_play) {
- if (ERR_OVER & fsi_reg_read(fsi, DIFF_ST)) {
- fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
- fsi_reg_write(fsi, DIFF_ST, 0);
- }
- }
-
- ret = 0;
-
-fsi_dma_transfer_err:
- return ret;
-}
-
-static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
- int start)
-{
- struct fsi_master *master = fsi_get_master(fsi);
- u32 clk = fsi_is_port_a(fsi) ? CRA : CRB;
- u32 enable = start ? DMA_ON : 0;
-
- fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
-
- dmaengine_terminate_all(io->chan);
-
- if (fsi_is_clk_master(fsi))
- fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
-
- return 0;
-}
-
-static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev)
-{
- int is_play = fsi_stream_is_play(fsi, io);
-
-#ifdef CONFIG_SUPERH
- dma_cap_mask_t mask;
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- io->chan = dma_request_channel(mask, shdma_chan_filter,
- (void *)io->dma_id);
-#else
- io->chan = dma_request_chan(dev, is_play ? "tx" : "rx");
- if (IS_ERR(io->chan))
- io->chan = NULL;
-#endif
- if (io->chan) {
- struct dma_slave_config cfg = {};
- int ret;
-
- if (is_play) {
- cfg.dst_addr = fsi->phys + REG_DODT;
- cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- cfg.direction = DMA_MEM_TO_DEV;
- } else {
- cfg.src_addr = fsi->phys + REG_DIDT;
- cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- cfg.direction = DMA_DEV_TO_MEM;
- }
-
- ret = dmaengine_slave_config(io->chan, &cfg);
- if (ret < 0) {
- dma_release_channel(io->chan);
- io->chan = NULL;
- }
- }
-
- if (!io->chan) {
-
- /* switch to PIO handler */
- if (is_play)
- fsi->playback.handler = &fsi_pio_push_handler;
- else
- fsi->capture.handler = &fsi_pio_pop_handler;
-
- dev_info(dev, "switch handler (dma => pio)\n");
-
- /* probe again */
- return fsi_stream_probe(fsi, dev);
- }
-
- return 0;
-}
-
-static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
-{
- fsi_stream_stop(fsi, io);
-
- if (io->chan)
- dma_release_channel(io->chan);
-
- io->chan = NULL;
- return 0;
-}
-
-static struct fsi_stream_handler fsi_dma_push_handler = {
- .init = fsi_dma_init,
- .probe = fsi_dma_probe,
- .transfer = fsi_dma_transfer,
- .remove = fsi_dma_remove,
- .start_stop = fsi_dma_push_start_stop,
-};
-
-/*
- * dai ops
- */
-static void fsi_fifo_init(struct fsi_priv *fsi,
- struct fsi_stream *io,
- struct device *dev)
-{
- struct fsi_master *master = fsi_get_master(fsi);
- int is_play = fsi_stream_is_play(fsi, io);
- u32 shift, i;
- int frame_capa;
-
- /* get on-chip RAM capacity */
- shift = fsi_master_read(master, FIFO_SZ);
- shift >>= fsi_get_port_shift(fsi, io);
- shift &= FIFO_SZ_MASK;
- frame_capa = 256 << shift;
- dev_dbg(dev, "fifo = %d words\n", frame_capa);
-
- /*
- * The maximum number of sample data varies depending
- * on the number of channels selected for the format.
- *
- * FIFOs are used in 4-channel units in 3-channel mode
- * and in 8-channel units in 5- to 7-channel mode
- * meaning that more FIFOs than the required size of DPRAM
- * are used.
- *
- * ex) if 256 words of DP-RAM is connected
- * 1 channel: 256 (256 x 1 = 256)
- * 2 channels: 128 (128 x 2 = 256)
- * 3 channels: 64 ( 64 x 3 = 192)
- * 4 channels: 64 ( 64 x 4 = 256)
- * 5 channels: 32 ( 32 x 5 = 160)
- * 6 channels: 32 ( 32 x 6 = 192)
- * 7 channels: 32 ( 32 x 7 = 224)
- * 8 channels: 32 ( 32 x 8 = 256)
- */
- for (i = 1; i < fsi->chan_num; i <<= 1)
- frame_capa >>= 1;
- dev_dbg(dev, "%d channel %d store\n",
- fsi->chan_num, frame_capa);
-
- io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
-
- /*
- * set interrupt generation factor
- * clear FIFO
- */
- if (is_play) {
- fsi_reg_write(fsi, DOFF_CTL, IRQ_HALF);
- fsi_reg_mask_set(fsi, DOFF_CTL, FIFO_CLR, FIFO_CLR);
- } else {
- fsi_reg_write(fsi, DIFF_CTL, IRQ_HALF);
- fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
- }
-}
-
-static int fsi_hw_startup(struct fsi_priv *fsi,
- struct fsi_stream *io,
- struct device *dev)
-{
- u32 data = 0;
-
- /* clock setting */
- if (fsi_is_clk_master(fsi))
- data = DIMD | DOMD;
-
- fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data);
-
- /* clock inversion (CKG2) */
- data = 0;
- if (fsi->bit_clk_inv)
- data |= (1 << 0);
- if (fsi->lr_clk_inv)
- data |= (1 << 4);
- if (fsi_is_clk_master(fsi))
- data <<= 8;
- fsi_reg_write(fsi, CKG2, data);
-
- /* spdif ? */
- if (fsi_is_spdif(fsi)) {
- fsi_spdif_clk_ctrl(fsi, 1);
- fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
- }
-
- /*
- * get bus settings
- */
- data = 0;
- switch (io->sample_width) {
- case 2:
- data = BUSOP_GET(16, io->bus_option);
- break;
- case 4:
- data = BUSOP_GET(24, io->bus_option);
- break;
- }
- fsi_format_bus_setup(fsi, io, data, dev);
-
- /* irq clear */
- fsi_irq_disable(fsi, io);
- fsi_irq_clear_status(fsi);
-
- /* fifo init */
- fsi_fifo_init(fsi, io, dev);
-
- /* start master clock */
- if (fsi_is_clk_master(fsi))
- return fsi_clk_enable(dev, fsi);
-
- return 0;
-}
-
-static int fsi_hw_shutdown(struct fsi_priv *fsi,
- struct device *dev)
-{
- /* stop master clock */
- if (fsi_is_clk_master(fsi))
- return fsi_clk_disable(dev, fsi);
-
- return 0;
-}
-
-static int fsi_dai_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct fsi_priv *fsi = fsi_get_priv(substream);
-
- fsi_clk_invalid(fsi);
-
- return 0;
-}
-
-static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct fsi_priv *fsi = fsi_get_priv(substream);
-
- fsi_clk_invalid(fsi);
-}
-
-static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct fsi_priv *fsi = fsi_get_priv(substream);
- struct fsi_stream *io = fsi_stream_get(fsi, substream);
- int ret = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- fsi_stream_init(fsi, io, substream);
- if (!ret)
- ret = fsi_hw_startup(fsi, io, dai->dev);
- if (!ret)
- ret = fsi_stream_start(fsi, io);
- if (!ret)
- ret = fsi_stream_transfer(io);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- if (!ret)
- ret = fsi_hw_shutdown(fsi, dai->dev);
- fsi_stream_stop(fsi, io);
- fsi_stream_quit(fsi, io);
- break;
- }
-
- return ret;
-}
-
-static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt)
-{
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- fsi->fmt = CR_I2S;
- fsi->chan_num = 2;
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- fsi->fmt = CR_PCM;
- fsi->chan_num = 2;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
-{
- struct fsi_master *master = fsi_get_master(fsi);
-
- if (fsi_version(master) < 2)
- return -EINVAL;
-
- fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM;
- fsi->chan_num = 2;
-
- return 0;
-}
-
-static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
- struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
- int ret;
-
- /* set clock master audio interface */
- switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
- case SND_SOC_DAIFMT_BC_FC:
- break;
- case SND_SOC_DAIFMT_BP_FP:
- fsi->clk_master = 1; /* cpu is master */
- break;
- default:
- return -EINVAL;
- }
-
- /* set clock inversion */
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_IF:
- fsi->bit_clk_inv = 0;
- fsi->lr_clk_inv = 1;
- break;
- case SND_SOC_DAIFMT_IB_NF:
- fsi->bit_clk_inv = 1;
- fsi->lr_clk_inv = 0;
- break;
- case SND_SOC_DAIFMT_IB_IF:
- fsi->bit_clk_inv = 1;
- fsi->lr_clk_inv = 1;
- break;
- case SND_SOC_DAIFMT_NB_NF:
- default:
- fsi->bit_clk_inv = 0;
- fsi->lr_clk_inv = 0;
- break;
- }
-
- if (fsi_is_clk_master(fsi)) {
- if (fsi->clk_cpg)
- fsi_clk_init(dai->dev, fsi, 0, 1, 1,
- fsi_clk_set_rate_cpg);
- else
- fsi_clk_init(dai->dev, fsi, 1, 1, 0,
- fsi_clk_set_rate_external);
- }
-
- /* set format */
- if (fsi_is_spdif(fsi))
- ret = fsi_set_fmt_spdif(fsi);
- else
- ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
-
- return ret;
-}
-
-static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct fsi_priv *fsi = fsi_get_priv(substream);
-
- if (fsi_is_clk_master(fsi))
- fsi_clk_valid(fsi, params_rate(params));
-
- return 0;
-}
-
-/*
- * Select below from Sound Card, not auto
- * SND_SOC_DAIFMT_CBC_CFC
- * SND_SOC_DAIFMT_CBP_CFP
- */
-static u64 fsi_dai_formats =
- SND_SOC_POSSIBLE_DAIFMT_I2S |
- SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
- SND_SOC_POSSIBLE_DAIFMT_NB_NF |
- SND_SOC_POSSIBLE_DAIFMT_NB_IF |
- SND_SOC_POSSIBLE_DAIFMT_IB_NF |
- SND_SOC_POSSIBLE_DAIFMT_IB_IF;
-
-static const struct snd_soc_dai_ops fsi_dai_ops = {
- .startup = fsi_dai_startup,
- .shutdown = fsi_dai_shutdown,
- .trigger = fsi_dai_trigger,
- .set_fmt = fsi_dai_set_fmt,
- .hw_params = fsi_dai_hw_params,
- .auto_selectable_formats = &fsi_dai_formats,
- .num_auto_selectable_formats = 1,
-};
-
-/*
- * pcm ops
- */
-
-static const struct snd_pcm_hardware fsi_pcm_hardware = {
- .info = SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID,
- .buffer_bytes_max = 64 * 1024,
- .period_bytes_min = 32,
- .period_bytes_max = 8192,
- .periods_min = 1,
- .periods_max = 32,
- .fifo_size = 256,
-};
-
-static int fsi_pcm_open(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int ret = 0;
-
- snd_soc_set_runtime_hwparams(substream, &fsi_pcm_hardware);
-
- ret = snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
-
- return ret;
-}
-
-static snd_pcm_uframes_t fsi_pointer(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct fsi_priv *fsi = fsi_get_priv(substream);
- struct fsi_stream *io = fsi_stream_get(fsi, substream);
-
- return fsi_sample2frame(fsi, io->buff_sample_pos);
-}
-
-/*
- * snd_soc_component
- */
-
-#define PREALLOC_BUFFER (32 * 1024)
-#define PREALLOC_BUFFER_MAX (32 * 1024)
-
-static int fsi_pcm_new(struct snd_soc_component *component,
- struct snd_soc_pcm_runtime *rtd)
-{
- snd_pcm_set_managed_buffer_all(
- rtd->pcm,
- SNDRV_DMA_TYPE_DEV,
- rtd->card->snd_card->dev,
- PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
- return 0;
-}
-
-/*
- * alsa struct
- */
-
-static struct snd_soc_dai_driver fsi_soc_dai[] = {
- {
- .name = "fsia-dai",
- .playback = {
- .rates = FSI_RATES,
- .formats = FSI_FMTS,
- .channels_min = 2,
- .channels_max = 2,
- },
- .capture = {
- .rates = FSI_RATES,
- .formats = FSI_FMTS,
- .channels_min = 2,
- .channels_max = 2,
- },
- .ops = &fsi_dai_ops,
- },
- {
- .name = "fsib-dai",
- .playback = {
- .rates = FSI_RATES,
- .formats = FSI_FMTS,
- .channels_min = 2,
- .channels_max = 2,
- },
- .capture = {
- .rates = FSI_RATES,
- .formats = FSI_FMTS,
- .channels_min = 2,
- .channels_max = 2,
- },
- .ops = &fsi_dai_ops,
- },
-};
-
-static const struct snd_soc_component_driver fsi_soc_component = {
- .name = "fsi",
- .open = fsi_pcm_open,
- .pointer = fsi_pointer,
- .pcm_construct = fsi_pcm_new,
-};
-
-/*
- * platform function
- */
-static void fsi_of_parse(char *name,
- struct device_node *np,
- struct sh_fsi_port_info *info,
- struct device *dev)
-{
- int i;
- char prop[128];
- unsigned long flags = 0;
- struct {
- char *name;
- unsigned int val;
- } of_parse_property[] = {
- { "spdif-connection", SH_FSI_FMT_SPDIF },
- { "stream-mode-support", SH_FSI_ENABLE_STREAM_MODE },
- { "use-internal-clock", SH_FSI_CLK_CPG },
- };
-
- for (i = 0; i < ARRAY_SIZE(of_parse_property); i++) {
- sprintf(prop, "%s,%s", name, of_parse_property[i].name);
- if (of_property_present(np, prop))
- flags |= of_parse_property[i].val;
- }
- info->flags = flags;
-
- dev_dbg(dev, "%s flags : %lx\n", name, info->flags);
-}
-
-static void fsi_port_info_init(struct fsi_priv *fsi,
- struct sh_fsi_port_info *info)
-{
- if (info->flags & SH_FSI_FMT_SPDIF)
- fsi->spdif = 1;
-
- if (info->flags & SH_FSI_CLK_CPG)
- fsi->clk_cpg = 1;
-
- if (info->flags & SH_FSI_ENABLE_STREAM_MODE)
- fsi->enable_stream = 1;
-}
-
-static void fsi_handler_init(struct fsi_priv *fsi,
- struct sh_fsi_port_info *info)
-{
- fsi->playback.handler = &fsi_pio_push_handler; /* default PIO */
- fsi->playback.priv = fsi;
- fsi->capture.handler = &fsi_pio_pop_handler; /* default PIO */
- fsi->capture.priv = fsi;
-
- if (info->tx_id) {
- fsi->playback.dma_id = info->tx_id;
- fsi->playback.handler = &fsi_dma_push_handler;
- }
-}
-
-static const struct fsi_core fsi1_core = {
- .ver = 1,
-
- /* Interrupt */
- .int_st = INT_ST,
- .iemsk = IEMSK,
- .imsk = IMSK,
-};
-
-static const struct fsi_core fsi2_core = {
- .ver = 2,
-
- /* Interrupt */
- .int_st = CPU_INT_ST,
- .iemsk = CPU_IEMSK,
- .imsk = CPU_IMSK,
- .a_mclk = A_MST_CTLR,
- .b_mclk = B_MST_CTLR,
-};
-
-static const struct of_device_id fsi_of_match[] = {
- { .compatible = "renesas,sh_fsi", .data = &fsi1_core},
- { .compatible = "renesas,sh_fsi2", .data = &fsi2_core},
- {},
-};
-MODULE_DEVICE_TABLE(of, fsi_of_match);
-
-static const struct platform_device_id fsi_id_table[] = {
- { "sh_fsi", (kernel_ulong_t)&fsi1_core },
- {},
-};
-MODULE_DEVICE_TABLE(platform, fsi_id_table);
-
-static int fsi_probe(struct platform_device *pdev)
-{
- struct fsi_master *master;
- struct device_node *np = pdev->dev.of_node;
- struct sh_fsi_platform_info info;
- const struct fsi_core *core;
- struct fsi_priv *fsi;
- struct resource *res;
- unsigned int irq;
- int ret;
-
- memset(&info, 0, sizeof(info));
-
- core = NULL;
- if (np) {
- core = of_device_get_match_data(&pdev->dev);
- fsi_of_parse("fsia", np, &info.port_a, &pdev->dev);
- fsi_of_parse("fsib", np, &info.port_b, &pdev->dev);
- } else {
- const struct platform_device_id *id_entry = pdev->id_entry;
- if (id_entry)
- core = (struct fsi_core *)id_entry->driver_data;
-
- if (pdev->dev.platform_data)
- memcpy(&info, pdev->dev.platform_data, sizeof(info));
- }
-
- if (!core) {
- dev_err(&pdev->dev, "unknown fsi device\n");
- return -ENODEV;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
- if (!res || (int)irq <= 0) {
- dev_err(&pdev->dev, "Not enough FSI platform resources.\n");
- return -ENODEV;
- }
-
- master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL);
- if (!master)
- return -ENOMEM;
-
- master->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!master->base) {
- dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n");
- return -ENXIO;
- }
-
- /* master setting */
- master->core = core;
- spin_lock_init(&master->lock);
-
- /* FSI A setting */
- fsi = &master->fsia;
- fsi->base = master->base;
- fsi->phys = res->start;
- fsi->master = master;
- fsi_port_info_init(fsi, &info.port_a);
- fsi_handler_init(fsi, &info.port_a);
- ret = fsi_stream_probe(fsi, &pdev->dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "FSIA stream probe failed\n");
- return ret;
- }
-
- /* FSI B setting */
- fsi = &master->fsib;
- fsi->base = master->base + 0x40;
- fsi->phys = res->start + 0x40;
- fsi->master = master;
- fsi_port_info_init(fsi, &info.port_b);
- fsi_handler_init(fsi, &info.port_b);
- ret = fsi_stream_probe(fsi, &pdev->dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "FSIB stream probe failed\n");
- goto exit_fsia;
- }
-
- pm_runtime_enable(&pdev->dev);
- dev_set_drvdata(&pdev->dev, master);
-
- ret = devm_request_irq(&pdev->dev, irq, &fsi_interrupt, 0,
- dev_name(&pdev->dev), master);
- if (ret) {
- dev_err(&pdev->dev, "irq request err\n");
- goto exit_fsib;
- }
-
- ret = devm_snd_soc_register_component(&pdev->dev, &fsi_soc_component,
- fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
- if (ret < 0) {
- dev_err(&pdev->dev, "cannot snd component register\n");
- goto exit_fsib;
- }
-
- return ret;
-
-exit_fsib:
- pm_runtime_disable(&pdev->dev);
- fsi_stream_remove(&master->fsib);
-exit_fsia:
- fsi_stream_remove(&master->fsia);
-
- return ret;
-}
-
-static void fsi_remove(struct platform_device *pdev)
-{
- struct fsi_master *master;
-
- master = dev_get_drvdata(&pdev->dev);
-
- pm_runtime_disable(&pdev->dev);
-
- fsi_stream_remove(&master->fsia);
- fsi_stream_remove(&master->fsib);
-}
-
-static void __fsi_suspend(struct fsi_priv *fsi,
- struct fsi_stream *io,
- struct device *dev)
-{
- if (!fsi_stream_is_working(fsi, io))
- return;
-
- fsi_stream_stop(fsi, io);
- fsi_hw_shutdown(fsi, dev);
-}
-
-static void __fsi_resume(struct fsi_priv *fsi,
- struct fsi_stream *io,
- struct device *dev)
-{
- if (!fsi_stream_is_working(fsi, io))
- return;
-
- fsi_hw_startup(fsi, io, dev);
- fsi_stream_start(fsi, io);
-}
-
-static int fsi_suspend(struct device *dev)
-{
- struct fsi_master *master = dev_get_drvdata(dev);
- struct fsi_priv *fsia = &master->fsia;
- struct fsi_priv *fsib = &master->fsib;
-
- __fsi_suspend(fsia, &fsia->playback, dev);
- __fsi_suspend(fsia, &fsia->capture, dev);
-
- __fsi_suspend(fsib, &fsib->playback, dev);
- __fsi_suspend(fsib, &fsib->capture, dev);
-
- return 0;
-}
-
-static int fsi_resume(struct device *dev)
-{
- struct fsi_master *master = dev_get_drvdata(dev);
- struct fsi_priv *fsia = &master->fsia;
- struct fsi_priv *fsib = &master->fsib;
-
- __fsi_resume(fsia, &fsia->playback, dev);
- __fsi_resume(fsia, &fsia->capture, dev);
-
- __fsi_resume(fsib, &fsib->playback, dev);
- __fsi_resume(fsib, &fsib->capture, dev);
-
- return 0;
-}
-
-static const struct dev_pm_ops fsi_pm_ops = {
- .suspend = fsi_suspend,
- .resume = fsi_resume,
-};
-
-static struct platform_driver fsi_driver = {
- .driver = {
- .name = "fsi-pcm-audio",
- .pm = &fsi_pm_ops,
- .of_match_table = fsi_of_match,
- },
- .probe = fsi_probe,
- .remove_new = fsi_remove,
- .id_table = fsi_id_table,
-};
-
-module_platform_driver(fsi_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("SuperH onchip FSI audio driver");
-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
-MODULE_ALIAS("platform:fsi-pcm-audio");
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
deleted file mode 100644
index cc200f45826c..000000000000
--- a/sound/soc/sh/hac.c
+++ /dev/null
@@ -1,344 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Hitachi Audio Controller (AC97) support for SH7760/SH7780
-//
-// Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net>
-//
-// dont forget to set IPSEL/OMSEL register bits (in your board code) to
-// enable HAC output pins!
-
-/* BIG FAT FIXME: although the SH7760 has 2 independent AC97 units, only
- * the FIRST can be used since ASoC does not pass any information to the
- * ac97_read/write() functions regarding WHICH unit to use. You'll have
- * to edit the code a bit to use the other AC97 unit. --mlau
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/delay.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/ac97_codec.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-
-/* regs and bits */
-#define HACCR 0x08
-#define HACCSAR 0x20
-#define HACCSDR 0x24
-#define HACPCML 0x28
-#define HACPCMR 0x2C
-#define HACTIER 0x50
-#define HACTSR 0x54
-#define HACRIER 0x58
-#define HACRSR 0x5C
-#define HACACR 0x60
-
-#define CR_CR (1 << 15) /* "codec-ready" indicator */
-#define CR_CDRT (1 << 11) /* cold reset */
-#define CR_WMRT (1 << 10) /* warm reset */
-#define CR_B9 (1 << 9) /* the mysterious "bit 9" */
-#define CR_ST (1 << 5) /* AC97 link start bit */
-
-#define CSAR_RD (1 << 19) /* AC97 data read bit */
-#define CSAR_WR (0)
-
-#define TSR_CMDAMT (1 << 31)
-#define TSR_CMDDMT (1 << 30)
-
-#define RSR_STARY (1 << 22)
-#define RSR_STDRY (1 << 21)
-
-#define ACR_DMARX16 (1 << 30)
-#define ACR_DMATX16 (1 << 29)
-#define ACR_TX12ATOM (1 << 26)
-#define ACR_DMARX20 ((1 << 24) | (1 << 22))
-#define ACR_DMATX20 ((1 << 23) | (1 << 21))
-
-#define CSDR_SHIFT 4
-#define CSDR_MASK (0xffff << CSDR_SHIFT)
-#define CSAR_SHIFT 12
-#define CSAR_MASK (0x7f << CSAR_SHIFT)
-
-#define AC97_WRITE_RETRY 1
-#define AC97_READ_RETRY 5
-
-/* manual-suggested AC97 codec access timeouts (us) */
-#define TMO_E1 500 /* 21 < E1 < 1000 */
-#define TMO_E2 13 /* 13 < E2 */
-#define TMO_E3 21 /* 21 < E3 */
-#define TMO_E4 500 /* 21 < E4 < 1000 */
-
-struct hac_priv {
- unsigned long mmio; /* HAC base address */
-} hac_cpu_data[] = {
-#if defined(CONFIG_CPU_SUBTYPE_SH7760)
- {
- .mmio = 0xFE240000,
- },
- {
- .mmio = 0xFE250000,
- },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
- {
- .mmio = 0xFFE40000,
- },
-#else
-#error "Unsupported SuperH SoC"
-#endif
-};
-
-#define HACREG(reg) (*(unsigned long *)(hac->mmio + (reg)))
-
-/*
- * AC97 read/write flow as outlined in the SH7760 manual (pages 903-906)
- */
-static int hac_get_codec_data(struct hac_priv *hac, unsigned short r,
- unsigned short *v)
-{
- unsigned int to1, to2, i;
- unsigned short adr;
-
- for (i = AC97_READ_RETRY; i; i--) {
- *v = 0;
- /* wait for HAC to receive something from the codec */
- for (to1 = TMO_E4;
- to1 && !(HACREG(HACRSR) & RSR_STARY);
- --to1)
- udelay(1);
- for (to2 = TMO_E4;
- to2 && !(HACREG(HACRSR) & RSR_STDRY);
- --to2)
- udelay(1);
-
- if (!to1 && !to2)
- return 0; /* codec comm is down */
-
- adr = ((HACREG(HACCSAR) & CSAR_MASK) >> CSAR_SHIFT);
- *v = ((HACREG(HACCSDR) & CSDR_MASK) >> CSDR_SHIFT);
-
- HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY);
-
- if (r == adr)
- break;
-
- /* manual says: wait at least 21 usec before retrying */
- udelay(21);
- }
- HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY);
- return i;
-}
-
-static unsigned short hac_read_codec_aux(struct hac_priv *hac,
- unsigned short reg)
-{
- unsigned short val;
- unsigned int i, to;
-
- for (i = AC97_READ_RETRY; i; i--) {
- /* send_read_request */
- local_irq_disable();
- HACREG(HACTSR) &= ~(TSR_CMDAMT);
- HACREG(HACCSAR) = (reg << CSAR_SHIFT) | CSAR_RD;
- local_irq_enable();
-
- for (to = TMO_E3;
- to && !(HACREG(HACTSR) & TSR_CMDAMT);
- --to)
- udelay(1);
-
- HACREG(HACTSR) &= ~TSR_CMDAMT;
- val = 0;
- if (hac_get_codec_data(hac, reg, &val) != 0)
- break;
- }
-
- return i ? val : ~0;
-}
-
-static void hac_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
- unsigned short val)
-{
- int unit_id = 0 /* ac97->private_data */;
- struct hac_priv *hac = &hac_cpu_data[unit_id];
- unsigned int i, to;
- /* write_codec_aux */
- for (i = AC97_WRITE_RETRY; i; i--) {
- /* send_write_request */
- local_irq_disable();
- HACREG(HACTSR) &= ~(TSR_CMDDMT | TSR_CMDAMT);
- HACREG(HACCSDR) = (val << CSDR_SHIFT);
- HACREG(HACCSAR) = (reg << CSAR_SHIFT) & (~CSAR_RD);
- local_irq_enable();
-
- /* poll-wait for CMDAMT and CMDDMT */
- for (to = TMO_E1;
- to && !(HACREG(HACTSR) & (TSR_CMDAMT|TSR_CMDDMT));
- --to)
- udelay(1);
-
- HACREG(HACTSR) &= ~(TSR_CMDAMT | TSR_CMDDMT);
- if (to)
- break;
- /* timeout, try again */
- }
-}
-
-static unsigned short hac_ac97_read(struct snd_ac97 *ac97,
- unsigned short reg)
-{
- int unit_id = 0 /* ac97->private_data */;
- struct hac_priv *hac = &hac_cpu_data[unit_id];
- return hac_read_codec_aux(hac, reg);
-}
-
-static void hac_ac97_warmrst(struct snd_ac97 *ac97)
-{
- int unit_id = 0 /* ac97->private_data */;
- struct hac_priv *hac = &hac_cpu_data[unit_id];
- unsigned int tmo;
-
- HACREG(HACCR) = CR_WMRT | CR_ST | CR_B9;
- msleep(10);
- HACREG(HACCR) = CR_ST | CR_B9;
- for (tmo = 1000; (tmo > 0) && !(HACREG(HACCR) & CR_CR); tmo--)
- udelay(1);
-
- if (!tmo)
- printk(KERN_INFO "hac: reset: AC97 link down!\n");
- /* settings this bit lets us have a conversation with codec */
- HACREG(HACACR) |= ACR_TX12ATOM;
-}
-
-static void hac_ac97_coldrst(struct snd_ac97 *ac97)
-{
- int unit_id = 0 /* ac97->private_data */;
- struct hac_priv *hac;
- hac = &hac_cpu_data[unit_id];
-
- HACREG(HACCR) = 0;
- HACREG(HACCR) = CR_CDRT | CR_ST | CR_B9;
- msleep(10);
- hac_ac97_warmrst(ac97);
-}
-
-static struct snd_ac97_bus_ops hac_ac97_ops = {
- .read = hac_ac97_read,
- .write = hac_ac97_write,
- .reset = hac_ac97_coldrst,
- .warm_reset = hac_ac97_warmrst,
-};
-
-static int hac_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct hac_priv *hac = &hac_cpu_data[dai->id];
- int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
-
- switch (params->msbits) {
- case 16:
- HACREG(HACACR) |= d ? ACR_DMARX16 : ACR_DMATX16;
- HACREG(HACACR) &= d ? ~ACR_DMARX20 : ~ACR_DMATX20;
- break;
- case 20:
- HACREG(HACACR) &= d ? ~ACR_DMARX16 : ~ACR_DMATX16;
- HACREG(HACACR) |= d ? ACR_DMARX20 : ACR_DMATX20;
- break;
- default:
- pr_debug("hac: invalid depth %d bit\n", params->msbits);
- return -EINVAL;
- break;
- }
-
- return 0;
-}
-
-#define AC97_RATES \
- SNDRV_PCM_RATE_8000_192000
-
-#define AC97_FMTS \
- SNDRV_PCM_FMTBIT_S16_LE
-
-static const struct snd_soc_dai_ops hac_dai_ops = {
- .hw_params = hac_hw_params,
-};
-
-static struct snd_soc_dai_driver sh4_hac_dai[] = {
-{
- .name = "hac-dai.0",
- .playback = {
- .rates = AC97_RATES,
- .formats = AC97_FMTS,
- .channels_min = 2,
- .channels_max = 2,
- },
- .capture = {
- .rates = AC97_RATES,
- .formats = AC97_FMTS,
- .channels_min = 2,
- .channels_max = 2,
- },
- .ops = &hac_dai_ops,
-},
-#ifdef CONFIG_CPU_SUBTYPE_SH7760
-{
- .name = "hac-dai.1",
- .id = 1,
- .playback = {
- .rates = AC97_RATES,
- .formats = AC97_FMTS,
- .channels_min = 2,
- .channels_max = 2,
- },
- .capture = {
- .rates = AC97_RATES,
- .formats = AC97_FMTS,
- .channels_min = 2,
- .channels_max = 2,
- },
- .ops = &hac_dai_ops,
-
-},
-#endif
-};
-
-static const struct snd_soc_component_driver sh4_hac_component = {
- .name = "sh4-hac",
- .legacy_dai_naming = 1,
-};
-
-static int hac_soc_platform_probe(struct platform_device *pdev)
-{
- int ret;
-
- ret = snd_soc_set_ac97_ops(&hac_ac97_ops);
- if (ret != 0)
- return ret;
-
- return devm_snd_soc_register_component(&pdev->dev, &sh4_hac_component,
- sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
-}
-
-static void hac_soc_platform_remove(struct platform_device *pdev)
-{
- snd_soc_set_ac97_ops(NULL);
-}
-
-static struct platform_driver hac_pcm_driver = {
- .driver = {
- .name = "hac-pcm-audio",
- },
-
- .probe = hac_soc_platform_probe,
- .remove_new = hac_soc_platform_remove,
-};
-
-module_platform_driver(hac_pcm_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
-MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c
deleted file mode 100644
index 5a0bc6edac0a..000000000000
--- a/sound/soc/sh/migor.c
+++ /dev/null
@@ -1,205 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// ALSA SoC driver for Migo-R
-//
-// Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-
-#include <linux/clkdev.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/module.h>
-
-#include <asm/clock.h>
-
-#include <cpu/sh7722.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-
-#include "../codecs/wm8978.h"
-#include "siu.h"
-
-/* Default 8000Hz sampling frequency */
-static unsigned long codec_freq = 8000 * 512;
-
-static unsigned int use_count;
-
-/* External clock, sourced from the codec at the SIUMCKB pin */
-static unsigned long siumckb_recalc(struct clk *clk)
-{
- return codec_freq;
-}
-
-static struct sh_clk_ops siumckb_clk_ops = {
- .recalc = siumckb_recalc,
-};
-
-static struct clk siumckb_clk = {
- .ops = &siumckb_clk_ops,
- .rate = 0, /* initialised at run-time */
-};
-
-static struct clk_lookup *siumckb_lookup;
-
-static int migor_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
- int ret;
- unsigned int rate = params_rate(params);
-
- ret = snd_soc_dai_set_sysclk(codec_dai, WM8978_PLL, 13000000,
- SND_SOC_CLOCK_IN);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_clkdiv(codec_dai, WM8978_OPCLKRATE, rate * 512);
- if (ret < 0)
- return ret;
-
- codec_freq = rate * 512;
- /*
- * This propagates the parent frequency change to children and
- * recalculates the frequency table
- */
- clk_set_rate(&siumckb_clk, codec_freq);
- dev_dbg(codec_dai->dev, "%s: configure %luHz\n", __func__, codec_freq);
-
- ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_cpu(rtd, 0), SIU_CLKB_EXT,
- codec_freq / 2, SND_SOC_CLOCK_IN);
-
- if (!ret)
- use_count++;
-
- return ret;
-}
-
-static int migor_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
-
- if (use_count) {
- use_count--;
-
- if (!use_count)
- snd_soc_dai_set_sysclk(codec_dai, WM8978_PLL, 0,
- SND_SOC_CLOCK_IN);
- } else {
- dev_dbg(codec_dai->dev, "Unbalanced hw_free!\n");
- }
-
- return 0;
-}
-
-static const struct snd_soc_ops migor_dai_ops = {
- .hw_params = migor_hw_params,
- .hw_free = migor_hw_free,
-};
-
-static const struct snd_soc_dapm_widget migor_dapm_widgets[] = {
- SND_SOC_DAPM_HP("Headphone", NULL),
- SND_SOC_DAPM_MIC("Onboard Microphone", NULL),
- SND_SOC_DAPM_MIC("External Microphone", NULL),
-};
-
-static const struct snd_soc_dapm_route audio_map[] = {
- /* Headphone output connected to LHP/RHP, enable OUT4 for VMID */
- { "Headphone", NULL, "OUT4 VMID" },
- { "OUT4 VMID", NULL, "LHP" },
- { "OUT4 VMID", NULL, "RHP" },
-
- /* On-board microphone */
- { "RMICN", NULL, "Mic Bias" },
- { "RMICP", NULL, "Mic Bias" },
- { "Mic Bias", NULL, "Onboard Microphone" },
-
- /* External microphone */
- { "LMICN", NULL, "Mic Bias" },
- { "LMICP", NULL, "Mic Bias" },
- { "Mic Bias", NULL, "External Microphone" },
-};
-
-/* migor digital audio interface glue - connects codec <--> CPU */
-SND_SOC_DAILINK_DEFS(wm8978,
- DAILINK_COMP_ARRAY(COMP_CPU("siu-pcm-audio")),
- DAILINK_COMP_ARRAY(COMP_CODEC("wm8978.0-001a", "wm8978-hifi")),
- DAILINK_COMP_ARRAY(COMP_PLATFORM("siu-pcm-audio")));
-
-static struct snd_soc_dai_link migor_dai = {
- .name = "wm8978",
- .stream_name = "WM8978",
- .dai_fmt = SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_CBS_CFS,
- .ops = &migor_dai_ops,
- SND_SOC_DAILINK_REG(wm8978),
-};
-
-/* migor audio machine driver */
-static struct snd_soc_card snd_soc_migor = {
- .name = "Migo-R",
- .owner = THIS_MODULE,
- .dai_link = &migor_dai,
- .num_links = 1,
-
- .dapm_widgets = migor_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(migor_dapm_widgets),
- .dapm_routes = audio_map,
- .num_dapm_routes = ARRAY_SIZE(audio_map),
-};
-
-static struct platform_device *migor_snd_device;
-
-static int __init migor_init(void)
-{
- int ret;
-
- ret = clk_register(&siumckb_clk);
- if (ret < 0)
- return ret;
-
- siumckb_lookup = clkdev_create(&siumckb_clk, "siumckb_clk", NULL);
- if (!siumckb_lookup) {
- ret = -ENOMEM;
- goto eclkdevalloc;
- }
-
- /* Port number used on this machine: port B */
- migor_snd_device = platform_device_alloc("soc-audio", 1);
- if (!migor_snd_device) {
- ret = -ENOMEM;
- goto epdevalloc;
- }
-
- platform_set_drvdata(migor_snd_device, &snd_soc_migor);
-
- ret = platform_device_add(migor_snd_device);
- if (ret)
- goto epdevadd;
-
- return 0;
-
-epdevadd:
- platform_device_put(migor_snd_device);
-epdevalloc:
- clkdev_drop(siumckb_lookup);
-eclkdevalloc:
- clk_unregister(&siumckb_clk);
- return ret;
-}
-
-static void __exit migor_exit(void)
-{
- clkdev_drop(siumckb_lookup);
- clk_unregister(&siumckb_clk);
- platform_device_unregister(migor_snd_device);
-}
-
-module_init(migor_init);
-module_exit(migor_exit);
-
-MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
-MODULE_DESCRIPTION("ALSA SoC Migor");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile
deleted file mode 100644
index d07eccfa3ac2..000000000000
--- a/sound/soc/sh/rcar/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o ssiu.o src.o ctu.o mix.o dvc.o cmd.o debugfs.o
-obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
deleted file mode 100644
index afd69c6eb654..000000000000
--- a/sound/soc/sh/rcar/adg.c
+++ /dev/null
@@ -1,775 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Helper routines for R-Car sound ADG.
-//
-// Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-#include "rsnd.h"
-
-#define CLKA 0
-#define CLKB 1
-#define CLKC 2
-#define CLKI 3
-#define CLKINMAX 4
-
-#define CLKOUT 0
-#define CLKOUT1 1
-#define CLKOUT2 2
-#define CLKOUT3 3
-#define CLKOUTMAX 4
-
-#define BRRx_MASK(x) (0x3FF & x)
-
-static struct rsnd_mod_ops adg_ops = {
- .name = "adg",
-};
-
-#define ADG_HZ_441 0
-#define ADG_HZ_48 1
-#define ADG_HZ_SIZE 2
-
-struct rsnd_adg {
- struct clk *clkin[CLKINMAX];
- struct clk *clkout[CLKOUTMAX];
- struct clk *null_clk;
- struct clk_onecell_data onecell;
- struct rsnd_mod mod;
- int clkin_rate[CLKINMAX];
- int clkin_size;
- int clkout_size;
- u32 ckr;
- u32 brga;
- u32 brgb;
-
- int brg_rate[ADG_HZ_SIZE]; /* BRGA / BRGB */
-};
-
-#define for_each_rsnd_clkin(pos, adg, i) \
- for (i = 0; \
- (i < adg->clkin_size) && \
- ((pos) = adg->clkin[i]); \
- i++)
-#define for_each_rsnd_clkout(pos, adg, i) \
- for (i = 0; \
- (i < adg->clkout_size) && \
- ((pos) = adg->clkout[i]); \
- i++)
-#define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
-
-static const char * const clkin_name_gen4[] = {
- [CLKA] = "clkin",
-};
-
-static const char * const clkin_name_gen2[] = {
- [CLKA] = "clk_a",
- [CLKB] = "clk_b",
- [CLKC] = "clk_c",
- [CLKI] = "clk_i",
-};
-
-static const char * const clkout_name_gen2[] = {
- [CLKOUT] = "audio_clkout",
- [CLKOUT1] = "audio_clkout1",
- [CLKOUT2] = "audio_clkout2",
- [CLKOUT3] = "audio_clkout3",
-};
-
-static u32 rsnd_adg_calculate_brgx(unsigned long div)
-{
- int i;
-
- if (!div)
- return 0;
-
- for (i = 3; i >= 0; i--) {
- int ratio = 2 << (i * 2);
- if (0 == (div % ratio))
- return (u32)((i << 8) | ((div / ratio) - 1));
- }
-
- return ~0;
-}
-
-static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
-{
- struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- int id = rsnd_mod_id(ssi_mod);
- int ws = id;
-
- if (rsnd_ssi_is_pin_sharing(io)) {
- switch (id) {
- case 1:
- case 2:
- case 9:
- ws = 0;
- break;
- case 4:
- ws = 3;
- break;
- case 8:
- ws = 7;
- break;
- }
- } else {
- /*
- * SSI8 is not connected to ADG.
- * Thus SSI9 is using ws = 8
- */
- if (id == 9)
- ws = 8;
- }
-
- return (0x6 + ws) << 8;
-}
-
-static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- unsigned int target_rate,
- unsigned int *target_val,
- unsigned int *target_en)
-{
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- int sel;
- unsigned int val, en;
- unsigned int min, diff;
- unsigned int sel_rate[] = {
- adg->clkin_rate[CLKA], /* 0000: CLKA */
- adg->clkin_rate[CLKB], /* 0001: CLKB */
- adg->clkin_rate[CLKC], /* 0010: CLKC */
- adg->brg_rate[ADG_HZ_441], /* 0011: BRGA */
- adg->brg_rate[ADG_HZ_48], /* 0100: BRGB */
- };
-
- min = ~0;
- val = 0;
- en = 0;
- for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) {
- int idx = 0;
- int step = 2;
- int div;
-
- if (!sel_rate[sel])
- continue;
-
- for (div = 2; div <= 98304; div += step) {
- diff = abs(target_rate - sel_rate[sel] / div);
- if (min > diff) {
- val = (sel << 8) | idx;
- min = diff;
- en = 1 << (sel + 1); /* fixme */
- }
-
- /*
- * step of 0_0000 / 0_0001 / 0_1101
- * are out of order
- */
- if ((idx > 2) && (idx % 2))
- step *= 2;
- if (idx == 0x1c) {
- div += step;
- step *= 2;
- }
- idx++;
- }
- }
-
- if (min == ~0) {
- dev_err(dev, "no Input clock\n");
- return;
- }
-
- *target_val = val;
- if (target_en)
- *target_en = en;
-}
-
-static void rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- unsigned int in_rate,
- unsigned int out_rate,
- u32 *in, u32 *out, u32 *en)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- unsigned int target_rate;
- u32 *target_val;
- u32 _in;
- u32 _out;
- u32 _en;
-
- /* default = SSI WS */
- _in =
- _out = rsnd_adg_ssi_ws_timing_gen2(io);
-
- target_rate = 0;
- target_val = NULL;
- _en = 0;
- if (runtime->rate != in_rate) {
- target_rate = out_rate;
- target_val = &_out;
- } else if (runtime->rate != out_rate) {
- target_rate = in_rate;
- target_val = &_in;
- }
-
- if (target_rate)
- __rsnd_adg_get_timesel_ratio(priv, io,
- target_rate,
- target_val, &_en);
-
- if (in)
- *in = _in;
- if (out)
- *out = _out;
- if (en)
- *en = _en;
-}
-
-int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(cmd_mod);
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- int id = rsnd_mod_id(cmd_mod);
- int shift = (id % 2) ? 16 : 0;
- u32 mask, val;
-
- rsnd_adg_get_timesel_ratio(priv, io,
- rsnd_src_get_in_rate(priv, io),
- rsnd_src_get_out_rate(priv, io),
- NULL, &val, NULL);
-
- val = val << shift;
- mask = 0x0f1f << shift;
-
- rsnd_mod_bset(adg_mod, CMDOUT_TIMSEL, mask, val);
-
- return 0;
-}
-
-int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,
- struct rsnd_dai_stream *io,
- unsigned int in_rate,
- unsigned int out_rate)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(src_mod);
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- u32 in, out;
- u32 mask, en;
- int id = rsnd_mod_id(src_mod);
- int shift = (id % 2) ? 16 : 0;
-
- rsnd_mod_confirm_src(src_mod);
-
- rsnd_adg_get_timesel_ratio(priv, io,
- in_rate, out_rate,
- &in, &out, &en);
-
- in = in << shift;
- out = out << shift;
- mask = 0x0f1f << shift;
-
- rsnd_mod_bset(adg_mod, SRCIN_TIMSEL(id / 2), mask, in);
- rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL(id / 2), mask, out);
-
- if (en)
- rsnd_mod_bset(adg_mod, DIV_EN, en, en);
-
- return 0;
-}
-
-static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- struct device *dev = rsnd_priv_to_dev(priv);
- int id = rsnd_mod_id(ssi_mod);
- int shift = (id % 4) * 8;
- u32 mask = 0xFF << shift;
-
- rsnd_mod_confirm_ssi(ssi_mod);
-
- val = val << shift;
-
- /*
- * SSI 8 is not connected to ADG.
- * it works with SSI 7
- */
- if (id == 8)
- return;
-
- rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL(id / 4), mask, val);
-
- dev_dbg(dev, "AUDIO_CLK_SEL is 0x%x\n", val);
-}
-
-int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
-{
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct clk *clk;
- int i;
- int sel_table[] = {
- [CLKA] = 0x1,
- [CLKB] = 0x2,
- [CLKC] = 0x3,
- [CLKI] = 0x0,
- };
-
- /*
- * find suitable clock from
- * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
- */
- for_each_rsnd_clkin(clk, adg, i)
- if (rate == adg->clkin_rate[i])
- return sel_table[i];
-
- /*
- * find divided clock from BRGA/BRGB
- */
- if (rate == adg->brg_rate[ADG_HZ_441])
- return 0x10;
-
- if (rate == adg->brg_rate[ADG_HZ_48])
- return 0x20;
-
- return -EIO;
-}
-
-int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod)
-{
- rsnd_adg_set_ssi_clk(ssi_mod, 0);
-
- return 0;
-}
-
-int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- int data;
- u32 ckr = 0;
-
- data = rsnd_adg_clk_query(priv, rate);
- if (data < 0)
- return data;
-
- rsnd_adg_set_ssi_clk(ssi_mod, data);
-
- if (0 == (rate % 8000))
- ckr = 0x80000000; /* BRGB output = 48kHz */
-
- rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr);
-
- dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n",
- (ckr) ? 'B' : 'A',
- (ckr) ? adg->brg_rate[ADG_HZ_48] :
- adg->brg_rate[ADG_HZ_441]);
-
- return 0;
-}
-
-void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
-{
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- struct clk *clk;
- int i;
-
- if (enable) {
- rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr);
- rsnd_mod_write(adg_mod, BRRA, adg->brga);
- rsnd_mod_write(adg_mod, BRRB, adg->brgb);
- }
-
- for_each_rsnd_clkin(clk, adg, i) {
- if (enable) {
- clk_prepare_enable(clk);
-
- /*
- * We shouldn't use clk_get_rate() under
- * atomic context. Let's keep it when
- * rsnd_adg_clk_enable() was called
- */
- adg->clkin_rate[i] = clk_get_rate(clk);
- } else {
- clk_disable_unprepare(clk);
- }
- }
-}
-
-static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,
- const char * const name,
- const char *parent)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct clk *clk;
-
- clk = clk_register_fixed_rate(dev, name, parent, 0, 0);
- if (IS_ERR_OR_NULL(clk)) {
- dev_err(dev, "create null clk error\n");
- return ERR_CAST(clk);
- }
-
- return clk;
-}
-
-static struct clk *rsnd_adg_null_clk_get(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg = priv->adg;
-
- if (!adg->null_clk) {
- static const char * const name = "rsnd_adg_null";
-
- adg->null_clk = rsnd_adg_create_null_clk(priv, name, NULL);
- }
-
- return adg->null_clk;
-}
-
-static void rsnd_adg_null_clk_clean(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg = priv->adg;
-
- if (adg->null_clk)
- clk_unregister_fixed_rate(adg->null_clk);
-}
-
-static int rsnd_adg_get_clkin(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg = priv->adg;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct clk *clk;
- const char * const *clkin_name;
- int clkin_size;
- int i;
-
- clkin_name = clkin_name_gen2;
- clkin_size = ARRAY_SIZE(clkin_name_gen2);
- if (rsnd_is_gen4(priv)) {
- clkin_name = clkin_name_gen4;
- clkin_size = ARRAY_SIZE(clkin_name_gen4);
- }
-
- for (i = 0; i < clkin_size; i++) {
- clk = devm_clk_get(dev, clkin_name[i]);
-
- if (IS_ERR_OR_NULL(clk))
- clk = rsnd_adg_null_clk_get(priv);
- if (IS_ERR_OR_NULL(clk))
- goto err;
-
- adg->clkin[i] = clk;
- }
-
- adg->clkin_size = clkin_size;
-
- return 0;
-
-err:
- dev_err(dev, "adg clock IN get failed\n");
-
- rsnd_adg_null_clk_clean(priv);
-
- return -EIO;
-}
-
-static void rsnd_adg_unregister_clkout(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg = priv->adg;
- struct clk *clk;
- int i;
-
- for_each_rsnd_clkout(clk, adg, i)
- clk_unregister_fixed_rate(clk);
-}
-
-static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg = priv->adg;
- struct clk *clk;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np = dev->of_node;
- struct property *prop;
- u32 ckr, brgx, brga, brgb;
- u32 req_rate[ADG_HZ_SIZE] = {};
- uint32_t count = 0;
- unsigned long req_Hz[ADG_HZ_SIZE];
- int clkout_size;
- int i, req_size;
- int approximate = 0;
- const char *parent_clk_name = NULL;
- const char * const *clkout_name;
- int brg_table[] = {
- [CLKA] = 0x0,
- [CLKB] = 0x1,
- [CLKC] = 0x4,
- [CLKI] = 0x2,
- };
-
- ckr = 0;
- brga = 0xff; /* default */
- brgb = 0xff; /* default */
-
- /*
- * ADG supports BRRA/BRRB output only
- * this means all clkout0/1/2/3 will be same rate
- */
- prop = of_find_property(np, "clock-frequency", NULL);
- if (!prop)
- goto rsnd_adg_get_clkout_end;
-
- req_size = prop->length / sizeof(u32);
- if (req_size > ADG_HZ_SIZE) {
- dev_err(dev, "too many clock-frequency\n");
- return -EINVAL;
- }
-
- of_property_read_u32_array(np, "clock-frequency", req_rate, req_size);
- req_Hz[ADG_HZ_48] = 0;
- req_Hz[ADG_HZ_441] = 0;
- for (i = 0; i < req_size; i++) {
- if (0 == (req_rate[i] % 44100))
- req_Hz[ADG_HZ_441] = req_rate[i];
- if (0 == (req_rate[i] % 48000))
- req_Hz[ADG_HZ_48] = req_rate[i];
- }
-
- /*
- * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC
- * have 44.1kHz or 48kHz base clocks for now.
- *
- * SSI itself can divide parent clock by 1/1 - 1/16
- * see
- * rsnd_adg_ssi_clk_try_start()
- * rsnd_ssi_master_clk_start()
- */
-
- /*
- * [APPROXIMATE]
- *
- * clk_i (internal clock) can't create accurate rate, it will be approximate rate.
- *
- * <Note>
- *
- * clk_i needs x2 of required maximum rate.
- * see
- * - Minimum division of BRRA/BRRB
- * - rsnd_ssi_clk_query()
- *
- * Sample Settings for TDM 8ch, 32bit width
- *
- * 8(ch) x 32(bit) x 44100(Hz) x 2<Note> = 22579200
- * 8(ch) x 32(bit) x 48000(Hz) x 2<Note> = 24576000
- *
- * clock-frequency = <22579200 24576000>;
- */
- for_each_rsnd_clkin(clk, adg, i) {
- u32 rate, div;
-
- rate = clk_get_rate(clk);
-
- if (0 == rate) /* not used */
- continue;
-
- /* BRGA */
-
- if (i == CLKI)
- /* see [APPROXIMATE] */
- rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_441]) * req_Hz[ADG_HZ_441];
- if (!adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441] && (0 == rate % 44100)) {
- div = rate / req_Hz[ADG_HZ_441];
- brgx = rsnd_adg_calculate_brgx(div);
- if (BRRx_MASK(brgx) == brgx) {
- brga = brgx;
- adg->brg_rate[ADG_HZ_441] = rate / div;
- ckr |= brg_table[i] << 20;
- if (req_Hz[ADG_HZ_441])
- parent_clk_name = __clk_get_name(clk);
- if (i == CLKI)
- approximate = 1;
- }
- }
-
- /* BRGB */
-
- if (i == CLKI)
- /* see [APPROXIMATE] */
- rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_48]) * req_Hz[ADG_HZ_48];
- if (!adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48] && (0 == rate % 48000)) {
- div = rate / req_Hz[ADG_HZ_48];
- brgx = rsnd_adg_calculate_brgx(div);
- if (BRRx_MASK(brgx) == brgx) {
- brgb = brgx;
- adg->brg_rate[ADG_HZ_48] = rate / div;
- ckr |= brg_table[i] << 16;
- if (req_Hz[ADG_HZ_48])
- parent_clk_name = __clk_get_name(clk);
- if (i == CLKI)
- approximate = 1;
- }
- }
- }
-
- if (!(adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48]) &&
- !(adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441]))
- goto rsnd_adg_get_clkout_end;
-
- if (approximate)
- dev_info(dev, "It uses CLK_I as approximate rate");
-
- clkout_name = clkout_name_gen2;
- clkout_size = ARRAY_SIZE(clkout_name_gen2);
- if (rsnd_is_gen4(priv))
- clkout_size = 1; /* reuse clkout_name_gen2[] */
-
- /*
- * ADG supports BRRA/BRRB output only.
- * this means all clkout0/1/2/3 will be * same rate
- */
-
- of_property_read_u32(np, "#clock-cells", &count);
- /*
- * for clkout
- */
- if (!count) {
- clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT],
- parent_clk_name, 0, req_rate[0]);
- if (IS_ERR_OR_NULL(clk))
- goto err;
-
- adg->clkout[CLKOUT] = clk;
- adg->clkout_size = 1;
- of_clk_add_provider(np, of_clk_src_simple_get, clk);
- }
- /*
- * for clkout0/1/2/3
- */
- else {
- for (i = 0; i < clkout_size; i++) {
- clk = clk_register_fixed_rate(dev, clkout_name[i],
- parent_clk_name, 0,
- req_rate[0]);
- if (IS_ERR_OR_NULL(clk))
- goto err;
-
- adg->clkout[i] = clk;
- }
- adg->onecell.clks = adg->clkout;
- adg->onecell.clk_num = clkout_size;
- adg->clkout_size = clkout_size;
- of_clk_add_provider(np, of_clk_src_onecell_get,
- &adg->onecell);
- }
-
-rsnd_adg_get_clkout_end:
- adg->ckr = ckr;
- adg->brga = brga;
- adg->brgb = brgb;
-
- return 0;
-
-err:
- dev_err(dev, "adg clock OUT get failed\n");
-
- rsnd_adg_unregister_clkout(priv);
-
- return -EIO;
-}
-
-#if defined(DEBUG) || defined(CONFIG_DEBUG_FS)
-__printf(3, 4)
-static void dbg_msg(struct device *dev, struct seq_file *m,
- const char *fmt, ...)
-{
- char msg[128];
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(msg, sizeof(msg), fmt, args);
- va_end(args);
-
- if (m)
- seq_puts(m, msg);
- else
- dev_dbg(dev, "%s", msg);
-}
-
-void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m)
-{
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct clk *clk;
- int i;
-
- for_each_rsnd_clkin(clk, adg, i)
- dbg_msg(dev, m, "%-18s : %pa : %ld\n",
- __clk_get_name(clk), clk, clk_get_rate(clk));
-
- dbg_msg(dev, m, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n",
- adg->ckr, adg->brga, adg->brgb);
- dbg_msg(dev, m, "BRGA (for 44100 base) = %d\n", adg->brg_rate[ADG_HZ_441]);
- dbg_msg(dev, m, "BRGB (for 48000 base) = %d\n", adg->brg_rate[ADG_HZ_48]);
-
- /*
- * Actual CLKOUT will be exchanged in rsnd_adg_ssi_clk_try_start()
- * by BRGCKR::BRGCKR_31
- */
- for_each_rsnd_clkout(clk, adg, i)
- dbg_msg(dev, m, "%-18s : %pa : %ld\n",
- __clk_get_name(clk), clk, clk_get_rate(clk));
-}
-#else
-#define rsnd_adg_clk_dbg_info(priv, m)
-#endif
-
-int rsnd_adg_probe(struct rsnd_priv *priv)
-{
- struct rsnd_adg *adg;
- struct device *dev = rsnd_priv_to_dev(priv);
- int ret;
-
- adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
- if (!adg)
- return -ENOMEM;
-
- ret = rsnd_mod_init(priv, &adg->mod, &adg_ops,
- NULL, 0, 0);
- if (ret)
- return ret;
-
- priv->adg = adg;
-
- ret = rsnd_adg_get_clkin(priv);
- if (ret)
- return ret;
-
- ret = rsnd_adg_get_clkout(priv);
- if (ret)
- return ret;
-
- rsnd_adg_clk_enable(priv);
- rsnd_adg_clk_dbg_info(priv, NULL);
-
- return 0;
-}
-
-void rsnd_adg_remove(struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np = dev->of_node;
-
- rsnd_adg_unregister_clkout(priv);
-
- of_clk_del_provider(np);
-
- rsnd_adg_clk_disable(priv);
-
- /* It should be called after rsnd_adg_clk_disable() */
- rsnd_adg_null_clk_clean(priv);
-}
diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c
deleted file mode 100644
index 329e6ab1b222..000000000000
--- a/sound/soc/sh/rcar/cmd.c
+++ /dev/null
@@ -1,195 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car CMD support
-//
-// Copyright (C) 2015 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-#include "rsnd.h"
-
-struct rsnd_cmd {
- struct rsnd_mod mod;
-};
-
-#define CMD_NAME "cmd"
-
-#define rsnd_cmd_nr(priv) ((priv)->cmd_nr)
-#define for_each_rsnd_cmd(pos, priv, i) \
- for ((i) = 0; \
- ((i) < rsnd_cmd_nr(priv)) && \
- ((pos) = (struct rsnd_cmd *)(priv)->cmd + i); \
- i++)
-
-static int rsnd_cmd_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
- struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- u32 data;
- static const u32 path[] = {
- [1] = 1 << 0,
- [5] = 1 << 8,
- [6] = 1 << 12,
- [9] = 1 << 15,
- };
-
- if (!mix && !dvc)
- return 0;
-
- if (ARRAY_SIZE(path) < rsnd_mod_id(mod) + 1)
- return -ENXIO;
-
- if (mix) {
- struct rsnd_dai *rdai;
- int i;
-
- /*
- * it is assuming that integrater is well understanding about
- * data path. Here doesn't check impossible connection,
- * like src2 + src5
- */
- data = 0;
- for_each_rsnd_dai(rdai, priv, i) {
- struct rsnd_dai_stream *tio = &rdai->playback;
- struct rsnd_mod *src = rsnd_io_to_mod_src(tio);
-
- if (mix == rsnd_io_to_mod_mix(tio))
- data |= path[rsnd_mod_id(src)];
-
- tio = &rdai->capture;
- src = rsnd_io_to_mod_src(tio);
- if (mix == rsnd_io_to_mod_mix(tio))
- data |= path[rsnd_mod_id(src)];
- }
-
- } else {
- struct rsnd_mod *src = rsnd_io_to_mod_src(io);
-
- static const u8 cmd_case[] = {
- [0] = 0x3,
- [1] = 0x3,
- [2] = 0x4,
- [3] = 0x1,
- [4] = 0x2,
- [5] = 0x4,
- [6] = 0x1,
- [9] = 0x2,
- };
-
- if (unlikely(!src))
- return -EIO;
-
- data = path[rsnd_mod_id(src)] |
- cmd_case[rsnd_mod_id(src)] << 16;
- }
-
- dev_dbg(dev, "ctu/mix path = 0x%08x\n", data);
-
- rsnd_mod_write(mod, CMD_ROUTE_SLCT, data);
- rsnd_mod_write(mod, CMD_BUSIF_MODE, rsnd_get_busif_shift(io, mod) | 1);
- rsnd_mod_write(mod, CMD_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
-
- rsnd_adg_set_cmd_timsel_gen2(mod, io);
-
- return 0;
-}
-
-static int rsnd_cmd_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_mod_write(mod, CMD_CTRL, 0x10);
-
- return 0;
-}
-
-static int rsnd_cmd_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_mod_write(mod, CMD_CTRL, 0);
-
- return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_cmd_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0x180 + rsnd_mod_id_raw(mod) * 0x20, 0x30);
-}
-#define DEBUG_INFO .debug_info = rsnd_cmd_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_cmd_ops = {
- .name = CMD_NAME,
- .init = rsnd_cmd_init,
- .start = rsnd_cmd_start,
- .stop = rsnd_cmd_stop,
- .get_status = rsnd_mod_get_status,
- DEBUG_INFO
-};
-
-static struct rsnd_mod *rsnd_cmd_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_cmd_nr(priv)))
- id = 0;
-
- return rsnd_mod_get((struct rsnd_cmd *)(priv->cmd) + id);
-}
-int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct rsnd_mod *mod = rsnd_cmd_mod_get(priv, id);
-
- return rsnd_dai_connect(mod, io, mod->type);
-}
-
-int rsnd_cmd_probe(struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_cmd *cmd;
- int i, nr;
-
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
- /* same number as DVC */
- nr = priv->dvc_nr;
- if (!nr)
- return 0;
-
- cmd = devm_kcalloc(dev, nr, sizeof(*cmd), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
-
- priv->cmd_nr = nr;
- priv->cmd = cmd;
-
- for_each_rsnd_cmd(cmd, priv, i) {
- int ret = rsnd_mod_init(priv, rsnd_mod_get(cmd),
- &rsnd_cmd_ops, NULL,
- RSND_MOD_CMD, i);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-void rsnd_cmd_remove(struct rsnd_priv *priv)
-{
- struct rsnd_cmd *cmd;
- int i;
-
- for_each_rsnd_cmd(cmd, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(cmd));
- }
-}
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
deleted file mode 100644
index 0b1aa23c1189..000000000000
--- a/sound/soc/sh/rcar/core.c
+++ /dev/null
@@ -1,2114 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car SRU/SCU/SSIU/SSI support
-//
-// Copyright (C) 2013 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-//
-// Based on fsi.c
-// Kuninori Morimoto <morimoto.kuninori@renesas.com>
-
-/*
- * Renesas R-Car sound device structure
- *
- * Gen1
- *
- * SRU : Sound Routing Unit
- * - SRC : Sampling Rate Converter
- * - CMD
- * - CTU : Channel Count Conversion Unit
- * - MIX : Mixer
- * - DVC : Digital Volume and Mute Function
- * - SSI : Serial Sound Interface
- *
- * Gen2
- *
- * SCU : Sampling Rate Converter Unit
- * - SRC : Sampling Rate Converter
- * - CMD
- * - CTU : Channel Count Conversion Unit
- * - MIX : Mixer
- * - DVC : Digital Volume and Mute Function
- * SSIU : Serial Sound Interface Unit
- * - SSI : Serial Sound Interface
- */
-
-/*
- * driver data Image
- *
- * rsnd_priv
- * |
- * | ** this depends on Gen1/Gen2
- * |
- * +- gen
- * |
- * | ** these depend on data path
- * | ** gen and platform data control it
- * |
- * +- rdai[0]
- * | | sru ssiu ssi
- * | +- playback -> [mod] -> [mod] -> [mod] -> ...
- * | |
- * | | sru ssiu ssi
- * | +- capture -> [mod] -> [mod] -> [mod] -> ...
- * |
- * +- rdai[1]
- * | | sru ssiu ssi
- * | +- playback -> [mod] -> [mod] -> [mod] -> ...
- * | |
- * | | sru ssiu ssi
- * | +- capture -> [mod] -> [mod] -> [mod] -> ...
- * ...
- * |
- * | ** these control ssi
- * |
- * +- ssi
- * | |
- * | +- ssi[0]
- * | +- ssi[1]
- * | +- ssi[2]
- * | ...
- * |
- * | ** these control src
- * |
- * +- src
- * |
- * +- src[0]
- * +- src[1]
- * +- src[2]
- * ...
- *
- *
- * for_each_rsnd_dai(xx, priv, xx)
- * rdai[0] => rdai[1] => rdai[2] => ...
- *
- * for_each_rsnd_mod(xx, rdai, xx)
- * [mod] => [mod] => [mod] => ...
- *
- * rsnd_dai_call(xxx, fn )
- * [mod]->fn() -> [mod]->fn() -> [mod]->fn()...
- *
- */
-
-#include <linux/pm_runtime.h>
-#include <linux/of_graph.h>
-#include "rsnd.h"
-
-#define RSND_RATES SNDRV_PCM_RATE_8000_192000
-#define RSND_FMTS (SNDRV_PCM_FMTBIT_S8 |\
- SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S24_LE)
-
-static const struct of_device_id rsnd_of_match[] = {
- { .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 },
- { .compatible = "renesas,rcar_sound-gen2", .data = (void *)RSND_GEN2 },
- { .compatible = "renesas,rcar_sound-gen3", .data = (void *)RSND_GEN3 },
- { .compatible = "renesas,rcar_sound-gen4", .data = (void *)RSND_GEN4 },
- /* Special Handling */
- { .compatible = "renesas,rcar_sound-r8a77990", .data = (void *)(RSND_GEN3 | RSND_SOC_E) },
- {},
-};
-MODULE_DEVICE_TABLE(of, rsnd_of_match);
-
-/*
- * rsnd_mod functions
- */
-void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type)
-{
- if (mod->type != type) {
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_warn(dev, "%s is not your expected module\n",
- rsnd_mod_name(mod));
- }
-}
-
-struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- if (!mod || !mod->ops || !mod->ops->dma_req)
- return NULL;
-
- return mod->ops->dma_req(io, mod);
-}
-
-#define MOD_NAME_NUM 5
-#define MOD_NAME_SIZE 16
-char *rsnd_mod_name(struct rsnd_mod *mod)
-{
- static char names[MOD_NAME_NUM][MOD_NAME_SIZE];
- static int num;
- char *name = names[num];
-
- num++;
- if (num >= MOD_NAME_NUM)
- num = 0;
-
- /*
- * Let's use same char to avoid pointlessness memory
- * Thus, rsnd_mod_name() should be used immediately
- * Don't keep pointer
- */
- if ((mod)->ops->id_sub) {
- snprintf(name, MOD_NAME_SIZE, "%s[%d%d]",
- mod->ops->name,
- rsnd_mod_id(mod),
- rsnd_mod_id_sub(mod));
- } else {
- snprintf(name, MOD_NAME_SIZE, "%s[%d]",
- mod->ops->name,
- rsnd_mod_id(mod));
- }
-
- return name;
-}
-
-u32 *rsnd_mod_get_status(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type)
-{
- return &mod->status;
-}
-
-int rsnd_mod_id_raw(struct rsnd_mod *mod)
-{
- return mod->id;
-}
-
-int rsnd_mod_id(struct rsnd_mod *mod)
-{
- if ((mod)->ops->id)
- return (mod)->ops->id(mod);
-
- return rsnd_mod_id_raw(mod);
-}
-
-int rsnd_mod_id_sub(struct rsnd_mod *mod)
-{
- if ((mod)->ops->id_sub)
- return (mod)->ops->id_sub(mod);
-
- return 0;
-}
-
-int rsnd_mod_init(struct rsnd_priv *priv,
- struct rsnd_mod *mod,
- struct rsnd_mod_ops *ops,
- struct clk *clk,
- enum rsnd_mod_type type,
- int id)
-{
- int ret = clk_prepare(clk);
-
- if (ret)
- return ret;
-
- mod->id = id;
- mod->ops = ops;
- mod->type = type;
- mod->clk = clk;
- mod->priv = priv;
-
- return 0;
-}
-
-void rsnd_mod_quit(struct rsnd_mod *mod)
-{
- clk_unprepare(mod->clk);
- mod->clk = NULL;
-}
-
-void rsnd_mod_interrupt(struct rsnd_mod *mod,
- void (*callback)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io))
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dai *rdai;
- int i;
-
- for_each_rsnd_dai(rdai, priv, i) {
- struct rsnd_dai_stream *io = &rdai->playback;
-
- if (mod == io->mod[mod->type])
- callback(mod, io);
-
- io = &rdai->capture;
- if (mod == io->mod[mod->type])
- callback(mod, io);
- }
-}
-
-int rsnd_io_is_working(struct rsnd_dai_stream *io)
-{
- /* see rsnd_dai_stream_init/quit() */
- if (io->substream)
- return snd_pcm_running(io->substream);
-
- return 0;
-}
-
-int rsnd_runtime_channel_original_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
-
- /*
- * params will be added when refine
- * see
- * __rsnd_soc_hw_rule_rate()
- * __rsnd_soc_hw_rule_channels()
- */
- if (params)
- return params_channels(params);
- else if (runtime)
- return runtime->channels;
- return 0;
-}
-
-int rsnd_runtime_channel_after_ctu_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params)
-{
- int chan = rsnd_runtime_channel_original_with_params(io, params);
- struct rsnd_mod *ctu_mod = rsnd_io_to_mod_ctu(io);
-
- if (ctu_mod) {
- u32 converted_chan = rsnd_io_converted_chan(io);
-
- /*
- * !! Note !!
- *
- * converted_chan will be used for CTU,
- * or TDM Split mode.
- * User shouldn't use CTU with TDM Split mode.
- */
- if (rsnd_runtime_is_tdm_split(io)) {
- struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io));
-
- dev_err(dev, "CTU and TDM Split should be used\n");
- }
-
- if (converted_chan)
- return converted_chan;
- }
-
- return chan;
-}
-
-int rsnd_channel_normalization(int chan)
-{
- if (WARN_ON((chan > 8) || (chan < 0)))
- return 0;
-
- /* TDM Extend Mode needs 8ch */
- if (chan == 6)
- chan = 8;
-
- return chan;
-}
-
-int rsnd_runtime_channel_for_ssi_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- int chan = rsnd_io_is_play(io) ?
- rsnd_runtime_channel_after_ctu_with_params(io, params) :
- rsnd_runtime_channel_original_with_params(io, params);
-
- /* Use Multi SSI */
- if (rsnd_runtime_is_multi_ssi(io))
- chan /= rsnd_rdai_ssi_lane_get(rdai);
-
- return rsnd_channel_normalization(chan);
-}
-
-int rsnd_runtime_is_multi_ssi(struct rsnd_dai_stream *io)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- int lane = rsnd_rdai_ssi_lane_get(rdai);
- int chan = rsnd_io_is_play(io) ?
- rsnd_runtime_channel_after_ctu(io) :
- rsnd_runtime_channel_original(io);
-
- return (chan > 2) && (lane > 1);
-}
-
-int rsnd_runtime_is_tdm(struct rsnd_dai_stream *io)
-{
- return rsnd_runtime_channel_for_ssi(io) >= 6;
-}
-
-int rsnd_runtime_is_tdm_split(struct rsnd_dai_stream *io)
-{
- return !!rsnd_flags_has(io, RSND_STREAM_TDM_SPLIT);
-}
-
-/*
- * ADINR function
- */
-u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- switch (snd_pcm_format_width(runtime->format)) {
- case 8:
- return 16 << 16;
- case 16:
- return 8 << 16;
- case 24:
- return 0 << 16;
- }
-
- dev_warn(dev, "not supported sample bits\n");
-
- return 0;
-}
-
-/*
- * DALIGN function
- */
-u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
-{
- static const u32 dalign_values[8] = {
- 0x76543210, 0x00000032, 0x00007654, 0x00000076,
- 0xfedcba98, 0x000000ba, 0x0000fedc, 0x000000fe,
- };
- int id = 0;
- struct rsnd_mod *ssiu = rsnd_io_to_mod_ssiu(io);
- struct rsnd_mod *target;
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- u32 dalign;
-
- /*
- * *Hardware* L/R and *Software* L/R are inverted for 16bit data.
- * 31..16 15...0
- * HW: [L ch] [R ch]
- * SW: [R ch] [L ch]
- * We need to care about inversion timing to control
- * Playback/Capture correctly.
- * The point is [DVC] needs *Hardware* L/R, [MEM] needs *Software* L/R
- *
- * sL/R : software L/R
- * hL/R : hardware L/R
- * (*) : conversion timing
- *
- * Playback
- * sL/R (*) hL/R hL/R hL/R hL/R hL/R
- * [MEM] -> [SRC] -> [DVC] -> [CMD] -> [SSIU] -> [SSI] -> codec
- *
- * Capture
- * hL/R hL/R hL/R hL/R hL/R (*) sL/R
- * codec -> [SSI] -> [SSIU] -> [SRC] -> [DVC] -> [CMD] -> [MEM]
- */
- if (rsnd_io_is_play(io)) {
- struct rsnd_mod *src = rsnd_io_to_mod_src(io);
-
- target = src ? src : ssiu;
- } else {
- struct rsnd_mod *cmd = rsnd_io_to_mod_cmd(io);
-
- target = cmd ? cmd : ssiu;
- }
-
- if (mod == ssiu)
- id = rsnd_mod_id_sub(mod);
-
- dalign = dalign_values[id];
-
- if (mod == target && snd_pcm_format_width(runtime->format) == 16) {
- /* Target mod needs inverted DALIGN when 16bit */
- dalign = (dalign & 0xf0f0f0f0) >> 4 |
- (dalign & 0x0f0f0f0f) << 4;
- }
-
- return dalign;
-}
-
-u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod)
-{
- static const enum rsnd_mod_type playback_mods[] = {
- RSND_MOD_SRC,
- RSND_MOD_CMD,
- RSND_MOD_SSIU,
- };
- static const enum rsnd_mod_type capture_mods[] = {
- RSND_MOD_CMD,
- RSND_MOD_SRC,
- RSND_MOD_SSIU,
- };
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_mod *tmod = NULL;
- const enum rsnd_mod_type *mods =
- rsnd_io_is_play(io) ?
- playback_mods : capture_mods;
- int i;
-
- /*
- * This is needed for 24bit data
- * We need to shift 8bit
- *
- * Linux 24bit data is located as 0x00******
- * HW 24bit data is located as 0x******00
- *
- */
- if (snd_pcm_format_width(runtime->format) != 24)
- return 0;
-
- for (i = 0; i < ARRAY_SIZE(playback_mods); i++) {
- tmod = rsnd_io_to_mod(io, mods[i]);
- if (tmod)
- break;
- }
-
- if (tmod != mod)
- return 0;
-
- if (rsnd_io_is_play(io))
- return (0 << 20) | /* shift to Left */
- (8 << 16); /* 8bit */
- else
- return (1 << 20) | /* shift to Right */
- (8 << 16); /* 8bit */
-}
-
-/*
- * rsnd_dai functions
- */
-struct rsnd_mod *rsnd_mod_next(int *iterator,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type *array,
- int array_size)
-{
- int max = array ? array_size : RSND_MOD_MAX;
-
- for (; *iterator < max; (*iterator)++) {
- enum rsnd_mod_type type = (array) ? array[*iterator] : *iterator;
- struct rsnd_mod *mod = rsnd_io_to_mod(io, type);
-
- if (mod)
- return mod;
- }
-
- return NULL;
-}
-
-static enum rsnd_mod_type rsnd_mod_sequence[][RSND_MOD_MAX] = {
- {
- /* CAPTURE */
- RSND_MOD_AUDMAPP,
- RSND_MOD_AUDMA,
- RSND_MOD_DVC,
- RSND_MOD_MIX,
- RSND_MOD_CTU,
- RSND_MOD_CMD,
- RSND_MOD_SRC,
- RSND_MOD_SSIU,
- RSND_MOD_SSIM3,
- RSND_MOD_SSIM2,
- RSND_MOD_SSIM1,
- RSND_MOD_SSIP,
- RSND_MOD_SSI,
- }, {
- /* PLAYBACK */
- RSND_MOD_AUDMAPP,
- RSND_MOD_AUDMA,
- RSND_MOD_SSIM3,
- RSND_MOD_SSIM2,
- RSND_MOD_SSIM1,
- RSND_MOD_SSIP,
- RSND_MOD_SSI,
- RSND_MOD_SSIU,
- RSND_MOD_DVC,
- RSND_MOD_MIX,
- RSND_MOD_CTU,
- RSND_MOD_CMD,
- RSND_MOD_SRC,
- },
-};
-
-static int rsnd_status_update(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod, enum rsnd_mod_type type,
- int shift, int add, int timing)
-{
- u32 *status = mod->ops->get_status(mod, io, type);
- u32 mask = 0xF << shift;
- u8 val = (*status >> shift) & 0xF;
- u8 next_val = (val + add) & 0xF;
- int func_call = (val == timing);
-
- /* no status update */
- if (add == 0 || shift == 28)
- return 1;
-
- if (next_val == 0xF) /* underflow case */
- func_call = -1;
- else
- *status = (*status & ~mask) + (next_val << shift);
-
- return func_call;
-}
-
-#define rsnd_dai_call(fn, io, param...) \
-({ \
- struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io)); \
- struct rsnd_mod *mod; \
- int is_play = rsnd_io_is_play(io); \
- int ret = 0, i; \
- enum rsnd_mod_type *types = rsnd_mod_sequence[is_play]; \
- for_each_rsnd_mod_arrays(i, mod, io, types, RSND_MOD_MAX) { \
- int tmp = 0; \
- int func_call = rsnd_status_update(io, mod, types[i], \
- __rsnd_mod_shift_##fn, \
- __rsnd_mod_add_##fn, \
- __rsnd_mod_call_##fn); \
- if (func_call > 0 && (mod)->ops->fn) \
- tmp = (mod)->ops->fn(mod, io, param); \
- if (unlikely(func_call < 0) || \
- unlikely(tmp && (tmp != -EPROBE_DEFER))) \
- dev_err(dev, "%s : %s error (%d, %d)\n", \
- rsnd_mod_name(mod), #fn, tmp, func_call);\
- ret |= tmp; \
- } \
- ret; \
-})
-
-int rsnd_dai_connect(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type)
-{
- struct rsnd_priv *priv;
- struct device *dev;
-
- if (!mod)
- return -EIO;
-
- if (io->mod[type] == mod)
- return 0;
-
- if (io->mod[type])
- return -EINVAL;
-
- priv = rsnd_mod_to_priv(mod);
- dev = rsnd_priv_to_dev(priv);
-
- io->mod[type] = mod;
-
- dev_dbg(dev, "%s is connected to io (%s)\n",
- rsnd_mod_name(mod),
- rsnd_io_is_play(io) ? "Playback" : "Capture");
-
- return 0;
-}
-
-static void rsnd_dai_disconnect(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type)
-{
- io->mod[type] = NULL;
-}
-
-int rsnd_rdai_channels_ctrl(struct rsnd_dai *rdai,
- int max_channels)
-{
- if (max_channels > 0)
- rdai->max_channels = max_channels;
-
- return rdai->max_channels;
-}
-
-int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai,
- int ssi_lane)
-{
- if (ssi_lane > 0)
- rdai->ssi_lane = ssi_lane;
-
- return rdai->ssi_lane;
-}
-
-int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width)
-{
- if (width > 0)
- rdai->chan_width = width;
-
- return rdai->chan_width;
-}
-
-struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id)
-{
- if ((id < 0) || (id >= rsnd_rdai_nr(priv)))
- return NULL;
-
- return priv->rdai + id;
-}
-
-static struct snd_soc_dai_driver
-*rsnd_daidrv_get(struct rsnd_priv *priv, int id)
-{
- if ((id < 0) || (id >= rsnd_rdai_nr(priv)))
- return NULL;
-
- return priv->daidrv + id;
-}
-
-#define rsnd_dai_to_priv(dai) snd_soc_dai_get_drvdata(dai)
-static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai)
-{
- struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
-
- return rsnd_rdai_get(priv, dai->id);
-}
-
-/*
- * rsnd_soc_dai functions
- */
-void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io)
-{
- struct snd_pcm_substream *substream = io->substream;
-
- /*
- * this function should be called...
- *
- * - if rsnd_dai_pointer_update() returns true
- * - without spin lock
- */
-
- snd_pcm_period_elapsed(substream);
-}
-
-static void rsnd_dai_stream_init(struct rsnd_dai_stream *io,
- struct snd_pcm_substream *substream)
-{
- io->substream = substream;
-}
-
-static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io)
-{
- io->substream = NULL;
-}
-
-static
-struct snd_soc_dai *rsnd_substream_to_dai(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
-
- return snd_soc_rtd_to_cpu(rtd, 0);
-}
-
-static
-struct rsnd_dai_stream *rsnd_rdai_to_io(struct rsnd_dai *rdai,
- struct snd_pcm_substream *substream)
-{
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- return &rdai->playback;
- else
- return &rdai->capture;
-}
-
-static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- ret = rsnd_dai_call(init, io, priv);
- if (ret < 0)
- goto dai_trigger_end;
-
- ret = rsnd_dai_call(start, io, priv);
- if (ret < 0)
- goto dai_trigger_end;
-
- ret = rsnd_dai_call(irq, io, priv, 1);
- if (ret < 0)
- goto dai_trigger_end;
-
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- ret = rsnd_dai_call(irq, io, priv, 0);
-
- ret |= rsnd_dai_call(stop, io, priv);
-
- ret |= rsnd_dai_call(quit, io, priv);
-
- break;
- default:
- ret = -EINVAL;
- }
-
-dai_trigger_end:
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return ret;
-}
-
-static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
-
- /* set clock master for audio interface */
- switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
- case SND_SOC_DAIFMT_BC_FC:
- rdai->clk_master = 0;
- break;
- case SND_SOC_DAIFMT_BP_FP:
- rdai->clk_master = 1; /* cpu is master */
- break;
- default:
- return -EINVAL;
- }
-
- /* set format */
- rdai->bit_clk_inv = 0;
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- rdai->sys_delay = 0;
- rdai->data_alignment = 0;
- rdai->frm_clk_inv = 0;
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- case SND_SOC_DAIFMT_DSP_B:
- rdai->sys_delay = 1;
- rdai->data_alignment = 0;
- rdai->frm_clk_inv = 1;
- break;
- case SND_SOC_DAIFMT_RIGHT_J:
- rdai->sys_delay = 1;
- rdai->data_alignment = 1;
- rdai->frm_clk_inv = 1;
- break;
- case SND_SOC_DAIFMT_DSP_A:
- rdai->sys_delay = 0;
- rdai->data_alignment = 0;
- rdai->frm_clk_inv = 1;
- break;
- }
-
- /* set clock inversion */
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_IF:
- rdai->frm_clk_inv = !rdai->frm_clk_inv;
- break;
- case SND_SOC_DAIFMT_IB_NF:
- rdai->bit_clk_inv = !rdai->bit_clk_inv;
- break;
- case SND_SOC_DAIFMT_IB_IF:
- rdai->bit_clk_inv = !rdai->bit_clk_inv;
- rdai->frm_clk_inv = !rdai->frm_clk_inv;
- break;
- case SND_SOC_DAIFMT_NB_NF:
- default:
- break;
- }
-
- return 0;
-}
-
-static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
- u32 tx_mask, u32 rx_mask,
- int slots, int slot_width)
-{
- struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- switch (slot_width) {
- case 16:
- case 24:
- case 32:
- break;
- default:
- /* use default */
- /*
- * Indicate warning if DT has "dai-tdm-slot-width"
- * but the value was not expected.
- */
- if (slot_width)
- dev_warn(dev, "unsupported TDM slot width (%d), force to use default 32\n",
- slot_width);
- slot_width = 32;
- }
-
- switch (slots) {
- case 2:
- /* TDM Split Mode */
- case 6:
- case 8:
- /* TDM Extend Mode */
- rsnd_rdai_channels_set(rdai, slots);
- rsnd_rdai_ssi_lane_set(rdai, 1);
- rsnd_rdai_width_set(rdai, slot_width);
- break;
- default:
- dev_err(dev, "unsupported TDM slots (%d)\n", slots);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static unsigned int rsnd_soc_hw_channels_list[] = {
- 2, 6, 8,
-};
-
-static unsigned int rsnd_soc_hw_rate_list[] = {
- 8000,
- 11025,
- 16000,
- 22050,
- 32000,
- 44100,
- 48000,
- 64000,
- 88200,
- 96000,
- 176400,
- 192000,
-};
-
-static int rsnd_soc_hw_rule(struct rsnd_dai *rdai,
- unsigned int *list, int list_num,
- struct snd_interval *baseline, struct snd_interval *iv,
- struct rsnd_dai_stream *io, char *unit)
-{
- struct snd_interval p;
- unsigned int rate;
- int i;
-
- snd_interval_any(&p);
- p.min = UINT_MAX;
- p.max = 0;
-
- for (i = 0; i < list_num; i++) {
-
- if (!snd_interval_test(iv, list[i]))
- continue;
-
- rate = rsnd_ssi_clk_query(rdai,
- baseline->min, list[i], NULL);
- if (rate > 0) {
- p.min = min(p.min, list[i]);
- p.max = max(p.max, list[i]);
- }
-
- rate = rsnd_ssi_clk_query(rdai,
- baseline->max, list[i], NULL);
- if (rate > 0) {
- p.min = min(p.min, list[i]);
- p.max = max(p.max, list[i]);
- }
- }
-
- /* Indicate error once if it can't handle */
- if (!rsnd_flags_has(io, RSND_HW_RULE_ERR) && (p.min > p.max)) {
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_warn(dev, "It can't handle %d %s <-> %d %s\n",
- baseline->min, unit, baseline->max, unit);
- rsnd_flags_set(io, RSND_HW_RULE_ERR);
- }
-
- return snd_interval_refine(iv, &p);
-}
-
-static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
- struct snd_interval ic;
- struct rsnd_dai_stream *io = rule->private;
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
-
- /*
- * possible sampling rate limitation is same as
- * 2ch if it supports multi ssi
- * and same as 8ch if TDM 6ch (see rsnd_ssi_config_init())
- */
- ic = *ic_;
- ic.min =
- ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params);
-
- return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_rate_list,
- ARRAY_SIZE(rsnd_soc_hw_rate_list),
- &ic, ir, io, "ch");
-}
-
-static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
- struct snd_interval ic;
- struct rsnd_dai_stream *io = rule->private;
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
-
- /*
- * possible sampling rate limitation is same as
- * 2ch if it supports multi ssi
- * and same as 8ch if TDM 6ch (see rsnd_ssi_config_init())
- */
- ic = *ic_;
- ic.min =
- ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params);
-
- return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_channels_list,
- ARRAY_SIZE(rsnd_soc_hw_channels_list),
- ir, &ic, io, "Hz");
-}
-
-static const struct snd_pcm_hardware rsnd_pcm_hardware = {
- .info = SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID,
- .buffer_bytes_max = 64 * 1024,
- .period_bytes_min = 32,
- .period_bytes_max = 8192,
- .periods_min = 1,
- .periods_max = 32,
- .fifo_size = 256,
-};
-
-static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- struct snd_pcm_hw_constraint_list *constraint = &rdai->constraint;
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned int max_channels = rsnd_rdai_channels_get(rdai);
- int i;
-
- rsnd_flags_del(io, RSND_HW_RULE_ERR);
-
- rsnd_dai_stream_init(io, substream);
-
- /*
- * Channel Limitation
- * It depends on Platform design
- */
- constraint->list = rsnd_soc_hw_channels_list;
- constraint->count = 0;
- constraint->mask = 0;
-
- for (i = 0; i < ARRAY_SIZE(rsnd_soc_hw_channels_list); i++) {
- if (rsnd_soc_hw_channels_list[i] > max_channels)
- break;
- constraint->count = i + 1;
- }
-
- snd_soc_set_runtime_hwparams(substream, &rsnd_pcm_hardware);
-
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS, constraint);
-
- snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
-
- /*
- * Sampling Rate / Channel Limitation
- * It depends on Clock Master Mode
- */
- if (rsnd_rdai_is_clk_master(rdai)) {
- int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-
- snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- rsnd_soc_hw_rule_rate,
- is_play ? &rdai->playback : &rdai->capture,
- SNDRV_PCM_HW_PARAM_CHANNELS, -1);
- snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
- rsnd_soc_hw_rule_channels,
- is_play ? &rdai->playback : &rdai->capture,
- SNDRV_PCM_HW_PARAM_RATE, -1);
- }
-
- return 0;
-}
-
-static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
-
- /*
- * call rsnd_dai_call without spinlock
- */
- rsnd_dai_call(cleanup, io, priv);
-
- rsnd_dai_stream_quit(io);
-}
-
-static int rsnd_soc_dai_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
-
- return rsnd_dai_call(prepare, io, priv);
-}
-
-static u64 rsnd_soc_dai_formats[] = {
- /*
- * 1st Priority
- *
- * Well tested formats.
- * Select below from Sound Card, not auto
- * SND_SOC_DAIFMT_CBC_CFC
- * SND_SOC_DAIFMT_CBP_CFP
- */
- SND_SOC_POSSIBLE_DAIFMT_I2S |
- SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
- SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
- SND_SOC_POSSIBLE_DAIFMT_NB_NF |
- SND_SOC_POSSIBLE_DAIFMT_NB_IF |
- SND_SOC_POSSIBLE_DAIFMT_IB_NF |
- SND_SOC_POSSIBLE_DAIFMT_IB_IF,
- /*
- * 2nd Priority
- *
- * Supported, but not well tested
- */
- SND_SOC_POSSIBLE_DAIFMT_DSP_A |
- SND_SOC_POSSIBLE_DAIFMT_DSP_B,
-};
-
-static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- struct device_node *dai_np)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *ssiu_np = rsnd_ssiu_of_node(priv);
- struct device_node *np;
- int is_play = rsnd_io_is_play(io);
- int i;
-
- if (!ssiu_np)
- return;
-
- /*
- * This driver assumes that it is TDM Split mode
- * if it includes ssiu node
- */
- for (i = 0;; i++) {
- struct device_node *node = is_play ?
- of_parse_phandle(dai_np, "playback", i) :
- of_parse_phandle(dai_np, "capture", i);
-
- if (!node)
- break;
-
- for_each_child_of_node(ssiu_np, np) {
- if (np == node) {
- rsnd_flags_set(io, RSND_STREAM_TDM_SPLIT);
- dev_dbg(dev, "%s is part of TDM Split\n", io->name);
- }
- }
-
- of_node_put(node);
- }
-
- of_node_put(ssiu_np);
-}
-
-static void rsnd_parse_connect_simple(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- struct device_node *dai_np)
-{
- if (!rsnd_io_to_mod_ssi(io))
- return;
-
- rsnd_parse_tdm_split_mode(priv, io, dai_np);
-}
-
-static void rsnd_parse_connect_graph(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- struct device_node *endpoint)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *remote_node;
-
- if (!rsnd_io_to_mod_ssi(io))
- return;
-
- remote_node = of_graph_get_remote_port_parent(endpoint);
-
- /* HDMI0 */
- if (strstr(remote_node->full_name, "hdmi@fead0000")) {
- rsnd_flags_set(io, RSND_STREAM_HDMI0);
- dev_dbg(dev, "%s connected to HDMI0\n", io->name);
- }
-
- /* HDMI1 */
- if (strstr(remote_node->full_name, "hdmi@feae0000")) {
- rsnd_flags_set(io, RSND_STREAM_HDMI1);
- dev_dbg(dev, "%s connected to HDMI1\n", io->name);
- }
-
- rsnd_parse_tdm_split_mode(priv, io, endpoint);
-
- of_node_put(remote_node);
-}
-
-void rsnd_parse_connect_common(struct rsnd_dai *rdai, char *name,
- struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id),
- struct device_node *node,
- struct device_node *playback,
- struct device_node *capture)
-{
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np;
- int i;
-
- if (!node)
- return;
-
- i = 0;
- for_each_child_of_node(node, np) {
- struct rsnd_mod *mod;
-
- i = rsnd_node_fixed_index(dev, np, name, i);
- if (i < 0) {
- of_node_put(np);
- break;
- }
-
- mod = mod_get(priv, i);
-
- if (np == playback)
- rsnd_dai_connect(mod, &rdai->playback, mod->type);
- if (np == capture)
- rsnd_dai_connect(mod, &rdai->capture, mod->type);
- i++;
- }
-
- of_node_put(node);
-}
-
-int rsnd_node_fixed_index(struct device *dev, struct device_node *node, char *name, int idx)
-{
- char node_name[16];
-
- /*
- * rsnd is assuming each device nodes are sequential numbering,
- * but some of them are not.
- * This function adjusts index for it.
- *
- * ex)
- * Normal case, special case
- * ssi-0
- * ssi-1
- * ssi-2
- * ssi-3 ssi-3
- * ssi-4 ssi-4
- * ...
- *
- * assume Max 64 node
- */
- for (; idx < 64; idx++) {
- snprintf(node_name, sizeof(node_name), "%s-%d", name, idx);
-
- if (strncmp(node_name, of_node_full_name(node), sizeof(node_name)) == 0)
- return idx;
- }
-
- dev_err(dev, "strange node numbering (%s)",
- of_node_full_name(node));
- return -EINVAL;
-}
-
-int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np;
- int i;
-
- i = 0;
- for_each_child_of_node(node, np) {
- i = rsnd_node_fixed_index(dev, np, name, i);
- if (i < 0) {
- of_node_put(np);
- return 0;
- }
- i++;
- }
-
- return i;
-}
-
-static int rsnd_dai_of_node(struct rsnd_priv *priv, int *is_graph)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np = dev->of_node;
- struct device_node *ports, *node;
- int nr = 0;
- int i = 0;
-
- *is_graph = 0;
-
- /*
- * parse both previous dai (= rcar_sound,dai), and
- * graph dai (= ports/port)
- */
-
- /*
- * Simple-Card
- */
- node = of_get_child_by_name(np, RSND_NODE_DAI);
- if (!node)
- goto audio_graph;
-
- of_node_put(node);
-
- for_each_child_of_node(np, node) {
- if (!of_node_name_eq(node, RSND_NODE_DAI))
- continue;
-
- priv->component_dais[i] = of_get_child_count(node);
- nr += priv->component_dais[i];
- i++;
- if (i >= RSND_MAX_COMPONENT) {
- dev_info(dev, "reach to max component\n");
- of_node_put(node);
- break;
- }
- }
-
- return nr;
-
-audio_graph:
- /*
- * Audio-Graph-Card
- */
- for_each_child_of_node(np, ports) {
- if (!of_node_name_eq(ports, "ports") &&
- !of_node_name_eq(ports, "port"))
- continue;
- priv->component_dais[i] = of_graph_get_endpoint_count(ports);
- nr += priv->component_dais[i];
- i++;
- if (i >= RSND_MAX_COMPONENT) {
- dev_info(dev, "reach to max component\n");
- of_node_put(ports);
- break;
- }
- }
-
- *is_graph = 1;
-
- return nr;
-}
-
-
-#define PREALLOC_BUFFER (32 * 1024)
-#define PREALLOC_BUFFER_MAX (32 * 1024)
-
-static int rsnd_preallocate_pages(struct snd_soc_pcm_runtime *rtd,
- struct rsnd_dai_stream *io,
- int stream)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct snd_pcm_substream *substream;
-
- /*
- * use Audio-DMAC dev if we can use IPMMU
- * see
- * rsnd_dmaen_attach()
- */
- if (io->dmac_dev)
- dev = io->dmac_dev;
-
- for (substream = rtd->pcm->streams[stream].substream;
- substream;
- substream = substream->next) {
- snd_pcm_set_managed_buffer(substream,
- SNDRV_DMA_TYPE_DEV,
- dev,
- PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
- }
-
- return 0;
-}
-
-static int rsnd_soc_dai_pcm_new(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
-{
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- int ret;
-
- ret = rsnd_dai_call(pcm_new, &rdai->playback, rtd);
- if (ret)
- return ret;
-
- ret = rsnd_dai_call(pcm_new, &rdai->capture, rtd);
- if (ret)
- return ret;
-
- ret = rsnd_preallocate_pages(rtd, &rdai->playback,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- return ret;
-
- ret = rsnd_preallocate_pages(rtd, &rdai->capture,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
- .pcm_new = rsnd_soc_dai_pcm_new,
- .startup = rsnd_soc_dai_startup,
- .shutdown = rsnd_soc_dai_shutdown,
- .trigger = rsnd_soc_dai_trigger,
- .set_fmt = rsnd_soc_dai_set_fmt,
- .set_tdm_slot = rsnd_soc_set_dai_tdm_slot,
- .prepare = rsnd_soc_dai_prepare,
- .auto_selectable_formats = rsnd_soc_dai_formats,
- .num_auto_selectable_formats = ARRAY_SIZE(rsnd_soc_dai_formats),
-};
-
-static void __rsnd_dai_probe(struct rsnd_priv *priv,
- struct device_node *dai_np,
- struct device_node *node_np,
- uint32_t node_arg,
- int dai_i)
-{
- struct rsnd_dai_stream *io_playback;
- struct rsnd_dai_stream *io_capture;
- struct snd_soc_dai_driver *drv;
- struct rsnd_dai *rdai;
- struct device *dev = rsnd_priv_to_dev(priv);
- int playback_exist = 0, capture_exist = 0;
- int io_i;
-
- rdai = rsnd_rdai_get(priv, dai_i);
- drv = rsnd_daidrv_get(priv, dai_i);
- io_playback = &rdai->playback;
- io_capture = &rdai->capture;
-
- snprintf(rdai->name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", dai_i);
-
- /* for multi Component */
- rdai->dai_args.np = node_np;
- rdai->dai_args.args_count = 1;
- rdai->dai_args.args[0] = node_arg;
-
- rdai->priv = priv;
- drv->name = rdai->name;
- drv->ops = &rsnd_soc_dai_ops;
- drv->id = dai_i;
- drv->dai_args = &rdai->dai_args;
-
- io_playback->rdai = rdai;
- io_capture->rdai = rdai;
- rsnd_rdai_channels_set(rdai, 2); /* default 2ch */
- rsnd_rdai_ssi_lane_set(rdai, 1); /* default 1lane */
- rsnd_rdai_width_set(rdai, 32); /* default 32bit width */
-
- for (io_i = 0;; io_i++) {
- struct device_node *playback = of_parse_phandle(dai_np, "playback", io_i);
- struct device_node *capture = of_parse_phandle(dai_np, "capture", io_i);
-
- if (!playback && !capture)
- break;
-
- if (io_i == 0) {
- /* check whether playback/capture property exists */
- if (playback)
- playback_exist = 1;
- if (capture)
- capture_exist = 1;
- }
-
- rsnd_parse_connect_ssi(rdai, playback, capture);
- rsnd_parse_connect_ssiu(rdai, playback, capture);
- rsnd_parse_connect_src(rdai, playback, capture);
- rsnd_parse_connect_ctu(rdai, playback, capture);
- rsnd_parse_connect_mix(rdai, playback, capture);
- rsnd_parse_connect_dvc(rdai, playback, capture);
-
- of_node_put(playback);
- of_node_put(capture);
- }
-
- if (playback_exist) {
- snprintf(io_playback->name, RSND_DAI_NAME_SIZE, "DAI%d Playback", dai_i);
- drv->playback.rates = RSND_RATES;
- drv->playback.formats = RSND_FMTS;
- drv->playback.channels_min = 2;
- drv->playback.channels_max = 8;
- drv->playback.stream_name = io_playback->name;
- }
- if (capture_exist) {
- snprintf(io_capture->name, RSND_DAI_NAME_SIZE, "DAI%d Capture", dai_i);
- drv->capture.rates = RSND_RATES;
- drv->capture.formats = RSND_FMTS;
- drv->capture.channels_min = 2;
- drv->capture.channels_max = 8;
- drv->capture.stream_name = io_capture->name;
- }
-
- if (rsnd_ssi_is_pin_sharing(io_capture) ||
- rsnd_ssi_is_pin_sharing(io_playback)) {
- /* should have symmetric_rate if pin sharing */
- drv->symmetric_rate = 1;
- }
-
- dev_dbg(dev, "%s (%s/%s)\n", rdai->name,
- rsnd_io_to_mod_ssi(io_playback) ? "play" : " -- ",
- rsnd_io_to_mod_ssi(io_capture) ? "capture" : " -- ");
-}
-
-static int rsnd_dai_probe(struct rsnd_priv *priv)
-{
- struct snd_soc_dai_driver *rdrv;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *np = dev->of_node;
- struct rsnd_dai *rdai;
- int nr = 0;
- int is_graph;
- int dai_i;
-
- nr = rsnd_dai_of_node(priv, &is_graph);
- if (!nr)
- return -EINVAL;
-
- rdrv = devm_kcalloc(dev, nr, sizeof(*rdrv), GFP_KERNEL);
- rdai = devm_kcalloc(dev, nr, sizeof(*rdai), GFP_KERNEL);
- if (!rdrv || !rdai)
- return -ENOMEM;
-
- priv->rdai_nr = nr;
- priv->daidrv = rdrv;
- priv->rdai = rdai;
-
- /*
- * parse all dai
- */
- dai_i = 0;
- if (is_graph) {
- struct device_node *ports;
- struct device_node *dai_np;
-
- for_each_child_of_node(np, ports) {
- if (!of_node_name_eq(ports, "ports") &&
- !of_node_name_eq(ports, "port"))
- continue;
- for_each_endpoint_of_node(ports, dai_np) {
- __rsnd_dai_probe(priv, dai_np, dai_np, 0, dai_i);
- if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
- rdai = rsnd_rdai_get(priv, dai_i);
-
- rsnd_parse_connect_graph(priv, &rdai->playback, dai_np);
- rsnd_parse_connect_graph(priv, &rdai->capture, dai_np);
- }
- dai_i++;
- }
- }
- } else {
- struct device_node *node;
- struct device_node *dai_np;
-
- for_each_child_of_node(np, node) {
- if (!of_node_name_eq(node, RSND_NODE_DAI))
- continue;
-
- for_each_child_of_node(node, dai_np) {
- __rsnd_dai_probe(priv, dai_np, np, dai_i, dai_i);
- if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
- rdai = rsnd_rdai_get(priv, dai_i);
-
- rsnd_parse_connect_simple(priv, &rdai->playback, dai_np);
- rsnd_parse_connect_simple(priv, &rdai->capture, dai_np);
- }
- dai_i++;
- }
- }
- }
-
- return 0;
-}
-
-/*
- * pcm ops
- */
-static int rsnd_hw_update(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&priv->lock, flags);
- if (hw_params)
- ret = rsnd_dai_call(hw_params, io, substream, hw_params);
- else
- ret = rsnd_dai_call(hw_free, io, substream);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return ret;
-}
-
-static int rsnd_hw_params(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- struct snd_soc_pcm_runtime *fe = snd_soc_substream_to_rtd(substream);
-
- /*
- * rsnd assumes that it might be used under DPCM if user want to use
- * channel / rate convert. Then, rsnd should be FE.
- * And then, this function will be called *after* BE settings.
- * this means, each BE already has fixuped hw_params.
- * see
- * dpcm_fe_dai_hw_params()
- * dpcm_be_dai_hw_params()
- */
- io->converted_rate = 0;
- io->converted_chan = 0;
- if (fe->dai_link->dynamic) {
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct snd_soc_dpcm *dpcm;
- int stream = substream->stream;
-
- for_each_dpcm_be(fe, stream, dpcm) {
- struct snd_soc_pcm_runtime *be = dpcm->be;
- struct snd_pcm_hw_params *be_params = &be->dpcm[stream].hw_params;
-
- if (params_channels(hw_params) != params_channels(be_params))
- io->converted_chan = params_channels(be_params);
- if (params_rate(hw_params) != params_rate(be_params))
- io->converted_rate = params_rate(be_params);
- }
- if (io->converted_chan)
- dev_dbg(dev, "convert channels = %d\n", io->converted_chan);
- if (io->converted_rate) {
- /*
- * SRC supports convert rates from params_rate(hw_params)/k_down
- * to params_rate(hw_params)*k_up, where k_up is always 6, and
- * k_down depends on number of channels and SRC unit.
- * So all SRC units can upsample audio up to 6 times regardless
- * its number of channels. And all SRC units can downsample
- * 2 channel audio up to 6 times too.
- */
- int k_up = 6;
- int k_down = 6;
- int channel;
- struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
-
- dev_dbg(dev, "convert rate = %d\n", io->converted_rate);
-
- channel = io->converted_chan ? io->converted_chan :
- params_channels(hw_params);
-
- switch (rsnd_mod_id(src_mod)) {
- /*
- * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times.
- * SRC1, SRC3 and SRC4 can downsample 4 channel audio
- * up to 4 times.
- * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio
- * no more than twice.
- */
- case 1:
- case 3:
- case 4:
- if (channel > 4) {
- k_down = 2;
- break;
- }
- fallthrough;
- case 0:
- if (channel > 2)
- k_down = 4;
- break;
-
- /* Other SRC units do not support more than 2 channels */
- default:
- if (channel > 2)
- return -EINVAL;
- }
-
- if (params_rate(hw_params) > io->converted_rate * k_down) {
- hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
- io->converted_rate * k_down;
- hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
- io->converted_rate * k_down;
- hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
- } else if (params_rate(hw_params) * k_up < io->converted_rate) {
- hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
- DIV_ROUND_UP(io->converted_rate, k_up);
- hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
- DIV_ROUND_UP(io->converted_rate, k_up);
- hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
- }
-
- /*
- * TBD: Max SRC input and output rates also depend on number
- * of channels and SRC unit:
- * SRC1, SRC3 and SRC4 do not support more than 128kHz
- * for 6 channel and 96kHz for 8 channel audio.
- * Perhaps this function should return EINVAL if the input or
- * the output rate exceeds the limitation.
- */
- }
- }
-
- return rsnd_hw_update(substream, hw_params);
-}
-
-static int rsnd_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- return rsnd_hw_update(substream, NULL);
-}
-
-static snd_pcm_uframes_t rsnd_pointer(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- snd_pcm_uframes_t pointer = 0;
-
- rsnd_dai_call(pointer, io, &pointer);
-
- return pointer;
-}
-
-/*
- * snd_kcontrol
- */
-static int rsnd_kctrl_info(struct snd_kcontrol *kctrl,
- struct snd_ctl_elem_info *uinfo)
-{
- struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
-
- if (cfg->texts) {
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = cfg->size;
- uinfo->value.enumerated.items = cfg->max;
- if (uinfo->value.enumerated.item >= cfg->max)
- uinfo->value.enumerated.item = cfg->max - 1;
- strscpy(uinfo->value.enumerated.name,
- cfg->texts[uinfo->value.enumerated.item],
- sizeof(uinfo->value.enumerated.name));
- } else {
- uinfo->count = cfg->size;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = cfg->max;
- uinfo->type = (cfg->max == 1) ?
- SNDRV_CTL_ELEM_TYPE_BOOLEAN :
- SNDRV_CTL_ELEM_TYPE_INTEGER;
- }
-
- return 0;
-}
-
-static int rsnd_kctrl_get(struct snd_kcontrol *kctrl,
- struct snd_ctl_elem_value *uc)
-{
- struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
- int i;
-
- for (i = 0; i < cfg->size; i++)
- if (cfg->texts)
- uc->value.enumerated.item[i] = cfg->val[i];
- else
- uc->value.integer.value[i] = cfg->val[i];
-
- return 0;
-}
-
-static int rsnd_kctrl_put(struct snd_kcontrol *kctrl,
- struct snd_ctl_elem_value *uc)
-{
- struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
- int i, change = 0;
-
- if (!cfg->accept(cfg->io))
- return 0;
-
- for (i = 0; i < cfg->size; i++) {
- if (cfg->texts) {
- change |= (uc->value.enumerated.item[i] != cfg->val[i]);
- cfg->val[i] = uc->value.enumerated.item[i];
- } else {
- change |= (uc->value.integer.value[i] != cfg->val[i]);
- cfg->val[i] = uc->value.integer.value[i];
- }
- }
-
- if (change && cfg->update)
- cfg->update(cfg->io, cfg->mod);
-
- return change;
-}
-
-int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io)
-{
- return 1;
-}
-
-int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- if (!runtime) {
- dev_warn(dev, "Can't update kctrl when idle\n");
- return 0;
- }
-
- return 1;
-}
-
-struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg)
-{
- cfg->cfg.val = cfg->val;
-
- return &cfg->cfg;
-}
-
-struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg)
-{
- cfg->cfg.val = &cfg->val;
-
- return &cfg->cfg;
-}
-
-const char * const volume_ramp_rate[] = {
- "128 dB/1 step", /* 00000 */
- "64 dB/1 step", /* 00001 */
- "32 dB/1 step", /* 00010 */
- "16 dB/1 step", /* 00011 */
- "8 dB/1 step", /* 00100 */
- "4 dB/1 step", /* 00101 */
- "2 dB/1 step", /* 00110 */
- "1 dB/1 step", /* 00111 */
- "0.5 dB/1 step", /* 01000 */
- "0.25 dB/1 step", /* 01001 */
- "0.125 dB/1 step", /* 01010 = VOLUME_RAMP_MAX_MIX */
- "0.125 dB/2 steps", /* 01011 */
- "0.125 dB/4 steps", /* 01100 */
- "0.125 dB/8 steps", /* 01101 */
- "0.125 dB/16 steps", /* 01110 */
- "0.125 dB/32 steps", /* 01111 */
- "0.125 dB/64 steps", /* 10000 */
- "0.125 dB/128 steps", /* 10001 */
- "0.125 dB/256 steps", /* 10010 */
- "0.125 dB/512 steps", /* 10011 */
- "0.125 dB/1024 steps", /* 10100 */
- "0.125 dB/2048 steps", /* 10101 */
- "0.125 dB/4096 steps", /* 10110 */
- "0.125 dB/8192 steps", /* 10111 = VOLUME_RAMP_MAX_DVC */
-};
-
-int rsnd_kctrl_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd,
- const unsigned char *name,
- int (*accept)(struct rsnd_dai_stream *io),
- void (*update)(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod),
- struct rsnd_kctrl_cfg *cfg,
- const char * const *texts,
- int size,
- u32 max)
-{
- struct snd_card *card = rtd->card->snd_card;
- struct snd_kcontrol *kctrl;
- struct snd_kcontrol_new knew = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = name,
- .info = rsnd_kctrl_info,
- .index = rtd->num,
- .get = rsnd_kctrl_get,
- .put = rsnd_kctrl_put,
- };
- int ret;
-
- /*
- * 1) Avoid duplicate register for DVC with MIX case
- * 2) Allow duplicate register for MIX
- * 3) re-register if card was rebinded
- */
- list_for_each_entry(kctrl, &card->controls, list) {
- struct rsnd_kctrl_cfg *c = kctrl->private_data;
-
- if (c == cfg)
- return 0;
- }
-
- if (size > RSND_MAX_CHANNELS)
- return -EINVAL;
-
- kctrl = snd_ctl_new1(&knew, cfg);
- if (!kctrl)
- return -ENOMEM;
-
- ret = snd_ctl_add(card, kctrl);
- if (ret < 0)
- return ret;
-
- cfg->texts = texts;
- cfg->max = max;
- cfg->size = size;
- cfg->accept = accept;
- cfg->update = update;
- cfg->card = card;
- cfg->kctrl = kctrl;
- cfg->io = io;
- cfg->mod = mod;
-
- return 0;
-}
-
-/*
- * snd_soc_component
- */
-static const struct snd_soc_component_driver rsnd_soc_component = {
- .name = "rsnd",
- .probe = rsnd_debugfs_probe,
- .hw_params = rsnd_hw_params,
- .hw_free = rsnd_hw_free,
- .pointer = rsnd_pointer,
- .legacy_dai_naming = 1,
-};
-
-static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io)
-{
- int ret;
-
- ret = rsnd_dai_call(probe, io, priv);
- if (ret == -EAGAIN) {
- struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_mod *mod;
- int i;
-
- /*
- * Fallback to PIO mode
- */
-
- /*
- * call "remove" for SSI/SRC/DVC
- * SSI will be switch to PIO mode if it was DMA mode
- * see
- * rsnd_dma_init()
- * rsnd_ssi_fallback()
- */
- rsnd_dai_call(remove, io, priv);
-
- /*
- * remove all mod from io
- * and, re connect ssi
- */
- for_each_rsnd_mod(i, mod, io)
- rsnd_dai_disconnect(mod, io, i);
- rsnd_dai_connect(ssi_mod, io, RSND_MOD_SSI);
-
- /*
- * fallback
- */
- rsnd_dai_call(fallback, io, priv);
-
- /*
- * retry to "probe".
- * DAI has SSI which is PIO mode only now.
- */
- ret = rsnd_dai_call(probe, io, priv);
- }
-
- return ret;
-}
-
-/*
- * rsnd probe
- */
-static int rsnd_probe(struct platform_device *pdev)
-{
- struct rsnd_priv *priv;
- struct device *dev = &pdev->dev;
- struct rsnd_dai *rdai;
- int (*probe_func[])(struct rsnd_priv *priv) = {
- rsnd_gen_probe,
- rsnd_dma_probe,
- rsnd_ssi_probe,
- rsnd_ssiu_probe,
- rsnd_src_probe,
- rsnd_ctu_probe,
- rsnd_mix_probe,
- rsnd_dvc_probe,
- rsnd_cmd_probe,
- rsnd_adg_probe,
- rsnd_dai_probe,
- };
- int ret, i;
- int ci;
-
- /*
- * init priv data
- */
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENODEV;
-
- priv->pdev = pdev;
- priv->flags = (unsigned long)of_device_get_match_data(dev);
- spin_lock_init(&priv->lock);
-
- /*
- * init each module
- */
- for (i = 0; i < ARRAY_SIZE(probe_func); i++) {
- ret = probe_func[i](priv);
- if (ret)
- return ret;
- }
-
- for_each_rsnd_dai(rdai, priv, i) {
- ret = rsnd_rdai_continuance_probe(priv, &rdai->playback);
- if (ret)
- goto exit_snd_probe;
-
- ret = rsnd_rdai_continuance_probe(priv, &rdai->capture);
- if (ret)
- goto exit_snd_probe;
- }
-
- dev_set_drvdata(dev, priv);
-
- /*
- * asoc register
- */
- ci = 0;
- for (i = 0; priv->component_dais[i] > 0; i++) {
- int nr = priv->component_dais[i];
-
- ret = devm_snd_soc_register_component(dev, &rsnd_soc_component,
- priv->daidrv + ci, nr);
- if (ret < 0) {
- dev_err(dev, "cannot snd component register\n");
- goto exit_snd_probe;
- }
-
- ci += nr;
- }
-
- pm_runtime_enable(dev);
-
- dev_info(dev, "probed\n");
- return ret;
-
-exit_snd_probe:
- for_each_rsnd_dai(rdai, priv, i) {
- rsnd_dai_call(remove, &rdai->playback, priv);
- rsnd_dai_call(remove, &rdai->capture, priv);
- }
-
- /*
- * adg is very special mod which can't use rsnd_dai_call(remove),
- * and it registers ADG clock on probe.
- * It should be unregister if probe failed.
- * Mainly it is assuming -EPROBE_DEFER case
- */
- rsnd_adg_remove(priv);
-
- return ret;
-}
-
-static void rsnd_remove(struct platform_device *pdev)
-{
- struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev);
- struct rsnd_dai *rdai;
- void (*remove_func[])(struct rsnd_priv *priv) = {
- rsnd_ssi_remove,
- rsnd_ssiu_remove,
- rsnd_src_remove,
- rsnd_ctu_remove,
- rsnd_mix_remove,
- rsnd_dvc_remove,
- rsnd_cmd_remove,
- rsnd_adg_remove,
- };
- int i;
-
- pm_runtime_disable(&pdev->dev);
-
- for_each_rsnd_dai(rdai, priv, i) {
- int ret;
-
- ret = rsnd_dai_call(remove, &rdai->playback, priv);
- if (ret)
- dev_warn(&pdev->dev, "Failed to remove playback dai #%d\n", i);
-
- ret = rsnd_dai_call(remove, &rdai->capture, priv);
- if (ret)
- dev_warn(&pdev->dev, "Failed to remove capture dai #%d\n", i);
- }
-
- for (i = 0; i < ARRAY_SIZE(remove_func); i++)
- remove_func[i](priv);
-}
-
-static int __maybe_unused rsnd_suspend(struct device *dev)
-{
- struct rsnd_priv *priv = dev_get_drvdata(dev);
-
- rsnd_adg_clk_disable(priv);
-
- return 0;
-}
-
-static int __maybe_unused rsnd_resume(struct device *dev)
-{
- struct rsnd_priv *priv = dev_get_drvdata(dev);
-
- rsnd_adg_clk_enable(priv);
-
- return 0;
-}
-
-static const struct dev_pm_ops rsnd_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(rsnd_suspend, rsnd_resume)
-};
-
-static struct platform_driver rsnd_driver = {
- .driver = {
- .name = "rcar_sound",
- .pm = &rsnd_pm_ops,
- .of_match_table = rsnd_of_match,
- },
- .probe = rsnd_probe,
- .remove_new = rsnd_remove,
-};
-module_platform_driver(rsnd_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Renesas R-Car audio driver");
-MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
-MODULE_ALIAS("platform:rcar-pcm-audio");
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c
deleted file mode 100644
index e39eb2ac7e95..000000000000
--- a/sound/soc/sh/rcar/ctu.c
+++ /dev/null
@@ -1,393 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// ctu.c
-//
-// Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-#include "rsnd.h"
-
-#define CTU_NAME_SIZE 16
-#define CTU_NAME "ctu"
-
-/*
- * User needs to setup CTU by amixer, and its settings are
- * based on below registers
- *
- * CTUn_CPMDR : amixser set "CTU Pass"
- * CTUn_SV0xR : amixser set "CTU SV0"
- * CTUn_SV1xR : amixser set "CTU SV1"
- * CTUn_SV2xR : amixser set "CTU SV2"
- * CTUn_SV3xR : amixser set "CTU SV3"
- *
- * [CTU Pass]
- * 0000: default
- * 0001: Connect input data of channel 0
- * 0010: Connect input data of channel 1
- * 0011: Connect input data of channel 2
- * 0100: Connect input data of channel 3
- * 0101: Connect input data of channel 4
- * 0110: Connect input data of channel 5
- * 0111: Connect input data of channel 6
- * 1000: Connect input data of channel 7
- * 1001: Connect calculated data by scale values of matrix row 0
- * 1010: Connect calculated data by scale values of matrix row 1
- * 1011: Connect calculated data by scale values of matrix row 2
- * 1100: Connect calculated data by scale values of matrix row 3
- *
- * [CTU SVx]
- * [Output0] = [SV00, SV01, SV02, SV03, SV04, SV05, SV06, SV07]
- * [Output1] = [SV10, SV11, SV12, SV13, SV14, SV15, SV16, SV17]
- * [Output2] = [SV20, SV21, SV22, SV23, SV24, SV25, SV26, SV27]
- * [Output3] = [SV30, SV31, SV32, SV33, SV34, SV35, SV36, SV37]
- * [Output4] = [ 0, 0, 0, 0, 0, 0, 0, 0 ]
- * [Output5] = [ 0, 0, 0, 0, 0, 0, 0, 0 ]
- * [Output6] = [ 0, 0, 0, 0, 0, 0, 0, 0 ]
- * [Output7] = [ 0, 0, 0, 0, 0, 0, 0, 0 ]
- *
- * [SVxx]
- * Plus Minus
- * value time dB value time dB
- * -----------------------------------------------------------------------
- * H'7F_FFFF 2 6 H'80_0000 2 6
- * ...
- * H'40_0000 1 0 H'C0_0000 1 0
- * ...
- * H'00_0001 2.38 x 10^-7 -132
- * H'00_0000 0 Mute H'FF_FFFF 2.38 x 10^-7 -132
- *
- *
- * Ex) Input ch -> Output ch
- * 1ch -> 0ch
- * 0ch -> 1ch
- *
- * amixer set "CTU Reset" on
- * amixer set "CTU Pass" 9,10
- * amixer set "CTU SV0" 0,4194304
- * amixer set "CTU SV1" 4194304,0
- * or
- * amixer set "CTU Reset" on
- * amixer set "CTU Pass" 2,1
- */
-
-struct rsnd_ctu {
- struct rsnd_mod mod;
- struct rsnd_kctrl_cfg_m pass;
- struct rsnd_kctrl_cfg_m sv[4];
- struct rsnd_kctrl_cfg_s reset;
- int channels;
- u32 flags;
-};
-
-#define KCTRL_INITIALIZED (1 << 0)
-
-#define rsnd_ctu_nr(priv) ((priv)->ctu_nr)
-#define for_each_rsnd_ctu(pos, priv, i) \
- for ((i) = 0; \
- ((i) < rsnd_ctu_nr(priv)) && \
- ((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \
- i++)
-
-#define rsnd_mod_to_ctu(_mod) \
- container_of((_mod), struct rsnd_ctu, mod)
-
-#define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id)
-
-static void rsnd_ctu_activation(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, CTU_SWRSR, 0);
- rsnd_mod_write(mod, CTU_SWRSR, 1);
-}
-
-static void rsnd_ctu_halt(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, CTU_CTUIR, 1);
- rsnd_mod_write(mod, CTU_SWRSR, 0);
-}
-
-static int rsnd_ctu_probe_(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- return rsnd_cmd_attach(io, rsnd_mod_id(mod));
-}
-
-static void rsnd_ctu_value_init(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
- u32 cpmdr = 0;
- u32 scmdr = 0;
- int i, j;
-
- for (i = 0; i < RSND_MAX_CHANNELS; i++) {
- u32 val = rsnd_kctrl_valm(ctu->pass, i);
-
- cpmdr |= val << (28 - (i * 4));
-
- if ((val > 0x8) && (scmdr < (val - 0x8)))
- scmdr = val - 0x8;
- }
-
- rsnd_mod_write(mod, CTU_CTUIR, 1);
-
- rsnd_mod_write(mod, CTU_ADINR, rsnd_runtime_channel_original(io));
-
- rsnd_mod_write(mod, CTU_CPMDR, cpmdr);
-
- rsnd_mod_write(mod, CTU_SCMDR, scmdr);
-
- for (i = 0; i < 4; i++) {
-
- if (i >= scmdr)
- break;
-
- for (j = 0; j < RSND_MAX_CHANNELS; j++)
- rsnd_mod_write(mod, CTU_SVxxR(i, j), rsnd_kctrl_valm(ctu->sv[i], j));
- }
-
- rsnd_mod_write(mod, CTU_CTUIR, 0);
-}
-
-static void rsnd_ctu_value_reset(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
- int i;
-
- if (!rsnd_kctrl_vals(ctu->reset))
- return;
-
- for (i = 0; i < RSND_MAX_CHANNELS; i++) {
- rsnd_kctrl_valm(ctu->pass, i) = 0;
- rsnd_kctrl_valm(ctu->sv[0], i) = 0;
- rsnd_kctrl_valm(ctu->sv[1], i) = 0;
- rsnd_kctrl_valm(ctu->sv[2], i) = 0;
- rsnd_kctrl_valm(ctu->sv[3], i) = 0;
- }
- rsnd_kctrl_vals(ctu->reset) = 0;
-}
-
-static int rsnd_ctu_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- ret = rsnd_mod_power_on(mod);
- if (ret < 0)
- return ret;
-
- rsnd_ctu_activation(mod);
-
- rsnd_ctu_value_init(io, mod);
-
- return 0;
-}
-
-static int rsnd_ctu_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_ctu_halt(mod);
-
- rsnd_mod_power_off(mod);
-
- return 0;
-}
-
-static int rsnd_ctu_pcm_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd)
-{
- struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
- int ret;
-
- if (rsnd_flags_has(ctu, KCTRL_INITIALIZED))
- return 0;
-
- /* CTU Pass */
- ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass",
- rsnd_kctrl_accept_anytime,
- NULL,
- &ctu->pass, RSND_MAX_CHANNELS,
- 0xC);
- if (ret < 0)
- return ret;
-
- /* ROW0 */
- ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0",
- rsnd_kctrl_accept_anytime,
- NULL,
- &ctu->sv[0], RSND_MAX_CHANNELS,
- 0x00FFFFFF);
- if (ret < 0)
- return ret;
-
- /* ROW1 */
- ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV1",
- rsnd_kctrl_accept_anytime,
- NULL,
- &ctu->sv[1], RSND_MAX_CHANNELS,
- 0x00FFFFFF);
- if (ret < 0)
- return ret;
-
- /* ROW2 */
- ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV2",
- rsnd_kctrl_accept_anytime,
- NULL,
- &ctu->sv[2], RSND_MAX_CHANNELS,
- 0x00FFFFFF);
- if (ret < 0)
- return ret;
-
- /* ROW3 */
- ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV3",
- rsnd_kctrl_accept_anytime,
- NULL,
- &ctu->sv[3], RSND_MAX_CHANNELS,
- 0x00FFFFFF);
- if (ret < 0)
- return ret;
-
- /* Reset */
- ret = rsnd_kctrl_new_s(mod, io, rtd, "CTU Reset",
- rsnd_kctrl_accept_anytime,
- rsnd_ctu_value_reset,
- &ctu->reset, 1);
-
- rsnd_flags_set(ctu, KCTRL_INITIALIZED);
-
- return ret;
-}
-
-static int rsnd_ctu_id(struct rsnd_mod *mod)
-{
- /*
- * ctu00: -> 0, ctu01: -> 0, ctu02: -> 0, ctu03: -> 0
- * ctu10: -> 1, ctu11: -> 1, ctu12: -> 1, ctu13: -> 1
- */
- return mod->id / 4;
-}
-
-static int rsnd_ctu_id_sub(struct rsnd_mod *mod)
-{
- /*
- * ctu00: -> 0, ctu01: -> 1, ctu02: -> 2, ctu03: -> 3
- * ctu10: -> 0, ctu11: -> 1, ctu12: -> 2, ctu13: -> 3
- */
- return mod->id % 4;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_ctu_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0x500 + rsnd_mod_id_raw(mod) * 0x100, 0x100);
-}
-#define DEBUG_INFO .debug_info = rsnd_ctu_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_ctu_ops = {
- .name = CTU_NAME,
- .probe = rsnd_ctu_probe_,
- .init = rsnd_ctu_init,
- .quit = rsnd_ctu_quit,
- .pcm_new = rsnd_ctu_pcm_new,
- .get_status = rsnd_mod_get_status,
- .id = rsnd_ctu_id,
- .id_sub = rsnd_ctu_id_sub,
- .id_cmd = rsnd_mod_id_raw,
- DEBUG_INFO
-};
-
-struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
- id = 0;
-
- return rsnd_mod_get(rsnd_ctu_get(priv, id));
-}
-
-int rsnd_ctu_probe(struct rsnd_priv *priv)
-{
- struct device_node *node;
- struct device_node *np;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_ctu *ctu;
- struct clk *clk;
- char name[CTU_NAME_SIZE];
- int i, nr, ret;
-
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
- node = rsnd_ctu_of_node(priv);
- if (!node)
- return 0; /* not used is not error */
-
- nr = of_get_child_count(node);
- if (!nr) {
- ret = -EINVAL;
- goto rsnd_ctu_probe_done;
- }
-
- ctu = devm_kcalloc(dev, nr, sizeof(*ctu), GFP_KERNEL);
- if (!ctu) {
- ret = -ENOMEM;
- goto rsnd_ctu_probe_done;
- }
-
- priv->ctu_nr = nr;
- priv->ctu = ctu;
-
- i = 0;
- ret = 0;
- for_each_child_of_node(node, np) {
- ctu = rsnd_ctu_get(priv, i);
-
- /*
- * CTU00, CTU01, CTU02, CTU03 => CTU0
- * CTU10, CTU11, CTU12, CTU13 => CTU1
- */
- snprintf(name, CTU_NAME_SIZE, "%s.%d",
- CTU_NAME, i / 4);
-
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- of_node_put(np);
- goto rsnd_ctu_probe_done;
- }
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
- clk, RSND_MOD_CTU, i);
- if (ret) {
- of_node_put(np);
- goto rsnd_ctu_probe_done;
- }
-
- i++;
- }
-
-
-rsnd_ctu_probe_done:
- of_node_put(node);
-
- return ret;
-}
-
-void rsnd_ctu_remove(struct rsnd_priv *priv)
-{
- struct rsnd_ctu *ctu;
- int i;
-
- for_each_rsnd_ctu(ctu, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(ctu));
- }
-}
diff --git a/sound/soc/sh/rcar/debugfs.c b/sound/soc/sh/rcar/debugfs.c
deleted file mode 100644
index 26d3b310b9db..000000000000
--- a/sound/soc/sh/rcar/debugfs.c
+++ /dev/null
@@ -1,96 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// // Renesas R-Car debugfs support
-//
-// Copyright (c) 2021 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-//
-// > mount -t debugfs none /sys/kernel/debug
-// > cd /sys/kernel/debug/asoc/rcar-sound/ec500000.sound/rdai{N}/
-// > cat playback/xxx
-// > cat capture/xxx
-//
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/debugfs.h>
-#include "rsnd.h"
-
-static int rsnd_debugfs_show(struct seq_file *m, void *v)
-{
- struct rsnd_dai_stream *io = m->private;
- struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- int i;
-
- /* adg is out of mods */
- rsnd_adg_clk_dbg_info(priv, m);
-
- for_each_rsnd_mod(i, mod, io) {
- u32 *status = mod->ops->get_status(mod, io, mod->type);
-
- seq_printf(m, "name: %s\n", rsnd_mod_name(mod));
- seq_printf(m, "status: %08x\n", *status);
-
- if (mod->ops->debug_info)
- mod->ops->debug_info(m, io, mod);
- }
-
- return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(rsnd_debugfs);
-
-void rsnd_debugfs_reg_show(struct seq_file *m, phys_addr_t _addr,
- void __iomem *base, int offset, int size)
-{
- int i, j;
-
- for (i = 0; i < size; i += 0x10) {
- phys_addr_t addr = _addr + offset + i;
-
- seq_printf(m, "%pa:", &addr);
- for (j = 0; j < 0x10; j += 0x4)
- seq_printf(m, " %08x", __raw_readl(base + offset + i + j));
- seq_puts(m, "\n");
- }
-}
-
-void rsnd_debugfs_mod_reg_show(struct seq_file *m, struct rsnd_mod *mod,
- int reg_id, int offset, int size)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-
- rsnd_debugfs_reg_show(m,
- rsnd_gen_get_phy_addr(priv, reg_id),
- rsnd_gen_get_base_addr(priv, reg_id),
- offset, size);
-}
-
-int rsnd_debugfs_probe(struct snd_soc_component *component)
-{
- struct rsnd_priv *priv = dev_get_drvdata(component->dev);
- struct rsnd_dai *rdai;
- struct dentry *dir;
- char name[64];
- int i;
-
- /* Gen1 is not supported */
- if (rsnd_is_gen1(priv))
- return 0;
-
- for_each_rsnd_dai(rdai, priv, i) {
- /*
- * created debugfs will be automatically
- * removed, nothing to do for _remove.
- * see
- * soc_cleanup_component_debugfs()
- */
- snprintf(name, sizeof(name), "rdai%d", i);
- dir = debugfs_create_dir(name, component->debugfs_root);
-
- debugfs_create_file("playback", 0444, dir, &rdai->playback, &rsnd_debugfs_fops);
- debugfs_create_file("capture", 0444, dir, &rdai->capture, &rsnd_debugfs_fops);
- }
-
- return 0;
-}
-
-#endif /* CONFIG_DEBUG_FS */
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
deleted file mode 100644
index 1c494e521463..000000000000
--- a/sound/soc/sh/rcar/dma.c
+++ /dev/null
@@ -1,946 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car Audio DMAC support
-//
-// Copyright (C) 2015 Renesas Electronics Corp.
-// Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-#include <linux/delay.h>
-#include <linux/of_dma.h>
-#include "rsnd.h"
-
-/*
- * Audio DMAC peri peri register
- */
-#define PDMASAR 0x00
-#define PDMADAR 0x04
-#define PDMACHCR 0x0c
-
-/* PDMACHCR */
-#define PDMACHCR_DE (1 << 0)
-
-
-struct rsnd_dmaen {
- struct dma_chan *chan;
- dma_cookie_t cookie;
- unsigned int dma_len;
-};
-
-struct rsnd_dmapp {
- int dmapp_id;
- u32 chcr;
-};
-
-struct rsnd_dma {
- struct rsnd_mod mod;
- struct rsnd_mod *mod_from;
- struct rsnd_mod *mod_to;
- dma_addr_t src_addr;
- dma_addr_t dst_addr;
- union {
- struct rsnd_dmaen en;
- struct rsnd_dmapp pp;
- } dma;
-};
-
-struct rsnd_dma_ctrl {
- void __iomem *ppbase;
- phys_addr_t ppres;
- int dmaen_num;
- int dmapp_num;
-};
-
-#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma)
-#define rsnd_mod_to_dma(_mod) container_of((_mod), struct rsnd_dma, mod)
-#define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en)
-#define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp)
-
-/* for DEBUG */
-static struct rsnd_mod_ops mem_ops = {
- .name = "mem",
-};
-
-static struct rsnd_mod mem = {
-};
-
-/*
- * Audio DMAC
- */
-static void __rsnd_dmaen_complete(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- if (rsnd_io_is_working(io))
- rsnd_dai_period_elapsed(io);
-}
-
-static void rsnd_dmaen_complete(void *data)
-{
- struct rsnd_mod *mod = data;
-
- rsnd_mod_interrupt(mod, __rsnd_dmaen_complete);
-}
-
-static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod_from,
- struct rsnd_mod *mod_to)
-{
- if ((!mod_from && !mod_to) ||
- (mod_from && mod_to))
- return NULL;
-
- if (mod_from)
- return rsnd_mod_dma_req(io, mod_from);
- else
- return rsnd_mod_dma_req(io, mod_to);
-}
-
-static int rsnd_dmaen_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
-
- if (dmaen->chan)
- dmaengine_terminate_async(dmaen->chan);
-
- return 0;
-}
-
-static int rsnd_dmaen_cleanup(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
-
- /*
- * DMAEngine release uses mutex lock.
- * Thus, it shouldn't be called under spinlock.
- * Let's call it under prepare
- */
- if (dmaen->chan)
- dma_release_channel(dmaen->chan);
-
- dmaen->chan = NULL;
-
- return 0;
-}
-
-static int rsnd_dmaen_prepare(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- /* maybe suspended */
- if (dmaen->chan)
- return 0;
-
- /*
- * DMAEngine request uses mutex lock.
- * Thus, it shouldn't be called under spinlock.
- * Let's call it under prepare
- */
- dmaen->chan = rsnd_dmaen_request_channel(io,
- dma->mod_from,
- dma->mod_to);
- if (IS_ERR_OR_NULL(dmaen->chan)) {
- dmaen->chan = NULL;
- dev_err(dev, "can't get dma channel\n");
- return -EIO;
- }
-
- return 0;
-}
-
-static int rsnd_dmaen_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
- struct snd_pcm_substream *substream = io->substream;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct dma_async_tx_descriptor *desc;
- struct dma_slave_config cfg = {};
- enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
- int is_play = rsnd_io_is_play(io);
- int ret;
-
- /*
- * in case of monaural data writing or reading through Audio-DMAC
- * data is always in Left Justified format, so both src and dst
- * DMA Bus width need to be set equal to physical data width.
- */
- if (rsnd_runtime_channel_original(io) == 1) {
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- int bits = snd_pcm_format_physical_width(runtime->format);
-
- switch (bits) {
- case 8:
- buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
- break;
- case 16:
- buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
- break;
- case 32:
- buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
- break;
- default:
- dev_err(dev, "invalid format width %d\n", bits);
- return -EINVAL;
- }
- }
-
- cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
- cfg.src_addr = dma->src_addr;
- cfg.dst_addr = dma->dst_addr;
- cfg.src_addr_width = buswidth;
- cfg.dst_addr_width = buswidth;
-
- dev_dbg(dev, "%s %pad -> %pad\n",
- rsnd_mod_name(mod),
- &cfg.src_addr, &cfg.dst_addr);
-
- ret = dmaengine_slave_config(dmaen->chan, &cfg);
- if (ret < 0)
- return ret;
-
- desc = dmaengine_prep_dma_cyclic(dmaen->chan,
- substream->runtime->dma_addr,
- snd_pcm_lib_buffer_bytes(substream),
- snd_pcm_lib_period_bytes(substream),
- is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
- if (!desc) {
- dev_err(dev, "dmaengine_prep_slave_sg() fail\n");
- return -EIO;
- }
-
- desc->callback = rsnd_dmaen_complete;
- desc->callback_param = rsnd_mod_get(dma);
-
- dmaen->dma_len = snd_pcm_lib_buffer_bytes(substream);
-
- dmaen->cookie = dmaengine_submit(desc);
- if (dmaen->cookie < 0) {
- dev_err(dev, "dmaengine_submit() fail\n");
- return -EIO;
- }
-
- dma_async_issue_pending(dmaen->chan);
-
- return 0;
-}
-
-struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, char *name,
- struct rsnd_mod *mod, char *x)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct dma_chan *chan = NULL;
- struct device_node *np;
- int i = 0;
-
- for_each_child_of_node(of_node, np) {
- i = rsnd_node_fixed_index(dev, np, name, i);
- if (i < 0) {
- chan = NULL;
- of_node_put(np);
- break;
- }
-
- if (i == rsnd_mod_id_raw(mod) && (!chan))
- chan = of_dma_request_slave_channel(np, x);
- i++;
- }
-
- /* It should call of_node_put(), since, it is rsnd_xxx_of_node() */
- of_node_put(of_node);
-
- return chan;
-}
-
-static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
- struct rsnd_dma *dma,
- struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- struct dma_chan *chan;
-
- /* try to get DMAEngine channel */
- chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
- if (IS_ERR_OR_NULL(chan)) {
- /* Let's follow when -EPROBE_DEFER case */
- if (PTR_ERR(chan) == -EPROBE_DEFER)
- return PTR_ERR(chan);
-
- /*
- * DMA failed. try to PIO mode
- * see
- * rsnd_ssi_fallback()
- * rsnd_rdai_continuance_probe()
- */
- return -EAGAIN;
- }
-
- /*
- * use it for IPMMU if needed
- * see
- * rsnd_preallocate_pages()
- */
- io->dmac_dev = chan->device->dev;
-
- dma_release_channel(chan);
-
- dmac->dmaen_num++;
-
- return 0;
-}
-
-static int rsnd_dmaen_pointer(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- snd_pcm_uframes_t *pointer)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
- struct dma_tx_state state;
- enum dma_status status;
- unsigned int pos = 0;
-
- status = dmaengine_tx_status(dmaen->chan, dmaen->cookie, &state);
- if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) {
- if (state.residue > 0 && state.residue <= dmaen->dma_len)
- pos = dmaen->dma_len - state.residue;
- }
- *pointer = bytes_to_frames(runtime, pos);
-
- return 0;
-}
-
-static struct rsnd_mod_ops rsnd_dmaen_ops = {
- .name = "audmac",
- .prepare = rsnd_dmaen_prepare,
- .cleanup = rsnd_dmaen_cleanup,
- .start = rsnd_dmaen_start,
- .stop = rsnd_dmaen_stop,
- .pointer = rsnd_dmaen_pointer,
- .get_status = rsnd_mod_get_status,
-};
-
-/*
- * Audio DMAC peri peri
- */
-static const u8 gen2_id_table_ssiu[] = {
- /* SSI00 ~ SSI07 */
- 0x00, 0x01, 0x02, 0x03, 0x39, 0x3a, 0x3b, 0x3c,
- /* SSI10 ~ SSI17 */
- 0x04, 0x05, 0x06, 0x07, 0x3d, 0x3e, 0x3f, 0x40,
- /* SSI20 ~ SSI27 */
- 0x08, 0x09, 0x0a, 0x0b, 0x41, 0x42, 0x43, 0x44,
- /* SSI30 ~ SSI37 */
- 0x0c, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
- /* SSI40 ~ SSI47 */
- 0x0d, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
- /* SSI5 */
- 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* SSI6 */
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* SSI7 */
- 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* SSI8 */
- 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* SSI90 ~ SSI97 */
- 0x12, 0x13, 0x14, 0x15, 0x53, 0x54, 0x55, 0x56,
-};
-static const u8 gen2_id_table_scu[] = {
- 0x2d, /* SCU_SRCI0 */
- 0x2e, /* SCU_SRCI1 */
- 0x2f, /* SCU_SRCI2 */
- 0x30, /* SCU_SRCI3 */
- 0x31, /* SCU_SRCI4 */
- 0x32, /* SCU_SRCI5 */
- 0x33, /* SCU_SRCI6 */
- 0x34, /* SCU_SRCI7 */
- 0x35, /* SCU_SRCI8 */
- 0x36, /* SCU_SRCI9 */
-};
-static const u8 gen2_id_table_cmd[] = {
- 0x37, /* SCU_CMD0 */
- 0x38, /* SCU_CMD1 */
-};
-
-static u32 rsnd_dmapp_get_id(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
- struct rsnd_mod *ssiu = rsnd_io_to_mod_ssiu(io);
- struct rsnd_mod *src = rsnd_io_to_mod_src(io);
- struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
- const u8 *entry = NULL;
- int id = 255;
- int size = 0;
-
- if ((mod == ssi) ||
- (mod == ssiu)) {
- int busif = rsnd_mod_id_sub(ssiu);
-
- entry = gen2_id_table_ssiu;
- size = ARRAY_SIZE(gen2_id_table_ssiu);
- id = (rsnd_mod_id(mod) * 8) + busif;
- } else if (mod == src) {
- entry = gen2_id_table_scu;
- size = ARRAY_SIZE(gen2_id_table_scu);
- id = rsnd_mod_id(mod);
- } else if (mod == dvc) {
- entry = gen2_id_table_cmd;
- size = ARRAY_SIZE(gen2_id_table_cmd);
- id = rsnd_mod_id(mod);
- }
-
- if ((!entry) || (size <= id)) {
- struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io));
-
- dev_err(dev, "unknown connection (%s)\n", rsnd_mod_name(mod));
-
- /* use non-prohibited SRS number as error */
- return 0x00; /* SSI00 */
- }
-
- return entry[id];
-}
-
-static u32 rsnd_dmapp_get_chcr(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod_from,
- struct rsnd_mod *mod_to)
-{
- return (rsnd_dmapp_get_id(io, mod_from) << 24) +
- (rsnd_dmapp_get_id(io, mod_to) << 16);
-}
-
-#define rsnd_dmapp_addr(dmac, dma, reg) \
- (dmac->ppbase + 0x20 + reg + \
- (0x10 * rsnd_dma_to_dmapp(dma)->dmapp_id))
-static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg)
-{
- struct rsnd_mod *mod = rsnd_mod_get(dma);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_dbg(dev, "w 0x%px : %08x\n", rsnd_dmapp_addr(dmac, dma, reg), data);
-
- iowrite32(data, rsnd_dmapp_addr(dmac, dma, reg));
-}
-
-static u32 rsnd_dmapp_read(struct rsnd_dma *dma, u32 reg)
-{
- struct rsnd_mod *mod = rsnd_mod_get(dma);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
-
- return ioread32(rsnd_dmapp_addr(dmac, dma, reg));
-}
-
-static void rsnd_dmapp_bset(struct rsnd_dma *dma, u32 data, u32 mask, u32 reg)
-{
- struct rsnd_mod *mod = rsnd_mod_get(dma);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- void __iomem *addr = rsnd_dmapp_addr(dmac, dma, reg);
- u32 val = ioread32(addr);
-
- val &= ~mask;
- val |= (data & mask);
-
- iowrite32(val, addr);
-}
-
-static int rsnd_dmapp_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- int i;
-
- rsnd_dmapp_bset(dma, 0, PDMACHCR_DE, PDMACHCR);
-
- for (i = 0; i < 1024; i++) {
- if (0 == (rsnd_dmapp_read(dma, PDMACHCR) & PDMACHCR_DE))
- return 0;
- udelay(1);
- }
-
- return -EIO;
-}
-
-static int rsnd_dmapp_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
-
- rsnd_dmapp_write(dma, dma->src_addr, PDMASAR);
- rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR);
- rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR);
-
- return 0;
-}
-
-static int rsnd_dmapp_attach(struct rsnd_dai_stream *io,
- struct rsnd_dma *dma,
- struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
-{
- struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dmapp->dmapp_id = dmac->dmapp_num;
- dmapp->chcr = rsnd_dmapp_get_chcr(io, mod_from, mod_to) | PDMACHCR_DE;
-
- dmac->dmapp_num++;
-
- dev_dbg(dev, "id/src/dst/chcr = %d/%pad/%pad/%08x\n",
- dmapp->dmapp_id, &dma->src_addr, &dma->dst_addr, dmapp->chcr);
-
- return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_dmapp_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
-
- rsnd_debugfs_reg_show(m, dmac->ppres, dmac->ppbase,
- 0x20 + 0x10 * dmapp->dmapp_id, 0x10);
-}
-#define DEBUG_INFO .debug_info = rsnd_dmapp_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_dmapp_ops = {
- .name = "audmac-pp",
- .start = rsnd_dmapp_start,
- .stop = rsnd_dmapp_stop,
- .quit = rsnd_dmapp_stop,
- .get_status = rsnd_mod_get_status,
- DEBUG_INFO
-};
-
-/*
- * Common DMAC Interface
- */
-
-/*
- * DMA read/write register offset
- *
- * RSND_xxx_I_N for Audio DMAC input
- * RSND_xxx_O_N for Audio DMAC output
- * RSND_xxx_I_P for Audio DMAC peri peri input
- * RSND_xxx_O_P for Audio DMAC peri peri output
- *
- * ex) R-Car H2 case
- * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
- * SSI : 0xec541000 / 0xec241008 / 0xec24100c
- * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
- * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
- * CMD : 0xec500000 / / 0xec008000 0xec308000
- */
-#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
-#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
-
-#define RDMA_SSIU_I_N(addr, i, j) (addr ##_reg - 0x00441000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
-#define RDMA_SSIU_O_N(addr, i, j) RDMA_SSIU_I_N(addr, i, j)
-
-#define RDMA_SSIU_I_P(addr, i, j) (addr ##_reg - 0x00141000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
-#define RDMA_SSIU_O_P(addr, i, j) RDMA_SSIU_I_P(addr, i, j)
-
-#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i))
-#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i))
-
-#define RDMA_SRC_I_P(addr, i) (addr ##_reg - 0x00200000 + (0x400 * i))
-#define RDMA_SRC_O_P(addr, i) (addr ##_reg - 0x001fc000 + (0x400 * i))
-
-#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i))
-#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i))
-
-static dma_addr_t
-rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod,
- int is_play, int is_from)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI);
- phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU);
- int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod) ||
- !!(rsnd_io_to_mod_ssiu(io) == mod);
- int use_src = !!rsnd_io_to_mod_src(io);
- int use_cmd = !!rsnd_io_to_mod_dvc(io) ||
- !!rsnd_io_to_mod_mix(io) ||
- !!rsnd_io_to_mod_ctu(io);
- int id = rsnd_mod_id(mod);
- int busif = rsnd_mod_id_sub(rsnd_io_to_mod_ssiu(io));
- struct dma_addr {
- dma_addr_t out_addr;
- dma_addr_t in_addr;
- } dma_addrs[3][2][3] = {
- /* SRC */
- /* Capture */
- {{{ 0, 0 },
- { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) },
- { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } },
- /* Playback */
- {{ 0, 0, },
- { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) },
- { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } }
- },
- /* SSI */
- /* Capture */
- {{{ RDMA_SSI_O_N(ssi, id), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 } },
- /* Playback */
- {{ 0, RDMA_SSI_I_N(ssi, id) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) } }
- },
- /* SSIU */
- /* Capture */
- {{{ RDMA_SSIU_O_N(ssi, id, busif), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 } },
- /* Playback */
- {{ 0, RDMA_SSIU_I_N(ssi, id, busif) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) } } },
- };
-
- /*
- * FIXME
- *
- * We can't support SSI9-4/5/6/7, because its address is
- * out of calculation rule
- */
- if ((id == 9) && (busif >= 4))
- dev_err(dev, "This driver doesn't support SSI%d-%d, so far",
- id, busif);
-
- /* it shouldn't happen */
- if (use_cmd && !use_src)
- dev_err(dev, "DVC is selected without SRC\n");
-
- /* use SSIU or SSI ? */
- if (is_ssi && rsnd_ssi_use_busif(io))
- is_ssi++;
-
- return (is_from) ?
- dma_addrs[is_ssi][is_play][use_src + use_cmd].out_addr :
- dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr;
-}
-
-/*
- * Gen4 DMA read/write register offset
- *
- * ex) R-Car V4H case
- * mod / SYS-DMAC in / SYS-DMAC out
- * SSI_SDMC: 0xec400000 / 0xec400000 / 0xec400000
- */
-#define RDMA_SSI_SDMC(addr, i) (addr + (0x8000 * i))
-static dma_addr_t
-rsnd_gen4_dma_addr(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
- int is_play, int is_from)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- phys_addr_t addr = rsnd_gen_get_phy_addr(priv, RSND_GEN4_SDMC);
- int id = rsnd_mod_id(mod);
- int busif = rsnd_mod_id_sub(mod);
-
- /*
- * SSI0 only is supported
- */
- if (id != 0) {
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_err(dev, "This driver doesn't support non SSI0");
- return -EINVAL;
- }
-
- return RDMA_SSI_SDMC(addr, busif);
-}
-
-static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod,
- int is_play, int is_from)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
-
- if (!mod)
- return 0;
-
- /*
- * gen1 uses default DMA addr
- */
- if (rsnd_is_gen1(priv))
- return 0;
- else if (rsnd_is_gen4(priv))
- return rsnd_gen4_dma_addr(io, mod, is_play, is_from);
- else
- return rsnd_gen2_dma_addr(io, mod, is_play, is_from);
-}
-
-#define MOD_MAX (RSND_MOD_MAX + 1) /* +Memory */
-static void rsnd_dma_of_path(struct rsnd_mod *this,
- struct rsnd_dai_stream *io,
- int is_play,
- struct rsnd_mod **mod_from,
- struct rsnd_mod **mod_to)
-{
- struct rsnd_mod *ssi;
- struct rsnd_mod *src = rsnd_io_to_mod_src(io);
- struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io);
- struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
- struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
- struct rsnd_mod *mod[MOD_MAX];
- struct rsnd_mod *mod_start, *mod_end;
- struct rsnd_priv *priv = rsnd_mod_to_priv(this);
- struct device *dev = rsnd_priv_to_dev(priv);
- int nr, i, idx;
-
- /*
- * It should use "rcar_sound,ssiu" on DT.
- * But, we need to keep compatibility for old version.
- *
- * If it has "rcar_sound.ssiu", it will be used.
- * If not, "rcar_sound.ssi" will be used.
- * see
- * rsnd_ssiu_dma_req()
- * rsnd_ssi_dma_req()
- */
- if (rsnd_ssiu_of_node(priv)) {
- struct rsnd_mod *ssiu = rsnd_io_to_mod_ssiu(io);
-
- /* use SSIU */
- ssi = ssiu;
- if (this == rsnd_io_to_mod_ssi(io))
- this = ssiu;
- } else {
- /* keep compatible, use SSI */
- ssi = rsnd_io_to_mod_ssi(io);
- }
-
- if (!ssi)
- return;
-
- nr = 0;
- for (i = 0; i < MOD_MAX; i++) {
- mod[i] = NULL;
- nr += !!rsnd_io_to_mod(io, i);
- }
-
- /*
- * [S] -*-> [E]
- * [S] -*-> SRC -o-> [E]
- * [S] -*-> SRC -> DVC -o-> [E]
- * [S] -*-> SRC -> CTU -> MIX -> DVC -o-> [E]
- *
- * playback [S] = mem
- * [E] = SSI
- *
- * capture [S] = SSI
- * [E] = mem
- *
- * -*-> Audio DMAC
- * -o-> Audio DMAC peri peri
- */
- mod_start = (is_play) ? NULL : ssi;
- mod_end = (is_play) ? ssi : NULL;
-
- idx = 0;
- mod[idx++] = mod_start;
- for (i = 1; i < nr; i++) {
- if (src) {
- mod[idx++] = src;
- src = NULL;
- } else if (ctu) {
- mod[idx++] = ctu;
- ctu = NULL;
- } else if (mix) {
- mod[idx++] = mix;
- mix = NULL;
- } else if (dvc) {
- mod[idx++] = dvc;
- dvc = NULL;
- }
- }
- mod[idx] = mod_end;
-
- /*
- * | SSI | SRC |
- * -------------+-----+-----+
- * is_play | o | * |
- * !is_play | * | o |
- */
- if ((this == ssi) == (is_play)) {
- *mod_from = mod[idx - 1];
- *mod_to = mod[idx];
- } else {
- *mod_from = mod[0];
- *mod_to = mod[1];
- }
-
- dev_dbg(dev, "module connection (this is %s)\n", rsnd_mod_name(this));
- for (i = 0; i <= idx; i++) {
- dev_dbg(dev, " %s%s\n",
- rsnd_mod_name(mod[i] ? mod[i] : &mem),
- (mod[i] == *mod_from) ? " from" :
- (mod[i] == *mod_to) ? " to" : "");
- }
-}
-
-static int rsnd_dma_alloc(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
- struct rsnd_mod **dma_mod)
-{
- struct rsnd_mod *mod_from = NULL;
- struct rsnd_mod *mod_to = NULL;
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_dma *dma;
- struct rsnd_mod_ops *ops;
- enum rsnd_mod_type type;
- int (*attach)(struct rsnd_dai_stream *io, struct rsnd_dma *dma,
- struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
- int is_play = rsnd_io_is_play(io);
- int ret, dma_id;
-
- /*
- * DMA failed. try to PIO mode
- * see
- * rsnd_ssi_fallback()
- * rsnd_rdai_continuance_probe()
- */
- if (!dmac)
- return -EAGAIN;
-
- rsnd_dma_of_path(mod, io, is_play, &mod_from, &mod_to);
-
- /* for Gen2 or later */
- if (mod_from && mod_to) {
- ops = &rsnd_dmapp_ops;
- attach = rsnd_dmapp_attach;
- dma_id = dmac->dmapp_num;
- type = RSND_MOD_AUDMAPP;
- } else {
- ops = &rsnd_dmaen_ops;
- attach = rsnd_dmaen_attach;
- dma_id = dmac->dmaen_num;
- type = RSND_MOD_AUDMA;
- }
-
- /* for Gen1, overwrite */
- if (rsnd_is_gen1(priv)) {
- ops = &rsnd_dmaen_ops;
- attach = rsnd_dmaen_attach;
- dma_id = dmac->dmaen_num;
- type = RSND_MOD_AUDMA;
- }
-
- dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
- if (!dma)
- return -ENOMEM;
-
- *dma_mod = rsnd_mod_get(dma);
-
- ret = rsnd_mod_init(priv, *dma_mod, ops, NULL,
- type, dma_id);
- if (ret < 0)
- return ret;
-
- dev_dbg(dev, "%s %s -> %s\n",
- rsnd_mod_name(*dma_mod),
- rsnd_mod_name(mod_from ? mod_from : &mem),
- rsnd_mod_name(mod_to ? mod_to : &mem));
-
- ret = attach(io, dma, mod_from, mod_to);
- if (ret < 0)
- return ret;
-
- dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1);
- dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0);
- dma->mod_from = mod_from;
- dma->mod_to = mod_to;
-
- return 0;
-}
-
-int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
- struct rsnd_mod **dma_mod)
-{
- if (!(*dma_mod)) {
- int ret = rsnd_dma_alloc(io, mod, dma_mod);
-
- if (ret < 0)
- return ret;
- }
-
- return rsnd_dai_connect(*dma_mod, io, (*dma_mod)->type);
-}
-
-int rsnd_dma_probe(struct rsnd_priv *priv)
-{
- struct platform_device *pdev = rsnd_priv_to_pdev(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_dma_ctrl *dmac;
- struct resource *res;
-
- /*
- * for Gen1
- */
- if (rsnd_is_gen1(priv))
- return 0;
-
- /*
- * for Gen2 or later
- */
- dmac = devm_kzalloc(dev, sizeof(*dmac), GFP_KERNEL);
- if (!dmac) {
- dev_err(dev, "dma allocate failed\n");
- return 0; /* it will be PIO mode */
- }
-
- /* for Gen4 doesn't have DMA-pp */
- if (rsnd_is_gen4(priv))
- goto audmapp_end;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audmapp");
- if (!res) {
- dev_err(dev, "lack of audmapp in DT\n");
- return 0; /* it will be PIO mode */
- }
-
- dmac->dmapp_num = 0;
- dmac->ppres = res->start;
- dmac->ppbase = devm_ioremap_resource(dev, res);
- if (IS_ERR(dmac->ppbase))
- return PTR_ERR(dmac->ppbase);
-audmapp_end:
- priv->dma = dmac;
-
- /* dummy mem mod for debug */
- return rsnd_mod_init(NULL, &mem, &mem_ops, NULL, 0, 0);
-}
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
deleted file mode 100644
index 16befcbc312c..000000000000
--- a/sound/soc/sh/rcar/dvc.c
+++ /dev/null
@@ -1,396 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car DVC support
-//
-// Copyright (C) 2014 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-/*
- * Playback Volume
- * amixer set "DVC Out" 100%
- *
- * Capture Volume
- * amixer set "DVC In" 100%
- *
- * Playback Mute
- * amixer set "DVC Out Mute" on
- *
- * Capture Mute
- * amixer set "DVC In Mute" on
- *
- * Volume Ramp
- * amixer set "DVC Out Ramp Up Rate" "0.125 dB/64 steps"
- * amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps"
- * amixer set "DVC Out Ramp" on
- * aplay xxx.wav &
- * amixer set "DVC Out" 80% // Volume Down
- * amixer set "DVC Out" 100% // Volume Up
- */
-
-#include "rsnd.h"
-
-#define RSND_DVC_NAME_SIZE 16
-
-#define DVC_NAME "dvc"
-
-struct rsnd_dvc {
- struct rsnd_mod mod;
- struct rsnd_kctrl_cfg_m volume;
- struct rsnd_kctrl_cfg_m mute;
- struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */
- struct rsnd_kctrl_cfg_s rup; /* Ramp Rate Up */
- struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */
-};
-
-#define rsnd_dvc_get(priv, id) ((struct rsnd_dvc *)(priv->dvc) + id)
-#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
-
-#define rsnd_mod_to_dvc(_mod) \
- container_of((_mod), struct rsnd_dvc, mod)
-
-#define for_each_rsnd_dvc(pos, priv, i) \
- for ((i) = 0; \
- ((i) < rsnd_dvc_nr(priv)) && \
- ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \
- i++)
-
-static void rsnd_dvc_activation(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, DVC_SWRSR, 0);
- rsnd_mod_write(mod, DVC_SWRSR, 1);
-}
-
-static void rsnd_dvc_halt(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, DVC_DVUIR, 1);
- rsnd_mod_write(mod, DVC_SWRSR, 0);
-}
-
-#define rsnd_dvc_get_vrpdr(dvc) (rsnd_kctrl_vals(dvc->rup) << 8 | \
- rsnd_kctrl_vals(dvc->rdown))
-#define rsnd_dvc_get_vrdbr(dvc) (0x3ff - (rsnd_kctrl_valm(dvc->volume, 0) >> 13))
-
-static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
- u32 val[RSND_MAX_CHANNELS];
- int i;
-
- /* Enable Ramp */
- if (rsnd_kctrl_vals(dvc->ren))
- for (i = 0; i < RSND_MAX_CHANNELS; i++)
- val[i] = rsnd_kctrl_max(dvc->volume);
- else
- for (i = 0; i < RSND_MAX_CHANNELS; i++)
- val[i] = rsnd_kctrl_valm(dvc->volume, i);
-
- /* Enable Digital Volume */
- for (i = 0; i < RSND_MAX_CHANNELS; i++)
- rsnd_mod_write(mod, DVC_VOLxR(i), val[i]);
-}
-
-static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
- u32 adinr = 0;
- u32 dvucr = 0;
- u32 vrctr = 0;
- u32 vrpdr = 0;
- u32 vrdbr = 0;
-
- adinr = rsnd_get_adinr_bit(mod, io) |
- rsnd_runtime_channel_after_ctu(io);
-
- /* Enable Digital Volume, Zero Cross Mute Mode */
- dvucr |= 0x101;
-
- /* Enable Ramp */
- if (rsnd_kctrl_vals(dvc->ren)) {
- dvucr |= 0x10;
-
- /*
- * FIXME !!
- * use scale-downed Digital Volume
- * as Volume Ramp
- * 7F FFFF -> 3FF
- */
- vrctr = 0xff;
- vrpdr = rsnd_dvc_get_vrpdr(dvc);
- vrdbr = rsnd_dvc_get_vrdbr(dvc);
- }
-
- /* Initialize operation */
- rsnd_mod_write(mod, DVC_DVUIR, 1);
-
- /* General Information */
- rsnd_mod_write(mod, DVC_ADINR, adinr);
- rsnd_mod_write(mod, DVC_DVUCR, dvucr);
-
- /* Volume Ramp Parameter */
- rsnd_mod_write(mod, DVC_VRCTR, vrctr);
- rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
- rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
-
- /* Digital Volume Function Parameter */
- rsnd_dvc_volume_parameter(io, mod);
-
- /* cancel operation */
- rsnd_mod_write(mod, DVC_DVUIR, 0);
-}
-
-static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
- u32 zcmcr = 0;
- u32 vrpdr = 0;
- u32 vrdbr = 0;
- int i;
-
- for (i = 0; i < rsnd_kctrl_size(dvc->mute); i++)
- zcmcr |= (!!rsnd_kctrl_valm(dvc->mute, i)) << i;
-
- if (rsnd_kctrl_vals(dvc->ren)) {
- vrpdr = rsnd_dvc_get_vrpdr(dvc);
- vrdbr = rsnd_dvc_get_vrdbr(dvc);
- }
-
- /* Disable DVC Register access */
- rsnd_mod_write(mod, DVC_DVUER, 0);
-
- /* Zero Cross Mute Function */
- rsnd_mod_write(mod, DVC_ZCMCR, zcmcr);
-
- /* Volume Ramp Function */
- rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
- rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
- /* add DVC_VRWTR here */
-
- /* Digital Volume Function Parameter */
- rsnd_dvc_volume_parameter(io, mod);
-
- /* Enable DVC Register access */
- rsnd_mod_write(mod, DVC_DVUER, 1);
-}
-
-static int rsnd_dvc_probe_(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- return rsnd_cmd_attach(io, rsnd_mod_id(mod));
-}
-
-static int rsnd_dvc_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- ret = rsnd_mod_power_on(mod);
- if (ret < 0)
- return ret;
-
- rsnd_dvc_activation(mod);
-
- rsnd_dvc_volume_init(io, mod);
-
- rsnd_dvc_volume_update(io, mod);
-
- return 0;
-}
-
-static int rsnd_dvc_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_dvc_halt(mod);
-
- rsnd_mod_power_off(mod);
-
- return 0;
-}
-
-static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd)
-{
- struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- int is_play = rsnd_io_is_play(io);
- int channels = rsnd_rdai_channels_get(rdai);
- int ret;
-
- /* Volume */
- ret = rsnd_kctrl_new_m(mod, io, rtd,
- is_play ?
- "DVC Out Playback Volume" : "DVC In Capture Volume",
- rsnd_kctrl_accept_anytime,
- rsnd_dvc_volume_update,
- &dvc->volume, channels,
- 0x00800000 - 1);
- if (ret < 0)
- return ret;
-
- /* Mute */
- ret = rsnd_kctrl_new_m(mod, io, rtd,
- is_play ?
- "DVC Out Mute Switch" : "DVC In Mute Switch",
- rsnd_kctrl_accept_anytime,
- rsnd_dvc_volume_update,
- &dvc->mute, channels,
- 1);
- if (ret < 0)
- return ret;
-
- /* Ramp */
- ret = rsnd_kctrl_new_s(mod, io, rtd,
- is_play ?
- "DVC Out Ramp Switch" : "DVC In Ramp Switch",
- rsnd_kctrl_accept_anytime,
- rsnd_dvc_volume_update,
- &dvc->ren, 1);
- if (ret < 0)
- return ret;
-
- ret = rsnd_kctrl_new_e(mod, io, rtd,
- is_play ?
- "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate",
- rsnd_kctrl_accept_anytime,
- rsnd_dvc_volume_update,
- &dvc->rup,
- volume_ramp_rate,
- VOLUME_RAMP_MAX_DVC);
- if (ret < 0)
- return ret;
-
- ret = rsnd_kctrl_new_e(mod, io, rtd,
- is_play ?
- "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate",
- rsnd_kctrl_accept_anytime,
- rsnd_dvc_volume_update,
- &dvc->rdown,
- volume_ramp_rate,
- VOLUME_RAMP_MAX_DVC);
-
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-
- return rsnd_dma_request_channel(rsnd_dvc_of_node(priv),
- DVC_NAME, mod, "tx");
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_dvc_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0xe00 + rsnd_mod_id(mod) * 0x100, 0x60);
-}
-#define DEBUG_INFO .debug_info = rsnd_dvc_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_dvc_ops = {
- .name = DVC_NAME,
- .dma_req = rsnd_dvc_dma_req,
- .probe = rsnd_dvc_probe_,
- .init = rsnd_dvc_init,
- .quit = rsnd_dvc_quit,
- .pcm_new = rsnd_dvc_pcm_new,
- .get_status = rsnd_mod_get_status,
- DEBUG_INFO
-};
-
-struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv)))
- id = 0;
-
- return rsnd_mod_get(rsnd_dvc_get(priv, id));
-}
-
-int rsnd_dvc_probe(struct rsnd_priv *priv)
-{
- struct device_node *node;
- struct device_node *np;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_dvc *dvc;
- struct clk *clk;
- char name[RSND_DVC_NAME_SIZE];
- int i, nr, ret;
-
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
- node = rsnd_dvc_of_node(priv);
- if (!node)
- return 0; /* not used is not error */
-
- nr = of_get_child_count(node);
- if (!nr) {
- ret = -EINVAL;
- goto rsnd_dvc_probe_done;
- }
-
- dvc = devm_kcalloc(dev, nr, sizeof(*dvc), GFP_KERNEL);
- if (!dvc) {
- ret = -ENOMEM;
- goto rsnd_dvc_probe_done;
- }
-
- priv->dvc_nr = nr;
- priv->dvc = dvc;
-
- i = 0;
- ret = 0;
- for_each_child_of_node(node, np) {
- dvc = rsnd_dvc_get(priv, i);
-
- snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d",
- DVC_NAME, i);
-
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- of_node_put(np);
- goto rsnd_dvc_probe_done;
- }
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops,
- clk, RSND_MOD_DVC, i);
- if (ret) {
- of_node_put(np);
- goto rsnd_dvc_probe_done;
- }
-
- i++;
- }
-
-rsnd_dvc_probe_done:
- of_node_put(node);
-
- return ret;
-}
-
-void rsnd_dvc_remove(struct rsnd_priv *priv)
-{
- struct rsnd_dvc *dvc;
- int i;
-
- for_each_rsnd_dvc(dvc, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(dvc));
- }
-}
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
deleted file mode 100644
index 86bdecc24956..000000000000
--- a/sound/soc/sh/rcar/gen.c
+++ /dev/null
@@ -1,562 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car Gen1 SRU/SSI support
-//
-// Copyright (C) 2013 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-/*
- * #define DEBUG
- *
- * you can also add below in
- * ${LINUX}/drivers/base/regmap/regmap.c
- * for regmap debug
- *
- * #define LOG_DEVICE "xxxx.rcar_sound"
- */
-
-#include "rsnd.h"
-
-struct rsnd_gen {
- struct rsnd_gen_ops *ops;
-
- /* RSND_BASE_MAX base */
- void __iomem *base[RSND_BASE_MAX];
- phys_addr_t res[RSND_BASE_MAX];
- struct regmap *regmap[RSND_BASE_MAX];
-
- /* RSND_REG_MAX base */
- struct regmap_field *regs[REG_MAX];
- const char *reg_name[REG_MAX];
-};
-
-#define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
-#define rsnd_reg_name(gen, id) ((gen)->reg_name[id])
-
-struct rsnd_regmap_field_conf {
- int idx;
- unsigned int reg_offset;
- unsigned int id_offset;
- const char *reg_name;
-};
-
-#define RSND_REG_SET(id, offset, _id_offset, n) \
-{ \
- .idx = id, \
- .reg_offset = offset, \
- .id_offset = _id_offset, \
- .reg_name = n, \
-}
-/* single address mapping */
-#define RSND_GEN_S_REG(id, offset) \
- RSND_REG_SET(id, offset, 0, #id)
-
-/* multi address mapping */
-#define RSND_GEN_M_REG(id, offset, _id_offset) \
- RSND_REG_SET(id, offset, _id_offset, #id)
-
-/*
- * basic function
- */
-static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
- struct rsnd_gen *gen, enum rsnd_reg reg)
-{
- if (!gen->regs[reg]) {
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_err(dev, "unsupported register access %x\n", reg);
- return 0;
- }
-
- return 1;
-}
-
-static int rsnd_mod_id_cmd(struct rsnd_mod *mod)
-{
- if (mod->ops->id_cmd)
- return mod->ops->id_cmd(mod);
-
- return rsnd_mod_id(mod);
-}
-
-u32 rsnd_mod_read(struct rsnd_mod *mod, enum rsnd_reg reg)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
- u32 val;
-
- if (!rsnd_is_accessible_reg(priv, gen, reg))
- return 0;
-
- regmap_fields_read(gen->regs[reg], rsnd_mod_id_cmd(mod), &val);
-
- dev_dbg(dev, "r %s - %-18s (%4d) : %08x\n",
- rsnd_mod_name(mod),
- rsnd_reg_name(gen, reg), reg, val);
-
- return val;
-}
-
-void rsnd_mod_write(struct rsnd_mod *mod,
- enum rsnd_reg reg, u32 data)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
- if (!rsnd_is_accessible_reg(priv, gen, reg))
- return;
-
- regmap_fields_force_write(gen->regs[reg], rsnd_mod_id_cmd(mod), data);
-
- dev_dbg(dev, "w %s - %-18s (%4d) : %08x\n",
- rsnd_mod_name(mod),
- rsnd_reg_name(gen, reg), reg, data);
-}
-
-void rsnd_mod_bset(struct rsnd_mod *mod,
- enum rsnd_reg reg, u32 mask, u32 data)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
- if (!rsnd_is_accessible_reg(priv, gen, reg))
- return;
-
- regmap_fields_force_update_bits(gen->regs[reg],
- rsnd_mod_id_cmd(mod), mask, data);
-
- dev_dbg(dev, "b %s - %-18s (%4d) : %08x/%08x\n",
- rsnd_mod_name(mod),
- rsnd_reg_name(gen, reg), reg, data, mask);
-
-}
-
-phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id)
-{
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
- return gen->res[reg_id];
-}
-
-#ifdef CONFIG_DEBUG_FS
-void __iomem *rsnd_gen_get_base_addr(struct rsnd_priv *priv, int reg_id)
-{
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
- return gen->base[reg_id];
-}
-#endif
-
-#define rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf) \
- _rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf, ARRAY_SIZE(conf))
-static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
- int id_size,
- int reg_id,
- const char *name,
- const struct rsnd_regmap_field_conf *conf,
- int conf_size)
-{
- struct platform_device *pdev = rsnd_priv_to_pdev(priv);
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct resource *res;
- struct regmap_config regc;
- struct regmap_field *regs;
- struct regmap *regmap;
- struct reg_field regf;
- void __iomem *base;
- int i;
-
- memset(&regc, 0, sizeof(regc));
- regc.reg_bits = 32;
- regc.val_bits = 32;
- regc.reg_stride = 4;
- regc.name = name;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
- if (!res)
- res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id);
- if (!res)
- return -ENODEV;
-
- base = devm_ioremap_resource(dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- regmap = devm_regmap_init_mmio(dev, base, &regc);
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
-
- /* RSND_BASE_MAX base */
- gen->base[reg_id] = base;
- gen->regmap[reg_id] = regmap;
- gen->res[reg_id] = res->start;
-
- for (i = 0; i < conf_size; i++) {
-
- regf.reg = conf[i].reg_offset;
- regf.id_offset = conf[i].id_offset;
- regf.lsb = 0;
- regf.msb = 31;
- regf.id_size = id_size;
-
- regs = devm_regmap_field_alloc(dev, regmap, regf);
- if (IS_ERR(regs))
- return PTR_ERR(regs);
-
- /* RSND_REG_MAX base */
- gen->regs[conf[i].idx] = regs;
- gen->reg_name[conf[i].idx] = conf[i].reg_name;
- }
-
- return 0;
-}
-
-/*
- * Gen4
- */
-static int rsnd_gen4_probe(struct rsnd_priv *priv)
-{
- static const struct rsnd_regmap_field_conf conf_ssiu[] = {
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898),
- RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840),
- RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848),
- RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880),
- RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888),
-
- RSND_GEN_S_REG(SSI_BUSIF0_MODE, 0x0),
- RSND_GEN_S_REG(SSI_BUSIF0_ADINR, 0x4),
- RSND_GEN_S_REG(SSI_BUSIF0_DALIGN, 0x8),
- RSND_GEN_S_REG(SSI_BUSIF1_MODE, 0x20),
- RSND_GEN_S_REG(SSI_BUSIF1_ADINR, 0x24),
- RSND_GEN_S_REG(SSI_BUSIF1_DALIGN, 0x28),
- RSND_GEN_S_REG(SSI_BUSIF2_MODE, 0x40),
- RSND_GEN_S_REG(SSI_BUSIF2_ADINR, 0x44),
- RSND_GEN_S_REG(SSI_BUSIF2_DALIGN, 0x48),
- RSND_GEN_S_REG(SSI_BUSIF3_MODE, 0x60),
- RSND_GEN_S_REG(SSI_BUSIF3_ADINR, 0x64),
- RSND_GEN_S_REG(SSI_BUSIF3_DALIGN, 0x68),
- RSND_GEN_S_REG(SSI_BUSIF4_MODE, 0x500),
- RSND_GEN_S_REG(SSI_BUSIF4_ADINR, 0x504),
- RSND_GEN_S_REG(SSI_BUSIF4_DALIGN, 0x508),
- RSND_GEN_S_REG(SSI_BUSIF5_MODE, 0x520),
- RSND_GEN_S_REG(SSI_BUSIF5_ADINR, 0x524),
- RSND_GEN_S_REG(SSI_BUSIF5_DALIGN, 0x528),
- RSND_GEN_S_REG(SSI_BUSIF6_MODE, 0x540),
- RSND_GEN_S_REG(SSI_BUSIF6_ADINR, 0x544),
- RSND_GEN_S_REG(SSI_BUSIF6_DALIGN, 0x548),
- RSND_GEN_S_REG(SSI_BUSIF7_MODE, 0x560),
- RSND_GEN_S_REG(SSI_BUSIF7_ADINR, 0x564),
- RSND_GEN_S_REG(SSI_BUSIF7_DALIGN, 0x568),
- RSND_GEN_S_REG(SSI_CTRL, 0x010),
- RSND_GEN_S_REG(SSI_INT_ENABLE, 0x018),
- RSND_GEN_S_REG(SSI_MODE, 0x00c),
- RSND_GEN_S_REG(SSI_MODE2, 0xa0c),
- };
- static const struct rsnd_regmap_field_conf conf_adg[] = {
- RSND_GEN_S_REG(BRRA, 0x00),
- RSND_GEN_S_REG(BRRB, 0x04),
- RSND_GEN_S_REG(BRGCKR, 0x08),
- RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
- };
- static const struct rsnd_regmap_field_conf conf_ssi[] = {
- RSND_GEN_S_REG(SSICR, 0x00),
- RSND_GEN_S_REG(SSISR, 0x04),
- RSND_GEN_S_REG(SSITDR, 0x08),
- RSND_GEN_S_REG(SSIRDR, 0x0c),
- RSND_GEN_S_REG(SSIWSR, 0x20),
- };
- static const struct rsnd_regmap_field_conf conf_sdmc[] = {
- RSND_GEN_M_REG(SSI_BUSIF, 0x0, 0x8000),
- };
- int ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_ADG, "adg", conf_adg);
- int ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSIU, "ssiu", conf_ssiu);
- int ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSI, "ssi", conf_ssi);
- int ret_sdmc = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SDMC, "sdmc", conf_sdmc);
-
- return ret_adg | ret_ssiu | ret_ssi | ret_sdmc;
-}
-
-/*
- * Gen2
- */
-static int rsnd_gen2_probe(struct rsnd_priv *priv)
-{
- static const struct rsnd_regmap_field_conf conf_ssiu[] = {
- RSND_GEN_S_REG(SSI_MODE0, 0x800),
- RSND_GEN_S_REG(SSI_MODE1, 0x804),
- RSND_GEN_S_REG(SSI_MODE2, 0x808),
- RSND_GEN_S_REG(SSI_CONTROL, 0x810),
- RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840),
- RSND_GEN_S_REG(SSI_SYS_STATUS1, 0x844),
- RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848),
- RSND_GEN_S_REG(SSI_SYS_STATUS3, 0x84c),
- RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880),
- RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884),
- RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888),
- RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE1, 0x854),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE3, 0x85c),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE5, 0x894),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898),
- RSND_GEN_S_REG(SSI_SYS_INT_ENABLE7, 0x89c),
- RSND_GEN_S_REG(HDMI0_SEL, 0x9e0),
- RSND_GEN_S_REG(HDMI1_SEL, 0x9e4),
-
- /* FIXME: it needs SSI_MODE2/3 in the future */
- RSND_GEN_M_REG(SSI_BUSIF0_MODE, 0x0, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF0_ADINR, 0x4, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF0_DALIGN, 0x8, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF1_MODE, 0x20, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF1_ADINR, 0x24, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF1_DALIGN, 0x28, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF2_MODE, 0x40, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF2_ADINR, 0x44, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF2_DALIGN, 0x48, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF3_MODE, 0x60, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF3_ADINR, 0x64, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF3_DALIGN, 0x68, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF4_MODE, 0x500, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF4_ADINR, 0x504, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF4_DALIGN, 0x508, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF5_MODE, 0x520, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF5_ADINR, 0x524, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF5_DALIGN, 0x528, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF6_MODE, 0x540, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF6_ADINR, 0x544, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF6_DALIGN, 0x548, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF7_MODE, 0x560, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF7_ADINR, 0x564, 0x80),
- RSND_GEN_M_REG(SSI_BUSIF7_DALIGN, 0x568, 0x80),
- RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80),
- RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80),
- RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80),
- RSND_GEN_S_REG(SSI9_BUSIF0_MODE, 0x48c),
- RSND_GEN_S_REG(SSI9_BUSIF0_ADINR, 0x484),
- RSND_GEN_S_REG(SSI9_BUSIF0_DALIGN, 0x488),
- RSND_GEN_S_REG(SSI9_BUSIF1_MODE, 0x4a0),
- RSND_GEN_S_REG(SSI9_BUSIF1_ADINR, 0x4a4),
- RSND_GEN_S_REG(SSI9_BUSIF1_DALIGN, 0x4a8),
- RSND_GEN_S_REG(SSI9_BUSIF2_MODE, 0x4c0),
- RSND_GEN_S_REG(SSI9_BUSIF2_ADINR, 0x4c4),
- RSND_GEN_S_REG(SSI9_BUSIF2_DALIGN, 0x4c8),
- RSND_GEN_S_REG(SSI9_BUSIF3_MODE, 0x4e0),
- RSND_GEN_S_REG(SSI9_BUSIF3_ADINR, 0x4e4),
- RSND_GEN_S_REG(SSI9_BUSIF3_DALIGN, 0x4e8),
- RSND_GEN_S_REG(SSI9_BUSIF4_MODE, 0xd80),
- RSND_GEN_S_REG(SSI9_BUSIF4_ADINR, 0xd84),
- RSND_GEN_S_REG(SSI9_BUSIF4_DALIGN, 0xd88),
- RSND_GEN_S_REG(SSI9_BUSIF5_MODE, 0xda0),
- RSND_GEN_S_REG(SSI9_BUSIF5_ADINR, 0xda4),
- RSND_GEN_S_REG(SSI9_BUSIF5_DALIGN, 0xda8),
- RSND_GEN_S_REG(SSI9_BUSIF6_MODE, 0xdc0),
- RSND_GEN_S_REG(SSI9_BUSIF6_ADINR, 0xdc4),
- RSND_GEN_S_REG(SSI9_BUSIF6_DALIGN, 0xdc8),
- RSND_GEN_S_REG(SSI9_BUSIF7_MODE, 0xde0),
- RSND_GEN_S_REG(SSI9_BUSIF7_ADINR, 0xde4),
- RSND_GEN_S_REG(SSI9_BUSIF7_DALIGN, 0xde8),
- };
-
- static const struct rsnd_regmap_field_conf conf_scu[] = {
- RSND_GEN_M_REG(SRC_I_BUSIF_MODE,0x0, 0x20),
- RSND_GEN_M_REG(SRC_O_BUSIF_MODE,0x4, 0x20),
- RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20),
- RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
- RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
- RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20),
- RSND_GEN_M_REG(CMD_BUSIF_MODE, 0x184, 0x20),
- RSND_GEN_M_REG(CMD_BUSIF_DALIGN,0x188, 0x20),
- RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20),
- RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20),
- RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8),
- RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc),
- RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0),
- RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1d4),
- RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40),
- RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40),
- RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40),
- RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40),
- RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40),
- RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40),
- RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40),
- RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40),
- RSND_GEN_M_REG(CTU_SWRSR, 0x500, 0x100),
- RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100),
- RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100),
- RSND_GEN_M_REG(CTU_CPMDR, 0x510, 0x100),
- RSND_GEN_M_REG(CTU_SCMDR, 0x514, 0x100),
- RSND_GEN_M_REG(CTU_SV00R, 0x518, 0x100),
- RSND_GEN_M_REG(CTU_SV01R, 0x51c, 0x100),
- RSND_GEN_M_REG(CTU_SV02R, 0x520, 0x100),
- RSND_GEN_M_REG(CTU_SV03R, 0x524, 0x100),
- RSND_GEN_M_REG(CTU_SV04R, 0x528, 0x100),
- RSND_GEN_M_REG(CTU_SV05R, 0x52c, 0x100),
- RSND_GEN_M_REG(CTU_SV06R, 0x530, 0x100),
- RSND_GEN_M_REG(CTU_SV07R, 0x534, 0x100),
- RSND_GEN_M_REG(CTU_SV10R, 0x538, 0x100),
- RSND_GEN_M_REG(CTU_SV11R, 0x53c, 0x100),
- RSND_GEN_M_REG(CTU_SV12R, 0x540, 0x100),
- RSND_GEN_M_REG(CTU_SV13R, 0x544, 0x100),
- RSND_GEN_M_REG(CTU_SV14R, 0x548, 0x100),
- RSND_GEN_M_REG(CTU_SV15R, 0x54c, 0x100),
- RSND_GEN_M_REG(CTU_SV16R, 0x550, 0x100),
- RSND_GEN_M_REG(CTU_SV17R, 0x554, 0x100),
- RSND_GEN_M_REG(CTU_SV20R, 0x558, 0x100),
- RSND_GEN_M_REG(CTU_SV21R, 0x55c, 0x100),
- RSND_GEN_M_REG(CTU_SV22R, 0x560, 0x100),
- RSND_GEN_M_REG(CTU_SV23R, 0x564, 0x100),
- RSND_GEN_M_REG(CTU_SV24R, 0x568, 0x100),
- RSND_GEN_M_REG(CTU_SV25R, 0x56c, 0x100),
- RSND_GEN_M_REG(CTU_SV26R, 0x570, 0x100),
- RSND_GEN_M_REG(CTU_SV27R, 0x574, 0x100),
- RSND_GEN_M_REG(CTU_SV30R, 0x578, 0x100),
- RSND_GEN_M_REG(CTU_SV31R, 0x57c, 0x100),
- RSND_GEN_M_REG(CTU_SV32R, 0x580, 0x100),
- RSND_GEN_M_REG(CTU_SV33R, 0x584, 0x100),
- RSND_GEN_M_REG(CTU_SV34R, 0x588, 0x100),
- RSND_GEN_M_REG(CTU_SV35R, 0x58c, 0x100),
- RSND_GEN_M_REG(CTU_SV36R, 0x590, 0x100),
- RSND_GEN_M_REG(CTU_SV37R, 0x594, 0x100),
- RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40),
- RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40),
- RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40),
- RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40),
- RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40),
- RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40),
- RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40),
- RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40),
- RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40),
- RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40),
- RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100),
- RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100),
- RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100),
- RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100),
- RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100),
- RSND_GEN_M_REG(DVC_VRCTR, 0xe18, 0x100),
- RSND_GEN_M_REG(DVC_VRPDR, 0xe1c, 0x100),
- RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100),
- RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100),
- RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100),
- RSND_GEN_M_REG(DVC_VOL2R, 0xe30, 0x100),
- RSND_GEN_M_REG(DVC_VOL3R, 0xe34, 0x100),
- RSND_GEN_M_REG(DVC_VOL4R, 0xe38, 0x100),
- RSND_GEN_M_REG(DVC_VOL5R, 0xe3c, 0x100),
- RSND_GEN_M_REG(DVC_VOL6R, 0xe40, 0x100),
- RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100),
- RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100),
- };
- static const struct rsnd_regmap_field_conf conf_adg[] = {
- RSND_GEN_S_REG(BRRA, 0x00),
- RSND_GEN_S_REG(BRRB, 0x04),
- RSND_GEN_S_REG(BRGCKR, 0x08),
- RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
- RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
- RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14),
- RSND_GEN_S_REG(DIV_EN, 0x30),
- RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34),
- RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38),
- RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c),
- RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40),
- RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44),
- RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48),
- RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c),
- RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50),
- RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54),
- RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58),
- RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c),
- };
- static const struct rsnd_regmap_field_conf conf_ssi[] = {
- RSND_GEN_M_REG(SSICR, 0x00, 0x40),
- RSND_GEN_M_REG(SSISR, 0x04, 0x40),
- RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
- RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40),
- RSND_GEN_M_REG(SSIWSR, 0x20, 0x40),
- };
- int ret_ssiu;
- int ret_scu;
- int ret_adg;
- int ret_ssi;
-
- ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, "ssiu", conf_ssiu);
- ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, "scu", conf_scu);
- ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG, "adg", conf_adg);
- ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, "ssi", conf_ssi);
- if (ret_ssiu < 0 ||
- ret_scu < 0 ||
- ret_adg < 0 ||
- ret_ssi < 0)
- return ret_ssiu | ret_scu | ret_adg | ret_ssi;
-
- return 0;
-}
-
-/*
- * Gen1
- */
-
-static int rsnd_gen1_probe(struct rsnd_priv *priv)
-{
- static const struct rsnd_regmap_field_conf conf_adg[] = {
- RSND_GEN_S_REG(BRRA, 0x00),
- RSND_GEN_S_REG(BRRB, 0x04),
- RSND_GEN_S_REG(BRGCKR, 0x08),
- RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
- RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
- };
- static const struct rsnd_regmap_field_conf conf_ssi[] = {
- RSND_GEN_M_REG(SSICR, 0x00, 0x40),
- RSND_GEN_M_REG(SSISR, 0x04, 0x40),
- RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
- RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40),
- RSND_GEN_M_REG(SSIWSR, 0x20, 0x40),
- };
- int ret_adg;
- int ret_ssi;
-
- ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, "adg", conf_adg);
- ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, "ssi", conf_ssi);
- if (ret_adg < 0 ||
- ret_ssi < 0)
- return ret_adg | ret_ssi;
-
- return 0;
-}
-
-/*
- * Gen
- */
-int rsnd_gen_probe(struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_gen *gen;
- int ret;
-
- gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
- if (!gen)
- return -ENOMEM;
-
- priv->gen = gen;
-
- ret = -ENODEV;
- if (rsnd_is_gen1(priv))
- ret = rsnd_gen1_probe(priv);
- else if (rsnd_is_gen2(priv) ||
- rsnd_is_gen3(priv))
- ret = rsnd_gen2_probe(priv);
- else if (rsnd_is_gen4(priv))
- ret = rsnd_gen4_probe(priv);
-
- if (ret < 0)
- dev_err(dev, "unknown generation R-Car sound device\n");
-
- return ret;
-}
diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c
deleted file mode 100644
index 1de0e085804c..000000000000
--- a/sound/soc/sh/rcar/mix.c
+++ /dev/null
@@ -1,360 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// mix.c
-//
-// Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-/*
- * CTUn MIXn
- * +------+ +------+
- * [SRC3 / SRC6] -> |CTU n0| -> [MIX n0| ->
- * [SRC4 / SRC9] -> |CTU n1| -> [MIX n1| ->
- * [SRC0 / SRC1] -> |CTU n2| -> [MIX n2| ->
- * [SRC2 / SRC5] -> |CTU n3| -> [MIX n3| ->
- * +------+ +------+
- *
- * ex)
- * DAI0 : playback = <&src0 &ctu02 &mix0 &dvc0 &ssi0>;
- * DAI1 : playback = <&src2 &ctu03 &mix0 &dvc0 &ssi0>;
- *
- * MIX Volume
- * amixer set "MIX",0 100% // DAI0 Volume
- * amixer set "MIX",1 100% // DAI1 Volume
- *
- * Volume Ramp
- * amixer set "MIX Ramp Up Rate" "0.125 dB/1 step"
- * amixer set "MIX Ramp Down Rate" "4 dB/1 step"
- * amixer set "MIX Ramp" on
- * aplay xxx.wav &
- * amixer set "MIX",0 80% // DAI0 Volume Down
- * amixer set "MIX",1 100% // DAI1 Volume Up
- */
-
-#include "rsnd.h"
-
-#define MIX_NAME_SIZE 16
-#define MIX_NAME "mix"
-
-struct rsnd_mix {
- struct rsnd_mod mod;
- struct rsnd_kctrl_cfg_s volumeA; /* MDBAR */
- struct rsnd_kctrl_cfg_s volumeB; /* MDBBR */
- struct rsnd_kctrl_cfg_s volumeC; /* MDBCR */
- struct rsnd_kctrl_cfg_s volumeD; /* MDBDR */
- struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */
- struct rsnd_kctrl_cfg_s rup; /* Ramp Rate Up */
- struct rsnd_kctrl_cfg_s rdw; /* Ramp Rate Down */
- u32 flags;
-};
-
-#define ONCE_KCTRL_INITIALIZED (1 << 0)
-#define HAS_VOLA (1 << 1)
-#define HAS_VOLB (1 << 2)
-#define HAS_VOLC (1 << 3)
-#define HAS_VOLD (1 << 4)
-
-#define VOL_MAX 0x3ff
-
-#define rsnd_mod_to_mix(_mod) \
- container_of((_mod), struct rsnd_mix, mod)
-
-#define rsnd_mix_get(priv, id) ((struct rsnd_mix *)(priv->mix) + id)
-#define rsnd_mix_nr(priv) ((priv)->mix_nr)
-#define for_each_rsnd_mix(pos, priv, i) \
- for ((i) = 0; \
- ((i) < rsnd_mix_nr(priv)) && \
- ((pos) = (struct rsnd_mix *)(priv)->mix + i); \
- i++)
-
-static void rsnd_mix_activation(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, MIX_SWRSR, 0);
- rsnd_mod_write(mod, MIX_SWRSR, 1);
-}
-
-static void rsnd_mix_halt(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, MIX_MIXIR, 1);
- rsnd_mod_write(mod, MIX_SWRSR, 0);
-}
-
-#define rsnd_mix_get_vol(mix, X) \
- rsnd_flags_has(mix, HAS_VOL##X) ? \
- (VOL_MAX - rsnd_kctrl_vals(mix->volume##X)) : 0
-static void rsnd_mix_volume_parameter(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mix *mix = rsnd_mod_to_mix(mod);
- u32 volA = rsnd_mix_get_vol(mix, A);
- u32 volB = rsnd_mix_get_vol(mix, B);
- u32 volC = rsnd_mix_get_vol(mix, C);
- u32 volD = rsnd_mix_get_vol(mix, D);
-
- dev_dbg(dev, "MIX A/B/C/D = %02x/%02x/%02x/%02x\n",
- volA, volB, volC, volD);
-
- rsnd_mod_write(mod, MIX_MDBAR, volA);
- rsnd_mod_write(mod, MIX_MDBBR, volB);
- rsnd_mod_write(mod, MIX_MDBCR, volC);
- rsnd_mod_write(mod, MIX_MDBDR, volD);
-}
-
-static void rsnd_mix_volume_init(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_mix *mix = rsnd_mod_to_mix(mod);
-
- rsnd_mod_write(mod, MIX_MIXIR, 1);
-
- /* General Information */
- rsnd_mod_write(mod, MIX_ADINR, rsnd_runtime_channel_after_ctu(io));
-
- /* volume step */
- rsnd_mod_write(mod, MIX_MIXMR, rsnd_kctrl_vals(mix->ren));
- rsnd_mod_write(mod, MIX_MVPDR, rsnd_kctrl_vals(mix->rup) << 8 |
- rsnd_kctrl_vals(mix->rdw));
-
- /* common volume parameter */
- rsnd_mix_volume_parameter(io, mod);
-
- rsnd_mod_write(mod, MIX_MIXIR, 0);
-}
-
-static void rsnd_mix_volume_update(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- /* Disable MIX dB setting */
- rsnd_mod_write(mod, MIX_MDBER, 0);
-
- /* common volume parameter */
- rsnd_mix_volume_parameter(io, mod);
-
- /* Enable MIX dB setting */
- rsnd_mod_write(mod, MIX_MDBER, 1);
-}
-
-static int rsnd_mix_probe_(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- return rsnd_cmd_attach(io, rsnd_mod_id(mod));
-}
-
-static int rsnd_mix_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- ret = rsnd_mod_power_on(mod);
- if (ret < 0)
- return ret;
-
- rsnd_mix_activation(mod);
-
- rsnd_mix_volume_init(io, mod);
-
- rsnd_mix_volume_update(io, mod);
-
- return 0;
-}
-
-static int rsnd_mix_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_mix_halt(mod);
-
- rsnd_mod_power_off(mod);
-
- return 0;
-}
-
-static int rsnd_mix_pcm_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mix *mix = rsnd_mod_to_mix(mod);
- struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
- struct rsnd_kctrl_cfg_s *volume;
- int ret;
-
- switch (rsnd_mod_id(src_mod)) {
- case 3:
- case 6: /* MDBAR */
- volume = &mix->volumeA;
- rsnd_flags_set(mix, HAS_VOLA);
- break;
- case 4:
- case 9: /* MDBBR */
- volume = &mix->volumeB;
- rsnd_flags_set(mix, HAS_VOLB);
- break;
- case 0:
- case 1: /* MDBCR */
- volume = &mix->volumeC;
- rsnd_flags_set(mix, HAS_VOLC);
- break;
- case 2:
- case 5: /* MDBDR */
- volume = &mix->volumeD;
- rsnd_flags_set(mix, HAS_VOLD);
- break;
- default:
- dev_err(dev, "unknown SRC is connected\n");
- return -EINVAL;
- }
-
- /* Volume */
- ret = rsnd_kctrl_new_s(mod, io, rtd,
- "MIX Playback Volume",
- rsnd_kctrl_accept_anytime,
- rsnd_mix_volume_update,
- volume, VOL_MAX);
- if (ret < 0)
- return ret;
- rsnd_kctrl_vals(*volume) = VOL_MAX;
-
- if (rsnd_flags_has(mix, ONCE_KCTRL_INITIALIZED))
- return ret;
-
- /* Ramp */
- ret = rsnd_kctrl_new_s(mod, io, rtd,
- "MIX Ramp Switch",
- rsnd_kctrl_accept_anytime,
- rsnd_mix_volume_update,
- &mix->ren, 1);
- if (ret < 0)
- return ret;
-
- ret = rsnd_kctrl_new_e(mod, io, rtd,
- "MIX Ramp Up Rate",
- rsnd_kctrl_accept_anytime,
- rsnd_mix_volume_update,
- &mix->rup,
- volume_ramp_rate,
- VOLUME_RAMP_MAX_MIX);
- if (ret < 0)
- return ret;
-
- ret = rsnd_kctrl_new_e(mod, io, rtd,
- "MIX Ramp Down Rate",
- rsnd_kctrl_accept_anytime,
- rsnd_mix_volume_update,
- &mix->rdw,
- volume_ramp_rate,
- VOLUME_RAMP_MAX_MIX);
-
- rsnd_flags_set(mix, ONCE_KCTRL_INITIALIZED);
-
- return ret;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_mix_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0xd00 + rsnd_mod_id(mod) * 0x40, 0x30);
-}
-#define DEBUG_INFO .debug_info = rsnd_mix_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_mix_ops = {
- .name = MIX_NAME,
- .probe = rsnd_mix_probe_,
- .init = rsnd_mix_init,
- .quit = rsnd_mix_quit,
- .pcm_new = rsnd_mix_pcm_new,
- .get_status = rsnd_mod_get_status,
- DEBUG_INFO
-};
-
-struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv)))
- id = 0;
-
- return rsnd_mod_get(rsnd_mix_get(priv, id));
-}
-
-int rsnd_mix_probe(struct rsnd_priv *priv)
-{
- struct device_node *node;
- struct device_node *np;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mix *mix;
- struct clk *clk;
- char name[MIX_NAME_SIZE];
- int i, nr, ret;
-
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
- node = rsnd_mix_of_node(priv);
- if (!node)
- return 0; /* not used is not error */
-
- nr = of_get_child_count(node);
- if (!nr) {
- ret = -EINVAL;
- goto rsnd_mix_probe_done;
- }
-
- mix = devm_kcalloc(dev, nr, sizeof(*mix), GFP_KERNEL);
- if (!mix) {
- ret = -ENOMEM;
- goto rsnd_mix_probe_done;
- }
-
- priv->mix_nr = nr;
- priv->mix = mix;
-
- i = 0;
- ret = 0;
- for_each_child_of_node(node, np) {
- mix = rsnd_mix_get(priv, i);
-
- snprintf(name, MIX_NAME_SIZE, "%s.%d",
- MIX_NAME, i);
-
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- of_node_put(np);
- goto rsnd_mix_probe_done;
- }
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops,
- clk, RSND_MOD_MIX, i);
- if (ret) {
- of_node_put(np);
- goto rsnd_mix_probe_done;
- }
-
- i++;
- }
-
-rsnd_mix_probe_done:
- of_node_put(node);
-
- return ret;
-}
-
-void rsnd_mix_remove(struct rsnd_priv *priv)
-{
- struct rsnd_mix *mix;
- int i;
-
- for_each_rsnd_mix(mix, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(mix));
- }
-}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
deleted file mode 100644
index da716b1f52e4..000000000000
--- a/sound/soc/sh/rcar/rsnd.h
+++ /dev/null
@@ -1,916 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car
-//
-// Copyright (C) 2013 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-#ifndef RSND_H
-#define RSND_H
-
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/sh_dma.h>
-#include <linux/workqueue.h>
-#include <sound/soc.h>
-#include <sound/pcm_params.h>
-
-#define RSND_GEN1_SRU 0
-#define RSND_GEN1_ADG 1
-#define RSND_GEN1_SSI 2
-
-#define RSND_GEN2_SCU 0
-#define RSND_GEN2_ADG 1
-#define RSND_GEN2_SSIU 2
-#define RSND_GEN2_SSI 3
-
-#define RSND_GEN4_ADG 0
-#define RSND_GEN4_SSIU 1
-#define RSND_GEN4_SSI 2
-#define RSND_GEN4_SDMC 3
-
-#define RSND_BASE_MAX 4
-
-/*
- * pseudo register
- *
- * The register address offsets SRU/SCU/SSIU on Gen1/Gen2 are very different.
- * This driver uses pseudo register in order to hide it.
- * see gen1/gen2 for detail
- */
-enum rsnd_reg {
- /* SCU (MIX/CTU/DVC) */
- SRC_I_BUSIF_MODE,
- SRC_O_BUSIF_MODE,
- SRC_ROUTE_MODE0,
- SRC_SWRSR,
- SRC_SRCIR,
- SRC_ADINR,
- SRC_IFSCR,
- SRC_IFSVR,
- SRC_SRCCR,
- SRC_CTRL,
- SRC_BSDSR,
- SRC_BSISR,
- SRC_INT_ENABLE0,
- SRC_BUSIF_DALIGN,
- SRCIN_TIMSEL0,
- SRCIN_TIMSEL1,
- SRCIN_TIMSEL2,
- SRCIN_TIMSEL3,
- SRCIN_TIMSEL4,
- SRCOUT_TIMSEL0,
- SRCOUT_TIMSEL1,
- SRCOUT_TIMSEL2,
- SRCOUT_TIMSEL3,
- SRCOUT_TIMSEL4,
- SCU_SYS_STATUS0,
- SCU_SYS_STATUS1,
- SCU_SYS_INT_EN0,
- SCU_SYS_INT_EN1,
- CMD_CTRL,
- CMD_BUSIF_MODE,
- CMD_BUSIF_DALIGN,
- CMD_ROUTE_SLCT,
- CMDOUT_TIMSEL,
- CTU_SWRSR,
- CTU_CTUIR,
- CTU_ADINR,
- CTU_CPMDR,
- CTU_SCMDR,
- CTU_SV00R,
- CTU_SV01R,
- CTU_SV02R,
- CTU_SV03R,
- CTU_SV04R,
- CTU_SV05R,
- CTU_SV06R,
- CTU_SV07R,
- CTU_SV10R,
- CTU_SV11R,
- CTU_SV12R,
- CTU_SV13R,
- CTU_SV14R,
- CTU_SV15R,
- CTU_SV16R,
- CTU_SV17R,
- CTU_SV20R,
- CTU_SV21R,
- CTU_SV22R,
- CTU_SV23R,
- CTU_SV24R,
- CTU_SV25R,
- CTU_SV26R,
- CTU_SV27R,
- CTU_SV30R,
- CTU_SV31R,
- CTU_SV32R,
- CTU_SV33R,
- CTU_SV34R,
- CTU_SV35R,
- CTU_SV36R,
- CTU_SV37R,
- MIX_SWRSR,
- MIX_MIXIR,
- MIX_ADINR,
- MIX_MIXMR,
- MIX_MVPDR,
- MIX_MDBAR,
- MIX_MDBBR,
- MIX_MDBCR,
- MIX_MDBDR,
- MIX_MDBER,
- DVC_SWRSR,
- DVC_DVUIR,
- DVC_ADINR,
- DVC_DVUCR,
- DVC_ZCMCR,
- DVC_VOL0R,
- DVC_VOL1R,
- DVC_VOL2R,
- DVC_VOL3R,
- DVC_VOL4R,
- DVC_VOL5R,
- DVC_VOL6R,
- DVC_VOL7R,
- DVC_DVUER,
- DVC_VRCTR,
- DVC_VRPDR,
- DVC_VRDBR,
-
- /* ADG */
- BRRA,
- BRRB,
- BRGCKR,
- DIV_EN,
- AUDIO_CLK_SEL0,
- AUDIO_CLK_SEL1,
- AUDIO_CLK_SEL2,
-
- /* SSIU */
- SSI_MODE,
- SSI_MODE0,
- SSI_MODE1,
- SSI_MODE2,
- SSI_CONTROL,
- SSI_CTRL,
- SSI_BUSIF0_MODE,
- SSI_BUSIF1_MODE,
- SSI_BUSIF2_MODE,
- SSI_BUSIF3_MODE,
- SSI_BUSIF4_MODE,
- SSI_BUSIF5_MODE,
- SSI_BUSIF6_MODE,
- SSI_BUSIF7_MODE,
- SSI_BUSIF0_ADINR,
- SSI_BUSIF1_ADINR,
- SSI_BUSIF2_ADINR,
- SSI_BUSIF3_ADINR,
- SSI_BUSIF4_ADINR,
- SSI_BUSIF5_ADINR,
- SSI_BUSIF6_ADINR,
- SSI_BUSIF7_ADINR,
- SSI_BUSIF0_DALIGN,
- SSI_BUSIF1_DALIGN,
- SSI_BUSIF2_DALIGN,
- SSI_BUSIF3_DALIGN,
- SSI_BUSIF4_DALIGN,
- SSI_BUSIF5_DALIGN,
- SSI_BUSIF6_DALIGN,
- SSI_BUSIF7_DALIGN,
- SSI_INT_ENABLE,
- SSI_SYS_STATUS0,
- SSI_SYS_STATUS1,
- SSI_SYS_STATUS2,
- SSI_SYS_STATUS3,
- SSI_SYS_STATUS4,
- SSI_SYS_STATUS5,
- SSI_SYS_STATUS6,
- SSI_SYS_STATUS7,
- SSI_SYS_INT_ENABLE0,
- SSI_SYS_INT_ENABLE1,
- SSI_SYS_INT_ENABLE2,
- SSI_SYS_INT_ENABLE3,
- SSI_SYS_INT_ENABLE4,
- SSI_SYS_INT_ENABLE5,
- SSI_SYS_INT_ENABLE6,
- SSI_SYS_INT_ENABLE7,
- SSI_BUSIF,
- HDMI0_SEL,
- HDMI1_SEL,
- SSI9_BUSIF0_MODE,
- SSI9_BUSIF1_MODE,
- SSI9_BUSIF2_MODE,
- SSI9_BUSIF3_MODE,
- SSI9_BUSIF4_MODE,
- SSI9_BUSIF5_MODE,
- SSI9_BUSIF6_MODE,
- SSI9_BUSIF7_MODE,
- SSI9_BUSIF0_ADINR,
- SSI9_BUSIF1_ADINR,
- SSI9_BUSIF2_ADINR,
- SSI9_BUSIF3_ADINR,
- SSI9_BUSIF4_ADINR,
- SSI9_BUSIF5_ADINR,
- SSI9_BUSIF6_ADINR,
- SSI9_BUSIF7_ADINR,
- SSI9_BUSIF0_DALIGN,
- SSI9_BUSIF1_DALIGN,
- SSI9_BUSIF2_DALIGN,
- SSI9_BUSIF3_DALIGN,
- SSI9_BUSIF4_DALIGN,
- SSI9_BUSIF5_DALIGN,
- SSI9_BUSIF6_DALIGN,
- SSI9_BUSIF7_DALIGN,
-
- /* SSI */
- SSICR,
- SSISR,
- SSITDR,
- SSIRDR,
- SSIWSR,
-
- REG_MAX,
-};
-#define SRCIN_TIMSEL(i) (SRCIN_TIMSEL0 + (i))
-#define SRCOUT_TIMSEL(i) (SRCOUT_TIMSEL0 + (i))
-#define CTU_SVxxR(i, j) (CTU_SV00R + (i * 8) + (j))
-#define DVC_VOLxR(i) (DVC_VOL0R + (i))
-#define AUDIO_CLK_SEL(i) (AUDIO_CLK_SEL0 + (i))
-#define SSI_BUSIF_MODE(i) (SSI_BUSIF0_MODE + (i))
-#define SSI_BUSIF_ADINR(i) (SSI_BUSIF0_ADINR + (i))
-#define SSI_BUSIF_DALIGN(i) (SSI_BUSIF0_DALIGN + (i))
-#define SSI9_BUSIF_MODE(i) (SSI9_BUSIF0_MODE + (i))
-#define SSI9_BUSIF_ADINR(i) (SSI9_BUSIF0_ADINR + (i))
-#define SSI9_BUSIF_DALIGN(i) (SSI9_BUSIF0_DALIGN + (i))
-#define SSI_SYS_STATUS(i) (SSI_SYS_STATUS0 + (i))
-#define SSI_SYS_INT_ENABLE(i) (SSI_SYS_INT_ENABLE0 + (i))
-
-
-struct rsnd_priv;
-struct rsnd_mod;
-struct rsnd_dai;
-struct rsnd_dai_stream;
-
-/*
- * R-Car basic functions
- */
-u32 rsnd_mod_read(struct rsnd_mod *mod, enum rsnd_reg reg);
-void rsnd_mod_write(struct rsnd_mod *mod, enum rsnd_reg reg, u32 data);
-void rsnd_mod_bset(struct rsnd_mod *mod, enum rsnd_reg reg, u32 mask, u32 data);
-u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
-u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
-u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
-
-/*
- * R-Car DMA
- */
-int rsnd_dma_attach(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
-int rsnd_dma_probe(struct rsnd_priv *priv);
-struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, char *name,
- struct rsnd_mod *mod, char *x);
-
-/*
- * R-Car sound mod
- */
-enum rsnd_mod_type {
- RSND_MOD_AUDMAPP,
- RSND_MOD_AUDMA,
- RSND_MOD_DVC,
- RSND_MOD_MIX,
- RSND_MOD_CTU,
- RSND_MOD_CMD,
- RSND_MOD_SRC,
- RSND_MOD_SSIM3, /* SSI multi 3 */
- RSND_MOD_SSIM2, /* SSI multi 2 */
- RSND_MOD_SSIM1, /* SSI multi 1 */
- RSND_MOD_SSIP, /* SSI parent */
- RSND_MOD_SSI,
- RSND_MOD_SSIU,
- RSND_MOD_MAX,
-};
-
-struct rsnd_mod_ops {
- char *name;
- struct dma_chan* (*dma_req)(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod);
- int (*probe)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*remove)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*init)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*quit)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*start)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*stop)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*irq)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv, int enable);
- int (*pcm_new)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd);
- int (*hw_params)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params);
- int (*pointer)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- snd_pcm_uframes_t *pointer);
- int (*fallback)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*prepare)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*cleanup)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv);
- int (*hw_free)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_pcm_substream *substream);
- u32 *(*get_status)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type);
- int (*id)(struct rsnd_mod *mod);
- int (*id_sub)(struct rsnd_mod *mod);
- int (*id_cmd)(struct rsnd_mod *mod);
-
-#ifdef CONFIG_DEBUG_FS
- void (*debug_info)(struct seq_file *m,
- struct rsnd_dai_stream *io, struct rsnd_mod *mod);
-#endif
-};
-
-struct rsnd_dai_stream;
-struct rsnd_mod {
- int id;
- enum rsnd_mod_type type;
- struct rsnd_mod_ops *ops;
- struct rsnd_priv *priv;
- struct clk *clk;
- u32 status;
-};
-/*
- * status
- *
- * 0xH000DCB0
- *
- * B 0: init 1: quit
- * C 0: start 1: stop
- * D 0: hw_params 1: hw_free
- *
- * H is always called (see __rsnd_mod_call)
- */
-#define __rsnd_mod_shift_init 4
-#define __rsnd_mod_shift_quit 4
-#define __rsnd_mod_shift_start 8
-#define __rsnd_mod_shift_stop 8
-#define __rsnd_mod_shift_hw_params 12
-#define __rsnd_mod_shift_hw_free 12
-#define __rsnd_mod_shift_probe 28 /* always called */
-#define __rsnd_mod_shift_remove 28 /* always called */
-#define __rsnd_mod_shift_irq 28 /* always called */
-#define __rsnd_mod_shift_pcm_new 28 /* always called */
-#define __rsnd_mod_shift_fallback 28 /* always called */
-#define __rsnd_mod_shift_pointer 28 /* always called */
-#define __rsnd_mod_shift_prepare 28 /* always called */
-#define __rsnd_mod_shift_cleanup 28 /* always called */
-
-#define __rsnd_mod_add_probe 0
-#define __rsnd_mod_add_remove 0
-#define __rsnd_mod_add_prepare 0
-#define __rsnd_mod_add_cleanup 0
-#define __rsnd_mod_add_init 1 /* needs protect */
-#define __rsnd_mod_add_quit -1 /* needs protect */
-#define __rsnd_mod_add_start 1 /* needs protect */
-#define __rsnd_mod_add_stop -1 /* needs protect */
-#define __rsnd_mod_add_hw_params 1 /* needs protect */
-#define __rsnd_mod_add_hw_free -1 /* needs protect */
-#define __rsnd_mod_add_irq 0
-#define __rsnd_mod_add_pcm_new 0
-#define __rsnd_mod_add_fallback 0
-#define __rsnd_mod_add_pointer 0
-
-#define __rsnd_mod_call_probe 0
-#define __rsnd_mod_call_remove 0
-#define __rsnd_mod_call_prepare 0
-#define __rsnd_mod_call_cleanup 0
-#define __rsnd_mod_call_init 0 /* needs protect */
-#define __rsnd_mod_call_quit 1 /* needs protect */
-#define __rsnd_mod_call_start 0 /* needs protect */
-#define __rsnd_mod_call_stop 1 /* needs protect */
-#define __rsnd_mod_call_hw_params 0 /* needs protect */
-#define __rsnd_mod_call_hw_free 1 /* needs protect */
-#define __rsnd_mod_call_irq 0
-#define __rsnd_mod_call_pcm_new 0
-#define __rsnd_mod_call_fallback 0
-#define __rsnd_mod_call_pointer 0
-
-#define rsnd_mod_to_priv(mod) ((mod)->priv)
-#define rsnd_mod_power_on(mod) clk_enable((mod)->clk)
-#define rsnd_mod_power_off(mod) clk_disable((mod)->clk)
-#define rsnd_mod_get(ip) (&(ip)->mod)
-
-int rsnd_mod_init(struct rsnd_priv *priv,
- struct rsnd_mod *mod,
- struct rsnd_mod_ops *ops,
- struct clk *clk,
- enum rsnd_mod_type type,
- int id);
-void rsnd_mod_quit(struct rsnd_mod *mod);
-struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod);
-void rsnd_mod_interrupt(struct rsnd_mod *mod,
- void (*callback)(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io));
-u32 *rsnd_mod_get_status(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type);
-int rsnd_mod_id(struct rsnd_mod *mod);
-int rsnd_mod_id_raw(struct rsnd_mod *mod);
-int rsnd_mod_id_sub(struct rsnd_mod *mod);
-char *rsnd_mod_name(struct rsnd_mod *mod);
-struct rsnd_mod *rsnd_mod_next(int *iterator,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type *array,
- int array_size);
-#define for_each_rsnd_mod(iterator, pos, io) \
- for (iterator = 0; \
- (pos = rsnd_mod_next(&iterator, io, NULL, 0)); iterator++)
-#define for_each_rsnd_mod_arrays(iterator, pos, io, array, size) \
- for (iterator = 0; \
- (pos = rsnd_mod_next(&iterator, io, array, size)); iterator++)
-#define for_each_rsnd_mod_array(iterator, pos, io, array) \
- for_each_rsnd_mod_arrays(iterator, pos, io, array, ARRAY_SIZE(array))
-
-void rsnd_parse_connect_common(struct rsnd_dai *rdai, char *name,
- struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id),
- struct device_node *node,
- struct device_node *playback,
- struct device_node *capture);
-int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name);
-int rsnd_node_fixed_index(struct device *dev, struct device_node *node, char *name, int idx);
-
-int rsnd_channel_normalization(int chan);
-#define rsnd_runtime_channel_original(io) \
- rsnd_runtime_channel_original_with_params(io, NULL)
-int rsnd_runtime_channel_original_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params);
-#define rsnd_runtime_channel_after_ctu(io) \
- rsnd_runtime_channel_after_ctu_with_params(io, NULL)
-int rsnd_runtime_channel_after_ctu_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params);
-#define rsnd_runtime_channel_for_ssi(io) \
- rsnd_runtime_channel_for_ssi_with_params(io, NULL)
-int rsnd_runtime_channel_for_ssi_with_params(struct rsnd_dai_stream *io,
- struct snd_pcm_hw_params *params);
-int rsnd_runtime_is_multi_ssi(struct rsnd_dai_stream *io);
-int rsnd_runtime_is_tdm(struct rsnd_dai_stream *io);
-int rsnd_runtime_is_tdm_split(struct rsnd_dai_stream *io);
-
-/*
- * DT
- */
-#define rsnd_parse_of_node(priv, node) \
- of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, node)
-#define RSND_NODE_DAI "rcar_sound,dai"
-#define RSND_NODE_SSI "rcar_sound,ssi"
-#define RSND_NODE_SSIU "rcar_sound,ssiu"
-#define RSND_NODE_SRC "rcar_sound,src"
-#define RSND_NODE_CTU "rcar_sound,ctu"
-#define RSND_NODE_MIX "rcar_sound,mix"
-#define RSND_NODE_DVC "rcar_sound,dvc"
-
-/*
- * R-Car sound DAI
- */
-#define RSND_DAI_NAME_SIZE 16
-struct rsnd_dai_stream {
- char name[RSND_DAI_NAME_SIZE];
- struct snd_pcm_substream *substream;
- struct rsnd_mod *mod[RSND_MOD_MAX];
- struct rsnd_mod *dma;
- struct rsnd_dai *rdai;
- struct device *dmac_dev; /* for IPMMU */
- u32 converted_rate; /* converted sampling rate */
- int converted_chan; /* converted channels */
- u32 parent_ssi_status;
- u32 flags;
-};
-
-/* flags */
-#define RSND_STREAM_HDMI0 (1 << 0) /* for HDMI0 */
-#define RSND_STREAM_HDMI1 (1 << 1) /* for HDMI1 */
-#define RSND_STREAM_TDM_SPLIT (1 << 2) /* for TDM split mode */
-#define RSND_HW_RULE_ERR (1 << 3) /* hw_rule error */
-
-#define rsnd_io_to_mod(io, i) ((i) < RSND_MOD_MAX ? (io)->mod[(i)] : NULL)
-#define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI)
-#define rsnd_io_to_mod_ssiu(io) rsnd_io_to_mod((io), RSND_MOD_SSIU)
-#define rsnd_io_to_mod_ssip(io) rsnd_io_to_mod((io), RSND_MOD_SSIP)
-#define rsnd_io_to_mod_src(io) rsnd_io_to_mod((io), RSND_MOD_SRC)
-#define rsnd_io_to_mod_ctu(io) rsnd_io_to_mod((io), RSND_MOD_CTU)
-#define rsnd_io_to_mod_mix(io) rsnd_io_to_mod((io), RSND_MOD_MIX)
-#define rsnd_io_to_mod_dvc(io) rsnd_io_to_mod((io), RSND_MOD_DVC)
-#define rsnd_io_to_mod_cmd(io) rsnd_io_to_mod((io), RSND_MOD_CMD)
-#define rsnd_io_to_rdai(io) ((io)->rdai)
-#define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io)))
-#define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io)
-#define rsnd_io_to_runtime(io) ((io)->substream ? \
- (io)->substream->runtime : NULL)
-#define rsnd_io_converted_rate(io) ((io)->converted_rate)
-#define rsnd_io_converted_chan(io) ((io)->converted_chan)
-int rsnd_io_is_working(struct rsnd_dai_stream *io);
-
-struct rsnd_dai {
- char name[RSND_DAI_NAME_SIZE];
- struct rsnd_dai_stream playback;
- struct rsnd_dai_stream capture;
- struct rsnd_priv *priv;
- struct snd_pcm_hw_constraint_list constraint;
- struct of_phandle_args dai_args;
-
- int max_channels; /* 2ch - 16ch */
- int ssi_lane; /* 1lane - 4lane */
- int chan_width; /* 16/24/32 bit width */
-
- unsigned int clk_master:1;
- unsigned int bit_clk_inv:1;
- unsigned int frm_clk_inv:1;
- unsigned int sys_delay:1;
- unsigned int data_alignment:1;
-};
-
-#define rsnd_rdai_nr(priv) ((priv)->rdai_nr)
-#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master)
-#define rsnd_rdai_to_priv(rdai) ((rdai)->priv)
-#define for_each_rsnd_dai(rdai, priv, i) \
- for (i = 0; \
- (i < rsnd_rdai_nr(priv)) && \
- ((rdai) = rsnd_rdai_get(priv, i)); \
- i++)
-
-struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id);
-
-#define rsnd_rdai_channels_set(rdai, max_channels) \
- rsnd_rdai_channels_ctrl(rdai, max_channels)
-#define rsnd_rdai_channels_get(rdai) \
- rsnd_rdai_channels_ctrl(rdai, 0)
-int rsnd_rdai_channels_ctrl(struct rsnd_dai *rdai,
- int max_channels);
-
-#define rsnd_rdai_ssi_lane_set(rdai, ssi_lane) \
- rsnd_rdai_ssi_lane_ctrl(rdai, ssi_lane)
-#define rsnd_rdai_ssi_lane_get(rdai) \
- rsnd_rdai_ssi_lane_ctrl(rdai, 0)
-int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai,
- int ssi_lane);
-
-#define rsnd_rdai_width_set(rdai, width) \
- rsnd_rdai_width_ctrl(rdai, width)
-#define rsnd_rdai_width_get(rdai) \
- rsnd_rdai_width_ctrl(rdai, 0)
-int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width);
-void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io);
-int rsnd_dai_connect(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type);
-
-/*
- * R-Car Gen1/Gen2
- */
-int rsnd_gen_probe(struct rsnd_priv *priv);
-void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
- struct rsnd_mod *mod,
- enum rsnd_reg reg);
-phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id);
-#ifdef CONFIG_DEBUG_FS
-void __iomem *rsnd_gen_get_base_addr(struct rsnd_priv *priv, int reg_id);
-#endif
-
-/*
- * R-Car ADG
- */
-int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate);
-int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod);
-int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate);
-int rsnd_adg_probe(struct rsnd_priv *priv);
-void rsnd_adg_remove(struct rsnd_priv *priv);
-int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,
- struct rsnd_dai_stream *io,
- unsigned int in_rate,
- unsigned int out_rate);
-int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
- struct rsnd_dai_stream *io);
-#define rsnd_adg_clk_enable(priv) rsnd_adg_clk_control(priv, 1)
-#define rsnd_adg_clk_disable(priv) rsnd_adg_clk_control(priv, 0)
-void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable);
-void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m);
-
-/*
- * R-Car sound priv
- */
-struct rsnd_priv {
-
- struct platform_device *pdev;
- spinlock_t lock;
- unsigned long flags;
-#define RSND_GEN_MASK (0xF << 0)
-#define RSND_GEN1 (1 << 0)
-#define RSND_GEN2 (2 << 0)
-#define RSND_GEN3 (3 << 0)
-#define RSND_GEN4 (4 << 0)
-#define RSND_SOC_MASK (0xFF << 4)
-#define RSND_SOC_E (1 << 4) /* E1/E2/E3 */
-
- /*
- * below value will be filled on rsnd_gen_probe()
- */
- void *gen;
-
- /*
- * below value will be filled on rsnd_adg_probe()
- */
- void *adg;
-
- /*
- * below value will be filled on rsnd_dma_probe()
- */
- void *dma;
-
- /*
- * below value will be filled on rsnd_ssi_probe()
- */
- void *ssi;
- int ssi_nr;
-
- /*
- * below value will be filled on rsnd_ssiu_probe()
- */
- void *ssiu;
- int ssiu_nr;
-
- /*
- * below value will be filled on rsnd_src_probe()
- */
- void *src;
- int src_nr;
-
- /*
- * below value will be filled on rsnd_ctu_probe()
- */
- void *ctu;
- int ctu_nr;
-
- /*
- * below value will be filled on rsnd_mix_probe()
- */
- void *mix;
- int mix_nr;
-
- /*
- * below value will be filled on rsnd_dvc_probe()
- */
- void *dvc;
- int dvc_nr;
-
- /*
- * below value will be filled on rsnd_cmd_probe()
- */
- void *cmd;
- int cmd_nr;
-
- /*
- * below value will be filled on rsnd_dai_probe()
- */
- struct snd_soc_dai_driver *daidrv;
- struct rsnd_dai *rdai;
- int rdai_nr;
-
-#define RSND_MAX_COMPONENT 3
- int component_dais[RSND_MAX_COMPONENT];
-};
-
-#define rsnd_priv_to_pdev(priv) ((priv)->pdev)
-#define rsnd_priv_to_dev(priv) (&(rsnd_priv_to_pdev(priv)->dev))
-
-#define rsnd_is_gen1(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN1)
-#define rsnd_is_gen2(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN2)
-#define rsnd_is_gen3(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN3)
-#define rsnd_is_gen4(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN4)
-#define rsnd_is_e3(priv) (((priv)->flags & \
- (RSND_GEN_MASK | RSND_SOC_MASK)) == \
- (RSND_GEN3 | RSND_SOC_E))
-
-#define rsnd_flags_has(p, f) ((p)->flags & (f))
-#define rsnd_flags_set(p, f) ((p)->flags |= (f))
-#define rsnd_flags_del(p, f) ((p)->flags &= ~(f))
-
-/*
- * rsnd_kctrl
- */
-struct rsnd_kctrl_cfg {
- unsigned int max;
- unsigned int size;
- u32 *val;
- const char * const *texts;
- int (*accept)(struct rsnd_dai_stream *io);
- void (*update)(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
- struct rsnd_dai_stream *io;
- struct snd_card *card;
- struct snd_kcontrol *kctrl;
- struct rsnd_mod *mod;
-};
-
-#define RSND_MAX_CHANNELS 8
-struct rsnd_kctrl_cfg_m {
- struct rsnd_kctrl_cfg cfg;
- u32 val[RSND_MAX_CHANNELS];
-};
-
-struct rsnd_kctrl_cfg_s {
- struct rsnd_kctrl_cfg cfg;
- u32 val;
-};
-#define rsnd_kctrl_size(x) ((x).cfg.size)
-#define rsnd_kctrl_max(x) ((x).cfg.max)
-#define rsnd_kctrl_valm(x, i) ((x).val[i]) /* = (x).cfg.val[i] */
-#define rsnd_kctrl_vals(x) ((x).val) /* = (x).cfg.val[0] */
-
-int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io);
-int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io);
-struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg);
-struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg);
-int rsnd_kctrl_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd,
- const unsigned char *name,
- int (*accept)(struct rsnd_dai_stream *io),
- void (*update)(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod),
- struct rsnd_kctrl_cfg *cfg,
- const char * const *texts,
- int size,
- u32 max);
-
-#define rsnd_kctrl_new_m(mod, io, rtd, name, accept, update, cfg, size, max) \
- rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_m(cfg), \
- NULL, size, max)
-
-#define rsnd_kctrl_new_s(mod, io, rtd, name, accept, update, cfg, max) \
- rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_s(cfg), \
- NULL, 1, max)
-
-#define rsnd_kctrl_new_e(mod, io, rtd, name, accept, update, cfg, texts, size) \
- rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_s(cfg), \
- texts, 1, size)
-
-extern const char * const volume_ramp_rate[];
-#define VOLUME_RAMP_MAX_DVC (0x17 + 1)
-#define VOLUME_RAMP_MAX_MIX (0x0a + 1)
-
-/*
- * R-Car SSI
- */
-int rsnd_ssi_probe(struct rsnd_priv *priv);
-void rsnd_ssi_remove(struct rsnd_priv *priv);
-struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
-int rsnd_ssi_use_busif(struct rsnd_dai_stream *io);
-u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io);
-int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
-
-#define rsnd_ssi_is_pin_sharing(io) \
- __rsnd_ssi_is_pin_sharing(rsnd_io_to_mod_ssi(io))
-int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
-
-#define rsnd_ssi_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_SSI)
-void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
- struct device_node *playback,
- struct device_node *capture);
-unsigned int rsnd_ssi_clk_query(struct rsnd_dai *rdai,
- int param1, int param2, int *idx);
-
-/*
- * R-Car SSIU
- */
-int rsnd_ssiu_attach(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod);
-int rsnd_ssiu_probe(struct rsnd_priv *priv);
-void rsnd_ssiu_remove(struct rsnd_priv *priv);
-void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
- struct device_node *playback,
- struct device_node *capture);
-#define rsnd_ssiu_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_SSIU)
-bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod);
-
-/*
- * R-Car SRC
- */
-int rsnd_src_probe(struct rsnd_priv *priv);
-void rsnd_src_remove(struct rsnd_priv *priv);
-struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
-
-#define rsnd_src_get_in_rate(priv, io) rsnd_src_get_rate(priv, io, 1)
-#define rsnd_src_get_out_rate(priv, io) rsnd_src_get_rate(priv, io, 0)
-unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- int is_in);
-
-#define rsnd_src_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_SRC)
-#define rsnd_parse_connect_src(rdai, playback, capture) \
- rsnd_parse_connect_common(rdai, "src", rsnd_src_mod_get, \
- rsnd_src_of_node(rsnd_rdai_to_priv(rdai)), \
- playback, capture)
-
-/*
- * R-Car CTU
- */
-int rsnd_ctu_probe(struct rsnd_priv *priv);
-void rsnd_ctu_remove(struct rsnd_priv *priv);
-struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id);
-#define rsnd_ctu_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_CTU)
-#define rsnd_parse_connect_ctu(rdai, playback, capture) \
- rsnd_parse_connect_common(rdai, "ctu", rsnd_ctu_mod_get, \
- rsnd_ctu_of_node(rsnd_rdai_to_priv(rdai)), \
- playback, capture)
-
-/*
- * R-Car MIX
- */
-int rsnd_mix_probe(struct rsnd_priv *priv);
-void rsnd_mix_remove(struct rsnd_priv *priv);
-struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id);
-#define rsnd_mix_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_MIX)
-#define rsnd_parse_connect_mix(rdai, playback, capture) \
- rsnd_parse_connect_common(rdai, "mix", rsnd_mix_mod_get, \
- rsnd_mix_of_node(rsnd_rdai_to_priv(rdai)), \
- playback, capture)
-
-/*
- * R-Car DVC
- */
-int rsnd_dvc_probe(struct rsnd_priv *priv);
-void rsnd_dvc_remove(struct rsnd_priv *priv);
-struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id);
-#define rsnd_dvc_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_DVC)
-#define rsnd_parse_connect_dvc(rdai, playback, capture) \
- rsnd_parse_connect_common(rdai, "dvc", rsnd_dvc_mod_get, \
- rsnd_dvc_of_node(rsnd_rdai_to_priv(rdai)), \
- playback, capture)
-
-/*
- * R-Car CMD
- */
-int rsnd_cmd_probe(struct rsnd_priv *priv);
-void rsnd_cmd_remove(struct rsnd_priv *priv);
-int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id);
-
-void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type);
-#ifdef DEBUG
-#define rsnd_mod_confirm_ssi(mssi) rsnd_mod_make_sure(mssi, RSND_MOD_SSI)
-#define rsnd_mod_confirm_src(msrc) rsnd_mod_make_sure(msrc, RSND_MOD_SRC)
-#define rsnd_mod_confirm_dvc(mdvc) rsnd_mod_make_sure(mdvc, RSND_MOD_DVC)
-#else
-#define rsnd_mod_confirm_ssi(mssi)
-#define rsnd_mod_confirm_src(msrc)
-#define rsnd_mod_confirm_dvc(mdvc)
-#endif
-
-/*
- * If you don't need interrupt status debug message,
- * define RSND_DEBUG_NO_IRQ_STATUS as 1 on top of src.c/ssi.c
- *
- * #define RSND_DEBUG_NO_IRQ_STATUS 1
- */
-#define rsnd_print_irq_status(dev, param...) do { \
- if (!IS_BUILTIN(RSND_DEBUG_NO_IRQ_STATUS)) \
- dev_info(dev, param); \
-} while (0)
-
-#ifdef CONFIG_DEBUG_FS
-int rsnd_debugfs_probe(struct snd_soc_component *component);
-void rsnd_debugfs_reg_show(struct seq_file *m, phys_addr_t _addr,
- void __iomem *base, int offset, int size);
-void rsnd_debugfs_mod_reg_show(struct seq_file *m, struct rsnd_mod *mod,
- int reg_id, int offset, int size);
-
-#else
-#define rsnd_debugfs_probe NULL
-#endif
-
-#endif /* RSND_H */
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
deleted file mode 100644
index 3241a1bdc9ea..000000000000
--- a/sound/soc/sh/rcar/src.c
+++ /dev/null
@@ -1,736 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car SRC support
-//
-// Copyright (C) 2013 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-/*
- * You can use Synchronous Sampling Rate Convert (if no DVC)
- *
- * amixer set "SRC Out Rate" on
- * aplay xxx.wav &
- * amixer set "SRC Out Rate" 96000 // convert rate to 96000Hz
- * amixer set "SRC Out Rate" 22050 // convert rate to 22050Hz
- */
-
-/*
- * you can enable below define if you don't need
- * SSI interrupt status debug message when debugging
- * see rsnd_print_irq_status()
- *
- * #define RSND_DEBUG_NO_IRQ_STATUS 1
- */
-
-#include <linux/of_irq.h>
-#include "rsnd.h"
-
-#define SRC_NAME "src"
-
-/* SCU_SYSTEM_STATUS0/1 */
-#define OUF_SRC(id) ((1 << (id + 16)) | (1 << id))
-
-struct rsnd_src {
- struct rsnd_mod mod;
- struct rsnd_mod *dma;
- struct rsnd_kctrl_cfg_s sen; /* sync convert enable */
- struct rsnd_kctrl_cfg_s sync; /* sync convert */
- int irq;
-};
-
-#define RSND_SRC_NAME_SIZE 16
-
-#define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id)
-#define rsnd_src_nr(priv) ((priv)->src_nr)
-#define rsnd_src_sync_is_enabled(mod) (rsnd_mod_to_src(mod)->sen.val)
-
-#define rsnd_mod_to_src(_mod) \
- container_of((_mod), struct rsnd_src, mod)
-
-#define for_each_rsnd_src(pos, priv, i) \
- for ((i) = 0; \
- ((i) < rsnd_src_nr(priv)) && \
- ((pos) = (struct rsnd_src *)(priv)->src + i); \
- i++)
-
-
-/*
- * image of SRC (Sampling Rate Converter)
- *
- * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+
- * 48kHz <-> | SRC | <------> | SSI | <-----> | codec |
- * 44.1kHz <-> +-----+ +-----+ +-------+
- * ...
- *
- */
-
-static void rsnd_src_activation(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, SRC_SWRSR, 0);
- rsnd_mod_write(mod, SRC_SWRSR, 1);
-}
-
-static void rsnd_src_halt(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, SRC_SRCIR, 1);
- rsnd_mod_write(mod, SRC_SWRSR, 0);
-}
-
-static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- int is_play = rsnd_io_is_play(io);
-
- return rsnd_dma_request_channel(rsnd_src_of_node(priv),
- SRC_NAME, mod,
- is_play ? "rx" : "tx");
-}
-
-static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- u32 convert_rate;
-
- if (!runtime)
- return 0;
-
- if (!rsnd_src_sync_is_enabled(mod))
- return rsnd_io_converted_rate(io);
-
- convert_rate = src->sync.val;
-
- if (!convert_rate)
- convert_rate = rsnd_io_converted_rate(io);
-
- if (!convert_rate)
- convert_rate = runtime->rate;
-
- return convert_rate;
-}
-
-unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- int is_in)
-{
- struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- unsigned int rate = 0;
- int is_play = rsnd_io_is_play(io);
-
- /*
- * Playback
- * runtime_rate -> [SRC] -> convert_rate
- *
- * Capture
- * convert_rate -> [SRC] -> runtime_rate
- */
-
- if (is_play == is_in)
- return runtime->rate;
-
- /*
- * return convert rate if SRC is used,
- * otherwise, return runtime->rate as usual
- */
- if (src_mod)
- rate = rsnd_src_convert_rate(io, src_mod);
-
- if (!rate)
- rate = runtime->rate;
-
- return rate;
-}
-
-static const u32 bsdsr_table_pattern1[] = {
- 0x01800000, /* 6 - 1/6 */
- 0x01000000, /* 6 - 1/4 */
- 0x00c00000, /* 6 - 1/3 */
- 0x00800000, /* 6 - 1/2 */
- 0x00600000, /* 6 - 2/3 */
- 0x00400000, /* 6 - 1 */
-};
-
-static const u32 bsdsr_table_pattern2[] = {
- 0x02400000, /* 6 - 1/6 */
- 0x01800000, /* 6 - 1/4 */
- 0x01200000, /* 6 - 1/3 */
- 0x00c00000, /* 6 - 1/2 */
- 0x00900000, /* 6 - 2/3 */
- 0x00600000, /* 6 - 1 */
-};
-
-static const u32 bsisr_table[] = {
- 0x00100060, /* 6 - 1/6 */
- 0x00100040, /* 6 - 1/4 */
- 0x00100030, /* 6 - 1/3 */
- 0x00100020, /* 6 - 1/2 */
- 0x00100020, /* 6 - 2/3 */
- 0x00100020, /* 6 - 1 */
-};
-
-static const u32 chan288888[] = {
- 0x00000006, /* 1 to 2 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
-};
-
-static const u32 chan244888[] = {
- 0x00000006, /* 1 to 2 */
- 0x0000001e, /* 1 to 4 */
- 0x0000001e, /* 1 to 4 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
- 0x000001fe, /* 1 to 8 */
-};
-
-static const u32 chan222222[] = {
- 0x00000006, /* 1 to 2 */
- 0x00000006, /* 1 to 2 */
- 0x00000006, /* 1 to 2 */
- 0x00000006, /* 1 to 2 */
- 0x00000006, /* 1 to 2 */
- 0x00000006, /* 1 to 2 */
-};
-
-static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- int is_play = rsnd_io_is_play(io);
- int use_src = 0;
- u32 fin, fout;
- u32 ifscr, fsrate, adinr;
- u32 cr, route;
- u32 i_busif, o_busif, tmp;
- const u32 *bsdsr_table;
- const u32 *chptn;
- uint ratio;
- int chan;
- int idx;
-
- if (!runtime)
- return;
-
- fin = rsnd_src_get_in_rate(priv, io);
- fout = rsnd_src_get_out_rate(priv, io);
-
- chan = rsnd_runtime_channel_original(io);
-
- /* 6 - 1/6 are very enough ratio for SRC_BSDSR */
- if (fin == fout)
- ratio = 0;
- else if (fin > fout)
- ratio = 100 * fin / fout;
- else
- ratio = 100 * fout / fin;
-
- if (ratio > 600) {
- dev_err(dev, "FSO/FSI ratio error\n");
- return;
- }
-
- use_src = (fin != fout) | rsnd_src_sync_is_enabled(mod);
-
- /*
- * SRC_ADINR
- */
- adinr = rsnd_get_adinr_bit(mod, io) | chan;
-
- /*
- * SRC_IFSCR / SRC_IFSVR
- */
- ifscr = 0;
- fsrate = 0;
- if (use_src) {
- u64 n;
-
- ifscr = 1;
- n = (u64)0x0400000 * fin;
- do_div(n, fout);
- fsrate = n;
- }
-
- /*
- * SRC_SRCCR / SRC_ROUTE_MODE0
- */
- cr = 0x00011110;
- route = 0x0;
- if (use_src) {
- route = 0x1;
-
- if (rsnd_src_sync_is_enabled(mod)) {
- cr |= 0x1;
- route |= rsnd_io_is_play(io) ?
- (0x1 << 24) : (0x1 << 25);
- }
- }
-
- /*
- * SRC_BSDSR / SRC_BSISR
- *
- * see
- * Combination of Register Setting Related to
- * FSO/FSI Ratio and Channel, Latency
- */
- switch (rsnd_mod_id(mod)) {
- case 0:
- chptn = chan288888;
- bsdsr_table = bsdsr_table_pattern1;
- break;
- case 1:
- case 3:
- case 4:
- chptn = chan244888;
- bsdsr_table = bsdsr_table_pattern1;
- break;
- case 2:
- case 9:
- chptn = chan222222;
- bsdsr_table = bsdsr_table_pattern1;
- break;
- case 5:
- case 6:
- case 7:
- case 8:
- chptn = chan222222;
- bsdsr_table = bsdsr_table_pattern2;
- break;
- default:
- goto convert_rate_err;
- }
-
- /*
- * E3 need to overwrite
- */
- if (rsnd_is_e3(priv))
- switch (rsnd_mod_id(mod)) {
- case 0:
- case 4:
- chptn = chan222222;
- }
-
- for (idx = 0; idx < ARRAY_SIZE(chan222222); idx++)
- if (chptn[idx] & (1 << chan))
- break;
-
- if (chan > 8 ||
- idx >= ARRAY_SIZE(chan222222))
- goto convert_rate_err;
-
- /* BUSIF_MODE */
- tmp = rsnd_get_busif_shift(io, mod);
- i_busif = ( is_play ? tmp : 0) | 1;
- o_busif = (!is_play ? tmp : 0) | 1;
-
- rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
-
- rsnd_mod_write(mod, SRC_SRCIR, 1); /* initialize */
- rsnd_mod_write(mod, SRC_ADINR, adinr);
- rsnd_mod_write(mod, SRC_IFSCR, ifscr);
- rsnd_mod_write(mod, SRC_IFSVR, fsrate);
- rsnd_mod_write(mod, SRC_SRCCR, cr);
- rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]);
- rsnd_mod_write(mod, SRC_BSISR, bsisr_table[idx]);
- rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */
-
- rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif);
- rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif);
-
- rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
-
- rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
-
- return;
-
-convert_rate_err:
- dev_err(dev, "unknown BSDSR/BSDIR settings\n");
-}
-
-static int rsnd_src_irq(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv,
- int enable)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- u32 sys_int_val, int_val, sys_int_mask;
- int irq = src->irq;
- int id = rsnd_mod_id(mod);
-
- sys_int_val =
- sys_int_mask = OUF_SRC(id);
- int_val = 0x3300;
-
- /*
- * IRQ is not supported on non-DT
- * see
- * rsnd_src_probe_()
- */
- if ((irq <= 0) || !enable) {
- sys_int_val = 0;
- int_val = 0;
- }
-
- /*
- * WORKAROUND
- *
- * ignore over flow error when rsnd_src_sync_is_enabled()
- */
- if (rsnd_src_sync_is_enabled(mod))
- sys_int_val = sys_int_val & 0xffff;
-
- rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
- rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
- rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
-
- return 0;
-}
-
-static void rsnd_src_status_clear(struct rsnd_mod *mod)
-{
- u32 val = OUF_SRC(rsnd_mod_id(mod));
-
- rsnd_mod_write(mod, SCU_SYS_STATUS0, val);
- rsnd_mod_write(mod, SCU_SYS_STATUS1, val);
-}
-
-static bool rsnd_src_error_occurred(struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- u32 val0, val1;
- u32 status0, status1;
- bool ret = false;
-
- val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
-
- /*
- * WORKAROUND
- *
- * ignore over flow error when rsnd_src_sync_is_enabled()
- */
- if (rsnd_src_sync_is_enabled(mod))
- val0 = val0 & 0xffff;
-
- status0 = rsnd_mod_read(mod, SCU_SYS_STATUS0);
- status1 = rsnd_mod_read(mod, SCU_SYS_STATUS1);
- if ((status0 & val0) || (status1 & val1)) {
- rsnd_print_irq_status(dev, "%s err status : 0x%08x, 0x%08x\n",
- rsnd_mod_name(mod), status0, status1);
-
- ret = true;
- }
-
- return ret;
-}
-
-static int rsnd_src_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- u32 val;
-
- /*
- * WORKAROUND
- *
- * Enable SRC output if you want to use sync convert together with DVC
- */
- val = (rsnd_io_to_mod_dvc(io) && !rsnd_src_sync_is_enabled(mod)) ?
- 0x01 : 0x11;
-
- rsnd_mod_write(mod, SRC_CTRL, val);
-
- return 0;
-}
-
-static int rsnd_src_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_mod_write(mod, SRC_CTRL, 0);
-
- return 0;
-}
-
-static int rsnd_src_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- int ret;
-
- /* reset sync convert_rate */
- src->sync.val = 0;
-
- ret = rsnd_mod_power_on(mod);
- if (ret < 0)
- return ret;
-
- rsnd_src_activation(mod);
-
- rsnd_src_set_convert_rate(io, mod);
-
- rsnd_src_status_clear(mod);
-
- return 0;
-}
-
-static int rsnd_src_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
-
- rsnd_src_halt(mod);
-
- rsnd_mod_power_off(mod);
-
- /* reset sync convert_rate */
- src->sync.val = 0;
-
- return 0;
-}
-
-static void __rsnd_src_interrupt(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- bool stop = false;
-
- spin_lock(&priv->lock);
-
- /* ignore all cases if not working */
- if (!rsnd_io_is_working(io))
- goto rsnd_src_interrupt_out;
-
- if (rsnd_src_error_occurred(mod))
- stop = true;
-
- rsnd_src_status_clear(mod);
-rsnd_src_interrupt_out:
-
- spin_unlock(&priv->lock);
-
- if (stop)
- snd_pcm_stop_xrun(io->substream);
-}
-
-static irqreturn_t rsnd_src_interrupt(int irq, void *data)
-{
- struct rsnd_mod *mod = data;
-
- rsnd_mod_interrupt(mod, __rsnd_src_interrupt);
-
- return IRQ_HANDLED;
-}
-
-static int rsnd_src_probe_(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- int irq = src->irq;
- int ret;
-
- if (irq > 0) {
- /*
- * IRQ is not supported on non-DT
- * see
- * rsnd_src_irq()
- */
- ret = devm_request_irq(dev, irq,
- rsnd_src_interrupt,
- IRQF_SHARED,
- dev_name(dev), mod);
- if (ret)
- return ret;
- }
-
- ret = rsnd_dma_attach(io, mod, &src->dma);
-
- return ret;
-}
-
-static int rsnd_src_pcm_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- int ret;
-
- /*
- * enable SRC sync convert if possible
- */
-
- /*
- * It can't use SRC Synchronous convert
- * when Capture if it uses CMD
- */
- if (rsnd_io_to_mod_cmd(io) && !rsnd_io_is_play(io))
- return 0;
-
- /*
- * enable sync convert
- */
- ret = rsnd_kctrl_new_s(mod, io, rtd,
- rsnd_io_is_play(io) ?
- "SRC Out Rate Switch" :
- "SRC In Rate Switch",
- rsnd_kctrl_accept_anytime,
- rsnd_src_set_convert_rate,
- &src->sen, 1);
- if (ret < 0)
- return ret;
-
- ret = rsnd_kctrl_new_s(mod, io, rtd,
- rsnd_io_is_play(io) ?
- "SRC Out Rate" :
- "SRC In Rate",
- rsnd_kctrl_accept_runtime,
- rsnd_src_set_convert_rate,
- &src->sync, 192000);
-
- return ret;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_src_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- rsnd_mod_id(mod) * 0x20, 0x20);
- seq_puts(m, "\n");
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0x1c0, 0x20);
- seq_puts(m, "\n");
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
- 0x200 + rsnd_mod_id(mod) * 0x40, 0x40);
-}
-#define DEBUG_INFO .debug_info = rsnd_src_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_src_ops = {
- .name = SRC_NAME,
- .dma_req = rsnd_src_dma_req,
- .probe = rsnd_src_probe_,
- .init = rsnd_src_init,
- .quit = rsnd_src_quit,
- .start = rsnd_src_start,
- .stop = rsnd_src_stop,
- .irq = rsnd_src_irq,
- .pcm_new = rsnd_src_pcm_new,
- .get_status = rsnd_mod_get_status,
- DEBUG_INFO
-};
-
-struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
- id = 0;
-
- return rsnd_mod_get(rsnd_src_get(priv, id));
-}
-
-int rsnd_src_probe(struct rsnd_priv *priv)
-{
- struct device_node *node;
- struct device_node *np;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_src *src;
- struct clk *clk;
- char name[RSND_SRC_NAME_SIZE];
- int i, nr, ret;
-
- /* This driver doesn't support Gen1 at this point */
- if (rsnd_is_gen1(priv))
- return 0;
-
- node = rsnd_src_of_node(priv);
- if (!node)
- return 0; /* not used is not error */
-
- nr = rsnd_node_count(priv, node, SRC_NAME);
- if (!nr) {
- ret = -EINVAL;
- goto rsnd_src_probe_done;
- }
-
- src = devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL);
- if (!src) {
- ret = -ENOMEM;
- goto rsnd_src_probe_done;
- }
-
- priv->src_nr = nr;
- priv->src = src;
-
- i = 0;
- for_each_child_of_node(node, np) {
- if (!of_device_is_available(np))
- goto skip;
-
- i = rsnd_node_fixed_index(dev, np, SRC_NAME, i);
- if (i < 0) {
- ret = -EINVAL;
- of_node_put(np);
- goto rsnd_src_probe_done;
- }
-
- src = rsnd_src_get(priv, i);
-
- snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
- SRC_NAME, i);
-
- src->irq = irq_of_parse_and_map(np, 0);
- if (!src->irq) {
- ret = -EINVAL;
- of_node_put(np);
- goto rsnd_src_probe_done;
- }
-
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- of_node_put(np);
- goto rsnd_src_probe_done;
- }
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(src),
- &rsnd_src_ops, clk, RSND_MOD_SRC, i);
- if (ret) {
- of_node_put(np);
- goto rsnd_src_probe_done;
- }
-
-skip:
- i++;
- }
-
- ret = 0;
-
-rsnd_src_probe_done:
- of_node_put(node);
-
- return ret;
-}
-
-void rsnd_src_remove(struct rsnd_priv *priv)
-{
- struct rsnd_src *src;
- int i;
-
- for_each_rsnd_src(src, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(src));
- }
-}
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
deleted file mode 100644
index 0a46aa1975fa..000000000000
--- a/sound/soc/sh/rcar/ssi.c
+++ /dev/null
@@ -1,1260 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car SSIU/SSI support
-//
-// Copyright (C) 2013 Renesas Solutions Corp.
-// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-//
-// Based on fsi.c
-// Kuninori Morimoto <morimoto.kuninori@renesas.com>
-
-/*
- * you can enable below define if you don't need
- * SSI interrupt status debug message when debugging
- * see rsnd_print_irq_status()
- *
- * #define RSND_DEBUG_NO_IRQ_STATUS 1
- */
-
-#include <sound/simple_card_utils.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/delay.h>
-#include "rsnd.h"
-#define RSND_SSI_NAME_SIZE 16
-
-/*
- * SSICR
- */
-#define FORCE (1u << 31) /* Fixed */
-#define DMEN (1u << 28) /* DMA Enable */
-#define UIEN (1u << 27) /* Underflow Interrupt Enable */
-#define OIEN (1u << 26) /* Overflow Interrupt Enable */
-#define IIEN (1u << 25) /* Idle Mode Interrupt Enable */
-#define DIEN (1u << 24) /* Data Interrupt Enable */
-#define CHNL_4 (1u << 22) /* Channels */
-#define CHNL_6 (2u << 22) /* Channels */
-#define CHNL_8 (3u << 22) /* Channels */
-#define DWL_MASK (7u << 19) /* Data Word Length mask */
-#define DWL_8 (0u << 19) /* Data Word Length */
-#define DWL_16 (1u << 19) /* Data Word Length */
-#define DWL_18 (2u << 19) /* Data Word Length */
-#define DWL_20 (3u << 19) /* Data Word Length */
-#define DWL_22 (4u << 19) /* Data Word Length */
-#define DWL_24 (5u << 19) /* Data Word Length */
-#define DWL_32 (6u << 19) /* Data Word Length */
-
-/*
- * System word length
- */
-#define SWL_16 (1 << 16) /* R/W System Word Length */
-#define SWL_24 (2 << 16) /* R/W System Word Length */
-#define SWL_32 (3 << 16) /* R/W System Word Length */
-
-#define SCKD (1 << 15) /* Serial Bit Clock Direction */
-#define SWSD (1 << 14) /* Serial WS Direction */
-#define SCKP (1 << 13) /* Serial Bit Clock Polarity */
-#define SWSP (1 << 12) /* Serial WS Polarity */
-#define SDTA (1 << 10) /* Serial Data Alignment */
-#define PDTA (1 << 9) /* Parallel Data Alignment */
-#define DEL (1 << 8) /* Serial Data Delay */
-#define CKDV(v) (v << 4) /* Serial Clock Division Ratio */
-#define TRMD (1 << 1) /* Transmit/Receive Mode Select */
-#define EN (1 << 0) /* SSI Module Enable */
-
-/*
- * SSISR
- */
-#define UIRQ (1 << 27) /* Underflow Error Interrupt Status */
-#define OIRQ (1 << 26) /* Overflow Error Interrupt Status */
-#define IIRQ (1 << 25) /* Idle Mode Interrupt Status */
-#define DIRQ (1 << 24) /* Data Interrupt Status Flag */
-
-/*
- * SSIWSR
- */
-#define CONT (1 << 8) /* WS Continue Function */
-#define WS_MODE (1 << 0) /* WS Mode */
-
-#define SSI_NAME "ssi"
-
-struct rsnd_ssi {
- struct rsnd_mod mod;
-
- u32 flags;
- u32 cr_own;
- u32 cr_clk;
- u32 cr_mode;
- u32 cr_en;
- u32 wsr;
- int chan;
- int rate;
- int irq;
- unsigned int usrcnt;
-
- /* for PIO */
- int byte_pos;
- int byte_per_period;
- int next_period_byte;
-};
-
-/* flags */
-#define RSND_SSI_CLK_PIN_SHARE (1 << 0)
-#define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */
-#define RSND_SSI_PROBED (1 << 2)
-
-#define for_each_rsnd_ssi(pos, priv, i) \
- for (i = 0; \
- (i < rsnd_ssi_nr(priv)) && \
- ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \
- i++)
-
-#define rsnd_ssi_get(priv, id) ((struct rsnd_ssi *)(priv->ssi) + id)
-#define rsnd_ssi_nr(priv) ((priv)->ssi_nr)
-#define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
-#define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io))
-#define rsnd_ssi_is_multi_secondary(mod, io) \
- (rsnd_ssi_multi_secondaries(io) & (1 << rsnd_mod_id(mod)))
-#define rsnd_ssi_is_run_mods(mod, io) \
- (rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod)))
-#define rsnd_ssi_can_output_clk(mod) (!__rsnd_ssi_is_pin_sharing(mod))
-
-int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
-{
- struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- int use_busif = 0;
-
- if (!rsnd_ssi_is_dma_mode(mod))
- return 0;
-
- if (!(rsnd_flags_has(ssi, RSND_SSI_NO_BUSIF)))
- use_busif = 1;
- if (rsnd_io_to_mod_src(io))
- use_busif = 1;
-
- return use_busif;
-}
-
-static void rsnd_ssi_status_clear(struct rsnd_mod *mod)
-{
- rsnd_mod_write(mod, SSISR, 0);
-}
-
-static u32 rsnd_ssi_status_get(struct rsnd_mod *mod)
-{
- return rsnd_mod_read(mod, SSISR);
-}
-
-static void rsnd_ssi_status_check(struct rsnd_mod *mod,
- u32 bit)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- u32 status;
- int i;
-
- for (i = 0; i < 1024; i++) {
- status = rsnd_ssi_status_get(mod);
- if (status & bit)
- return;
-
- udelay(5);
- }
-
- dev_warn(dev, "%s status check failed\n", rsnd_mod_name(mod));
-}
-
-static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io)
-{
- static const enum rsnd_mod_type types[] = {
- RSND_MOD_SSIM1,
- RSND_MOD_SSIM2,
- RSND_MOD_SSIM3,
- };
- int i, mask;
-
- mask = 0;
- for (i = 0; i < ARRAY_SIZE(types); i++) {
- struct rsnd_mod *mod = rsnd_io_to_mod(io, types[i]);
-
- if (!mod)
- continue;
-
- mask |= 1 << rsnd_mod_id(mod);
- }
-
- return mask;
-}
-
-static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io)
-{
- struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
- u32 mods;
-
- mods = rsnd_ssi_multi_secondaries_runtime(io) |
- 1 << rsnd_mod_id(ssi_mod);
-
- if (ssi_parent_mod)
- mods |= 1 << rsnd_mod_id(ssi_parent_mod);
-
- return mods;
-}
-
-u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io)
-{
- if (rsnd_runtime_is_multi_ssi(io))
- return rsnd_ssi_multi_secondaries(io);
-
- return 0;
-}
-
-static u32 rsnd_rdai_width_to_swl(struct rsnd_dai *rdai)
-{
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
- int width = rsnd_rdai_width_get(rdai);
-
- switch (width) {
- case 32: return SWL_32;
- case 24: return SWL_24;
- case 16: return SWL_16;
- }
-
- dev_err(dev, "unsupported slot width value: %d\n", width);
- return 0;
-}
-
-unsigned int rsnd_ssi_clk_query(struct rsnd_dai *rdai,
- int param1, int param2, int *idx)
-{
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- static const int ssi_clk_mul_table[] = {
- 1, 2, 4, 8, 16, 6, 12,
- };
- int j, ret;
- unsigned int main_rate;
- int width = rsnd_rdai_width_get(rdai);
-
- for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) {
-
- /*
- * It will set SSIWSR.CONT here, but SSICR.CKDV = 000
- * with it is not allowed. (SSIWSR.WS_MODE with
- * SSICR.CKDV = 000 is not allowed either).
- * Skip it. See SSICR.CKDV
- */
- if (j == 0)
- continue;
-
- main_rate = width * param1 * param2 * ssi_clk_mul_table[j];
-
- ret = rsnd_adg_clk_query(priv, main_rate);
- if (ret < 0)
- continue;
-
- if (idx)
- *idx = j;
-
- return main_rate;
- }
-
- return 0;
-}
-
-static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- int chan = rsnd_runtime_channel_for_ssi(io);
- int idx, ret;
- unsigned int main_rate;
- unsigned int rate = rsnd_io_is_play(io) ?
- rsnd_src_get_out_rate(priv, io) :
- rsnd_src_get_in_rate(priv, io);
-
- if (!rsnd_rdai_is_clk_master(rdai))
- return 0;
-
- if (!rsnd_ssi_can_output_clk(mod))
- return 0;
-
- if (rsnd_ssi_is_multi_secondary(mod, io))
- return 0;
-
- if (rsnd_runtime_is_tdm_split(io))
- chan = rsnd_io_converted_chan(io);
-
- chan = rsnd_channel_normalization(chan);
-
- if (ssi->usrcnt > 0) {
- if (ssi->rate != rate) {
- dev_err(dev, "SSI parent/child should use same rate\n");
- return -EINVAL;
- }
-
- if (ssi->chan != chan) {
- dev_err(dev, "SSI parent/child should use same chan\n");
- return -EINVAL;
- }
-
- return 0;
- }
-
- ret = -EIO;
- main_rate = rsnd_ssi_clk_query(rdai, rate, chan, &idx);
- if (!main_rate)
- goto rate_err;
-
- ret = rsnd_adg_ssi_clk_try_start(mod, main_rate);
- if (ret < 0)
- goto rate_err;
-
- /*
- * SSI clock will be output contiguously
- * by below settings.
- * This means, rsnd_ssi_master_clk_start()
- * and rsnd_ssi_register_setup() are necessary
- * for SSI parent
- *
- * SSICR : FORCE, SCKD, SWSD
- * SSIWSR : CONT
- */
- ssi->cr_clk = FORCE | rsnd_rdai_width_to_swl(rdai) |
- SCKD | SWSD | CKDV(idx);
- ssi->wsr = CONT;
- ssi->rate = rate;
- ssi->chan = chan;
-
- dev_dbg(dev, "%s outputs %d chan %u Hz\n",
- rsnd_mod_name(mod), chan, rate);
-
- return 0;
-
-rate_err:
- dev_err(dev, "unsupported clock rate\n");
- return ret;
-}
-
-static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- if (!rsnd_rdai_is_clk_master(rdai))
- return;
-
- if (!rsnd_ssi_can_output_clk(mod))
- return;
-
- if (ssi->usrcnt > 1)
- return;
-
- ssi->cr_clk = 0;
- ssi->rate = 0;
- ssi->chan = 0;
-
- rsnd_adg_ssi_clk_stop(mod);
-}
-
-static void rsnd_ssi_config_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- u32 cr_own = ssi->cr_own;
- u32 cr_mode = ssi->cr_mode;
- u32 wsr = ssi->wsr;
- int width;
- int is_tdm, is_tdm_split;
-
- is_tdm = rsnd_runtime_is_tdm(io);
- is_tdm_split = rsnd_runtime_is_tdm_split(io);
-
- if (is_tdm)
- dev_dbg(dev, "TDM mode\n");
- if (is_tdm_split)
- dev_dbg(dev, "TDM Split mode\n");
-
- cr_own |= FORCE | rsnd_rdai_width_to_swl(rdai);
-
- if (rdai->bit_clk_inv)
- cr_own |= SCKP;
- if (rdai->frm_clk_inv && !is_tdm)
- cr_own |= SWSP;
- if (rdai->data_alignment)
- cr_own |= SDTA;
- if (rdai->sys_delay)
- cr_own |= DEL;
-
- /*
- * TDM Mode
- * see
- * rsnd_ssiu_init_gen2()
- */
- if (is_tdm || is_tdm_split) {
- wsr |= WS_MODE;
- cr_own |= CHNL_8;
- }
-
- /*
- * We shouldn't exchange SWSP after running.
- * This means, parent needs to care it.
- */
- if (rsnd_ssi_is_parent(mod, io))
- goto init_end;
-
- if (rsnd_io_is_play(io))
- cr_own |= TRMD;
-
- cr_own &= ~DWL_MASK;
- width = snd_pcm_format_width(runtime->format);
- if (is_tdm_split) {
- /*
- * The SWL and DWL bits in SSICR should be fixed at 32-bit
- * setting when TDM split mode.
- * see datasheet
- * Operation :: TDM Format Split Function (TDM Split Mode)
- */
- width = 32;
- }
-
- switch (width) {
- case 8:
- cr_own |= DWL_8;
- break;
- case 16:
- cr_own |= DWL_16;
- break;
- case 24:
- cr_own |= DWL_24;
- break;
- case 32:
- cr_own |= DWL_32;
- break;
- }
-
- if (rsnd_ssi_is_dma_mode(mod)) {
- cr_mode = UIEN | OIEN | /* over/under run */
- DMEN; /* DMA : enable DMA */
- } else {
- cr_mode = DIEN; /* PIO : enable Data interrupt */
- }
-
-init_end:
- ssi->cr_own = cr_own;
- ssi->cr_mode = cr_mode;
- ssi->wsr = wsr;
-}
-
-static void rsnd_ssi_register_setup(struct rsnd_mod *mod)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- rsnd_mod_write(mod, SSIWSR, ssi->wsr);
- rsnd_mod_write(mod, SSICR, ssi->cr_own |
- ssi->cr_clk |
- ssi->cr_mode |
- ssi->cr_en);
-}
-
-/*
- * SSI mod common functions
- */
-static int rsnd_ssi_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- int ret;
-
- if (!rsnd_ssi_is_run_mods(mod, io))
- return 0;
-
- ret = rsnd_ssi_master_clk_start(mod, io);
- if (ret < 0)
- return ret;
-
- ssi->usrcnt++;
-
- ret = rsnd_mod_power_on(mod);
- if (ret < 0)
- return ret;
-
- rsnd_ssi_config_init(mod, io);
-
- rsnd_ssi_register_setup(mod);
-
- /* clear error status */
- rsnd_ssi_status_clear(mod);
-
- return 0;
-}
-
-static int rsnd_ssi_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- if (!rsnd_ssi_is_run_mods(mod, io))
- return 0;
-
- if (!ssi->usrcnt) {
- dev_err(dev, "%s usrcnt error\n", rsnd_mod_name(mod));
- return -EIO;
- }
-
- rsnd_ssi_master_clk_stop(mod, io);
-
- rsnd_mod_power_off(mod);
-
- ssi->usrcnt--;
-
- if (!ssi->usrcnt) {
- ssi->cr_own = 0;
- ssi->cr_mode = 0;
- ssi->wsr = 0;
- }
-
- return 0;
-}
-
-static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- unsigned int fmt_width = snd_pcm_format_width(params_format(params));
-
- if (fmt_width > rdai->chan_width) {
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- dev_err(dev, "invalid combination of slot-width and format-data-width\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int rsnd_ssi_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- if (!rsnd_ssi_is_run_mods(mod, io))
- return 0;
-
- /*
- * EN will be set via SSIU :: SSI_CONTROL
- * if Multi channel mode
- */
- if (rsnd_ssi_multi_secondaries_runtime(io))
- return 0;
-
- /*
- * EN is for data output.
- * SSI parent EN is not needed.
- */
- if (rsnd_ssi_is_parent(mod, io))
- return 0;
-
- ssi->cr_en = EN;
-
- rsnd_mod_write(mod, SSICR, ssi->cr_own |
- ssi->cr_clk |
- ssi->cr_mode |
- ssi->cr_en);
-
- return 0;
-}
-
-static int rsnd_ssi_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- u32 cr;
-
- if (!rsnd_ssi_is_run_mods(mod, io))
- return 0;
-
- if (rsnd_ssi_is_parent(mod, io))
- return 0;
-
- cr = ssi->cr_own |
- ssi->cr_clk;
-
- /*
- * disable all IRQ,
- * Playback: Wait all data was sent
- * Capture: It might not receave data. Do nothing
- */
- if (rsnd_io_is_play(io)) {
- rsnd_mod_write(mod, SSICR, cr | ssi->cr_en);
- rsnd_ssi_status_check(mod, DIRQ);
- }
-
- /* In multi-SSI mode, stop is performed by setting ssi0129 in
- * SSI_CONTROL to 0 (in rsnd_ssio_stop_gen2). Do nothing here.
- */
- if (rsnd_ssi_multi_secondaries_runtime(io))
- return 0;
-
- /*
- * disable SSI,
- * and, wait idle state
- */
- rsnd_mod_write(mod, SSICR, cr); /* disabled all */
- rsnd_ssi_status_check(mod, IIRQ);
-
- ssi->cr_en = 0;
-
- return 0;
-}
-
-static int rsnd_ssi_irq(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv,
- int enable)
-{
- u32 val = 0;
- int is_tdm, is_tdm_split;
- int id = rsnd_mod_id(mod);
-
- is_tdm = rsnd_runtime_is_tdm(io);
- is_tdm_split = rsnd_runtime_is_tdm_split(io);
-
- if (rsnd_is_gen1(priv))
- return 0;
-
- if (rsnd_ssi_is_parent(mod, io))
- return 0;
-
- if (!rsnd_ssi_is_run_mods(mod, io))
- return 0;
-
- if (enable)
- val = rsnd_ssi_is_dma_mode(mod) ? 0x0e000000 : 0x0f000000;
-
- if (is_tdm || is_tdm_split) {
- switch (id) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 9:
- val |= 0x0000ff00;
- break;
- }
- }
-
- rsnd_mod_write(mod, SSI_INT_ENABLE, val);
-
- return 0;
-}
-
-static bool rsnd_ssi_pio_interrupt(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io);
-static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- int is_dma = rsnd_ssi_is_dma_mode(mod);
- u32 status;
- bool elapsed = false;
- bool stop = false;
-
- spin_lock(&priv->lock);
-
- /* ignore all cases if not working */
- if (!rsnd_io_is_working(io))
- goto rsnd_ssi_interrupt_out;
-
- status = rsnd_ssi_status_get(mod);
-
- /* PIO only */
- if (!is_dma && (status & DIRQ))
- elapsed = rsnd_ssi_pio_interrupt(mod, io);
-
- /* DMA only */
- if (is_dma && (status & (UIRQ | OIRQ))) {
- rsnd_print_irq_status(dev, "%s err status : 0x%08x\n",
- rsnd_mod_name(mod), status);
-
- stop = true;
- }
-
- stop |= rsnd_ssiu_busif_err_status_clear(mod);
-
- rsnd_ssi_status_clear(mod);
-rsnd_ssi_interrupt_out:
- spin_unlock(&priv->lock);
-
- if (elapsed)
- rsnd_dai_period_elapsed(io);
-
- if (stop)
- snd_pcm_stop_xrun(io->substream);
-
-}
-
-static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
-{
- struct rsnd_mod *mod = data;
-
- rsnd_mod_interrupt(mod, __rsnd_ssi_interrupt);
-
- return IRQ_HANDLED;
-}
-
-static u32 *rsnd_ssi_get_status(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type)
-{
- /*
- * SSIP (= SSI parent) needs to be special, otherwise,
- * 2nd SSI might doesn't start. see also rsnd_mod_call()
- *
- * We can't include parent SSI status on SSI, because we don't know
- * how many SSI requests parent SSI. Thus, it is localed on "io" now.
- * ex) trouble case
- * Playback: SSI0
- * Capture : SSI1 (needs SSI0)
- *
- * 1) start Capture -> SSI0/SSI1 are started.
- * 2) start Playback -> SSI0 doesn't work, because it is already
- * marked as "started" on 1)
- *
- * OTOH, using each mod's status is good for MUX case.
- * It doesn't need to start in 2nd start
- * ex)
- * IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0
- * |
- * IO-1: SRC1 -> CTU2 -+
- *
- * 1) start IO-0 -> start SSI0
- * 2) start IO-1 -> SSI0 doesn't need to start, because it is
- * already started on 1)
- */
- if (type == RSND_MOD_SSIP)
- return &io->parent_ssi_status;
-
- return rsnd_mod_get_status(mod, io, type);
-}
-
-/*
- * SSI PIO
- */
-static void rsnd_ssi_parent_attach(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-
- if (!__rsnd_ssi_is_pin_sharing(mod))
- return;
-
- if (!rsnd_rdai_is_clk_master(rdai))
- return;
-
- if (rsnd_ssi_is_multi_secondary(mod, io))
- return;
-
- switch (rsnd_mod_id(mod)) {
- case 1:
- case 2:
- case 9:
- rsnd_dai_connect(rsnd_ssi_mod_get(priv, 0), io, RSND_MOD_SSIP);
- break;
- case 4:
- rsnd_dai_connect(rsnd_ssi_mod_get(priv, 3), io, RSND_MOD_SSIP);
- break;
- case 8:
- rsnd_dai_connect(rsnd_ssi_mod_get(priv, 7), io, RSND_MOD_SSIP);
- break;
- }
-}
-
-static int rsnd_ssi_pcm_new(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct snd_soc_pcm_runtime *rtd)
-{
- /*
- * rsnd_rdai_is_clk_master() will be enabled after set_fmt,
- * and, pcm_new will be called after it.
- * This function reuse pcm_new at this point.
- */
- rsnd_ssi_parent_attach(mod, io);
-
- return 0;
-}
-
-static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- int ret = 0;
-
- /*
- * SSIP/SSIU/IRQ are not needed on
- * SSI Multi secondaries
- */
- if (rsnd_ssi_is_multi_secondary(mod, io))
- return 0;
-
- /*
- * It can't judge ssi parent at this point
- * see rsnd_ssi_pcm_new()
- */
-
- /*
- * SSI might be called again as PIO fallback
- * It is easy to manual handling for IRQ request/free
- *
- * OTOH, this function might be called many times if platform is
- * using MIX. It needs xxx_attach() many times on xxx_probe().
- * Because of it, we can't control .probe/.remove calling count by
- * mod->status.
- * But it don't need to call request_irq() many times.
- * Let's control it by RSND_SSI_PROBED flag.
- */
- if (!rsnd_flags_has(ssi, RSND_SSI_PROBED)) {
- ret = request_irq(ssi->irq,
- rsnd_ssi_interrupt,
- IRQF_SHARED,
- dev_name(dev), mod);
-
- rsnd_flags_set(ssi, RSND_SSI_PROBED);
- }
-
- return ret;
-}
-
-static int rsnd_ssi_common_remove(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- struct rsnd_mod *pure_ssi_mod = rsnd_io_to_mod_ssi(io);
-
- /* Do nothing if non SSI (= SSI parent, multi SSI) mod */
- if (pure_ssi_mod != mod)
- return 0;
-
- /* PIO will request IRQ again */
- if (rsnd_flags_has(ssi, RSND_SSI_PROBED)) {
- free_irq(ssi->irq, mod);
-
- rsnd_flags_del(ssi, RSND_SSI_PROBED);
- }
-
- return 0;
-}
-
-/*
- * SSI PIO functions
- */
-static bool rsnd_ssi_pio_interrupt(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- u32 *buf = (u32 *)(runtime->dma_area + ssi->byte_pos);
- int shift = 0;
- int byte_pos;
- bool elapsed = false;
-
- if (snd_pcm_format_width(runtime->format) == 24)
- shift = 8;
-
- /*
- * 8/16/32 data can be assesse to TDR/RDR register
- * directly as 32bit data
- * see rsnd_ssi_init()
- */
- if (rsnd_io_is_play(io))
- rsnd_mod_write(mod, SSITDR, (*buf) << shift);
- else
- *buf = (rsnd_mod_read(mod, SSIRDR) >> shift);
-
- byte_pos = ssi->byte_pos + sizeof(*buf);
-
- if (byte_pos >= ssi->next_period_byte) {
- int period_pos = byte_pos / ssi->byte_per_period;
-
- if (period_pos >= runtime->periods) {
- byte_pos = 0;
- period_pos = 0;
- }
-
- ssi->next_period_byte = (period_pos + 1) * ssi->byte_per_period;
-
- elapsed = true;
- }
-
- WRITE_ONCE(ssi->byte_pos, byte_pos);
-
- return elapsed;
-}
-
-static int rsnd_ssi_pio_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- if (!rsnd_ssi_is_parent(mod, io)) {
- ssi->byte_pos = 0;
- ssi->byte_per_period = runtime->period_size *
- runtime->channels *
- samples_to_bytes(runtime, 1);
- ssi->next_period_byte = ssi->byte_per_period;
- }
-
- return rsnd_ssi_init(mod, io, priv);
-}
-
-static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- snd_pcm_uframes_t *pointer)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
-
- *pointer = bytes_to_frames(runtime, READ_ONCE(ssi->byte_pos));
-
- return 0;
-}
-
-static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
- .name = SSI_NAME,
- .probe = rsnd_ssi_common_probe,
- .remove = rsnd_ssi_common_remove,
- .init = rsnd_ssi_pio_init,
- .quit = rsnd_ssi_quit,
- .start = rsnd_ssi_start,
- .stop = rsnd_ssi_stop,
- .irq = rsnd_ssi_irq,
- .pointer = rsnd_ssi_pio_pointer,
- .pcm_new = rsnd_ssi_pcm_new,
- .hw_params = rsnd_ssi_hw_params,
- .get_status = rsnd_ssi_get_status,
-};
-
-static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- /*
- * SSIP/SSIU/IRQ/DMA are not needed on
- * SSI Multi secondaries
- */
- if (rsnd_ssi_is_multi_secondary(mod, io))
- return 0;
-
- ret = rsnd_ssi_common_probe(mod, io, priv);
- if (ret)
- return ret;
-
- /* SSI probe might be called many times in MUX multi path */
- ret = rsnd_dma_attach(io, mod, &io->dma);
-
- return ret;
-}
-
-static int rsnd_ssi_fallback(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
-
- /*
- * fallback to PIO
- *
- * SSI .probe might be called again.
- * see
- * rsnd_rdai_continuance_probe()
- */
- mod->ops = &rsnd_ssi_pio_ops;
-
- dev_info(dev, "%s fallback to PIO mode\n", rsnd_mod_name(mod));
-
- return 0;
-}
-
-static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- int is_play = rsnd_io_is_play(io);
- char *name;
-
- /*
- * It should use "rcar_sound,ssiu" on DT.
- * But, we need to keep compatibility for old version.
- *
- * If it has "rcar_sound.ssiu", it will be used.
- * If not, "rcar_sound.ssi" will be used.
- * see
- * rsnd_ssiu_dma_req()
- * rsnd_dma_of_path()
- */
-
- if (rsnd_ssi_use_busif(io))
- name = is_play ? "rxu" : "txu";
- else
- name = is_play ? "rx" : "tx";
-
- return rsnd_dma_request_channel(rsnd_ssi_of_node(priv),
- SSI_NAME, mod, name);
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_ssi_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- seq_printf(m, "clock: %s\n", rsnd_rdai_is_clk_master(rdai) ?
- "provider" : "consumer");
- seq_printf(m, "bit_clk_inv: %d\n", rdai->bit_clk_inv);
- seq_printf(m, "frm_clk_inv: %d\n", rdai->frm_clk_inv);
- seq_printf(m, "pin share: %d\n", __rsnd_ssi_is_pin_sharing(mod));
- seq_printf(m, "can out clk: %d\n", rsnd_ssi_can_output_clk(mod));
- seq_printf(m, "multi secondary: %d\n", rsnd_ssi_is_multi_secondary(mod, io));
- seq_printf(m, "tdm: %d, %d\n", rsnd_runtime_is_tdm(io),
- rsnd_runtime_is_tdm_split(io));
- seq_printf(m, "chan: %d\n", ssi->chan);
- seq_printf(m, "user: %d\n", ssi->usrcnt);
-
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SSI,
- rsnd_mod_id(mod) * 0x40, 0x40);
-}
-#define DEBUG_INFO .debug_info = rsnd_ssi_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
- .name = SSI_NAME,
- .dma_req = rsnd_ssi_dma_req,
- .probe = rsnd_ssi_dma_probe,
- .remove = rsnd_ssi_common_remove,
- .init = rsnd_ssi_init,
- .quit = rsnd_ssi_quit,
- .start = rsnd_ssi_start,
- .stop = rsnd_ssi_stop,
- .irq = rsnd_ssi_irq,
- .pcm_new = rsnd_ssi_pcm_new,
- .fallback = rsnd_ssi_fallback,
- .hw_params = rsnd_ssi_hw_params,
- .get_status = rsnd_ssi_get_status,
- DEBUG_INFO
-};
-
-int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod)
-{
- return mod->ops == &rsnd_ssi_dma_ops;
-}
-
-/*
- * ssi mod function
- */
-static void rsnd_ssi_connect(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- static const enum rsnd_mod_type types[] = {
- RSND_MOD_SSI,
- RSND_MOD_SSIM1,
- RSND_MOD_SSIM2,
- RSND_MOD_SSIM3,
- };
- enum rsnd_mod_type type;
- int i;
-
- /* try SSI -> SSIM1 -> SSIM2 -> SSIM3 */
- for (i = 0; i < ARRAY_SIZE(types); i++) {
- type = types[i];
- if (!rsnd_io_to_mod(io, type)) {
- rsnd_dai_connect(mod, io, type);
- rsnd_rdai_channels_set(rdai, (i + 1) * 2);
- rsnd_rdai_ssi_lane_set(rdai, (i + 1));
- return;
- }
- }
-}
-
-void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
- struct device_node *playback,
- struct device_node *capture)
-{
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *node;
- struct device_node *np;
- int i;
-
- node = rsnd_ssi_of_node(priv);
- if (!node)
- return;
-
- i = 0;
- for_each_child_of_node(node, np) {
- struct rsnd_mod *mod;
-
- i = rsnd_node_fixed_index(dev, np, SSI_NAME, i);
- if (i < 0) {
- of_node_put(np);
- break;
- }
-
- mod = rsnd_ssi_mod_get(priv, i);
-
- if (np == playback)
- rsnd_ssi_connect(mod, &rdai->playback);
- if (np == capture)
- rsnd_ssi_connect(mod, &rdai->capture);
- i++;
- }
-
- of_node_put(node);
-}
-
-struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
- id = 0;
-
- return rsnd_mod_get(rsnd_ssi_get(priv, id));
-}
-
-int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
-{
- if (!mod)
- return 0;
-
- return !!(rsnd_flags_has(rsnd_mod_to_ssi(mod), RSND_SSI_CLK_PIN_SHARE));
-}
-
-int rsnd_ssi_probe(struct rsnd_priv *priv)
-{
- struct device_node *node;
- struct device_node *np;
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mod_ops *ops;
- struct clk *clk;
- struct rsnd_ssi *ssi;
- char name[RSND_SSI_NAME_SIZE];
- int i, nr, ret;
-
- node = rsnd_ssi_of_node(priv);
- if (!node)
- return -EINVAL;
-
- nr = rsnd_node_count(priv, node, SSI_NAME);
- if (!nr) {
- ret = -EINVAL;
- goto rsnd_ssi_probe_done;
- }
-
- ssi = devm_kcalloc(dev, nr, sizeof(*ssi), GFP_KERNEL);
- if (!ssi) {
- ret = -ENOMEM;
- goto rsnd_ssi_probe_done;
- }
-
- priv->ssi = ssi;
- priv->ssi_nr = nr;
-
- i = 0;
- for_each_child_of_node(node, np) {
- if (!of_device_is_available(np))
- goto skip;
-
- i = rsnd_node_fixed_index(dev, np, SSI_NAME, i);
- if (i < 0) {
- ret = -EINVAL;
- of_node_put(np);
- goto rsnd_ssi_probe_done;
- }
-
- ssi = rsnd_ssi_get(priv, i);
-
- snprintf(name, RSND_SSI_NAME_SIZE, "%s.%d",
- SSI_NAME, i);
-
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- of_node_put(np);
- goto rsnd_ssi_probe_done;
- }
-
- if (of_property_read_bool(np, "shared-pin"))
- rsnd_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE);
-
- if (of_property_read_bool(np, "no-busif"))
- rsnd_flags_set(ssi, RSND_SSI_NO_BUSIF);
-
- ssi->irq = irq_of_parse_and_map(np, 0);
- if (!ssi->irq) {
- ret = -EINVAL;
- of_node_put(np);
- goto rsnd_ssi_probe_done;
- }
-
- if (of_property_read_bool(np, "pio-transfer"))
- ops = &rsnd_ssi_pio_ops;
- else
- ops = &rsnd_ssi_dma_ops;
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk,
- RSND_MOD_SSI, i);
- if (ret) {
- of_node_put(np);
- goto rsnd_ssi_probe_done;
- }
-skip:
- i++;
- }
-
- ret = 0;
-
-rsnd_ssi_probe_done:
- of_node_put(node);
-
- return ret;
-}
-
-void rsnd_ssi_remove(struct rsnd_priv *priv)
-{
- struct rsnd_ssi *ssi;
- int i;
-
- for_each_rsnd_ssi(ssi, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(ssi));
- }
-}
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c
deleted file mode 100644
index 17bd8cc86dd0..000000000000
--- a/sound/soc/sh/rcar/ssiu.c
+++ /dev/null
@@ -1,609 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas R-Car SSIU support
-//
-// Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-#include "rsnd.h"
-
-#define SSIU_NAME "ssiu"
-
-struct rsnd_ssiu {
- struct rsnd_mod mod;
- u32 busif_status[8]; /* for BUSIF0 - BUSIF7 */
- unsigned int usrcnt;
- int id;
- int id_sub;
-};
-
-/* SSI_MODE */
-#define TDM_EXT (1 << 0)
-#define TDM_SPLIT (1 << 8)
-
-#define rsnd_ssiu_nr(priv) ((priv)->ssiu_nr)
-#define rsnd_mod_to_ssiu(_mod) container_of((_mod), struct rsnd_ssiu, mod)
-#define for_each_rsnd_ssiu(pos, priv, i) \
- for (i = 0; \
- (i < rsnd_ssiu_nr(priv)) && \
- ((pos) = ((struct rsnd_ssiu *)(priv)->ssiu + i)); \
- i++)
-
-/*
- * SSI Gen2 Gen3 Gen4
- * 0 BUSIF0-3 BUSIF0-7 BUSIF0-7
- * 1 BUSIF0-3 BUSIF0-7
- * 2 BUSIF0-3 BUSIF0-7
- * 3 BUSIF0 BUSIF0-7
- * 4 BUSIF0 BUSIF0-7
- * 5 BUSIF0 BUSIF0
- * 6 BUSIF0 BUSIF0
- * 7 BUSIF0 BUSIF0
- * 8 BUSIF0 BUSIF0
- * 9 BUSIF0-3 BUSIF0-7
- * total 22 52 8
- */
-static const int gen2_id[] = { 0, 4, 8, 12, 13, 14, 15, 16, 17, 18 };
-static const int gen3_id[] = { 0, 8, 16, 24, 32, 40, 41, 42, 43, 44 };
-static const int gen4_id[] = { 0 };
-
-/* enable busif buffer over/under run interrupt. */
-#define rsnd_ssiu_busif_err_irq_enable(mod) rsnd_ssiu_busif_err_irq_ctrl(mod, 1)
-#define rsnd_ssiu_busif_err_irq_disable(mod) rsnd_ssiu_busif_err_irq_ctrl(mod, 0)
-static void rsnd_ssiu_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable)
-{
- int id = rsnd_mod_id(mod);
- int shift, offset;
- int i;
-
- switch (id) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- shift = id;
- offset = 0;
- break;
- case 9:
- shift = 1;
- offset = 1;
- break;
- default:
- return;
- }
-
- for (i = 0; i < 4; i++) {
- enum rsnd_reg reg = SSI_SYS_INT_ENABLE((i * 2) + offset);
- u32 val = 0xf << (shift * 4);
- u32 sys_int_enable = rsnd_mod_read(mod, reg);
-
- if (enable)
- sys_int_enable |= val;
- else
- sys_int_enable &= ~val;
- rsnd_mod_write(mod, reg, sys_int_enable);
- }
-}
-
-bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod)
-{
- bool error = false;
- int id = rsnd_mod_id(mod);
- int shift, offset;
- int i;
-
- switch (id) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- shift = id;
- offset = 0;
- break;
- case 9:
- shift = 1;
- offset = 1;
- break;
- default:
- goto out;
- }
-
- for (i = 0; i < 4; i++) {
- u32 reg = SSI_SYS_STATUS(i * 2) + offset;
- u32 status = rsnd_mod_read(mod, reg);
- u32 val = 0xf << (shift * 4);
-
- status &= val;
- if (status) {
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- rsnd_print_irq_status(dev, "%s err status : 0x%08x\n",
- rsnd_mod_name(mod), status);
- error = true;
- }
- rsnd_mod_write(mod, reg, val);
- }
-out:
- return error;
-}
-
-static u32 *rsnd_ssiu_get_status(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- enum rsnd_mod_type type)
-{
- struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
- int busif = rsnd_mod_id_sub(mod);
-
- return &ssiu->busif_status[busif];
-}
-
-static int rsnd_ssiu_init(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- u32 ssis = rsnd_ssi_multi_secondaries_runtime(io);
- int use_busif = rsnd_ssi_use_busif(io);
- int id = rsnd_mod_id(mod);
- int is_clk_master = rsnd_rdai_is_clk_master(rdai);
- u32 val1, val2;
-
- /* clear status */
- rsnd_ssiu_busif_err_status_clear(mod);
-
- /* Gen4 doesn't have SSI_MODE */
- if (rsnd_is_gen4(priv))
- goto ssi_mode_setting_end;
-
- /*
- * SSI_MODE0
- */
- rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
-
- /*
- * SSI_MODE1 / SSI_MODE2
- *
- * FIXME
- * sharing/multi with SSI0 are mainly supported
- */
- val1 = rsnd_mod_read(mod, SSI_MODE1);
- val2 = rsnd_mod_read(mod, SSI_MODE2);
- if (rsnd_ssi_is_pin_sharing(io)) {
-
- ssis |= (1 << id);
-
- } else if (ssis) {
- /*
- * Multi SSI
- *
- * set synchronized bit here
- */
-
- /* SSI4 is synchronized with SSI3 */
- if (ssis & (1 << 4))
- val1 |= (1 << 20);
- /* SSI012 are synchronized */
- if (ssis == 0x0006)
- val1 |= (1 << 4);
- /* SSI0129 are synchronized */
- if (ssis == 0x0206)
- val2 |= (1 << 4);
- }
-
- /* SSI1 is sharing pin with SSI0 */
- if (ssis & (1 << 1))
- val1 |= is_clk_master ? 0x2 : 0x1;
-
- /* SSI2 is sharing pin with SSI0 */
- if (ssis & (1 << 2))
- val1 |= is_clk_master ? 0x2 << 2 :
- 0x1 << 2;
- /* SSI4 is sharing pin with SSI3 */
- if (ssis & (1 << 4))
- val1 |= is_clk_master ? 0x2 << 16 :
- 0x1 << 16;
- /* SSI9 is sharing pin with SSI0 */
- if (ssis & (1 << 9))
- val2 |= is_clk_master ? 0x2 : 0x1;
-
- rsnd_mod_bset(mod, SSI_MODE1, 0x0013001f, val1);
- rsnd_mod_bset(mod, SSI_MODE2, 0x00000017, val2);
-
-ssi_mode_setting_end:
- /*
- * Enable busif buffer over/under run interrupt.
- * It will be handled from ssi.c
- * see
- * __rsnd_ssi_interrupt()
- */
- rsnd_ssiu_busif_err_irq_enable(mod);
-
- return 0;
-}
-
-static int rsnd_ssiu_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- /* disable busif buffer over/under run interrupt. */
- rsnd_ssiu_busif_err_irq_disable(mod);
-
- return 0;
-}
-
-static struct rsnd_mod_ops rsnd_ssiu_ops_gen1 = {
- .name = SSIU_NAME,
- .init = rsnd_ssiu_init,
- .quit = rsnd_ssiu_quit,
- .get_status = rsnd_ssiu_get_status,
-};
-
-static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
- u32 has_hdmi0 = rsnd_flags_has(io, RSND_STREAM_HDMI0);
- u32 has_hdmi1 = rsnd_flags_has(io, RSND_STREAM_HDMI1);
- int ret;
- u32 mode = 0;
-
- ret = rsnd_ssiu_init(mod, io, priv);
- if (ret < 0)
- return ret;
-
- ssiu->usrcnt++;
-
- /*
- * TDM Extend/Split Mode
- * see
- * rsnd_ssi_config_init()
- */
- if (rsnd_runtime_is_tdm(io))
- mode = TDM_EXT;
- else if (rsnd_runtime_is_tdm_split(io))
- mode = TDM_SPLIT;
-
- rsnd_mod_write(mod, SSI_MODE, mode);
-
- if (rsnd_ssi_use_busif(io)) {
- int id = rsnd_mod_id(mod);
- int busif = rsnd_mod_id_sub(mod);
- enum rsnd_reg adinr_reg, mode_reg, dalign_reg;
-
- if ((id == 9) && (busif >= 4)) {
- adinr_reg = SSI9_BUSIF_ADINR(busif);
- mode_reg = SSI9_BUSIF_MODE(busif);
- dalign_reg = SSI9_BUSIF_DALIGN(busif);
- } else {
- adinr_reg = SSI_BUSIF_ADINR(busif);
- mode_reg = SSI_BUSIF_MODE(busif);
- dalign_reg = SSI_BUSIF_DALIGN(busif);
- }
-
- rsnd_mod_write(mod, adinr_reg,
- rsnd_get_adinr_bit(mod, io) |
- (rsnd_io_is_play(io) ?
- rsnd_runtime_channel_after_ctu(io) :
- rsnd_runtime_channel_original(io)));
- rsnd_mod_write(mod, mode_reg,
- rsnd_get_busif_shift(io, mod) | 1);
- rsnd_mod_write(mod, dalign_reg,
- rsnd_get_dalign(mod, io));
- }
-
- if (has_hdmi0 || has_hdmi1) {
- enum rsnd_mod_type rsnd_ssi_array[] = {
- RSND_MOD_SSIM1,
- RSND_MOD_SSIM2,
- RSND_MOD_SSIM3,
- };
- struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_mod *pos;
- u32 val;
- int i;
-
- i = rsnd_mod_id(ssi_mod);
-
- /* output all same SSI as default */
- val = i << 16 |
- i << 20 |
- i << 24 |
- i << 28 |
- i;
-
- for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) {
- int shift = (i * 4) + 20;
-
- val = (val & ~(0xF << shift)) |
- rsnd_mod_id(pos) << shift;
- }
-
- if (has_hdmi0)
- rsnd_mod_write(mod, HDMI0_SEL, val);
- if (has_hdmi1)
- rsnd_mod_write(mod, HDMI1_SEL, val);
- }
-
- return 0;
-}
-
-static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int busif = rsnd_mod_id_sub(mod);
-
- if (!rsnd_ssi_use_busif(io))
- return 0;
-
- rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4));
-
- if (rsnd_ssi_multi_secondaries_runtime(io))
- rsnd_mod_write(mod, SSI_CONTROL, 0x1);
-
- return 0;
-}
-
-static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
- int busif = rsnd_mod_id_sub(mod);
-
- if (!rsnd_ssi_use_busif(io))
- return 0;
-
- rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 0);
-
- if (--ssiu->usrcnt)
- return 0;
-
- if (rsnd_ssi_multi_secondaries_runtime(io))
- rsnd_mod_write(mod, SSI_CONTROL, 0);
-
- return 0;
-}
-
-static int rsnd_ssiu_id(struct rsnd_mod *mod)
-{
- struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
-
- /* see rsnd_ssiu_probe() */
- return ssiu->id;
-}
-
-static int rsnd_ssiu_id_sub(struct rsnd_mod *mod)
-{
- struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
-
- /* see rsnd_ssiu_probe() */
- return ssiu->id_sub;
-}
-
-static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- int is_play = rsnd_io_is_play(io);
- char *name;
-
- /*
- * It should use "rcar_sound,ssiu" on DT.
- * But, we need to keep compatibility for old version.
- *
- * If it has "rcar_sound.ssiu", it will be used.
- * If not, "rcar_sound.ssi" will be used.
- * see
- * rsnd_ssi_dma_req()
- * rsnd_dma_of_path()
- */
-
- name = is_play ? "rx" : "tx";
-
- return rsnd_dma_request_channel(rsnd_ssiu_of_node(priv),
- SSIU_NAME, mod, name);
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void rsnd_ssiu_debug_info(struct seq_file *m,
- struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SSIU,
- rsnd_mod_id(mod) * 0x80, 0x80);
-}
-#define DEBUG_INFO .debug_info = rsnd_ssiu_debug_info
-#else
-#define DEBUG_INFO
-#endif
-
-static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = {
- .name = SSIU_NAME,
- .dma_req = rsnd_ssiu_dma_req,
- .init = rsnd_ssiu_init_gen2,
- .quit = rsnd_ssiu_quit,
- .start = rsnd_ssiu_start_gen2,
- .stop = rsnd_ssiu_stop_gen2,
- .get_status = rsnd_ssiu_get_status,
- DEBUG_INFO
-};
-
-static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id)
-{
- if (WARN_ON(id < 0 || id >= rsnd_ssiu_nr(priv)))
- id = 0;
-
- return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id);
-}
-
-static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_ssiu *ssiu;
- int is_dma_mode;
- int i;
-
- if (!ssi_mod)
- return;
-
- is_dma_mode = rsnd_ssi_is_dma_mode(ssi_mod);
-
- /* select BUSIF0 */
- for_each_rsnd_ssiu(ssiu, priv, i) {
- struct rsnd_mod *mod = rsnd_mod_get(ssiu);
-
- if (is_dma_mode &&
- (rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) &&
- (rsnd_mod_id_sub(mod) == 0)) {
- rsnd_dai_connect(mod, io, mod->type);
- return;
- }
- }
-}
-
-void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
- struct device_node *playback,
- struct device_node *capture)
-{
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *node = rsnd_ssiu_of_node(priv);
- struct rsnd_dai_stream *io_p = &rdai->playback;
- struct rsnd_dai_stream *io_c = &rdai->capture;
-
- /* use rcar_sound,ssiu if exist */
- if (node) {
- struct device_node *np;
- int i = 0;
-
- for_each_child_of_node(node, np) {
- struct rsnd_mod *mod;
-
- i = rsnd_node_fixed_index(dev, np, SSIU_NAME, i);
- if (i < 0) {
- of_node_put(np);
- break;
- }
-
- mod = rsnd_ssiu_mod_get(priv, i);
-
- if (np == playback)
- rsnd_dai_connect(mod, io_p, mod->type);
- if (np == capture)
- rsnd_dai_connect(mod, io_c, mod->type);
- i++;
- }
-
- of_node_put(node);
- }
-
- /* Keep DT compatibility */
- if (!rsnd_io_to_mod_ssiu(io_p))
- rsnd_parse_connect_ssiu_compatible(priv, io_p);
- if (!rsnd_io_to_mod_ssiu(io_c))
- rsnd_parse_connect_ssiu_compatible(priv, io_c);
-}
-
-int rsnd_ssiu_probe(struct rsnd_priv *priv)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct device_node *node;
- struct rsnd_ssiu *ssiu;
- struct rsnd_mod_ops *ops;
- const int *list = NULL;
- int i, nr;
-
- /*
- * Keep DT compatibility.
- * if it has "rcar_sound,ssiu", use it.
- * if not, use "rcar_sound,ssi"
- * see
- * rsnd_ssiu_bufsif_to_id()
- */
- node = rsnd_ssiu_of_node(priv);
- if (node)
- nr = rsnd_node_count(priv, node, SSIU_NAME);
- else
- nr = priv->ssi_nr;
-
- if (!nr)
- return -EINVAL;
-
- ssiu = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL);
- if (!ssiu)
- return -ENOMEM;
-
- priv->ssiu = ssiu;
- priv->ssiu_nr = nr;
-
- if (rsnd_is_gen1(priv))
- ops = &rsnd_ssiu_ops_gen1;
- else
- ops = &rsnd_ssiu_ops_gen2;
-
- /* Keep compatibility */
- nr = 0;
- if ((node) &&
- (ops == &rsnd_ssiu_ops_gen2)) {
- ops->id = rsnd_ssiu_id;
- ops->id_sub = rsnd_ssiu_id_sub;
-
- if (rsnd_is_gen2(priv)) {
- list = gen2_id;
- nr = ARRAY_SIZE(gen2_id);
- } else if (rsnd_is_gen3(priv)) {
- list = gen3_id;
- nr = ARRAY_SIZE(gen3_id);
- } else if (rsnd_is_gen4(priv)) {
- list = gen4_id;
- nr = ARRAY_SIZE(gen4_id);
- } else {
- dev_err(dev, "unknown SSIU\n");
- return -ENODEV;
- }
- }
-
- for_each_rsnd_ssiu(ssiu, priv, i) {
- int ret;
-
- if (node) {
- int j;
-
- /*
- * see
- * rsnd_ssiu_get_id()
- * rsnd_ssiu_get_id_sub()
- */
- for (j = 0; j < nr; j++) {
- if (list[j] > i)
- break;
- ssiu->id = j;
- ssiu->id_sub = i - list[ssiu->id];
- }
- } else {
- ssiu->id = i;
- }
-
- ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu),
- ops, NULL, RSND_MOD_SSIU, i);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-void rsnd_ssiu_remove(struct rsnd_priv *priv)
-{
- struct rsnd_ssiu *ssiu;
- int i;
-
- for_each_rsnd_ssiu(ssiu, priv, i) {
- rsnd_mod_quit(rsnd_mod_get(ssiu));
- }
-}
diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
deleted file mode 100644
index 9d103646973a..000000000000
--- a/sound/soc/sh/rz-ssi.c
+++ /dev/null
@@ -1,1107 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Renesas RZ/G2L ASoC Serial Sound Interface (SSIF-2) Driver
-//
-// Copyright (C) 2021 Renesas Electronics Corp.
-// Copyright (C) 2019 Chris Brandt.
-//
-
-#include <linux/clk.h>
-#include <linux/dmaengine.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/pm_runtime.h>
-#include <linux/reset.h>
-#include <sound/soc.h>
-
-/* REGISTER OFFSET */
-#define SSICR 0x000
-#define SSISR 0x004
-#define SSIFCR 0x010
-#define SSIFSR 0x014
-#define SSIFTDR 0x018
-#define SSIFRDR 0x01c
-#define SSIOFR 0x020
-#define SSISCR 0x024
-
-/* SSI REGISTER BITS */
-#define SSICR_DWL(x) (((x) & 0x7) << 19)
-#define SSICR_SWL(x) (((x) & 0x7) << 16)
-
-#define SSICR_CKS BIT(30)
-#define SSICR_TUIEN BIT(29)
-#define SSICR_TOIEN BIT(28)
-#define SSICR_RUIEN BIT(27)
-#define SSICR_ROIEN BIT(26)
-#define SSICR_MST BIT(14)
-#define SSICR_BCKP BIT(13)
-#define SSICR_LRCKP BIT(12)
-#define SSICR_CKDV(x) (((x) & 0xf) << 4)
-#define SSICR_TEN BIT(1)
-#define SSICR_REN BIT(0)
-
-#define SSISR_TUIRQ BIT(29)
-#define SSISR_TOIRQ BIT(28)
-#define SSISR_RUIRQ BIT(27)
-#define SSISR_ROIRQ BIT(26)
-#define SSISR_IIRQ BIT(25)
-
-#define SSIFCR_AUCKE BIT(31)
-#define SSIFCR_SSIRST BIT(16)
-#define SSIFCR_TIE BIT(3)
-#define SSIFCR_RIE BIT(2)
-#define SSIFCR_TFRST BIT(1)
-#define SSIFCR_RFRST BIT(0)
-
-#define SSIFSR_TDC_MASK 0x3f
-#define SSIFSR_TDC_SHIFT 24
-#define SSIFSR_RDC_MASK 0x3f
-#define SSIFSR_RDC_SHIFT 8
-
-#define SSIFSR_TDE BIT(16)
-#define SSIFSR_RDF BIT(0)
-
-#define SSIOFR_LRCONT BIT(8)
-
-#define SSISCR_TDES(x) (((x) & 0x1f) << 8)
-#define SSISCR_RDFS(x) (((x) & 0x1f) << 0)
-
-/* Pre allocated buffers sizes */
-#define PREALLOC_BUFFER (SZ_32K)
-#define PREALLOC_BUFFER_MAX (SZ_32K)
-
-#define SSI_RATES SNDRV_PCM_RATE_8000_48000 /* 8k-44.1kHz */
-#define SSI_FMTS SNDRV_PCM_FMTBIT_S16_LE
-#define SSI_CHAN_MIN 2
-#define SSI_CHAN_MAX 2
-#define SSI_FIFO_DEPTH 32
-
-struct rz_ssi_priv;
-
-struct rz_ssi_stream {
- struct rz_ssi_priv *priv;
- struct snd_pcm_substream *substream;
- int fifo_sample_size; /* sample capacity of SSI FIFO */
- int dma_buffer_pos; /* The address for the next DMA descriptor */
- int period_counter; /* for keeping track of periods transferred */
- int sample_width;
- int buffer_pos; /* current frame position in the buffer */
- int running; /* 0=stopped, 1=running */
-
- int uerr_num;
- int oerr_num;
-
- struct dma_chan *dma_ch;
-
- int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm);
-};
-
-struct rz_ssi_priv {
- void __iomem *base;
- struct platform_device *pdev;
- struct reset_control *rstc;
- struct device *dev;
- struct clk *sfr_clk;
- struct clk *clk;
-
- phys_addr_t phys;
- int irq_int;
- int irq_tx;
- int irq_rx;
- int irq_rt;
-
- spinlock_t lock;
-
- /*
- * The SSI supports full-duplex transmission and reception.
- * However, if an error occurs, channel reset (both transmission
- * and reception reset) is required.
- * So it is better to use as half-duplex (playing and recording
- * should be done on separate channels).
- */
- struct rz_ssi_stream playback;
- struct rz_ssi_stream capture;
-
- /* clock */
- unsigned long audio_mck;
- unsigned long audio_clk_1;
- unsigned long audio_clk_2;
-
- bool lrckp_fsync_fall; /* LR clock polarity (SSICR.LRCKP) */
- bool bckp_rise; /* Bit clock polarity (SSICR.BCKP) */
- bool dma_rt;
-};
-
-static void rz_ssi_dma_complete(void *data);
-
-static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data)
-{
- writel(data, (priv->base + reg));
-}
-
-static u32 rz_ssi_reg_readl(struct rz_ssi_priv *priv, uint reg)
-{
- return readl(priv->base + reg);
-}
-
-static void rz_ssi_reg_mask_setl(struct rz_ssi_priv *priv, uint reg,
- u32 bclr, u32 bset)
-{
- u32 val;
-
- val = readl(priv->base + reg);
- val = (val & ~bclr) | bset;
- writel(val, (priv->base + reg));
-}
-
-static inline struct snd_soc_dai *
-rz_ssi_get_dai(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
-
- return snd_soc_rtd_to_cpu(rtd, 0);
-}
-
-static inline bool rz_ssi_stream_is_play(struct rz_ssi_priv *ssi,
- struct snd_pcm_substream *substream)
-{
- return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-}
-
-static inline struct rz_ssi_stream *
-rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream)
-{
- struct rz_ssi_stream *stream = &ssi->playback;
-
- if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
- stream = &ssi->capture;
-
- return stream;
-}
-
-static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi)
-{
- return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch));
-}
-
-static void rz_ssi_set_substream(struct rz_ssi_stream *strm,
- struct snd_pcm_substream *substream)
-{
- struct rz_ssi_priv *ssi = strm->priv;
- unsigned long flags;
-
- spin_lock_irqsave(&ssi->lock, flags);
- strm->substream = substream;
- spin_unlock_irqrestore(&ssi->lock, flags);
-}
-
-static bool rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
- struct rz_ssi_stream *strm)
-{
- unsigned long flags;
- bool ret;
-
- spin_lock_irqsave(&ssi->lock, flags);
- ret = strm->substream && strm->substream->runtime;
- spin_unlock_irqrestore(&ssi->lock, flags);
-
- return ret;
-}
-
-static void rz_ssi_stream_init(struct rz_ssi_stream *strm,
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- rz_ssi_set_substream(strm, substream);
- strm->sample_width = samples_to_bytes(runtime, 1);
- strm->dma_buffer_pos = 0;
- strm->period_counter = 0;
- strm->buffer_pos = 0;
-
- strm->oerr_num = 0;
- strm->uerr_num = 0;
- strm->running = 0;
-
- /* fifo init */
- strm->fifo_sample_size = SSI_FIFO_DEPTH;
-}
-
-static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi,
- struct rz_ssi_stream *strm)
-{
- struct snd_soc_dai *dai = rz_ssi_get_dai(strm->substream);
-
- rz_ssi_set_substream(strm, NULL);
-
- if (strm->oerr_num > 0)
- dev_info(dai->dev, "overrun = %d\n", strm->oerr_num);
-
- if (strm->uerr_num > 0)
- dev_info(dai->dev, "underrun = %d\n", strm->uerr_num);
-}
-
-static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
- unsigned int channels)
-{
- static s8 ckdv[16] = { 1, 2, 4, 8, 16, 32, 64, 128,
- 6, 12, 24, 48, 96, -1, -1, -1 };
- unsigned int channel_bits = 32; /* System Word Length */
- unsigned long bclk_rate = rate * channels * channel_bits;
- unsigned int div;
- unsigned int i;
- u32 ssicr = 0;
- u32 clk_ckdv;
-
- /* Clear AUCKE so we can set MST */
- rz_ssi_reg_writel(ssi, SSIFCR, 0);
-
- /* Continue to output LRCK pin even when idle */
- rz_ssi_reg_writel(ssi, SSIOFR, SSIOFR_LRCONT);
- if (ssi->audio_clk_1 && ssi->audio_clk_2) {
- if (ssi->audio_clk_1 % bclk_rate)
- ssi->audio_mck = ssi->audio_clk_2;
- else
- ssi->audio_mck = ssi->audio_clk_1;
- }
-
- /* Clock setting */
- ssicr |= SSICR_MST;
- if (ssi->audio_mck == ssi->audio_clk_1)
- ssicr |= SSICR_CKS;
- if (ssi->bckp_rise)
- ssicr |= SSICR_BCKP;
- if (ssi->lrckp_fsync_fall)
- ssicr |= SSICR_LRCKP;
-
- /* Determine the clock divider */
- clk_ckdv = 0;
- div = ssi->audio_mck / bclk_rate;
- /* try to find an match */
- for (i = 0; i < ARRAY_SIZE(ckdv); i++) {
- if (ckdv[i] == div) {
- clk_ckdv = i;
- break;
- }
- }
-
- if (i == ARRAY_SIZE(ckdv)) {
- dev_err(ssi->dev, "Rate not divisible by audio clock source\n");
- return -EINVAL;
- }
-
- /*
- * DWL: Data Word Length = 16 bits
- * SWL: System Word Length = 32 bits
- */
- ssicr |= SSICR_CKDV(clk_ckdv);
- ssicr |= SSICR_DWL(1) | SSICR_SWL(3);
- rz_ssi_reg_writel(ssi, SSICR, ssicr);
- rz_ssi_reg_writel(ssi, SSIFCR,
- (SSIFCR_AUCKE | SSIFCR_TFRST | SSIFCR_RFRST));
-
- return 0;
-}
-
-static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
-{
- bool is_play = rz_ssi_stream_is_play(ssi, strm->substream);
- u32 ssicr, ssifcr;
-
- ssicr = rz_ssi_reg_readl(ssi, SSICR);
- ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF;
-
- /* FIFO interrupt thresholds */
- if (rz_ssi_is_dma_enabled(ssi))
- rz_ssi_reg_writel(ssi, SSISCR, 0);
- else
- rz_ssi_reg_writel(ssi, SSISCR,
- SSISCR_TDES(strm->fifo_sample_size / 2 - 1) |
- SSISCR_RDFS(0));
-
- /* enable IRQ */
- if (is_play) {
- ssicr |= SSICR_TUIEN | SSICR_TOIEN;
- ssifcr |= SSIFCR_TIE | SSIFCR_RFRST;
- } else {
- ssicr |= SSICR_RUIEN | SSICR_ROIEN;
- ssifcr |= SSIFCR_RIE | SSIFCR_TFRST;
- }
-
- rz_ssi_reg_writel(ssi, SSICR, ssicr);
- rz_ssi_reg_writel(ssi, SSIFCR, ssifcr);
-
- /* Clear all error flags */
- rz_ssi_reg_mask_setl(ssi, SSISR,
- (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
- SSISR_RUIRQ), 0);
-
- strm->running = 1;
- ssicr |= is_play ? SSICR_TEN : SSICR_REN;
- rz_ssi_reg_writel(ssi, SSICR, ssicr);
-
- return 0;
-}
-
-static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
-{
- int timeout;
-
- strm->running = 0;
-
- /* Disable TX/RX */
- rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
-
- /* Cancel all remaining DMA transactions */
- if (rz_ssi_is_dma_enabled(ssi))
- dmaengine_terminate_async(strm->dma_ch);
-
- /* Disable irqs */
- rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN |
- SSICR_RUIEN | SSICR_ROIEN, 0);
- rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_TIE | SSIFCR_RIE, 0);
-
- /* Clear all error flags */
- rz_ssi_reg_mask_setl(ssi, SSISR,
- (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
- SSISR_RUIRQ), 0);
-
- /* Wait for idle */
- timeout = 100;
- while (--timeout) {
- if (rz_ssi_reg_readl(ssi, SSISR) & SSISR_IIRQ)
- break;
- udelay(1);
- }
-
- if (!timeout)
- dev_info(ssi->dev, "timeout waiting for SSI idle\n");
-
- /* Hold FIFOs in reset */
- rz_ssi_reg_mask_setl(ssi, SSIFCR, 0,
- SSIFCR_TFRST | SSIFCR_RFRST);
-
- return 0;
-}
-
-static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int frames)
-{
- struct snd_pcm_substream *substream = strm->substream;
- struct snd_pcm_runtime *runtime;
- int current_period;
-
- if (!strm->running || !substream || !substream->runtime)
- return;
-
- runtime = substream->runtime;
- strm->buffer_pos += frames;
- WARN_ON(strm->buffer_pos > runtime->buffer_size);
-
- /* ring buffer */
- if (strm->buffer_pos == runtime->buffer_size)
- strm->buffer_pos = 0;
-
- current_period = strm->buffer_pos / runtime->period_size;
- if (strm->period_counter != current_period) {
- snd_pcm_period_elapsed(strm->substream);
- strm->period_counter = current_period;
- }
-}
-
-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;
- int i;
-
- if (!rz_ssi_stream_is_valid(ssi, strm))
- return -EINVAL;
-
- runtime = substream->runtime;
-
- do {
- /* frames left in this period */
- frames_left = runtime->period_size -
- (strm->buffer_pos % runtime->period_size);
- if (!frames_left)
- frames_left = runtime->period_size;
-
- /* Samples in RX FIFO */
- fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >>
- SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK;
-
- /* Only read full frames at a time */
- samples = 0;
- while (frames_left && (fifo_samples >= runtime->channels)) {
- samples += runtime->channels;
- fifo_samples -= runtime->channels;
- frames_left--;
- }
-
- /* not enough samples yet */
- if (!samples)
- break;
-
- /* calculate new buffer index */
- 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);
-
- rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
- rz_ssi_pointer_update(strm, samples / runtime->channels);
- } while (!frames_left && fifo_samples >= runtime->channels);
-
- return 0;
-}
-
-static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
-{
- struct snd_pcm_substream *substream = strm->substream;
- struct snd_pcm_runtime *runtime = substream->runtime;
- int sample_space;
- int samples = 0;
- int frames_left;
- int i;
- u32 ssifsr;
- u16 *buf;
-
- if (!rz_ssi_stream_is_valid(ssi, strm))
- return -EINVAL;
-
- /* frames left in this period */
- frames_left = runtime->period_size - (strm->buffer_pos %
- runtime->period_size);
- if (frames_left == 0)
- frames_left = runtime->period_size;
-
- sample_space = strm->fifo_sample_size;
- ssifsr = rz_ssi_reg_readl(ssi, SSIFSR);
- sample_space -= (ssifsr >> SSIFSR_TDC_SHIFT) & SSIFSR_TDC_MASK;
-
- /* Only add full frames at a time */
- while (frames_left && (sample_space >= runtime->channels)) {
- samples += runtime->channels;
- sample_space -= runtime->channels;
- frames_left--;
- }
-
- /* no space to send anything right now */
- if (samples == 0)
- return 0;
-
- /* calculate new buffer index */
- 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));
-
- rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_TDE, 0);
- rz_ssi_pointer_update(strm, samples / runtime->channels);
-
- return 0;
-}
-
-static irqreturn_t rz_ssi_interrupt(int irq, void *data)
-{
- struct rz_ssi_stream *strm = NULL;
- struct rz_ssi_priv *ssi = data;
- u32 ssisr = rz_ssi_reg_readl(ssi, SSISR);
-
- if (ssi->playback.substream)
- strm = &ssi->playback;
- else if (ssi->capture.substream)
- strm = &ssi->capture;
- else
- return IRQ_HANDLED; /* Left over TX/RX interrupt */
-
- if (irq == ssi->irq_int) { /* error or idle */
- if (ssisr & SSISR_TUIRQ)
- strm->uerr_num++;
- if (ssisr & SSISR_TOIRQ)
- strm->oerr_num++;
- if (ssisr & SSISR_RUIRQ)
- strm->uerr_num++;
- if (ssisr & SSISR_ROIRQ)
- strm->oerr_num++;
-
- if (ssisr & (SSISR_TUIRQ | SSISR_TOIRQ | SSISR_RUIRQ |
- SSISR_ROIRQ)) {
- /* Error handling */
- /* You must reset (stop/restart) after each interrupt */
- rz_ssi_stop(ssi, strm);
-
- /* Clear all flags */
- rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ |
- SSISR_TUIRQ | SSISR_ROIRQ |
- SSISR_RUIRQ, 0);
-
- /* Add/remove more data */
- strm->transfer(ssi, strm);
-
- /* Resume */
- rz_ssi_start(ssi, strm);
- }
- }
-
- if (!strm->running)
- return IRQ_HANDLED;
-
- /* tx data empty */
- if (irq == ssi->irq_tx)
- strm->transfer(ssi, &ssi->playback);
-
- /* rx data full */
- if (irq == ssi->irq_rx) {
- strm->transfer(ssi, &ssi->capture);
- rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
- }
-
- if (irq == ssi->irq_rt) {
- struct snd_pcm_substream *substream = strm->substream;
-
- if (rz_ssi_stream_is_play(ssi, substream)) {
- strm->transfer(ssi, &ssi->playback);
- } else {
- strm->transfer(ssi, &ssi->capture);
- rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static int rz_ssi_dma_slave_config(struct rz_ssi_priv *ssi,
- struct dma_chan *dma_ch, bool is_play)
-{
- struct dma_slave_config cfg;
-
- memset(&cfg, 0, sizeof(cfg));
-
- 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;
-
- return dmaengine_slave_config(dma_ch, &cfg);
-}
-
-static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi,
- struct rz_ssi_stream *strm)
-{
- struct snd_pcm_substream *substream = strm->substream;
- struct dma_async_tx_descriptor *desc;
- struct snd_pcm_runtime *runtime;
- enum dma_transfer_direction dir;
- u32 dma_paddr, dma_size;
- int amount;
-
- if (!rz_ssi_stream_is_valid(ssi, strm))
- return -EINVAL;
-
- runtime = substream->runtime;
- if (runtime->state == SNDRV_PCM_STATE_DRAINING)
- /*
- * Stream is ending, so do not queue up any more DMA
- * transfers otherwise we play partial sound clips
- * because we can't shut off the DMA quick enough.
- */
- return 0;
-
- dir = rz_ssi_stream_is_play(ssi, substream) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
-
- /* Always transfer 1 period */
- amount = runtime->period_size;
-
- /* DMA physical address and size */
- dma_paddr = runtime->dma_addr + frames_to_bytes(runtime,
- strm->dma_buffer_pos);
- dma_size = frames_to_bytes(runtime, amount);
- desc = dmaengine_prep_slave_single(strm->dma_ch, dma_paddr, dma_size,
- dir,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- dev_err(ssi->dev, "dmaengine_prep_slave_single() fail\n");
- return -ENOMEM;
- }
-
- desc->callback = rz_ssi_dma_complete;
- desc->callback_param = strm;
-
- if (dmaengine_submit(desc) < 0) {
- dev_err(ssi->dev, "dmaengine_submit() fail\n");
- return -EIO;
- }
-
- /* Update DMA pointer */
- strm->dma_buffer_pos += amount;
- if (strm->dma_buffer_pos >= runtime->buffer_size)
- strm->dma_buffer_pos = 0;
-
- /* Start DMA */
- dma_async_issue_pending(strm->dma_ch);
-
- return 0;
-}
-
-static void rz_ssi_dma_complete(void *data)
-{
- struct rz_ssi_stream *strm = (struct rz_ssi_stream *)data;
-
- if (!strm->running || !strm->substream || !strm->substream->runtime)
- return;
-
- /* Note that next DMA transaction has probably already started */
- rz_ssi_pointer_update(strm, strm->substream->runtime->period_size);
-
- /* Queue up another DMA transaction */
- rz_ssi_dma_transfer(strm->priv, strm);
-}
-
-static void rz_ssi_release_dma_channels(struct rz_ssi_priv *ssi)
-{
- if (ssi->playback.dma_ch) {
- dma_release_channel(ssi->playback.dma_ch);
- ssi->playback.dma_ch = NULL;
- if (ssi->dma_rt)
- ssi->dma_rt = false;
- }
-
- if (ssi->capture.dma_ch) {
- dma_release_channel(ssi->capture.dma_ch);
- ssi->capture.dma_ch = NULL;
- }
-}
-
-static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev)
-{
- ssi->playback.dma_ch = dma_request_chan(dev, "tx");
- if (IS_ERR(ssi->playback.dma_ch))
- ssi->playback.dma_ch = NULL;
-
- ssi->capture.dma_ch = dma_request_chan(dev, "rx");
- if (IS_ERR(ssi->capture.dma_ch))
- ssi->capture.dma_ch = NULL;
-
- if (!ssi->playback.dma_ch && !ssi->capture.dma_ch) {
- ssi->playback.dma_ch = dma_request_chan(dev, "rt");
- if (IS_ERR(ssi->playback.dma_ch)) {
- ssi->playback.dma_ch = NULL;
- goto no_dma;
- }
-
- ssi->dma_rt = true;
- }
-
- 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:
- rz_ssi_release_dma_channels(ssi);
-
- return -ENODEV;
-}
-
-static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
- struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
- int ret = 0, i, num_transfer = 1;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- /* Soft Reset */
- rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST);
- rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0);
- udelay(5);
-
- rz_ssi_stream_init(strm, substream);
-
- if (ssi->dma_rt) {
- bool is_playback;
-
- is_playback = rz_ssi_stream_is_play(ssi, substream);
- ret = rz_ssi_dma_slave_config(ssi, ssi->playback.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);
- }
- }
-
- /* 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);
- if (ret)
- goto done;
- }
-
- ret = rz_ssi_start(ssi, strm);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- rz_ssi_stop(ssi, strm);
- rz_ssi_stream_quit(ssi, strm);
- break;
- }
-
-done:
- return ret;
-}
-
-static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
- struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
-
- switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
- case SND_SOC_DAIFMT_BP_FP:
- break;
- default:
- dev_err(ssi->dev, "Codec should be clk and frame consumer\n");
- return -EINVAL;
- }
-
- /*
- * set clock polarity
- *
- * "normal" BCLK = Signal is available at rising edge of BCLK
- * "normal" FSYNC = (I2S) Left ch starts with falling FSYNC edge
- */
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- ssi->bckp_rise = false;
- ssi->lrckp_fsync_fall = false;
- break;
- case SND_SOC_DAIFMT_NB_IF:
- ssi->bckp_rise = false;
- ssi->lrckp_fsync_fall = true;
- break;
- case SND_SOC_DAIFMT_IB_NF:
- ssi->bckp_rise = true;
- ssi->lrckp_fsync_fall = false;
- break;
- case SND_SOC_DAIFMT_IB_IF:
- ssi->bckp_rise = true;
- ssi->lrckp_fsync_fall = true;
- break;
- default:
- return -EINVAL;
- }
-
- /* only i2s support */
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- break;
- default:
- dev_err(ssi->dev, "Only I2S mode is supported.\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
- unsigned int sample_bits = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
- unsigned int channels = params_channels(params);
-
- if (sample_bits != 16) {
- dev_err(ssi->dev, "Unsupported sample width: %d\n",
- sample_bits);
- return -EINVAL;
- }
-
- if (channels != 2) {
- dev_err(ssi->dev, "Number of channels not matched: %d\n",
- channels);
- return -EINVAL;
- }
-
- return rz_ssi_clk_setup(ssi, params_rate(params),
- params_channels(params));
-}
-
-static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
- .trigger = rz_ssi_dai_trigger,
- .set_fmt = rz_ssi_dai_set_fmt,
- .hw_params = rz_ssi_dai_hw_params,
-};
-
-static const struct snd_pcm_hardware rz_ssi_pcm_hardware = {
- .info = SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID,
- .buffer_bytes_max = PREALLOC_BUFFER,
- .period_bytes_min = 32,
- .period_bytes_max = 8192,
- .channels_min = SSI_CHAN_MIN,
- .channels_max = SSI_CHAN_MAX,
- .periods_min = 1,
- .periods_max = 32,
- .fifo_size = 32 * 2,
-};
-
-static int rz_ssi_pcm_open(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- snd_soc_set_runtime_hwparams(substream, &rz_ssi_pcm_hardware);
-
- return snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
-}
-
-static snd_pcm_uframes_t rz_ssi_pcm_pointer(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_soc_dai *dai = rz_ssi_get_dai(substream);
- struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
- struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
-
- return strm->buffer_pos;
-}
-
-static int rz_ssi_pcm_new(struct snd_soc_component *component,
- struct snd_soc_pcm_runtime *rtd)
-{
- snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
- rtd->card->snd_card->dev,
- PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
- return 0;
-}
-
-static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
- {
- .name = "rz-ssi-dai",
- .playback = {
- .rates = SSI_RATES,
- .formats = SSI_FMTS,
- .channels_min = SSI_CHAN_MIN,
- .channels_max = SSI_CHAN_MAX,
- },
- .capture = {
- .rates = SSI_RATES,
- .formats = SSI_FMTS,
- .channels_min = SSI_CHAN_MIN,
- .channels_max = SSI_CHAN_MAX,
- },
- .ops = &rz_ssi_dai_ops,
- },
-};
-
-static const struct snd_soc_component_driver rz_ssi_soc_component = {
- .name = "rz-ssi",
- .open = rz_ssi_pcm_open,
- .pointer = rz_ssi_pcm_pointer,
- .pcm_construct = rz_ssi_pcm_new,
- .legacy_dai_naming = 1,
-};
-
-static int rz_ssi_probe(struct platform_device *pdev)
-{
- struct rz_ssi_priv *ssi;
- struct clk *audio_clk;
- struct resource *res;
- int ret;
-
- ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL);
- if (!ssi)
- return -ENOMEM;
-
- ssi->pdev = pdev;
- ssi->dev = &pdev->dev;
- ssi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
- if (IS_ERR(ssi->base))
- return PTR_ERR(ssi->base);
-
- ssi->phys = res->start;
- ssi->clk = devm_clk_get(&pdev->dev, "ssi");
- if (IS_ERR(ssi->clk))
- return PTR_ERR(ssi->clk);
-
- ssi->sfr_clk = devm_clk_get(&pdev->dev, "ssi_sfr");
- if (IS_ERR(ssi->sfr_clk))
- return PTR_ERR(ssi->sfr_clk);
-
- audio_clk = devm_clk_get(&pdev->dev, "audio_clk1");
- if (IS_ERR(audio_clk))
- return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk),
- "no audio clk1");
-
- ssi->audio_clk_1 = clk_get_rate(audio_clk);
- audio_clk = devm_clk_get(&pdev->dev, "audio_clk2");
- if (IS_ERR(audio_clk))
- return dev_err_probe(&pdev->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");
-
- ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2;
-
- /* Detect DMA support */
- ret = rz_ssi_dma_request(ssi, &pdev->dev);
- if (ret < 0) {
- dev_warn(&pdev->dev, "DMA not available, using PIO\n");
- ssi->playback.transfer = rz_ssi_pio_send;
- ssi->capture.transfer = rz_ssi_pio_recv;
- } else {
- dev_info(&pdev->dev, "DMA enabled");
- ssi->playback.transfer = rz_ssi_dma_transfer;
- ssi->capture.transfer = rz_ssi_dma_transfer;
- }
-
- ssi->playback.priv = ssi;
- ssi->capture.priv = ssi;
-
- spin_lock_init(&ssi->lock);
- dev_set_drvdata(&pdev->dev, ssi);
-
- /* Error Interrupt */
- ssi->irq_int = platform_get_irq_byname(pdev, "int_req");
- if (ssi->irq_int < 0) {
- rz_ssi_release_dma_channels(ssi);
- return ssi->irq_int;
- }
-
- ret = devm_request_irq(&pdev->dev, ssi->irq_int, &rz_ssi_interrupt,
- 0, dev_name(&pdev->dev), ssi);
- if (ret < 0) {
- rz_ssi_release_dma_channels(ssi);
- return dev_err_probe(&pdev->dev, ret,
- "irq request error (int_req)\n");
- }
-
- if (!rz_ssi_is_dma_enabled(ssi)) {
- /* Tx and Rx interrupts (pio only) */
- ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx");
- ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx");
- if (ssi->irq_tx == -ENXIO && ssi->irq_rx == -ENXIO) {
- ssi->irq_rt = platform_get_irq_byname(pdev, "dma_rt");
- if (ssi->irq_rt < 0)
- return ssi->irq_rt;
-
- ret = devm_request_irq(&pdev->dev, ssi->irq_rt,
- &rz_ssi_interrupt, 0,
- dev_name(&pdev->dev), ssi);
- if (ret < 0)
- return dev_err_probe(&pdev->dev, ret,
- "irq request error (dma_rt)\n");
- } else {
- if (ssi->irq_tx < 0)
- return ssi->irq_tx;
-
- if (ssi->irq_rx < 0)
- return ssi->irq_rx;
-
- ret = devm_request_irq(&pdev->dev, ssi->irq_tx,
- &rz_ssi_interrupt, 0,
- dev_name(&pdev->dev), ssi);
- if (ret < 0)
- return dev_err_probe(&pdev->dev, ret,
- "irq request error (dma_tx)\n");
-
- ret = devm_request_irq(&pdev->dev, ssi->irq_rx,
- &rz_ssi_interrupt, 0,
- dev_name(&pdev->dev), ssi);
- if (ret < 0)
- return dev_err_probe(&pdev->dev, ret,
- "irq request error (dma_rx)\n");
- }
- }
-
- ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
- if (IS_ERR(ssi->rstc)) {
- ret = PTR_ERR(ssi->rstc);
- goto err_reset;
- }
-
- reset_control_deassert(ssi->rstc);
- pm_runtime_enable(&pdev->dev);
- ret = pm_runtime_resume_and_get(&pdev->dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "pm_runtime_resume_and_get failed\n");
- goto err_pm;
- }
-
- ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component,
- rz_ssi_soc_dai,
- ARRAY_SIZE(rz_ssi_soc_dai));
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to register snd component\n");
- goto err_snd_soc;
- }
-
- return 0;
-
-err_snd_soc:
- pm_runtime_put(ssi->dev);
-err_pm:
- pm_runtime_disable(ssi->dev);
- reset_control_assert(ssi->rstc);
-err_reset:
- rz_ssi_release_dma_channels(ssi);
-
- return ret;
-}
-
-static void rz_ssi_remove(struct platform_device *pdev)
-{
- struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev);
-
- rz_ssi_release_dma_channels(ssi);
-
- pm_runtime_put(ssi->dev);
- pm_runtime_disable(ssi->dev);
- reset_control_assert(ssi->rstc);
-}
-
-static const struct of_device_id rz_ssi_of_match[] = {
- { .compatible = "renesas,rz-ssi", },
- {/* Sentinel */},
-};
-MODULE_DEVICE_TABLE(of, rz_ssi_of_match);
-
-static struct platform_driver rz_ssi_driver = {
- .driver = {
- .name = "rz-ssi-pcm-audio",
- .of_match_table = rz_ssi_of_match,
- },
- .probe = rz_ssi_probe,
- .remove_new = rz_ssi_remove,
-};
-
-module_platform_driver(rz_ssi_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Renesas RZ/G2L ASoC Serial Sound Interface Driver");
-MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c
deleted file mode 100644
index d267243a159b..000000000000
--- a/sound/soc/sh/sh7760-ac97.c
+++ /dev/null
@@ -1,72 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Generic AC97 sound support for SH7760
-//
-// (c) 2007 Manuel Lauss
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <asm/io.h>
-
-#define IPSEL 0xFE400034
-
-SND_SOC_DAILINK_DEFS(ac97,
- DAILINK_COMP_ARRAY(COMP_CPU("hac-dai.0")), /* HAC0 */
- DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")),
- DAILINK_COMP_ARRAY(COMP_PLATFORM("sh7760-pcm-audio")));
-
-static struct snd_soc_dai_link sh7760_ac97_dai = {
- .name = "AC97",
- .stream_name = "AC97 HiFi",
- SND_SOC_DAILINK_REG(ac97),
-};
-
-static struct snd_soc_card sh7760_ac97_soc_machine = {
- .name = "SH7760 AC97",
- .owner = THIS_MODULE,
- .dai_link = &sh7760_ac97_dai,
- .num_links = 1,
-};
-
-static struct platform_device *sh7760_ac97_snd_device;
-
-static int __init sh7760_ac97_init(void)
-{
- int ret;
- unsigned short ipsel;
-
- /* enable both AC97 controllers in pinmux reg */
- ipsel = __raw_readw(IPSEL);
- __raw_writew(ipsel | (3 << 10), IPSEL);
-
- ret = -ENOMEM;
- sh7760_ac97_snd_device = platform_device_alloc("soc-audio", -1);
- if (!sh7760_ac97_snd_device)
- goto out;
-
- platform_set_drvdata(sh7760_ac97_snd_device,
- &sh7760_ac97_soc_machine);
- ret = platform_device_add(sh7760_ac97_snd_device);
-
- if (ret)
- platform_device_put(sh7760_ac97_snd_device);
-
-out:
- return ret;
-}
-
-static void __exit sh7760_ac97_exit(void)
-{
- platform_device_unregister(sh7760_ac97_snd_device);
-}
-
-module_init(sh7760_ac97_init);
-module_exit(sh7760_ac97_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Generic SH7760 AC97 sound machine");
-MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h
deleted file mode 100644
index a675c36fc9d9..000000000000
--- a/sound/soc/sh/siu.h
+++ /dev/null
@@ -1,180 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-//
-// siu.h - ALSA SoC driver for Renesas SH7343, SH7722 SIU peripheral.
-//
-// Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-// Copyright (C) 2006 Carlos Munoz <carlos@kenati.com>
-
-#ifndef SIU_H
-#define SIU_H
-
-/* Common kernel and user-space firmware-building defines and types */
-
-#define YRAM0_SIZE (0x0040 / 4) /* 16 */
-#define YRAM1_SIZE (0x0080 / 4) /* 32 */
-#define YRAM2_SIZE (0x0040 / 4) /* 16 */
-#define YRAM3_SIZE (0x0080 / 4) /* 32 */
-#define YRAM4_SIZE (0x0080 / 4) /* 32 */
-#define YRAM_DEF_SIZE (YRAM0_SIZE + YRAM1_SIZE + YRAM2_SIZE + \
- YRAM3_SIZE + YRAM4_SIZE)
-#define YRAM_FIR_SIZE (0x0400 / 4) /* 256 */
-#define YRAM_IIR_SIZE (0x0200 / 4) /* 128 */
-
-#define XRAM0_SIZE (0x0400 / 4) /* 256 */
-#define XRAM1_SIZE (0x0200 / 4) /* 128 */
-#define XRAM2_SIZE (0x0200 / 4) /* 128 */
-
-/* PRAM program array size */
-#define PRAM0_SIZE (0x0100 / 4) /* 64 */
-#define PRAM1_SIZE ((0x2000 - 0x0100) / 4) /* 1984 */
-
-#include <linux/types.h>
-
-struct siu_spb_param {
- __u32 ab1a; /* input FIFO address */
- __u32 ab0a; /* output FIFO address */
- __u32 dir; /* 0=the ather except CPUOUTPUT, 1=CPUINPUT */
- __u32 event; /* SPB program starting conditions */
- __u32 stfifo; /* STFIFO register setting value */
- __u32 trdat; /* TRDAT register setting value */
-};
-
-struct siu_firmware {
- __u32 yram_fir_coeff[YRAM_FIR_SIZE];
- __u32 pram0[PRAM0_SIZE];
- __u32 pram1[PRAM1_SIZE];
- __u32 yram0[YRAM0_SIZE];
- __u32 yram1[YRAM1_SIZE];
- __u32 yram2[YRAM2_SIZE];
- __u32 yram3[YRAM3_SIZE];
- __u32 yram4[YRAM4_SIZE];
- __u32 spbpar_num;
- struct siu_spb_param spbpar[32];
-};
-
-#ifdef __KERNEL__
-
-#include <linux/dmaengine.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/sh_dma.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-
-#define SIU_PERIOD_BYTES_MAX 8192 /* DMA transfer/period size */
-#define SIU_PERIOD_BYTES_MIN 256 /* DMA transfer/period size */
-#define SIU_PERIODS_MAX 64 /* Max periods in buffer */
-#define SIU_PERIODS_MIN 4 /* Min periods in buffer */
-#define SIU_BUFFER_BYTES_MAX (SIU_PERIOD_BYTES_MAX * SIU_PERIODS_MAX)
-
-/* SIU ports: only one can be used at a time */
-enum {
- SIU_PORT_A,
- SIU_PORT_B,
- SIU_PORT_NUM,
-};
-
-/* SIU clock configuration */
-enum {
- SIU_CLKA_PLL,
- SIU_CLKA_EXT,
- SIU_CLKB_PLL,
- SIU_CLKB_EXT
-};
-
-struct device;
-struct siu_info {
- struct device *dev;
- int port_id;
- u32 __iomem *pram;
- u32 __iomem *xram;
- u32 __iomem *yram;
- u32 __iomem *reg;
- struct siu_firmware fw;
-};
-
-struct siu_stream {
- struct work_struct work;
- struct snd_pcm_substream *substream;
- snd_pcm_format_t format;
- size_t buf_bytes;
- size_t period_bytes;
- int cur_period; /* Period currently in dma */
- u32 volume;
- snd_pcm_sframes_t xfer_cnt; /* Number of frames */
- u8 rw_flg; /* transfer status */
- /* DMA status */
- struct dma_chan *chan; /* DMA channel */
- struct dma_async_tx_descriptor *tx_desc;
- dma_cookie_t cookie;
- struct sh_dmae_slave param;
-};
-
-struct siu_port {
- unsigned long play_cap; /* Used to track full duplex */
- struct snd_pcm *pcm;
- struct siu_stream playback;
- struct siu_stream capture;
- u32 stfifo; /* STFIFO value from firmware */
- u32 trdat; /* TRDAT value from firmware */
-};
-
-extern struct siu_port *siu_ports[SIU_PORT_NUM];
-
-static inline struct siu_port *siu_port_info(struct snd_pcm_substream *substream)
-{
- struct platform_device *pdev =
- to_platform_device(substream->pcm->card->dev);
- return siu_ports[pdev->id];
-}
-
-/* Register access */
-static inline void siu_write32(u32 __iomem *addr, u32 val)
-{
- __raw_writel(val, addr);
-}
-
-static inline u32 siu_read32(u32 __iomem *addr)
-{
- return __raw_readl(addr);
-}
-
-/* SIU registers */
-#define SIU_IFCTL (0x000 / sizeof(u32))
-#define SIU_SRCTL (0x004 / sizeof(u32))
-#define SIU_SFORM (0x008 / sizeof(u32))
-#define SIU_CKCTL (0x00c / sizeof(u32))
-#define SIU_TRDAT (0x010 / sizeof(u32))
-#define SIU_STFIFO (0x014 / sizeof(u32))
-#define SIU_DPAK (0x01c / sizeof(u32))
-#define SIU_CKREV (0x020 / sizeof(u32))
-#define SIU_EVNTC (0x028 / sizeof(u32))
-#define SIU_SBCTL (0x040 / sizeof(u32))
-#define SIU_SBPSET (0x044 / sizeof(u32))
-#define SIU_SBFSTS (0x068 / sizeof(u32))
-#define SIU_SBDVCA (0x06c / sizeof(u32))
-#define SIU_SBDVCB (0x070 / sizeof(u32))
-#define SIU_SBACTIV (0x074 / sizeof(u32))
-#define SIU_DMAIA (0x090 / sizeof(u32))
-#define SIU_DMAIB (0x094 / sizeof(u32))
-#define SIU_DMAOA (0x098 / sizeof(u32))
-#define SIU_DMAOB (0x09c / sizeof(u32))
-#define SIU_DMAML (0x0a0 / sizeof(u32))
-#define SIU_SPSTS (0x0cc / sizeof(u32))
-#define SIU_SPCTL (0x0d0 / sizeof(u32))
-#define SIU_BRGASEL (0x100 / sizeof(u32))
-#define SIU_BRRA (0x104 / sizeof(u32))
-#define SIU_BRGBSEL (0x108 / sizeof(u32))
-#define SIU_BRRB (0x10c / sizeof(u32))
-
-extern const struct snd_soc_component_driver siu_component;
-extern struct siu_info *siu_i2s_data;
-
-int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card);
-void siu_free_port(struct siu_port *port_info);
-
-#endif
-
-#endif /* SIU_H */
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
deleted file mode 100644
index d0b5c543fd2f..000000000000
--- a/sound/soc/sh/siu_dai.c
+++ /dev/null
@@ -1,800 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-//
-// siu_dai.c - ALSA SoC driver for Renesas SH7343, SH7722 SIU peripheral.
-//
-// Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-// Copyright (C) 2006 Carlos Munoz <carlos@kenati.com>
-
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-#include <asm/clock.h>
-#include <asm/siu.h>
-
-#include <sound/control.h>
-#include <sound/soc.h>
-
-#include "siu.h"
-
-/* Board specifics */
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
-# define SIU_MAX_VOLUME 0x1000
-#else
-# define SIU_MAX_VOLUME 0x7fff
-#endif
-
-#define PRAM_SIZE 0x2000
-#define XRAM_SIZE 0x800
-#define YRAM_SIZE 0x800
-
-#define XRAM_OFFSET 0x4000
-#define YRAM_OFFSET 0x6000
-#define REG_OFFSET 0xc000
-
-#define PLAYBACK_ENABLED 1
-#define CAPTURE_ENABLED 2
-
-#define VOLUME_CAPTURE 0
-#define VOLUME_PLAYBACK 1
-#define DFLT_VOLUME_LEVEL 0x08000800
-
-/*
- * SPDIF is only available on port A and on some SIU implementations it is only
- * available for input. Due to the lack of hardware to test it, SPDIF is left
- * disabled in this driver version
- */
-struct format_flag {
- u32 i2s;
- u32 pcm;
- u32 spdif;
- u32 mask;
-};
-
-struct port_flag {
- struct format_flag playback;
- struct format_flag capture;
-};
-
-struct siu_info *siu_i2s_data;
-
-static struct port_flag siu_flags[SIU_PORT_NUM] = {
- [SIU_PORT_A] = {
- .playback = {
- .i2s = 0x50000000,
- .pcm = 0x40000000,
- .spdif = 0x80000000, /* not on all SIU versions */
- .mask = 0xd0000000,
- },
- .capture = {
- .i2s = 0x05000000,
- .pcm = 0x04000000,
- .spdif = 0x08000000,
- .mask = 0x0d000000,
- },
- },
- [SIU_PORT_B] = {
- .playback = {
- .i2s = 0x00500000,
- .pcm = 0x00400000,
- .spdif = 0, /* impossible - turn off */
- .mask = 0x00500000,
- },
- .capture = {
- .i2s = 0x00050000,
- .pcm = 0x00040000,
- .spdif = 0, /* impossible - turn off */
- .mask = 0x00050000,
- },
- },
-};
-
-static void siu_dai_start(struct siu_port *port_info)
-{
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
-
- dev_dbg(port_info->pcm->card->dev, "%s\n", __func__);
-
- /* Issue software reset to siu */
- siu_write32(base + SIU_SRCTL, 0);
-
- /* Wait for the reset to take effect */
- udelay(1);
-
- port_info->stfifo = 0;
- port_info->trdat = 0;
-
- /* portA, portB, SIU operate */
- siu_write32(base + SIU_SRCTL, 0x301);
-
- /* portA=256fs, portB=256fs */
- siu_write32(base + SIU_CKCTL, 0x40400000);
-
- /* portA's BRG does not divide SIUCKA */
- siu_write32(base + SIU_BRGASEL, 0);
- siu_write32(base + SIU_BRRA, 0);
-
- /* portB's BRG divides SIUCKB by half */
- siu_write32(base + SIU_BRGBSEL, 1);
- siu_write32(base + SIU_BRRB, 0);
-
- siu_write32(base + SIU_IFCTL, 0x44440000);
-
- /* portA: 32 bit/fs, master; portB: 32 bit/fs, master */
- siu_write32(base + SIU_SFORM, 0x0c0c0000);
-
- /*
- * Volume levels: looks like the DSP firmware implements volume controls
- * differently from what's described in the datasheet
- */
- siu_write32(base + SIU_SBDVCA, port_info->playback.volume);
- siu_write32(base + SIU_SBDVCB, port_info->capture.volume);
-}
-
-static void siu_dai_stop(struct siu_port *port_info)
-{
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
-
- /* SIU software reset */
- siu_write32(base + SIU_SRCTL, 0);
-}
-
-static void siu_dai_spbAselect(struct siu_port *port_info)
-{
- struct siu_info *info = siu_i2s_data;
- struct siu_firmware *fw = &info->fw;
- u32 *ydef = fw->yram0;
- u32 idx;
-
- /* path A use */
- if (!info->port_id)
- idx = 1; /* portA */
- else
- idx = 2; /* portB */
-
- ydef[0] = (fw->spbpar[idx].ab1a << 16) |
- (fw->spbpar[idx].ab0a << 8) |
- (fw->spbpar[idx].dir << 7) | 3;
- ydef[1] = fw->yram0[1]; /* 0x03000300 */
- ydef[2] = (16 / 2) << 24;
- ydef[3] = fw->yram0[3]; /* 0 */
- ydef[4] = fw->yram0[4]; /* 0 */
- ydef[7] = fw->spbpar[idx].event;
- port_info->stfifo |= fw->spbpar[idx].stfifo;
- port_info->trdat |= fw->spbpar[idx].trdat;
-}
-
-static void siu_dai_spbBselect(struct siu_port *port_info)
-{
- struct siu_info *info = siu_i2s_data;
- struct siu_firmware *fw = &info->fw;
- u32 *ydef = fw->yram0;
- u32 idx;
-
- /* path B use */
- if (!info->port_id)
- idx = 7; /* portA */
- else
- idx = 8; /* portB */
-
- ydef[5] = (fw->spbpar[idx].ab1a << 16) |
- (fw->spbpar[idx].ab0a << 8) | 1;
- ydef[6] = fw->spbpar[idx].event;
- port_info->stfifo |= fw->spbpar[idx].stfifo;
- port_info->trdat |= fw->spbpar[idx].trdat;
-}
-
-static void siu_dai_open(struct siu_stream *siu_stream)
-{
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
- u32 srctl, ifctl;
-
- srctl = siu_read32(base + SIU_SRCTL);
- ifctl = siu_read32(base + SIU_IFCTL);
-
- switch (info->port_id) {
- case SIU_PORT_A:
- /* portA operates */
- srctl |= 0x200;
- ifctl &= ~0xc2;
- break;
- case SIU_PORT_B:
- /* portB operates */
- srctl |= 0x100;
- ifctl &= ~0x31;
- break;
- }
-
- siu_write32(base + SIU_SRCTL, srctl);
- /* Unmute and configure portA */
- siu_write32(base + SIU_IFCTL, ifctl);
-}
-
-/*
- * At the moment only fixed Left-upper, Left-lower, Right-upper, Right-lower
- * packing is supported
- */
-static void siu_dai_pcmdatapack(struct siu_stream *siu_stream)
-{
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
- u32 dpak;
-
- dpak = siu_read32(base + SIU_DPAK);
-
- switch (info->port_id) {
- case SIU_PORT_A:
- dpak &= ~0xc0000000;
- break;
- case SIU_PORT_B:
- dpak &= ~0x00c00000;
- break;
- }
-
- siu_write32(base + SIU_DPAK, dpak);
-}
-
-static int siu_dai_spbstart(struct siu_port *port_info)
-{
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
- struct siu_firmware *fw = &info->fw;
- u32 *ydef = fw->yram0;
- int cnt;
- u32 __iomem *add;
- u32 *ptr;
-
- /* Load SPB Program in PRAM */
- ptr = fw->pram0;
- add = info->pram;
- for (cnt = 0; cnt < PRAM0_SIZE; cnt++, add++, ptr++)
- siu_write32(add, *ptr);
-
- ptr = fw->pram1;
- add = info->pram + (0x0100 / sizeof(u32));
- for (cnt = 0; cnt < PRAM1_SIZE; cnt++, add++, ptr++)
- siu_write32(add, *ptr);
-
- /* XRAM initialization */
- add = info->xram;
- for (cnt = 0; cnt < XRAM0_SIZE + XRAM1_SIZE + XRAM2_SIZE; cnt++, add++)
- siu_write32(add, 0);
-
- /* YRAM variable area initialization */
- add = info->yram;
- for (cnt = 0; cnt < YRAM_DEF_SIZE; cnt++, add++)
- siu_write32(add, ydef[cnt]);
-
- /* YRAM FIR coefficient area initialization */
- add = info->yram + (0x0200 / sizeof(u32));
- for (cnt = 0; cnt < YRAM_FIR_SIZE; cnt++, add++)
- siu_write32(add, fw->yram_fir_coeff[cnt]);
-
- /* YRAM IIR coefficient area initialization */
- add = info->yram + (0x0600 / sizeof(u32));
- for (cnt = 0; cnt < YRAM_IIR_SIZE; cnt++, add++)
- siu_write32(add, 0);
-
- siu_write32(base + SIU_TRDAT, port_info->trdat);
- port_info->trdat = 0x0;
-
-
- /* SPB start condition: software */
- siu_write32(base + SIU_SBACTIV, 0);
- /* Start SPB */
- siu_write32(base + SIU_SBCTL, 0xc0000000);
- /* Wait for program to halt */
- cnt = 0x10000;
- while (--cnt && siu_read32(base + SIU_SBCTL) != 0x80000000)
- cpu_relax();
-
- if (!cnt)
- return -EBUSY;
-
- /* SPB program start address setting */
- siu_write32(base + SIU_SBPSET, 0x00400000);
- /* SPB hardware start(FIFOCTL source) */
- siu_write32(base + SIU_SBACTIV, 0xc0000000);
-
- return 0;
-}
-
-static void siu_dai_spbstop(struct siu_port *port_info)
-{
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
-
- siu_write32(base + SIU_SBACTIV, 0);
- /* SPB stop */
- siu_write32(base + SIU_SBCTL, 0);
-
- port_info->stfifo = 0;
-}
-
-/* API functions */
-
-/* Playback and capture hardware properties are identical */
-static const struct snd_pcm_hardware siu_dai_pcm_hw = {
- .info = SNDRV_PCM_INFO_INTERLEAVED,
- .formats = SNDRV_PCM_FMTBIT_S16,
- .rates = SNDRV_PCM_RATE_8000_48000,
- .rate_min = 8000,
- .rate_max = 48000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = SIU_BUFFER_BYTES_MAX,
- .period_bytes_min = SIU_PERIOD_BYTES_MIN,
- .period_bytes_max = SIU_PERIOD_BYTES_MAX,
- .periods_min = SIU_PERIODS_MIN,
- .periods_max = SIU_PERIODS_MAX,
-};
-
-static int siu_dai_info_volume(struct snd_kcontrol *kctrl,
- struct snd_ctl_elem_info *uinfo)
-{
- struct siu_port *port_info = snd_kcontrol_chip(kctrl);
-
- dev_dbg(port_info->pcm->card->dev, "%s\n", __func__);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = SIU_MAX_VOLUME;
-
- return 0;
-}
-
-static int siu_dai_get_volume(struct snd_kcontrol *kctrl,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct siu_port *port_info = snd_kcontrol_chip(kctrl);
- struct device *dev = port_info->pcm->card->dev;
- u32 vol;
-
- dev_dbg(dev, "%s\n", __func__);
-
- switch (kctrl->private_value) {
- case VOLUME_PLAYBACK:
- /* Playback is always on port 0 */
- vol = port_info->playback.volume;
- ucontrol->value.integer.value[0] = vol & 0xffff;
- ucontrol->value.integer.value[1] = vol >> 16 & 0xffff;
- break;
- case VOLUME_CAPTURE:
- /* Capture is always on port 1 */
- vol = port_info->capture.volume;
- ucontrol->value.integer.value[0] = vol & 0xffff;
- ucontrol->value.integer.value[1] = vol >> 16 & 0xffff;
- break;
- default:
- dev_err(dev, "%s() invalid private_value=%ld\n",
- __func__, kctrl->private_value);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int siu_dai_put_volume(struct snd_kcontrol *kctrl,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct siu_port *port_info = snd_kcontrol_chip(kctrl);
- struct device *dev = port_info->pcm->card->dev;
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
- u32 new_vol;
- u32 cur_vol;
-
- dev_dbg(dev, "%s\n", __func__);
-
- if (ucontrol->value.integer.value[0] < 0 ||
- ucontrol->value.integer.value[0] > SIU_MAX_VOLUME ||
- ucontrol->value.integer.value[1] < 0 ||
- ucontrol->value.integer.value[1] > SIU_MAX_VOLUME)
- return -EINVAL;
-
- new_vol = ucontrol->value.integer.value[0] |
- ucontrol->value.integer.value[1] << 16;
-
- /* See comment above - DSP firmware implementation */
- switch (kctrl->private_value) {
- case VOLUME_PLAYBACK:
- /* Playback is always on port 0 */
- cur_vol = port_info->playback.volume;
- siu_write32(base + SIU_SBDVCA, new_vol);
- port_info->playback.volume = new_vol;
- break;
- case VOLUME_CAPTURE:
- /* Capture is always on port 1 */
- cur_vol = port_info->capture.volume;
- siu_write32(base + SIU_SBDVCB, new_vol);
- port_info->capture.volume = new_vol;
- break;
- default:
- dev_err(dev, "%s() invalid private_value=%ld\n",
- __func__, kctrl->private_value);
- return -EINVAL;
- }
-
- if (cur_vol != new_vol)
- return 1;
-
- return 0;
-}
-
-static const struct snd_kcontrol_new playback_controls = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Playback Volume",
- .index = 0,
- .info = siu_dai_info_volume,
- .get = siu_dai_get_volume,
- .put = siu_dai_put_volume,
- .private_value = VOLUME_PLAYBACK,
-};
-
-static const struct snd_kcontrol_new capture_controls = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Capture Volume",
- .index = 0,
- .info = siu_dai_info_volume,
- .get = siu_dai_get_volume,
- .put = siu_dai_put_volume,
- .private_value = VOLUME_CAPTURE,
-};
-
-int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card)
-{
- struct device *dev = card->dev;
- struct snd_kcontrol *kctrl;
- int ret;
-
- *port_info = kzalloc(sizeof(**port_info), GFP_KERNEL);
- if (!*port_info)
- return -ENOMEM;
-
- dev_dbg(dev, "%s: port #%d@%p\n", __func__, port, *port_info);
-
- (*port_info)->playback.volume = DFLT_VOLUME_LEVEL;
- (*port_info)->capture.volume = DFLT_VOLUME_LEVEL;
-
- /*
- * Add mixer support. The SPB is used to change the volume. Both
- * ports use the same SPB. Therefore, we only register one
- * control instance since it will be used by both channels.
- * In error case we continue without controls.
- */
- kctrl = snd_ctl_new1(&playback_controls, *port_info);
- ret = snd_ctl_add(card, kctrl);
- if (ret < 0)
- dev_err(dev,
- "failed to add playback controls %p port=%d err=%d\n",
- kctrl, port, ret);
-
- kctrl = snd_ctl_new1(&capture_controls, *port_info);
- ret = snd_ctl_add(card, kctrl);
- if (ret < 0)
- dev_err(dev,
- "failed to add capture controls %p port=%d err=%d\n",
- kctrl, port, ret);
-
- return 0;
-}
-
-void siu_free_port(struct siu_port *port_info)
-{
- kfree(port_info);
-}
-
-static int siu_dai_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct siu_info *info = snd_soc_dai_get_drvdata(dai);
- struct snd_pcm_runtime *rt = substream->runtime;
- struct siu_port *port_info = siu_port_info(substream);
- int ret;
-
- dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__,
- info->port_id, port_info);
-
- snd_soc_set_runtime_hwparams(substream, &siu_dai_pcm_hw);
-
- ret = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
- if (unlikely(ret < 0))
- return ret;
-
- siu_dai_start(port_info);
-
- return 0;
-}
-
-static void siu_dai_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct siu_info *info = snd_soc_dai_get_drvdata(dai);
- struct siu_port *port_info = siu_port_info(substream);
-
- dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__,
- info->port_id, port_info);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- port_info->play_cap &= ~PLAYBACK_ENABLED;
- else
- port_info->play_cap &= ~CAPTURE_ENABLED;
-
- /* Stop the siu if the other stream is not using it */
- if (!port_info->play_cap) {
- /* during stmread or stmwrite ? */
- if (WARN_ON(port_info->playback.rw_flg || port_info->capture.rw_flg))
- return;
- siu_dai_spbstop(port_info);
- siu_dai_stop(port_info);
- }
-}
-
-/* PCM part of siu_dai_playback_prepare() / siu_dai_capture_prepare() */
-static int siu_dai_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct siu_info *info = snd_soc_dai_get_drvdata(dai);
- struct snd_pcm_runtime *rt = substream->runtime;
- struct siu_port *port_info = siu_port_info(substream);
- struct siu_stream *siu_stream;
- int self, ret;
-
- dev_dbg(substream->pcm->card->dev,
- "%s: port %d, active streams %lx, %d channels\n",
- __func__, info->port_id, port_info->play_cap, rt->channels);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- self = PLAYBACK_ENABLED;
- siu_stream = &port_info->playback;
- } else {
- self = CAPTURE_ENABLED;
- siu_stream = &port_info->capture;
- }
-
- /* Set up the siu if not already done */
- if (!port_info->play_cap) {
- siu_stream->rw_flg = 0; /* stream-data transfer flag */
-
- siu_dai_spbAselect(port_info);
- siu_dai_spbBselect(port_info);
-
- siu_dai_open(siu_stream);
-
- siu_dai_pcmdatapack(siu_stream);
-
- ret = siu_dai_spbstart(port_info);
- if (ret < 0)
- goto fail;
- } else {
- ret = 0;
- }
-
- port_info->play_cap |= self;
-
-fail:
- return ret;
-}
-
-/*
- * SIU can set bus format to I2S / PCM / SPDIF independently for playback and
- * capture, however, the current API sets the bus format globally for a DAI.
- */
-static int siu_dai_set_fmt(struct snd_soc_dai *dai,
- unsigned int fmt)
-{
- struct siu_info *info = snd_soc_dai_get_drvdata(dai);
- u32 __iomem *base = info->reg;
- u32 ifctl;
-
- dev_dbg(dai->dev, "%s: fmt 0x%x on port %d\n",
- __func__, fmt, info->port_id);
-
- if (info->port_id < 0)
- return -ENODEV;
-
- /* Here select between I2S / PCM / SPDIF */
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- ifctl = siu_flags[info->port_id].playback.i2s |
- siu_flags[info->port_id].capture.i2s;
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- ifctl = siu_flags[info->port_id].playback.pcm |
- siu_flags[info->port_id].capture.pcm;
- break;
- /* SPDIF disabled - see comment at the top */
- default:
- return -EINVAL;
- }
-
- ifctl |= ~(siu_flags[info->port_id].playback.mask |
- siu_flags[info->port_id].capture.mask) &
- siu_read32(base + SIU_IFCTL);
- siu_write32(base + SIU_IFCTL, ifctl);
-
- return 0;
-}
-
-static int siu_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
- unsigned int freq, int dir)
-{
- struct clk *siu_clk, *parent_clk;
- char *siu_name, *parent_name;
- int ret;
-
- if (dir != SND_SOC_CLOCK_IN)
- return -EINVAL;
-
- dev_dbg(dai->dev, "%s: using clock %d\n", __func__, clk_id);
-
- switch (clk_id) {
- case SIU_CLKA_PLL:
- siu_name = "siua_clk";
- parent_name = "pll_clk";
- break;
- case SIU_CLKA_EXT:
- siu_name = "siua_clk";
- parent_name = "siumcka_clk";
- break;
- case SIU_CLKB_PLL:
- siu_name = "siub_clk";
- parent_name = "pll_clk";
- break;
- case SIU_CLKB_EXT:
- siu_name = "siub_clk";
- parent_name = "siumckb_clk";
- break;
- default:
- return -EINVAL;
- }
-
- siu_clk = clk_get(dai->dev, siu_name);
- if (IS_ERR(siu_clk)) {
- dev_err(dai->dev, "%s: cannot get a SIU clock: %ld\n", __func__,
- PTR_ERR(siu_clk));
- return PTR_ERR(siu_clk);
- }
-
- parent_clk = clk_get(dai->dev, parent_name);
- if (IS_ERR(parent_clk)) {
- ret = PTR_ERR(parent_clk);
- dev_err(dai->dev, "cannot get a SIU clock parent: %d\n", ret);
- goto epclkget;
- }
-
- ret = clk_set_parent(siu_clk, parent_clk);
- if (ret < 0) {
- dev_err(dai->dev, "cannot reparent the SIU clock: %d\n", ret);
- goto eclksetp;
- }
-
- ret = clk_set_rate(siu_clk, freq);
- if (ret < 0)
- dev_err(dai->dev, "cannot set SIU clock rate: %d\n", ret);
-
- /* TODO: when clkdev gets reference counting we'll move these to siu_dai_shutdown() */
-eclksetp:
- clk_put(parent_clk);
-epclkget:
- clk_put(siu_clk);
-
- return ret;
-}
-
-static const struct snd_soc_dai_ops siu_dai_ops = {
- .startup = siu_dai_startup,
- .shutdown = siu_dai_shutdown,
- .prepare = siu_dai_prepare,
- .set_sysclk = siu_dai_set_sysclk,
- .set_fmt = siu_dai_set_fmt,
-};
-
-static struct snd_soc_dai_driver siu_i2s_dai = {
- .name = "siu-i2s-dai",
- .playback = {
- .channels_min = 2,
- .channels_max = 2,
- .formats = SNDRV_PCM_FMTBIT_S16,
- .rates = SNDRV_PCM_RATE_8000_48000,
- },
- .capture = {
- .channels_min = 2,
- .channels_max = 2,
- .formats = SNDRV_PCM_FMTBIT_S16,
- .rates = SNDRV_PCM_RATE_8000_48000,
- },
- .ops = &siu_dai_ops,
-};
-
-static int siu_probe(struct platform_device *pdev)
-{
- const struct firmware *fw_entry;
- struct resource *res, *region;
- struct siu_info *info;
- int ret;
-
- info = devm_kmalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
- siu_i2s_data = info;
- info->dev = &pdev->dev;
-
- ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev);
- if (ret)
- return ret;
-
- /*
- * Loaded firmware is "const" - read only, but we have to modify it in
- * snd_siu_sh7343_spbAselect() and snd_siu_sh7343_spbBselect()
- */
- memcpy(&info->fw, fw_entry->data, fw_entry->size);
-
- release_firmware(fw_entry);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- region = devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res), pdev->name);
- if (!region) {
- dev_err(&pdev->dev, "SIU region already claimed\n");
- return -EBUSY;
- }
-
- info->pram = devm_ioremap(&pdev->dev, res->start, PRAM_SIZE);
- if (!info->pram)
- return -ENOMEM;
- info->xram = devm_ioremap(&pdev->dev, res->start + XRAM_OFFSET,
- XRAM_SIZE);
- if (!info->xram)
- return -ENOMEM;
- info->yram = devm_ioremap(&pdev->dev, res->start + YRAM_OFFSET,
- YRAM_SIZE);
- if (!info->yram)
- return -ENOMEM;
- info->reg = devm_ioremap(&pdev->dev, res->start + REG_OFFSET,
- resource_size(res) - REG_OFFSET);
- if (!info->reg)
- return -ENOMEM;
-
- dev_set_drvdata(&pdev->dev, info);
-
- /* register using ARRAY version so we can keep dai name */
- ret = devm_snd_soc_register_component(&pdev->dev, &siu_component,
- &siu_i2s_dai, 1);
- if (ret < 0)
- return ret;
-
- pm_runtime_enable(&pdev->dev);
-
- return 0;
-}
-
-static void siu_remove(struct platform_device *pdev)
-{
- pm_runtime_disable(&pdev->dev);
-}
-
-static struct platform_driver siu_driver = {
- .driver = {
- .name = "siu-pcm-audio",
- },
- .probe = siu_probe,
- .remove_new = siu_remove,
-};
-
-module_platform_driver(siu_driver);
-
-MODULE_AUTHOR("Carlos Munoz <carlos@kenati.com>");
-MODULE_DESCRIPTION("ALSA SoC SH7722 SIU driver");
-MODULE_LICENSE("GPL");
-
-MODULE_FIRMWARE("siu_spb.bin");
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
deleted file mode 100644
index f15ff36e7934..000000000000
--- a/sound/soc/sh/siu_pcm.c
+++ /dev/null
@@ -1,553 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-//
-// siu_pcm.c - ALSA driver for Renesas SH7343, SH7722 SIU peripheral.
-//
-// Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-// Copyright (C) 2006 Carlos Munoz <carlos@kenati.com>
-
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmaengine.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <sound/control.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <asm/siu.h>
-
-#include "siu.h"
-
-#define DRV_NAME "siu-i2s"
-#define GET_MAX_PERIODS(buf_bytes, period_bytes) \
- ((buf_bytes) / (period_bytes))
-#define PERIOD_OFFSET(buf_addr, period_num, period_bytes) \
- ((buf_addr) + ((period_num) * (period_bytes)))
-
-#define RWF_STM_RD 0x01 /* Read in progress */
-#define RWF_STM_WT 0x02 /* Write in progress */
-
-struct siu_port *siu_ports[SIU_PORT_NUM];
-
-/* transfersize is number of u32 dma transfers per period */
-static int siu_pcm_stmwrite_stop(struct siu_port *port_info)
-{
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
- struct siu_stream *siu_stream = &port_info->playback;
- u32 stfifo;
-
- if (!siu_stream->rw_flg)
- return -EPERM;
-
- /* output FIFO disable */
- stfifo = siu_read32(base + SIU_STFIFO);
- siu_write32(base + SIU_STFIFO, stfifo & ~0x0c180c18);
- pr_debug("%s: STFIFO %x -> %x\n", __func__,
- stfifo, stfifo & ~0x0c180c18);
-
- /* during stmwrite clear */
- siu_stream->rw_flg = 0;
-
- return 0;
-}
-
-static int siu_pcm_stmwrite_start(struct siu_port *port_info)
-{
- struct siu_stream *siu_stream = &port_info->playback;
-
- if (siu_stream->rw_flg)
- return -EPERM;
-
- /* Current period in buffer */
- port_info->playback.cur_period = 0;
-
- /* during stmwrite flag set */
- siu_stream->rw_flg = RWF_STM_WT;
-
- /* DMA transfer start */
- queue_work(system_highpri_wq, &siu_stream->work);
-
- return 0;
-}
-
-static void siu_dma_tx_complete(void *arg)
-{
- struct siu_stream *siu_stream = arg;
-
- if (!siu_stream->rw_flg)
- return;
-
- /* Update completed period count */
- if (++siu_stream->cur_period >=
- GET_MAX_PERIODS(siu_stream->buf_bytes,
- siu_stream->period_bytes))
- siu_stream->cur_period = 0;
-
- pr_debug("%s: done period #%d (%u/%u bytes), cookie %d\n",
- __func__, siu_stream->cur_period,
- siu_stream->cur_period * siu_stream->period_bytes,
- siu_stream->buf_bytes, siu_stream->cookie);
-
- queue_work(system_highpri_wq, &siu_stream->work);
-
- /* Notify alsa: a period is done */
- snd_pcm_period_elapsed(siu_stream->substream);
-}
-
-static int siu_pcm_wr_set(struct siu_port *port_info,
- dma_addr_t buff, u32 size)
-{
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
- struct siu_stream *siu_stream = &port_info->playback;
- struct snd_pcm_substream *substream = siu_stream->substream;
- struct device *dev = substream->pcm->card->dev;
- struct dma_async_tx_descriptor *desc;
- dma_cookie_t cookie;
- struct scatterlist sg;
- u32 stfifo;
-
- sg_init_table(&sg, 1);
- sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)),
- size, offset_in_page(buff));
- sg_dma_len(&sg) = size;
- sg_dma_address(&sg) = buff;
-
- desc = dmaengine_prep_slave_sg(siu_stream->chan,
- &sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- dev_err(dev, "Failed to allocate a dma descriptor\n");
- return -ENOMEM;
- }
-
- desc->callback = siu_dma_tx_complete;
- desc->callback_param = siu_stream;
- cookie = dmaengine_submit(desc);
- if (cookie < 0) {
- dev_err(dev, "Failed to submit a dma transfer\n");
- return cookie;
- }
-
- siu_stream->tx_desc = desc;
- siu_stream->cookie = cookie;
-
- dma_async_issue_pending(siu_stream->chan);
-
- /* only output FIFO enable */
- stfifo = siu_read32(base + SIU_STFIFO);
- siu_write32(base + SIU_STFIFO, stfifo | (port_info->stfifo & 0x0c180c18));
- dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__,
- stfifo, stfifo | (port_info->stfifo & 0x0c180c18));
-
- return 0;
-}
-
-static int siu_pcm_rd_set(struct siu_port *port_info,
- dma_addr_t buff, size_t size)
-{
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
- struct siu_stream *siu_stream = &port_info->capture;
- struct snd_pcm_substream *substream = siu_stream->substream;
- struct device *dev = substream->pcm->card->dev;
- struct dma_async_tx_descriptor *desc;
- dma_cookie_t cookie;
- struct scatterlist sg;
- u32 stfifo;
-
- dev_dbg(dev, "%s: %u@%llx\n", __func__, size, (unsigned long long)buff);
-
- sg_init_table(&sg, 1);
- sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)),
- size, offset_in_page(buff));
- sg_dma_len(&sg) = size;
- sg_dma_address(&sg) = buff;
-
- desc = dmaengine_prep_slave_sg(siu_stream->chan,
- &sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- dev_err(dev, "Failed to allocate dma descriptor\n");
- return -ENOMEM;
- }
-
- desc->callback = siu_dma_tx_complete;
- desc->callback_param = siu_stream;
- cookie = dmaengine_submit(desc);
- if (cookie < 0) {
- dev_err(dev, "Failed to submit dma descriptor\n");
- return cookie;
- }
-
- siu_stream->tx_desc = desc;
- siu_stream->cookie = cookie;
-
- dma_async_issue_pending(siu_stream->chan);
-
- /* only input FIFO enable */
- stfifo = siu_read32(base + SIU_STFIFO);
- siu_write32(base + SIU_STFIFO, siu_read32(base + SIU_STFIFO) |
- (port_info->stfifo & 0x13071307));
- dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__,
- stfifo, stfifo | (port_info->stfifo & 0x13071307));
-
- return 0;
-}
-
-static void siu_io_work(struct work_struct *work)
-{
- struct siu_stream *siu_stream = container_of(work, struct siu_stream,
- work);
- struct snd_pcm_substream *substream = siu_stream->substream;
- struct device *dev = substream->pcm->card->dev;
- struct snd_pcm_runtime *rt = substream->runtime;
- struct siu_port *port_info = siu_port_info(substream);
-
- dev_dbg(dev, "%s: flags %x\n", __func__, siu_stream->rw_flg);
-
- if (!siu_stream->rw_flg) {
- dev_dbg(dev, "%s: stream inactive\n", __func__);
- return;
- }
-
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- dma_addr_t buff;
- size_t count;
-
- buff = (dma_addr_t)PERIOD_OFFSET(rt->dma_addr,
- siu_stream->cur_period,
- siu_stream->period_bytes);
- count = siu_stream->period_bytes;
-
- /* DMA transfer start */
- siu_pcm_rd_set(port_info, buff, count);
- } else {
- siu_pcm_wr_set(port_info,
- (dma_addr_t)PERIOD_OFFSET(rt->dma_addr,
- siu_stream->cur_period,
- siu_stream->period_bytes),
- siu_stream->period_bytes);
- }
-}
-
-/* Capture */
-static int siu_pcm_stmread_start(struct siu_port *port_info)
-{
- struct siu_stream *siu_stream = &port_info->capture;
-
- if (siu_stream->xfer_cnt > 0x1000000)
- return -EINVAL;
- if (siu_stream->rw_flg)
- return -EPERM;
-
- /* Current period in buffer */
- siu_stream->cur_period = 0;
-
- /* during stmread flag set */
- siu_stream->rw_flg = RWF_STM_RD;
-
- queue_work(system_highpri_wq, &siu_stream->work);
-
- return 0;
-}
-
-static int siu_pcm_stmread_stop(struct siu_port *port_info)
-{
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
- struct siu_stream *siu_stream = &port_info->capture;
- struct device *dev = siu_stream->substream->pcm->card->dev;
- u32 stfifo;
-
- if (!siu_stream->rw_flg)
- return -EPERM;
-
- /* input FIFO disable */
- stfifo = siu_read32(base + SIU_STFIFO);
- siu_write32(base + SIU_STFIFO, stfifo & ~0x13071307);
- dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__,
- stfifo, stfifo & ~0x13071307);
-
- /* during stmread flag clear */
- siu_stream->rw_flg = 0;
-
- return 0;
-}
-
-static bool filter(struct dma_chan *chan, void *secondary)
-{
- struct sh_dmae_slave *param = secondary;
-
- pr_debug("%s: secondary ID %d\n", __func__, param->shdma_slave.slave_id);
-
- chan->private = &param->shdma_slave;
- return true;
-}
-
-static int siu_pcm_open(struct snd_soc_component *component,
- struct snd_pcm_substream *ss)
-{
- /* Playback / Capture */
- struct siu_platform *pdata = component->dev->platform_data;
- struct siu_info *info = siu_i2s_data;
- struct siu_port *port_info = siu_port_info(ss);
- struct siu_stream *siu_stream;
- u32 port = info->port_id;
- struct device *dev = ss->pcm->card->dev;
- dma_cap_mask_t mask;
- struct sh_dmae_slave *param;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- dev_dbg(dev, "%s, port=%d@%p\n", __func__, port, port_info);
-
- if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- siu_stream = &port_info->playback;
- param = &siu_stream->param;
- param->shdma_slave.slave_id = port ? pdata->dma_slave_tx_b :
- pdata->dma_slave_tx_a;
- } else {
- siu_stream = &port_info->capture;
- param = &siu_stream->param;
- param->shdma_slave.slave_id = port ? pdata->dma_slave_rx_b :
- pdata->dma_slave_rx_a;
- }
-
- /* Get DMA channel */
- siu_stream->chan = dma_request_channel(mask, filter, param);
- if (!siu_stream->chan) {
- dev_err(dev, "DMA channel allocation failed!\n");
- return -EBUSY;
- }
-
- siu_stream->substream = ss;
-
- return 0;
-}
-
-static int siu_pcm_close(struct snd_soc_component *component,
- struct snd_pcm_substream *ss)
-{
- struct siu_info *info = siu_i2s_data;
- struct device *dev = ss->pcm->card->dev;
- struct siu_port *port_info = siu_port_info(ss);
- struct siu_stream *siu_stream;
-
- dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id);
-
- if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
- siu_stream = &port_info->playback;
- else
- siu_stream = &port_info->capture;
-
- dma_release_channel(siu_stream->chan);
- siu_stream->chan = NULL;
-
- siu_stream->substream = NULL;
-
- return 0;
-}
-
-static int siu_pcm_prepare(struct snd_soc_component *component,
- struct snd_pcm_substream *ss)
-{
- struct siu_info *info = siu_i2s_data;
- struct siu_port *port_info = siu_port_info(ss);
- struct device *dev = ss->pcm->card->dev;
- struct snd_pcm_runtime *rt;
- struct siu_stream *siu_stream;
- snd_pcm_sframes_t xfer_cnt;
-
- if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
- siu_stream = &port_info->playback;
- else
- siu_stream = &port_info->capture;
-
- rt = siu_stream->substream->runtime;
-
- siu_stream->buf_bytes = snd_pcm_lib_buffer_bytes(ss);
- siu_stream->period_bytes = snd_pcm_lib_period_bytes(ss);
-
- dev_dbg(dev, "%s: port=%d, %d channels, period=%u bytes\n", __func__,
- info->port_id, rt->channels, siu_stream->period_bytes);
-
- /* We only support buffers that are multiples of the period */
- if (siu_stream->buf_bytes % siu_stream->period_bytes) {
- dev_err(dev, "%s() - buffer=%d not multiple of period=%d\n",
- __func__, siu_stream->buf_bytes,
- siu_stream->period_bytes);
- return -EINVAL;
- }
-
- xfer_cnt = bytes_to_frames(rt, siu_stream->period_bytes);
- if (!xfer_cnt || xfer_cnt > 0x1000000)
- return -EINVAL;
-
- siu_stream->format = rt->format;
- siu_stream->xfer_cnt = xfer_cnt;
-
- dev_dbg(dev, "port=%d buf=%lx buf_bytes=%d period_bytes=%d "
- "format=%d channels=%d xfer_cnt=%d\n", info->port_id,
- (unsigned long)rt->dma_addr, siu_stream->buf_bytes,
- siu_stream->period_bytes,
- siu_stream->format, rt->channels, (int)xfer_cnt);
-
- return 0;
-}
-
-static int siu_pcm_trigger(struct snd_soc_component *component,
- struct snd_pcm_substream *ss, int cmd)
-{
- struct siu_info *info = siu_i2s_data;
- struct device *dev = ss->pcm->card->dev;
- struct siu_port *port_info = siu_port_info(ss);
- int ret;
-
- dev_dbg(dev, "%s: port=%d@%p, cmd=%d\n", __func__,
- info->port_id, port_info, cmd);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
- ret = siu_pcm_stmwrite_start(port_info);
- else
- ret = siu_pcm_stmread_start(port_info);
-
- if (ret < 0)
- dev_warn(dev, "%s: start failed on port=%d\n",
- __func__, info->port_id);
-
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
- siu_pcm_stmwrite_stop(port_info);
- else
- siu_pcm_stmread_stop(port_info);
- ret = 0;
-
- break;
- default:
- dev_err(dev, "%s() unsupported cmd=%d\n", __func__, cmd);
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-/*
- * So far only resolution of one period is supported, subject to extending the
- * dmangine API
- */
-static snd_pcm_uframes_t
-siu_pcm_pointer_dma(struct snd_soc_component *component,
- struct snd_pcm_substream *ss)
-{
- struct device *dev = ss->pcm->card->dev;
- struct siu_info *info = siu_i2s_data;
- u32 __iomem *base = info->reg;
- struct siu_port *port_info = siu_port_info(ss);
- struct snd_pcm_runtime *rt = ss->runtime;
- size_t ptr;
- struct siu_stream *siu_stream;
-
- if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
- siu_stream = &port_info->playback;
- else
- siu_stream = &port_info->capture;
-
- /*
- * ptr is the offset into the buffer where the dma is currently at. We
- * check if the dma buffer has just wrapped.
- */
- ptr = PERIOD_OFFSET(rt->dma_addr,
- siu_stream->cur_period,
- siu_stream->period_bytes) - rt->dma_addr;
-
- dev_dbg(dev,
- "%s: port=%d, events %x, FSTS %x, xferred %u/%u, cookie %d\n",
- __func__, info->port_id, siu_read32(base + SIU_EVNTC),
- siu_read32(base + SIU_SBFSTS), ptr, siu_stream->buf_bytes,
- siu_stream->cookie);
-
- if (ptr >= siu_stream->buf_bytes)
- ptr = 0;
-
- return bytes_to_frames(ss->runtime, ptr);
-}
-
-static int siu_pcm_new(struct snd_soc_component *component,
- struct snd_soc_pcm_runtime *rtd)
-{
- /* card->dev == socdev->dev, see snd_soc_new_pcms() */
- struct snd_card *card = rtd->card->snd_card;
- struct snd_pcm *pcm = rtd->pcm;
- struct siu_info *info = siu_i2s_data;
- struct platform_device *pdev = to_platform_device(card->dev);
- int ret;
- int i;
-
- /* pdev->id selects between SIUA and SIUB */
- if (pdev->id < 0 || pdev->id >= SIU_PORT_NUM)
- return -EINVAL;
-
- info->port_id = pdev->id;
-
- /*
- * While the siu has 2 ports, only one port can be on at a time (only 1
- * SPB). So far all the boards using the siu had only one of the ports
- * wired to a codec. To simplify things, we only register one port with
- * alsa. In case both ports are needed, it should be changed here
- */
- for (i = pdev->id; i < pdev->id + 1; i++) {
- struct siu_port **port_info = &siu_ports[i];
-
- ret = siu_init_port(i, port_info, card);
- if (ret < 0)
- return ret;
-
- snd_pcm_set_managed_buffer_all(pcm,
- SNDRV_DMA_TYPE_DEV, card->dev,
- SIU_BUFFER_BYTES_MAX, SIU_BUFFER_BYTES_MAX);
-
- (*port_info)->pcm = pcm;
-
- /* IO works */
- INIT_WORK(&(*port_info)->playback.work, siu_io_work);
- INIT_WORK(&(*port_info)->capture.work, siu_io_work);
- }
-
- dev_info(card->dev, "SuperH SIU driver initialized.\n");
- return 0;
-}
-
-static void siu_pcm_free(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct platform_device *pdev = to_platform_device(pcm->card->dev);
- struct siu_port *port_info = siu_ports[pdev->id];
-
- cancel_work_sync(&port_info->capture.work);
- cancel_work_sync(&port_info->playback.work);
-
- siu_free_port(port_info);
-
- dev_dbg(pcm->card->dev, "%s\n", __func__);
-}
-
-const struct snd_soc_component_driver siu_component = {
- .name = DRV_NAME,
- .open = siu_pcm_open,
- .close = siu_pcm_close,
- .prepare = siu_pcm_prepare,
- .trigger = siu_pcm_trigger,
- .pointer = siu_pcm_pointer_dma,
- .pcm_construct = siu_pcm_new,
- .pcm_destruct = siu_pcm_free,
- .legacy_dai_naming = 1,
-};
-EXPORT_SYMBOL_GPL(siu_component);
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
deleted file mode 100644
index 96cf523c2273..000000000000
--- a/sound/soc/sh/ssi.c
+++ /dev/null
@@ -1,403 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Serial Sound Interface (I2S) support for SH7760/SH7780
-//
-// Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net>
-//
-// dont forget to set IPSEL/OMSEL register bits (in your board code) to
-// enable SSI output pins!
-
-/*
- * LIMITATIONS:
- * The SSI unit has only one physical data line, so full duplex is
- * impossible. This can be remedied on the SH7760 by using the
- * other SSI unit for recording; however the SH7780 has only 1 SSI
- * unit, and its pins are shared with the AC97 unit, among others.
- *
- * FEATURES:
- * The SSI features "compressed mode": in this mode it continuously
- * streams PCM data over the I2S lines and uses LRCK as a handshake
- * signal. Can be used to send compressed data (AC3/DTS) to a DSP.
- * The number of bits sent over the wire in a frame can be adjusted
- * and can be independent from the actual sample bit depth. This is
- * useful to support TDM mode codecs like the AD1939 which have a
- * fixed TDM slot size, regardless of sample resolution.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-#include <asm/io.h>
-
-#define SSICR 0x00
-#define SSISR 0x04
-
-#define CR_DMAEN (1 << 28)
-#define CR_CHNL_SHIFT 22
-#define CR_CHNL_MASK (3 << CR_CHNL_SHIFT)
-#define CR_DWL_SHIFT 19
-#define CR_DWL_MASK (7 << CR_DWL_SHIFT)
-#define CR_SWL_SHIFT 16
-#define CR_SWL_MASK (7 << CR_SWL_SHIFT)
-#define CR_SCK_MASTER (1 << 15) /* bitclock master bit */
-#define CR_SWS_MASTER (1 << 14) /* wordselect master bit */
-#define CR_SCKP (1 << 13) /* I2Sclock polarity */
-#define CR_SWSP (1 << 12) /* LRCK polarity */
-#define CR_SPDP (1 << 11)
-#define CR_SDTA (1 << 10) /* i2s alignment (msb/lsb) */
-#define CR_PDTA (1 << 9) /* fifo data alignment */
-#define CR_DEL (1 << 8) /* delay data by 1 i2sclk */
-#define CR_BREN (1 << 7) /* clock gating in burst mode */
-#define CR_CKDIV_SHIFT 4
-#define CR_CKDIV_MASK (7 << CR_CKDIV_SHIFT) /* bitclock divider */
-#define CR_MUTE (1 << 3) /* SSI mute */
-#define CR_CPEN (1 << 2) /* compressed mode */
-#define CR_TRMD (1 << 1) /* transmit/receive select */
-#define CR_EN (1 << 0) /* enable SSI */
-
-#define SSIREG(reg) (*(unsigned long *)(ssi->mmio + (reg)))
-
-struct ssi_priv {
- unsigned long mmio;
- unsigned long sysclk;
- int inuse;
-} ssi_cpu_data[] = {
-#if defined(CONFIG_CPU_SUBTYPE_SH7760)
- {
- .mmio = 0xFE680000,
- },
- {
- .mmio = 0xFE690000,
- },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
- {
- .mmio = 0xFFE70000,
- },
-#else
-#error "Unsupported SuperH SoC"
-#endif
-};
-
-/*
- * track usage of the SSI; it is simplex-only so prevent attempts of
- * concurrent playback + capture. FIXME: any locking required?
- */
-static int ssi_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
- if (ssi->inuse) {
- pr_debug("ssi: already in use!\n");
- return -EBUSY;
- } else
- ssi->inuse = 1;
- return 0;
-}
-
-static void ssi_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
-
- ssi->inuse = 0;
-}
-
-static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- SSIREG(SSICR) |= CR_DMAEN | CR_EN;
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- SSIREG(SSICR) &= ~(CR_DMAEN | CR_EN);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int ssi_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
- unsigned long ssicr = SSIREG(SSICR);
- unsigned int bits, channels, swl, recv, i;
-
- channels = params_channels(params);
- bits = params->msbits;
- recv = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1;
-
- pr_debug("ssi_hw_params() enter\nssicr was %08lx\n", ssicr);
- pr_debug("bits: %u channels: %u\n", bits, channels);
-
- ssicr &= ~(CR_TRMD | CR_CHNL_MASK | CR_DWL_MASK | CR_PDTA |
- CR_SWL_MASK);
-
- /* direction (send/receive) */
- if (!recv)
- ssicr |= CR_TRMD; /* transmit */
-
- /* channels */
- if ((channels < 2) || (channels > 8) || (channels & 1)) {
- pr_debug("ssi: invalid number of channels\n");
- return -EINVAL;
- }
- ssicr |= ((channels >> 1) - 1) << CR_CHNL_SHIFT;
-
- /* DATA WORD LENGTH (DWL): databits in audio sample */
- i = 0;
- switch (bits) {
- case 32: ++i;
- case 24: ++i;
- case 22: ++i;
- case 20: ++i;
- case 18: ++i;
- case 16: ++i;
- ssicr |= i << CR_DWL_SHIFT;
- case 8: break;
- default:
- pr_debug("ssi: invalid sample width\n");
- return -EINVAL;
- }
-
- /*
- * SYSTEM WORD LENGTH: size in bits of half a frame over the I2S
- * wires. This is usually bits_per_sample x channels/2; i.e. in
- * Stereo mode the SWL equals DWL. SWL can be bigger than the
- * product of (channels_per_slot x samplebits), e.g. for codecs
- * like the AD1939 which only accept 32bit wide TDM slots. For
- * "standard" I2S operation we set SWL = chans / 2 * DWL here.
- * Waiting for ASoC to get TDM support ;-)
- */
- if ((bits > 16) && (bits <= 24)) {
- bits = 24; /* these are padded by the SSI */
- /*ssicr |= CR_PDTA;*/ /* cpu/data endianness ? */
- }
- i = 0;
- swl = (bits * channels) / 2;
- switch (swl) {
- case 256: ++i;
- case 128: ++i;
- case 64: ++i;
- case 48: ++i;
- case 32: ++i;
- case 16: ++i;
- ssicr |= i << CR_SWL_SHIFT;
- case 8: break;
- default:
- pr_debug("ssi: invalid system word length computed\n");
- return -EINVAL;
- }
-
- SSIREG(SSICR) = ssicr;
-
- pr_debug("ssi_hw_params() leave\nssicr is now %08lx\n", ssicr);
- return 0;
-}
-
-static int ssi_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
- unsigned int freq, int dir)
-{
- struct ssi_priv *ssi = &ssi_cpu_data[cpu_dai->id];
-
- ssi->sysclk = freq;
-
- return 0;
-}
-
-/*
- * This divider is used to generate the SSI_SCK (I2S bitclock) from the
- * clock at the HAC_BIT_CLK ("oversampling clock") pin.
- */
-static int ssi_set_clkdiv(struct snd_soc_dai *dai, int did, int div)
-{
- struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
- unsigned long ssicr;
- int i;
-
- i = 0;
- ssicr = SSIREG(SSICR) & ~CR_CKDIV_MASK;
- switch (div) {
- case 16: ++i;
- case 8: ++i;
- case 4: ++i;
- case 2: ++i;
- SSIREG(SSICR) = ssicr | (i << CR_CKDIV_SHIFT);
- case 1: break;
- default:
- pr_debug("ssi: invalid sck divider %d\n", div);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
- struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
- unsigned long ssicr = SSIREG(SSICR);
-
- pr_debug("ssi_set_fmt()\nssicr was 0x%08lx\n", ssicr);
-
- ssicr &= ~(CR_DEL | CR_PDTA | CR_BREN | CR_SWSP | CR_SCKP |
- CR_SWS_MASTER | CR_SCK_MASTER);
-
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- break;
- case SND_SOC_DAIFMT_RIGHT_J:
- ssicr |= CR_DEL | CR_PDTA;
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- ssicr |= CR_DEL;
- break;
- default:
- pr_debug("ssi: unsupported format\n");
- return -EINVAL;
- }
-
- switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
- case SND_SOC_DAIFMT_CONT:
- break;
- case SND_SOC_DAIFMT_GATED:
- ssicr |= CR_BREN;
- break;
- }
-
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- ssicr |= CR_SCKP; /* sample data at low clkedge */
- break;
- case SND_SOC_DAIFMT_NB_IF:
- ssicr |= CR_SCKP | CR_SWSP;
- break;
- case SND_SOC_DAIFMT_IB_NF:
- break;
- case SND_SOC_DAIFMT_IB_IF:
- ssicr |= CR_SWSP; /* word select starts low */
- break;
- default:
- pr_debug("ssi: invalid inversion\n");
- return -EINVAL;
- }
-
- switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
- case SND_SOC_DAIFMT_BC_FC:
- break;
- case SND_SOC_DAIFMT_BP_FC:
- ssicr |= CR_SCK_MASTER;
- break;
- case SND_SOC_DAIFMT_BC_FP:
- ssicr |= CR_SWS_MASTER;
- break;
- case SND_SOC_DAIFMT_BP_FP:
- ssicr |= CR_SWS_MASTER | CR_SCK_MASTER;
- break;
- default:
- pr_debug("ssi: invalid master/secondary configuration\n");
- return -EINVAL;
- }
-
- SSIREG(SSICR) = ssicr;
- pr_debug("ssi_set_fmt() leave\nssicr is now 0x%08lx\n", ssicr);
-
- return 0;
-}
-
-/* the SSI depends on an external clocksource (at HAC_BIT_CLK) even in
- * Master mode, so really this is board specific; the SSI can do any
- * rate with the right bitclk and divider settings.
- */
-#define SSI_RATES \
- SNDRV_PCM_RATE_8000_192000
-
-/* the SSI can do 8-32 bit samples, with 8 possible channels */
-#define SSI_FMTS \
- (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \
- SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
- SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \
- SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \
- SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE)
-
-static const struct snd_soc_dai_ops ssi_dai_ops = {
- .startup = ssi_startup,
- .shutdown = ssi_shutdown,
- .trigger = ssi_trigger,
- .hw_params = ssi_hw_params,
- .set_sysclk = ssi_set_sysclk,
- .set_clkdiv = ssi_set_clkdiv,
- .set_fmt = ssi_set_fmt,
-};
-
-static struct snd_soc_dai_driver sh4_ssi_dai[] = {
-{
- .name = "ssi-dai.0",
- .playback = {
- .rates = SSI_RATES,
- .formats = SSI_FMTS,
- .channels_min = 2,
- .channels_max = 8,
- },
- .capture = {
- .rates = SSI_RATES,
- .formats = SSI_FMTS,
- .channels_min = 2,
- .channels_max = 8,
- },
- .ops = &ssi_dai_ops,
-},
-#ifdef CONFIG_CPU_SUBTYPE_SH7760
-{
- .name = "ssi-dai.1",
- .playback = {
- .rates = SSI_RATES,
- .formats = SSI_FMTS,
- .channels_min = 2,
- .channels_max = 8,
- },
- .capture = {
- .rates = SSI_RATES,
- .formats = SSI_FMTS,
- .channels_min = 2,
- .channels_max = 8,
- },
- .ops = &ssi_dai_ops,
-},
-#endif
-};
-
-static const struct snd_soc_component_driver sh4_ssi_component = {
- .name = "sh4-ssi",
- .legacy_dai_naming = 1,
-};
-
-static int sh4_soc_dai_probe(struct platform_device *pdev)
-{
- return devm_snd_soc_register_component(&pdev->dev, &sh4_ssi_component,
- sh4_ssi_dai,
- ARRAY_SIZE(sh4_ssi_dai));
-}
-
-static struct platform_driver sh4_ssi_driver = {
- .driver = {
- .name = "sh4-ssi-dai",
- },
-
- .probe = sh4_soc_dai_probe,
-};
-
-module_platform_driver(sh4_ssi_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
-MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");