Merge branch 'fix/asoc' into for-linus

This commit is contained in:
Takashi Iwai 2010-11-23 12:41:17 +01:00
commit 9e8c32cac9
32 changed files with 282 additions and 216 deletions

View file

@ -359,8 +359,8 @@ static struct clk_lookup dm355_clks[] = {
CLK(NULL, "uart1", &uart1_clk), CLK(NULL, "uart1", &uart1_clk),
CLK(NULL, "uart2", &uart2_clk), CLK(NULL, "uart2", &uart2_clk),
CLK("i2c_davinci.1", NULL, &i2c_clk), CLK("i2c_davinci.1", NULL, &i2c_clk),
CLK("davinci-asp.0", NULL, &asp0_clk), CLK("davinci-mcbsp.0", NULL, &asp0_clk),
CLK("davinci-asp.1", NULL, &asp1_clk), CLK("davinci-mcbsp.1", NULL, &asp1_clk),
CLK("davinci_mmc.0", NULL, &mmcsd0_clk), CLK("davinci_mmc.0", NULL, &mmcsd0_clk),
CLK("davinci_mmc.1", NULL, &mmcsd1_clk), CLK("davinci_mmc.1", NULL, &mmcsd1_clk),
CLK("spi_davinci.0", NULL, &spi0_clk), CLK("spi_davinci.0", NULL, &spi0_clk),
@ -664,7 +664,7 @@ static struct resource dm355_asp1_resources[] = {
}; };
static struct platform_device dm355_asp1_device = { static struct platform_device dm355_asp1_device = {
.name = "davinci-asp", .name = "davinci-mcbsp",
.id = 1, .id = 1,
.num_resources = ARRAY_SIZE(dm355_asp1_resources), .num_resources = ARRAY_SIZE(dm355_asp1_resources),
.resource = dm355_asp1_resources, .resource = dm355_asp1_resources,

View file

@ -459,7 +459,7 @@ static struct clk_lookup dm365_clks[] = {
CLK(NULL, "usb", &usb_clk), CLK(NULL, "usb", &usb_clk),
CLK("davinci_emac.1", NULL, &emac_clk), CLK("davinci_emac.1", NULL, &emac_clk),
CLK("davinci_voicecodec", NULL, &voicecodec_clk), CLK("davinci_voicecodec", NULL, &voicecodec_clk),
CLK("davinci-asp.0", NULL, &asp0_clk), CLK("davinci-mcbsp", NULL, &asp0_clk),
CLK(NULL, "rto", &rto_clk), CLK(NULL, "rto", &rto_clk),
CLK(NULL, "mjcp", &mjcp_clk), CLK(NULL, "mjcp", &mjcp_clk),
CLK(NULL, NULL, NULL), CLK(NULL, NULL, NULL),
@ -922,8 +922,8 @@ static struct resource dm365_asp_resources[] = {
}; };
static struct platform_device dm365_asp_device = { static struct platform_device dm365_asp_device = {
.name = "davinci-asp", .name = "davinci-mcbsp",
.id = 0, .id = -1,
.num_resources = ARRAY_SIZE(dm365_asp_resources), .num_resources = ARRAY_SIZE(dm365_asp_resources),
.resource = dm365_asp_resources, .resource = dm365_asp_resources,
}; };

View file

@ -302,7 +302,7 @@ static struct clk_lookup dm644x_clks[] = {
CLK("davinci_emac.1", NULL, &emac_clk), CLK("davinci_emac.1", NULL, &emac_clk),
CLK("i2c_davinci.1", NULL, &i2c_clk), CLK("i2c_davinci.1", NULL, &i2c_clk),
CLK("palm_bk3710", NULL, &ide_clk), CLK("palm_bk3710", NULL, &ide_clk),
CLK("davinci-asp", NULL, &asp_clk), CLK("davinci-mcbsp", NULL, &asp_clk),
CLK("davinci_mmc.0", NULL, &mmcsd_clk), CLK("davinci_mmc.0", NULL, &mmcsd_clk),
CLK(NULL, "spi", &spi_clk), CLK(NULL, "spi", &spi_clk),
CLK(NULL, "gpio", &gpio_clk), CLK(NULL, "gpio", &gpio_clk),
@ -580,7 +580,7 @@ static struct resource dm644x_asp_resources[] = {
}; };
static struct platform_device dm644x_asp_device = { static struct platform_device dm644x_asp_device = {
.name = "davinci-asp", .name = "davinci-mcbsp",
.id = -1, .id = -1,
.num_resources = ARRAY_SIZE(dm644x_asp_resources), .num_resources = ARRAY_SIZE(dm644x_asp_resources),
.resource = dm644x_asp_resources, .resource = dm644x_asp_resources,

View file

@ -522,9 +522,6 @@
#define WM8350_MCLK_SEL_PLL_32K 3 #define WM8350_MCLK_SEL_PLL_32K 3
#define WM8350_MCLK_SEL_MCLK 5 #define WM8350_MCLK_SEL_MCLK 5
#define WM8350_MCLK_DIR_OUT 0
#define WM8350_MCLK_DIR_IN 1
/* clock divider id's */ /* clock divider id's */
#define WM8350_ADC_CLKDIV 0 #define WM8350_ADC_CLKDIV 0
#define WM8350_DAC_CLKDIV 1 #define WM8350_DAC_CLKDIV 1

View file

@ -16,7 +16,8 @@ config SND_ATMEL_SOC_SSC
config SND_AT91_SOC_SAM9G20_WM8731 config SND_AT91_SOC_SAM9G20_WM8731
tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC && \
AT91_PROGRAMMABLE_CLOCKS
select SND_ATMEL_SOC_SSC select SND_ATMEL_SOC_SSC
select SND_SOC_WM8731 select SND_SOC_WM8731
help help
@ -25,7 +26,7 @@ config SND_AT91_SOC_SAM9G20_WM8731
config SND_AT32_SOC_PLAYPAQ config SND_AT32_SOC_PLAYPAQ
tristate "SoC Audio support for PlayPaq with WM8510" tristate "SoC Audio support for PlayPaq with WM8510"
depends on SND_ATMEL_SOC && BOARD_PLAYPAQ depends on SND_ATMEL_SOC && BOARD_PLAYPAQ && AT91_PROGRAMMABLE_CLOCKS
select SND_ATMEL_SOC_SSC select SND_ATMEL_SOC_SSC
select SND_SOC_WM8510 select SND_SOC_WM8510
help help

View file

@ -28,6 +28,11 @@
#include <sound/max98088.h> #include <sound/max98088.h>
#include "max98088.h" #include "max98088.h"
enum max98088_type {
MAX98088,
MAX98089,
};
struct max98088_cdata { struct max98088_cdata {
unsigned int rate; unsigned int rate;
unsigned int fmt; unsigned int fmt;
@ -36,6 +41,7 @@ struct max98088_cdata {
struct max98088_priv { struct max98088_priv {
u8 reg_cache[M98088_REG_CNT]; u8 reg_cache[M98088_REG_CNT];
enum max98088_type devtype;
void *control_data; void *control_data;
struct max98088_pdata *pdata; struct max98088_pdata *pdata;
unsigned int sysclk; unsigned int sysclk;
@ -2040,6 +2046,8 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
if (max98088 == NULL) if (max98088 == NULL)
return -ENOMEM; return -ENOMEM;
max98088->devtype = id->driver_data;
i2c_set_clientdata(i2c, max98088); i2c_set_clientdata(i2c, max98088);
max98088->control_data = i2c; max98088->control_data = i2c;
max98088->pdata = i2c->dev.platform_data; max98088->pdata = i2c->dev.platform_data;
@ -2059,7 +2067,8 @@ static int __devexit max98088_i2c_remove(struct i2c_client *client)
} }
static const struct i2c_device_id max98088_i2c_id[] = { static const struct i2c_device_id max98088_i2c_id[] = {
{ "max98088", 0 }, { "max98088", MAX98088 },
{ "max98089", MAX98089 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);

View file

@ -597,6 +597,7 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
.resume = uda134x_soc_resume, .resume = uda134x_soc_resume,
.reg_cache_size = sizeof(uda134x_reg), .reg_cache_size = sizeof(uda134x_reg),
.reg_word_size = sizeof(u8), .reg_word_size = sizeof(u8),
.reg_cache_default = uda134x_reg,
.reg_cache_step = 1, .reg_cache_step = 1,
.read = uda134x_read_reg_cache, .read = uda134x_read_reg_cache,
.write = uda134x_write, .write = uda134x_write,

View file

@ -831,7 +831,7 @@ static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
} }
/* MCLK direction */ /* MCLK direction */
if (dir == WM8350_MCLK_DIR_OUT) if (dir == SND_SOC_CLOCK_OUT)
wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_2, wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_2,
WM8350_MCLK_DIR); WM8350_MCLK_DIR);
else else
@ -1586,6 +1586,13 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME,
WM8350_OUT2_VU | WM8350_OUT2R_MUTE); WM8350_OUT2_VU | WM8350_OUT2R_MUTE);
/* Make sure AIF tristating is disabled by default */
wm8350_clear_bits(wm8350, WM8350_AI_FORMATING, WM8350_AIF_TRI);
/* Make sure we've got a sane companding setup too */
wm8350_clear_bits(wm8350, WM8350_ADC_DAC_COMP,
WM8350_DAC_COMP | WM8350_LOOPBACK);
/* Make sure jack detect is disabled to start off with */ /* Make sure jack detect is disabled to start off with */
wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
WM8350_JDL_ENA | WM8350_JDR_ENA); WM8350_JDL_ENA | WM8350_JDR_ENA);

View file

@ -34,7 +34,6 @@
/* codec private data */ /* codec private data */
struct wm8776_priv { struct wm8776_priv {
enum snd_soc_control_type control_type; enum snd_soc_control_type control_type;
u16 reg_cache[WM8776_CACHEREGNUM];
int sysclk[2]; int sysclk[2];
}; };

View file

@ -3500,8 +3500,11 @@ static ssize_t wm8962_beep_set(struct device *dev,
{ {
struct wm8962_priv *wm8962 = dev_get_drvdata(dev); struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
long int time; long int time;
int ret;
strict_strtol(buf, 10, &time); ret = strict_strtol(buf, 10, &time);
if (ret != 0)
return ret;
input_event(wm8962->beep, EV_SND, SND_TONE, time); input_event(wm8962->beep, EV_SND, SND_TONE, time);

View file

@ -3903,6 +3903,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
return -ENOMEM; return -ENOMEM;
snd_soc_codec_set_drvdata(codec, wm8994); snd_soc_codec_set_drvdata(codec, wm8994);
codec->reg_cache = &wm8994->reg_cache;
wm8994->pdata = dev_get_platdata(codec->dev->parent); wm8994->pdata = dev_get_platdata(codec->dev->parent);
wm8994->codec = codec; wm8994->codec = codec;

View file

@ -157,12 +157,23 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
} }
/* davinci-evm digital audio interface glue - connects codec <--> CPU */ /* davinci-evm digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link evm_dai = { static struct snd_soc_dai_link dm6446_evm_dai = {
.name = "TLV320AIC3X", .name = "TLV320AIC3X",
.stream_name = "AIC3X", .stream_name = "AIC3X",
.cpu_dai_name = "davinci-mcasp.0", .cpu_dai_name = "davinci-mcbsp",
.codec_dai_name = "tlv320aic3x-hifi", .codec_dai_name = "tlv320aic3x-hifi",
.codec_name = "tlv320aic3x-codec.0-001a", .codec_name = "tlv320aic3x-codec.1-001b",
.platform_name = "davinci-pcm-audio",
.init = evm_aic3x_init,
.ops = &evm_ops,
};
static struct snd_soc_dai_link dm355_evm_dai = {
.name = "TLV320AIC3X",
.stream_name = "AIC3X",
.cpu_dai_name = "davinci-mcbsp.1",
.codec_dai_name = "tlv320aic3x-hifi",
.codec_name = "tlv320aic3x-codec.1-001b",
.platform_name = "davinci-pcm-audio", .platform_name = "davinci-pcm-audio",
.init = evm_aic3x_init, .init = evm_aic3x_init,
.ops = &evm_ops, .ops = &evm_ops,
@ -172,10 +183,10 @@ static struct snd_soc_dai_link dm365_evm_dai = {
#ifdef CONFIG_SND_DM365_AIC3X_CODEC #ifdef CONFIG_SND_DM365_AIC3X_CODEC
.name = "TLV320AIC3X", .name = "TLV320AIC3X",
.stream_name = "AIC3X", .stream_name = "AIC3X",
.cpu_dai_name = "davinci-i2s", .cpu_dai_name = "davinci-mcbsp",
.codec_dai_name = "tlv320aic3x-hifi", .codec_dai_name = "tlv320aic3x-hifi",
.init = evm_aic3x_init, .init = evm_aic3x_init,
.codec_name = "tlv320aic3x-codec.0-001a", .codec_name = "tlv320aic3x-codec.1-0018",
.ops = &evm_ops, .ops = &evm_ops,
#elif defined(CONFIG_SND_DM365_VOICE_CODEC) #elif defined(CONFIG_SND_DM365_VOICE_CODEC)
.name = "Voice Codec - CQ93VC", .name = "Voice Codec - CQ93VC",
@ -219,10 +230,17 @@ static struct snd_soc_dai_link da8xx_evm_dai = {
.ops = &evm_ops, .ops = &evm_ops,
}; };
/* davinci dm6446, dm355 evm audio machine driver */ /* davinci dm6446 evm audio machine driver */
static struct snd_soc_card snd_soc_card_evm = { static struct snd_soc_card dm6446_snd_soc_card_evm = {
.name = "DaVinci EVM", .name = "DaVinci DM6446 EVM",
.dai_link = &evm_dai, .dai_link = &dm6446_evm_dai,
.num_links = 1,
};
/* davinci dm355 evm audio machine driver */
static struct snd_soc_card dm355_snd_soc_card_evm = {
.name = "DaVinci DM355 EVM",
.dai_link = &dm355_evm_dai,
.num_links = 1, .num_links = 1,
}; };
@ -261,10 +279,10 @@ static int __init evm_init(void)
int ret; int ret;
if (machine_is_davinci_evm()) { if (machine_is_davinci_evm()) {
evm_snd_dev_data = &snd_soc_card_evm; evm_snd_dev_data = &dm6446_snd_soc_card_evm;
index = 0; index = 0;
} else if (machine_is_davinci_dm355_evm()) { } else if (machine_is_davinci_dm355_evm()) {
evm_snd_dev_data = &snd_soc_card_evm; evm_snd_dev_data = &dm355_snd_soc_card_evm;
index = 1; index = 1;
} else if (machine_is_davinci_dm365_evm()) { } else if (machine_is_davinci_dm365_evm()) {
evm_snd_dev_data = &dm365_snd_soc_card_evm; evm_snd_dev_data = &dm365_snd_soc_card_evm;

View file

@ -426,9 +426,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
snd_pcm_format_t fmt; snd_pcm_format_t fmt;
unsigned element_cnt = 1; unsigned element_cnt = 1;
dai->capture_dma_data = dev->dma_params;
dai->playback_dma_data = dev->dma_params;
/* general line settings */ /* general line settings */
spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
@ -601,6 +598,15 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
return ret; return ret;
} }
static int davinci_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
return 0;
}
static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
@ -612,6 +618,7 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000
static struct snd_soc_dai_ops davinci_i2s_dai_ops = { static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
.startup = davinci_i2s_startup,
.shutdown = davinci_i2s_shutdown, .shutdown = davinci_i2s_shutdown,
.prepare = davinci_i2s_prepare, .prepare = davinci_i2s_prepare,
.trigger = davinci_i2s_trigger, .trigger = davinci_i2s_trigger,
@ -749,7 +756,7 @@ static struct platform_driver davinci_mcbsp_driver = {
.probe = davinci_i2s_probe, .probe = davinci_i2s_probe,
.remove = davinci_i2s_remove, .remove = davinci_i2s_remove,
.driver = { .driver = {
.name = "davinci-i2s", .name = "davinci-mcbsp",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
}; };

View file

@ -715,9 +715,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
int word_length; int word_length;
u8 fifo_level; u8 fifo_level;
cpu_dai->capture_dma_data = dev->dma_params;
cpu_dai->playback_dma_data = dev->dma_params;
davinci_hw_common_param(dev, substream->stream); davinci_hw_common_param(dev, substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
fifo_level = dev->txnumevt; fifo_level = dev->txnumevt;
@ -799,7 +796,17 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
return ret; return ret;
} }
static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
return 0;
}
static struct snd_soc_dai_ops davinci_mcasp_dai_ops = { static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
.startup = davinci_mcasp_startup,
.trigger = davinci_mcasp_trigger, .trigger = davinci_mcasp_trigger,
.hw_params = davinci_mcasp_hw_params, .hw_params = davinci_mcasp_hw_params,
.set_fmt = davinci_mcasp_set_dai_fmt, .set_fmt = davinci_mcasp_set_dai_fmt,

View file

@ -84,7 +84,7 @@ static struct snd_soc_ops sffsdr_ops = {
static struct snd_soc_dai_link sffsdr_dai = { static struct snd_soc_dai_link sffsdr_dai = {
.name = "PCM3008", /* Codec name */ .name = "PCM3008", /* Codec name */
.stream_name = "PCM3008 HiFi", .stream_name = "PCM3008 HiFi",
.cpu_dai_name = "davinci-asp.0", .cpu_dai_name = "davinci-mcbsp",
.codec_dai_name = "pcm3008-hifi", .codec_dai_name = "pcm3008-hifi",
.codec_name = "pcm3008-codec", .codec_name = "pcm3008-codec",
.platform_name = "davinci-pcm-audio", .platform_name = "davinci-pcm-audio",

View file

@ -97,9 +97,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
&davinci_vcif_dev->dma_params[substream->stream]; &davinci_vcif_dev->dma_params[substream->stream];
u32 w; u32 w;
dai->capture_dma_data = davinci_vcif_dev->dma_params;
dai->playback_dma_data = davinci_vcif_dev->dma_params;
/* Restart the codec before setup */ /* Restart the codec before setup */
davinci_vcif_stop(substream); davinci_vcif_stop(substream);
davinci_vcif_start(substream); davinci_vcif_start(substream);
@ -174,9 +171,19 @@ static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd,
return ret; return ret;
} }
static int davinci_vcif_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct davinci_vcif_dev *dev = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
return 0;
}
#define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000 #define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000
static struct snd_soc_dai_ops davinci_vcif_dai_ops = { static struct snd_soc_dai_ops davinci_vcif_dai_ops = {
.startup = davinci_vcif_startup,
.trigger = davinci_vcif_trigger, .trigger = davinci_vcif_trigger,
.hw_params = davinci_vcif_hw_params, .hw_params = davinci_vcif_hw_params,
}; };

View file

@ -160,7 +160,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op,
rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
if (rc != 0) { if (rc != 0) {
pr_err("Failed to register DAI\n"); pr_err("Failed to register DAI\n");
return 0; return rc;
} }
psc_dma = dev_get_drvdata(&op->dev); psc_dma = dev_get_drvdata(&op->dev);

View file

@ -34,8 +34,8 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret; int ret;
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
@ -79,10 +79,10 @@ static struct snd_soc_ops eukrea_tlv320_snd_ops = {
static struct snd_soc_dai_link eukrea_tlv320_dai = { static struct snd_soc_dai_link eukrea_tlv320_dai = {
.name = "tlv320aic23", .name = "tlv320aic23",
.stream_name = "TLV320AIC23", .stream_name = "TLV320AIC23",
.codec_dai = "tlv320aic23-hifi", .codec_dai_name = "tlv320aic23-hifi",
.platform_name = "imx-pcm-audio.0", .platform_name = "imx-pcm-audio.0",
.codec_name = "tlv320aic23-codec.0-001a", .codec_name = "tlv320aic23-codec.0-001a",
.cpu_dai = "imx-ssi.0", .cpu_dai_name = "imx-ssi.0",
.ops = &eukrea_tlv320_snd_ops, .ops = &eukrea_tlv320_snd_ops,
}; };

View file

@ -20,6 +20,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dmaengine.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/initval.h> #include <sound/initval.h>
@ -27,165 +28,146 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <mach/dma-mx1-mx2.h> #include <mach/dma.h>
#include "imx-ssi.h" #include "imx-ssi.h"
struct imx_pcm_runtime_data { struct imx_pcm_runtime_data {
int sg_count; int period_bytes;
struct scatterlist *sg_list;
int period;
int periods; int periods;
unsigned long dma_addr;
int dma; int dma;
struct snd_pcm_substream *substream;
unsigned long offset; unsigned long offset;
unsigned long size; unsigned long size;
unsigned long period_cnt;
void *buf; void *buf;
int period_time; int period_time;
struct dma_async_tx_descriptor *desc;
struct dma_chan *dma_chan;
struct imx_dma_data dma_data;
}; };
/* Called by the DMA framework when a period has elapsed */ static void audio_dma_irq(void *data)
static void imx_ssi_dma_progression(int channel, void *data,
struct scatterlist *sg)
{ {
struct snd_pcm_substream *substream = data; struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data; struct imx_pcm_runtime_data *iprtd = runtime->private_data;
if (!sg) iprtd->offset += iprtd->period_bytes;
return; iprtd->offset %= iprtd->period_bytes * iprtd->periods;
runtime = iprtd->substream->runtime; snd_pcm_period_elapsed(substream);
iprtd->offset = sg->dma_address - runtime->dma_addr;
snd_pcm_period_elapsed(iprtd->substream);
} }
static void imx_ssi_dma_callback(int channel, void *data) static bool filter(struct dma_chan *chan, void *param)
{ {
pr_err("%s shouldn't be called\n", __func__); struct imx_pcm_runtime_data *iprtd = param;
if (!imx_dma_is_general_purpose(chan))
return false;
chan->private = &iprtd->dma_data;
return true;
} }
static void snd_imx_dma_err_callback(int channel, void *data, int err) static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
{ struct snd_pcm_hw_params *params)
struct snd_pcm_substream *substream = data;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct imx_pcm_dma_params *dma_params =
snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
int ret;
pr_err("DMA timeout on channel %d -%s%s%s%s\n",
channel,
err & IMX_DMA_ERR_BURST ? " burst" : "",
err & IMX_DMA_ERR_REQUEST ? " request" : "",
err & IMX_DMA_ERR_TRANSFER ? " transfer" : "",
err & IMX_DMA_ERR_BUFFER ? " buffer" : "");
imx_dma_disable(iprtd->dma);
ret = imx_dma_setup_sg(iprtd->dma, iprtd->sg_list, iprtd->sg_count,
IMX_DMA_LENGTH_LOOP, dma_params->dma_addr,
substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
DMA_MODE_WRITE : DMA_MODE_READ);
if (!ret)
imx_dma_enable(iprtd->dma);
}
static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct imx_pcm_dma_params *dma_params; struct imx_pcm_dma_params *dma_params;
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data; struct imx_pcm_runtime_data *iprtd = runtime->private_data;
struct dma_slave_config slave_config;
dma_cap_mask_t mask;
enum dma_slave_buswidth buswidth;
int ret; int ret;
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH); iprtd->dma_data.peripheral_type = IMX_DMATYPE_SSI;
if (iprtd->dma < 0) { iprtd->dma_data.priority = DMA_PRIO_HIGH;
pr_err("Failed to claim the audio DMA\n"); iprtd->dma_data.dma_request = dma_params->dma;
return -ENODEV;
/* Try to grab a DMA channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
if (!iprtd->dma_chan)
return -EINVAL;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S24_LE:
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
default:
return 0;
} }
ret = imx_dma_setup_handlers(iprtd->dma, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
imx_ssi_dma_callback, slave_config.direction = DMA_TO_DEVICE;
snd_imx_dma_err_callback, substream); slave_config.dst_addr = dma_params->dma_addr;
slave_config.dst_addr_width = buswidth;
slave_config.dst_maxburst = dma_params->burstsize;
} else {
slave_config.direction = DMA_FROM_DEVICE;
slave_config.src_addr = dma_params->dma_addr;
slave_config.src_addr_width = buswidth;
slave_config.src_maxburst = dma_params->burstsize;
}
ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config);
if (ret) if (ret)
goto out; return ret;
ret = imx_dma_setup_progression_handler(iprtd->dma,
imx_ssi_dma_progression);
if (ret) {
pr_err("Failed to setup the DMA handler\n");
goto out;
}
ret = imx_dma_config_channel(iprtd->dma,
IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
dma_params->dma, 1);
if (ret < 0) {
pr_err("Cannot configure DMA channel: %d\n", ret);
goto out;
}
imx_dma_config_burstlen(iprtd->dma, dma_params->burstsize * 2);
return 0; return 0;
out:
imx_dma_free(iprtd->dma);
return ret;
} }
static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data; struct imx_pcm_runtime_data *iprtd = runtime->private_data;
int i;
unsigned long dma_addr; unsigned long dma_addr;
struct dma_chan *chan;
struct imx_pcm_dma_params *dma_params;
int ret;
imx_ssi_dma_alloc(substream); dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
ret = imx_ssi_dma_alloc(substream, params);
if (ret)
return ret;
chan = iprtd->dma_chan;
iprtd->size = params_buffer_bytes(params); iprtd->size = params_buffer_bytes(params);
iprtd->periods = params_periods(params); iprtd->periods = params_periods(params);
iprtd->period = params_period_bytes(params); iprtd->period_bytes = params_period_bytes(params);
iprtd->offset = 0; iprtd->offset = 0;
iprtd->period_time = HZ / (params_rate(params) / iprtd->period_time = HZ / (params_rate(params) /
params_period_size(params)); params_period_size(params));
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
if (iprtd->sg_count != iprtd->periods) {
kfree(iprtd->sg_list);
iprtd->sg_list = kcalloc(iprtd->periods + 1,
sizeof(struct scatterlist), GFP_KERNEL);
if (!iprtd->sg_list)
return -ENOMEM;
iprtd->sg_count = iprtd->periods + 1;
}
sg_init_table(iprtd->sg_list, iprtd->sg_count);
dma_addr = runtime->dma_addr; dma_addr = runtime->dma_addr;
for (i = 0; i < iprtd->periods; i++) { iprtd->buf = (unsigned int *)substream->dma_buffer.area;
iprtd->sg_list[i].page_link = 0;
iprtd->sg_list[i].offset = 0; iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
iprtd->sg_list[i].dma_address = dma_addr; iprtd->period_bytes * iprtd->periods,
iprtd->sg_list[i].length = iprtd->period; iprtd->period_bytes,
dma_addr += iprtd->period; substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (!iprtd->desc) {
dev_err(&chan->dev->device, "cannot prepare slave dma\n");
return -EINVAL;
} }
/* close the loop */ iprtd->desc->callback = audio_dma_irq;
iprtd->sg_list[iprtd->sg_count - 1].offset = 0; iprtd->desc->callback_param = substream;
iprtd->sg_list[iprtd->sg_count - 1].length = 0;
iprtd->sg_list[iprtd->sg_count - 1].page_link =
((unsigned long) iprtd->sg_list | 0x01) & ~0x02;
return 0; return 0;
} }
@ -194,41 +176,21 @@ static int snd_imx_pcm_hw_free(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data; struct imx_pcm_runtime_data *iprtd = runtime->private_data;
if (iprtd->dma >= 0) { if (iprtd->dma_chan) {
imx_dma_free(iprtd->dma); dma_release_channel(iprtd->dma_chan);
iprtd->dma = -EINVAL; iprtd->dma_chan = NULL;
} }
kfree(iprtd->sg_list);
iprtd->sg_list = NULL;
return 0; return 0;
} }
static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream) static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct imx_pcm_dma_params *dma_params; struct imx_pcm_dma_params *dma_params;
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
int err;
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
iprtd->substream = substream;
iprtd->buf = (unsigned int *)substream->dma_buffer.area;
iprtd->period_cnt = 0;
pr_debug("%s: buf: %p period: %d periods: %d\n",
__func__, iprtd->buf, iprtd->period, iprtd->periods);
err = imx_dma_setup_sg(iprtd->dma, iprtd->sg_list, iprtd->sg_count,
IMX_DMA_LENGTH_LOOP, dma_params->dma_addr,
substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
DMA_MODE_WRITE : DMA_MODE_READ);
if (err)
return err;
return 0; return 0;
} }
@ -241,14 +203,14 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
imx_dma_enable(iprtd->dma); dmaengine_submit(iprtd->desc);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
imx_dma_disable(iprtd->dma); dmaengine_terminate_all(iprtd->dma_chan);
break; break;
default: default:
@ -263,6 +225,9 @@ static snd_pcm_uframes_t snd_imx_pcm_pointer(struct snd_pcm_substream *substream
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data; struct imx_pcm_runtime_data *iprtd = runtime->private_data;
pr_debug("%s: %ld %ld\n", __func__, iprtd->offset,
bytes_to_frames(substream->runtime, iprtd->offset));
return bytes_to_frames(substream->runtime, iprtd->offset); return bytes_to_frames(substream->runtime, iprtd->offset);
} }
@ -279,7 +244,7 @@ static struct snd_pcm_hardware snd_imx_hardware = {
.channels_max = 2, .channels_max = 2,
.buffer_bytes_max = IMX_SSI_DMABUF_SIZE, .buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
.period_bytes_min = 128, .period_bytes_min = 128,
.period_bytes_max = 16 * 1024, .period_bytes_max = 65535, /* Limited by SDMA engine */
.periods_min = 2, .periods_min = 2,
.periods_max = 255, .periods_max = 255,
.fifo_size = 0, .fifo_size = 0,
@ -304,11 +269,23 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
} }
snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
return 0;
}
static int snd_imx_close(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
kfree(iprtd);
return 0; return 0;
} }
static struct snd_pcm_ops imx_pcm_ops = { static struct snd_pcm_ops imx_pcm_ops = {
.open = snd_imx_open, .open = snd_imx_open,
.close = snd_imx_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_imx_pcm_hw_params, .hw_params = snd_imx_pcm_hw_params,
.hw_free = snd_imx_pcm_hw_free, .hw_free = snd_imx_pcm_hw_free,
@ -340,7 +317,6 @@ static struct platform_driver imx_pcm_driver = {
.name = "imx-pcm-audio", .name = "imx-pcm-audio",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = imx_soc_platform_probe, .probe = imx_soc_platform_probe,
.remove = __devexit_p(imx_soc_platform_remove), .remove = __devexit_p(imx_soc_platform_remove),
}; };
@ -356,4 +332,3 @@ static void __exit snd_imx_pcm_exit(void)
platform_driver_unregister(&imx_pcm_driver); platform_driver_unregister(&imx_pcm_driver);
} }
module_exit(snd_imx_pcm_exit); module_exit(snd_imx_pcm_exit);

