Example #1
0
static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
			struct snd_pcm_hw_params *params)
{
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_interval *channels = hw_param_interval(params,
                                       SNDRV_PCM_HW_PARAM_CHANNELS);
	unsigned int be_id = rtd->dai_link->be_id;
	unsigned int threshold;


	switch (be_id) {
	case OMAP_ABE_DAI_MM_FM:
		channels->min = 2;
		threshold = 2;
		break;
	case OMAP_ABE_DAI_BT_VX:
		channels->min = 1;
		threshold = 1;
		break;
	default:
		threshold = 1;
		break;
	}

	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
				    SNDRV_PCM_HW_PARAM_FIRST_MASK],
		     SNDRV_PCM_FORMAT_S16_LE);

	omap_mcbsp_set_tx_threshold(cpu_dai->id, threshold);
	omap_mcbsp_set_rx_threshold(cpu_dai->id, threshold);

	return 0;
}
Example #2
0
static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
	struct omap_pcm_dma_data *dma_data;
	int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
	int words;

	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);

	/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
	if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
		/*
		 * Configure McBSP threshold based on either:
		 * packet_size, when the sDMA is in packet mode, or
		 * based on the period size.
		 */
		if (dma_data->packet_size)
			words = dma_data->packet_size;
		else
			words = snd_pcm_lib_period_bytes(substream) /
							(mcbsp_data->wlen / 8);
	else
		words = 1;

	/* Configure McBSP internal buffer usage */
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, words);
	else
		omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words);
}
Example #3
0
/*
 * Stream DMA parameters. DMA request line and port address are set runtime
 * since they are different between OMAP1 and later OMAPs
 */
