Skip to content

Commit 873e9f3

Browse files
committed
Merge pull request #1163 from HiassofT/i2s-bcm2835
I2S: switch to bcm2835
2 parents 548b08c + d6c9e7f commit 873e9f3

File tree

5 files changed

+75
-26
lines changed

5 files changed

+75
-26
lines changed

arch/arm/boot/dts/bcm2708_common.dtsi

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,11 @@
127127
};
128128

129129
i2s: i2s@7e203000 {
130-
compatible = "brcm,bcm2708-i2s";
130+
compatible = "brcm,bcm2835-i2s";
131131
reg = <0x7e203000 0x24>,
132132
<0x7e101098 0x08>;
133133

134-
//dmas = <&dma 2>,
135-
// <&dma 3>;
134+
dmas = <&dma 2>, <&dma 3>;
136135
dma-names = "tx", "rx";
137136
status = "disabled";
138137
};

arch/arm/configs/bcm2709_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ CONFIG_SND_USB_CAIAQ=m
835835
CONFIG_SND_USB_CAIAQ_INPUT=y
836836
CONFIG_SND_USB_6FIRE=m
837837
CONFIG_SND_SOC=m
838+
CONFIG_SND_BCM2835_SOC_I2S=m
838839
CONFIG_SND_BCM2708_SOC_I2S=m
839840
CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
840841
CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m

arch/arm/configs/bcmrpi_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@ CONFIG_SND_USB_CAIAQ=m
828828
CONFIG_SND_USB_CAIAQ_INPUT=y
829829
CONFIG_SND_USB_6FIRE=m
830830
CONFIG_SND_SOC=m
831+
CONFIG_SND_BCM2835_SOC_I2S=m
831832
CONFIG_SND_BCM2708_SOC_I2S=m
832833
CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
833834
CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m

sound/soc/bcm/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
config SND_BCM2835_SOC_I2S
22
tristate "SoC Audio support for the Broadcom BCM2835 I2S module"
3-
depends on ARCH_BCM2835 || COMPILE_TEST
3+
depends on ARCH_BCM2835 || MACH_BCM2708 || MACH_BCM2709 || COMPILE_TEST
44
select SND_SOC_GENERIC_DMAENGINE_PCM
55
select REGMAP_MMIO
66
help
@@ -70,7 +70,7 @@ config SND_BCM2708_SOC_IQAUDIO_DAC
7070

7171
config SND_BCM2708_SOC_RASPIDAC3
7272
tristate "Support for RaspiDAC Rev.3x"
73-
depends on SND_BCM2708_SOC_I2S
73+
depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
7474
select SND_SOC_PCM512x_I2C
7575
select SND_SOC_TPA6130A2
7676
help

sound/soc/bcm/bcm2835-i2s.c

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <linux/delay.h>
3939
#include <linux/io.h>
4040
#include <linux/clk.h>
41+
#include <linux/of_address.h>
4142

4243
#include <sound/core.h>
4344
#include <sound/pcm.h>
@@ -158,10 +159,6 @@ static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = {
158159
#define BCM2835_I2S_INT_RXR BIT(1)
159160
#define BCM2835_I2S_INT_TXW BIT(0)
160161

161-
/* I2S DMA interface */
162-
/* FIXME: Needs IOMMU support */
163-
#define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000)
164-
165162
/* General device struct */
166163
struct bcm2835_i2s_dev {
167164
struct device *dev;
@@ -343,11 +340,15 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
343340
switch (params_format(params)) {
344341
case SNDRV_PCM_FORMAT_S16_LE:
345342
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;
347348
break;
348349
case SNDRV_PCM_FORMAT_S32_LE:
349350
data_length = 32;
350-
bclk_ratio = 80;
351+
bclk_ratio = 100;
351352
break;
352353
default:
353354
return -EINVAL;
@@ -410,20 +411,30 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
410411
divf = dividend & BCM2835_CLK_DIVF_MASK;
411412
}
412413

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+
}
422433

423434
/* Setup the frame format */
424435
format = BCM2835_I2S_CHEN;
425436

426-
if (data_length > 24)
437+
if (data_length >= 24)
427438
format |= BCM2835_I2S_CHWEX;
428439

429440
format |= BCM2835_I2S_CHWID((data_length-8)&0xf);
@@ -714,13 +725,15 @@ static struct snd_soc_dai_driver bcm2835_i2s_dai = {
714725
.channels_max = 2,
715726
.rates = SNDRV_PCM_RATE_8000_192000,
716727
.formats = SNDRV_PCM_FMTBIT_S16_LE
728+
| SNDRV_PCM_FMTBIT_S24_LE
717729
| SNDRV_PCM_FMTBIT_S32_LE
718730
},
719731
.capture = {
720732
.channels_min = 2,
721733
.channels_max = 2,
722734
.rates = SNDRV_PCM_RATE_8000_192000,
723735
.formats = SNDRV_PCM_FMTBIT_S16_LE
736+
| SNDRV_PCM_FMTBIT_S24_LE
724737
| SNDRV_PCM_FMTBIT_S32_LE
725738
},
726739
.ops = &bcm2835_i2s_dai_ops,
@@ -769,6 +782,7 @@ static const struct regmap_config bcm2835_regmap_config[] = {
769782
.precious_reg = bcm2835_i2s_precious_reg,
770783
.volatile_reg = bcm2835_i2s_volatile_reg,
771784
.cache_type = REGCACHE_RBTREE,
785+
.name = "i2s",
772786
},
773787
{
774788
.reg_bits = 32,
@@ -777,20 +791,54 @@ static const struct regmap_config bcm2835_regmap_config[] = {
777791
.max_register = BCM2835_CLK_PCMDIV_REG,
778792
.volatile_reg = bcm2835_clk_volatile_reg,
779793
.cache_type = REGCACHE_RBTREE,
794+
.name = "clk",
780795
},
781796
};
782797

783798
static const struct snd_soc_component_driver bcm2835_i2s_component = {
784799
.name = "bcm2835-i2s-comp",
785800
};
786801

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+
787821
static int bcm2835_i2s_probe(struct platform_device *pdev)
788822
{
789823
struct bcm2835_i2s_dev *dev;
790824
int i;
791825
int ret;
792826
struct regmap *regmap[2];
793827
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;
794842

795843
/* Request both ioareas */
796844
for (i = 0; i <= 1; i++) {
@@ -817,12 +865,10 @@ static int bcm2835_i2s_probe(struct platform_device *pdev)
817865

818866
/* Set the DMA address */
819867
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;
822869

823870
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;
826872

827873
/* Set the bus width */
828874
dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width =
@@ -848,7 +894,9 @@ static int bcm2835_i2s_probe(struct platform_device *pdev)
848894
return ret;
849895
}
850896

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);
852900
if (ret) {
853901
dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
854902
return ret;

0 commit comments

Comments
 (0)