1818#include <sound/pcm_params.h>
1919#include <sound/dmaengine_pcm.h>
2020#include <sound/tlv.h>
21+
2122#include "rockchip_sai.h"
2223
2324#define DRV_NAME "rockchip-sai"
@@ -215,12 +216,14 @@ static void rockchip_sai_xfer_clk_stop_and_wait(struct rk_sai_dev *sai, unsigned
215216static int rockchip_sai_runtime_suspend (struct device * dev )
216217{
217218 struct rk_sai_dev * sai = dev_get_drvdata (dev );
219+ unsigned long flags ;
218220
219221 rockchip_sai_fsync_lost_detect (sai , 0 );
220222 rockchip_sai_fsync_err_detect (sai , 0 );
221223
222- scoped_guard (spinlock_irqsave , & sai -> xfer_lock )
223- rockchip_sai_xfer_clk_stop_and_wait (sai , NULL );
224+ spin_lock_irqsave (& sai -> xfer_lock , flags );
225+ rockchip_sai_xfer_clk_stop_and_wait (sai , NULL );
226+ spin_unlock_irqrestore (& sai -> xfer_lock , flags );
224227
225228 regcache_cache_only (sai -> regmap , true);
226229 /*
@@ -480,6 +483,7 @@ static int rockchip_sai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
480483 struct rk_sai_dev * sai = snd_soc_dai_get_drvdata (dai );
481484 unsigned int mask = 0 , val = 0 ;
482485 unsigned int clk_gates ;
486+ unsigned long flags ;
483487 int ret = 0 ;
484488
485489 pm_runtime_get_sync (dai -> dev );
@@ -495,56 +499,56 @@ static int rockchip_sai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
495499 sai -> is_master_mode = false;
496500 break ;
497501 default :
498- pm_runtime_put ( dai -> dev ) ;
499- return - EINVAL ;
502+ ret = - EINVAL ;
503+ goto err_pm_put ;
500504 }
501505
502- scoped_guard ( spinlock_irqsave , & sai -> xfer_lock ) {
503- rockchip_sai_xfer_clk_stop_and_wait (sai , & clk_gates );
504- if (sai -> initialized ) {
505- if (sai -> has_capture && sai -> has_playback )
506- rockchip_sai_xfer_stop (sai , -1 );
507- else if (sai -> has_capture )
508- rockchip_sai_xfer_stop (sai , SNDRV_PCM_STREAM_CAPTURE );
509- else
510- rockchip_sai_xfer_stop (sai , SNDRV_PCM_STREAM_PLAYBACK );
511- } else {
512- rockchip_sai_clear (sai , 0 );
513- sai -> initialized = true;
514- }
506+ spin_lock_irqsave ( & sai -> xfer_lock , flags );
507+ rockchip_sai_xfer_clk_stop_and_wait (sai , & clk_gates );
508+ if (sai -> initialized ) {
509+ if (sai -> has_capture && sai -> has_playback )
510+ rockchip_sai_xfer_stop (sai , -1 );
511+ else if (sai -> has_capture )
512+ rockchip_sai_xfer_stop (sai , SNDRV_PCM_STREAM_CAPTURE );
513+ else
514+ rockchip_sai_xfer_stop (sai , SNDRV_PCM_STREAM_PLAYBACK );
515+ } else {
516+ rockchip_sai_clear (sai , 0 );
517+ sai -> initialized = true;
518+ }
515519
516- regmap_update_bits (sai -> regmap , SAI_CKR , mask , val );
517-
518- mask = SAI_CKR_CKP_MASK | SAI_CKR_FSP_MASK ;
519- switch (fmt & SND_SOC_DAIFMT_INV_MASK ) {
520- case SND_SOC_DAIFMT_NB_NF :
521- val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_NORMAL ;
522- break ;
523- case SND_SOC_DAIFMT_NB_IF :
524- val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_INVERTED ;
525- break ;
526- case SND_SOC_DAIFMT_IB_NF :
527- val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_NORMAL ;
528- break ;
529- case SND_SOC_DAIFMT_IB_IF :
530- val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_INVERTED ;
531- break ;
532- default :
533- ret = - EINVAL ;
534- break ;
535- }
520+ regmap_update_bits (sai -> regmap , SAI_CKR , mask , val );
536521
537- if (ret == 0 ) {
538- regmap_update_bits (sai -> regmap , SAI_CKR , mask , val );
539- rockchip_sai_fmt_create (sai , fmt );
540- }
541-
542- if (clk_gates )
543- regmap_update_bits (sai -> regmap , SAI_XFER ,
544- SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK ,
545- clk_gates );
522+ mask = SAI_CKR_CKP_MASK | SAI_CKR_FSP_MASK ;
523+ switch (fmt & SND_SOC_DAIFMT_INV_MASK ) {
524+ case SND_SOC_DAIFMT_NB_NF :
525+ val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_NORMAL ;
526+ break ;
527+ case SND_SOC_DAIFMT_NB_IF :
528+ val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_INVERTED ;
529+ break ;
530+ case SND_SOC_DAIFMT_IB_NF :
531+ val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_NORMAL ;
532+ break ;
533+ case SND_SOC_DAIFMT_IB_IF :
534+ val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_INVERTED ;
535+ break ;
536+ default :
537+ ret = - EINVAL ;
538+ goto err_xfer_unlock ;
546539 }
547540
541+ regmap_update_bits (sai -> regmap , SAI_CKR , mask , val );
542+
543+ rockchip_sai_fmt_create (sai , fmt );
544+
545+ err_xfer_unlock :
546+ if (clk_gates )
547+ regmap_update_bits (sai -> regmap , SAI_XFER ,
548+ SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK ,
549+ clk_gates );
550+ spin_unlock_irqrestore (& sai -> xfer_lock , flags );
551+ err_pm_put :
548552 pm_runtime_put (dai -> dev );
549553
550554 return ret ;
@@ -560,6 +564,7 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream,
560564 unsigned int ch_per_lane , slot_width ;
561565 unsigned int val , fscr , reg ;
562566 unsigned int lanes , req_lanes ;
567+ unsigned long flags ;
563568 int ret = 0 ;
564569
565570 if (!rockchip_sai_stream_valid (substream , dai ))
@@ -586,8 +591,8 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream,
586591 dev_err (sai -> dev , "not enough lanes (%d) for requested number of %s channels (%d)\n" ,
587592 lanes , reg == SAI_TXCR ? "playback" : "capture" ,
588593 params_channels (params ));
589- pm_runtime_put ( sai -> dev ) ;
590- return - EINVAL ;
594+ ret = - EINVAL ;
595+ goto err_pm_put ;
591596 } else {
592597 lanes = req_lanes ;
593598 }
@@ -613,88 +618,84 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream,
613618 val = SAI_XCR_VDW (32 );
614619 break ;
615620 default :
616- pm_runtime_put ( sai -> dev ) ;
617- return - EINVAL ;
621+ ret = - EINVAL ;
622+ goto err_pm_put ;
618623 }
619624
620625 val |= SAI_XCR_CSR (lanes );
621626
622- scoped_guard (spinlock_irqsave , & sai -> xfer_lock ) {
627+ spin_lock_irqsave (& sai -> xfer_lock , flags );
628+
629+ regmap_update_bits (sai -> regmap , reg , SAI_XCR_VDW_MASK | SAI_XCR_CSR_MASK , val );
623630
624- regmap_update_bits (sai -> regmap , reg , SAI_XCR_VDW_MASK | SAI_XCR_CSR_MASK , val );
631+ if (!sai -> is_tdm )
632+ regmap_update_bits (sai -> regmap , reg , SAI_XCR_SBW_MASK ,
633+ SAI_XCR_SBW (params_physical_width (params )));
625634
626- if (!sai -> is_tdm )
627- regmap_update_bits (sai -> regmap , reg , SAI_XCR_SBW_MASK ,
628- SAI_XCR_SBW (params_physical_width (params )));
635+ regmap_read (sai -> regmap , reg , & val );
629636
630- regmap_read (sai -> regmap , reg , & val );
637+ slot_width = SAI_XCR_SBW_V (val );
638+ ch_per_lane = params_channels (params ) / lanes ;
631639
632- slot_width = SAI_XCR_SBW_V ( val );
633- ch_per_lane = params_channels ( params ) / lanes ;
640+ regmap_update_bits ( sai -> regmap , reg , SAI_XCR_SNB_MASK ,
641+ SAI_XCR_SNB ( ch_per_lane )) ;
634642
635- regmap_update_bits (sai -> regmap , reg , SAI_XCR_SNB_MASK ,
636- SAI_XCR_SNB (ch_per_lane ));
643+ fscr = SAI_FSCR_FW (sai -> fw_ratio * slot_width * ch_per_lane );
637644
638- fscr = SAI_FSCR_FW (sai -> fw_ratio * slot_width * ch_per_lane );
645+ switch (sai -> fpw ) {
646+ case FPW_ONE_BCLK_WIDTH :
647+ fscr |= SAI_FSCR_FPW (1 );
648+ break ;
649+ case FPW_ONE_SLOT_WIDTH :
650+ fscr |= SAI_FSCR_FPW (slot_width );
651+ break ;
652+ case FPW_HALF_FRAME_WIDTH :
653+ fscr |= SAI_FSCR_FPW (sai -> fw_ratio * slot_width * ch_per_lane / 2 );
654+ break ;
655+ default :
656+ dev_err (sai -> dev , "Invalid Frame Pulse Width %d\n" , sai -> fpw );
657+ ret = - EINVAL ;
658+ goto err_xfer_unlock ;
659+ }
639660
640- switch (sai -> fpw ) {
641- case FPW_ONE_BCLK_WIDTH :
642- fscr |= SAI_FSCR_FPW (1 );
643- break ;
644- case FPW_ONE_SLOT_WIDTH :
645- fscr |= SAI_FSCR_FPW (slot_width );
646- break ;
647- case FPW_HALF_FRAME_WIDTH :
648- fscr |= SAI_FSCR_FPW (sai -> fw_ratio * slot_width * ch_per_lane / 2 );
649- break ;
650- default :
651- dev_err (sai -> dev , "Invalid Frame Pulse Width %d\n" , sai -> fpw );
661+ regmap_update_bits (sai -> regmap , SAI_FSCR ,
662+ SAI_FSCR_FW_MASK | SAI_FSCR_FPW_MASK , fscr );
663+
664+ if (sai -> is_master_mode ) {
665+ bclk_rate = sai -> fw_ratio * slot_width * ch_per_lane * params_rate (params );
666+ ret = clk_set_rate (sai -> mclk , sai -> mclk_rate );
667+ if (ret ) {
668+ dev_err (sai -> dev , "Failed to set mclk to %u: %pe\n" ,
669+ sai -> mclk_rate , ERR_PTR (ret ));
670+ goto err_xfer_unlock ;
671+ }
672+
673+ mclk_rate = clk_get_rate (sai -> mclk );
674+ if (mclk_rate < bclk_rate ) {
675+ dev_err (sai -> dev , "Mismatch mclk: %u, at least %u\n" ,
676+ mclk_rate , bclk_rate );
652677 ret = - EINVAL ;
653- break ;
678+ goto err_xfer_unlock ;
654679 }
655680
656- if (ret == 0 ) {
657- regmap_update_bits (sai -> regmap , SAI_FSCR ,
658- SAI_FSCR_FW_MASK | SAI_FSCR_FPW_MASK , fscr );
659-
660- if (sai -> is_master_mode ) {
661- bclk_rate = sai -> fw_ratio * slot_width *
662- ch_per_lane * params_rate (params );
663- ret = clk_set_rate (sai -> mclk , sai -> mclk_rate );
664- if (ret )
665- dev_err (sai -> dev , "Failed to set mclk to %u: %pe\n" ,
666- sai -> mclk_rate , ERR_PTR (ret ));
667- else {
668- mclk_rate = clk_get_rate (sai -> mclk );
669- if (mclk_rate < bclk_rate ) {
670- dev_err (sai -> dev , "Mismatch mclk: %u, at least %u\n" ,
671- mclk_rate , bclk_rate );
672- ret = - EINVAL ;
673- } else {
674-
675- div_bclk = DIV_ROUND_CLOSEST (mclk_rate , bclk_rate );
676- mclk_req_rate = bclk_rate * div_bclk ;
677-
678- if (mclk_rate <
679- mclk_req_rate - CLK_SHIFT_RATE_HZ_MAX ||
680- mclk_rate >
681- mclk_req_rate + CLK_SHIFT_RATE_HZ_MAX ) {
682- dev_err (sai -> dev ,
683- "Mismatch mclk: %u, expected %u (+/- %dHz)\n" ,
684- mclk_rate , mclk_req_rate ,
685- CLK_SHIFT_RATE_HZ_MAX );
686- ret = - EINVAL ;
687- } else
688- regmap_update_bits (sai -> regmap ,
689- SAI_CKR ,
690- SAI_CKR_MDIV_MASK ,
691- SAI_CKR_MDIV (div_bclk ));
692- }
693- }
694- }
681+ div_bclk = DIV_ROUND_CLOSEST (mclk_rate , bclk_rate );
682+ mclk_req_rate = bclk_rate * div_bclk ;
683+
684+ if (mclk_rate < mclk_req_rate - CLK_SHIFT_RATE_HZ_MAX ||
685+ mclk_rate > mclk_req_rate + CLK_SHIFT_RATE_HZ_MAX ) {
686+ dev_err (sai -> dev , "Mismatch mclk: %u, expected %u (+/- %dHz)\n" ,
687+ mclk_rate , mclk_req_rate , CLK_SHIFT_RATE_HZ_MAX );
688+ ret = - EINVAL ;
689+ goto err_xfer_unlock ;
695690 }
691+
692+ regmap_update_bits (sai -> regmap , SAI_CKR , SAI_CKR_MDIV_MASK ,
693+ SAI_CKR_MDIV (div_bclk ));
696694 }
697695
696+ err_xfer_unlock :
697+ spin_unlock_irqrestore (& sai -> xfer_lock , flags );
698+ err_pm_put :
698699 pm_runtime_put (sai -> dev );
699700
700701 return ret ;
@@ -704,6 +705,7 @@ static int rockchip_sai_prepare(struct snd_pcm_substream *substream,
704705 struct snd_soc_dai * dai )
705706{
706707 struct rk_sai_dev * sai = snd_soc_dai_get_drvdata (dai );
708+ unsigned long flags ;
707709
708710 if (!rockchip_sai_stream_valid (substream , dai ))
709711 return 0 ;
@@ -724,12 +726,13 @@ static int rockchip_sai_prepare(struct snd_pcm_substream *substream,
724726 * udelay falls short.
725727 */
726728 udelay (20 );
727- scoped_guard (spinlock_irqsave , & sai -> xfer_lock )
728- regmap_update_bits (sai -> regmap , SAI_XFER ,
729- SAI_XFER_CLK_MASK |
730- SAI_XFER_FSS_MASK ,
731- SAI_XFER_CLK_EN |
732- SAI_XFER_FSS_EN );
729+ spin_lock_irqsave (& sai -> xfer_lock , flags );
730+ regmap_update_bits (sai -> regmap , SAI_XFER ,
731+ SAI_XFER_CLK_MASK |
732+ SAI_XFER_FSS_MASK ,
733+ SAI_XFER_CLK_EN |
734+ SAI_XFER_FSS_EN );
735+ spin_unlock_irqrestore (& sai -> xfer_lock , flags );
733736 }
734737
735738 rockchip_sai_fsync_lost_detect (sai , 1 );
@@ -912,6 +915,7 @@ static int rockchip_sai_set_tdm_slot(struct snd_soc_dai *dai,
912915 int slots , int slot_width )
913916{
914917 struct rk_sai_dev * sai = snd_soc_dai_get_drvdata (dai );
918+ unsigned long flags ;
915919 unsigned int clk_gates ;
916920 int sw = slot_width ;
917921
@@ -927,16 +931,16 @@ static int rockchip_sai_set_tdm_slot(struct snd_soc_dai *dai,
927931 return - EINVAL ;
928932
929933 pm_runtime_get_sync (dai -> dev );
930- scoped_guard ( spinlock_irqsave , & sai -> xfer_lock ) {
931- rockchip_sai_xfer_clk_stop_and_wait (sai , & clk_gates );
932- regmap_update_bits (sai -> regmap , SAI_TXCR , SAI_XCR_SBW_MASK ,
933- SAI_XCR_SBW (sw ));
934- regmap_update_bits (sai -> regmap , SAI_RXCR , SAI_XCR_SBW_MASK ,
935- SAI_XCR_SBW (sw ));
936- regmap_update_bits (sai -> regmap , SAI_XFER ,
937- SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK ,
938- clk_gates );
939- }
934+ spin_lock_irqsave ( & sai -> xfer_lock , flags );
935+ rockchip_sai_xfer_clk_stop_and_wait (sai , & clk_gates );
936+ regmap_update_bits (sai -> regmap , SAI_TXCR , SAI_XCR_SBW_MASK ,
937+ SAI_XCR_SBW (sw ));
938+ regmap_update_bits (sai -> regmap , SAI_RXCR , SAI_XCR_SBW_MASK ,
939+ SAI_XCR_SBW (sw ));
940+ regmap_update_bits (sai -> regmap , SAI_XFER ,
941+ SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK ,
942+ clk_gates );
943+ spin_unlock_irqrestore ( & sai -> xfer_lock , flags );
940944 pm_runtime_put (dai -> dev );
941945
942946 return 0 ;
0 commit comments