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(¶ms->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; }
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); }
/* * 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); }
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; }
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; }
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(¶ms->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(¶ms->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(¶ms->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; }
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; }
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; }
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; }