mirror of
https://abf.rosa.ru/djam/kernel-5.15.git
synced 2025-02-23 18:42:55 +00:00
99 lines
3 KiB
Diff
99 lines
3 KiB
Diff
From 0076b9479bf1b3ef5ae9b36c1516861a7c817c50 Mon Sep 17 00:00:00 2001
|
|
From: Alexey Sheplyakov <asheplyakov@altlinux.org>
|
|
Date: Mon, 29 Mar 2021 12:22:11 +0400
|
|
Subject: [PATCH 626/634] (BROKEN) dwc-i2s: support Baikal-M SoC
|
|
|
|
* dw_i2s_probe: request all IRQs specified in device tree
|
|
* i2s_irq_handler: avoid flooding system with RX overrun warnings
|
|
|
|
Note that the sound frequency is distorted (i.e. playing 440 Hz
|
|
sine wave results in 467 Hz)
|
|
---
|
|
sound/soc/dwc/dwc-i2s.c | 36 ++++++++++++++++++++++++++----------
|
|
sound/soc/dwc/local.h | 1 +
|
|
2 files changed, 27 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c
|
|
index 315ca5c4b..af98ec6fe 100644
|
|
--- a/sound/soc/dwc/dwc-i2s.c
|
|
+++ b/sound/soc/dwc/dwc-i2s.c
|
|
@@ -100,6 +100,7 @@ static inline void i2s_enable_irqs(struct dw_i2s_dev *dev, u32 stream,
|
|
|
|
static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
|
|
{
|
|
+ unsigned int rxor_count;
|
|
struct dw_i2s_dev *dev = dev_id;
|
|
bool irq_valid = false;
|
|
u32 isr[4];
|
|
@@ -136,9 +137,13 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
|
|
irq_valid = true;
|
|
}
|
|
|
|
- /* Error Handling: TX */
|
|
+ /* Error Handling: RX */
|
|
if (isr[i] & ISR_RXFO) {
|
|
- dev_err(dev->dev, "RX overrun (ch_id=%d)\n", i);
|
|
+ rxor_count = READ_ONCE(dev->rx_overrun_count);
|
|
+ if (!(rxor_count & 0x3ff))
|
|
+ dev_dbg(dev->dev, "RX overrun (ch_id=%d)\n", i);
|
|
+ rxor_count++;
|
|
+ WRITE_ONCE(dev->rx_overrun_count, rxor_count);
|
|
irq_valid = true;
|
|
}
|
|
}
|
|
@@ -629,7 +634,8 @@ static int dw_i2s_probe(struct platform_device *pdev)
|
|
const struct i2s_platform_data *pdata = pdev->dev.platform_data;
|
|
struct dw_i2s_dev *dev;
|
|
struct resource *res;
|
|
- int ret, irq;
|
|
+ int ret, irq, irq_count;
|
|
+ unsigned idx;
|
|
struct snd_soc_dai_driver *dw_i2s_dai;
|
|
const char *clk_id;
|
|
|
|
@@ -649,13 +655,23 @@ static int dw_i2s_probe(struct platform_device *pdev)
|
|
|
|
dev->dev = &pdev->dev;
|
|
|
|
- irq = platform_get_irq_optional(pdev, 0);
|
|
- if (irq >= 0) {
|
|
- ret = devm_request_irq(&pdev->dev, irq, i2s_irq_handler, 0,
|
|
- pdev->name, dev);
|
|
- if (ret < 0) {
|
|
- dev_err(&pdev->dev, "failed to request irq\n");
|
|
- return ret;
|
|
+ irq_count = platform_irq_count(pdev);
|
|
+ if (irq_count < 0) /* - EPROBE_DEFER */
|
|
+ return irq_count;
|
|
+ else if (!irq_count) {
|
|
+ dev_err(&pdev->dev, "no IRQs found for device\n");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ for (idx = 0; idx < (unsigned)irq_count; idx++) {
|
|
+ irq = platform_get_irq_optional(pdev, idx);
|
|
+ if (irq >= 0) {
|
|
+ ret = devm_request_irq(&pdev->dev, irq, i2s_irq_handler, 0,
|
|
+ pdev->name, dev);
|
|
+ if (ret < 0) {
|
|
+ dev_err(&pdev->dev, "failed to request irq\n");
|
|
+ return ret;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
diff --git a/sound/soc/dwc/local.h b/sound/soc/dwc/local.h
|
|
index 1c361eb61..1d6b6fd87 100644
|
|
--- a/sound/soc/dwc/local.h
|
|
+++ b/sound/soc/dwc/local.h
|
|
@@ -117,6 +117,7 @@ struct dw_i2s_dev {
|
|
bool *period_elapsed);
|
|
unsigned int tx_ptr;
|
|
unsigned int rx_ptr;
|
|
+ unsigned int rx_overrun_count;
|
|
};
|
|
|
|
#if IS_ENABLED(CONFIG_SND_DESIGNWARE_PCM)
|
|
--
|
|
2.33.2
|
|
|