static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
	struct omap_pcm_dma_data *dma_data;
	int words;

	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);

	/*
	 * Configure McBSP threshold based on either:
	 * packet_size, when the sDMA is in packet mode, or based on the
	 * period size in THRESHOLD mode, otherwise use McBSP threshold = 1
	 * for mono streams.
	 */
	if (dma_data->packet_size)
		words = dma_data->packet_size;
	else
		words = 1;

	/* Configure McBSP internal buffer usage */
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		omap_mcbsp_set_tx_threshold(mcbsp, words);
	else
		omap_mcbsp_set_rx_threshold(mcbsp, words);
}
Example #4
0
static int sdp4430_mcbsp_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 *cpu_dai = rtd->cpu_dai;
	int ret = 0, channels = 0;
	unsigned int be_id, fmt;


        be_id = rtd->dai_link->be_id;

	if (be_id == OMAP_ABE_DAI_BT_VX) {
		if (machine_is_tuna())
			fmt = SND_SOC_DAIFMT_I2S |
				SND_SOC_DAIFMT_NB_NF |
				SND_SOC_DAIFMT_CBM_CFM;
		else
			fmt = SND_SOC_DAIFMT_DSP_B |
				SND_SOC_DAIFMT_NB_IF |
				SND_SOC_DAIFMT_CBM_CFM;
	} else {
		fmt = SND_SOC_DAIFMT_I2S |
			SND_SOC_DAIFMT_NB_NF |
			SND_SOC_DAIFMT_CBM_CFM;
	}

	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
	if (ret < 0) {
		printk(KERN_ERR "can't set cpu DAI configuration\n");
		return ret;
	}

	/*
	 * TODO: where does this clock come from (external source??) -
	 * do we need to enable it.
	 */
	/* Set McBSP clock to external */
	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
				     32 * 96 * params_rate(params),
				     SND_SOC_CLOCK_IN);
	if (ret < 0)
		printk(KERN_ERR "can't set cpu system clock\n");

	ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 96);
	if (ret < 0)
		printk(KERN_ERR "can't set McBSP cpu DAI clkdiv\n");

	/*
	 * Configure McBSP internal buffer threshold
	 * for playback/record
	 */
	channels = params_channels(params);
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		omap_mcbsp_set_tx_threshold(cpu_dai->id, channels);
	else
		omap_mcbsp_set_rx_threshold(cpu_dai->id, channels);

	return ret;
}
Example #5
0
static int archos_omap4_mcbsp_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 *cpu_dai = rtd->cpu_dai;
    int ret = 0;
    unsigned int be_id, channels;

    be_id = rtd->dai_link->be_id;

    if (be_id == OMAP_ABE_DAI_BT_VX) {
        ret = snd_soc_dai_set_fmt(cpu_dai,
                                  SND_SOC_DAIFMT_DSP_B |
                                  SND_SOC_DAIFMT_NB_IF |
                                  SND_SOC_DAIFMT_CBM_CFM);
    } else if (be_id == OMAP_ABE_DAI_HDMI_IN) {
        ret = snd_soc_dai_set_fmt(cpu_dai,
                                  SND_SOC_DAIFMT_I2S |
                                  SND_SOC_DAIFMT_NB_NF |
                                  SND_SOC_DAIFMT_CBS_CFS);
    } else {
        /* Set cpu DAI configuration */
        ret = snd_soc_dai_set_fmt(cpu_dai,
                                  SND_SOC_DAIFMT_I2S |
                                  SND_SOC_DAIFMT_NB_NF |
                                  SND_SOC_DAIFMT_CBM_CFM);
    }

    if (ret < 0) {
        printk(KERN_ERR "can't set cpu DAI configuration\n");
        return ret;
    }

    if (params != NULL) {
        /* Configure McBSP internal buffer usage */
        /* this need to be done for playback and/or record */
        channels = params_channels(params);
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
            omap_mcbsp_set_tx_threshold(
                cpu_dai->id, channels);
        else
            omap_mcbsp_set_rx_threshold(
                cpu_dai->id, channels);
    }

    /*
     * TODO: where does this clock come from (external source??) -
     * do we need to enable it.
     */
    /* Set McBSP clock to external */
    ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
                                 64 * params_rate(params),
                                 SND_SOC_CLOCK_IN);
    if (ret < 0)
        printk(KERN_ERR "can't set cpu system clock\n");

    return ret;
}
Example #6
0
static int sdp4430_modem_mcbsp_configure(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params, int flag)
{
	int ret = 0;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_pcm_substream *modem_substream[2];
	struct snd_soc_pcm_runtime *modem_rtd;
	int channels;

	if (flag) {
		modem_substream[substream->stream] =
		snd_soc_get_dai_substream(rtd->card,
						OMAP_ABE_BE_MM_EXT1,
						substream->stream);
		if (unlikely(modem_substream[substream->stream] == NULL))
			return -ENODEV;

		modem_rtd =
			modem_substream[substream->stream]->private_data;

		if (!mcbsp_cfg) {
			/* Set cpu DAI configuration */
			ret = snd_soc_dai_set_fmt(modem_rtd->cpu_dai,
					  SND_SOC_DAIFMT_I2S |
					  SND_SOC_DAIFMT_NB_NF |
					  SND_SOC_DAIFMT_CBM_CFM);

			if (unlikely(ret < 0)) {
				printk(KERN_ERR "can't set Modem cpu DAI configuration\n");
				goto exit;
			} else {
				mcbsp_cfg = 1;
			}
		}

		if (params != NULL) {
			/* Configure McBSP internal buffer usage */
			/* this need to be done for playback and/or record */
			channels = params_channels(params);
			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
				omap_mcbsp_set_rx_threshold(
					modem_rtd->cpu_dai->id, channels);
			else
				omap_mcbsp_set_tx_threshold(
					modem_rtd->cpu_dai->id, channels);
		}
	} else {
		mcbsp_cfg = 0;
	}

exit:
	return ret;
}
static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
			struct snd_pcm_hw_params *params)
{
	struct snd_interval *channels = hw_param_interval(params,
                                       SNDRV_PCM_HW_PARAM_CHANNELS);
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	unsigned int be_id;
	unsigned int threshold;
	unsigned int val, min_mask;
	DBG ("%s: Entered \n", __func__);
	//DBG ("%s: CPU DAI %s BE_ID %d\n", __func__, cpu_dai->name, rtd->dai_link->be_id);

	be_id = rtd->dai_link->be_id;

