mirror of
https://abf.rosa.ru/djam/kernel-6.6.git
synced 2025-02-25 03:42:46 +00:00
107 lines
3.2 KiB
Diff
107 lines
3.2 KiB
Diff
From a1d78cf95aa6777e5e7b4cb117450b51c858d550 Mon Sep 17 00:00:00 2001
|
|
From: Alexey Sheplyakov <asheplyakov@basealt.ru>
|
|
Date: Mon, 23 May 2022 19:35:08 +0400
|
|
Subject: [PATCH 627/631] (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)
|
|
|
|
Signed-off-by: Alexey Sheplyakov <asheplyakov@basealt.ru>
|
|
X-feature-Baikal-M
|
|
|
|
[ Adapted for kernel 6.6 ]
|
|
Signed-off-by: Mikhail Novosyolov <m.novosyolov@rosalinux.ru>
|
|
---
|
|
sound/soc/dwc/dwc-i2s.c | 36 +++++++++++++++++++++++++-----------
|
|
sound/soc/dwc/local.h | 1 +
|
|
2 files changed, 26 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c
|
|
index 9ea4be56d3b7..ade5165a7087 100644
|
|
--- a/sound/soc/dwc/dwc-i2s.c
|
|
+++ b/sound/soc/dwc/dwc-i2s.c
|
|
@@ -102,6 +102,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];
|
|
@@ -138,9 +139,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_ratelimited(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;
|
|
}
|
|
}
|
|
@@ -920,7 +925,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;
|
|
|
|
@@ -958,16 +964,24 @@ static int dw_i2s_probe(struct platform_device *pdev)
|
|
return ret;
|
|
}
|
|
|
|
- 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");
|
|
- goto err_assert_reset;
|
|
- }
|
|
+ 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;
|
|
+ }
|
|
+
|
|
dev->i2s_reg_comp1 = I2S_COMP_PARAM_1;
|
|
dev->i2s_reg_comp2 = I2S_COMP_PARAM_2;
|
|
if (pdata) {
|
|
diff --git a/sound/soc/dwc/local.h b/sound/soc/dwc/local.h
|
|
index dce88c9ad5f3..be7a026e5f91 100644
|
|
--- a/sound/soc/dwc/local.h
|
|
+++ b/sound/soc/dwc/local.h
|
|
@@ -149,6 +149,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.40.1
|
|
|