Skip to content

Commit dd0111d

Browse files
committed
Merge remote-tracking branches 'asoc/topic/dpcm', 'asoc/topic/dt', 'asoc/topic/dwc' and 'asoc/topic/fsl' into asoc-next
5 parents 3ceeda1 + 0946497 + add3873 + 57072ae + 121a015 commit dd0111d

File tree

12 files changed

+580
-134
lines changed

12 files changed

+580
-134
lines changed

Documentation/devicetree/bindings/sound/designware-i2s.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ Required properties:
1212
one for receive.
1313
- dma-names : "tx" for the transmit channel, "rx" for the receive channel.
1414

15+
Optional properties:
16+
- interrupts: The interrupt line number for the I2S controller. Add this
17+
parameter if the I2S controller that you are using does not support DMA.
18+
1519
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names'
1620
properties please check:
1721
* resource-names.txt

Documentation/devicetree/bindings/sound/fsl-asoc-card.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Required properties:
5858
* DMIC (stands for Digital Microphone Jack)
5959

6060
Note: The "Mic Jack" and "AMIC" are redundant while
61-
coexsiting in order to support the old bindings
61+
coexisting in order to support the old bindings
6262
of wm8962 and sgtl5000.
6363

6464
Optional properties:

Documentation/sound/alsa/soc/machine.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ ASoC Machine Driver
33

44
The ASoC machine (or board) driver is the code that glues together all the
55
component drivers (e.g. codecs, platforms and DAIs). It also describes the
6-
relationships between each componnent which include audio paths, GPIOs,
6+
relationships between each component which include audio paths, GPIOs,
77
interrupts, clocking, jacks and voltage regulators.
88

99
The machine driver can contain codec and platform specific code. It registers

include/sound/soc-dapm.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ struct snd_soc_dapm_context;
358358
struct regulator;
359359
struct snd_soc_dapm_widget_list;
360360
struct snd_soc_dapm_update;
361+
enum snd_soc_dapm_direction;
361362

362363
int dapm_regulator_event(struct snd_soc_dapm_widget *w,
363364
struct snd_kcontrol *kcontrol, int event);
@@ -454,7 +455,9 @@ void dapm_mark_endpoints_dirty(struct snd_soc_card *card);
454455

455456
/* dapm path query */
456457
int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
457-
struct snd_soc_dapm_widget_list **list);
458+
struct snd_soc_dapm_widget_list **list,
459+
bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,
460+
enum snd_soc_dapm_direction));
458461

459462
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
460463
struct snd_kcontrol *kcontrol);

sound/soc/dwc/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,13 @@ config SND_DESIGNWARE_I2S
77
Synopsys desigwnware I2S device. The device supports upto
88
maximum of 8 channels each for play and record.
99

10+
config SND_DESIGNWARE_PCM
11+
tristate "PCM PIO extension for I2S driver"
12+
depends on SND_DESIGNWARE_I2S
13+
help
14+
Say Y, M or N if you want to add a custom ALSA extension that registers
15+
a PCM and uses PIO to transfer data.
16+
17+
This functionality is specially suited for I2S devices that don't have
18+
DMA support.
1019

sound/soc/dwc/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# SYNOPSYS Platform Support
22
obj-$(CONFIG_SND_DESIGNWARE_I2S) += designware_i2s.o
3-
3+
ifdef CONFIG_SND_DESIGNWARE_PCM
4+
obj-$(CONFIG_SND_DESIGNWARE_I2S) += designware_pcm.o
5+
endif

sound/soc/dwc/designware_i2s.c

