Skip to content

Instantly share code, notes, and snippets.

@pelwell
Last active October 13, 2015 08:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pelwell/4df57791157259758cf6 to your computer and use it in GitHub Desktop.
Save pelwell/4df57791157259758cf6 to your computer and use it in GitHub Desktop.
This diff is the result of replacing the downstream I2S driver with the @HiassofT's modified upstream I2S driver after a simple 2835->2708 textual substitution, because I find it makes it easier to understand the consequences of switching. As you can see, the two drivers are virtually identical.
diff --git a/sound/soc/bcm/bcm2708-i2s.c b/sound/soc/bcm/bcm2708-i2s.c
index ad9ca2c..1eeb131 100644
--- a/sound/soc/bcm/bcm2708-i2s.c
+++ b/sound/soc/bcm/bcm2708-i2s.c
@@ -31,8 +31,6 @@
* General Public License for more details.
*/
-#include "bcm2708-i2s.h"
-
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
@@ -40,9 +38,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/clk.h>
-#ifndef CONFIG_ARCH_BCM2835
-#include <mach/gpio.h>
-#endif
+#include <linux/of_address.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -51,8 +47,6 @@
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
-#include <asm/system_info.h>
-
/* Clock registers */
#define BCM2708_CLK_PCMCTL_REG 0x00
#define BCM2708_CLK_PCMDIV_REG 0x04
@@ -165,14 +159,6 @@ static const unsigned int bcm2708_clk_freq[BCM2708_CLK_SRC_HDMI+1] = {
#define BCM2708_I2S_INT_RXR BIT(1)
#define BCM2708_I2S_INT_TXW BIT(0)
-/* I2S DMA interface */
-#define BCM2708_I2S_FIFO_PHYSICAL_ADDR 0x7E203004
-#define BCM2708_DMA_DREQ_PCM_TX 2
-#define BCM2708_DMA_DREQ_PCM_RX 3
-
-/* I2S pin configuration */
-static int bcm2708_i2s_gpio=BCM2708_I2S_GPIO_AUTO;
-
/* General device struct */
struct bcm2708_i2s_dev {
struct device *dev;
@@ -184,12 +170,6 @@ struct bcm2708_i2s_dev {
struct regmap *clk_regmap;
};
-void bcm2708_i2s_set_gpio(int gpio) {
- bcm2708_i2s_gpio=gpio;
-}
-EXPORT_SYMBOL(bcm2708_i2s_set_gpio);
-
-
static void bcm2708_i2s_start_clock(struct bcm2708_i2s_dev *dev)
{
/* Start the clock if in master mode */
@@ -321,71 +301,6 @@ static int bcm2708_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai,
return 0;
}
-
-#ifdef CONFIG_ARCH_BCM2835
-static void bcm2708_i2s_setup_gpio(void) { }
-#else
-static int bcm2708_i2s_set_function(unsigned offset, int function)
-{
- #define GPIOFSEL(x) (0x00+(x)*4)
- void __iomem *gpio = __io_address(GPIO_BASE);
- unsigned alt = function <= 3 ? function + 4: function == 4 ? 3 : 2;
- unsigned gpiodir;
- unsigned gpio_bank = offset / 10;
- unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3;
-
- if (offset >= BCM2708_NR_GPIOS)
- return -EINVAL;
-
- gpiodir = readl(gpio + GPIOFSEL(gpio_bank));
- gpiodir &= ~(7 << gpio_field_offset);
- gpiodir |= alt << gpio_field_offset;
- writel(gpiodir, gpio + GPIOFSEL(gpio_bank));
- return 0;
-}
-
-static void bcm2708_i2s_setup_gpio(void)
-{
- /*
- * This is the common way to handle the GPIO pins for
- * the Raspberry Pi.
- * TODO Better way would be to handle
- * this in the device tree!
- */
- int pin,pinconfig,startpin,alt;
-
- /* SPI is on different GPIOs on different boards */
- /* for Raspberry Pi B+, this is pin GPIO18-21, for original on 28-31 */
- if (bcm2708_i2s_gpio==BCM2708_I2S_GPIO_AUTO) {
- if ((system_rev & 0xffffff) >= 0x10) {
- /* Model B+ */
- pinconfig=BCM2708_I2S_GPIO_PIN18;
- } else {
- /* original */
- pinconfig=BCM2708_I2S_GPIO_PIN28;
- }
- } else {
- pinconfig=bcm2708_i2s_gpio;
- }
-
- if (pinconfig==BCM2708_I2S_GPIO_PIN18) {
- startpin=18;
- alt=BCM2708_I2S_GPIO_PIN18_ALT;
- } else if (pinconfig==BCM2708_I2S_GPIO_PIN28) {
- startpin=28;
- alt=BCM2708_I2S_GPIO_PIN28_ALT;
- } else {
- printk(KERN_INFO "Can't configure I2S GPIOs, unknown pin mode for I2S: %i\n",pinconfig);
- return;
- }
-
- /* configure I2S pins to correct ALT mode */
- for (pin = startpin; pin <= startpin+3; pin++) {
- bcm2708_i2s_set_function(pin, alt);
- }
-}
-#endif
-
static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -415,9 +330,6 @@ static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream,
if (csreg & (BCM2708_I2S_TXON | BCM2708_I2S_RXON))
return 0;
- if (!dev->dev->of_node)
- bcm2708_i2s_setup_gpio();
-
/*
* Adjust the data length according to the format.
* We prefill the half frame length with an integer
@@ -792,8 +704,9 @@ static int bcm2708_i2s_dai_probe(struct snd_soc_dai *dai)
{
struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
- dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
- dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE];
+ snd_soc_dai_init_dma_data(dai,
+ &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK],
+ &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]);
return 0;
}
@@ -899,7 +812,6 @@ static const struct snd_dmaengine_pcm_config bcm2708_dmaengine_pcm_config = {
.prealloc_buffer_size = 256 * PAGE_SIZE,
};
-
static int bcm2708_i2s_probe(struct platform_device *pdev)
{
struct bcm2708_i2s_dev *dev;
@@ -907,6 +819,15 @@ static int bcm2708_i2s_probe(struct platform_device *pdev)
int ret;
struct regmap *regmap[2];
struct resource *mem[2];
+ const __be32 *addr;
+ dma_addr_t dma_reg_base;
+
+ addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL);
+ if (!addr) {
+ dev_err(&pdev->dev, "could not get DMA-register address\n");
+ return -ENODEV;
+ }
+ dma_reg_base = be32_to_cpup(addr);
if (of_property_read_bool(pdev->dev.of_node, "brcm,enable-mmap"))
bcm2708_pcm_hardware.info |=
@@ -924,32 +845,24 @@ static int bcm2708_i2s_probe(struct platform_device *pdev)
regmap[i] = devm_regmap_init_mmio(&pdev->dev, base,
&bcm2708_regmap_config[i]);
- if (IS_ERR(regmap[i])) {
- dev_err(&pdev->dev, "I2S probe: regmap init failed\n");
+ if (IS_ERR(regmap[i]))
return PTR_ERR(regmap[i]);
- }
}
dev = devm_kzalloc(&pdev->dev, sizeof(*dev),
GFP_KERNEL);
- if (IS_ERR(dev))
- return PTR_ERR(dev);
+ if (!dev)
+ return -ENOMEM;
dev->i2s_regmap = regmap[0];
dev->clk_regmap = regmap[1];
/* Set the DMA address */
dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr =
- (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR;
+ dma_reg_base + BCM2708_I2S_FIFO_A_REG;
dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr =
- (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR;
-
- /* Set the DREQ */
- dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].slave_id =
- BCM2708_DMA_DREQ_PCM_TX;
- dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].slave_id =
- BCM2708_DMA_DREQ_PCM_RX;
+ dma_reg_base + BCM2708_I2S_FIFO_A_REG;
/* Set the bus width */
dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width =
@@ -968,34 +881,24 @@ static int bcm2708_i2s_probe(struct platform_device *pdev)
dev->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, dev);
- ret = snd_soc_register_component(&pdev->dev,
+ ret = devm_snd_soc_register_component(&pdev->dev,
&bcm2708_i2s_component, &bcm2708_i2s_dai, 1);
-
if (ret) {
dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
- ret = -ENOMEM;
return ret;
}
- ret = snd_dmaengine_pcm_register(&pdev->dev,
- &bcm2708_dmaengine_pcm_config,
- SND_DMAENGINE_PCM_FLAG_COMPAT);
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
+ &bcm2708_dmaengine_pcm_config,
+ SND_DMAENGINE_PCM_FLAG_COMPAT);
if (ret) {
dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
- snd_soc_unregister_component(&pdev->dev);
return ret;
}
return 0;
}
-static int bcm2708_i2s_remove(struct platform_device *pdev)
-{
- snd_dmaengine_pcm_unregister(&pdev->dev);
- snd_soc_unregister_component(&pdev->dev);
- return 0;
-}
-
static const struct of_device_id bcm2708_i2s_of_match[] = {
{ .compatible = "brcm,bcm2708-i2s", },
{},
@@ -1004,10 +907,8 @@ MODULE_DEVICE_TABLE(of, bcm2708_i2s_of_match);
static struct platform_driver bcm2708_i2s_driver = {
.probe = bcm2708_i2s_probe,
- .remove = bcm2708_i2s_remove,
.driver = {
.name = "bcm2708-i2s",
- .owner = THIS_MODULE,
.of_match_table = bcm2708_i2s_of_match,
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment