^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * ALSA SoC Synopsys I2S Audio Layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * sound/soc/dwc/designware_i2s.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2010 ST Microelectronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Rajeev Kumar <rajeevkumar.linux@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/designware_i2s.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <sound/dmaengine_pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static inline void i2s_write_reg(void __iomem *io_base, int reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) writel(val, io_base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static inline u32 i2s_read_reg(void __iomem *io_base, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return readl(io_base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static inline void i2s_disable_channels(struct dw_i2s_dev *dev, u32 stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) i2s_write_reg(dev->i2s_base, TER(i), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) i2s_write_reg(dev->i2s_base, RER(i), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u32 i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) i2s_read_reg(dev->i2s_base, TOR(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) i2s_read_reg(dev->i2s_base, ROR(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static inline void i2s_disable_irqs(struct dw_i2s_dev *dev, u32 stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int chan_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u32 i, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) for (i = 0; i < (chan_nr / 2); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) irq = i2s_read_reg(dev->i2s_base, IMR(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) for (i = 0; i < (chan_nr / 2); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) irq = i2s_read_reg(dev->i2s_base, IMR(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static inline void i2s_enable_irqs(struct dw_i2s_dev *dev, u32 stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int chan_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u32 i, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) for (i = 0; i < (chan_nr / 2); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) irq = i2s_read_reg(dev->i2s_base, IMR(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) for (i = 0; i < (chan_nr / 2); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) irq = i2s_read_reg(dev->i2s_base, IMR(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct dw_i2s_dev *dev = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) bool irq_valid = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 isr[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) isr[i] = i2s_read_reg(dev->i2s_base, ISR(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) i2s_clear_irqs(dev, SNDRV_PCM_STREAM_PLAYBACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) i2s_clear_irqs(dev, SNDRV_PCM_STREAM_CAPTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * Check if TX fifo is empty. If empty fill FIFO with samples
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * NOTE: Only two channels supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if ((isr[i] & ISR_TXFE) && (i == 0) && dev->use_pio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dw_pcm_push_tx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) irq_valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * Data available. Retrieve samples from FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * NOTE: Only two channels supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if ((isr[i] & ISR_RXDA) && (i == 0) && dev->use_pio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) dw_pcm_pop_rx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) irq_valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* Error Handling: TX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (isr[i] & ISR_TXFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) dev_err(dev->dev, "TX overrun (ch_id=%d)\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) irq_valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* Error Handling: TX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (isr[i] & ISR_RXFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dev_err(dev->dev, "RX overrun (ch_id=%d)\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) irq_valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (irq_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static void i2s_start(struct dw_i2s_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct i2s_clk_config_data *config = &dev->config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) i2s_write_reg(dev->i2s_base, IER, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) i2s_enable_irqs(dev, substream->stream, config->chan_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) i2s_write_reg(dev->i2s_base, ITER, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) i2s_write_reg(dev->i2s_base, IRER, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) i2s_write_reg(dev->i2s_base, CER, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static void i2s_stop(struct dw_i2s_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) i2s_clear_irqs(dev, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) i2s_write_reg(dev->i2s_base, ITER, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) i2s_write_reg(dev->i2s_base, IRER, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) i2s_disable_irqs(dev, substream->stream, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (!dev->active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) i2s_write_reg(dev->i2s_base, CER, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) i2s_write_reg(dev->i2s_base, IER, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static int dw_i2s_startup(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct snd_soc_dai *cpu_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) union dw_i2s_snd_dma_data *dma_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (!(dev->capability & DWC_I2S_RECORD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (!(dev->capability & DWC_I2S_PLAY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) dma_data = &dev->play_dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) dma_data = &dev->capture_dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) u32 ch_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct i2s_clk_config_data *config = &dev->config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) i2s_disable_channels(dev, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) i2s_write_reg(dev->i2s_base, TCR(ch_reg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) dev->xfer_resolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) i2s_write_reg(dev->i2s_base, TFCR(ch_reg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) dev->fifo_th - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) i2s_write_reg(dev->i2s_base, RCR(ch_reg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) dev->xfer_resolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) i2s_write_reg(dev->i2s_base, RFCR(ch_reg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) dev->fifo_th - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct i2s_clk_config_data *config = &dev->config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) switch (params_format(params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case SNDRV_PCM_FORMAT_S16_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) config->data_width = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) dev->ccr = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) dev->xfer_resolution = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) case SNDRV_PCM_FORMAT_S24_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) config->data_width = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) dev->ccr = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) dev->xfer_resolution = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case SNDRV_PCM_FORMAT_S32_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) config->data_width = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) dev->ccr = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) dev->xfer_resolution = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) dev_err(dev->dev, "designware-i2s: unsupported PCM fmt");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) config->chan_nr = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) switch (config->chan_nr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) case EIGHT_CHANNEL_SUPPORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) case SIX_CHANNEL_SUPPORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) case FOUR_CHANNEL_SUPPORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) case TWO_CHANNEL_SUPPORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dev_err(dev->dev, "channel not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) dw_i2s_config(dev, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) i2s_write_reg(dev->i2s_base, CCR, dev->ccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) config->sample_rate = params_rate(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (dev->capability & DW_I2S_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (dev->i2s_clk_cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ret = dev->i2s_clk_cfg(config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dev_err(dev->dev, "runtime audio clk config fail\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) u32 bitclk = config->sample_rate *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) config->data_width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ret = clk_set_rate(dev->clk, bitclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) dev_err(dev->dev, "Can't set I2S clock rate: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) snd_soc_dai_set_dma_data(dai, substream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static int dw_i2s_prepare(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) i2s_write_reg(dev->i2s_base, TXFFR, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) i2s_write_reg(dev->i2s_base, RXFFR, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static int dw_i2s_trigger(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int cmd, struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) dev->active++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) i2s_start(dev, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) dev->active--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) i2s_stop(dev, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static int dw_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) case SND_SOC_DAIFMT_CBM_CFM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (dev->capability & DW_I2S_SLAVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) case SND_SOC_DAIFMT_CBS_CFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (dev->capability & DW_I2S_MASTER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case SND_SOC_DAIFMT_CBM_CFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) case SND_SOC_DAIFMT_CBS_CFM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) dev_dbg(dev->dev, "dwc : Invalid master/slave format\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) .startup = dw_i2s_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .shutdown = dw_i2s_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .hw_params = dw_i2s_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .prepare = dw_i2s_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) .trigger = dw_i2s_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) .set_fmt = dw_i2s_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static int dw_i2s_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (dw_dev->capability & DW_I2S_MASTER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) clk_disable(dw_dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static int dw_i2s_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (dw_dev->capability & DW_I2S_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ret = clk_enable(dw_dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static int dw_i2s_suspend(struct snd_soc_component *component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct dw_i2s_dev *dev = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (dev->capability & DW_I2S_MASTER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) clk_disable(dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int dw_i2s_resume(struct snd_soc_component *component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct dw_i2s_dev *dev = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int stream, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (dev->capability & DW_I2S_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) ret = clk_enable(dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) for_each_component_dais(component, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) for_each_pcm_streams(stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (snd_soc_dai_stream_active(dai, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) dw_i2s_config(dev, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) #define dw_i2s_suspend NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) #define dw_i2s_resume NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static const struct snd_soc_component_driver dw_i2s_component = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) .name = "dw-i2s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) .suspend = dw_i2s_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) .resume = dw_i2s_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * The following tables allow a direct lookup of various parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * defined in the I2S block's configuration in terms of sound system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * parameters. Each table is sized to the number of entries possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * according to the number of configuration bits describing an I2S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * block parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* Maximum bit resolution of a channel - not uniformly spaced */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static const u32 fifo_width[COMP_MAX_WORDSIZE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 12, 16, 20, 24, 32, 0, 0, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* Width of (DMA) bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static const u32 bus_widths[COMP_MAX_DATA_WIDTH] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) DMA_SLAVE_BUSWIDTH_1_BYTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) DMA_SLAVE_BUSWIDTH_2_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) DMA_SLAVE_BUSWIDTH_4_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) DMA_SLAVE_BUSWIDTH_UNDEFINED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /* PCM format to support channel resolution */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static const u32 formats[COMP_MAX_WORDSIZE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) SNDRV_PCM_FMTBIT_S24_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) SNDRV_PCM_FMTBIT_S24_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) SNDRV_PCM_FMTBIT_S32_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static int dw_configure_dai(struct dw_i2s_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct snd_soc_dai_driver *dw_i2s_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) unsigned int rates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * Read component parameter registers to extract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * the I2S block's configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) u32 comp2 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) u32 fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) u32 idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (dev->capability & DWC_I2S_RECORD &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) dev->quirks & DW_I2S_QUIRK_COMP_PARAM1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) comp1 = comp1 & ~BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (dev->capability & DWC_I2S_PLAY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) dev->quirks & DW_I2S_QUIRK_COMP_PARAM1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) comp1 = comp1 & ~BIT(6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (COMP1_TX_ENABLED(comp1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) dev_dbg(dev->dev, " designware: play supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) idx = COMP1_TX_WORDSIZE_0(comp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (WARN_ON(idx >= ARRAY_SIZE(formats)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (dev->quirks & DW_I2S_QUIRK_16BIT_IDX_OVERRIDE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) idx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) dw_i2s_dai->playback.channels_max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 1 << (COMP1_TX_CHANNELS(comp1) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) dw_i2s_dai->playback.formats = formats[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) dw_i2s_dai->playback.rates = rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (COMP1_RX_ENABLED(comp1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) dev_dbg(dev->dev, "designware: record supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) idx = COMP2_RX_WORDSIZE_0(comp2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (WARN_ON(idx >= ARRAY_SIZE(formats)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (dev->quirks & DW_I2S_QUIRK_16BIT_IDX_OVERRIDE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) idx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dw_i2s_dai->capture.channels_max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 1 << (COMP1_RX_CHANNELS(comp1) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) dw_i2s_dai->capture.formats = formats[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) dw_i2s_dai->capture.rates = rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (COMP1_MODE_EN(comp1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) dev_dbg(dev->dev, "designware: i2s master mode supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) dev->capability |= DW_I2S_MASTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) dev_dbg(dev->dev, "designware: i2s slave mode supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) dev->capability |= DW_I2S_SLAVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) dev->fifo_th = fifo_depth / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static int dw_configure_dai_by_pd(struct dw_i2s_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) struct snd_soc_dai_driver *dw_i2s_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct resource *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) const struct i2s_platform_data *pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) u32 idx = COMP1_APB_DATA_WIDTH(comp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (WARN_ON(idx >= ARRAY_SIZE(bus_widths)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) ret = dw_configure_dai(dev, dw_i2s_dai, pdata->snd_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (dev->quirks & DW_I2S_QUIRK_16BIT_IDX_OVERRIDE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) idx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* Set DMA slaves info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) dev->play_dma_data.pd.data = pdata->play_dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) dev->capture_dma_data.pd.data = pdata->capture_dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) dev->play_dma_data.pd.addr = res->start + I2S_TXDMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) dev->capture_dma_data.pd.addr = res->start + I2S_RXDMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) dev->play_dma_data.pd.max_burst = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) dev->capture_dma_data.pd.max_burst = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) dev->play_dma_data.pd.addr_width = bus_widths[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) dev->capture_dma_data.pd.addr_width = bus_widths[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) dev->play_dma_data.pd.filter = pdata->filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) dev->capture_dma_data.pd.filter = pdata->filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct snd_soc_dai_driver *dw_i2s_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) struct resource *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) u32 fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) u32 idx = COMP1_APB_DATA_WIDTH(comp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) u32 idx2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (WARN_ON(idx >= ARRAY_SIZE(bus_widths)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) ret = dw_configure_dai(dev, dw_i2s_dai, SNDRV_PCM_RATE_8000_192000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (COMP1_TX_ENABLED(comp1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) idx2 = COMP1_TX_WORDSIZE_0(comp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) dev->capability |= DWC_I2S_PLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) dev->play_dma_data.dt.addr = res->start + I2S_TXDMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) dev->play_dma_data.dt.addr_width = bus_widths[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) dev->play_dma_data.dt.fifo_size = fifo_depth *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) (fifo_width[idx2]) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) dev->play_dma_data.dt.maxburst = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (COMP1_RX_ENABLED(comp1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) idx2 = COMP2_RX_WORDSIZE_0(comp2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) dev->capability |= DWC_I2S_RECORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) dev->capture_dma_data.dt.addr = res->start + I2S_RXDMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) dev->capture_dma_data.dt.addr_width = bus_widths[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) dev->capture_dma_data.dt.fifo_size = fifo_depth *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) (fifo_width[idx2] >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) dev->capture_dma_data.dt.maxburst = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) static int dw_i2s_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) const struct i2s_platform_data *pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct dw_i2s_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int ret, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct snd_soc_dai_driver *dw_i2s_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) const char *clk_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (!dw_i2s_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) dw_i2s_dai->ops = &dw_i2s_dai_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) dev->i2s_base = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (IS_ERR(dev->i2s_base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return PTR_ERR(dev->i2s_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) dev->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (irq >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ret = devm_request_irq(&pdev->dev, irq, i2s_irq_handler, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) pdev->name, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) dev_err(&pdev->dev, "failed to request irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) dev->i2s_reg_comp1 = I2S_COMP_PARAM_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) dev->i2s_reg_comp2 = I2S_COMP_PARAM_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) dev->capability = pdata->cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) clk_id = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) dev->quirks = pdata->quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (dev->quirks & DW_I2S_QUIRK_COMP_REG_OFFSET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dev->i2s_reg_comp1 = pdata->i2s_reg_comp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dev->i2s_reg_comp2 = pdata->i2s_reg_comp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ret = dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) clk_id = "i2sclk";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) ret = dw_configure_dai_by_dt(dev, dw_i2s_dai, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (dev->capability & DW_I2S_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (!dev->i2s_clk_cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) dev_err(&pdev->dev, "no clock configure method\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) dev->clk = devm_clk_get(&pdev->dev, clk_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (IS_ERR(dev->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return PTR_ERR(dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) ret = clk_prepare_enable(dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) dev_set_drvdata(&pdev->dev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) ret = devm_snd_soc_register_component(&pdev->dev, &dw_i2s_component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) dw_i2s_dai, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) dev_err(&pdev->dev, "not able to register dai\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) goto err_clk_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (irq >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ret = dw_pcm_register(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) dev->use_pio = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) dev->use_pio = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dev_err(&pdev->dev, "could not register pcm: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) goto err_clk_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) pm_runtime_enable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) err_clk_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (dev->capability & DW_I2S_MASTER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) clk_disable_unprepare(dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static int dw_i2s_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (dev->capability & DW_I2S_MASTER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) clk_disable_unprepare(dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) pm_runtime_disable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static const struct of_device_id dw_i2s_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) { .compatible = "snps,designware-i2s", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) MODULE_DEVICE_TABLE(of, dw_i2s_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static const struct dev_pm_ops dwc_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) SET_RUNTIME_PM_OPS(dw_i2s_runtime_suspend, dw_i2s_runtime_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) static struct platform_driver dw_i2s_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) .probe = dw_i2s_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) .remove = dw_i2s_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) .name = "designware-i2s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) .of_match_table = of_match_ptr(dw_i2s_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) .pm = &dwc_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) module_platform_driver(dw_i2s_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) MODULE_AUTHOR("Rajeev Kumar <rajeevkumar.linux@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) MODULE_DESCRIPTION("DESIGNWARE I2S SoC Interface");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) MODULE_ALIAS("platform:designware_i2s");