Lines changed: 115 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -24,90 +24,7 @@
2424
#include <sound/pcm_params.h>
2525
#include <sound/soc.h>
2626
#include <sound/dmaengine_pcm.h>
27-
28-
/* common register for all channel */
29-
#define IER 0x000
30-
#define IRER 0x004
31-
#define ITER 0x008
32-
#define CER 0x00C
33-
#define CCR 0x010
34-
#define RXFFR 0x014
35-
#define TXFFR 0x018
36-
37-
/* I2STxRxRegisters for all channels */
38-
#define LRBR_LTHR(x) (0x40 * x + 0x020)
39-
#define RRBR_RTHR(x) (0x40 * x + 0x024)
40-
#define RER(x) (0x40 * x + 0x028)
41-
#define TER(x) (0x40 * x + 0x02C)
42-
#define RCR(x) (0x40 * x + 0x030)
43-
#define TCR(x) (0x40 * x + 0x034)
44-
#define ISR(x) (0x40 * x + 0x038)
45-
#define IMR(x) (0x40 * x + 0x03C)
46-
#define ROR(x) (0x40 * x + 0x040)
47-
#define TOR(x) (0x40 * x + 0x044)
48-
#define RFCR(x) (0x40 * x + 0x048)
49-
#define TFCR(x) (0x40 * x + 0x04C)
50-
#define RFF(x) (0x40 * x + 0x050)
51-
#define TFF(x) (0x40 * x + 0x054)
52-
53-
/* I2SCOMPRegisters */
54-
#define I2S_COMP_PARAM_2 0x01F0
55-
#define I2S_COMP_PARAM_1 0x01F4
56-
#define I2S_COMP_VERSION 0x01F8
57-
#define I2S_COMP_TYPE 0x01FC
58-
59-
/*
60-
* Component parameter register fields - define the I2S block's
61-
* configuration.
62-
*/
63-
#define COMP1_TX_WORDSIZE_3(r) (((r) & GENMASK(27, 25)) >> 25)
64-
#define COMP1_TX_WORDSIZE_2(r) (((r) & GENMASK(24, 22)) >> 22)
65-
#define COMP1_TX_WORDSIZE_1(r) (((r) & GENMASK(21, 19)) >> 19)
66-
#define COMP1_TX_WORDSIZE_0(r) (((r) & GENMASK(18, 16)) >> 16)
67-
#define COMP1_TX_CHANNELS(r) (((r) & GENMASK(10, 9)) >> 9)
68-
#define COMP1_RX_CHANNELS(r) (((r) & GENMASK(8, 7)) >> 7)
69-
#define COMP1_RX_ENABLED(r) (((r) & BIT(6)) >> 6)
70-
#define COMP1_TX_ENABLED(r) (((r) & BIT(5)) >> 5)
71-
#define COMP1_MODE_EN(r) (((r) & BIT(4)) >> 4)
72-
#define COMP1_FIFO_DEPTH_GLOBAL(r) (((r) & GENMASK(3, 2)) >> 2)
73-
#define COMP1_APB_DATA_WIDTH(r) (((r) & GENMASK(1, 0)) >> 0)
74-
75-
#define COMP2_RX_WORDSIZE_3(r) (((r) & GENMASK(12, 10)) >> 10)
76-
#define COMP2_RX_WORDSIZE_2(r) (((r) & GENMASK(9, 7)) >> 7)
77-
#define COMP2_RX_WORDSIZE_1(r) (((r) & GENMASK(5, 3)) >> 3)
78-
#define COMP2_RX_WORDSIZE_0(r) (((r) & GENMASK(2, 0)) >> 0)
79-
80-
/* Number of entries in WORDSIZE and DATA_WIDTH parameter registers */
81-
#define COMP_MAX_WORDSIZE (1 << 3)
82-
#define COMP_MAX_DATA_WIDTH (1 << 2)
83-
84-
#define MAX_CHANNEL_NUM 8
85-
#define MIN_CHANNEL_NUM 2
86-
87-
union dw_i2s_snd_dma_data {
88-
struct i2s_dma_data pd;
89-
struct snd_dmaengine_dai_dma_data dt;
90-
};
91-
92-
struct dw_i2s_dev {
93-
void __iomem *i2s_base;
94-
struct clk *clk;
95-
int active;
96-
unsigned int capability;
97-
unsigned int quirks;
98-
unsigned int i2s_reg_comp1;
99-
unsigned int i2s_reg_comp2;
100-
struct device *dev;
101-
u32 ccr;
102-
u32 xfer_resolution;
103-
u32 fifo_th;
104-
105-
/* data related to DMA transfers b/w i2s and DMAC */
106-
union dw_i2s_snd_dma_data play_dma_data;
107-
union dw_i2s_snd_dma_data capture_dma_data;
108-
struct i2s_clk_config_data config;
109-
int (*i2s_clk_cfg)(struct i2s_clk_config_data *config);
110-
};
27+
#include "local.h"
11128