	switch (be_id) {
	case OMAP_ABE_DAI_MM_FM:
		channels->min = 2;
		threshold = 2;
                val = SNDRV_PCM_FORMAT_S16_LE;
		break;
	case OMAP_ABE_DAI_BT_VX:
		channels->min = 1;
		threshold = 1;
                val = SNDRV_PCM_FORMAT_S16_LE;
		break;
	default:
		threshold = 1;
                val = SNDRV_PCM_FORMAT_S16_LE;
		break;
	}
        
        min_mask = snd_mask_min(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -     
                                               SNDRV_PCM_HW_PARAM_FIRST_MASK]);

	//DBG ("%s: Returned min_mask 0x%x Format %x\n", __func__, min_mask, val);

        snd_mask_reset(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT - 
                                      SNDRV_PCM_HW_PARAM_FIRST_MASK],
			              min_mask);

	//DBG ("%s: Returned min_mask 0x%x Format %x\n", __func__, min_mask, val);

        snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
                                    SNDRV_PCM_HW_PARAM_FIRST_MASK], val);	

	omap_mcbsp_set_tx_threshold(cpu_dai->id, threshold);
	omap_mcbsp_set_rx_threshold(cpu_dai->id, threshold);
	
	DBG ("%s: Exiting \n", __func__);
	return 0;
}
static int omap_abe_mcbsp_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 *cpu_dai = rtd->cpu_dai;
	struct snd_soc_card *card = rtd->card;
	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
	struct clk *fclk;
	unsigned long fclk_rate;
	int ret;
	unsigned int channels;

	/* Set cpu DAI configuration */
	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);

	if (ret < 0) {
		dev_err(card->dev, "can't set cpu DAI configuration\n");
		return ret;
	}

	if (rtd->dai_link->no_pcm) {
		/* Configure McBSP internal buffer usage */
		/* this need to be done for playback and/or record */
		channels = params_channels(params);
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
			omap_mcbsp_set_tx_threshold(mcbsp, channels);
		else
			omap_mcbsp_set_rx_threshold(mcbsp, channels);
	}

	/* Get McBSP PRCM FCLK (internal clock) rate */
	fclk = clk_get(mcbsp->dev, "prcm_fck");
	if (IS_ERR(fclk)) {
		dev_err(card->dev, "can't get McBSP prcm_fck\n");
		return PTR_ERR(fclk);
	}

	fclk_rate = clk_get_rate(fclk);
	clk_put(fclk);

	/* Set McBSP clock to external */
	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
				     fclk_rate, SND_SOC_CLOCK_IN);
	if (ret < 0)
		dev_err(card->dev, "can't set cpu system clock\n");

	return ret;
}
static int omap_abe_modem_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_card *card = rtd->card;
	struct omap_abe_data *card_data = snd_soc_card_get_drvdata(card);
	struct snd_pcm_substream *modem_substream[2];
	struct snd_soc_pcm_runtime *modem_rtd;
	int channels, ret = 0, stream = substream->stream;

	modem_substream[stream] =
		snd_soc_get_dai_substream(card, OMAP_ABE_BE_MM_EXT1, stream);
	if (modem_substream[stream] == NULL)
		return -ENODEV;

	modem_rtd = modem_substream[stream]->private_data;

	if (!card_data->mcbsp_cfg) {
		/* Set cpu DAI configuration */
		ret = snd_soc_dai_set_fmt(modem_rtd->cpu_dai,
					SND_SOC_DAIFMT_I2S |
					SND_SOC_DAIFMT_NB_NF |
					SND_SOC_DAIFMT_CBM_CFM);
		if (ret < 0) {
			dev_err(card->dev, "can't set Modem cpu DAI configuration\n");
			return ret;
		} else
			card_data->mcbsp_cfg = 1;
	}

	if (params != NULL) {
		struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(
							modem_rtd->cpu_dai);
		/* Configure McBSP internal buffer usage */
		/* this need to be done for playback and/or record */
		channels = params_channels(params);
		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
			omap_mcbsp_set_rx_threshold(mcbsp, channels);
		else
			omap_mcbsp_set_tx_threshold(mcbsp, channels);
	}

	return ret;
}
static int omap_abe_mcbsp_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 *cpu_dai = rtd->cpu_dai;
	struct snd_soc_card *card = rtd->card;
	int ret;
	unsigned int be_id, channels;

	be_id = rtd->dai_link->be_id;

	if (be_id == OMAP_ABE_DAI_BT_VX)
		ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_B |
				SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBM_CFM);
	else
		/* Set cpu DAI configuration */
		ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
				SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);

	if (ret < 0) {
		dev_err(card->dev, "can't set cpu DAI configuration\n");
		return ret;
	}

	if (params != NULL) {
		struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
		/* Configure McBSP internal buffer usage */
		/* this need to be done for playback and/or record */
		channels = params_channels(params);
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
			omap_mcbsp_set_tx_threshold(mcbsp, channels);
		else
			omap_mcbsp_set_rx_threshold(mcbsp, channels);
	}

	/* Set McBSP clock to external */
	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
				     64 * params_rate(params), SND_SOC_CLOCK_IN);
	if (ret < 0)
		dev_err(card->dev, "can't set cpu system clock\n");

	return ret;
}
Example #11
0
static int omap_mcbsp_dai_prepare(struct snd_pcm_substream *substream,
						struct snd_soc_dai *dai)
{
		struct snd_soc_pcm_runtime *rtd = substream->private_data;
		struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
		struct omap_mcbsp_data *mcbsp_data =
				to_mcbsp(cpu_dai->private_data);
		int bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
		int     xfer_size;

