@@ -472,17 +472,22 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
472
472
{
473
473
struct i2s_dai * i2s = to_info (dai );
474
474
struct i2s_dai * other = get_other_dai (i2s );
475
- u32 mod = readl (i2s -> addr + I2SMOD );
476
475
const struct samsung_i2s_variant_regs * i2s_regs = i2s -> variant_regs ;
477
476
unsigned int cdcon_mask = 1 << i2s_regs -> cdclkcon_off ;
478
477
unsigned int rsrc_mask = 1 << i2s_regs -> rclksrc_off ;
478
+ u32 mod , mask , val = 0 ;
479
+
480
+ spin_lock (i2s -> lock );
481
+ mod = readl (i2s -> addr + I2SMOD );
482
+ spin_unlock (i2s -> lock );
479
483
480
484
switch (clk_id ) {
481
485
case SAMSUNG_I2S_OPCLK :
482
- mod &= ~ MOD_OPCLK_MASK ;
483
- mod | = dir ;
486
+ mask = MOD_OPCLK_MASK ;
487
+ val = dir ;
484
488
break ;
485
489
case SAMSUNG_I2S_CDCLK :
490
+ mask = 1 << i2s_regs -> cdclkcon_off ;
486
491
/* Shouldn't matter in GATING(CLOCK_IN) mode */
487
492
if (dir == SND_SOC_CLOCK_IN )
488
493
rfs = 0 ;
@@ -499,15 +504,15 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
499
504
}
500
505
501
506
if (dir == SND_SOC_CLOCK_IN )
502
- mod |= 1 << i2s_regs -> cdclkcon_off ;
503
- else
504
- mod &= ~(1 << i2s_regs -> cdclkcon_off );
507
+ val = 1 << i2s_regs -> cdclkcon_off ;
505
508
506
509
i2s -> rfs = rfs ;
507
510
break ;
508
511
509
512
case SAMSUNG_I2S_RCLKSRC_0 : /* clock corrsponding to IISMOD[10] := 0 */
510
513
case SAMSUNG_I2S_RCLKSRC_1 : /* clock corrsponding to IISMOD[10] := 1 */
514
+ mask = 1 << i2s_regs -> rclksrc_off ;
515
+
511
516
if ((i2s -> quirks & QUIRK_NO_MUXPSR )
512
517
|| (clk_id == SAMSUNG_I2S_RCLKSRC_0 ))
513
518
clk_id = 0 ;
@@ -557,18 +562,19 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
557
562
return 0 ;
558
563
}
559
564
560
- if (clk_id == 0 )
561
- mod &= ~(1 << i2s_regs -> rclksrc_off );
562
- else
563
- mod |= 1 << i2s_regs -> rclksrc_off ;
564
-
565
+ if (clk_id == 1 )
566
+ val = 1 << i2s_regs -> rclksrc_off ;
565
567
break ;
566
568
default :
567
569
dev_err (& i2s -> pdev -> dev , "We don't serve that!\n" );
568
570
return - EINVAL ;
569
571
}
570
572
573
+ spin_lock (i2s -> lock );
574
+ mod = readl (i2s -> addr + I2SMOD );
575
+ mod = (mod & ~mask ) | val ;
571
576
writel (mod , i2s -> addr + I2SMOD );
577
+ spin_unlock (i2s -> lock );
572
578
573
579
return 0 ;
574
580
}
@@ -577,9 +583,8 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
577
583
unsigned int fmt )
578
584
{
579
585
struct i2s_dai * i2s = to_info (dai );
580
- u32 mod = readl (i2s -> addr + I2SMOD );
581
586
int lrp_shift , sdf_shift , sdf_mask , lrp_rlow , mod_slave ;
582
- u32 tmp = 0 ;
587
+ u32 mod , tmp = 0 ;
583
588
584
589
lrp_shift = i2s -> variant_regs -> lrp_off ;
585
590
sdf_shift = i2s -> variant_regs -> sdf_off ;
@@ -639,12 +644,15 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
639
644
return - EINVAL ;
640
645
}
641
646
647
+ spin_lock (i2s -> lock );
648
+ mod = readl (i2s -> addr + I2SMOD );
642
649
/*
643
650
* Don't change the I2S mode if any controller is active on this
644
651
* channel.
645
652
*/
646
653
if (any_active (i2s ) &&
647
654
((mod & (sdf_mask | lrp_rlow | mod_slave )) != tmp )) {
655
+ spin_unlock (i2s -> lock );
648
656
dev_err (& i2s -> pdev -> dev ,
649
657
"%s:%d Other DAI busy\n" , __func__ , __LINE__ );
650
658
return - EAGAIN ;
@@ -653,6 +661,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
653
661
mod &= ~(sdf_mask | lrp_rlow | mod_slave );
654
662
mod |= tmp ;
655
663
writel (mod , i2s -> addr + I2SMOD );
664
+ spin_unlock (i2s -> lock );
656
665
657
666
return 0 ;
658
667
}
@@ -661,16 +670,16 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
661
670
struct snd_pcm_hw_params * params , struct snd_soc_dai * dai )
662
671
{
663
672
struct i2s_dai * i2s = to_info (dai );
664
- u32 mod = readl ( i2s -> addr + I2SMOD ) ;
673
+ u32 mod , mask = 0 , val = 0 ;
665
674
666
675
if (!is_secondary (i2s ))
667
- mod &= ~ (MOD_DC2_EN | MOD_DC1_EN );
676
+ mask |= (MOD_DC2_EN | MOD_DC1_EN );
668
677
669
678
switch (params_channels (params )) {
670
679
case 6 :
671
- mod |= MOD_DC2_EN ;
680
+ val |= MOD_DC2_EN ;
672
681
case 4 :
673
- mod |= MOD_DC1_EN ;
682
+ val |= MOD_DC1_EN ;
674
683
break ;
675
684
case 2 :
676
685
if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
@@ -692,44 +701,49 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
692
701
}
693
702
694
703
if (is_secondary (i2s ))
695
- mod &= ~ MOD_BLCS_MASK ;
704
+ mask |= MOD_BLCS_MASK ;
696
705
else
697
- mod &= ~ MOD_BLCP_MASK ;
706
+ mask |= MOD_BLCP_MASK ;
698
707
699
708
if (is_manager (i2s ))
700
- mod &= ~ MOD_BLC_MASK ;
709
+ mask |= MOD_BLC_MASK ;
701
710
702
711
switch (params_width (params )) {
703
712
case 8 :
704
713
if (is_secondary (i2s ))
705
- mod |= MOD_BLCS_8BIT ;
714
+ val |= MOD_BLCS_8BIT ;
706
715
else
707
- mod |= MOD_BLCP_8BIT ;
716
+ val |= MOD_BLCP_8BIT ;
708
717
if (is_manager (i2s ))
709
- mod |= MOD_BLC_8BIT ;
718
+ val |= MOD_BLC_8BIT ;
710
719
break ;
711
720
case 16 :
712
721
if (is_secondary (i2s ))
713
- mod |= MOD_BLCS_16BIT ;
722
+ val |= MOD_BLCS_16BIT ;
714
723
else
715
- mod |= MOD_BLCP_16BIT ;
724
+ val |= MOD_BLCP_16BIT ;
716
725
if (is_manager (i2s ))
717
- mod |= MOD_BLC_16BIT ;
726
+ val |= MOD_BLC_16BIT ;
718
727
break ;
719
728
case 24 :
720
729
if (is_secondary (i2s ))
721
- mod |= MOD_BLCS_24BIT ;
730
+ val |= MOD_BLCS_24BIT ;
722
731
else
723
- mod |= MOD_BLCP_24BIT ;
732
+ val |= MOD_BLCP_24BIT ;
724
733
if (is_manager (i2s ))
725
- mod |= MOD_BLC_24BIT ;
734
+ val |= MOD_BLC_24BIT ;
726
735
break ;
727
736
default :
728
737
dev_err (& i2s -> pdev -> dev , "Format(%d) not supported\n" ,
729
738
params_format (params ));
730
739
return - EINVAL ;
731
740
}
741
+
742
+ spin_lock (i2s -> lock );
743
+ mod = readl (i2s -> addr + I2SMOD );
744
+ mod = (mod & ~mask ) | val ;
732
745
writel (mod , i2s -> addr + I2SMOD );
746
+ spin_unlock (i2s -> lock );
733
747
734
748
samsung_asoc_init_dma_data (dai , & i2s -> dma_playback , & i2s -> dma_capture );
735
749
@@ -979,6 +993,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
979
993
{
980
994
struct i2s_dai * i2s = to_info (dai );
981
995
struct i2s_dai * other = get_other_dai (i2s );
996
+ unsigned long flags ;
982
997
983
998
if (is_secondary (i2s )) { /* If this is probe on the secondary DAI */
984
999
samsung_asoc_init_dma_data (dai , & other -> sec_dai -> dma_playback ,
@@ -999,11 +1014,14 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
999
1014
i2s -> rfs = 0 ;
1000
1015
i2s -> bfs = 0 ;
1001
1016
i2s -> rclk_srcrate = 0 ;
1017
+
1018
+ spin_lock_irqsave (i2s -> lock , flags );
1002
1019
i2s_txctrl (i2s , 0 );
1003
1020
i2s_rxctrl (i2s , 0 );
1004
1021
i2s_fifo (i2s , FIC_TXFLUSH );
1005
1022
i2s_fifo (other , FIC_TXFLUSH );
1006
1023
i2s_fifo (i2s , FIC_RXFLUSH );
1024
+ spin_unlock_irqrestore (i2s -> lock , flags );
1007
1025
1008
1026
/* Gate CDCLK by default */
1009
1027
if (!is_opened (other ))
@@ -1018,8 +1036,11 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
1018
1036
struct i2s_dai * i2s = snd_soc_dai_get_drvdata (dai );
1019
1037
1020
1038
if (!is_secondary (i2s )) {
1021
- if (i2s -> quirks & QUIRK_NEED_RSTCLR )
1039
+ if (i2s -> quirks & QUIRK_NEED_RSTCLR ) {
1040
+ spin_lock (i2s -> lock );
1022
1041
writel (0 , i2s -> addr + I2SCON );
1042
+ spin_unlock (i2s -> lock );
1043
+ }
1023
1044
}
1024
1045
1025
1046
return 0 ;
0 commit comments