Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 367
Fix playback and capture multiple runs which occasionally fails with Input/output error#3867
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
1ac6f57a5111658468cf2852840cFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -651,11 +651,11 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) | ||
| /* only start the DAI if we are not XRUN handling */ | ||
| if (dd->xrun == 0) { | ||
| /* start the DAI */ | ||
| dai_trigger(dd->dai, cmd, dev->direction); | ||
| ret = dma_start(dd->chan); | ||
| if (ret < 0) | ||
| return ret; | ||
| /* start the DAI */ | ||
| dai_trigger(dd->dai, cmd, dev->direction); | ||
| } else { | ||
| dd->xrun = 0; | ||
| } | ||
| @@ -695,8 +695,21 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) | ||
| COMPILER_FALLTHROUGH; | ||
| case COMP_TRIGGER_STOP: | ||
| comp_dbg(dev, "dai_comp_trigger_internal(), STOP"); | ||
| /* | ||
| * Some platforms cannot just simple disable | ||
| * DMA channel during the transfer, | ||
| * because it will hang the whole DMA controller. | ||
| * Therefore, stop the DMA first and let the DAI | ||
| * drain the FIFO in order to stop the channel | ||
| * as soon as possible. | ||
| */ | ||
| #if CONFIG_DMA_SUSPEND_DRAIN | ||
| ret = dma_stop(dd->chan); | ||
| dai_trigger(dd->dai, cmd, dev->direction); | ||
| #else | ||
| dai_trigger(dd->dai, cmd, dev->direction); | ||
| ret = dma_stop(dd->chan); | ||
| #endif | ||
| break; | ||
| case COMP_TRIGGER_PAUSE: | ||
dbaluta marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| comp_dbg(dev, "dai_comp_trigger_internal(), PAUSE"); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -33,41 +33,68 @@ static void sai_start(struct dai *dai, int direction) | ||
| uint32_t xcsr = 0U; | ||
dbaluta marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| /* enable DMA requests */ | ||
| if (direction == DAI_DIR_CAPTURE) { | ||
| /* Software Reset */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_CAPTURE), | ||
| REG_SAI_CSR_SR, REG_SAI_CSR_SR); | ||
| /* Clear SR bit to finish the reset */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_CAPTURE), | ||
| REG_SAI_CSR_SR, 0U); | ||
| /* Check if the opposite direction is also disabled */ | ||
| xcsr = dai_read(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK)); | ||
| if (!(xcsr & REG_SAI_CSR_FRDE)) { | ||
| /* Software Reset */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), | ||
| REG_SAI_CSR_SR, REG_SAI_CSR_SR); | ||
| /* Clear SR bit to finish the reset */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), | ||
| REG_SAI_CSR_SR, 0U); | ||
| /* Transmitter enable */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), | ||
| REG_SAI_CSR_TERE, REG_SAI_CSR_TERE); | ||
| } | ||
| } else { | ||
| /* Check if the opposite direction is also disabled */ | ||
| xcsr = dai_read(dai, REG_SAI_XCSR(DAI_DIR_CAPTURE)); | ||
| if (!(xcsr & REG_SAI_CSR_FRDE)) { | ||
| /* Software Reset */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), | ||
| REG_SAI_CSR_SR, REG_SAI_CSR_SR); | ||
| /* Clear SR bit to finish the reset */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), | ||
| REG_SAI_CSR_SR, 0U); | ||
| } | ||
| } | ||
| /* W1C */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(direction), | ||
| REG_SAI_CSR_FRDE, REG_SAI_CSR_FRDE); | ||
| #ifdef CONFIG_IMX8M | ||
| dai_update_bits(dai, REG_SAI_MCTL, REG_SAI_MCTL_MCLK_EN, | ||
| REG_SAI_MCTL_MCLK_EN); | ||
| #endif | ||
| REG_SAI_CSR_FEF, 1); | ||
| dai_update_bits(dai, REG_SAI_XCSR(direction), | ||
| REG_SAI_CSR_SEF, 1); | ||
| dai_update_bits(dai, REG_SAI_XCSR(direction), | ||
| REG_SAI_CSR_WSF, 1); | ||
| /* add one word to FIFO before TRCE is enabled */ | ||
| if (direction == DAI_DIR_PLAYBACK) | ||
| dai_write(dai, REG_SAI_TDR0, 0x0); | ||
| else | ||
| dai_write(dai, REG_SAI_RDR0, 0x0); | ||
| /* transmitter enable */ | ||
| /* enable DMA requests */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(direction), | ||
| REG_SAI_CSR_TERE, REG_SAI_CSR_TERE); | ||
| /* TODO: for the time being use half FIFO size as watermark */ | ||
| dai_update_bits(dai, REG_SAI_XCR1(direction), | ||
| REG_SAI_CR1_RFW_MASK, SAI_FIFO_WORD_SIZE / 2); | ||
| REG_SAI_CSR_FRDE, REG_SAI_CSR_FRDE); | ||
| #ifdef CONFIG_IMX8M | ||
| dai_update_bits(dai, REG_SAI_MCTL, REG_SAI_MCTL_MCLK_EN, | ||
| REG_SAI_MCTL_MCLK_EN); | ||
| #endif | ||
| /* transmit/receive data channel enable */ | ||
| dai_update_bits(dai, REG_SAI_XCR3(direction), | ||
| REG_SAI_CR3_TRCE_MASK, REG_SAI_CR3_TRCE(1)); | ||
| if (direction == DAI_DIR_CAPTURE) { | ||
| xcsr = dai_read(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK)); | ||
| if (!(xcsr & REG_SAI_CSR_FRDE)) { | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), | ||
| REG_SAI_CSR_TERE, REG_SAI_CSR_TERE); | ||
| dai_update_bits(dai, REG_SAI_XCR3(DAI_DIR_PLAYBACK), | ||
| REG_SAI_CR3_TRCE_MASK, | ||
| REG_SAI_CR3_TRCE(1)); | ||
| } | ||
| } | ||
| /* transmitter/receiver enable */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(direction), | ||
| REG_SAI_CSR_TERE, REG_SAI_CSR_TERE); | ||
| } | ||
| static void sai_stop(struct dai *dai, int direction) | ||
| @@ -76,32 +103,39 @@ static void sai_stop(struct dai *dai, int direction) | ||
| uint32_t xcsr = 0U; | ||
| /* Disable DMA request */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(direction), | ||
| REG_SAI_CSR_FRDE, 0); | ||
| /* Transmit/Receive data channel disable */ | ||
| dai_update_bits(dai, REG_SAI_XCR3(direction), | ||
| REG_SAI_CR3_TRCE_MASK, | ||
| REG_SAI_CR3_TRCE(0)); | ||
| /* Disable interrupts */ | ||
| dai_update_bits(dai, REG_SAI_XCSR(direction), | ||
| REG_SAI_CSR_XIE_MASK, 0); | ||
| /* Check if the opposite direction is also disabled */ | ||
| xcsr = dai_read(dai, REG_SAI_XCSR(!direction)); | ||
| if (!(xcsr & REG_SAI_CSR_FRDE)) { | ||
| /* Disable both directions and reset their FIFOs */ | ||
| dai_update_bits(dai, REG_SAI_TCSR, REG_SAI_CSR_TERE, 0); | ||
| poll_for_register_delay(dai_base(dai) + REG_SAI_TCSR, | ||
| REG_SAI_CSR_TERE, 0, 100); | ||
| dai_update_bits(dai, REG_SAI_RCSR, REG_SAI_CSR_TERE, 0); | ||
| poll_for_register_delay(dai_base(dai) + REG_SAI_RCSR, | ||
| /* Disable transmitter/receiver */ | ||
| if (direction == DAI_DIR_CAPTURE) { | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_CAPTURE), REG_SAI_CSR_TERE, 0); | ||
| poll_for_register_delay(dai_base(dai) + REG_SAI_XCSR(DAI_DIR_CAPTURE), | ||
| REG_SAI_CSR_TERE, 0, 100); | ||
| /* Software Reset for both Tx and Rx */ | ||
| dai_update_bits(dai, REG_SAI_TCSR, REG_SAI_CSR_SR, | ||
| REG_SAI_CSR_SR); | ||
| dai_update_bits(dai, REG_SAI_RCSR, REG_SAI_CSR_SR, | ||
| REG_SAI_CSR_SR); | ||
| /* Clear SR bit to finish the reset */ | ||
| dai_update_bits(dai, REG_SAI_TCSR, REG_SAI_CSR_SR, 0U); | ||
| dai_update_bits(dai, REG_SAI_RCSR, REG_SAI_CSR_SR, 0U); | ||
| /* Check if the opposite direction is also disabled */ | ||
| xcsr = dai_read(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK)); | ||
| if (!(xcsr & REG_SAI_CSR_FRDE)) { | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), REG_SAI_CSR_TERE, 0); | ||
| poll_for_register_delay(dai_base(dai) + REG_SAI_XCSR(DAI_DIR_PLAYBACK), | ||
| REG_SAI_CSR_TERE, 0, 100); | ||
| } | ||
| } else { | ||
| /* Check if the opposite direction is also disabled */ | ||
| xcsr = dai_read(dai, REG_SAI_XCSR(DAI_DIR_CAPTURE)); | ||
| if (!(xcsr & REG_SAI_CSR_FRDE)) { | ||
| dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), REG_SAI_CSR_TERE, 0); | ||
| poll_for_register_delay(dai_base(dai) + REG_SAI_XCSR(DAI_DIR_PLAYBACK), | ||
| REG_SAI_CSR_TERE, 0, 100); | ||
| } | ||
| } | ||
dbaluta marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| @@ -255,6 +289,9 @@ static inline int sai_set_config(struct dai *dai, | ||
| mask_cr5 = REG_SAI_CR5_WNW_MASK | REG_SAI_CR5_W0W_MASK | | ||
| REG_SAI_CR5_FBT_MASK; | ||
| /* TODO: for the time being use half FIFO size as watermark */ | ||
| dai_update_bits(dai, REG_SAI_XCR1(REG_TX_DIR), | ||
| REG_SAI_CR1_RFW_MASK, SAI_FIFO_WORD_SIZE / 2); | ||
| dai_update_bits(dai, REG_SAI_XCR2(REG_TX_DIR), mask_cr2, val_cr2); | ||
| dai_update_bits(dai, REG_SAI_XCR4(REG_TX_DIR), mask_cr4, val_cr4); | ||
| dai_update_bits(dai, REG_SAI_XCR5(REG_TX_DIR), mask_cr5, val_cr5); | ||
| @@ -264,6 +301,10 @@ static inline int sai_set_config(struct dai *dai, | ||
| val_cr2 |= REG_SAI_CR2_SYNC; | ||
| mask_cr2 |= REG_SAI_CR2_SYNC_MASK; | ||
| /* TODO: for the time being use half FIFO size as watermark */ | ||
| dai_update_bits(dai, REG_SAI_XCR1(REG_RX_DIR), | ||
| REG_SAI_CR1_RFW_MASK, SAI_FIFO_WORD_SIZE / 2); | ||
| dai_update_bits(dai, REG_SAI_XCR2(REG_RX_DIR), mask_cr2, val_cr2); | ||
| dai_update_bits(dai, REG_SAI_XCR4(REG_RX_DIR), mask_cr4, val_cr4); | ||
dbaluta marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| dai_update_bits(dai, REG_SAI_XCR5(REG_RX_DIR), mask_cr5, val_cr5); | ||
Uh oh!
There was an error while loading. Please reload this page.