38
38
#include <linux/delay.h>
39
39
#include <linux/io.h>
40
40
#include <linux/clk.h>
41
+ #include <linux/of_address.h>
41
42
42
43
#include <sound/core.h>
43
44
#include <sound/pcm.h>
@@ -158,10 +159,6 @@ static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = {
158
159
#define BCM2835_I2S_INT_RXR BIT(1)
159
160
#define BCM2835_I2S_INT_TXW BIT(0)
160
161
161
- /* I2S DMA interface */
162
- /* FIXME: Needs IOMMU support */
163
- #define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000)
164
-
165
162
/* General device struct */
166
163
struct bcm2835_i2s_dev {
167
164
struct device * dev ;
@@ -343,11 +340,15 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
343
340
switch (params_format (params )) {
344
341
case SNDRV_PCM_FORMAT_S16_LE :
345
342
data_length = 16 ;
346
- bclk_ratio = 40 ;
343
+ bclk_ratio = 50 ;
344
+ break ;
345
+ case SNDRV_PCM_FORMAT_S24_LE :
346
+ data_length = 24 ;
347
+ bclk_ratio = 50 ;
347
348
break ;
348
349
case SNDRV_PCM_FORMAT_S32_LE :
349
350
data_length = 32 ;
350
- bclk_ratio = 80 ;
351
+ bclk_ratio = 100 ;
351
352
break ;
352
353
default :
353
354
return - EINVAL ;
@@ -410,20 +411,30 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
410
411
divf = dividend & BCM2835_CLK_DIVF_MASK ;
411
412
}
412
413
413
- /* Set clock divider */
414
- regmap_write (dev -> clk_regmap , BCM2835_CLK_PCMDIV_REG , BCM2835_CLK_PASSWD
415
- | BCM2835_CLK_DIVI (divi )
416
- | BCM2835_CLK_DIVF (divf ));
417
-
418
- /* Setup clock, but don't start it yet */
419
- regmap_write (dev -> clk_regmap , BCM2835_CLK_PCMCTL_REG , BCM2835_CLK_PASSWD
420
- | BCM2835_CLK_MASH (mash )
421
- | BCM2835_CLK_SRC (clk_src ));
414
+ /* Clock should only be set up here if CPU is clock master */
415
+ switch (dev -> fmt & SND_SOC_DAIFMT_MASTER_MASK ) {
416
+ case SND_SOC_DAIFMT_CBS_CFS :
417
+ case SND_SOC_DAIFMT_CBS_CFM :
418
+ /* Set clock divider */
419
+ regmap_write (dev -> clk_regmap , BCM2835_CLK_PCMDIV_REG ,
420
+ BCM2835_CLK_PASSWD
421
+ | BCM2835_CLK_DIVI (divi )
422
+ | BCM2835_CLK_DIVF (divf ));
423
+
424
+ /* Setup clock, but don't start it yet */
425
+ regmap_write (dev -> clk_regmap , BCM2835_CLK_PCMCTL_REG ,
426
+ BCM2835_CLK_PASSWD
427
+ | BCM2835_CLK_MASH (mash )
428
+ | BCM2835_CLK_SRC (clk_src ));
429
+ break ;
430
+ default :
431
+ break ;
432
+ }
422
433
423
434
/* Setup the frame format */
424
435
format = BCM2835_I2S_CHEN ;
425
436
426
- if (data_length > 24 )
437
+ if (data_length >= 24 )
427
438
format |= BCM2835_I2S_CHWEX ;
428
439
429
440
format |= BCM2835_I2S_CHWID ((data_length - 8 )& 0xf );
@@ -714,13 +725,15 @@ static struct snd_soc_dai_driver bcm2835_i2s_dai = {
714
725
.channels_max = 2 ,
715
726
.rates = SNDRV_PCM_RATE_8000_192000 ,
716
727
.formats = SNDRV_PCM_FMTBIT_S16_LE
728
+ | SNDRV_PCM_FMTBIT_S24_LE
717
729
| SNDRV_PCM_FMTBIT_S32_LE
718
730
},
719
731
.capture = {
720
732
.channels_min = 2 ,
721
733
.channels_max = 2 ,
722
734
.rates = SNDRV_PCM_RATE_8000_192000 ,
723
735
.formats = SNDRV_PCM_FMTBIT_S16_LE
736
+ | SNDRV_PCM_FMTBIT_S24_LE
724
737
| SNDRV_PCM_FMTBIT_S32_LE
725
738
},
726
739
.ops = & bcm2835_i2s_dai_ops ,
@@ -769,6 +782,7 @@ static const struct regmap_config bcm2835_regmap_config[] = {
769
782
.precious_reg = bcm2835_i2s_precious_reg ,
770
783
.volatile_reg = bcm2835_i2s_volatile_reg ,
771
784
.cache_type = REGCACHE_RBTREE ,
785
+ .name = "i2s" ,
772
786
},
773
787
{
774
788
.reg_bits = 32 ,
@@ -777,20 +791,54 @@ static const struct regmap_config bcm2835_regmap_config[] = {
777
791
.max_register = BCM2835_CLK_PCMDIV_REG ,
778
792
.volatile_reg = bcm2835_clk_volatile_reg ,
779
793
.cache_type = REGCACHE_RBTREE ,
794
+ .name = "clk" ,
780
795
},
781
796
};
782
797
783
798
static const struct snd_soc_component_driver bcm2835_i2s_component = {
784
799
.name = "bcm2835-i2s-comp" ,
785
800
};
786
801
802
+ static struct snd_pcm_hardware bcm2835_pcm_hardware = {
803
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
804
+ SNDRV_PCM_INFO_JOINT_DUPLEX ,
805
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
806
+ SNDRV_PCM_FMTBIT_S24_LE |
807
+ SNDRV_PCM_FMTBIT_S32_LE ,
808
+ .period_bytes_min = 32 ,
809
+ .period_bytes_max = 64 * PAGE_SIZE ,
810
+ .periods_min = 2 ,
811
+ .periods_max = 255 ,
812
+ .buffer_bytes_max = 128 * PAGE_SIZE ,
813
+ };
814
+
815
+ static const struct snd_dmaengine_pcm_config bcm2835_dmaengine_pcm_config = {
816
+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config ,
817
+ .pcm_hardware = & bcm2835_pcm_hardware ,
818
+ .prealloc_buffer_size = 256 * PAGE_SIZE ,
819
+ };
820
+
787
821
static int bcm2835_i2s_probe (struct platform_device * pdev )
788
822
{
789
823
struct bcm2835_i2s_dev * dev ;
790
824
int i ;
791
825
int ret ;
792
826
struct regmap * regmap [2 ];
793
827
struct resource * mem [2 ];
828
+ const __be32 * addr ;
829
+ dma_addr_t dma_reg_base ;
830
+
831
+ addr = of_get_address (pdev -> dev .of_node , 0 , NULL , NULL );
832
+ if (!addr ) {
833
+ dev_err (& pdev -> dev , "could not get DMA-register address\n" );
834
+ return - ENODEV ;
835
+ }
836
+ dma_reg_base = be32_to_cpup (addr );
837
+
838
+ if (of_property_read_bool (pdev -> dev .of_node , "brcm,enable-mmap" ))
839
+ bcm2835_pcm_hardware .info |=
840
+ SNDRV_PCM_INFO_MMAP |
841
+ SNDRV_PCM_INFO_MMAP_VALID ;
794
842
795
843
/* Request both ioareas */
796
844
for (i = 0 ; i <= 1 ; i ++ ) {
@@ -817,12 +865,10 @@ static int bcm2835_i2s_probe(struct platform_device *pdev)
817
865
818
866
/* Set the DMA address */
819
867
dev -> dma_data [SNDRV_PCM_STREAM_PLAYBACK ].addr =
820
- (dma_addr_t )mem [0 ]-> start + BCM2835_I2S_FIFO_A_REG
821
- + BCM2835_VCMMU_SHIFT ;
868
+ dma_reg_base + BCM2835_I2S_FIFO_A_REG ;
822
869
823
870
dev -> dma_data [SNDRV_PCM_STREAM_CAPTURE ].addr =
824
- (dma_addr_t )mem [0 ]-> start + BCM2835_I2S_FIFO_A_REG
825
- + BCM2835_VCMMU_SHIFT ;
871
+ dma_reg_base + BCM2835_I2S_FIFO_A_REG ;
826
872
827
873
/* Set the bus width */
828
874
dev -> dma_data [SNDRV_PCM_STREAM_PLAYBACK ].addr_width =
@@ -848,7 +894,9 @@ static int bcm2835_i2s_probe(struct platform_device *pdev)
848
894
return ret ;
849
895
}
850
896
851
- ret = devm_snd_dmaengine_pcm_register (& pdev -> dev , NULL , 0 );
897
+ ret = devm_snd_dmaengine_pcm_register (& pdev -> dev ,
898
+ & bcm2835_dmaengine_pcm_config ,
899
+ SND_DMAENGINE_PCM_FLAG_COMPAT );
852
900
if (ret ) {
853
901
dev_err (& pdev -> dev , "Could not register PCM: %d\n" , ret );
854
902
return ret ;
0 commit comments