Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: fsl_xcvr: enable some interrupts

Merge series from Shengjiu Wang <shengjiu.wang@nxp.com>:

Enable interrupt of cmdc status update and the interrupts for
wrong preamble received.

+86 -13
+81 -13
sound/soc/fsl/fsl_xcvr.c
··· 53 53 struct snd_aes_iec958 rx_iec958; 54 54 struct snd_aes_iec958 tx_iec958; 55 55 u8 cap_ds[FSL_XCVR_CAPDS_SIZE]; 56 + struct work_struct work_rst; 57 + spinlock_t lock; /* Protect hw_reset and trigger */ 56 58 }; 57 59 58 60 static const struct fsl_xcvr_pll_conf { ··· 665 663 { 666 664 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai); 667 665 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 668 - int ret; 666 + unsigned long lock_flags; 667 + int ret = 0; 668 + 669 + spin_lock_irqsave(&xcvr->lock, lock_flags); 669 670 670 671 switch (cmd) { 671 672 case SNDRV_PCM_TRIGGER_START: ··· 680 675 FSL_XCVR_EXT_CTRL_DPTH_RESET(tx)); 681 676 if (ret < 0) { 682 677 dev_err(dai->dev, "Failed to set DPATH RESET: %d\n", ret); 683 - return ret; 678 + goto release_lock; 684 679 } 685 680 686 681 if (tx) { ··· 692 687 FSL_XCVR_ISR_CMDC_TX_EN); 693 688 if (ret < 0) { 694 689 dev_err(dai->dev, "err updating isr %d\n", ret); 695 - return ret; 690 + goto release_lock; 696 691 } 697 692 fallthrough; 698 693 case FSL_XCVR_MODE_SPDIF: ··· 701 696 FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX); 702 697 if (ret < 0) { 703 698 dev_err(dai->dev, "Failed to start DATA_TX: %d\n", ret); 704 - return ret; 699 + goto release_lock; 705 700 } 706 701 break; 707 702 } ··· 712 707 FSL_XCVR_EXT_CTRL_DMA_DIS(tx), 0); 713 708 if (ret < 0) { 714 709 dev_err(dai->dev, "Failed to enable DMA: %d\n", ret); 715 - return ret; 710 + goto release_lock; 716 711 } 717 712 718 713 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0, 719 714 FSL_XCVR_IRQ_EARC_ALL, FSL_XCVR_IRQ_EARC_ALL); 720 715 if (ret < 0) { 721 716 dev_err(dai->dev, "Error while setting IER0: %d\n", ret); 722 - return ret; 717 + goto release_lock; 723 718 } 724 719 725 720 /* clear DPATH RESET */ ··· 728 723 0); 729 724 if (ret < 0) { 730 725 dev_err(dai->dev, "Failed to clear DPATH RESET: %d\n", ret); 731 - return ret; 726 + goto release_lock; 732 727 } 733 728 734 729 break; ··· 741 736 FSL_XCVR_EXT_CTRL_DMA_DIS(tx)); 742 737 if (ret < 0) { 743 738 dev_err(dai->dev, "Failed to disable DMA: %d\n", ret); 744 - return ret; 739 + goto release_lock; 745 740 } 746 741 747 742 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0, 748 743 FSL_XCVR_IRQ_EARC_ALL, 0); 749 744 if (ret < 0) { 750 745 dev_err(dai->dev, "Failed to clear IER0: %d\n", ret); 751 - return ret; 746 + goto release_lock; 752 747 } 753 748 754 749 if (tx) { ··· 759 754 FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX); 760 755 if (ret < 0) { 761 756 dev_err(dai->dev, "Failed to stop DATA_TX: %d\n", ret); 762 - return ret; 757 + goto release_lock; 763 758 } 764 759 if (xcvr->soc_data->spdif_only) 765 760 break; ··· 773 768 if (ret < 0) { 774 769 dev_err(dai->dev, 775 770 "Err updating ISR %d\n", ret); 776 - return ret; 771 + goto release_lock; 777 772 } 778 773 break; 779 774 } 780 775 } 781 776 break; 782 777 default: 783 - return -EINVAL; 778 + ret = -EINVAL; 779 + break; 784 780 } 785 781 786 - return 0; 782 + release_lock: 783 + spin_unlock_irqrestore(&xcvr->lock, lock_flags); 784 + return ret; 787 785 } 788 786 789 787 static int fsl_xcvr_load_firmware(struct fsl_xcvr *xcvr) ··· 1206 1198 .cache_type = REGCACHE_FLAT, 1207 1199 }; 1208 1200 1201 + static void reset_rx_work(struct work_struct *work) 1202 + { 1203 + struct fsl_xcvr *xcvr = container_of(work, struct fsl_xcvr, work_rst); 1204 + struct device *dev = &xcvr->pdev->dev; 1205 + unsigned long lock_flags; 1206 + u32 ext_ctrl; 1207 + 1208 + dev_dbg(dev, "reset rx path\n"); 1209 + spin_lock_irqsave(&xcvr->lock, lock_flags); 1210 + regmap_read(xcvr->regmap, FSL_XCVR_EXT_CTRL, &ext_ctrl); 1211 + 1212 + if (!(ext_ctrl & FSL_XCVR_EXT_CTRL_DMA_RD_DIS)) { 1213 + regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, 1214 + FSL_XCVR_EXT_CTRL_DMA_RD_DIS, 1215 + FSL_XCVR_EXT_CTRL_DMA_RD_DIS); 1216 + regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, 1217 + FSL_XCVR_EXT_CTRL_RX_DPTH_RESET, 1218 + FSL_XCVR_EXT_CTRL_RX_DPTH_RESET); 1219 + regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, 1220 + FSL_XCVR_EXT_CTRL_DMA_RD_DIS, 1221 + 0); 1222 + regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, 1223 + FSL_XCVR_EXT_CTRL_RX_DPTH_RESET, 1224 + 0); 1225 + } 1226 + spin_unlock_irqrestore(&xcvr->lock, lock_flags); 1227 + } 1228 + 1209 1229 static irqreturn_t irq0_isr(int irq, void *devid) 1210 1230 { 1211 1231 struct fsl_xcvr *xcvr = (struct fsl_xcvr *)devid; ··· 1300 1264 if (isr & FSL_XCVR_IRQ_DMA_WR_REQ) { 1301 1265 dev_dbg(dev, "DMA write request\n"); 1302 1266 isr_clr |= FSL_XCVR_IRQ_DMA_WR_REQ; 1267 + } 1268 + if (isr & FSL_XCVR_IRQ_CMDC_STATUS_UPD) { 1269 + dev_dbg(dev, "CMDC status update\n"); 1270 + isr_clr |= FSL_XCVR_IRQ_CMDC_STATUS_UPD; 1271 + } 1272 + if (isr & FSL_XCVR_IRQ_PREAMBLE_MISMATCH) { 1273 + dev_dbg(dev, "Preamble mismatch\n"); 1274 + isr_clr |= FSL_XCVR_IRQ_PREAMBLE_MISMATCH; 1275 + } 1276 + if (isr & FSL_XCVR_IRQ_UNEXP_PRE_REC) { 1277 + dev_dbg(dev, "Unexpected preamble received\n"); 1278 + isr_clr |= FSL_XCVR_IRQ_UNEXP_PRE_REC; 1279 + } 1280 + if (isr & FSL_XCVR_IRQ_M_W_PRE_MISMATCH) { 1281 + dev_dbg(dev, "M/W preamble mismatch\n"); 1282 + isr_clr |= FSL_XCVR_IRQ_M_W_PRE_MISMATCH; 1283 + } 1284 + if (isr & FSL_XCVR_IRQ_B_PRE_MISMATCH) { 1285 + dev_dbg(dev, "B preamble mismatch\n"); 1286 + isr_clr |= FSL_XCVR_IRQ_B_PRE_MISMATCH; 1287 + } 1288 + 1289 + if (isr & (FSL_XCVR_IRQ_PREAMBLE_MISMATCH | 1290 + FSL_XCVR_IRQ_UNEXP_PRE_REC | 1291 + FSL_XCVR_IRQ_M_W_PRE_MISMATCH | 1292 + FSL_XCVR_IRQ_B_PRE_MISMATCH)) { 1293 + schedule_work(&xcvr->work_rst); 1303 1294 } 1304 1295 1305 1296 if (isr_clr) { ··· 1474 1411 fsl_xcvr_comp.name); 1475 1412 } 1476 1413 1414 + INIT_WORK(&xcvr->work_rst, reset_rx_work); 1415 + spin_lock_init(&xcvr->lock); 1477 1416 return ret; 1478 1417 } 1479 1418 1480 1419 static void fsl_xcvr_remove(struct platform_device *pdev) 1481 1420 { 1421 + struct fsl_xcvr *xcvr = dev_get_drvdata(&pdev->dev); 1422 + 1423 + cancel_work_sync(&xcvr->work_rst); 1482 1424 pm_runtime_disable(&pdev->dev); 1483 1425 } 1484 1426
+5
sound/soc/fsl/fsl_xcvr.h
··· 165 165 FSL_XCVR_IRQ_MUTE | \ 166 166 FSL_XCVR_IRQ_FIFO_UOFL_ERR | \ 167 167 FSL_XCVR_IRQ_HOST_WAKEUP | \ 168 + FSL_XCVR_IRQ_CMDC_STATUS_UPD |\ 169 + FSL_XCVR_IRQ_B_PRE_MISMATCH |\ 170 + FSL_XCVR_IRQ_M_W_PRE_MISMATCH |\ 171 + FSL_XCVR_IRQ_PREAMBLE_MISMATCH |\ 172 + FSL_XCVR_IRQ_UNEXP_PRE_REC |\ 168 173 FSL_XCVR_IRQ_ARC_MODE) 169 174 170 175 #define FSL_XCVR_ISR_CMDC_TX_EN BIT(3)