Exemplo n.º 1
0
static int config_asrc(struct snd_pcm_substream *substream,
					 struct snd_pcm_hw_params *params)
{
	unsigned int rate = params_rate(params);
	unsigned int channel = params_channels(params);
	unsigned int wordwidth = get_format_width(params);
	struct imx_pcm_runtime_data *pcm_data =
				substream->runtime->private_data;
	struct asrc_config config = {0};
	int ret = 0;

	if (rate <= 32000 || rate == asrc_esai_data.output_sample_rate)
		return -EINVAL;

	if (channel != 2)
		return -EINVAL;

	if (wordwidth != 24)
		return -EINVAL;

	ret = asrc_req_pair(channel, &asrc_esai_data.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);
		return -EINVAL;
	}

	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.inclk = OUTCLK_ASRCK1_CLK;
	config.word_width = wordwidth;
	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);
		return ret;
	}
	pcm_data->asrc_index = asrc_esai_data.asrc_index;
	pcm_data->asrc_enable = 1;

	return 0;
}
Exemplo n.º 2
0
    static int config_asrc(struct snd_pcm_substream *substream,
                           struct snd_pcm_hw_params *params)
{
    unsigned int rate = params_rate(params);
    unsigned int channel = params_channels(params);
    struct imx_pcm_runtime_data *iprtd =
            substream->runtime->private_data;
    struct asrc_config config = {0};
    int ret = 0;

    if ((channel != 2) && (channel != 4) && (channel != 6))
        return -EINVAL;

    ret = asrc_req_pair(channel, &iprtd->asrc_index);
    if (ret < 0) {
        pr_err("Fail to request asrc pair\n");
        return -EINVAL;
    }

    config.input_word_width = get_asrc_input_width(params);
    config.output_word_width = iprtd->p2p->p2p_width;
    config.pair = iprtd->asrc_index;
    config.channel_num = channel;
    config.input_sample_rate = rate;
    config.output_sample_rate = iprtd->p2p->p2p_rate;
    config.inclk = INCLK_NONE;
    config.outclk = OUTCLK_ESAI_TX;

    ret = asrc_config_pair(&config);
    if (ret < 0) {
        pr_err("Fail to config asrc\n");
        return ret;
    }

    return 0;
}
static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_dai_link *pcm_link = rtd->dai;
    struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai;
    struct snd_soc_dai *codec_dai = pcm_link->codec_dai;
    unsigned int rate = params_rate(params);
    u32 dai_format;
    unsigned int lrclk_ratio = 0;
#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE)
    unsigned int channel = params_channels(params);
#endif
    struct imx_esai *esai_mode = (struct imx_esai *)cpu_dai->private_data;
    if (clk_state.lr_clk_active > 1)
        return 0;

#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE)
    if (asrc_esai_data.output_sample_rate >= 32000) {
        unsigned int asrc_input_rate = rate;
        struct mxc_runtime_data *pcm_data =
                substream->runtime->private_data;
        struct asrc_config config;
        int retVal = 0;;

        retVal = asrc_req_pair(channel, &asrc_esai_data.asrc_index);
        if (retVal < 0) {
            pr_err("Fail to request asrc pair\n");
            return -1;
        }

        config.pair = asrc_esai_data.asrc_index;
        config.channel_num = channel;
        config.input_sample_rate = asrc_input_rate;
        config.output_sample_rate = asrc_esai_data.output_sample_rate;
        config.inclk = INCLK_NONE;
        config.word_width = 32;
        config.outclk = OUTCLK_ESAI_TX;
        retVal = asrc_config_pair(&config);
        if (retVal < 0) {
            pr_err("Fail to config asrc\n");
            asrc_release_pair(asrc_esai_data.asrc_index);
            return retVal;
        }
        rate = asrc_esai_data.output_sample_rate;
        pcm_data->asrc_index = asrc_esai_data.asrc_index;
        pcm_data->asrc_enable = 1;
    }
