fsl_esai.c (3f98538c7673e5306a126fd3cb7e0a84abc170ee) | fsl_esai.c (5be6155b50bbf7083b4bfa219e4ce6d1491f42f0) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2// 3// Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver 4// 5// Copyright (C) 2014 Freescale Semiconductor, Inc. 6 7#include <linux/clk.h> 8#include <linux/dmaengine.h> --- 21 unchanged lines hidden (view full) --- 30 * @regmap: regmap handler 31 * @coreclk: clock source to access register 32 * @extalclk: esai clock source to derive HCK, SCK and FS 33 * @fsysclk: system clock source to derive HCK, SCK and FS 34 * @spbaclk: SPBA clock (optional, depending on SoC design) 35 * @fifo_depth: depth of tx/rx FIFO 36 * @slot_width: width of each DAI slot 37 * @slots: number of slots | 1// SPDX-License-Identifier: GPL-2.0 2// 3// Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver 4// 5// Copyright (C) 2014 Freescale Semiconductor, Inc. 6 7#include <linux/clk.h> 8#include <linux/dmaengine.h> --- 21 unchanged lines hidden (view full) --- 30 * @regmap: regmap handler 31 * @coreclk: clock source to access register 32 * @extalclk: esai clock source to derive HCK, SCK and FS 33 * @fsysclk: system clock source to derive HCK, SCK and FS 34 * @spbaclk: SPBA clock (optional, depending on SoC design) 35 * @fifo_depth: depth of tx/rx FIFO 36 * @slot_width: width of each DAI slot 37 * @slots: number of slots |
38 * @channels: channel num for tx or rx |
|
38 * @hck_rate: clock rate of desired HCKx clock 39 * @sck_rate: clock rate of desired SCKx clock 40 * @hck_dir: the direction of HCKx pads 41 * @sck_div: if using PSR/PM dividers for SCKx clock 42 * @slave_mode: if fully using DAI slave mode 43 * @synchronous: if using tx/rx synchronous mode 44 * @name: driver name 45 */ --- 6 unchanged lines hidden (view full) --- 52 struct clk *extalclk; 53 struct clk *fsysclk; 54 struct clk *spbaclk; 55 u32 fifo_depth; 56 u32 slot_width; 57 u32 slots; 58 u32 tx_mask; 59 u32 rx_mask; | 39 * @hck_rate: clock rate of desired HCKx clock 40 * @sck_rate: clock rate of desired SCKx clock 41 * @hck_dir: the direction of HCKx pads 42 * @sck_div: if using PSR/PM dividers for SCKx clock 43 * @slave_mode: if fully using DAI slave mode 44 * @synchronous: if using tx/rx synchronous mode 45 * @name: driver name 46 */ --- 6 unchanged lines hidden (view full) --- 53 struct clk *extalclk; 54 struct clk *fsysclk; 55 struct clk *spbaclk; 56 u32 fifo_depth; 57 u32 slot_width; 58 u32 slots; 59 u32 tx_mask; 60 u32 rx_mask; |
61 u32 channels[2]; |
|
60 u32 hck_rate[2]; 61 u32 sck_rate[2]; 62 bool hck_dir[2]; 63 bool sck_div[2]; 64 bool slave_mode; 65 bool synchronous; 66 char name[32]; 67}; --- 470 unchanged lines hidden (view full) --- 538 /* Remove ESAI personal reset by configuring ESAI_PCRC and ESAI_PRRC */ 539 regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, 540 ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); 541 regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, 542 ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); 543 return 0; 544} 545 | 62 u32 hck_rate[2]; 63 u32 sck_rate[2]; 64 bool hck_dir[2]; 65 bool sck_div[2]; 66 bool slave_mode; 67 bool synchronous; 68 char name[32]; 69}; --- 470 unchanged lines hidden (view full) --- 540 /* Remove ESAI personal reset by configuring ESAI_PCRC and ESAI_PRRC */ 541 regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, 542 ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); 543 regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, 544 ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); 545 return 0; 546} 547 |
548static int fsl_esai_hw_init(struct fsl_esai *esai_priv) 549{ 550 struct platform_device *pdev = esai_priv->pdev; 551 int ret; 552 553 /* Reset ESAI unit */ 554 ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, 555 ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK, 556 ESAI_ECR_ESAIEN | ESAI_ECR_ERST); 557 if (ret) { 558 dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); 559 return ret; 560 } 561 562 /* 563 * We need to enable ESAI so as to access some of its registers. 564 * Otherwise, we would fail to dump regmap from user space. 565 */ 566 ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, 567 ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK, 568 ESAI_ECR_ESAIEN); 569 if (ret) { 570 dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); 571 return ret; 572 } 573 574 regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, 575 ESAI_PRRC_PDC_MASK, 0); 576 regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, 577 ESAI_PCRC_PC_MASK, 0); 578 579 return 0; 580} 581 582static int fsl_esai_register_restore(struct fsl_esai *esai_priv) 583{ 584 int ret; 585 586 /* FIFO reset for safety */ 587 regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, 588 ESAI_xFCR_xFR, ESAI_xFCR_xFR); 589 regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, 590 ESAI_xFCR_xFR, ESAI_xFCR_xFR); 591 592 regcache_mark_dirty(esai_priv->regmap); 593 ret = regcache_sync(esai_priv->regmap); 594 if (ret) 595 return ret; 596 597 /* FIFO reset done */ 598 regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0); 599 regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0); 600 601 return 0; 602} 603 604static void fsl_esai_trigger_start(struct fsl_esai *esai_priv, bool tx) 605{ 606 u8 i, channels = esai_priv->channels[tx]; 607 u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); 608 u32 mask; 609 610 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 611 ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); 612 613 /* Write initial words reqiured by ESAI as normal procedure */ 614 for (i = 0; tx && i < channels; i++) 615 regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); 616 617 /* 618 * When set the TE/RE in the end of enablement flow, there 619 * will be channel swap issue for multi data line case. 620 * In order to workaround this issue, we switch the bit 621 * enablement sequence to below sequence 622 * 1) clear the xSMB & xSMA: which is done in probe and 623 * stop state. 624 * 2) set TE/RE 625 * 3) set xSMB 626 * 4) set xSMA: xSMA is the last one in this flow, which 627 * will trigger esai to start. 628 */ 629 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), 630 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 631 tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins)); 632 mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask; 633 634 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), 635 ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); 636 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), 637 ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); 638} 639 640static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx) 641{ 642 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), 643 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); 644 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), 645 ESAI_xSMA_xS_MASK, 0); 646 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), 647 ESAI_xSMB_xS_MASK, 0); 648 649 /* Disable and reset FIFO */ 650 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 651 ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); 652 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 653 ESAI_xFCR_xFR, 0); 654} 655 |
|
546static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, 547 struct snd_soc_dai *dai) 548{ 549 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 550 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 656static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, 657 struct snd_soc_dai *dai) 658{ 659 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 660 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
551 u8 i, channels = substream->runtime->channels; 552 u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); 553 u32 mask; | |
554 | 661 |
662 esai_priv->channels[tx] = substream->runtime->channels; 663 |
|
555 switch (cmd) { 556 case SNDRV_PCM_TRIGGER_START: 557 case SNDRV_PCM_TRIGGER_RESUME: 558 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 664 switch (cmd) { 665 case SNDRV_PCM_TRIGGER_START: 666 case SNDRV_PCM_TRIGGER_RESUME: 667 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
559 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 560 ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); 561 562 /* Write initial words reqiured by ESAI as normal procedure */ 563 for (i = 0; tx && i < channels; i++) 564 regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); 565 566 /* 567 * When set the TE/RE in the end of enablement flow, there 568 * will be channel swap issue for multi data line case. 569 * In order to workaround this issue, we switch the bit 570 * enablement sequence to below sequence 571 * 1) clear the xSMB & xSMA: which is done in probe and 572 * stop state. 573 * 2) set TE/RE 574 * 3) set xSMB 575 * 4) set xSMA: xSMA is the last one in this flow, which 576 * will trigger esai to start. 577 */ 578 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), 579 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 580 tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins)); 581 mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask; 582 583 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), 584 ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); 585 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), 586 ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); 587 | 668 fsl_esai_trigger_start(esai_priv, tx); |
588 break; 589 case SNDRV_PCM_TRIGGER_SUSPEND: 590 case SNDRV_PCM_TRIGGER_STOP: 591 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 669 break; 670 case SNDRV_PCM_TRIGGER_SUSPEND: 671 case SNDRV_PCM_TRIGGER_STOP: 672 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
592 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), 593 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); 594 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), 595 ESAI_xSMA_xS_MASK, 0); 596 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), 597 ESAI_xSMB_xS_MASK, 0); 598 599 /* Disable and reset FIFO */ 600 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 601 ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); 602 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 603 ESAI_xFCR_xFR, 0); | 673 fsl_esai_trigger_stop(esai_priv, tx); |
604 break; 605 default: 606 return -EINVAL; 607 } 608 609 return 0; 610} 611 --- 249 unchanged lines hidden (view full) --- 861 if (esai_priv->synchronous) { 862 fsl_esai_dai.symmetric_rates = 1; 863 fsl_esai_dai.symmetric_channels = 1; 864 fsl_esai_dai.symmetric_samplebits = 1; 865 } 866 867 dev_set_drvdata(&pdev->dev, esai_priv); 868 | 674 break; 675 default: 676 return -EINVAL; 677 } 678 679 return 0; 680} 681 --- 249 unchanged lines hidden (view full) --- 931 if (esai_priv->synchronous) { 932 fsl_esai_dai.symmetric_rates = 1; 933 fsl_esai_dai.symmetric_channels = 1; 934 fsl_esai_dai.symmetric_samplebits = 1; 935 } 936 937 dev_set_drvdata(&pdev->dev, esai_priv); 938 |
869 /* Reset ESAI unit */ 870 ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST); 871 if (ret) { 872 dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); | 939 ret = fsl_esai_hw_init(esai_priv); 940 if (ret) |
873 return ret; | 941 return ret; |
874 } | |
875 | 942 |
876 /* 877 * We need to enable ESAI so as to access some of its registers. 878 * Otherwise, we would fail to dump regmap from user space. 879 */ 880 ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN); 881 if (ret) { 882 dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); 883 return ret; 884 } 885 | |
886 esai_priv->tx_mask = 0xFFFFFFFF; 887 esai_priv->rx_mask = 0xFFFFFFFF; 888 889 /* Clear the TSMA, TSMB, RSMA, RSMB */ 890 regmap_write(esai_priv->regmap, REG_ESAI_TSMA, 0); 891 regmap_write(esai_priv->regmap, REG_ESAI_TSMB, 0); 892 regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0); 893 regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0); --- 56 unchanged lines hidden (view full) --- 950 if (!IS_ERR(esai->fsysclk)) { 951 ret = clk_prepare_enable(esai->fsysclk); 952 if (ret) 953 goto err_fsysclk; 954 } 955 956 regcache_cache_only(esai->regmap, false); 957 | 943 esai_priv->tx_mask = 0xFFFFFFFF; 944 esai_priv->rx_mask = 0xFFFFFFFF; 945 946 /* Clear the TSMA, TSMB, RSMA, RSMB */ 947 regmap_write(esai_priv->regmap, REG_ESAI_TSMA, 0); 948 regmap_write(esai_priv->regmap, REG_ESAI_TSMB, 0); 949 regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0); 950 regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0); --- 56 unchanged lines hidden (view full) --- 1007 if (!IS_ERR(esai->fsysclk)) { 1008 ret = clk_prepare_enable(esai->fsysclk); 1009 if (ret) 1010 goto err_fsysclk; 1011 } 1012 1013 regcache_cache_only(esai->regmap, false); 1014 |
958 /* FIFO reset for safety */ 959 regmap_update_bits(esai->regmap, REG_ESAI_TFCR, 960 ESAI_xFCR_xFR, ESAI_xFCR_xFR); 961 regmap_update_bits(esai->regmap, REG_ESAI_RFCR, 962 ESAI_xFCR_xFR, ESAI_xFCR_xFR); 963 964 ret = regcache_sync(esai->regmap); | 1015 ret = fsl_esai_register_restore(esai); |
965 if (ret) 966 goto err_regcache_sync; 967 | 1016 if (ret) 1017 goto err_regcache_sync; 1018 |
968 /* FIFO reset done */ 969 regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0); 970 regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0); 971 | |
972 return 0; 973 974err_regcache_sync: 975 if (!IS_ERR(esai->fsysclk)) 976 clk_disable_unprepare(esai->fsysclk); 977err_fsysclk: 978 if (!IS_ERR(esai->extalclk)) 979 clk_disable_unprepare(esai->extalclk); --- 6 unchanged lines hidden (view full) --- 986 return ret; 987} 988 989static int fsl_esai_runtime_suspend(struct device *dev) 990{ 991 struct fsl_esai *esai = dev_get_drvdata(dev); 992 993 regcache_cache_only(esai->regmap, true); | 1019 return 0; 1020 1021err_regcache_sync: 1022 if (!IS_ERR(esai->fsysclk)) 1023 clk_disable_unprepare(esai->fsysclk); 1024err_fsysclk: 1025 if (!IS_ERR(esai->extalclk)) 1026 clk_disable_unprepare(esai->extalclk); --- 6 unchanged lines hidden (view full) --- 1033 return ret; 1034} 1035 1036static int fsl_esai_runtime_suspend(struct device *dev) 1037{ 1038 struct fsl_esai *esai = dev_get_drvdata(dev); 1039 1040 regcache_cache_only(esai->regmap, true); |
994 regcache_mark_dirty(esai->regmap); | |
995 996 if (!IS_ERR(esai->fsysclk)) 997 clk_disable_unprepare(esai->fsysclk); 998 if (!IS_ERR(esai->extalclk)) 999 clk_disable_unprepare(esai->extalclk); 1000 if (!IS_ERR(esai->spbaclk)) 1001 clk_disable_unprepare(esai->spbaclk); 1002 clk_disable_unprepare(esai->coreclk); --- 29 unchanged lines hidden --- | 1041 1042 if (!IS_ERR(esai->fsysclk)) 1043 clk_disable_unprepare(esai->fsysclk); 1044 if (!IS_ERR(esai->extalclk)) 1045 clk_disable_unprepare(esai->extalclk); 1046 if (!IS_ERR(esai->spbaclk)) 1047 clk_disable_unprepare(esai->spbaclk); 1048 clk_disable_unprepare(esai->coreclk); --- 29 unchanged lines hidden --- |