[d-kernel] [PATCH 28/32] (BROKEN) dwc-i2s: support Baikal-M SoC

Alexey Sheplyakov asheplyakov на basealt.ru
Ср Дек 14 16:19:15 MSK 2022


* 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)

Signed-off-by: Alexey Sheplyakov <asheplyakov на basealt.ru>
X-feature-Baikal-M
---
 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 7f7dd07c63b2..1568d82166f3 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;
 		}
 	}
@@ -630,7 +635,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;
 
@@ -650,13 +656,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 1c361eb6127e..1d6b6fd870ca 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.5



Подробная информация о списке рассылки devel-kernel