summaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl/fsl_sai.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-10 09:19:44 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-10 09:19:44 -0700
commite7990d45bb88c2f0565b5ee4c32eefe81653faff (patch)
tree852ab6988b7226083fefa0e0e851dbff0e7ec7f2 /sound/soc/fsl/fsl_sai.c
parent190a3998be3ede25d6145e187d6d321f504d28fb (diff)
parenta5065eb6da55b226661456e6a7435f605df98111 (diff)
downloadop-kernel-dev-e7990d45bb88c2f0565b5ee4c32eefe81653faff.zip
op-kernel-dev-e7990d45bb88c2f0565b5ee4c32eefe81653faff.tar.gz
Merge tag 'sound-fix-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai: "Here is a bunch of small fixes that have been collected since the previous pull request. In addition to various misc fixes, the following are included: - HD-audio quirks for Dell, HP, Chromebook, and ALC28x codecs - HD-audio AMD HDMI regression fix - Continued PM support/fixes for ice1712 driver - Multiplatform fixes for ASoC samsung drivers - Addition of device id tables to a few ASoC drivers - Bit clock polarity config and error flag fixes in ASoC fsl_sai" * tag 'sound-fix-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (32 commits) ALSA: usb-audio: Suppress repetitive debug messages from retire_playback_urb() ALSA: hda - Make full_reset boolean ALSA: hda - add headset mic detect quirk for a Dell laptop sound: dmasound: use module_platform_driver_probe() ALSA: au1x00: use module_platform_driver() ALSA: hda - Use runtime helper to check active state. ALSA: ice1712: Fix boundary checks in PCM pointer ops ASoC: davinci-mcasp: Fix bit clock polarity settings ASoC: samsung: Fix build on multiplatform ASoC: fsl_sai: Fix Bit Clock Polarity configurations ALSA: hda - Do not assign streams in reverse order ALSA: hda/realtek - Add eapd shutup to ALC283 ALSA: hda/realtek - Change model name alias for ChromeOS ASoC: da732x: Print correct major id ALSA: hda/realtek - Improve HP depop when system change power state on Chromebook ASoC: cs42l52: Fix mask for REVID sound/oss: Remove uncompilable DBG macro use ALSA: ice1712: Save/restore routing and rate registers ALSA: ice1712: restore AK4xxx volumes on resume ASoC: alc56(23|32): fix undefined return value of probing code ...
Diffstat (limited to 'sound/soc/fsl/fsl_sai.c')
-rw-r--r--sound/soc/fsl/fsl_sai.c93
1 files changed, 86 insertions, 7 deletions
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index c4a4231..56da8c8 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -23,6 +23,71 @@
#include "fsl_sai.h"
+#define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\
+ FSL_SAI_CSR_FEIE)
+
+static irqreturn_t fsl_sai_isr(int irq, void *devid)
+{
+ struct fsl_sai *sai = (struct fsl_sai *)devid;
+ struct device *dev = &sai->pdev->dev;
+ u32 xcsr, mask;
+
+ /* Only handle those what we enabled */
+ mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT;
+
+ /* Tx IRQ */
+ regmap_read(sai->regmap, FSL_SAI_TCSR, &xcsr);
+ xcsr &= mask;
+
+ if (xcsr & FSL_SAI_CSR_WSF)
+ dev_dbg(dev, "isr: Start of Tx word detected\n");
+
+ if (xcsr & FSL_SAI_CSR_SEF)
+ dev_warn(dev, "isr: Tx Frame sync error detected\n");
+
+ if (xcsr & FSL_SAI_CSR_FEF) {
+ dev_warn(dev, "isr: Transmit underrun detected\n");
+ /* FIFO reset for safety */
+ xcsr |= FSL_SAI_CSR_FR;
+ }
+
+ if (xcsr & FSL_SAI_CSR_FWF)
+ dev_dbg(dev, "isr: Enabled transmit FIFO is empty\n");
+
+ if (xcsr & FSL_SAI_CSR_FRF)
+ dev_dbg(dev, "isr: Transmit FIFO watermark has been reached\n");
+
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+ FSL_SAI_CSR_xF_W_MASK | FSL_SAI_CSR_FR, xcsr);
+
+ /* Rx IRQ */
+ regmap_read(sai->regmap, FSL_SAI_RCSR, &xcsr);
+ xcsr &= mask;
+
+ if (xcsr & FSL_SAI_CSR_WSF)
+ dev_dbg(dev, "isr: Start of Rx word detected\n");
+
+ if (xcsr & FSL_SAI_CSR_SEF)
+ dev_warn(dev, "isr: Rx Frame sync error detected\n");
+
+ if (xcsr & FSL_SAI_CSR_FEF) {
+ dev_warn(dev, "isr: Receive overflow detected\n");
+ /* FIFO reset for safety */
+ xcsr |= FSL_SAI_CSR_FR;
+ }
+
+ if (xcsr & FSL_SAI_CSR_FWF)
+ dev_dbg(dev, "isr: Enabled receive FIFO is full\n");
+
+ if (xcsr & FSL_SAI_CSR_FRF)
+ dev_dbg(dev, "isr: Receive FIFO watermark has been reached\n");
+
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+ FSL_SAI_CSR_xF_W_MASK | FSL_SAI_CSR_FR, xcsr);
+
+ return IRQ_HANDLED;
+}
+
static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int fsl_dir)
{
@@ -114,7 +179,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
* that is, together with the last bit of the previous
* data word.
*/
- val_cr2 &= ~FSL_SAI_CR2_BCP;
+ val_cr2 |= FSL_SAI_CR2_BCP;
val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP;
break;
case SND_SOC_DAIFMT_LEFT_J:
@@ -122,7 +187,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
* Frame high, one word length for frame sync,
* frame sync asserts with the first bit of the frame.
*/
- val_cr2 &= ~FSL_SAI_CR2_BCP;
+ val_cr2 |= FSL_SAI_CR2_BCP;
val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP);
break;
case SND_SOC_DAIFMT_DSP_A:
@@ -132,7 +197,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
* that is, together with the last bit of the previous
* data word.
*/
- val_cr2 &= ~FSL_SAI_CR2_BCP;
+ val_cr2 |= FSL_SAI_CR2_BCP;
val_cr4 &= ~FSL_SAI_CR4_FSP;
val_cr4 |= FSL_SAI_CR4_FSE;
sai->is_dsp_mode = true;
@@ -142,7 +207,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
* Frame high, one bit for frame sync,
* frame sync asserts with the first bit of the frame.
*/
- val_cr2 &= ~FSL_SAI_CR2_BCP;
+ val_cr2 |= FSL_SAI_CR2_BCP;
val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP);
sai->is_dsp_mode = true;
break;
@@ -373,8 +438,8 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
- regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, 0x0);
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, 0x0);
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, FSL_SAI_FLAGS);
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, FSL_SAI_FLAGS);
regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
FSL_SAI_MAXBURST_TX * 2);
regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
@@ -490,12 +555,14 @@ static int fsl_sai_probe(struct platform_device *pdev)
struct fsl_sai *sai;
struct resource *res;
void __iomem *base;
- int ret;
+ int irq, ret;
sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
if (!sai)
return -ENOMEM;
+ sai->pdev = pdev;
+
sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs");
if (sai->big_endian_regs)
fsl_sai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
@@ -514,6 +581,18 @@ static int fsl_sai_probe(struct platform_device *pdev)
return PTR_ERR(sai->regmap);
}
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
+ return irq;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, 0, np->name, sai);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
+ return ret;
+ }
+
sai->dma_params_rx.addr = res->start + FSL_SAI_RDR;
sai->dma_params_tx.addr = res->start + FSL_SAI_TDR;
sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
OpenPOWER on IntegriCloud