View file

@ -439,7 +439,22 @@ void imx_pcm_free(struct snd_pcm *pcm)
} }
EXPORT_SYMBOL_GPL(imx_pcm_free); EXPORT_SYMBOL_GPL(imx_pcm_free);
static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
{
struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
uint32_t val;
snd_soc_dai_set_drvdata(dai, ssi);
val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
writel(val, ssi->base + SSI_SFCSR);
return 0;
}
static struct snd_soc_dai_driver imx_ssi_dai = { static struct snd_soc_dai_driver imx_ssi_dai = {
.probe = imx_ssi_dai_probe,
.playback = { .playback = {
.channels_min = 2, .channels_min = 2,
.channels_max = 2, .channels_max = 2,
@ -455,20 +470,6 @@ static struct snd_soc_dai_driver imx_ssi_dai = {
.ops = &imx_ssi_pcm_dai_ops, .ops = &imx_ssi_pcm_dai_ops,
}; };
static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
{
struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
uint32_t val;
snd_soc_dai_set_drvdata(dai, ssi);
val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
writel(val, ssi->base + SSI_SFCSR);
return 0;
}
static struct snd_soc_dai_driver imx_ac97_dai = { static struct snd_soc_dai_driver imx_ac97_dai = {
.probe = imx_ssi_dai_probe, .probe = imx_ssi_dai_probe,
.ac97_control = 1, .ac97_control = 1,
@ -677,7 +678,17 @@ static int imx_ssi_probe(struct platform_device *pdev)
goto failed_register; goto failed_register;
} }
ssi->soc_platform_pdev = platform_device_alloc("imx-fiq-pcm-audio", pdev->id); ssi->soc_platform_pdev_fiq = platform_device_alloc("imx-fiq-pcm-audio", pdev->id);
if (!ssi->soc_platform_pdev_fiq)
goto failed_pdev_fiq_alloc;
platform_set_drvdata(ssi->soc_platform_pdev_fiq, ssi);
ret = platform_device_add(ssi->soc_platform_pdev_fiq);
if (ret) {
dev_err(&pdev->dev, "failed to add platform device\n");
goto failed_pdev_fiq_add;
}
ssi->soc_platform_pdev = platform_device_alloc("imx-pcm-audio", pdev->id);
if (!ssi->soc_platform_pdev) if (!ssi->soc_platform_pdev)
goto failed_pdev_alloc; goto failed_pdev_alloc;
platform_set_drvdata(ssi->soc_platform_pdev, ssi); platform_set_drvdata(ssi->soc_platform_pdev, ssi);
@ -692,6 +703,9 @@ static int imx_ssi_probe(struct platform_device *pdev)
failed_pdev_add: failed_pdev_add:
platform_device_put(ssi->soc_platform_pdev); platform_device_put(ssi->soc_platform_pdev);
failed_pdev_alloc: failed_pdev_alloc:
failed_pdev_fiq_add:
platform_device_put(ssi->soc_platform_pdev_fiq);
failed_pdev_fiq_alloc:
snd_soc_unregister_dai(&pdev->dev); snd_soc_unregister_dai(&pdev->dev);
failed_register: failed_register:
failed_ac97: failed_ac97:

View file

@ -185,6 +185,9 @@
#define DRV_NAME "imx-ssi" #define DRV_NAME "imx-ssi"
#include <linux/dmaengine.h>
#include <mach/dma.h>
struct imx_pcm_dma_params { struct imx_pcm_dma_params {
int dma; int dma;
unsigned long dma_addr; unsigned long dma_addr;
@ -212,6 +215,7 @@ struct imx_ssi {
int enabled; int enabled;
struct platform_device *soc_platform_pdev; struct platform_device *soc_platform_pdev;
struct platform_device *soc_platform_pdev_fiq;
}; };
struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,

View file

@ -20,9 +20,6 @@
#include <sound/soc-dapm.h> #include <sound/soc-dapm.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include "../codecs/wm9712.h"
#include "imx-ssi.h"
static struct snd_soc_card imx_phycore; static struct snd_soc_card imx_phycore;
static struct snd_soc_ops imx_phycore_hifi_ops = { static struct snd_soc_ops imx_phycore_hifi_ops = {
@ -41,7 +38,7 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = {
}; };
static struct snd_soc_card imx_phycore = { static struct snd_soc_card imx_phycore = {
.name = "PhyCORE-audio", .name = "PhyCORE-ac97-audio",
.dai_link = imx_phycore_dai_ac97, .dai_link = imx_phycore_dai_ac97,
.num_links = ARRAY_SIZE(imx_phycore_dai_ac97), .num_links = ARRAY_SIZE(imx_phycore_dai_ac97),
}; };

View file

@ -644,15 +644,23 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
case OMAP_MCBSP_CLKR_SRC_CLKR: case OMAP_MCBSP_CLKR_SRC_CLKR:
if (cpu_class_is_omap1())
break;
omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR); omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
break; break;
case OMAP_MCBSP_CLKR_SRC_CLKX: case OMAP_MCBSP_CLKR_SRC_CLKX:
if (cpu_class_is_omap1())
break;
omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX); omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
break; break;
case OMAP_MCBSP_FSR_SRC_FSR: case OMAP_MCBSP_FSR_SRC_FSR:
if (cpu_class_is_omap1())
break;
omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR); omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
break; break;
case OMAP_MCBSP_FSR_SRC_FSX: case OMAP_MCBSP_FSR_SRC_FSX:
if (cpu_class_is_omap1())
break;
omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX); omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
break; break;
default: default:

View file

@ -100,8 +100,13 @@ static int corgi_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */ /* check the jack status at stream startup */
corgi_ext_control(codec); corgi_ext_control(codec);
mutex_unlock(&codec->mutex);
return 0; return 0;
} }

