Skip to content

Commit 298d4f7

Browse files
vijendarmukundabroonie
authored andcommitted
ASoC: amd: ps: add support for SoundWire DMA interrupts
Move to request_threaded_irq and use thread for handling SoundWire DMA interrupts. Whenever audio data equal to the SoundWire FIFO watermark level are produced/consumed, interrupt is generated. Acknowledge the interrupt and wake up the irq thread. Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com> Link: https://lore.kernel.org/r/20230612095903.2113464-6-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent f722917 commit 298d4f7

2 files changed

Lines changed: 98 additions & 2 deletions

File tree

sound/soc/amd/ps/acp63.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,20 @@ enum acp_config {
165165
ACP_CONFIG_15,
166166
};
167167

168+
enum amd_sdw0_channel {
169+
ACP_SDW0_AUDIO0_TX = 0,
170+
ACP_SDW0_AUDIO1_TX,
171+
ACP_SDW0_AUDIO2_TX,
172+
ACP_SDW0_AUDIO0_RX,
173+
ACP_SDW0_AUDIO1_RX,
174+
ACP_SDW0_AUDIO2_RX,
175+
};
176+
177+
enum amd_sdw1_channel {
178+
ACP_SDW1_AUDIO1_TX,
179+
ACP_SDW1_AUDIO1_RX,
180+
};
181+
168182
struct pdm_stream_instance {
169183
u16 num_pages;
170184
u16 channels;
@@ -229,6 +243,8 @@ struct sdw_dma_ring_buf_reg {
229243
* @sdw0_dev_index: SoundWire Manager-0 platform device index
230244
* @sdw1_dev_index: SoundWire Manager-1 platform device index
231245
* @sdw_dma_dev_index: SoundWire DMA controller platform device index
246+
* @sdw0-dma_intr_stat: DMA interrupt status array for SoundWire manager-SW0 instance
247+
* @sdw_dma_intr_stat: DMA interrupt status array for SoundWire manager-SW1 instance
232248
* @acp_reset: flag set to true when bus reset is applied across all
233249
* the active SoundWire manager instances
234250
*/
@@ -246,6 +262,8 @@ struct acp63_dev_data {
246262
u16 sdw0_dev_index;
247263
u16 sdw1_dev_index;
248264
u16 sdw_dma_dev_index;
265+
u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS];
266+
u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS];
249267
bool acp_reset;
250268
};
251269

sound/soc/amd/ps/pci-ps.c

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,44 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev)
9999
return 0;
100100
}
101101