11229
static inline void i2s_write_reg(void __iomem *io_base, int reg, u32 val)
11330
{
@@ -145,51 +62,115 @@ static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream)
14562
}
14663
}
14764

148-
static void i2s_start(struct dw_i2s_dev *dev,
149-
struct snd_pcm_substream *substream)
65+
static inline void i2s_disable_irqs(struct dw_i2s_dev *dev, u32 stream,
66+
int chan_nr)
67+
{
68+
u32 i, irq;
69+
70+
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
71+
for (i = 0; i < (chan_nr / 2); i++) {
72+
irq = i2s_read_reg(dev->i2s_base, IMR(i));
73+
i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x30);
74+
}
75+
} else {
76+
for (i = 0; i < (chan_nr / 2); i++) {
77+
irq = i2s_read_reg(dev->i2s_base, IMR(i));
78+
i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x03);
79+
}
80+
}
81+
}
82+
83+
static inline void i2s_enable_irqs(struct dw_i2s_dev *dev, u32 stream,
84+
int chan_nr)
15085
{
151-
struct i2s_clk_config_data *config = &dev->config;
15286
u32 i, irq;
153-
i2s_write_reg(dev->i2s_base, IER, 1);
15487

155-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
156-
for (i = 0; i < (config->chan_nr / 2); i++) {
88+
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
89+
for (i = 0; i < (chan_nr / 2); i++) {
15790
irq = i2s_read_reg(dev->i2s_base, IMR(i));
15891
i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x30);
15992
}
160-
i2s_write_reg(dev->i2s_base, ITER, 1);
16193
} else {
162-
for (i = 0; i < (config->chan_nr / 2); i++) {
94+
for (i = 0; i < (chan_nr / 2); i++) {
16395
irq = i2s_read_reg(dev->i2s_base, IMR(i));
16496
i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x03);
16597
}
166-
i2s_write_reg(dev->i2s_base, IRER, 1);
98+
}
99+
}
100+
101+
static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
102+
{
103+
struct dw_i2s_dev *dev = dev_id;
104+
bool irq_valid = false;
105+
u32 isr[4];
106+
int i;
107+
108+
for (i = 0; i < 4; i++)
109+
isr[i] = i2s_read_reg(dev->i2s_base, ISR(i));
110+
111+
i2s_clear_irqs(dev, SNDRV_PCM_STREAM_PLAYBACK);
112+
i2s_clear_irqs(dev, SNDRV_PCM_STREAM_CAPTURE);
113+
114+
for (i = 0; i < 4; i++) {
115+
/*
116+
* Check if TX fifo is empty. If empty fill FIFO with samples
117+
* NOTE: Only two channels supported
118+
*/
119+
if ((isr[i] & ISR_TXFE) && (i == 0) && dev->use_pio) {
120+
dw_pcm_push_tx(dev);
121+
irq_valid = true;
122+
}
123+
124+
/* Data available. Record mode not supported in PIO mode */
125+
if (isr[i] & ISR_RXDA)
126+
irq_valid = true;
127+
128+
/* Error Handling: TX */
129+
if (isr[i] & ISR_TXFO) {
130+
dev_err(dev->dev, "TX overrun (ch_id=%d)\n", i);
131+
irq_valid = true;
132+
}
133+
134+
/* Error Handling: TX */
135+
if (isr[i] & ISR_RXFO) {
136+
dev_err(dev->dev, "RX overrun (ch_id=%d)\n", i);
137+
irq_valid = true;
138+
}
167139
}
168140

141+
if (irq_valid)
142+
return IRQ_HANDLED;
143+
else
144+
return IRQ_NONE;
145+
}
146+
147+
static void i2s_start(struct dw_i2s_dev *dev,
148+
struct snd_pcm_substream *substream)
149+
{
150+
struct i2s_clk_config_data *config = &dev->config;
151+
152+
i2s_write_reg(dev->i2s_base, IER, 1);
153+
i2s_enable_irqs(dev, substream->stream, config->chan_nr);
154+
155+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
156+
i2s_write_reg(dev->i2s_base, ITER, 1);
157+
else
158+
i2s_write_reg(dev->i2s_base, IRER, 1);
159+
169160
i2s_write_reg(dev->i2s_base, CER, 1);
170161
}
171162

