diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/imx/imx-cs42888.c | 87 | ||||
-rw-r--r-- | sound/soc/imx/imx-esai.c | 46 | ||||
-rw-r--r-- | sound/soc/imx/imx-pcm-dma-mx2.c | 4 | ||||
-rw-r--r-- | sound/soc/imx/imx-pcm.h | 3 |
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 |