View file

@ -72,9 +72,13 @@ static int magician_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */ /* check the jack status at stream startup */
magician_ext_control(codec); magician_ext_control(codec);
mutex_unlock(&codec->mutex);
return 0; return 0;
} }

View file

@ -77,8 +77,13 @@ static int poodle_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */ /* check the jack status at stream startup */
poodle_ext_control(codec); poodle_ext_control(codec);
mutex_unlock(&codec->mutex);
return 0; return 0;
} }

View file

@ -108,8 +108,13 @@ static int spitz_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */ /* check the jack status at stream startup */
spitz_ext_control(codec); spitz_ext_control(codec);
mutex_unlock(&codec->mutex);
return 0; return 0;
} }

View file

@ -81,8 +81,13 @@ static int tosa_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */ /* check the jack status at stream startup */
tosa_ext_control(codec); tosa_ext_control(codec);
mutex_unlock(&codec->mutex);
return 0; return 0;
} }

View file

@ -2,6 +2,7 @@ config SND_S3C24XX_SOC
tristate "SoC Audio for the Samsung S3CXXXX chips" tristate "SoC Audio for the Samsung S3CXXXX chips"
depends on ARCH_S3C2410 || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 depends on ARCH_S3C2410 || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210
select S3C64XX_DMA if ARCH_S3C64XX select S3C64XX_DMA if ARCH_S3C64XX
select S3C2410_DMA if ARCH_S3C2410
help help
Say Y or M if you want to add support for codecs attached to Say Y or M if you want to add support for codecs attached to
the S3C24XX AC97 or I2S interfaces. You will also need to the S3C24XX AC97 or I2S interfaces. You will also need to

