summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/imx/imx-cs42888.c87
-rw-r--r--sound/soc/imx/imx-esai.c46
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c4
-rw-r--r--sound/soc/imx/imx-pcm.h3
4 files changed, 116 insertions, 24 deletions
diff --git a/sound/soc/imx/imx-cs42888.c b/sound/soc/imx/imx-cs42888.c
index c58af0c46f25..3fc420cbf59e 100644
--- a/sound/soc/imx/imx-cs42888.c
+++ b/sound/soc/imx/imx-cs42888.c
@@ -39,14 +39,60 @@
#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 output_sample_rate;
+ unsigned int input_sample_rate;
};
static struct asrc_esai asrc_esai_data;
static bool asrc_support = 1;
+static int asrc_func;
+
+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 int get_format_width(struct snd_pcm_hw_params *params)
{
@@ -89,7 +135,7 @@ static int config_asrc(struct snd_pcm_substream *substream,
struct asrc_config config = {0};
int ret = 0;
- if (rate <= 32000 || rate == asrc_esai_data.output_sample_rate)
+ if ((rate == asrc_esai_data.input_sample_rate) || (asrc_func == 0))
return -EINVAL;
if (channel != 2)
@@ -108,8 +154,8 @@ static int config_asrc(struct snd_pcm_substream *substream,
config.pair = asrc_esai_data.asrc_index;
config.channel_num = channel;
- config.input_sample_rate = rate;
- config.output_sample_rate = asrc_esai_data.output_sample_rate;
+ config.input_sample_rate = asrc_esai_data.input_sample_rate;
+ config.output_sample_rate = rate;
config.inclk = OUTCLK_ASRCK1_CLK;
config.word_width = wordwidth;
config.outclk = OUTCLK_ESAI_TX;
@@ -121,6 +167,8 @@ static int config_asrc(struct snd_pcm_substream *substream,
asrc_finish_conv(asrc_esai_data.asrc_index);
return ret;
}
+ /*now our asrc driver support 24bit output*/
+ pcm_data->output_bit = 24;
pcm_data->asrc_index = asrc_esai_data.asrc_index;
pcm_data->asrc_enable = 1;
@@ -178,6 +226,8 @@ static void imx_3stack_shutdown(struct snd_pcm_substream *substream)
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];
}
if (!cpu_dai->active)
@@ -198,11 +248,9 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream,
return 0;
hw_state.hw = 1;
- if (asrc_support &&
- (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
- !config_asrc(substream, params)) {
- rate = asrc_esai_data.output_sample_rate;
- }
+ if (asrc_support && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
+ config_asrc(substream, params);
+
if (cpu_is_mx53() || machine_is_mx6q_sabreauto()) {
switch (rate) {
case 32000:
@@ -339,8 +387,25 @@ static int imx_3stack_cs42888_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
- if (asrc_support)
- asrc_esai_data.output_sample_rate = 44100;
+ if (asrc_support) {
+ struct snd_card *card = codec->card->snd_card;
+ int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(asrc_controls); i++) {
+ ret = snd_ctl_add(card,
+ snd_soc_cnew(&asrc_controls[i],
+ codec, asrc_controls[i].name,
+ codec->name_prefix));
+ if (ret < 0)
+ return ret;
+ }
+ /*asrc_func is inited 0.
+ * it means asrc would not
+ * be called defaultly*/
+ asrc_func = 0;
+ asrc_esai_data.input_sample_rate = asrc_rates[asrc_func];
+ }
snd_soc_dapm_new_controls(&codec->dapm, imx_3stack_dapm_widgets,
ARRAY_SIZE(imx_3stack_dapm_widgets));
diff --git a/sound/soc/imx/imx-esai.c b/sound/soc/imx/imx-esai.c
index 5f95ecce842e..67eedfad54bc 100644
--- a/sound/soc/imx/imx-esai.c
+++ b/sound/soc/imx/imx-esai.c
@@ -36,6 +36,7 @@
#include <mach/esai.h>
#include "imx-esai.h"
+#include "imx-pcm.h"
static struct imx_esai *local_esai;
@@ -301,6 +302,8 @@ static int imx_esai_hw_tx_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai)
{
+ struct imx_pcm_runtime_data *iprtd = substream->runtime->private_data;
+
struct imx_esai *esai = snd_soc_dai_get_drvdata(cpu_dai);
u32 tcr, tfcr;
unsigned int channels;
@@ -314,19 +317,40 @@ static int imx_esai_hw_tx_params(struct snd_pcm_substream *substream,
/* DAI data (word) size */
tfcr &= ESAI_TFCR_TWA_MASK;
tcr &= ESAI_TCR_TSWS_MASK;
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- tfcr |= ESAI_WORD_LEN_16;
- tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL16;
- break;
- case SNDRV_PCM_FORMAT_S20_3LE:
- tfcr |= ESAI_WORD_LEN_20;
- tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL20;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
+
+ if (iprtd->asrc_enable) {
+ switch (iprtd->output_bit) {
+ case 16:
+ tfcr |= ESAI_WORD_LEN_16;
+ tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL16;
+ break;
+ case 24:
+ tfcr |= ESAI_WORD_LEN_24;
+ tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL24;
+ break;
+ default:
+ return -EINVAL;
+
+ }
tfcr |= ESAI_WORD_LEN_24;
tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL24;
- break;
+ } else {
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ tfcr |= ESAI_WORD_LEN_16;
+ tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL16;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ tfcr |= ESAI_WORD_LEN_20;
+ tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL20;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ tfcr |= ESAI_WORD_LEN_24;
+ tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL24;
+ break;
+ default:
+ return -EINVAL;
+ }
}
channels = params_channels(params);
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 386bd26564a8..2547d2bb8fdb 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -134,7 +134,9 @@ static int imx_ssi_asrc_dma_alloc(struct snd_pcm_substream *substream,
if (!iprtd->asrc_p2p_dma_chan)
goto error;
- slave_config.direction = DMA_DEV_TO_DEV;;
+ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+
+ slave_config.direction = DMA_DEV_TO_DEV;
slave_config.src_addr = asrc_get_per_addr(iprtd->asrc_index, 0);
slave_config.src_addr_width = buswidth;
slave_config.src_maxburst = dma_params->burstsize * buswidth;
diff --git a/sound/soc/imx/imx-pcm.h b/sound/soc/imx/imx-pcm.h
index 274af8ff7dcc..ede1382a2e04 100644
--- a/sound/soc/imx/imx-pcm.h
+++ b/sound/soc/imx/imx-pcm.h
@@ -53,16 +53,17 @@ struct imx_pcm_runtime_data {
struct dma_async_tx_descriptor *desc;
struct dma_chan *dma_chan;
struct imx_dma_data dma_data;
+ int asrc_enable;
#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_IMX_HAVE_PLATFORM_IMX_ASRC)
int asrc_index;
- int asrc_enable;
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;
+ unsigned int output_bit;
#endif
};
#endif