提交 87fd83fd 编写于 作者: M Mark Brown

Merge remote-tracking branch 'asoc/topic/blackfin' into asoc-next

......@@ -283,14 +283,6 @@ static struct platform_device bfin_i2s = {
};
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
static struct platform_device bfin_tdm = {
.name = "bfin-tdm",
.id = CONFIG_SND_BF5XX_SPORT_NUM,
/* TODO: add platform data here */
};
#endif
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
......@@ -800,10 +792,6 @@ static struct platform_device *stamp_devices[] __initdata = {
#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
&bfin_i2s,
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
&bfin_tdm,
#endif
};
static int __init ad7160eval_init(void)
......
......@@ -493,8 +493,7 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = {
};
#endif
#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \
defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
static const u16 bfin_snd_pin[][7] = {
{P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
......@@ -549,13 +548,6 @@ static struct platform_device bfin_i2s_pcm = {
};
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
static struct platform_device bfin_tdm_pcm = {
.name = "bfin-tdm-pcm-audio",
.id = -1,
};
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
static struct platform_device bfin_ac97_pcm = {
.name = "bfin-ac97-pcm-audio",
......@@ -575,22 +567,10 @@ static struct platform_device bfin_i2s = {
};
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
static struct platform_device bfin_tdm = {
.name = "bfin-tdm",
.id = CONFIG_SND_BF5XX_SPORT_NUM,
.num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]),
.resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM],
.dev = {
.platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM],
},
};
#endif
#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
|| defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
static const char * const ad1836_link[] = {
"bfin-tdm.0",
"bfin-i2s.0",
"spi0.4",
};
static struct platform_device bfin_ad1836_machine = {
......@@ -1269,10 +1249,6 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_i2s_pcm,
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
&bfin_tdm_pcm,
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
&bfin_ac97_pcm,
#endif
......@@ -1281,10 +1257,6 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_i2s,
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
&bfin_tdm,
#endif
#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \
defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
&bfin_ad1836_machine,
......
......@@ -450,14 +450,6 @@ static struct platform_device bfin_i2s = {
};
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
static struct platform_device bfin_tdm = {
.name = "bfin-tdm",
.id = CONFIG_SND_BF5XX_SPORT_NUM,
/* TODO: add platform data here */
};
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
static struct platform_device bfin_ac97 = {
.name = "bfin-ac97",
......@@ -516,10 +508,6 @@ static struct platform_device *ezkit_devices[] __initdata = {
&bfin_i2s,
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
&bfin_tdm,
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
&bfin_ac97,
#endif
......
......@@ -542,8 +542,7 @@ static struct platform_device bfin_dpmc = {
};
#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \
defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) \
|| defined(CONFIG_SND_BF5XX_AC97) || \
defined(CONFIG_SND_BF5XX_AC97) || \
defined(CONFIG_SND_BF5XX_AC97_MODULE)
#include <asm/bfin_sport.h>
......@@ -603,13 +602,6 @@ static struct platform_device bfin_i2s_pcm = {
};
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
static struct platform_device bfin_tdm_pcm = {
.name = "bfin-tdm-pcm-audio",
.id = -1,
};
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
static struct platform_device bfin_ac97_pcm = {
.name = "bfin-ac97-pcm-audio",
......@@ -620,7 +612,7 @@ static struct platform_device bfin_ac97_pcm = {
#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
|| defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
static const char * const ad1836_link[] = {
"bfin-tdm.0",
"bfin-i2s.0",
"spi0.4",
};
static struct platform_device bfin_ad1836_machine = {
......@@ -675,20 +667,6 @@ static struct platform_device bfin_i2s = {
};
#endif
#if defined(CONFIG_SND_BF5XX_SOC_TDM) || \
defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE)
static struct platform_device bfin_tdm = {
.name = "bfin-tdm",
.id = CONFIG_SND_BF5XX_SPORT_NUM,
.num_resources =
ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]),
.resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM],
.dev = {
.platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM],
},
};
#endif
#if defined(CONFIG_SND_BF5XX_SOC_AC97) || \
defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE)
static struct platform_device bfin_ac97 = {
......@@ -761,10 +739,6 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_i2s_pcm,
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
&bfin_tdm_pcm,
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
&bfin_ac97_pcm,
#endif
......@@ -792,11 +766,6 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_i2s,
#endif
#if defined(CONFIG_SND_BF5XX_SOC_TDM) || \
defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE)
&bfin_tdm,
#endif
#if defined(CONFIG_SND_BF5XX_SOC_AC97) || \
defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE)
&bfin_ac97,
......
......@@ -2570,7 +2570,6 @@ static struct platform_device bfin_dpmc = {
};
#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \
defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) || \
defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
#define SPORT_REQ(x) \
......@@ -2628,13 +2627,6 @@ static struct platform_device bfin_i2s_pcm = {
};
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
static struct platform_device bfin_tdm_pcm = {
.name = "bfin-tdm-pcm-audio",
.id = -1,
};
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
static struct platform_device bfin_ac97_pcm = {
.name = "bfin-ac97-pcm-audio",
......@@ -2645,7 +2637,7 @@ static struct platform_device bfin_ac97_pcm = {
#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
|| defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
static const char * const ad1836_link[] = {
"bfin-tdm.0",
"bfin-i2s.0",
"spi0.4",
};
static struct platform_device bfin_ad1836_machine = {
......@@ -2699,18 +2691,6 @@ static struct platform_device bfin_i2s = {
};
#endif
#if defined(CONFIG_SND_BF5XX_SOC_TDM) || defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE)
static struct platform_device bfin_tdm = {
.name = "bfin-tdm",
.id = CONFIG_SND_BF5XX_SPORT_NUM,
.num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]),
.resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM],
.dev = {
.platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM],
},
};
#endif
#if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE)
static struct platform_device bfin_ac97 = {
.name = "bfin-ac97",
......@@ -2935,10 +2915,6 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_i2s_pcm,
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
&bfin_tdm_pcm,
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
&bfin_ac97_pcm,
#endif
......@@ -2961,10 +2937,6 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_i2s,
#endif
#if defined(CONFIG_SND_BF5XX_SOC_TDM) || defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE)
&bfin_tdm,
#endif
#if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE)
&bfin_ac97,
#endif
......
......@@ -1393,7 +1393,6 @@ static struct platform_device bfin_dpmc = {
};
#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \
defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) || \
defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
#define SPORT_REQ(x) \
......@@ -1461,13 +1460,6 @@ static struct platform_device bfin_i2s_pcm = {
};
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
static struct platform_device bfin_tdm_pcm = {
.name = "bfin-tdm-pcm-audio",
.id = -1,
};
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
static struct platform_device bfin_ac97_pcm = {
.name = "bfin-ac97-pcm-audio",
......@@ -1501,18 +1493,6 @@ static struct platform_device bfin_i2s = {
};
#endif
#if defined(CONFIG_SND_BF5XX_SOC_TDM) || defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE)
static struct platform_device bfin_tdm = {
.name = "bfin-tdm",
.id = CONFIG_SND_BF5XX_SPORT_NUM,
.num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]),
.resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM],
.dev = {
.platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM],
},
};
#endif
#if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE)
static struct platform_device bfin_ac97 = {
.name = "bfin-ac97",
......@@ -1646,9 +1626,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
&bfin_i2s_pcm,
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
&bfin_tdm_pcm,
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
&bfin_ac97_pcm,
#endif
......@@ -1661,10 +1639,6 @@ static struct platform_device *ezkit_devices[] __initdata = {
&bfin_i2s,
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
&bfin_tdm,
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
&bfin_ac97,
#endif
......
......@@ -523,14 +523,6 @@ static struct platform_device bfin_i2s = {
};
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
static struct platform_device bfin_tdm = {
.name = "bfin-tdm",
.id = CONFIG_SND_BF5XX_SPORT_NUM,
/* TODO: add platform data here */
};
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
static struct platform_device bfin_ac97 = {
.name = "bfin-ac97",
......@@ -542,7 +534,7 @@ static struct platform_device bfin_ac97 = {
#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
|| defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
static const char * const ad1836_link[] = {
"bfin-tdm.0",
"bfin-i2s.0",
"spi0.4",
};
static struct platform_device bfin_ad1836_machine = {
......@@ -611,10 +603,6 @@ static struct platform_device *ezkit_devices[] __initdata = {
&bfin_i2s,
#endif
#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
&bfin_tdm,
#endif
#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
&bfin_ac97,
#endif
......
......@@ -821,7 +821,7 @@ static struct platform_device bfin_i2s = {
#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
|| defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
static const char * const ad1836_link[] = {
"bfin-tdm.0",
"bfin-i2s.0",
"spi0.76",
};
static struct platform_device bfin_ad1836_machine = {
......
......@@ -56,6 +56,23 @@ config SND_SOC_BFIN_EVAL_ADAV80X
Note: This driver assumes that the ADAV80X digital record and playback
interfaces are connected to the first SPORT port on the BF5XX board.
config SND_BF5XX_SOC_AD1836
tristate "SoC AD1836 Audio support for BF5xx"
depends on SND_BF5XX_I2S
select SND_BF5XX_SOC_I2S
select SND_SOC_AD1836
help
Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
config SND_BF5XX_SOC_AD193X
tristate "SoC AD193X Audio support for Blackfin"
depends on SND_BF5XX_I2S
select SND_BF5XX_SOC_I2S
select SND_SOC_AD193X
help
Say Y if you want to add support for AD193X codec on Blackfin.
This driver supports AD1936, AD1937, AD1938 and AD1939.
config SND_BF5XX_SOC_AD73311
tristate "SoC AD73311 Audio support for Blackfin"
depends on SND_BF5XX_I2S
......@@ -72,33 +89,6 @@ config SND_BFIN_AD73311_SE
Enter the GPIO used to control AD73311's SE pin. Acceptable
values are 0 to 7
config SND_BF5XX_TDM
tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip"
depends on (BLACKFIN && SND_SOC)
select SND_BF5XX_SOC_SPORT
help
Say Y or M if you want to add support for codecs attached to
the Blackfin SPORT (synchronous serial ports) interface in TDM
mode.
You will also need to select the audio interfaces to support below.
config SND_BF5XX_SOC_AD1836
tristate "SoC AD1836 Audio support for BF5xx"
depends on SND_BF5XX_TDM
select SND_BF5XX_SOC_TDM
select SND_SOC_AD1836
help
Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
config SND_BF5XX_SOC_AD193X
tristate "SoC AD193X Audio support for Blackfin"
depends on SND_BF5XX_TDM
select SND_BF5XX_SOC_TDM
select SND_SOC_AD193X
help
Say Y if you want to add support for AD193X codec on Blackfin.
This driver supports AD1936, AD1937, AD1938 and AD1939.
config SND_BF5XX_AC97
tristate "SoC AC97 Audio for the ADI BF5xx chip"
depends on BLACKFIN
......@@ -174,9 +164,6 @@ config SND_BF5XX_SOC_I2S
config SND_BF6XX_SOC_I2S
tristate
config SND_BF5XX_SOC_TDM
tristate
config SND_BF5XX_SOC_AC97
tristate
......
# Blackfin Platform Support
snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o
snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o
snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o
snd-soc-bf5xx-sport-objs := bf5xx-sport.o
snd-soc-bf6xx-sport-objs := bf6xx-sport.o
snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o
snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o
snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o
snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o
obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o
obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o
obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o
obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o
obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o
obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o
obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o
obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o
# Blackfin Machine Support
snd-ad1836-objs := bf5xx-ad1836.o
......
......@@ -39,7 +39,6 @@
#include <asm/dma.h>
#include "bf5xx-ac97-pcm.h"
#include "bf5xx-ac97.h"
#include "bf5xx-sport.h"
......
/*
* linux/sound/arm/bf5xx-ac97-pcm.h -- ALSA PCM interface for the Blackfin
*
* Copyright 2007 Analog Device Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _BF5XX_AC97_PCM_H
#define _BF5XX_AC97_PCM_H
struct bf5xx_pcm_dma_params {
char *name; /* stream identifier */
};
struct bf5xx_gpio {
u32 sys;
u32 rx;
u32 tx;
u32 clk;
u32 frm;
};
#endif
......@@ -231,9 +231,9 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
return 0;
#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
ret = sport_set_multichannel(sport, 16, 0x3FF, 1);
ret = sport_set_multichannel(sport, 16, 0x3FF, 0x3FF, 1);
#else
ret = sport_set_multichannel(sport, 16, 0x1F, 1);
ret = sport_set_multichannel(sport, 16, 0x1F, 0x1F, 1);
#endif
if (ret) {
pr_err("SPORT is busy!\n");
......@@ -311,9 +311,9 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev)
/*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);
ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 0x3FF, 1);
#else
ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1);
ret = sport_set_multichannel(sport_handle, 16, 0x1F, 0x1F, 1);
#endif
if (ret) {
pr_err("SPORT is busy!\n");
......
......@@ -30,15 +30,10 @@
#include "../codecs/ad1836.h"
#include "bf5xx-tdm-pcm.h"
#include "bf5xx-tdm.h"
static struct snd_soc_card bf5xx_ad1836;
static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int bf5xx_ad1836_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
int ret = 0;
......@@ -49,13 +44,13 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xFF, 0xFF, 8, 32);
if (ret < 0)
return ret;
return 0;
}
static struct snd_soc_ops bf5xx_ad1836_ops = {
.hw_params = bf5xx_ad1836_hw_params,
};
#define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
SND_SOC_DAIFMT_CBM_CFM)
......@@ -63,9 +58,9 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai = {
.name = "ad1836",
.stream_name = "AD1836",
.codec_dai_name = "ad1836-hifi",
.platform_name = "bfin-tdm-pcm-audio",
.ops = &bf5xx_ad1836_ops,
.platform_name = "bfin-i2s-pcm-audio",
.dai_fmt = BF5XX_AD1836_DAIFMT,
.init = bf5xx_ad1836_init,
};
static struct snd_soc_card bf5xx_ad1836 = {
......
......@@ -39,30 +39,16 @@
#include "../codecs/ad193x.h"
#include "bf5xx-tdm-pcm.h"
#include "bf5xx-tdm.h"
static struct snd_soc_card bf5xx_ad193x;
static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int bf5xx_ad193x_link_init(struct snd_soc_pcm_runtime *rtd)
{
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 = 24576000;
break;
}
int ret;
/* set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
SND_SOC_CLOCK_IN);
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
......@@ -71,9 +57,7 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
/* set cpu DAI channel mapping */
ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
channel_map, ARRAY_SIZE(channel_map), channel_map);
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xFF, 0xFF, 8, 32);
if (ret < 0)
return ret;
......@@ -83,30 +67,26 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
#define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
SND_SOC_DAIFMT_CBM_CFM)
static struct snd_soc_ops bf5xx_ad193x_ops = {
.hw_params = bf5xx_ad193x_hw_params,
};
static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
{
.name = "ad193x",
.stream_name = "AD193X",
.cpu_dai_name = "bfin-tdm.0",
.cpu_dai_name = "bfin-i2s.0",
.codec_dai_name ="ad193x-hifi",
.platform_name = "bfin-tdm-pcm-audio",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "spi0.5",
.ops = &bf5xx_ad193x_ops,
.dai_fmt = BF5XX_AD193X_DAIFMT,
.init = bf5xx_ad193x_link_init,
},
{
.name = "ad193x",
.stream_name = "AD193X",
.cpu_dai_name = "bfin-tdm.1",
.cpu_dai_name = "bfin-i2s.1",
.codec_dai_name ="ad193x-hifi",
.platform_name = "bfin-tdm-pcm-audio",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "spi0.5",
.ops = &bf5xx_ad193x_ops,
.dai_fmt = BF5XX_AD193X_DAIFMT,
.init = bf5xx_ad193x_link_init,
},
};
......
......@@ -48,7 +48,6 @@
#include "../codecs/ad1980.h"
#include "bf5xx-ac97-pcm.h"
#include "bf5xx-ac97.h"
static struct snd_soc_card bf5xx_board;
......
......@@ -45,7 +45,6 @@
#include "../codecs/ad73311.h"
#include "bf5xx-sport.h"
#include "bf5xx-i2s-pcm.h"
#if CONFIG_SND_BF5XX_SPORT_NUM == 0
#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1
......
......@@ -39,8 +39,8 @@
#include <asm/dma.h>
#include "bf5xx-i2s-pcm.h"
#include "bf5xx-sport.h"
#include "bf5xx-i2s-pcm.h"
static void bf5xx_dma_irq(void *data)
{
......@@ -50,7 +50,6 @@ static void bf5xx_dma_irq(void *data)
static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_BLOCK_TRANSFER,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
......@@ -67,10 +66,16 @@ static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
snd_pcm_lib_malloc_pages(substream, size);
struct snd_soc_pcm_runtime *rtd = substream->private_data;
unsigned int buffer_size = params_buffer_bytes(params);
struct bf5xx_i2s_pcm_data *dma_data;
return 0;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
if (dma_data->tdm_mode)
buffer_size = buffer_size / params_channels(params) * 8;
return snd_pcm_lib_malloc_pages(substream, buffer_size);
}
static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
......@@ -82,9 +87,16 @@ static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
struct sport_device *sport = runtime->private_data;
int period_bytes = frames_to_bytes(runtime, runtime->period_size);
struct bf5xx_i2s_pcm_data *dma_data;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
if (dma_data->tdm_mode)
period_bytes = period_bytes / runtime->channels * 8;
pr_debug("%s enter\n", __func__);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
......@@ -131,10 +143,15 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
struct sport_device *sport = runtime->private_data;
unsigned int diff;
snd_pcm_uframes_t frames;
struct bf5xx_i2s_pcm_data *dma_data;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
pr_debug("%s enter\n", __func__);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
diff = sport_curr_offset_tx(sport);
......@@ -151,6 +168,8 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
diff = 0;
frames = bytes_to_frames(substream->runtime, diff);
if (dma_data->tdm_mode)
frames = frames * runtime->channels / 8;
return frames;
}
......@@ -162,11 +181,18 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
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;
struct bf5xx_i2s_pcm_data *dma_data;
int ret;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
pr_debug("%s enter\n", __func__);
snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
if (dma_data->tdm_mode)
runtime->hw.buffer_bytes_max /= 4;
else
runtime->hw.info |= SNDRV_PCM_INFO_MMAP;
ret = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
......@@ -202,6 +228,88 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
return 0 ;
}
static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int sample_size = runtime->sample_bits / 8;
struct bf5xx_i2s_pcm_data *dma_data;
unsigned int i;
void *src, *dst;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
if (dma_data->tdm_mode) {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
src = buf;
dst = runtime->dma_area;
dst += pos * sample_size * 8;
while (count--) {
for (i = 0; i < runtime->channels; i++) {
memcpy(dst + dma_data->map[i] *
sample_size, src, sample_size);
src += sample_size;
}
dst += 8 * sample_size;
}
} else {
src = runtime->dma_area;
src += pos * sample_size * 8;
dst = buf;
while (count--) {
for (i = 0; i < runtime->channels; i++) {
memcpy(dst, src + dma_data->map[i] *
sample_size, sample_size);
dst += sample_size;
}
src += 8 * sample_size;
}
}
} else {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
src = buf;
dst = runtime->dma_area;
dst += frames_to_bytes(runtime, pos);
} else {
src = runtime->dma_area;
src += frames_to_bytes(runtime, pos);
dst = buf;
}
memcpy(dst, src, frames_to_bytes(runtime, count));
}
return 0;
}
static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int sample_size = runtime->sample_bits / 8;
void *buf = runtime->dma_area;
struct bf5xx_i2s_pcm_data *dma_data;
unsigned int offset, size;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
if (dma_data->tdm_mode) {
offset = pos * 8 * sample_size;
size = count * 8 * sample_size;
} else {
offset = frames_to_bytes(runtime, pos);
size = frames_to_bytes(runtime, count);
}
snd_pcm_format_set_silence(runtime->format, buf + offset, size);
return 0;
}
static struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
.open = bf5xx_pcm_open,
.ioctl = snd_pcm_lib_ioctl,
......@@ -211,57 +319,16 @@ static struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
.trigger = bf5xx_pcm_trigger,
.pointer = bf5xx_pcm_pointer,
.mmap = bf5xx_pcm_mmap,
.copy = bf5xx_pcm_copy,
.silence = bf5xx_pcm_silence,
};
static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
{
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;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev;
buf->private_data = NULL;
buf->area = dma_alloc_coherent(pcm->card->dev, size,
&buf->addr, GFP_KERNEL);
if (!buf->area) {
pr_err("Failed to allocate dma memory - Please increase uncached DMA memory region\n");
return -ENOMEM;
}
buf->bytes = size;
pr_debug("%s, area:%p, size:0x%08lx\n", __func__,
buf->area, buf->bytes);
return 0;
}
static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
int stream;
for (stream = 0; stream < 2; stream++) {
substream = pcm->streams[stream].substream;
if (!substream)
continue;
buf = &substream->dma_buffer;
if (!buf->area)
continue;
dma_free_coherent(NULL, buf->bytes, buf->area, 0);
buf->area = NULL;
}
}
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
pr_debug("%s enter\n", __func__);
if (!card->dev->dma_mask)
......@@ -269,27 +336,13 @@ static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
goto out;
}
out:
return ret;
return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
SNDRV_DMA_TYPE_DEV, card->dev, size, size);
}
static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = {
.ops = &bf5xx_pcm_i2s_ops,
.pcm_new = bf5xx_pcm_i2s_new,
.pcm_free = bf5xx_pcm_free_dma_buffers,
};
static int bfin_i2s_soc_platform_probe(struct platform_device *pdev)
......
/*
* linux/sound/arm/bf5xx-i2s-pcm.h -- ALSA PCM interface for the Blackfin
*
* Copyright 2007 Analog Device Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _BF5XX_I2S_PCM_H
#define _BF5XX_I2S_PCM_H
#ifndef _BF5XX_TDM_PCM_H
#define _BF5XX_TDM_PCM_H
struct bf5xx_pcm_dma_params {
char *name; /* stream identifier */
};
#define BFIN_TDM_DAI_MAX_SLOTS 8
struct bf5xx_gpio {
u32 sys;
u32 rx;
u32 tx;
u32 clk;
u32 frm;
struct bf5xx_i2s_pcm_data {
unsigned int map[BFIN_TDM_DAI_MAX_SLOTS];
bool tdm_mode;
};
#endif
......@@ -42,6 +42,7 @@
#include <linux/gpio.h>
#include "bf5xx-sport.h"
#include "bf5xx-i2s-pcm.h"
struct bf5xx_i2s_port {
u16 tcr1;
......@@ -49,6 +50,13 @@ struct bf5xx_i2s_port {
u16 tcr2;
u16 rcr2;
int configured;
unsigned int slots;
unsigned int tx_mask;
unsigned int rx_mask;
struct bf5xx_i2s_pcm_data tx_dma_data;
struct bf5xx_i2s_pcm_data rx_dma_data;
};
static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
......@@ -74,7 +82,8 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
ret = -EINVAL;
break;
default:
printk(KERN_ERR "%s: Unknown DAI format type\n", __func__);
dev_err(cpu_dai->dev, "%s: Unknown DAI format type\n",
__func__);
ret = -EINVAL;
break;
}
......@@ -88,7 +97,8 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
ret = -EINVAL;
break;
default:
printk(KERN_ERR "%s: Unknown DAI master type\n", __func__);
dev_err(cpu_dai->dev, "%s: Unknown DAI master type\n",
__func__);
ret = -EINVAL;
break;
}
......@@ -141,14 +151,14 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1,
bf5xx_i2s->rcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
dev_err(dai->dev, "SPORT is busy!\n");
return -EBUSY;
}
ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1,
bf5xx_i2s->tcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
dev_err(dai->dev, "SPORT is busy!\n");
return -EBUSY;
}
}
......@@ -162,18 +172,76 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
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__);
dev_dbg(dai->dev, "%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_set_channel_map(struct snd_soc_dai *dai,
unsigned int tx_num, unsigned int *tx_slot,
unsigned int rx_num, unsigned int *rx_slot)
{
struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
unsigned int tx_mapped = 0, rx_mapped = 0;
unsigned int slot;
int i;
if ((tx_num > BFIN_TDM_DAI_MAX_SLOTS) ||
(rx_num > BFIN_TDM_DAI_MAX_SLOTS))
return -EINVAL;
for (i = 0; i < tx_num; i++) {
slot = tx_slot[i];
if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
(!(tx_mapped & (1 << slot)))) {
bf5xx_i2s->tx_dma_data.map[i] = slot;
tx_mapped |= 1 << slot;
} else
return -EINVAL;
}
for (i = 0; i < rx_num; i++) {
slot = rx_slot[i];
if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
(!(rx_mapped & (1 << slot)))) {
bf5xx_i2s->rx_dma_data.map[i] = slot;
rx_mapped |= 1 << slot;
} else
return -EINVAL;
}
return 0;
}
static int bf5xx_i2s_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
unsigned int rx_mask, int slots, int width)
{
struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
if (slots % 8 != 0 || slots > 8)
return -EINVAL;
if (width != 32)
return -EINVAL;
bf5xx_i2s->slots = slots;
bf5xx_i2s->tx_mask = tx_mask;
bf5xx_i2s->rx_mask = rx_mask;
bf5xx_i2s->tx_dma_data.tdm_mode = slots != 0;
bf5xx_i2s->rx_dma_data.tdm_mode = slots != 0;
return sport_set_multichannel(sport_handle, slots, tx_mask, rx_mask, 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);
dev_dbg(dai->dev, "%s : sport %d\n", __func__, dai->id);
if (dai->capture_active)
sport_rx_stop(sport_handle);
......@@ -188,23 +256,24 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
int ret;
pr_debug("%s : sport %d\n", __func__, dai->id);
dev_dbg(dai->dev, "%s : sport %d\n", __func__, dai->id);
ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1,
bf5xx_i2s->rcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
dev_err(dai->dev, "SPORT is busy!\n");
return -EBUSY;
}
ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1,
bf5xx_i2s->tcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
dev_err(dai->dev, "SPORT is busy!\n");
return -EBUSY;
}
return 0;
return sport_set_multichannel(sport_handle, bf5xx_i2s->slots,
bf5xx_i2s->tx_mask, bf5xx_i2s->rx_mask, 0);
}
#else
......@@ -212,6 +281,23 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
#define bf5xx_i2s_resume NULL
#endif
static int bf5xx_i2s_dai_probe(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;
unsigned int i;
for (i = 0; i < BFIN_TDM_DAI_MAX_SLOTS; i++) {
bf5xx_i2s->tx_dma_data.map[i] = i;
bf5xx_i2s->rx_dma_data.map[i] = i;
}
dai->playback_dma_data = &bf5xx_i2s->tx_dma_data;
dai->capture_dma_data = &bf5xx_i2s->rx_dma_data;
return 0;
}
#define BF5XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
......@@ -224,22 +310,25 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
SNDRV_PCM_FMTBIT_S32_LE)
static const struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
.shutdown = bf5xx_i2s_shutdown,
.hw_params = bf5xx_i2s_hw_params,
.set_fmt = bf5xx_i2s_set_dai_fmt,
.shutdown = bf5xx_i2s_shutdown,
.hw_params = bf5xx_i2s_hw_params,
.set_fmt = bf5xx_i2s_set_dai_fmt,
.set_tdm_slot = bf5xx_i2s_set_tdm_slot,
.set_channel_map = bf5xx_i2s_set_channel_map,
};
static struct snd_soc_dai_driver bf5xx_i2s_dai = {
.probe = bf5xx_i2s_dai_probe,
.suspend = bf5xx_i2s_suspend,
.resume = bf5xx_i2s_resume,
.playback = {
.channels_min = 1,
.channels_max = 2,
.channels_min = 2,
.channels_max = 8,
.rates = BF5XX_I2S_RATES,
.formats = BF5XX_I2S_FORMATS,},
.capture = {
.channels_min = 1,
.channels_max = 2,
.channels_min = 2,
.channels_max = 8,
.rates = BF5XX_I2S_RATES,
.formats = BF5XX_I2S_FORMATS,},
.ops = &bf5xx_i2s_dai_ops,
......@@ -255,7 +344,7 @@ static int bf5xx_i2s_probe(struct platform_device *pdev)
int ret;
/* configure SPORT for I2S */
sport_handle = sport_init(pdev, 4, 2 * sizeof(u32),
sport_handle = sport_init(pdev, 4, 8 * sizeof(u32),
sizeof(struct bf5xx_i2s_port));
if (!sport_handle)
return -ENODEV;
......@@ -264,7 +353,7 @@ static int bf5xx_i2s_probe(struct platform_device *pdev)
ret = snd_soc_register_component(&pdev->dev, &bf5xx_i2s_component,
&bf5xx_i2s_dai, 1);
if (ret) {
pr_err("Failed to register DAI: %d\n", ret);
dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret);
sport_done(sport_handle);
return ret;
}
......@@ -276,7 +365,7 @@ static int bf5xx_i2s_remove(struct platform_device *pdev)
{
struct sport_device *sport_handle = platform_get_drvdata(pdev);
pr_debug("%s enter\n", __func__);
dev_dbg(&pdev->dev, "%s enter\n", __func__);
snd_soc_unregister_component(&pdev->dev);
sport_done(sport_handle);
......
......@@ -46,10 +46,10 @@
/* note: multichannel is in units of 8 channels,
* tdm_count is # channels NOT / 8 ! */
int sport_set_multichannel(struct sport_device *sport,
int tdm_count, u32 mask, int packed)
int tdm_count, u32 tx_mask, u32 rx_mask, int packed)
{
pr_debug("%s tdm_count=%d mask:0x%08x packed=%d\n", __func__,
tdm_count, mask, packed);
pr_debug("%s tdm_count=%d tx_mask:0x%08x rx_mask:0x%08x packed=%d\n",
__func__, tdm_count, tx_mask, rx_mask, packed);
if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN))
return -EBUSY;
......@@ -65,8 +65,8 @@ int sport_set_multichannel(struct sport_device *sport,
sport->regs->mcmc2 = FRAME_DELAY | MCMEN | \
(packed ? (MCDTXPE|MCDRXPE) : 0);
sport->regs->mtcs0 = mask;
sport->regs->mrcs0 = mask;
sport->regs->mtcs0 = tx_mask;
sport->regs->mrcs0 = rx_mask;
sport->regs->mtcs1 = 0;
sport->regs->mrcs1 = 0;
sport->regs->mtcs2 = 0;
......
......@@ -128,7 +128,7 @@ void sport_done(struct sport_device *sport);
/* note: multichannel is in units of 8 channels, tdm_count is number of channels
* NOT / 8 ! all channels are enabled by default */
int sport_set_multichannel(struct sport_device *sport, int tdm_count,
u32 mask, int packed);
u32 tx_mask, u32 rx_mask, int packed);
int sport_config_rx(struct sport_device *sport,
unsigned int rcr1, unsigned int rcr2,
......
......@@ -40,7 +40,6 @@
#include <linux/gpio.h>
#include "../codecs/ssm2602.h"
#include "bf5xx-sport.h"
#include "bf5xx-i2s-pcm.h"
static struct snd_soc_card bf5xx_ssm2602;
......
/*
* File: sound/soc/blackfin/bf5xx-tdm-pcm.c
* Author: Barry Song <Barry.Song@analog.com>
*
* Created: Tue June 06 2009
* Description: DMA driver for tdm codec
*
* Modified:
* Copyright 2009 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gfp.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <asm/dma.h>
#include "bf5xx-tdm-pcm.h"
#include "bf5xx-tdm.h"
#include "bf5xx-sport.h"
#define PCM_BUFFER_MAX 0x8000
#define FRAGMENT_SIZE_MIN (4*1024)
#define FRAGMENTS_MIN 2
#define FRAGMENTS_MAX 32
static void bf5xx_dma_irq(void *data)
{
struct snd_pcm_substream *pcm = data;
snd_pcm_period_elapsed(pcm);
}
static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_RESUME),
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.rates = SNDRV_PCM_RATE_48000,
.channels_min = 2,
.channels_max = 8,
.buffer_bytes_max = PCM_BUFFER_MAX,
.period_bytes_min = FRAGMENT_SIZE_MIN,
.period_bytes_max = PCM_BUFFER_MAX/2,
.periods_min = FRAGMENTS_MIN,
.periods_max = FRAGMENTS_MAX,
};
static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
snd_pcm_lib_malloc_pages(substream, size * 4);
return 0;
}
static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
{
snd_pcm_lib_free_pages(substream);
return 0;
}
static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct sport_device *sport = runtime->private_data;
int fragsize_bytes = frames_to_bytes(runtime, runtime->period_size);
fragsize_bytes /= runtime->channels;
/* inflate the fragsize to match the dma width of SPORT */
fragsize_bytes *= 8;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
sport_config_tx_dma(sport, runtime->dma_area,
runtime->periods, fragsize_bytes);
} else {
sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
sport_config_rx_dma(sport, runtime->dma_area,
runtime->periods, fragsize_bytes);
}
return 0;
}
static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct sport_device *sport = runtime->private_data;
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
sport_tx_start(sport);
else
sport_rx_start(sport);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
sport_tx_stop(sport);
else
sport_rx_stop(sport);
break;
default:
ret = -EINVAL;
}
return ret;
}
static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct sport_device *sport = runtime->private_data;
unsigned int diff;
snd_pcm_uframes_t frames;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
diff = sport_curr_offset_tx(sport);
frames = diff / (8*4); /* 32 bytes per frame */
} else {
diff = sport_curr_offset_rx(sport);
frames = diff / (8*4);
}
return frames;
}
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 = 0;
snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
ret = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0)
goto out;
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 {
pr_err("sport_handle is NULL\n");
ret = -ENODEV;
}
out:
return ret;
}
static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct sport_device *sport = runtime->private_data;
struct bf5xx_tdm_port *tdm_port = sport->private_data;
unsigned int *src;
unsigned int *dst;
int i;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
src = buf;
dst = (unsigned int *)substream->runtime->dma_area;
dst += pos * 8;
while (count--) {
for (i = 0; i < substream->runtime->channels; i++)
*(dst + tdm_port->tx_map[i]) = *src++;
dst += 8;
}
} else {
src = (unsigned int *)substream->runtime->dma_area;
dst = buf;
src += pos * 8;
while (count--) {
for (i = 0; i < substream->runtime->channels; i++)
*dst++ = *(src + tdm_port->rx_map[i]);
src += 8;
}
}
return 0;
}
static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
{
unsigned char *buf = substream->runtime->dma_area;
buf += pos * 8 * 4;
memset(buf, '\0', count * 8 * 4);
return 0;
}
struct snd_pcm_ops bf5xx_pcm_tdm_ops = {
.open = bf5xx_pcm_open,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = bf5xx_pcm_hw_params,
.hw_free = bf5xx_pcm_hw_free,
.prepare = bf5xx_pcm_prepare,
.trigger = bf5xx_pcm_trigger,
.pointer = bf5xx_pcm_pointer,
.copy = bf5xx_pcm_copy,
.silence = bf5xx_pcm_silence,
};
static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
{
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;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev;
buf->private_data = NULL;
buf->area = dma_alloc_coherent(pcm->card->dev, size * 4,
&buf->addr, GFP_KERNEL);
if (!buf->area) {
pr_err("Failed to allocate dma memory - Please increase uncached DMA memory region\n");
return -ENOMEM;
}
buf->bytes = size;
return 0;
}
static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
int stream;
for (stream = 0; stream < 2; stream++) {
substream = pcm->streams[stream].substream;
if (!substream)
continue;
buf = &substream->dma_buffer;
if (!buf->area)
continue;
dma_free_coherent(NULL, buf->bytes, buf->area, 0);
buf->area = NULL;
}
}
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
static int bf5xx_pcm_tdm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
card->dev->dma_mask = &bf5xx_pcm_dmamask;
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
goto out;
}
out:
return ret;
}
static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = {
.ops = &bf5xx_pcm_tdm_ops,
.pcm_new = bf5xx_pcm_tdm_new,
.pcm_free = bf5xx_pcm_free_dma_buffers,
};
static int bf5xx_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform);
}
static int bf5xx_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
}
static struct platform_driver bfin_tdm_driver = {
.driver = {
.name = "bfin-tdm-pcm-audio",
.owner = THIS_MODULE,
},
.probe = bf5xx_soc_platform_probe,
.remove = bf5xx_soc_platform_remove,
};
module_platform_driver(bfin_tdm_driver);
MODULE_AUTHOR("Barry Song");
MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
MODULE_LICENSE("GPL");
/*
* sound/soc/blackfin/bf5xx-tdm-pcm.h -- ALSA PCM interface for the Blackfin
*
* Copyright 2009 Analog Device Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _BF5XX_TDM_PCM_H
#define _BF5XX_TDM_PCM_H
struct bf5xx_pcm_dma_params {
char *name; /* stream identifier */
};
#endif
/*
* File: sound/soc/blackfin/bf5xx-tdm.c
* Author: Barry Song <Barry.Song@analog.com>
*
* Created: Thurs June 04 2009
* Description: Blackfin I2S(TDM) CPU DAI driver
* Even though TDM mode can be as part of I2S DAI, but there
* are so much difference in configuration and data flow,
* it's very ugly to integrate I2S and TDM into a module
*
* Modified:
* Copyright 2009 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <asm/irq.h>
#include <asm/portmux.h>
#include <linux/mutex.h>
#include <linux/gpio.h>
#include "bf5xx-sport.h"
#include "bf5xx-tdm.h"
static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
int ret = 0;
/* interface format:support TDM,slave mode */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_A:
break;
default:
printk(KERN_ERR "%s: Unknown DAI format type\n", __func__);
ret = -EINVAL;
break;
}
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
break;
case SND_SOC_DAIFMT_CBS_CFS:
case SND_SOC_DAIFMT_CBM_CFS:
case SND_SOC_DAIFMT_CBS_CFM:
ret = -EINVAL;
break;
default:
printk(KERN_ERR "%s: Unknown DAI master type\n", __func__);
ret = -EINVAL;
break;
}
return ret;
}
static int bf5xx_tdm_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_tdm_port *bf5xx_tdm = sport_handle->private_data;
int ret = 0;
bf5xx_tdm->tcr2 &= ~0x1f;
bf5xx_tdm->rcr2 &= ~0x1f;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S32_LE:
bf5xx_tdm->tcr2 |= 31;
bf5xx_tdm->rcr2 |= 31;
sport_handle->wdsize = 4;
break;
/* at present, we only support 32bit transfer */
default:
pr_err("not supported PCM format yet\n");
return -EINVAL;
break;
}
if (!bf5xx_tdm->configured) {
/*
* TX and RX are not independent,they are enabled at the
* same time, even if only one side is running. So, we
* need to configure both of them at the time when the first
* stream is opened.
*
* CPU DAI:slave mode.
*/
ret = sport_config_rx(sport_handle, bf5xx_tdm->rcr1,
bf5xx_tdm->rcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
return -EBUSY;
}
ret = sport_config_tx(sport_handle, bf5xx_tdm->tcr1,
bf5xx_tdm->tcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
return -EBUSY;
}
bf5xx_tdm->configured = 1;
}
return 0;
}
static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data;
/* No active stream, SPORT is allowed to be configured again. */
if (!dai->active)
bf5xx_tdm->configured = 0;
}
static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai,
unsigned int tx_num, unsigned int *tx_slot,
unsigned int rx_num, unsigned int *rx_slot)
{
struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data;
int i;
unsigned int slot;
unsigned int tx_mapped = 0, rx_mapped = 0;
if ((tx_num > BFIN_TDM_DAI_MAX_SLOTS) ||
(rx_num > BFIN_TDM_DAI_MAX_SLOTS))
return -EINVAL;
for (i = 0; i < tx_num; i++) {
slot = tx_slot[i];
if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
(!(tx_mapped & (1 << slot)))) {
bf5xx_tdm->tx_map[i] = slot;
tx_mapped |= 1 << slot;
} else
return -EINVAL;
}
for (i = 0; i < rx_num; i++) {
slot = rx_slot[i];
if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
(!(rx_mapped & (1 << slot)))) {
bf5xx_tdm->rx_map[i] = slot;
rx_mapped |= 1 << slot;
} else
return -EINVAL;
}
return 0;
}
#ifdef CONFIG_PM
static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
{
struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
if (dai->playback_active)
sport_tx_stop(sport);
if (dai->capture_active)
sport_rx_stop(sport);
/* isolate sync/clock pins from codec while sports resume */
peripheral_free_list(sport->pin_req);
return 0;
}
static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
{
int ret;
struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
ret = sport_set_multichannel(sport, 8, 0xFF, 1);
if (ret) {
pr_err("SPORT is busy!\n");
ret = -EBUSY;
}
ret = sport_config_rx(sport, 0, 0x1F, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
ret = -EBUSY;
}
ret = sport_config_tx(sport, 0, 0x1F, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
ret = -EBUSY;
}
peripheral_request_list(sport->pin_req, "soc-audio");
return 0;
}
#else
#define bf5xx_tdm_suspend NULL
#define bf5xx_tdm_resume NULL
#endif
static const struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
.hw_params = bf5xx_tdm_hw_params,
.set_fmt = bf5xx_tdm_set_dai_fmt,
.shutdown = bf5xx_tdm_shutdown,
.set_channel_map = bf5xx_tdm_set_channel_map,
};
static struct snd_soc_dai_driver bf5xx_tdm_dai = {
.suspend = bf5xx_tdm_suspend,
.resume = bf5xx_tdm_resume,
.playback = {
.channels_min = 2,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S32_LE,},
.capture = {
.channels_min = 2,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S32_LE,},
.ops = &bf5xx_tdm_dai_ops,
};
static const struct snd_soc_component_driver bf5xx_tdm_component = {
.name = "bf5xx-tdm",
};
static int bfin_tdm_probe(struct platform_device *pdev)
{
struct sport_device *sport_handle;
int ret;
/* configure SPORT for TDM */
sport_handle = sport_init(pdev, 4, 8 * sizeof(u32),
sizeof(struct bf5xx_tdm_port));
if (!sport_handle)
return -ENODEV;
/* SPORT works in TDM mode */
ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1);
if (ret) {
pr_err("SPORT is busy!\n");
ret = -EBUSY;
goto sport_config_err;
}
ret = sport_config_rx(sport_handle, 0, 0x1F, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
ret = -EBUSY;
goto sport_config_err;
}
ret = sport_config_tx(sport_handle, 0, 0x1F, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
ret = -EBUSY;
goto sport_config_err;
}
ret = snd_soc_register_component(&pdev->dev, &bf5xx_tdm_component,
&bf5xx_tdm_dai, 1);
if (ret) {
pr_err("Failed to register DAI: %d\n", ret);
goto sport_config_err;
}
return 0;
sport_config_err:
sport_done(sport_handle);
return ret;
}
static int bfin_tdm_remove(struct platform_device *pdev)
{
struct sport_device *sport_handle = platform_get_drvdata(pdev);
snd_soc_unregister_component(&pdev->dev);
sport_done(sport_handle);
return 0;
}
static struct platform_driver bfin_tdm_driver = {
.probe = bfin_tdm_probe,
.remove = bfin_tdm_remove,
.driver = {
.name = "bfin-tdm",
.owner = THIS_MODULE,
},
};
module_platform_driver(bfin_tdm_driver);
/* Module information */
MODULE_AUTHOR("Barry Song");
MODULE_DESCRIPTION("TDM driver for ADI Blackfin");
MODULE_LICENSE("GPL");
/*
* sound/soc/blackfin/bf5xx-tdm.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _BF5XX_TDM_H
#define _BF5XX_TDM_H
#define BFIN_TDM_DAI_MAX_SLOTS 8
struct bf5xx_tdm_port {
u16 tcr1;
u16 rcr1;
u16 tcr2;
u16 rcr2;
unsigned int tx_map[BFIN_TDM_DAI_MAX_SLOTS];
unsigned int rx_map[BFIN_TDM_DAI_MAX_SLOTS];
int configured;
};
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册