172163
static void i2s_stop(struct dw_i2s_dev *dev,
173164
struct snd_pcm_substream *substream)
174165
{
175-
u32 i = 0, irq;
176166

177167
i2s_clear_irqs(dev, substream->stream);
178-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
168+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
179169
i2s_write_reg(dev->i2s_base, ITER, 0);
180-
181-
for (i = 0; i < 4; i++) {
182-
irq = i2s_read_reg(dev->i2s_base, IMR(i));
183-
i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x30);
184-
}
185-
} else {
170+
else
186171
i2s_write_reg(dev->i2s_base, IRER, 0);
187172

188-
for (i = 0; i < 4; i++) {
189-
irq = i2s_read_reg(dev->i2s_base, IMR(i));
190-
i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x03);
191-
}
192-
}
173+
i2s_disable_irqs(dev, substream->stream, 8);
193174

194175
if (!dev->active) {
195176
i2s_write_reg(dev->i2s_base, CER, 0);
@@ -223,7 +204,7 @@ static int dw_i2s_startup(struct snd_pcm_substream *substream,
223204

224205
static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
225206
{
226-
u32 ch_reg, irq;
207+
u32 ch_reg;
227208
struct i2s_clk_config_data *config = &dev->config;
228209

229210

@@ -235,16 +216,12 @@ static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
235216
dev->xfer_resolution);
236217
i2s_write_reg(dev->i2s_base, TFCR(ch_reg),
237218
dev->fifo_th - 1);
238-
irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
239-
i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
240219
i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
241220
} else {
242221
i2s_write_reg(dev->i2s_base, RCR(ch_reg),
243222
dev->xfer_resolution);
244223
i2s_write_reg(dev->i2s_base, RFCR(ch_reg),
245224
dev->fifo_th - 1);
246-
irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
247-
i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
248225
i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
249226
}
250227

@@ -278,7 +255,7 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
278255
break;
279256

280257
default:
281-
dev_err(dev->dev, "designware-i2s: unsuppted PCM fmt");
258+
dev_err(dev->dev, "designware-i2s: unsupported PCM fmt");
282259
return -EINVAL;
283260
}
284261

@@ -626,7 +603,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
626603
const struct i2s_platform_data *pdata = pdev->dev.platform_data;
627604
struct dw_i2s_dev *dev;
628605
struct resource *res;
629-
int ret;
606+
int ret, irq;
630607
struct snd_soc_dai_driver *dw_i2s_dai;
631608
const char *clk_id;
632609

@@ -651,6 +628,16 @@ static int dw_i2s_probe(struct platform_device *pdev)
651628

652629
dev->dev = &pdev->dev;
653630

631+
irq = platform_get_irq(pdev, 0);
632+
if (irq >= 0) {
633+
ret = devm_request_irq(&pdev->dev, irq, i2s_irq_handler, 0,
634+
pdev->name, dev);
635+
if (ret < 0) {
636+
dev_err(&pdev->dev, "failed to request irq\n");
637+
return ret;
638+
}
639+
}
640+
654641
dev->i2s_reg_comp1 = I2S_COMP_PARAM_1;
655642
dev->i2s_reg_comp2 = I2S_COMP_PARAM_2;
656643
if (pdata) {
@@ -697,12 +684,24 @@ static int dw_i2s_probe(struct platform_device *pdev)
697684

698685
if (!pdata) {
699686
ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
700-
if (ret) {
687+
if (ret == -EPROBE_DEFER) {
688+
dev_err(&pdev->dev,
689+
"failed to register PCM, deferring probe\n");
690+
return ret;
691+
} else if (ret) {
701692
dev_err(&pdev->dev,
702-
"Could not register PCM: %d\n", ret);
703-
goto err_clk_disable;
693+
"Could not register DMA PCM: %d\n"
694+
"falling back to PIO mode\n", ret);
695+
ret = dw_pcm_register(pdev);
696+
if (ret) {
697+
dev_err(&pdev->dev,
698+
"Could not register PIO PCM: %d\n",
699+
ret);
700+
goto err_clk_disable;
701+
}
704702
}
705703
}
704+
706705
pm_runtime_enable(&pdev->dev);
707706
return 0;
708707

0 commit comments

Comments
 (0)