102+
static irqreturn_t acp63_irq_thread(int irq, void *context)
103+
{
104+
struct sdw_dma_dev_data *sdw_dma_data;
105+
struct acp63_dev_data *adata = context;
106+
u32 stream_index;
107+
u16 pdev_index;
108+
109+
pdev_index = adata->sdw_dma_dev_index;
110+
sdw_dma_data = dev_get_drvdata(&adata->pdev[pdev_index]->dev);
111+
112+
for (stream_index = 0; stream_index < ACP63_SDW0_DMA_MAX_STREAMS; stream_index++) {
113+
if (adata->sdw0_dma_intr_stat[stream_index]) {
114+
if (sdw_dma_data->sdw0_dma_stream[stream_index])
115+
snd_pcm_period_elapsed(sdw_dma_data->sdw0_dma_stream[stream_index]);
116+
adata->sdw0_dma_intr_stat[stream_index] = 0;
117+
}
118+
}
119+
for (stream_index = 0; stream_index < ACP63_SDW1_DMA_MAX_STREAMS; stream_index++) {
120+
if (adata->sdw1_dma_intr_stat[stream_index]) {
121+
if (sdw_dma_data->sdw1_dma_stream[stream_index])
122+
snd_pcm_period_elapsed(sdw_dma_data->sdw1_dma_stream[stream_index]);
123+
adata->sdw1_dma_intr_stat[stream_index] = 0;
124+
}
125+
}
126+
return IRQ_HANDLED;
127+
}
128+
102129
static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
103130
{
104131
struct acp63_dev_data *adata;
105132
struct pdm_dev_data *ps_pdm_data;
106133
struct amd_sdw_manager *amd_manager;
107134
u32 ext_intr_stat, ext_intr_stat1;
135+
u32 stream_id = 0;
108136
u16 irq_flag = 0;
137+
u16 sdw_dma_irq_flag = 0;
109138
u16 pdev_index;
139+
u16 index;
110140

111141
adata = dev_id;
112142
if (!adata)
@@ -153,6 +183,54 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
153183
snd_pcm_period_elapsed(ps_pdm_data->capture_stream);
154184
irq_flag = 1;
155185
}
186+
if (ext_intr_stat & ACP_SDW_DMA_IRQ_MASK) {
187+
for (index = ACP_AUDIO2_RX_THRESHOLD; index <= ACP_AUDIO0_TX_THRESHOLD; index++) {
188+
if (ext_intr_stat & BIT(index)) {
189+
writel(BIT(index), adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
190+
switch (index) {
191+
case ACP_AUDIO0_TX_THRESHOLD:
192+
stream_id = ACP_SDW0_AUDIO0_TX;
193+
break;
194+
case ACP_AUDIO1_TX_THRESHOLD:
195+
stream_id = ACP_SDW0_AUDIO1_TX;
196+
break;
197+
case ACP_AUDIO2_TX_THRESHOLD:
198+
stream_id = ACP_SDW0_AUDIO2_TX;
199+
break;
200+
case ACP_AUDIO0_RX_THRESHOLD:
201+
stream_id = ACP_SDW0_AUDIO0_RX;
202+
break;
203+
case ACP_AUDIO1_RX_THRESHOLD:
204+
stream_id = ACP_SDW0_AUDIO1_RX;
205+
break;
206+
case ACP_AUDIO2_RX_THRESHOLD:
207+
stream_id = ACP_SDW0_AUDIO2_RX;
208+
break;
209+
}
210+
211+
adata->sdw0_dma_intr_stat[stream_id] = 1;
212+
sdw_dma_irq_flag = 1;
213+
}
214+
}
215+
}
216+
217+
if (ext_intr_stat1 & ACP_P1_AUDIO1_RX_THRESHOLD) {
218+
writel(ACP_P1_AUDIO1_RX_THRESHOLD,
219+
adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
220+
adata->sdw1_dma_intr_stat[ACP_SDW1_AUDIO1_RX] = 1;
221+
sdw_dma_irq_flag = 1;
222+
}
223+
224+
if (ext_intr_stat1 & ACP_P1_AUDIO1_TX_THRESHOLD) {
225+
writel(ACP_P1_AUDIO1_TX_THRESHOLD,
226+
adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
227+
adata->sdw1_dma_intr_stat[ACP_SDW1_AUDIO1_TX] = 1;
228+
sdw_dma_irq_flag = 1;
229+
}
230+
231+
if (sdw_dma_irq_flag)
232+
return IRQ_WAKE_THREAD;
233+
156234
if (irq_flag)
157235
return IRQ_HANDLED;
158236
else
@@ -553,8 +631,8 @@ static int snd_acp63_probe(struct pci_dev *pci,
553631
ret = acp63_init(adata->acp63_base, &pci->dev);
554632
if (ret)
555633
goto release_regions;
556-
ret = devm_request_irq(&pci->dev, pci->irq, acp63_irq_handler,
557-
irqflags, "ACP_PCI_IRQ", adata);
634+
ret = devm_request_threaded_irq(&pci->dev, pci->irq, acp63_irq_handler,
635+
acp63_irq_thread, irqflags, "ACP_PCI_IRQ", adata);
558636
if (ret) {
559637
dev_err(&pci->dev, "ACP PCI IRQ request failed\n");
560638
goto de_init;

0 commit comments

Comments
 (0)