#endif

    switch (rate) {
    case 32000:
        lrclk_ratio = 3;
        break;
    case 48000:
        lrclk_ratio = 3;
        break;
    case 64000:
        lrclk_ratio = 1;
        break;
    case 96000:
        lrclk_ratio = 1;
        break;
    case 128000:
        lrclk_ratio = 1;
        break;
    case 44100:
        lrclk_ratio = 3;
        break;
    case 88200:
        lrclk_ratio = 1;
        break;
    case 176400:
        lrclk_ratio = 0;
        break;
    case 192000:
        lrclk_ratio = 0;
        break;
    default:
        pr_info("Rate not support.\n");
        return -EINVAL;;
    }

    dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
                 SND_SOC_DAIFMT_CBS_CFS;

    esai_mode->sync_mode = 0;
    esai_mode->network_mode = 1;

    /* set cpu DAI configuration */
    snd_soc_dai_set_fmt(cpu_dai, dai_format);
    /* set i.MX active slot mask */
    snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32);
    /* set the ESAI system clock as output */
    snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL,
                           mclk_freq, SND_SOC_CLOCK_OUT);
    /* set the ratio */
    snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PSR, 1);
    snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 0);
    snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_FP, lrclk_ratio);
    snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PSR, 1);
    snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 0);
    snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_FP, lrclk_ratio);

    /* set codec DAI configuration */
    snd_soc_dai_set_fmt(codec_dai, dai_format);
    /* set codec Master clock */
    snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, SND_SOC_CLOCK_IN);

    return 0;
}
Exemplo n.º 4
0
static long asrc_ioctl_config_pair(struct asrc_pair_params *params,
				void __user *user)
{
	struct asrc_config config;
	enum asrc_pair_index index;
	long ret;

	ret = copy_from_user(&config, user, sizeof(config));
	if (ret) {
		dev_err(asrc->dev, "failed to get config from user space: %ld\n", ret);
		return ret;
	}

	index = config.pair;

	ret = asrc_config_pair(&config);
	if (ret) {
		pair_err("failed to config pair: %ld\n", ret);
		return ret;
	}

	params->input_wm = 4;
	params->output_wm = 2;

	ret = asrc_set_watermark(index, params->input_wm, params->output_wm);
	if (ret)
		return ret;

	params->output_buffer_size = config.dma_buffer_size;
	params->input_buffer_size = config.dma_buffer_size;
	if (config.buffer_num > ASRC_DMA_BUFFER_NUM)
		params->buffer_num = ASRC_DMA_BUFFER_NUM;
	else
		params->buffer_num = config.buffer_num;

	params->input_dma_total.length = ASRC_DMA_BUFFER_SIZE;
	params->output_dma_total.length = ASRC_DMA_BUFFER_SIZE;

	params->input_word_width = config.input_word_width;
	params->output_word_width = config.output_word_width;

	params->input_sample_rate = config.input_sample_rate;
	params->output_sample_rate = config.output_sample_rate;

	params->last_period_sample = ASRC_OUTPUT_LAST_SAMPLE_DEFAULT;

	ret = mxc_allocate_dma_buf(params);
	if (ret) {
		pair_err("failed to allocate dma buffer: %ld\n", ret);
		return ret;
	}

	/* Request DMA channel for both input and output */
	params->input_dma_channel = imx_asrc_get_dma_channel(index, true);
	if (params->input_dma_channel == NULL) {
		pair_err("failed to request input task dma channel\n");
		return  -EBUSY;
	}

	params->output_dma_channel = imx_asrc_get_dma_channel(index, false);
	if (params->output_dma_channel == NULL) {
		pair_err("failed to request output task dma channel\n");
		return  -EBUSY;
	}

	init_completion(&params->input_complete);
	init_completion(&params->output_complete);
	init_completion(&params->lastperiod_complete);

	/* Add work struct to receive last period of output data */
	INIT_WORK(&params->task_output_work, asrc_output_task_worker);

	ret = copy_to_user(user, &config, sizeof(config));
	if (ret) {
		pair_err("failed to send config to user space: %ld\n", ret);
		return ret;
	}

	return 0;
}
static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream,
				      struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai_link *machine = rtd->dai;
	struct snd_soc_dai *cpu_dai = machine->cpu_dai;
	struct snd_soc_dai *codec_dai = machine->codec_dai;
	struct imx_3stack_priv *priv = &card_priv;
	unsigned int rate = params_rate(params);
	struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data;
	int ret = 0;

	unsigned int channels = params_channels(params);
	u32 dai_format;

	/* only need to do this once as capture and playback are sync */
	if (priv->hw)
		return 0;
	priv->hw = 1;

#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE)
	if ((asrc_ssi_data.output_sample_rate != 0)
	    && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) {
		unsigned int asrc_input_rate = rate;
		unsigned int channel = params_channels(params);
		struct mxc_runtime_data *pcm_data =
		    substream->runtime->private_data;
		struct asrc_config config;
		struct mxc_audio_platform_data *plat;
		struct imx_3stack_priv *priv = &card_priv;
		int retVal = 0;
		retVal = asrc_req_pair(channel, &asrc_ssi_data.asrc_index);
		if (retVal < 0) {
			pr_err("asrc_req_pair fail\n");
			return -1;
		}
		config.pair = asrc_ssi_data.asrc_index;
		config.channel_num = channel;
		config.input_sample_rate = asrc_input_rate;
		config.output_sample_rate = asrc_ssi_data.output_sample_rate;
		config.inclk = INCLK_NONE;
		config.word_width = 32;
		plat = priv->pdev->dev.platform_data;
		if (plat->src_port == 1)
			config.outclk = OUTCLK_SSI1_TX;
		else
			config.outclk = OUTCLK_SSI2_TX;
		retVal = asrc_config_pair(&config);
		if (retVal < 0) {
			pr_err("Fail to config asrc\n");
			asrc_release_pair(asrc_ssi_data.asrc_index);
			return retVal;
		}
		rate = asrc_ssi_data.output_sample_rate;
		pcm_data->asrc_index = asrc_ssi_data.asrc_index;
		pcm_data->asrc_enable = 1;
	}
#endif

	snd_soc_dai_set_sysclk(codec_dai, ALC5623_SYSCLK, priv->sysclk, 0);
	snd_soc_dai_set_sysclk(codec_dai, ALC5623_LRCLK, rate, 0);

#if ALC5623_SSI_MASTER
	dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
	    SND_SOC_DAIFMT_CBM_CFM;
#else
	dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
	    SND_SOC_DAIFMT_CBS_CFS;
#endif

	ssi_mode->sync_mode = 1;
	if (channels == 1)
		ssi_mode->network_mode = 0;
	else
		ssi_mode->network_mode = 1;

	/* set codec DAI configuration */
	ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
	if (ret < 0)
		return ret;

	/* set i.MX active slot mask */
	snd_soc_dai_set_tdm_slot(cpu_dai,
				 channels == 1 ? 0xfffffffe : 0xfffffffc,
				 channels == 1 ? 0xfffffffe : 0xfffffffc,
				 2, 32);

	/* set cpu DAI configuration */
	ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
	if (ret < 0)
		return ret;

	/* set the SSI system clock as input (unused) */
	snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN);

	return 0;
}