summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorChen Liangjun <b36089@freescale.com>2012-07-29 21:33:04 +0800
committerChen Liangjun <b36089@freescale.com>2012-07-30 16:57:25 +0800
commit253214e27a09c3320423b5274be00c3416b48c1a (patch)
tree76a8519f61ea0e2a3f192c7286b847140354f910 /sound
parent238d8d1281485f65b8a6b56df638476f5cb22db7 (diff)
ENGR00218421-2 ESAI_ASRC:Add support for p2p virtual device playback
In the origin code, ESAI driver supoprt audio p2p playback by setting input PCM data's sample rate thought amixer interface.It is ugly and request user application call amixer control interface everytime before and playback. In this patch, user can call the audio p2p playback by writing data to an special virtual device. Driver would automatically get the params of input PCM. At the same time, driver would get the output sample rate and word data. With the data abover, driver can set ASRC properly and audio p2p palyback is support. This patch mainly focus on: 1 clean old p2p playback way for ESAI. 2 Setup the output sample rate and word width to virtual device's substream_runtime's private data. Everytime the virtual device is called, the data abover is used for config ASRC, ESAI, and codec. Signed-off-by: Chen Liangjun <b36089@freescale.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/cs42888.c7
-rw-r--r--sound/soc/imx/imx-cs42888.c136
-rw-r--r--sound/soc/imx/imx-esai.c2
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c8
-rw-r--r--sound/soc/imx/imx-pcm.h4
5 files changed, 48 insertions, 109 deletions
diff --git a/sound/soc/codecs/cs42888.c b/sound/soc/codecs/cs42888.c
index cc802e0e71c2..73571dafa9a4 100644
--- a/sound/soc/codecs/cs42888.c
+++ b/sound/soc/codecs/cs42888.c
@@ -34,6 +34,7 @@
#include <asm/div64.h>
#include "cs42888.h"
+#include "../imx/imx-pcm.h"
#define CS42888_NUM_SUPPLIES 4
static const char *cs42888_supply_names[CS42888_NUM_SUPPLIES] = {
"VA",
@@ -664,6 +665,7 @@ static int cs42888_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct imx_pcm_runtime_data *iprtd = substream->runtime->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
int ret;
@@ -672,7 +674,10 @@ static int cs42888_hw_params(struct snd_pcm_substream *substream,
unsigned int ratio;
u32 val;
- rate = params_rate(params); /* Sampling rate, in Hz */
+ if (iprtd->asrc_enable)
+ rate = iprtd->p2p->p2p_rate;
+ else
+ rate = params_rate(params); /* Sampling rate, in Hz */
ratio = cs42888->mclk / rate; /* MCLK/LRCK ratio */
for (i = 0; i < NUM_MCLK_RATIOS; i++) {
if (cs42888_mode_ratios[i].ratio == ratio)
diff --git a/sound/soc/imx/imx-cs42888.c b/sound/soc/imx/imx-cs42888.c
index 7f4f2840db7b..5fc128a4aacb 100644
--- a/sound/soc/imx/imx-cs42888.c
+++ b/sound/soc/imx/imx-cs42888.c
@@ -39,61 +39,6 @@
#include "imx-pcm.h"
#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_IMX_HAVE_PLATFORM_IMX_ASRC)
-static unsigned int asrc_rates[] = {
- 0,
- 24000,
- 32000,
- 44100,
- 48000,
- 64000,
- 88200,
- 96000,
- 176400,
- 192000,
-};
-struct asrc_esai {
- unsigned int cpu_dai_rates;
- unsigned int codec_dai_rates;
- enum asrc_pair_index asrc_index;
- unsigned int input_sample_rate;
-};
-static struct asrc_esai asrc_esai_data;
-static bool asrc_support = 1;
-static int asrc_func;
-enum asrc_word_width asrcp2p_output_bit = ASRC_WIDTH_24_BIT;
-
-static const char *asrc_function[] = {
- "disable", "24KHz", "32KHz", "44.1KHz",
- "48KHz", "64KHz", "88.2KHz", "96KHz", "176.4KHz", "192KHz"
-};
-
-static const struct soc_enum asrc_enum[] = {
- SOC_ENUM_SINGLE_EXT(9, asrc_function),
-};
-
-static int asrc_get_rate(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- ucontrol->value.enumerated.item[0] = asrc_func;
- return 0;
-}
-
-static int asrc_set_rate(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- if (asrc_func == ucontrol->value.enumerated.item[0])
- return 0;
-
- asrc_func = ucontrol->value.enumerated.item[0];
- asrc_esai_data.input_sample_rate = asrc_rates[asrc_func];
-
- return 1;
-}
-
-static const struct snd_kcontrol_new asrc_controls[] = {
- SOC_ENUM_EXT("ASRC", asrc_enum[0], asrc_get_rate,
- asrc_set_rate),
-};
static enum asrc_word_width get_asrc_input_width(
struct snd_pcm_hw_params *params)
@@ -129,61 +74,51 @@ static int config_asrc(struct snd_pcm_substream *substream,
{
unsigned int rate = params_rate(params);
unsigned int channel = params_channels(params);
- struct imx_pcm_runtime_data *pcm_data =
+ struct imx_pcm_runtime_data *iprtd =
substream->runtime->private_data;
struct asrc_config config = {0};
int ret = 0;
- if ((rate == asrc_esai_data.input_sample_rate)
- || !asrc_func)
- return -EINVAL;
-
if ((channel != 2) && (channel != 4) && (channel != 6))
return -EINVAL;
- ret = asrc_req_pair(channel, &asrc_esai_data.asrc_index);
+ ret = asrc_req_pair(channel, &iprtd->asrc_index);
if (ret < 0) {
pr_err("Fail to request asrc pair\n");
- asrc_release_pair(asrc_esai_data.asrc_index);
- asrc_finish_conv(asrc_esai_data.asrc_index);
+ asrc_release_pair(iprtd->asrc_index);
+ asrc_finish_conv(iprtd->asrc_index);
return -EINVAL;
}
config.input_word_width = get_asrc_input_width(params);
- config.output_word_width = asrcp2p_output_bit;
- config.pair = asrc_esai_data.asrc_index;
+ config.output_word_width = iprtd->p2p->p2p_width;
+ config.pair = iprtd->asrc_index;
config.channel_num = channel;
- config.input_sample_rate = asrc_esai_data.input_sample_rate;
- config.output_sample_rate = rate;
- config.inclk = OUTCLK_ASRCK1_CLK;
+ config.input_sample_rate = rate;
+ config.output_sample_rate = iprtd->p2p->p2p_rate;
+ config.inclk = INCLK_ASRCK1_CLK;
config.outclk = OUTCLK_ESAI_TX;
ret = asrc_config_pair(&config);
if (ret < 0) {
pr_err("Fail to config asrc\n");
- asrc_release_pair(asrc_esai_data.asrc_index);
- asrc_finish_conv(asrc_esai_data.asrc_index);
+ asrc_release_pair(iprtd->asrc_index);
+ asrc_finish_conv(iprtd->asrc_index);
return ret;
}
- /*now our asrc driver only support 24bit output*/
- pcm_data->output_bit = asrcp2p_output_bit;
- pcm_data->asrc_index = asrc_esai_data.asrc_index;
- pcm_data->asrc_enable = 1;
return 0;
}
-#else
-static bool asrc_support;
#endif
struct imx_priv_state {
int hw;
};
+static struct asrc_p2p_params *esai_asrc;
static struct imx_priv_state hw_state;
unsigned int mclk_freq;
-
static int imx_3stack_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -193,14 +128,6 @@ static int imx_3stack_startup(struct snd_pcm_substream *substream)
hw_state.hw = 0;
}
- if (asrc_support) {
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- asrc_esai_data.cpu_dai_rates =
- cpu_dai->driver->playback.rates;
- asrc_esai_data.codec_dai_rates =
- codec_dai->driver->playback.rates;
- }
-
return 0;
}
@@ -208,24 +135,14 @@ static void imx_3stack_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct imx_pcm_runtime_data *iprtd = substream->runtime->private_data;
- if (asrc_support) {
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct imx_pcm_runtime_data *pcm_data =
- substream->runtime->private_data;
- if (pcm_data->asrc_enable) {
- asrc_release_pair(asrc_esai_data.asrc_index);
- asrc_finish_conv(asrc_esai_data.asrc_index);
+ if (iprtd->asrc_enable) {
+ if (iprtd->asrc_index != -1) {
+ asrc_release_pair(iprtd->asrc_index);
+ asrc_finish_conv(iprtd->asrc_index);
}
- pcm_data->asrc_enable = 0;
- asrc_esai_data.asrc_index = -1;
-
- codec_dai->driver->playback.rates =
- asrc_esai_data.codec_dai_rates;
- cpu_dai->driver->playback.rates =
- asrc_esai_data.cpu_dai_rates;
- asrc_func = 0;
- asrc_esai_data.input_sample_rate = asrc_rates[asrc_func];
+ iprtd->asrc_index = -1;
}
if (!cpu_dai->active)
@@ -238,17 +155,22 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream,
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;
+ struct imx_pcm_runtime_data *iprtd = substream->runtime->private_data;
unsigned int rate = params_rate(params);
u32 dai_format;
unsigned int lrclk_ratio = 0;
+ int err = 0;
if (hw_state.hw)
return 0;
hw_state.hw = 1;
- if (asrc_support && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
- config_asrc(substream, params);
-
+ if (iprtd->asrc_enable) {
+ err = config_asrc(substream, params);
+ if (err < 0)
+ return err;
+ rate = iprtd->p2p->p2p_rate;
+ }
if (cpu_is_mx53() || machine_is_mx6q_sabreauto()) {
switch (rate) {
case 32000:
@@ -393,6 +315,8 @@ static int imx_3stack_cs42888_init(struct snd_soc_pcm_runtime *rtd)
}
static int imx_asrc_cs42888_init(struct snd_soc_pcm_runtime *rtd)
{
+
+ snd_soc_pcm_set_drvdata(rtd, (void *)esai_asrc);
return 0;
}
@@ -451,11 +375,15 @@ static int __devinit imx_3stack_cs42888_probe(struct platform_device *pdev)
imx_3stack_dai[0].codec_name = plat_data->codec_name;
imx_3stack_dai[1].codec_name = plat_data->codec_name;
}
+ esai_asrc = kzalloc(sizeof(struct asrc_p2p_params), GFP_KERNEL);
+ memcpy(esai_asrc, plat_data->priv, sizeof(struct asrc_p2p_params));
return 0;
}
static int __devexit imx_3stack_cs42888_remove(struct platform_device *pdev)
{
+ if (esai_asrc)
+ kfree(esai_asrc);
return 0;
}
diff --git a/sound/soc/imx/imx-esai.c b/sound/soc/imx/imx-esai.c
index f11757b0e7cc..b3cba9ea53c4 100644
--- a/sound/soc/imx/imx-esai.c
+++ b/sound/soc/imx/imx-esai.c
@@ -319,7 +319,7 @@ static int imx_esai_hw_tx_params(struct snd_pcm_substream *substream,
tcr &= ESAI_TCR_TSWS_MASK;
if (iprtd->asrc_enable) {
- switch (iprtd->output_bit) {
+ switch (iprtd->p2p->p2p_width) {
case ASRC_WIDTH_16_BIT:
tfcr |= ESAI_WORD_LEN_16;
tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL16;
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 9c6dcd2a0e40..712bf7d49522 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -134,7 +134,7 @@ static int imx_ssi_asrc_dma_alloc(struct snd_pcm_substream *substream,
if (!iprtd->asrc_p2p_dma_chan)
goto error;
- switch (iprtd->output_bit) {
+ switch (iprtd->p2p->p2p_width) {
case ASRC_WIDTH_16_BIT:
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
@@ -415,12 +415,18 @@ static struct snd_pcm_hardware snd_imx_hardware = {
static int snd_imx_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct imx_pcm_runtime_data *iprtd;
int ret;
iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
if (iprtd == NULL)
return -ENOMEM;
+ if (!strcmp(rtd->dai_link->name, "HiFi_ASRC")) {
+ iprtd->asrc_enable = true;
+ iprtd->p2p =
+ (struct asrc_p2p_params *)snd_soc_pcm_get_drvdata(rtd);
+ }
runtime->private_data = iprtd;
diff --git a/sound/soc/imx/imx-pcm.h b/sound/soc/imx/imx-pcm.h
index 86d6e36dab94..c6126216a9cd 100644
--- a/sound/soc/imx/imx-pcm.h
+++ b/sound/soc/imx/imx-pcm.h
@@ -57,14 +57,14 @@ struct imx_pcm_runtime_data {
int asrc_enable;
#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_IMX_HAVE_PLATFORM_IMX_ASRC)
- int asrc_index;
+ enum asrc_pair_index asrc_index;
struct dma_async_tx_descriptor *asrc_desc;
struct dma_chan *asrc_dma_chan;
struct imx_dma_data asrc_dma_data;
struct dma_async_tx_descriptor *asrc_p2p_desc;
struct dma_chan *asrc_p2p_dma_chan;
struct imx_dma_data asrc_p2p_dma_data;
- enum asrc_word_width output_bit;
+ struct asrc_p2p_params *p2p;
#endif
};
#endif