View file

@ -50,7 +50,6 @@ static unsigned int rates[] = {
16000, 16000,
44100, 44100,
48000, 48000,
88200,
}; };
static struct snd_pcm_hw_constraint_list hw_rates = { static struct snd_pcm_hw_constraint_list hw_rates = {
@ -130,7 +129,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
}; };
static struct platform_device *s3c24xx_snd_device; static struct platform_device *s3c24xx_snd_device;
static struct clk *xtal;
static int rx1950_startup(struct snd_pcm_substream *substream) static int rx1950_startup(struct snd_pcm_substream *substream)
{ {
@ -179,10 +177,8 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream,
case 44100: case 44100:
case 88200: case 88200:
clk_source = S3C24XX_CLKSRC_MPLL; clk_source = S3C24XX_CLKSRC_MPLL;
fs_mode = S3C2410_IISMOD_256FS; fs_mode = S3C2410_IISMOD_384FS;
div = clk_get_rate(xtal) / (256 * rate); div = 1;
if (clk_get_rate(xtal) % (256 * rate) > (128 * rate))
div++;
break; break;
default: default:
printk(KERN_ERR "%s: rate %d is not supported\n", printk(KERN_ERR "%s: rate %d is not supported\n",
@ -210,7 +206,7 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream,
/* set MCLK division for sample rate */ /* set MCLK division for sample rate */
ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
S3C2410_IISMOD_384FS); fs_mode);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -295,17 +291,8 @@ static int __init rx1950_init(void)
goto err_plat_add; goto err_plat_add;
} }
xtal = clk_get(&s3c24xx_snd_device->dev, "xtal");
if (IS_ERR(xtal)) {
ret = PTR_ERR(xtal);
platform_device_unregister(s3c24xx_snd_device);
goto err_clk;
}
return 0; return 0;
err_clk:
err_plat_add: err_plat_add:
err_plat_alloc: err_plat_alloc:
err_gpio_conf: err_gpio_conf:
@ -320,7 +307,6 @@ static void __exit rx1950_exit(void)
platform_device_unregister(s3c24xx_snd_device); platform_device_unregister(s3c24xx_snd_device);
snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
hp_jack_gpios); hp_jack_gpios);
clk_put(xtal);
gpio_free(S3C2410_GPA(1)); gpio_free(S3C2410_GPA(1));
} }

