aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/blackfin
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/blackfin')
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c13
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c166
-rw-r--r--sound/soc/blackfin/bf5xx-ad1836.c42
-rw-r--r--sound/soc/blackfin/bf5xx-ad193x.c56
-rw-r--r--sound/soc/blackfin/bf5xx-ad1980.c45
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c42
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c23
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c172
-rw-r--r--sound/soc/blackfin/bf5xx-sport.c159
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h16
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c42
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c23
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c110
13 files changed, 448 insertions, 461 deletions
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 5a2fd8abaef..98b44b316e7 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -243,6 +243,9 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@@ -314,6 +317,9 @@ static struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
{
+ struct snd_soc_pcm_runtime *rtd = pcm->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai);
struct snd_pcm_substream *substream = pcm->streams[stream].substream;
struct snd_dma_buffer *buf = &substream->dma_buffer;
size_t size = bf5xx_pcm_hardware.buffer_bytes_max
@@ -377,6 +383,9 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
struct snd_dma_buffer *buf;
int stream;
#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+ struct snd_soc_pcm_runtime *rtd = pcm->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai);
size_t size = bf5xx_pcm_hardware.buffer_bytes_max *
sizeof(struct ac97_frame) / 4;
#endif
@@ -405,8 +414,6 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
}
#endif
}
- if (sport_handle)
- sport_done(sport_handle);
}
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
@@ -458,7 +465,7 @@ static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
static struct platform_driver bf5xx_pcm_driver = {
.driver = {
- .name = "bf5xx-pcm-audio",
+ .name = "bfin-ac97-pcm-audio",
.owner = THIS_MODULE,
},
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index ffbac26b9bc..6d216259088 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -41,48 +41,7 @@
* anomaly does not affect blackfin sound drivers.
*/
-static int *cmd_count;
-static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
-
-#define SPORT_REQ(x) \
- [x] = {P_SPORT##x##_TFS, P_SPORT##x##_DTPRI, P_SPORT##x##_TSCLK, \
- P_SPORT##x##_RFS, P_SPORT##x##_DRPRI, P_SPORT##x##_RSCLK, 0}
-static u16 sport_req[][7] = {
-#ifdef SPORT0_TCR1
- SPORT_REQ(0),
-#endif
-#ifdef SPORT1_TCR1
- SPORT_REQ(1),
-#endif
-#ifdef SPORT2_TCR1
- SPORT_REQ(2),
-#endif
-#ifdef SPORT3_TCR1
- SPORT_REQ(3),
-#endif
-};
-
-#define SPORT_PARAMS(x) \
- [x] = { \
- .dma_rx_chan = CH_SPORT##x##_RX, \
- .dma_tx_chan = CH_SPORT##x##_TX, \
- .err_irq = IRQ_SPORT##x##_ERROR, \
- .regs = (struct sport_register *)SPORT##x##_TCR1, \
- }
-static struct sport_param sport_params[4] = {
-#ifdef SPORT0_TCR1
- SPORT_PARAMS(0),
-#endif
-#ifdef SPORT1_TCR1
- SPORT_PARAMS(1),
-#endif
-#ifdef SPORT2_TCR1
- SPORT_PARAMS(2),
-#endif
-#ifdef SPORT3_TCR1
- SPORT_PARAMS(3),
-#endif
-};
+static struct sport_device *ac97_sport_handle;
void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src,
size_t count, unsigned int chan_mask)
@@ -140,7 +99,8 @@ static unsigned int sport_tx_curr_frag(struct sport_device *sport)
static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
{
- struct sport_device *sport = sport_handle;
+ struct sport_device *sport = ac97_sport_handle;
+ int *cmd_count = sport->private_data;
int nextfrag = sport_tx_curr_frag(sport);
struct ac97_frame *nextwrite;
@@ -161,6 +121,7 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
+ struct sport_device *sport_handle = ac97_sport_handle;
struct ac97_frame out_frame[2], in_frame[2];
pr_debug("%s enter 0x%x\n", __func__, reg);
@@ -185,6 +146,8 @@ static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97,
void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
unsigned short val)
{
+ struct sport_device *sport_handle = ac97_sport_handle;
+
pr_debug("%s enter 0x%x:0x%04x\n", __func__, reg, val);
if (sport_handle->tx_run) {
@@ -203,28 +166,19 @@ void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
static void bf5xx_ac97_warm_reset(struct snd_ac97 *ac97)
{
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF561) || \
- (defined(BF537_FAMILY) && (CONFIG_SND_BF5XX_SPORT_NUM == 1))
-
-#define CONCAT(a, b, c) a ## b ## c
-#define BFIN_SPORT_RFS(x) CONCAT(P_SPORT, x, _RFS)
-
- u16 per = BFIN_SPORT_RFS(CONFIG_SND_BF5XX_SPORT_NUM);
- u16 gpio = P_IDENT(BFIN_SPORT_RFS(CONFIG_SND_BF5XX_SPORT_NUM));
+ struct sport_device *sport_handle = ac97_sport_handle;
+ u16 gpio = P_IDENT(sport_handle->pin_req[3]);
pr_debug("%s enter\n", __func__);
- peripheral_free(per);
+ peripheral_free_list(sport_handle->pin_req);
gpio_request(gpio, "bf5xx-ac97");
gpio_direction_output(gpio, 1);
udelay(2);
gpio_set_value(gpio, 0);
udelay(1);
gpio_free(gpio);
- peripheral_request(per, "soc-audio");
-#else
- pr_info("%s: Not implemented\n", __func__);
-#endif
+ peripheral_request_list(sport_handle->pin_req, "soc-audio");
}
static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97)
@@ -306,18 +260,32 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
#define bf5xx_ac97_resume NULL
#endif
-static int bf5xx_ac97_probe(struct snd_soc_dai *dai)
+static struct snd_soc_dai_driver bfin_ac97_dai = {
+ .ac97_control = 1,
+ .suspend = bf5xx_ac97_suspend,
+ .resume = bf5xx_ac97_resume,
+ .playback = {
+ .stream_name = "AC97 Playback",
+ .channels_min = 2,
+#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
+ .channels_max = 6,
+#else
+ .channels_max = 2,
+#endif
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+ .capture = {
+ .stream_name = "AC97 Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+};
+
+static int __devinit asoc_bfin_ac97_probe(struct platform_device *pdev)
{
- int ret = 0;
- cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
- if (cmd_count == NULL)
- return -ENOMEM;
-
- if (peripheral_request_list(sport_req[sport_num], "soc-audio")) {
- pr_err("Requesting Peripherals failed\n");
- ret = -EFAULT;
- goto peripheral_err;
- }
+ struct sport_device *sport_handle;
+ int ret;
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
/* Request PB3 as reset pin */
@@ -329,12 +297,14 @@ static int bf5xx_ac97_probe(struct snd_soc_dai *dai)
}
gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1);
#endif
- sport_handle = sport_init(&sport_params[sport_num], 2, \
- sizeof(struct ac97_frame), NULL);
+
+ sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame),
+ PAGE_SIZE);
if (!sport_handle) {
ret = -ENODEV;
goto sport_err;
}
+
/*SPORT works in TDM mode to simulate AC97 transfers*/
#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1);
@@ -361,67 +331,37 @@ static int bf5xx_ac97_probe(struct snd_soc_dai *dai)
goto sport_config_err;
}
+ ret = snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai);
+ if (ret) {
+ pr_err("Failed to register DAI: %d\n", ret);
+ goto sport_config_err;
+ }
+
+ ac97_sport_handle = sport_handle;
+
return 0;
sport_config_err:
- kfree(sport_handle);
+ sport_done(sport_handle);
sport_err:
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
gpio_err:
#endif
- peripheral_free_list(sport_req[sport_num]);
-peripheral_err:
- free_page((unsigned long)cmd_count);
- cmd_count = NULL;
return ret;
}
-static int bf5xx_ac97_remove(struct snd_soc_dai *dai)
+static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev)
{
- free_page((unsigned long)cmd_count);
- cmd_count = NULL;
- peripheral_free_list(sport_req[sport_num]);
+ struct sport_device *sport_handle = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_dai(&pdev->dev);
+ sport_done(sport_handle);
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
#endif
- return 0;
-}
-
-struct snd_soc_dai_driver bfin_ac97_dai = {
- .ac97_control = 1,
- .probe = bf5xx_ac97_probe,
- .remove = bf5xx_ac97_remove,
- .suspend = bf5xx_ac97_suspend,
- .resume = bf5xx_ac97_resume,
- .playback = {
- .stream_name = "AC97 Playback",
- .channels_min = 2,
-#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
- .channels_max = 6,
-#else
- .channels_max = 2,
-#endif
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE, },
- .capture = {
- .stream_name = "AC97 Capture",
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE, },
-};
-EXPORT_SYMBOL_GPL(bfin_ac97_dai);
-
-static __devinit int asoc_bfin_ac97_probe(struct platform_device *pdev)
-{
- return snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai);
-}
-static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_dai(&pdev->dev);
return 0;
}
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
index 83012da9dfc..ea4951cf552 100644
--- a/sound/soc/blackfin/bf5xx-ad1836.c
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -29,22 +29,12 @@
#include <asm/portmux.h>
#include "../codecs/ad1836.h"
-#include "bf5xx-sport.h"
#include "bf5xx-tdm-pcm.h"
#include "bf5xx-tdm.h"
static struct snd_soc_card bf5xx_ad1836;
-static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-
- snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
- return 0;
-}
-
static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -75,23 +65,33 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
}
static struct snd_soc_ops bf5xx_ad1836_ops = {
- .startup = bf5xx_ad1836_startup,
.hw_params = bf5xx_ad1836_hw_params,
};
-static struct snd_soc_dai_link bf5xx_ad1836_dai = {
- .name = "ad1836",
- .stream_name = "AD1836",
- .cpu_dai_name = "bf5xx-tdm",
- .codec_dai_name = "ad1836-hifi",
- .platform_name = "bf5xx-tdm-pcm-audio",
- .codec_name = "ad1836-codec.0",
- .ops = &bf5xx_ad1836_ops,
+static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
+ {
+ .name = "ad1836",
+ .stream_name = "AD1836",
+ .cpu_dai_name = "bfin-tdm.0",
+ .codec_dai_name = "ad1836-hifi",
+ .platform_name = "bfin-tdm-pcm-audio",
+ .codec_name = "ad1836.0",
+ .ops = &bf5xx_ad1836_ops,
+ },
+ {
+ .name = "ad1836",
+ .stream_name = "AD1836",
+ .cpu_dai_name = "bfin-tdm.1",
+ .codec_dai_name = "ad1836-hifi",
+ .platform_name = "bfin-tdm-pcm-audio",
+ .codec_name = "ad1836.0",
+ .ops = &bf5xx_ad1836_ops,
+ },
};
static struct snd_soc_card bf5xx_ad1836 = {
- .name = "bf5xx_ad1836",
- .dai_link = &bf5xx_ad1836_dai,
+ .name = "bfin-ad1836",
+ .dai_link = &bf5xx_ad1836_dai[CONFIG_SND_BF5XX_SPORT_NUM],
.num_links = 1,
};
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c
index d3ccb926b5e..d6651c033cb 100644
--- a/sound/soc/blackfin/bf5xx-ad193x.c
+++ b/sound/soc/blackfin/bf5xx-ad193x.c
@@ -38,30 +38,28 @@
#include <asm/portmux.h>
#include "../codecs/ad193x.h"
-#include "bf5xx-sport.h"
#include "bf5xx-tdm-pcm.h"
#include "bf5xx-tdm.h"
static struct snd_soc_card bf5xx_ad193x;
-static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-
- snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
- return 0;
-}
-
static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ unsigned int clk = 0;
unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7};
int ret = 0;
+
+ switch (params_rate(params)) {
+ case 48000:
+ clk = 12288000;
+ break;
+ }
+
/* set cpu DAI configuration */
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
@@ -74,6 +72,12 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
+ /* set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
/* set codec DAI slots, 8 channels, all channels are enabled */
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 0xFF, 8, 32);
if (ret < 0)
@@ -89,23 +93,33 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
}
static struct snd_soc_ops bf5xx_ad193x_ops = {
- .startup = bf5xx_ad193x_startup,
.hw_params = bf5xx_ad193x_hw_params,
};
-static struct snd_soc_dai_link bf5xx_ad193x_dai = {
- .name = "ad193x",
- .stream_name = "AD193X",
- .cpu_dai_name = "bf5xx-tdm",
- .codec_dai_name ="ad193x-hifi",
- .platform_name = "bf5xx-tdm-pcm-audio",
- .codec_name = "ad193x-codec.5",
- .ops = &bf5xx_ad193x_ops,
+static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
+ {
+ .name = "ad193x",
+ .stream_name = "AD193X",
+ .cpu_dai_name = "bfin-tdm.0",
+ .codec_dai_name ="ad193x-hifi",
+ .platform_name = "bfin-tdm-pcm-audio",
+ .codec_name = "ad193x.5",
+ .ops = &bf5xx_ad193x_ops,
+ },
+ {
+ .name = "ad193x",
+ .stream_name = "AD193X",
+ .cpu_dai_name = "bfin-tdm.1",
+ .codec_dai_name ="ad193x-hifi",
+ .platform_name = "bfin-tdm-pcm-audio",
+ .codec_name = "ad193x.5",
+ .ops = &bf5xx_ad193x_ops,
+ },
};
static struct snd_soc_card bf5xx_ad193x = {
- .name = "bf5xx_ad193x",
- .dai_link = &bf5xx_ad193x_dai,
+ .name = "bfin-ad193x",
+ .dai_link = &bf5xx_ad193x_dai[CONFIG_SND_BF5XX_SPORT_NUM],
.num_links = 1,
};
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c
index d57c9c9c988..06a84b211b5 100644
--- a/sound/soc/blackfin/bf5xx-ad1980.c
+++ b/sound/soc/blackfin/bf5xx-ad1980.c
@@ -47,39 +47,34 @@
#include <asm/portmux.h>
#include "../codecs/ad1980.h"
-#include "bf5xx-sport.h"
+
#include "bf5xx-ac97-pcm.h"
#include "bf5xx-ac97.h"
static struct snd_soc_card bf5xx_board;
-static int bf5xx_board_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-
- pr_debug("%s enter\n", __func__);
- snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
- return 0;
-}
-
-static struct snd_soc_ops bf5xx_board_ops = {
- .startup = bf5xx_board_startup,
-};
-
-static struct snd_soc_dai_link bf5xx_board_dai = {
- .name = "AC97",
- .stream_name = "AC97 HiFi",
- .cpu_dai_name = "bfin-ac97",
- .codec_dai_name = "ad1980-hifi",
- .platform_name = "bfin-pcm-audio",
- .codec_name = "ad1980-codec",
- .ops = &bf5xx_board_ops,
+static struct snd_soc_dai_link bf5xx_board_dai[] = {
+ {
+ .name = "AC97",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai_name = "bfin-ac97.0",
+ .codec_dai_name = "ad1980-hifi",
+ .platform_name = "bfin-ac97-pcm-audio",
+ .codec_name = "ad1980",
+ },
+ {
+ .name = "AC97",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai_name = "bfin-ac97.1",
+ .codec_dai_name = "ad1980-hifi",
+ .platform_name = "bfin-ac97-pcm-audio",
+ .codec_name = "ad1980",
+ },
};
static struct snd_soc_card bf5xx_board = {
- .name = "bf5xx-board",
- .dai_link = &bf5xx_board_dai,
+ .name = "bfin-ad1980",
+ .dai_link = &bf5xx_board_dai[CONFIG_SND_BF5XX_SPORT_NUM],
.num_links = 1,
};
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 732fb8bad07..732a247f252 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -145,16 +145,6 @@ static int bf5xx_probe(struct platform_device *pdev)
return 0;
}
-static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-
- pr_debug("%s enter\n", __func__);
- snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
- return 0;
-}
-
static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -176,24 +166,34 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
static struct snd_soc_ops bf5xx_ad73311_ops = {
- .startup = bf5xx_ad73311_startup,
.hw_params = bf5xx_ad73311_hw_params,
};
-static struct snd_soc_dai_link bf5xx_ad73311_dai = {
- .name = "ad73311",
- .stream_name = "AD73311",
- .cpu_dai_name = "bf5xx-i2s",
- .codec_dai_name = "ad73311-hifi",
- .platform_name = "bfin-pcm-audio",
- .codec_name = "ad73311-codec",
- .ops = &bf5xx_ad73311_ops,
+static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
+ {
+ .name = "ad73311",
+ .stream_name = "AD73311",
+ .cpu_dai_name = "bfin-i2s.0",
+ .codec_dai_name = "ad73311-hifi",
+ .platform_name = "bfin-i2s-pcm-audio",
+ .codec_name = "ad73311",
+ .ops = &bf5xx_ad73311_ops,
+ },
+ {
+ .name = "ad73311",
+ .stream_name = "AD73311",
+ .cpu_dai_name = "bfin-i2s.1",
+ .codec_dai_name = "ad73311-hifi",
+ .platform_name = "bfin-i2s-pcm-audio",
+ .codec_name = "ad73311",
+ .ops = &bf5xx_ad73311_ops,
+ },
};
static struct snd_soc_card bf5xx_ad73311 = {
- .name = "bf5xx_ad73311",
+ .name = "bfin-ad73311",
.probe = bf5xx_probe,
- .dai_link = &bf5xx_ad73311_dai,
+ .dai_link = &bf5xx_ad73311_dai[CONFIG_SND_BF5XX_SPORT_NUM],
.num_links = 1,
};
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 890a0dccf90..b5101efd1c8 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -148,10 +148,15 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai);
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
int ret;
pr_debug("%s enter\n", __func__);
+
snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
ret = snd_pcm_hw_constraint_integer(runtime, \
@@ -159,9 +164,14 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
if (ret < 0)
goto out;
- if (sport_handle != NULL)
+ if (sport_handle != NULL) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ sport_handle->tx_buf = buf->area;
+ else
+ sport_handle->rx_buf = buf->area;
+
runtime->private_data = sport_handle;
- else {
+ } else {
pr_err("sport_handle is NULL\n");
return -1;
}
@@ -214,11 +224,6 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
pr_debug("%s, area:%p, size:0x%08lx\n", __func__,
buf->area, buf->bytes);
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- sport_handle->tx_buf = buf->area;
- else
- sport_handle->rx_buf = buf->area;
-
return 0;
}
@@ -239,8 +244,6 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
dma_free_coherent(NULL, buf->bytes, buf->area, 0);
buf->area = NULL;
}
- if (sport_handle)
- sport_done(sport_handle);
}
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
@@ -292,7 +295,7 @@ static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev)
static struct platform_driver bfin_i2s_pcm_driver = {
.driver = {
- .name = "bfin-pcm-audio",
+ .name = "bfin-i2s-pcm-audio",
.owner = THIS_MODULE,
},
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index d453b1e9d60..00cc3e00b2f 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -51,59 +51,24 @@ struct bf5xx_i2s_port {
int configured;
};
-static struct bf5xx_i2s_port bf5xx_i2s;
-static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
-
-static struct sport_param sport_params[2] = {
- {
- .dma_rx_chan = CH_SPORT0_RX,
- .dma_tx_chan = CH_SPORT0_TX,
- .err_irq = IRQ_SPORT0_ERROR,
- .regs = (struct sport_register *)SPORT0_TCR1,
- },
- {
- .dma_rx_chan = CH_SPORT1_RX,
- .dma_tx_chan = CH_SPORT1_TX,
- .err_irq = IRQ_SPORT1_ERROR,
- .regs = (struct sport_register *)SPORT1_TCR1,
- }
-};
-
-/*
- * Setting the TFS pin selector for SPORT 0 based on whether the selected
- * port id F or G. If the port is F then no conflict should exist for the
- * TFS. When Port G is selected and EMAC then there is a conflict between
- * the PHY interrupt line and TFS. Current settings prevent the conflict
- * by ignoring the TFS pin when Port G is selected. This allows both
- * codecs and EMAC using Port G concurrently.
- */
-#ifdef CONFIG_BF527_SPORT0_PORTG
-#define LOCAL_SPORT0_TFS (0)
-#else
-#define LOCAL_SPORT0_TFS (P_SPORT0_TFS)
-#endif
-
-static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
- P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0},
- {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI,
- P_SPORT1_RSCLK, P_SPORT1_TFS, 0} };
-
static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
+ struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai);
+ struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
int ret = 0;
/* interface format:support I2S,slave mode */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
- bf5xx_i2s.tcr1 |= TFSR | TCKFE;
- bf5xx_i2s.rcr1 |= RFSR | RCKFE;
- bf5xx_i2s.tcr2 |= TSFSE;
- bf5xx_i2s.rcr2 |= RSFSE;
+ bf5xx_i2s->tcr1 |= TFSR | TCKFE;
+ bf5xx_i2s->rcr1 |= RFSR | RCKFE;
+ bf5xx_i2s->tcr2 |= TSFSE;
+ bf5xx_i2s->rcr2 |= RSFSE;
break;
case SND_SOC_DAIFMT_DSP_A:
- bf5xx_i2s.tcr1 |= TFSR;
- bf5xx_i2s.rcr1 |= RFSR;
+ bf5xx_i2s->tcr1 |= TFSR;
+ bf5xx_i2s->rcr1 |= RFSR;
break;
case SND_SOC_DAIFMT_LEFT_J:
ret = -EINVAL;
@@ -135,29 +100,35 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
+ struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
+ struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
int ret = 0;
- bf5xx_i2s.tcr2 &= ~0x1f;
- bf5xx_i2s.rcr2 &= ~0x1f;
+ bf5xx_i2s->tcr2 &= ~0x1f;
+ bf5xx_i2s->rcr2 &= ~0x1f;
switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ bf5xx_i2s->tcr2 |= 7;
+ bf5xx_i2s->rcr2 |= 7;
+ sport_handle->wdsize = 1;
case SNDRV_PCM_FORMAT_S16_LE:
- bf5xx_i2s.tcr2 |= 15;
- bf5xx_i2s.rcr2 |= 15;
+ bf5xx_i2s->tcr2 |= 15;
+ bf5xx_i2s->rcr2 |= 15;
sport_handle->wdsize = 2;
break;
case SNDRV_PCM_FORMAT_S24_LE:
- bf5xx_i2s.tcr2 |= 23;
- bf5xx_i2s.rcr2 |= 23;
+ bf5xx_i2s->tcr2 |= 23;
+ bf5xx_i2s->rcr2 |= 23;
sport_handle->wdsize = 3;
break;
case SNDRV_PCM_FORMAT_S32_LE:
- bf5xx_i2s.tcr2 |= 31;
- bf5xx_i2s.rcr2 |= 31;
+ bf5xx_i2s->tcr2 |= 31;
+ bf5xx_i2s->rcr2 |= 31;
sport_handle->wdsize = 4;
break;
}
- if (!bf5xx_i2s.configured) {
+ if (!bf5xx_i2s->configured) {
/*
* TX and RX are not independent,they are enabled at the
* same time, even if only one side is running. So, we
@@ -166,16 +137,16 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
*
* CPU DAI:slave mode.
*/
- bf5xx_i2s.configured = 1;
- ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
- bf5xx_i2s.rcr2, 0, 0);
+ bf5xx_i2s->configured = 1;
+ ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1,
+ bf5xx_i2s->rcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
return -EBUSY;
}
- ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
- bf5xx_i2s.tcr2, 0, 0);
+ ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1,
+ bf5xx_i2s->tcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
return -EBUSY;
@@ -188,41 +159,19 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
+ struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
+ struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
+
pr_debug("%s enter\n", __func__);
/* No active stream, SPORT is allowed to be configured again. */
if (!dai->active)
- bf5xx_i2s.configured = 0;
-}
-
-static int bf5xx_i2s_probe(struct snd_soc_dai *dai)
-{
- pr_debug("%s enter\n", __func__);
- if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
- pr_err("Requesting Peripherals failed\n");
- return -EFAULT;
- }
-
- /* request DMA for SPORT */
- sport_handle = sport_init(&sport_params[sport_num], 4, \
- 2 * sizeof(u32), NULL);
- if (!sport_handle) {
- peripheral_free_list(&sport_req[sport_num][0]);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static int bf5xx_i2s_remove(struct snd_soc_dai *dai)
-{
- pr_debug("%s enter\n", __func__);
- peripheral_free_list(&sport_req[sport_num][0]);
- return 0;
+ bf5xx_i2s->configured = 0;
}
#ifdef CONFIG_PM
static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
{
+ struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
pr_debug("%s : sport %d\n", __func__, dai->id);
@@ -235,19 +184,21 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
{
+ struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
+ struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
int ret;
pr_debug("%s : sport %d\n", __func__, dai->id);
- ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
- bf5xx_i2s.rcr2, 0, 0);
+ ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1,
+ bf5xx_i2s->rcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
return -EBUSY;
}
- ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
- bf5xx_i2s.tcr2, 0, 0);
+ ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1,
+ bf5xx_i2s->tcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
return -EBUSY;
@@ -266,8 +217,11 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_96000)
-#define BF5XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
- SNDRV_PCM_FMTBIT_S32_LE)
+#define BF5XX_I2S_FORMATS \
+ (SNDRV_PCM_FMTBIT_S8 | \
+ SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
.shutdown = bf5xx_i2s_shutdown,
@@ -276,8 +230,6 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
};
static struct snd_soc_dai_driver bf5xx_i2s_dai = {
- .probe = bf5xx_i2s_probe,
- .remove = bf5xx_i2s_remove,
.suspend = bf5xx_i2s_suspend,
.resume = bf5xx_i2s_resume,
.playback = {
@@ -293,23 +245,45 @@ static struct snd_soc_dai_driver bf5xx_i2s_dai = {
.ops = &bf5xx_i2s_dai_ops,
};
-static int bfin_i2s_drv_probe(struct platform_device *pdev)
+static int __devinit bf5xx_i2s_probe(struct platform_device *pdev)
{
- return snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai);
+ struct sport_device *sport_handle;
+ int ret;
+
+ /* configure SPORT for I2S */
+ sport_handle = sport_init(pdev, 4, 2 * sizeof(u32),
+ sizeof(struct bf5xx_i2s_port));
+ if (!sport_handle)
+ return -ENODEV;
+
+ /* register with the ASoC layers */
+ ret = snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai);
+ if (ret) {
+ pr_err("Failed to register DAI: %d\n", ret);
+ sport_done(sport_handle);
+ return ret;
+ }
+
+ return 0;
}
-static int __devexit bfin_i2s_drv_remove(struct platform_device *pdev)
+static int __devexit bf5xx_i2s_remove(struct platform_device *pdev)
{
+ struct sport_device *sport_handle = platform_get_drvdata(pdev);
+
+ pr_debug("%s enter\n", __func__);
+
snd_soc_unregister_dai(&pdev->dev);
+ sport_done(sport_handle);
+
return 0;
}
static struct platform_driver bfin_i2s_driver = {
- .probe = bfin_i2s_drv_probe,
- .remove = __devexit_p(bfin_i2s_drv_remove),
-
+ .probe = bf5xx_i2s_probe,
+ .remove = __devexit_p(bf5xx_i2s_remove),
.driver = {
- .name = "bf5xx-i2s",
+ .name = "bfin-i2s",
.owner = THIS_MODULE,
},
};
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c
index 99051ff0954..a2d40349fcc 100644
--- a/sound/soc/blackfin/bf5xx-sport.c
+++ b/sound/soc/blackfin/bf5xx-sport.c
@@ -42,8 +42,6 @@
/* delay between frame sync pulse and first data bit in multichannel mode */
#define FRAME_DELAY (1<<12)
-struct sport_device *sport_handle;
-EXPORT_SYMBOL(sport_handle);
/* note: multichannel is in units of 8 channels,
* tdm_count is # channels NOT / 8 ! */
int sport_set_multichannel(struct sport_device *sport,
@@ -798,86 +796,164 @@ int sport_set_err_callback(struct sport_device *sport,
}
EXPORT_SYMBOL(sport_set_err_callback);
-struct sport_device *sport_init(struct sport_param *param, unsigned wdsize,
- unsigned dummy_count, void *private_data)
+static int sport_config_pdev(struct platform_device *pdev, struct sport_param *param)
{
- int ret;
+ /* Extract settings from platform data */
+ struct device *dev = &pdev->dev;
+ struct bfin_snd_platform_data *pdata = dev->platform_data;
+ struct resource *res;
+
+ param->num = pdev->id;
+
+ if (!pdata) {
+ dev_err(dev, "no platform_data\n");
+ return -ENODEV;
+ }
+ param->pin_req = pdata->pin_req;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "no MEM resource\n");
+ return -ENODEV;
+ }
+ param->regs = (struct sport_register *)res->start;
+
+ /* first RX, then TX */
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!res) {
+ dev_err(dev, "no rx DMA resource\n");
+ return -ENODEV;
+ }
+ param->dma_rx_chan = res->start;
+
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!res) {
+ dev_err(dev, "no tx DMA resource\n");
+ return -ENODEV;
+ }
+ param->dma_tx_chan = res->start;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);