		xfer_size =
		omap_mcbsp_dai_dma_params[id][substream->stream].xfer_size;

		if (!(mcbsp_data->tx_active || mcbsp_data->rx_active)) {
			omap_mcbsp_config(bus_id, &mcbsp_data->regs);

		if ((bus_id == 1) && (xfer_size > 0))
			omap_mcbsp_set_tx_threshold(bus_id, xfer_size);
		}
		return 0;
}
Example #12
0
static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
				    struct snd_pcm_hw_params *params,
				    struct snd_soc_dai *dai)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
	int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
	int uninitialized_var(wlen);
	int uninitialized_var(channels);
	int uninitialized_var(wpf);
	unsigned long uninitialized_var(port);
	unsigned int uninitialized_var(format);
	int xfer_size = 0;

	if (cpu_class_is_omap1()) {
		dma = omap1_dma_reqs[bus_id][substream->stream];
		port = omap1_mcbsp_port[bus_id][substream->stream];
	} else if (cpu_is_omap2420()) {
		dma = omap24xx_dma_reqs[bus_id][substream->stream];
		port = omap2420_mcbsp_port[bus_id][substream->stream];
	} else if (cpu_is_omap2430()) {
		dma = omap24xx_dma_reqs[bus_id][substream->stream];
		port = omap2430_mcbsp_port[bus_id][substream->stream];
	} else if (cpu_is_omap343x()) {
		dma = omap24xx_dma_reqs[bus_id][substream->stream];
		port = omap34xx_mcbsp_port[bus_id][substream->stream];
		xfer_size = omap34xx_mcbsp_thresholds[bus_id]
					[substream->stream];
		/* reset the xfer_size to the integral multiple of
		the buffer size. This is for DMA packet mode transfer */
		if (xfer_size) {
			int buffer_size = params_buffer_size(params);
			if (xfer_size > buffer_size) {
				printk(KERN_DEBUG "buffer_size is %d \n",
					buffer_size);
				xfer_size = 0;
			} else if (params_channels(params) == 1) {
				/* Mono needs 16 bits DMA, no FIFO */
				xfer_size = 1;
			} else {
				int temp =  buffer_size / xfer_size;
				while (buffer_size % xfer_size) {
					temp++;
					xfer_size = buffer_size / (temp);
				}
			}
		}
	} else {
		return -ENODEV;
	}
	omap_mcbsp_dai_dma_params[id][substream->stream].name =
		substream->stream ? "Audio Capture" : "Audio Playback";
	omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
	omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
	omap_mcbsp_dai_dma_params[id][substream->stream].xfer_size = xfer_size;
	cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];

	if (mcbsp_data->configured) {
		/* McBSP already configured by another stream */
		return 0;
	}

	format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
	wpf = channels = params_channels(params);

	if (format == SND_SOC_DAIFMT_SPDIF) {
		regs->xcr2	&= ~(XPHASE);
		regs->rcr2	&= ~(RPHASE);
		/* Don't care about channels number and frame
			length 2. Set 4 frames (frame length 1) */
		regs->xcr1	|= XFRLEN1(4 - 1);
		regs->rcr1	|= RFRLEN1(1 - 1);
	} else {
		switch (channels) {
		case 2:
			if (format == SND_SOC_DAIFMT_I2S) {
				/* Use dual-phase frames */
				regs->rcr2	|= RPHASE;
				regs->xcr2	|= XPHASE;
				/* Set 1 word per (McBSP) frame for phase1 and phase2 */
				wpf--;
				regs->rcr2	|= RFRLEN2(wpf - 1);
				regs->xcr2	|= XFRLEN2(wpf - 1);
			} else if (format == SND_SOC_DAIFMT_I2S_1PHASE || format == SND_SOC_DAIFMT_DSP_A_1PHASE) {
				printk(KERN_DEBUG "Configure McBSP for 1 phase\n");
				regs->xcr2	&= ~(XPHASE);
				regs->rcr2	&= ~(RPHASE);
				wpf--;
			}
		case 1:
		case 4:
			/* Set word per (McBSP) frame for phase1 */
			regs->rcr1	|= RFRLEN1(wpf - 1);
			regs->xcr1	|= XFRLEN1(wpf - 1);
			break;
		default:
			/* Unsupported number of channels */
			return -EINVAL;
		}
	}

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		/* Set word lengths */
		wlen = 16;
		if (format == SND_SOC_DAIFMT_SPDIF ||
		   (channels != 1 && (format == SND_SOC_DAIFMT_I2S_1PHASE ||
		   format == SND_SOC_DAIFMT_DSP_A_1PHASE))) {
			regs->xcr1	|= XWDLEN1(OMAP_MCBSP_WORD_32);
			regs->rcr1	|= RWDLEN1(OMAP_MCBSP_WORD_32);
			omap_mcbsp_dai_dma_params[id]
			[SNDRV_PCM_STREAM_PLAYBACK].dma_word_size = 32;
			omap_mcbsp_dai_dma_params[id]
			[SNDRV_PCM_STREAM_CAPTURE].dma_word_size = 32;
		} else {
			regs->rcr2	|= RWDLEN2(OMAP_MCBSP_WORD_16);
			regs->rcr1	|= RWDLEN1(OMAP_MCBSP_WORD_16);
			regs->xcr2	|= XWDLEN2(OMAP_MCBSP_WORD_16);
			regs->xcr1	|= XWDLEN1(OMAP_MCBSP_WORD_16);
			omap_mcbsp_dai_dma_params[id]
			[substream->stream].dma_word_size = 16;
		}
		break;
	case SNDRV_PCM_FORMAT_S8:
		/* Set word lengths */
		wlen = 8;
		if (format == SND_SOC_DAIFMT_SPDIF ||
		   (channels != 1 && (format == SND_SOC_DAIFMT_I2S_1PHASE ||
		   format == SND_SOC_DAIFMT_DSP_A_1PHASE))) {
			regs->xcr1	|= XWDLEN1(OMAP_MCBSP_WORD_16);
			regs->rcr1	|= RWDLEN1(OMAP_MCBSP_WORD_16);
			omap_mcbsp_dai_dma_params[id]
			[SNDRV_PCM_STREAM_PLAYBACK].dma_word_size = 16;
			omap_mcbsp_dai_dma_params[id]
			[SNDRV_PCM_STREAM_CAPTURE].dma_word_size = 16;
		} else {
			regs->rcr2	|= RWDLEN2(OMAP_MCBSP_WORD_8);
			regs->rcr1	|= RWDLEN1(OMAP_MCBSP_WORD_8);
			regs->xcr2	|= XWDLEN2(OMAP_MCBSP_WORD_8);
			regs->xcr1	|= XWDLEN1(OMAP_MCBSP_WORD_8);
			omap_mcbsp_dai_dma_params[id]
			[substream->stream].dma_word_size = 8;
		}
		break;
	default:
		/* Unsupported PCM format */
		return -EINVAL;
	}

	/* Set FS period and length in terms of bit clock periods */
	switch (format) {
	case SND_SOC_DAIFMT_I2S:
	case SND_SOC_DAIFMT_I2S_1PHASE:
		regs->srgr2	|= FPER(wlen * channels - 1);
		regs->srgr1	|= FWID(wlen - 1);
		break;
	case SND_SOC_DAIFMT_DSP_A_1PHASE:
	case SND_SOC_DAIFMT_DSP_A:
	case SND_SOC_DAIFMT_DSP_B:
		regs->srgr2	|= FPER(wlen * channels - 1);
		regs->srgr1	|= FWID(0);
		break;
	case SND_SOC_DAIFMT_SPDIF:
		regs->srgr2	|= FPER(4 * 32 - 1);
		regs->srgr1	|= FWID(0);
		break;
	}

	regs->xccr |= XDMAEN;
	regs->wken = XRDYEN;
	regs->rccr |= RDMAEN;

	omap_mcbsp_config(bus_id, &mcbsp_data->regs);

	if ((bus_id == 1) && (xfer_size != 0)) {
		printk(KERN_DEBUG "Configure McBSP TX FIFO threshold to %d\n",
			xfer_size);
		omap_mcbsp_set_tx_threshold(bus_id, xfer_size);
	}

	/* We want to be able to change stuff 
		(like channels number) dynamically */ 
	//mcbsp_data->configured = 1;

	return 0;
}
Example #13
0
static int sdp4430_modem_mcbsp_configure(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params, int flag)
{
	int ret = 0;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_pcm_substream *modem_substream[2];
	struct snd_soc_pcm_runtime *modem_rtd;
	int channels;

	if (flag) {
		modem_substream[substream->stream] =
		snd_soc_get_dai_substream(rtd->card,
						OMAP_ABE_BE_MM_EXT1,
						substream->stream);
		if (unlikely(modem_substream[substream->stream] == NULL))
			return -ENODEV;

		modem_rtd =
			modem_substream[substream->stream]->private_data;

		if (!mcbsp_cfg) {
			if (omap4_tuna_get_type() == TUNA_TYPE_TORO) {
				/* Set cpu DAI configuration */
				ret = snd_soc_dai_set_fmt(modem_rtd->cpu_dai,
						SND_SOC_DAIFMT_I2S |
						SND_SOC_DAIFMT_NB_NF |
						SND_SOC_DAIFMT_CBS_CFS);
				if (unlikely(ret < 0)) {
					printk(KERN_ERR "can't set Modem cpu DAI format\n");
					goto exit;
				}

				/* McBSP2 fclk reparented to ABE_24M_FCLK */
				ret = snd_soc_dai_set_sysclk(modem_rtd->cpu_dai,
						OMAP_MCBSP_SYSCLK_CLKS_FCLK,
						32 * 96 * params_rate(params),
						SND_SOC_CLOCK_IN);
				if (unlikely(ret < 0)) {
					printk(KERN_ERR "can't set Modem cpu DAI sysclk\n");
					goto exit;
				}

				/* assuming McBSP2 is S16_LE stereo */
				ret = snd_soc_dai_set_clkdiv(modem_rtd->cpu_dai, 0, 96);
				if (unlikely(ret < 0)) {
					printk(KERN_ERR "can't set Modem cpu DAI clkdiv\n");
					goto exit;
				}
			} else {
				/* Set cpu DAI configuration */
				ret = snd_soc_dai_set_fmt(modem_rtd->cpu_dai,
						SND_SOC_DAIFMT_I2S |
						SND_SOC_DAIFMT_NB_NF |
						SND_SOC_DAIFMT_CBM_CFM);

				if (unlikely(ret < 0)) {
					printk(KERN_ERR "can't set Modem cpu DAI configuration\n");
					goto exit;
				}
			}
			mcbsp_cfg = 1;
		}

		if (params != NULL) {
			/* Configure McBSP internal buffer usage */
			/* this need to be done for playback and/or record */
			channels = params_channels(params);
			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
				omap_mcbsp_set_rx_threshold(
					modem_rtd->cpu_dai->id, channels);
			else
				omap_mcbsp_set_tx_threshold(
					modem_rtd->cpu_dai->id, channels);
		}
	} else {
		mcbsp_cfg = 0;
	}

exit:
	return ret;
}