View file

@ -3043,8 +3043,10 @@ int snd_soc_register_dais(struct device *dev,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
if (dai == NULL) if (dai == NULL) {
return -ENOMEM; ret = -ENOMEM;
goto err;
}
/* create DAI component name */ /* create DAI component name */
dai->name = fmt_multiple_name(dev, &dai_drv[i]); dai->name = fmt_multiple_name(dev, &dai_drv[i]);
@ -3263,9 +3265,6 @@ int snd_soc_register_codec(struct device *dev,
return 0; return 0;
error: error:
for (i--; i >= 0; i--)
snd_soc_unregister_dai(dev);
if (codec->reg_cache) if (codec->reg_cache)
kfree(codec->reg_cache); kfree(codec->reg_cache);
kfree(codec->name); kfree(codec->name);

View file

@ -683,12 +683,12 @@ static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
struct snd_soc_dapm_widget *b, struct snd_soc_dapm_widget *b,
int sort[]) int sort[])
{ {
if (a->codec != b->codec)
return (unsigned long)a - (unsigned long)b;
if (sort[a->id] != sort[b->id]) if (sort[a->id] != sort[b->id])
return sort[a->id] - sort[b->id]; return sort[a->id] - sort[b->id];
if (a->reg != b->reg) if (a->reg != b->reg)
return a->reg - b->reg; return a->reg - b->reg;
if (a->codec != b->codec)
return (unsigned long)a->codec - (unsigned long)b->codec;
return 0; return 0;
} }