static int pcm512x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); int alen; int gpio; int clock_output; int master_mode; int ret; dev_dbg(codec->dev, "hw_params %u Hz, %u channels\n", params_rate(params), params_channels(params)); switch (snd_pcm_format_width(params_format(params))) { case 16: alen = PCM512x_ALEN_16; break; case 20: alen = PCM512x_ALEN_20; break; case 24: alen = PCM512x_ALEN_24; break; case 32: alen = PCM512x_ALEN_32; break; default: dev_err(codec->dev, "Bad frame size: %d\n", snd_pcm_format_width(params_format(params))); return -EINVAL; } switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG, PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO, 0); if (ret != 0) { dev_err(codec->dev, "Failed to enable slave mode: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, PCM512x_DCAS, 0); if (ret != 0) { dev_err(codec->dev, "Failed to enable clock divider autoset: %d\n", ret); return ret; } return 0; case SND_SOC_DAIFMT_CBM_CFM: clock_output = PCM512x_BCKO | PCM512x_LRKO; master_mode = PCM512x_RLRK | PCM512x_RBCK; break; case SND_SOC_DAIFMT_CBM_CFS: clock_output = PCM512x_BCKO; master_mode = PCM512x_RBCK; break; default: return -EINVAL; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1, PCM512x_ALEN, alen); if (ret != 0) { dev_err(codec->dev, "Failed to set frame size: %d\n", ret); return ret; } if (pcm512x->pll_out) { ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_A, 0x11); if (ret != 0) { dev_err(codec->dev, "Failed to set FLEX_A: %d\n", ret); return ret; } ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_B, 0xff); if (ret != 0) { dev_err(codec->dev, "Failed to set FLEX_B: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_IDCM | PCM512x_DCAS | PCM512x_IPLK, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_DCAS); if (ret != 0) { dev_err(codec->dev, "Failed to ignore auto-clock failures: %d\n", ret); return ret; } } else { ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_IDCM | PCM512x_DCAS | PCM512x_IPLK, PCM512x_IDFS | PCM512x_IDBK | PCM512x_IDSK | PCM512x_IDCH | PCM512x_DCAS | PCM512x_IPLK); if (ret != 0) { dev_err(codec->dev, "Failed to ignore auto-clock failures: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, PCM512x_PLLE, 0); if (ret != 0) { dev_err(codec->dev, "Failed to disable pll: %d\n", ret); return ret; } } ret = pcm512x_set_dividers(dai, params); if (ret != 0) return ret; if (pcm512x->pll_out) { ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_REF, PCM512x_SREF, PCM512x_SREF_GPIO); if (ret != 0) { dev_err(codec->dev, "Failed to set gpio as pllref: %d\n", ret); return ret; } gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1; ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_PLLIN, PCM512x_GREF, gpio); if (ret != 0) { dev_err(codec->dev, "Failed to set gpio %d as pllin: %d\n", pcm512x->pll_in, ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, PCM512x_PLLE, PCM512x_PLLE); if (ret != 0) { dev_err(codec->dev, "Failed to enable pll: %d\n", ret); return ret; } } ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG, PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO, clock_output); if (ret != 0) { dev_err(codec->dev, "Failed to enable clock output: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_MASTER_MODE, PCM512x_RLRK | PCM512x_RBCK, master_mode); if (ret != 0) { dev_err(codec->dev, "Failed to enable master mode: %d\n", ret); return ret; } if (pcm512x->pll_out) { gpio = PCM512x_G1OE << (pcm512x->pll_out - 1); ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN, gpio, gpio); if (ret != 0) { dev_err(codec->dev, "Failed to enable gpio %d: %d\n", pcm512x->pll_out, ret); return ret; } gpio = PCM512x_GPIO_OUTPUT_1 + pcm512x->pll_out - 1; ret = regmap_update_bits(pcm512x->regmap, gpio, PCM512x_GxSL, PCM512x_GxSL_PLLCK); if (ret != 0) { dev_err(codec->dev, "Failed to output pll on %d: %d\n", ret, pcm512x->pll_out); return ret; } } ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, PCM512x_RQSY, PCM512x_RQSY_HALT); if (ret != 0) { dev_err(codec->dev, "Failed to halt clocks: %d\n", ret); return ret; } ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, PCM512x_RQSY, PCM512x_RQSY_RESUME); if (ret != 0) { dev_err(codec->dev, "Failed to resume clocks: %d\n", ret); return ret; } return 0; }
static int msm8960_slimbus_2_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 *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret = 0; unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS]; unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0; unsigned int num_tx_ch = 0; unsigned int num_rx_ch = 0; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { num_rx_ch = params_channels(params); pr_info("%s: %s rx_dai_id = %d num_ch = %d\n", __func__, codec_dai->name, codec_dai->id, num_rx_ch); ret = snd_soc_dai_get_channel_map(codec_dai, &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch); if (ret < 0) { pr_err("%s: failed to get codec chan map\n", __func__); goto end; } ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, num_rx_ch, rx_ch); if (ret < 0) { pr_err("%s: failed to set cpu chan map\n", __func__); goto end; } ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0, num_rx_ch, rx_ch); if (ret < 0) { pr_err("%s: failed to set codec channel map\n", __func__); goto end; } } else { num_tx_ch = params_channels(params); pr_info("%s: %s tx_dai_id = %d num_ch = %d\n", __func__, codec_dai->name, codec_dai->id, num_tx_ch); ret = snd_soc_dai_get_channel_map(codec_dai, &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch); if (ret < 0) { pr_err("%s: failed to get codec chan map\n", __func__); goto end; } ret = snd_soc_dai_set_channel_map(cpu_dai, num_tx_ch, tx_ch, 0 , 0); if (ret < 0) { pr_err("%s: failed to set cpu chan map\n", __func__); goto end; } ret = snd_soc_dai_set_channel_map(codec_dai, num_tx_ch, tx_ch, 0, 0); if (ret < 0) { pr_err("%s: failed to set codec channel map\n", __func__); goto end; } } end: return ret; }
static int s3c_pcmdev_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; u32 value, clk_rate; u32 bfs, rfs, sclk_div, sync_div, clk_div; u32 audioclk, tmp; struct clk *clk; debug_msg("%s\n", __func__); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, &s3c_pcmdev_pcm_stereo_out); else snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, &s3c_pcmdev_pcm_stereo_in); switch (params_channels(params)) { case 1: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) s3c_pcmdev_pcm_stereo_out.dma_size = 2; else s3c_pcmdev_pcm_stereo_in.dma_size = 2; break; case 2: break; default: break; } switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: bfs = 16; rfs = 256; break; case SNDRV_PCM_FORMAT_S16_LE: bfs = 32; rfs = 256; break; case SNDRV_PCM_FORMAT_S20_3LE: case SNDRV_PCM_FORMAT_S24_LE: /* B'coz 48-BFS needs atleast 512-RFS acc to *S5P6440* UserManual */ bfs = 48; rfs = 512; break; /* Impossible, as the AP doesn't support 64fs or more BFS */ case SNDRV_PCM_FORMAT_S32_LE: default: printk(KERN_ERR "Inside function %s..\ Default format not supported..\n", __func__); return -EINVAL; } /* Enable the interrupts */ value = readl(s3c_pcmdev.regs + S3C_PCM_IRQ_CTL); value |= S3C_PCMIRQSTAT_TXFIFO_ALMOST_EMPTY; value |= S3C_PCMIRQ_EN_IRQ_TO_ARM; /*..for using interrupt mode*/ /* writel(value, s3c_pcmdev.regs + S3C_PCM_IRQ_CTL);*/ clk = clk_get(NULL, RATESRCCLK); if (IS_ERR(clk)) { printk(KERN_ERR "failed to get %s\n", RATESRCCLK); return -EBUSY; } clk_disable(clk); clk_div = readl(S5P_CLK_DIV6); clk_div &= ~(0xF<<4); switch (params_rate(params)) { case 8000: case 16000: case 32000: clk_set_rate(clk, 49152000); audioclk = 49152000; break; case 48000: case 96000: clk_set_rate(clk, 73728000); audioclk = 73728000; break; case 11025: case 22050: case 44100: case 88200: clk_set_rate(clk, 67738000); audioclk = 67738000; break; default: printk(KERN_ERR "Required Rate =%d..not supported\n", params_rate(params)); return -EINVAL; } clk_rate = (params_rate(params)*bfs); tmp = ((audioclk/(clk_rate))/2)-1; debug_msg("clk_rate=%d...sclk_div=%d..clk_div6=0x%x..smaple_rate=%d\n", clk_rate, tmp, readl(S5P_CLK_DIV6), params_rate(params)); sclk_div = tmp; sync_div = bfs-1; value = readl(s3c_pcmdev.regs + S3C_PCM_CLKCTL); value &= ~(S3C_PCMCLKCTL_SCLK_DIV | S3C_PCMCLKCTL_SYNC_DIV); value |= (sclk_div << 9); value |= (sync_div << 0); writel(value, s3c_pcmdev.regs + S3C_PCM_CLKCTL); clk_enable(clk); s3c_pcmdev.clk_rate = clk_get_rate(s3c_pcmdev.clk_src); debug_msg("Setting FOUTepll to %dHz\n", s3c_pcmdev.clk_rate); s3c_pcmdev.clk_rate = clk_get_rate(s3c_pcmdev.pcm_clk); clk_put(clk); debug_msg("Inside...%s...S3C_PCM_CLKCTL=0x%x\n", __func__, readl(s3c_pcmdev.regs + S3C_PCM_CLKCTL)); return 0; }
static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct rk30_i2s_info *i2s = to_info(dai); u32 iismod; u32 dmarc; unsigned long flags; struct hdmi_audio hdmi_audio_cfg; I2S_DBG("Enter %s, %d \n", __func__, __LINE__); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dai->playback_dma_data = &i2s->playback_dma_data; else dai->capture_dma_data = &i2s->capture_dma_data; spin_lock_irqsave(&lock, flags); /* Working copies of register */ iismod = readl(&(pheadi2s->I2S_TXCR)); iismod &= (~((1<<5)-1)); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: iismod |= SAMPLE_DATA_8bit; break; case SNDRV_PCM_FORMAT_S16_LE: iismod |= I2S_DATA_WIDTH(15); break; case SNDRV_PCM_FORMAT_S20_3LE: iismod |= I2S_DATA_WIDTH(19); break; case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S24_3LE: iismod |= I2S_DATA_WIDTH(23); break; case SNDRV_PCM_FORMAT_S32_LE: iismod |= I2S_DATA_WIDTH(31); break; } iismod &= ~CHANNLE_4_EN; switch (params_channels(params)) { case 8: iismod |= CHANNLE_4_EN; break; case 6: iismod |= CHANNEL_3_EN; break; case 4: iismod |= CHANNEL_2_EN; break; case 2: iismod |= CHANNEL_1_EN; break; default: I2S_DBG("%d channels not supported\n", params_channels(params)); return -EINVAL; } //set hdmi codec params if(HW_PARAMS_FLAG_NLPCM == params->flags) hdmi_audio_cfg.type = HDMI_AUDIO_NLPCM; else hdmi_audio_cfg.type = HDMI_AUDIO_LPCM; //printk("i2s: hdmi_audio_cfg.type: %d\n", hdmi_audio_cfg.type); hdmi_audio_cfg.channel = params_channels(params); hdmi_audio_cfg.rate = SR2FS(params_rate(params)); hdmi_audio_cfg.word_length = HDMI_AUDIO_WORD_LENGTH_16bit; hdmi_config_audio(&hdmi_audio_cfg); // writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR)); dmarc = readl(&(pheadi2s->I2S_DMACR)); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dmarc = ((dmarc & 0xFFFFFE00) | 16); else dmarc = ((dmarc & 0xFE00FFFF) | 16<<16); writel(dmarc, &(pheadi2s->I2S_DMACR)); I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod); writel(iismod, &(pheadi2s->I2S_TXCR)); iismod = iismod & 0x00007FFF; writel(iismod, &(pheadi2s->I2S_RXCR)); spin_unlock_irqrestore(&lock, flags); return 0; }
/* * Configure the SSC. */ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { int id = dai->id; struct atmel_ssc_info *ssc_p = &ssc_info[id]; struct atmel_pcm_dma_params *dma_params; int dir, channels, bits; u32 tfmr, rfmr, tcmr, rcmr; int start_event; int ret; /* * Currently, there is only one set of dma params for * each direction. If more are added, this code will * have to be changed to select the proper set. */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dir = 0; else dir = 1; dma_params = ssc_p->dma_params[dir]; channels = params_channels(params); /* * Determine sample size in bits and the PDC increment. */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: bits = 8; dma_params->pdc_xfer_size = 1; break; case SNDRV_PCM_FORMAT_S16_LE: bits = 16; dma_params->pdc_xfer_size = 2; break; case SNDRV_PCM_FORMAT_S24_LE: bits = 24; dma_params->pdc_xfer_size = 4; break; case SNDRV_PCM_FORMAT_S32_LE: bits = 32; dma_params->pdc_xfer_size = 4; break; default: printk(KERN_WARNING "atmel_ssc_dai: unsupported PCM format"); return -EINVAL; } /* * The SSC only supports up to 16-bit samples in I2S format, due * to the size of the Frame Mode Register FSLEN field. */ if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S && bits > 16) { printk(KERN_WARNING "atmel_ssc_dai: sample size %d " "is too large for I2S\n", bits); return -EINVAL; } /* * Compute SSC register settings. */ switch (ssc_p->daifmt & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: /* * I2S format, SSC provides BCLK and LRC clocks. * * The SSC transmit and receive clocks are generated * from the MCK divider, and the BCLK signal * is output on the SSC TK line. */ rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | SSC_BF(RCMR_STTDLY, START_DELAY) | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, SSC_CKS_DIV); rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | SSC_BF(RFMR_FSLEN, (bits - 1)) | SSC_BF(RFMR_DATNB, (channels - 1)) | SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_LOOP, 0) | SSC_BF(RFMR_DATLEN, (bits - 1)); tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) | SSC_BF(TCMR_STTDLY, START_DELAY) | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | SSC_BF(TCMR_CKS, SSC_CKS_DIV); tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSDEN, 0) | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | SSC_BF(TFMR_FSLEN, (bits - 1)) | SSC_BF(TFMR_DATNB, (channels - 1)) | SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATDEF, 0) | SSC_BF(TFMR_DATLEN, (bits - 1)); break; case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: /* * I2S format, CODEC supplies BCLK and LRC clocks. * * The SSC transmit clock is obtained from the BCLK signal on * on the TK line, and the SSC receive clock is * generated from the transmit clock. * * For single channel data, one sample is transferred * on the falling edge of the LRC clock. * For two channel data, one sample is * transferred on both edges of the LRC clock. */ start_event = ((channels == 1) ? SSC_START_FALLING_RF : SSC_START_EDGE_RF); rcmr = SSC_BF(RCMR_PERIOD, 0) | SSC_BF(RCMR_STTDLY, START_DELAY) | SSC_BF(RCMR_START, start_event) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK); rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | SSC_BF(RFMR_FSLEN, 0) | SSC_BF(RFMR_DATNB, 0) | SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_LOOP, 0) | SSC_BF(RFMR_DATLEN, (bits - 1)); tcmr = SSC_BF(TCMR_PERIOD, 0) | SSC_BF(TCMR_STTDLY, START_DELAY) | SSC_BF(TCMR_START, start_event) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | SSC_BF(TCMR_CKS, SSC_CKS_PIN); tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSDEN, 0) | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) | SSC_BF(TFMR_FSLEN, 0) | SSC_BF(TFMR_DATNB, 0) | SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATDEF, 0) | SSC_BF(TFMR_DATLEN, (bits - 1)); break; case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: /* * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. * * The SSC transmit and receive clocks are generated from the * MCK divider, and the BCLK signal is output * on the SSC TK line. */ rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | SSC_BF(RCMR_STTDLY, 1) | SSC_BF(RCMR_START, SSC_START_RISING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, SSC_CKS_DIV); rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) | SSC_BF(RFMR_FSLEN, 0) | SSC_BF(RFMR_DATNB, (channels - 1)) | SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_LOOP, 0) | SSC_BF(RFMR_DATLEN, (bits - 1)); tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) | SSC_BF(TCMR_STTDLY, 1) | SSC_BF(TCMR_START, SSC_START_RISING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_RISING) | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | SSC_BF(TCMR_CKS, SSC_CKS_DIV); tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSDEN, 0) | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) | SSC_BF(TFMR_FSLEN, 0) | SSC_BF(TFMR_DATNB, (channels - 1)) | SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATDEF, 0) | SSC_BF(TFMR_DATLEN, (bits - 1)); break; case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: /* * DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks. * * The SSC transmit clock is obtained from the BCLK signal on * on the TK line, and the SSC receive clock is * generated from the transmit clock. * * Data is transferred on first BCLK after LRC pulse rising * edge.If stereo, the right channel data is contiguous with * the left channel data. */ rcmr = SSC_BF(RCMR_PERIOD, 0) | SSC_BF(RCMR_STTDLY, START_DELAY) | SSC_BF(RCMR_START, SSC_START_RISING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, SSC_CKS_PIN); rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | SSC_BF(RFMR_FSLEN, 0) | SSC_BF(RFMR_DATNB, (channels - 1)) | SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_LOOP, 0) | SSC_BF(RFMR_DATLEN, (bits - 1)); tcmr = SSC_BF(TCMR_PERIOD, 0) | SSC_BF(TCMR_STTDLY, START_DELAY) | SSC_BF(TCMR_START, SSC_START_RISING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | SSC_BF(TCMR_CKS, SSC_CKS_PIN); tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSDEN, 0) | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) | SSC_BF(TFMR_FSLEN, 0) | SSC_BF(TFMR_DATNB, (channels - 1)) | SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATDEF, 0) | SSC_BF(TFMR_DATLEN, (bits - 1)); break; default: printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n", ssc_p->daifmt); return -EINVAL; } pr_debug("atmel_ssc_hw_params: " "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr); if (!ssc_p->initialized) { /* Enable PMC peripheral clock for this SSC */ pr_debug("atmel_ssc_dai: Starting clock\n"); clk_enable(ssc_p->ssc->clk); /* Reset the SSC and its PDC registers */ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0); ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0); ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0); ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0); ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0); ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0); ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0, ssc_p->name, ssc_p); if (ret < 0) { printk(KERN_WARNING "atmel_ssc_dai: request_irq failure\n"); pr_debug("Atmel_ssc_dai: Stoping clock\n"); clk_disable(ssc_p->ssc->clk); return ret; } ssc_p->initialized = 1; } /* set SSC clock mode register */ ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div); /* set receive clock mode and format */ ssc_writel(ssc_p->ssc->regs, RCMR, rcmr); ssc_writel(ssc_p->ssc->regs, RFMR, rfmr); /* set transmit clock mode and format */ ssc_writel(ssc_p->ssc->regs, TCMR, tcmr); ssc_writel(ssc_p->ssc->regs, TFMR, tfmr); pr_debug("atmel_ssc_dai,hw_params: SSC initialized\n"); return 0; }
static int mop500_ab8500_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 *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct device *dev = rtd->card->dev; unsigned int fmt; int channels, ret = 0, driver_mode, slots; unsigned int sw_codec, sw_cpu; bool is_playback; dev_dbg(dev, "%s: Enter\n", __func__); dev_dbg(dev, "%s: substream->pcm->name = %s\n" "substream->pcm->id = %s.\n" "substream->name = %s.\n" "substream->number = %d.\n", __func__, substream->pcm->name, substream->pcm->id, substream->name, substream->number); /* Ensure configuration consistency between DAIs */ mutex_lock(&mop500_ab8500_params_lock); if (mop500_ab8500_usage) { if (mop500_ab8500_rate != params_rate(params) || mop500_ab8500_channels != params_channels(params)) { mutex_unlock(&mop500_ab8500_params_lock); return -EBUSY; } } else { mop500_ab8500_rate = params_rate(params); mop500_ab8500_channels = params_channels(params); } __set_bit(cpu_dai->id, &mop500_ab8500_usage); mutex_unlock(&mop500_ab8500_params_lock); channels = params_channels(params); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S32_LE: sw_cpu = 32; break; case SNDRV_PCM_FORMAT_S16_LE: sw_cpu = 16; break; default: return -EINVAL; } /* Setup codec depending on driver-mode */ if (channels == 8) driver_mode = DRIVERMODE_CODEC_ONLY; else driver_mode = DRIVERMODE_NORMAL; dev_dbg(dev, "%s: Driver-mode: %s.\n", __func__, (driver_mode == DRIVERMODE_NORMAL) ? "NORMAL" : "CODEC_ONLY"); /* Setup format */ if (driver_mode == DRIVERMODE_NORMAL) { fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CONT; } else { fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_GATED; } ret = snd_soc_dai_set_fmt(codec_dai, fmt); if (ret < 0) { dev_err(dev, "%s: ERROR: snd_soc_dai_set_fmt failed for codec_dai (ret = %d)!\n", __func__, ret); return ret; } ret = snd_soc_dai_set_fmt(cpu_dai, fmt); if (ret < 0) { dev_err(dev, "%s: ERROR: snd_soc_dai_set_fmt failed for cpu_dai (ret = %d)!\n", __func__, ret); return ret; } /* Setup TDM-slots */ is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); switch (channels) { case 1: slots = 16; tx_slots = (is_playback) ? TX_SLOT_MONO : 0; rx_slots = (is_playback) ? 0 : RX_SLOT_MONO; break; case 2: slots = 16; tx_slots = (is_playback) ? TX_SLOT_STEREO : 0; rx_slots = (is_playback) ? 0 : RX_SLOT_STEREO; break; case 8: slots = 16; tx_slots = (is_playback) ? TX_SLOT_8CH : 0; rx_slots = (is_playback) ? 0 : RX_SLOT_8CH; break; default: return -EINVAL; } if (driver_mode == DRIVERMODE_NORMAL) sw_codec = sw_cpu; else sw_codec = 20; dev_dbg(dev, "%s: CPU-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, tx_slots, rx_slots); ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_slots, rx_slots, slots, sw_cpu); if (ret) return ret; dev_dbg(dev, "%s: CODEC-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, tx_slots, rx_slots); ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_slots, rx_slots, slots, sw_codec); if (ret) return ret; return 0; }
static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; struct omap_pcm_dma_data *dma_data; int dma, bus_id = mcbsp_data->bus_id; int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; int pkt_size = 0; unsigned long port; unsigned int format, div, framesize, master; dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream]; 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_omap34xx()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap34xx_mcbsp_port[bus_id][substream->stream]; } else if (cpu_is_omap44xx()) { dma = omap44xx_dma_reqs[bus_id][substream->stream]; port = omap44xx_mcbsp_port[bus_id][substream->stream]; } else { return -ENODEV; } switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; wlen = 16; break; case SNDRV_PCM_FORMAT_S32_LE: dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; wlen = 32; break; default: return -EINVAL; } if (cpu_is_omap34xx()) { dma_data->set_threshold = omap_mcbsp_set_threshold; /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ if (omap_mcbsp_get_dma_op_mode(bus_id) == MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; period_words = params_period_bytes(params) / (wlen / 8); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) max_thrsh = omap_mcbsp_get_max_tx_threshold( mcbsp_data->bus_id); else{ max_thrsh = omap_mcbsp_get_max_rx_threshold( mcbsp_data->bus_id); max_thrsh=1; } /* * If the period contains less or equal number of words, * we are using the original threshold mode setup: * McBSP threshold = sDMA frame size = period_size * Otherwise we switch to sDMA packet mode: * McBSP threshold = sDMA packet size * sDMA frame size = period size */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ if (period_words > max_thrsh) { int divider = 0; /* * Look for the biggest threshold value, which * divides the period size evenly. */ divider = period_words / max_thrsh; if (period_words % max_thrsh) divider++; while (period_words % divider && divider < period_words) divider++; if (divider == period_words) return -EINVAL; pkt_size = period_words / divider; sync_mode = OMAP_DMA_SYNC_PACKET; } else { sync_mode = OMAP_DMA_SYNC_FRAME; } } else { printk("DMA Element Sync Mode for recording \n"); sync_mode=OMAP_DMA_SYNC_ELEMENT; } } } dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback"; dma_data->dma_req = dma; dma_data->port_addr = port; dma_data->sync_mode = sync_mode; dma_data->packet_size = pkt_size; snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); 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 (channels == 2 && (format == SND_SOC_DAIFMT_I2S || format == SND_SOC_DAIFMT_LEFT_J)) { /* 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); } regs->rcr1 |= RFRLEN1(wpf - 1); regs->xcr1 |= XFRLEN1(wpf - 1); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: /* Set word lengths */ 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); break; case SNDRV_PCM_FORMAT_S32_LE: /* Set word lengths */ regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_32); break; default: /* Unsupported PCM format */ return -EINVAL; } /* In McBSP master modes, FRAME (i.e. sample rate) is generated * by _counting_ BCLKs. Calculate frame size in BCLKs */ master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK; if (master == SND_SOC_DAIFMT_CBS_CFS) { div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1; framesize = (mcbsp_data->in_freq / div) / params_rate(params); if (framesize < wlen * channels) { printk(KERN_ERR "%s: not enough bandwidth for desired rate and " "channels\n", __func__); return -EINVAL; } } else framesize = wlen * channels; /* Set FS period and length in terms of bit clock periods */ switch (format) { case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_LEFT_J: regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID((framesize >> 1) - 1); break; case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID(0); break; } omap_mcbsp_config(bus_id, &mcbsp_data->regs); mcbsp_data->wlen = wlen; mcbsp_data->configured = 1; return 0; }
static int aic32x4_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); u8 data; int i; i = aic32x4_get_divs(aic32x4->sysclk, params_rate(params)); if (i < 0) { printk(KERN_ERR "aic32x4: sampling rate not supported\n"); return i; } /* Use PLL as CODEC_CLKIN and DAC_MOD_CLK as BDIV_CLKIN */ snd_soc_write(codec, AIC32X4_CLKMUX, AIC32X4_PLLCLKIN); snd_soc_write(codec, AIC32X4_IFACE3, AIC32X4_DACMOD2BCLK); /* We will fix R value to 1 and will make P & J=K.D as varialble */ data = snd_soc_read(codec, AIC32X4_PLLPR); data &= ~(7 << 4); snd_soc_write(codec, AIC32X4_PLLPR, (data | (aic32x4_divs[i].p_val << 4) | 0x01)); snd_soc_write(codec, AIC32X4_PLLJ, aic32x4_divs[i].pll_j); snd_soc_write(codec, AIC32X4_PLLDMSB, (aic32x4_divs[i].pll_d >> 8)); snd_soc_write(codec, AIC32X4_PLLDLSB, (aic32x4_divs[i].pll_d & 0xff)); /* NDAC divider value */ data = snd_soc_read(codec, AIC32X4_NDAC); data &= ~(0x7f); snd_soc_write(codec, AIC32X4_NDAC, data | aic32x4_divs[i].ndac); /* MDAC divider value */ data = snd_soc_read(codec, AIC32X4_MDAC); data &= ~(0x7f); snd_soc_write(codec, AIC32X4_MDAC, data | aic32x4_divs[i].mdac); /* DOSR MSB & LSB values */ snd_soc_write(codec, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8); snd_soc_write(codec, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff)); /* NADC divider value */ data = snd_soc_read(codec, AIC32X4_NADC); data &= ~(0x7f); snd_soc_write(codec, AIC32X4_NADC, data | aic32x4_divs[i].nadc); /* MADC divider value */ data = snd_soc_read(codec, AIC32X4_MADC); data &= ~(0x7f); snd_soc_write(codec, AIC32X4_MADC, data | aic32x4_divs[i].madc); /* AOSR value */ snd_soc_write(codec, AIC32X4_AOSR, aic32x4_divs[i].aosr); /* BCLK N divider */ data = snd_soc_read(codec, AIC32X4_BCLKN); data &= ~(0x7f); snd_soc_write(codec, AIC32X4_BCLKN, data | aic32x4_divs[i].blck_N); data = snd_soc_read(codec, AIC32X4_IFACE1); data = data & ~(3 << 4); switch (params_width(params)) { case 16: break; case 20: data |= (AIC32X4_WORD_LEN_20BITS << AIC32X4_DOSRMSB_SHIFT); break; case 24: data |= (AIC32X4_WORD_LEN_24BITS << AIC32X4_DOSRMSB_SHIFT); break; case 32: data |= (AIC32X4_WORD_LEN_32BITS << AIC32X4_DOSRMSB_SHIFT); break; } snd_soc_write(codec, AIC32X4_IFACE1, data); if (params_channels(params) == 1) { data = AIC32X4_RDAC2LCHN | AIC32X4_LDAC2LCHN; } else { if (aic32x4->swapdacs) data = AIC32X4_RDAC2LCHN | AIC32X4_LDAC2RCHN; else data = AIC32X4_LDAC2LCHN | AIC32X4_RDAC2RCHN; } snd_soc_update_bits(codec, AIC32X4_DACSETUP, AIC32X4_DAC_CHAN_MASK, data); return 0; }
static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); snd_pcm_format_t format = params_format(params); unsigned int channels = params_channels(params); unsigned int rate = params_rate(params); unsigned int regval; int bitwidth, ret; bitwidth = snd_pcm_format_width(format); if (bitwidth < 0) { dev_err(dai->dev, "%s() invalid bit width given: %d\n", __func__, bitwidth); return bitwidth; } regval = LPAIF_I2SCTL_LOOPBACK_DISABLE | LPAIF_I2SCTL_WSSRC_INTERNAL; switch (bitwidth) { case 16: regval |= LPAIF_I2SCTL_BITWIDTH_16; break; case 24: regval |= LPAIF_I2SCTL_BITWIDTH_24; break; case 32: regval |= LPAIF_I2SCTL_BITWIDTH_32; break; default: dev_err(dai->dev, "%s() invalid bitwidth given: %d\n", __func__, bitwidth); return -EINVAL; } switch (channels) { case 1: regval |= LPAIF_I2SCTL_SPKMODE_SD0; regval |= LPAIF_I2SCTL_SPKMONO_MONO; break; case 2: regval |= LPAIF_I2SCTL_SPKMODE_SD0; regval |= LPAIF_I2SCTL_SPKMONO_STEREO; break; case 4: regval |= LPAIF_I2SCTL_SPKMODE_QUAD01; regval |= LPAIF_I2SCTL_SPKMONO_STEREO; break; case 6: regval |= LPAIF_I2SCTL_SPKMODE_6CH; regval |= LPAIF_I2SCTL_SPKMONO_STEREO; break; case 8: regval |= LPAIF_I2SCTL_SPKMODE_8CH; regval |= LPAIF_I2SCTL_SPKMONO_STEREO; break; default: dev_err(dai->dev, "%s() invalid channels given: %u\n", __func__, channels); return -EINVAL; } ret = regmap_write(drvdata->lpaif_map, LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), regval); if (ret) { dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", __func__, ret); return ret; } ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id], rate * bitwidth * 2); if (ret) { dev_err(dai->dev, "%s() error setting mi2s bitclk to %u: %d\n", __func__, rate * bitwidth * 2, ret); return ret; } return 0; }
static int msm_snd_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 *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret = 0; unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS]; unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0; unsigned int user_set_tx_ch = 0; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { pr_debug("%s: rx_0_ch=%d\n", __func__, msm_slim_0_rx_ch); ret = snd_soc_dai_get_channel_map(codec_dai, &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch); if (ret < 0) { pr_err("%s: failed to get codec chan map\n", __func__); goto end; } ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, msm_slim_0_rx_ch, rx_ch); if (ret < 0) { pr_err("%s: failed to set cpu chan map\n", __func__); goto end; } ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0, msm_slim_0_rx_ch, rx_ch); if (ret < 0) { pr_err("%s: failed to set codec channel map\n", __func__); goto end; } } else { if (codec_dai->id == 2) user_set_tx_ch = msm_slim_0_tx_ch; else if (codec_dai->id == 4) user_set_tx_ch = params_channels(params); pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__, codec_dai->name, codec_dai->id, user_set_tx_ch); ret = snd_soc_dai_get_channel_map(codec_dai, &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch); if (ret < 0) { pr_err("%s: failed to get codec chan map\n", __func__); goto end; } ret = snd_soc_dai_set_channel_map(cpu_dai, user_set_tx_ch, tx_ch, 0 , 0); if (ret < 0) { pr_err("%s: failed to set cpu chan map\n", __func__); goto end; } ret = snd_soc_dai_set_channel_map(codec_dai, user_set_tx_ch, tx_ch, 0, 0); if (ret < 0) { pr_err("%s: failed to set codec channel map\n", __func__); goto end; } } end: return ret; }
static int hdmi_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct hdmi_audio_data *ad = card_drvdata_substream(substream); struct snd_aes_iec958 *iec = &ad->iec; struct snd_cea_861_aud_if *cea = &ad->cea; WARN_ON(ad->current_stream != substream); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: ad->dma_data.maxburst = 16; break; case SNDRV_PCM_FORMAT_S24_LE: ad->dma_data.maxburst = 32; break; default: dev_err(dai->dev, "format not supported!\n"); return -EINVAL; } ad->dss_audio.iec = iec; ad->dss_audio.cea = cea; /* * fill the IEC-60958 channel status word */ /* initialize the word bytes */ memset(iec->status, 0, sizeof(iec->status)); /* specify IEC-60958-3 (commercial use) */ iec->status[0] &= ~IEC958_AES0_PROFESSIONAL; /* specify that the audio is LPCM*/ iec->status[0] &= ~IEC958_AES0_NONAUDIO; iec->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT; iec->status[0] |= IEC958_AES0_CON_EMPHASIS_NONE; iec->status[0] |= IEC958_AES1_PRO_MODE_NOTID; iec->status[1] = IEC958_AES1_CON_GENERAL; iec->status[2] |= IEC958_AES2_CON_SOURCE_UNSPEC; iec->status[2] |= IEC958_AES2_CON_CHANNEL_UNSPEC; switch (params_rate(params)) { case 32000: iec->status[3] |= IEC958_AES3_CON_FS_32000; break; case 44100: iec->status[3] |= IEC958_AES3_CON_FS_44100; break; case 48000: iec->status[3] |= IEC958_AES3_CON_FS_48000; break; case 88200: iec->status[3] |= IEC958_AES3_CON_FS_88200; break; case 96000: iec->status[3] |= IEC958_AES3_CON_FS_96000; break; case 176400: iec->status[3] |= IEC958_AES3_CON_FS_176400; break; case 192000: iec->status[3] |= IEC958_AES3_CON_FS_192000; break; default: dev_err(dai->dev, "rate not supported!\n"); return -EINVAL; } /* specify the clock accuracy */ iec->status[3] |= IEC958_AES3_CON_CLOCK_1000PPM; /* * specify the word length. The same word length value can mean * two different lengths. Hence, we need to specify the maximum * word length as well. */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: iec->status[4] |= IEC958_AES4_CON_WORDLEN_20_16; iec->status[4] &= ~IEC958_AES4_CON_MAX_WORDLEN_24; break; case SNDRV_PCM_FORMAT_S24_LE: iec->status[4] |= IEC958_AES4_CON_WORDLEN_24_20; iec->status[4] |= IEC958_AES4_CON_MAX_WORDLEN_24; break; default: dev_err(dai->dev, "format not supported!\n"); return -EINVAL; } /* * Fill the CEA-861 audio infoframe (see spec for details) */ cea->db1_ct_cc = (params_channels(params) - 1) & CEA861_AUDIO_INFOFRAME_DB1CC; cea->db1_ct_cc |= CEA861_AUDIO_INFOFRAME_DB1CT_FROM_STREAM; cea->db2_sf_ss = CEA861_AUDIO_INFOFRAME_DB2SF_FROM_STREAM; cea->db2_sf_ss |= CEA861_AUDIO_INFOFRAME_DB2SS_FROM_STREAM; cea->db3 = 0; /* not used, all zeros */ /* * The OMAP HDMI IP requires to use the 8-channel channel code when * transmitting more than two channels. */ if (params_channels(params) == 2) cea->db4_ca = 0x0; else cea->db4_ca = 0x13; cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED; /* the expression is trivial but makes clear what we are doing */ cea->db5_dminh_lsv |= (0 & CEA861_AUDIO_INFOFRAME_DB5_LSV); return ad->ops->audio_config(ad->dssdev, &ad->dss_audio); }
/* this may get called several times by oss emulation */ static int sst_byt_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct sst_byt_priv_data *pdata = snd_soc_platform_get_drvdata(rtd->platform); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; struct sst_byt *byt = pdata->byt; u32 rate, bits; u8 channels; int ret, playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); dev_dbg(rtd->dev, "PCM: hw_params, pcm_data %p\n", pcm_data); ret = sst_byt_stream_type(byt, pcm_data->stream, 1, 1, !playback); if (ret < 0) { dev_err(rtd->dev, "failed to set stream format %d\n", ret); return ret; } rate = params_rate(params); ret = sst_byt_stream_set_rate(byt, pcm_data->stream, rate); if (ret < 0) { dev_err(rtd->dev, "could not set rate %d\n", rate); return ret; } bits = snd_pcm_format_width(params_format(params)); ret = sst_byt_stream_set_bits(byt, pcm_data->stream, bits); if (ret < 0) { dev_err(rtd->dev, "could not set formats %d\n", params_rate(params)); return ret; } channels = (u8)(params_channels(params) & 0xF); ret = sst_byt_stream_set_channels(byt, pcm_data->stream, channels); if (ret < 0) { dev_err(rtd->dev, "could not set channels %d\n", params_rate(params)); return ret; } snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); ret = sst_byt_stream_buffer(byt, pcm_data->stream, substream->dma_buffer.addr, params_buffer_bytes(params)); if (ret < 0) { dev_err(rtd->dev, "PCM: failed to set DMA buffer %d\n", ret); return ret; } ret = sst_byt_stream_commit(byt, pcm_data->stream); if (ret < 0) { dev_err(rtd->dev, "PCM: failed stream commit %d\n", ret); return ret; } return 0; }
static int max98371_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct max98371_priv *max98371 = snd_soc_codec_get_drvdata(codec); int blr_clk_ratio, ch_size, channels = params_channels(params); int rate = params_rate(params); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: regmap_update_bits(max98371->regmap, MAX98371_FMT, MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_16); ch_size = 8; break; case SNDRV_PCM_FORMAT_S16_LE: regmap_update_bits(max98371->regmap, MAX98371_FMT, MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_16); ch_size = 16; break; case SNDRV_PCM_FORMAT_S24_LE: regmap_update_bits(max98371->regmap, MAX98371_FMT, MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_32); ch_size = 24; break; case SNDRV_PCM_FORMAT_S32_LE: regmap_update_bits(max98371->regmap, MAX98371_FMT, MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_32); ch_size = 32; break; default: return -EINVAL; } /* BCLK/LRCLK ratio calculation */ blr_clk_ratio = channels * ch_size; switch (blr_clk_ratio) { case 32: regmap_update_bits(max98371->regmap, MAX98371_DAI_CLK, MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_32); break; case 48: regmap_update_bits(max98371->regmap, MAX98371_DAI_CLK, MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_48); break; case 64: regmap_update_bits(max98371->regmap, MAX98371_DAI_CLK, MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_64); break; default: return -EINVAL; } switch (rate) { case 32000: regmap_update_bits(max98371->regmap, MAX98371_SPK_SR, MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_32); break; case 44100: regmap_update_bits(max98371->regmap, MAX98371_SPK_SR, MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_44); break; case 48000: regmap_update_bits(max98371->regmap, MAX98371_SPK_SR, MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_48); break; case 88200: regmap_update_bits(max98371->regmap, MAX98371_SPK_SR, MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_88); break; case 96000: regmap_update_bits(max98371->regmap, MAX98371_SPK_SR, MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_96); break; default: return -EINVAL; } /* enabling both the RX channels*/ regmap_update_bits(max98371->regmap, MAX98371_MONOMIX_SRC, MAX98371_MONOMIX_SRC_MASK, MONOMIX_RX_0_1); regmap_update_bits(max98371->regmap, MAX98371_DAI_CHANNEL, MAX98371_CHANNEL_MASK, MAX98371_CHANNEL_MASK); return 0; }
static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai_link *dai = rtd->dai; struct s3c_pcm_info *pcm = to_info(dai->cpu_dai); struct s3c_dma_params *dma_data; void __iomem *regs = pcm->regs; struct clk *clk; int sclk_div, sync_div; unsigned long flags; u32 clkctl; u32 dma_tsfr_size = 0; /* added by LiXueZhong on 2013.09.25 */ unsigned long srcrate; unsigned long rate; dev_dbg(pcm->dev, "Entered %s\n", __func__); switch (params_channels(params)) { case 1: dma_tsfr_size = 2; break; case 2: dma_tsfr_size = 4; break; case 4: break; case 6: break; default: break; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { pcm->dma_playback->dma_size = dma_tsfr_size; dma_data = pcm->dma_playback; } else { pcm->dma_capture->dma_size = dma_tsfr_size; dma_data = pcm->dma_capture; } snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); /* Strictly check for sample size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: break; default: return -EINVAL; } spin_lock_irqsave(&pcm->lock, flags); /* Get hold of the PCMSOURCE_CLK */ clkctl = readl(regs + S3C_PCM_CLKCTL); if (clkctl & S3C_PCM_CLKCTL_SERCLKSEL_PCLK) clk = pcm->pclk; else clk = pcm->cclk; /* Set the SCLK divider */ ////////////////////////////////////////// /* modified by LiXueZhong on 2013.09.25 */ srcrate = clk_get_rate(clk); DBG("--- CLK = %u ---\n", srcrate); rate = pcm->sclk_per_fs * params_rate(params) * 2; sclk_div = srcrate / rate; if (srcrate % rate) sclk_div++; --sclk_div; /////////////////////////////////////////// clkctl &= ~(S3C_PCM_CLKCTL_SCLKDIV_MASK << S3C_PCM_CLKCTL_SCLKDIV_SHIFT); clkctl |= ((sclk_div & S3C_PCM_CLKCTL_SCLKDIV_MASK) << S3C_PCM_CLKCTL_SCLKDIV_SHIFT); /* Set the SYNC divider */ sync_div = pcm->sclk_per_fs - 1; clkctl &= ~(S3C_PCM_CLKCTL_SYNCDIV_MASK << S3C_PCM_CLKCTL_SYNCDIV_SHIFT); clkctl |= ((sync_div & S3C_PCM_CLKCTL_SYNCDIV_MASK) << S3C_PCM_CLKCTL_SYNCDIV_SHIFT); writel(clkctl, regs + S3C_PCM_CLKCTL); spin_unlock_irqrestore(&pcm->lock, flags); /* dev_dbg(pcm->dev, "SOURCE_CLK-%lu SCLK=%ufs SCLK_DIV=%d SYNC_DIV=%d\n", clk_get_rate(clk), pcm->sclk_per_fs, sclk_div, sync_div); */ DBG("--- SOURCE_CLK-%lu SCLK=%ufs SCLK_DIV=%d SYNC_DIV=%d ---\n", clk_get_rate(clk), pcm->sclk_per_fs, sclk_div, sync_div); return 0; }
static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; struct snd_dmaengine_dai_dma_data *dma_data; int wlen, channels, wpf; int pkt_size = 0; unsigned int format, div, framesize, master; dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); channels = params_channels(params); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: wlen = 16; break; case SNDRV_PCM_FORMAT_S32_LE: wlen = 32; break; default: return -EINVAL; } if (mcbsp->pdata->buffer_size) { if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; int divider = 0; period_words = params_period_bytes(params) / (wlen / 8); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) max_thrsh = mcbsp->max_tx_thres; else max_thrsh = mcbsp->max_rx_thres; /* * Use sDMA packet mode if McBSP is in threshold mode: * If period words less than the FIFO size the packet * size is set to the number of period words, otherwise * Look for the biggest threshold value which divides * the period size evenly. */ divider = period_words / max_thrsh; if (period_words % max_thrsh) divider++; while (period_words % divider && divider < period_words) divider++; if (divider == period_words) return -EINVAL; pkt_size = period_words / divider; } else if (channels > 1) { /* Use packet mode for non mono streams */ pkt_size = channels; } omap_mcbsp_set_threshold(substream, pkt_size); } dma_data->maxburst = pkt_size; if (mcbsp->configured) { /* McBSP already configured by another stream */ return 0; } regs->rcr2 &= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7)); regs->xcr2 &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7)); regs->rcr1 &= ~(RFRLEN1(0x7f) | RWDLEN1(7)); regs->xcr1 &= ~(XFRLEN1(0x7f) | XWDLEN1(7)); format = mcbsp->fmt & SND_SOC_DAIFMT_FORMAT_MASK; wpf = channels; if (channels == 2 && (format == SND_SOC_DAIFMT_I2S || format == SND_SOC_DAIFMT_LEFT_J)) { /* 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); } regs->rcr1 |= RFRLEN1(wpf - 1); regs->xcr1 |= XFRLEN1(wpf - 1); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: /* Set word lengths */ 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); break; case SNDRV_PCM_FORMAT_S32_LE: /* Set word lengths */ regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_32); break; default: /* Unsupported PCM format */ return -EINVAL; } /* In McBSP master modes, FRAME (i.e. sample rate) is generated * by _counting_ BCLKs. Calculate frame size in BCLKs */ master = mcbsp->fmt & SND_SOC_DAIFMT_MASTER_MASK; if (master == SND_SOC_DAIFMT_CBS_CFS) { div = mcbsp->clk_div ? mcbsp->clk_div : 1; framesize = (mcbsp->in_freq / div) / params_rate(params); if (framesize < wlen * channels) { printk(KERN_ERR "%s: not enough bandwidth for desired rate and " "channels\n", __func__); return -EINVAL; } } else framesize = wlen * channels; /* Set FS period and length in terms of bit clock periods */ regs->srgr2 &= ~FPER(0xfff); regs->srgr1 &= ~FWID(0xff); switch (format) { case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_LEFT_J: regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID((framesize >> 1) - 1); break; case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID(0); break; } omap_mcbsp_config(mcbsp, &mcbsp->cfg_regs); mcbsp->wlen = wlen; mcbsp->configured = 1; return 0; }
static int dw_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); struct i2s_clk_config_data *config = &dev->config; int ret; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: config->data_width = 16; dev->ccr = 0x00; dev->xfer_resolution = 0x02; break; case SNDRV_PCM_FORMAT_S24_LE: config->data_width = 24; dev->ccr = 0x08; dev->xfer_resolution = 0x04; break; case SNDRV_PCM_FORMAT_S32_LE: config->data_width = 32; dev->ccr = 0x10; dev->xfer_resolution = 0x05; break; default: dev_err(dev->dev, "designware-i2s: unsupported PCM fmt"); return -EINVAL; } config->chan_nr = params_channels(params); switch (config->chan_nr) { case EIGHT_CHANNEL_SUPPORT: case SIX_CHANNEL_SUPPORT: case FOUR_CHANNEL_SUPPORT: case TWO_CHANNEL_SUPPORT: break; default: dev_err(dev->dev, "channel not supported\n"); return -EINVAL; } dw_i2s_config(dev, substream->stream); i2s_write_reg(dev->i2s_base, CCR, dev->ccr); config->sample_rate = params_rate(params); if (dev->capability & DW_I2S_MASTER) { if (dev->i2s_clk_cfg) { ret = dev->i2s_clk_cfg(config); if (ret < 0) { dev_err(dev->dev, "runtime audio clk config fail\n"); return ret; } } else { u32 bitclk = config->sample_rate * config->data_width * 2; ret = clk_set_rate(dev->clk, bitclk); if (ret) { dev_err(dev->dev, "Can't set I2S clock rate: %d\n", ret); return ret; } } } return 0; }
static int tegra_wm8903_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 *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = codec->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); int srate, mclk, i2s_daifmt; int err; struct clk *clk_m; int rate; srate = params_rate(params); switch (srate) { case 64000: case 88200: case 96000: mclk = 128 * srate; break; default: mclk = 256 * srate; break; } clk_m = clk_get_sys(NULL, "clk_m"); if (IS_ERR(clk_m)) { dev_err(card->dev, "Can't retrieve clk clk_m\n"); err = PTR_ERR(clk_m); return err; } rate = clk_get_rate(clk_m); printk("extern1 rate=%d\n",rate); #if TEGRA30_I2S_MASTER_PLAYBACK /* FIXME: Codec only requires >= 3MHz if OSR==0 */ while (mclk < 6000000) mclk *= 2; i2s_daifmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; #else mclk = rate; i2s_daifmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; #endif err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); if (err < 0) { if (!(machine->util_data.set_mclk % mclk)) mclk = machine->util_data.set_mclk; else { dev_err(card->dev, "Can't configure clocks\n"); return err; } } tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1); /* Use DSP mode for mono on Tegra20 */ if ((params_channels(params) != 2) && (machine_is_ventana() || machine_is_harmony() || machine_is_kaen() || machine_is_aebl())) i2s_daifmt |= SND_SOC_DAIFMT_DSP_A; else i2s_daifmt |= SND_SOC_DAIFMT_I2S; err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "codec_dai fmt not set\n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "cpu_dai fmt not set\n"); return err; } err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); return err; } #ifdef CONFIG_ARCH_TEGRA_2x_SOC err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC1, TEGRA20_DAS_DAP_ID_1); if (err < 0) { dev_err(card->dev, "failed to set dap-dac path\n"); return err; } err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1, TEGRA20_DAS_DAP_SEL_DAC1); if (err < 0) { dev_err(card->dev, "failed to set dac-dap path\n"); return err; } #endif return 0; }
static int tegra_max98088_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 *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = codec->card; struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card); #ifndef CONFIG_ARCH_TEGRA_2x_SOC struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai); #endif int srate, mclk, sample_size, i2s_daifmt; int err; struct clk *clk; int rate; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: sample_size = 16; break; default: return -EINVAL; } srate = params_rate(params); switch (srate) { case 8000: case 16000: case 24000: case 32000: case 48000: case 64000: case 96000: mclk = 12288000; break; case 11025: case 22050: case 44100: case 88200: mclk = 11289600; break; default: mclk = 12000000; break; } #if defined(CONFIG_ARCH_TEGRA_2x_SOC) clk = clk_get_sys(NULL, "cdev1"); #else clk = clk_get_sys("extern1", NULL); #endif if (IS_ERR(clk)) { dev_err(card->dev, "Can't retrieve clk cdev1\n"); err = PTR_ERR(clk); return err; } rate = clk_get_rate(clk); printk("extern1 rate=%d\n",rate); #if TEGRA30_I2S_MASTER_PLAYBACK i2s_daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; #else i2s_daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; mclk = rate; #endif err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); if (err < 0) { if (!(machine->util_data.set_mclk % mclk)) mclk = machine->util_data.set_mclk; else { dev_err(card->dev, "Can't configure clocks\n"); return err; } } tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1); err = snd_soc_dai_set_fmt(codec_dai,i2s_daifmt); if (err < 0) { dev_err(card->dev, "codec_dai fmt not set\n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "cpu_dai fmt not set\n"); return err; } err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); return err; } #ifndef CONFIG_ARCH_TEGRA_2x_SOC if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) tegra_max98088_set_dam_cif(i2s->dam_ifc, srate, params_channels(params), sample_size, 0, 0, 0, 0); #endif return 0; }
static int tegra_max98095_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 *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = codec->card; struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card); struct tegra_asoc_platform_data *pdata = machine->pdata; #ifndef CONFIG_ARCH_TEGRA_2x_SOC struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai); #endif unsigned int srate, mclk, sample_size, i2s_daifmt; int err, rate; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: sample_size = 16; break; default: return -EINVAL; } srate = params_rate(params); switch (srate) { case 8000: case 16000: case 24000: case 32000: case 48000: case 64000: case 96000: mclk = 12288000; break; case 11025: case 22050: case 44100: case 88200: mclk = 11289600; break; default: mclk = 12000000; break; } i2s_daifmt = SND_SOC_DAIFMT_NB_NF; i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ? SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM; switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) { case TEGRA_DAIFMT_I2S : i2s_daifmt |= SND_SOC_DAIFMT_I2S; break; case TEGRA_DAIFMT_DSP_A : i2s_daifmt |= SND_SOC_DAIFMT_DSP_A; break; case TEGRA_DAIFMT_DSP_B : i2s_daifmt |= SND_SOC_DAIFMT_DSP_B; break; case TEGRA_DAIFMT_LEFT_J : i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J; break; case TEGRA_DAIFMT_RIGHT_J : i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J; break; default : dev_err(card->dev, "Can't configure i2s format\n"); return -EINVAL; } err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); if (err < 0) { if (!(machine->util_data.set_mclk % mclk)) mclk = machine->util_data.set_mclk; else { dev_err(card->dev, "Can't configure clocks\n"); return err; } } tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1); rate = clk_get_rate(machine->util_data.clk_cdev1); err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "codec_dai fmt not set\n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "cpu_dai fmt not set\n"); return err; } err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); return err; } #ifndef CONFIG_ARCH_TEGRA_2x_SOC if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) tegra_max98095_set_dam_cif(i2s->dam_ifc, srate, params_channels(params), sample_size); #endif return 0; }
static int tegra_bt_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; #ifndef CONFIG_ARCH_TEGRA_2x_SOC struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai); #endif struct snd_soc_card *card = rtd->card; struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card); int err, srate, mclk, min_mclk, sample_size; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: sample_size = 16; break; default: return -EINVAL; } srate = params_rate(params); switch (srate) { case 11025: case 22050: case 44100: case 88200: mclk = 11289600; break; case 8000: case 16000: case 32000: case 48000: case 64000: case 96000: mclk = 12288000; break; default: return -EINVAL; } min_mclk = 64 * srate; err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); if (err < 0) { if (!(machine->util_data.set_mclk % min_mclk)) mclk = machine->util_data.set_mclk; else { dev_err(card->dev, "Can't configure clocks\n"); return err; } } tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1); err = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (err < 0) { dev_err(rtd->codec->card->dev, "cpu_dai fmt not set\n"); return err; } #ifndef CONFIG_ARCH_TEGRA_2x_SOC if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) tegra_max98088_set_dam_cif(i2s->dam_ifc, params_rate(params), params_channels(params), sample_size, 0, 0, 0, 0); #endif return 0; }
static int wm8940_i2s_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_codec *codec = rtd->codec; u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F; u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1; u16 companding = snd_soc_read(codec, WM8940_COMPANDINGCTL) & 0xFFDF; int ret; /* LoutR control */ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && params_channels(params) == 2) iface |= (1 << 9); switch (params_rate(params)) { case 8000: addcntrl |= (0x5 << 1); break; case 11025: addcntrl |= (0x4 << 1); break; case 16000: addcntrl |= (0x3 << 1); break; case 22050: addcntrl |= (0x2 << 1); break; case 32000: addcntrl |= (0x1 << 1); break; case 44100: case 48000: break; } ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl); if (ret) goto error_ret; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: companding = companding | (1 << 5); break; case SNDRV_PCM_FORMAT_S16_LE: break; case SNDRV_PCM_FORMAT_S20_3LE: iface |= (1 << 5); break; case SNDRV_PCM_FORMAT_S24_LE: iface |= (2 << 5); break; case SNDRV_PCM_FORMAT_S32_LE: iface |= (3 << 5); break; } ret = snd_soc_write(codec, WM8940_COMPANDINGCTL, companding); if (ret) goto error_ret; ret = snd_soc_write(codec, WM8940_IFACE, iface); error_ret: return ret; }
static int tegra_voice_call_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 *codec_dai = rtd->codec_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = codec->card; struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card); int srate, mclk; int err; srate = params_rate(params); switch (srate) { case 8000: case 16000: case 24000: case 32000: case 48000: case 64000: case 96000: mclk = 12288000; break; case 11025: case 22050: case 44100: case 88200: mclk = 11289600; break; default: return -EINVAL; break; } err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); if (err < 0) { if (!(machine->util_data.set_mclk % mclk)) mclk = machine->util_data.set_mclk; else { dev_err(card->dev, "Can't configure clocks\n"); return err; } } tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1); err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (err < 0) { dev_err(card->dev, "codec_dai fmt not set\n"); return err; } err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); return err; } #ifndef CONFIG_ARCH_TEGRA_2x_SOC /* codec configuration */ machine->codec_info[HIFI_CODEC].rate = params_rate(params); machine->codec_info[HIFI_CODEC].channels = params_channels(params); machine->codec_info[HIFI_CODEC].bitsize = 16; machine->codec_info[HIFI_CODEC].is_i2smaster = 1; machine->codec_info[HIFI_CODEC].is_format_dsp = 0; /* baseband configuration */ machine->codec_info[BASEBAND].bitsize = 16; machine->codec_info[BASEBAND].is_i2smaster = 1; machine->codec_info[BASEBAND].is_format_dsp = 1; #endif machine->is_device_bt = 0; return 0; }
int ux500_cg29xx_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_dai *codec_dai = rtd->codec_dai; int channels = params_channels(params); int err; pr_debug("%s: Enter.\n", __func__); pr_debug("%s: substream->pcm->name = %s.\n", __func__, substream->pcm->name); pr_debug("%s: substream->pcm->id = %s.\n", __func__, substream->pcm->id); pr_debug("%s: substream->name = %s.\n", __func__, substream->name); pr_debug("%s: substream->number = %d.\n", __func__, substream->number); pr_debug("%s: channels = %d.\n", __func__, channels); pr_debug("%s: DAI-index (Codec): %d\n", __func__, codec_dai->id); pr_debug("%s: DAI-index (Platform): %d\n", __func__, cpu_dai->id); err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS); if (err) { pr_err("%s: snd_soc_dai_set_fmt(codec) failed with %d.\n", __func__, err); goto out_err; } err = snd_soc_dai_set_tdm_slot(codec_dai, 1 << CG29XX_DAI_SLOT0_SHIFT, 1 << CG29XX_DAI_SLOT0_SHIFT, UX500_CG29XX_DAI_SLOTS, UX500_CG29XX_DAI_SLOT_WIDTH); if (err) { pr_err("%s: cg29xx_set_tdm_slot(codec_dai) failed with %d.\n", __func__, err); goto out_err; } err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_NB_NF); if (err) { pr_err("%s: snd_soc_dai_set_fmt(cpu_dai) failed with %d.\n", __func__, err); goto out_err; } err = snd_soc_dai_set_sysclk(cpu_dai, UX500_MSP_MASTER_CLOCK, UX500_CG29XX_MSP_CLOCK_FREQ, 0); if (err) { pr_err("%s: snd_soc_dai_set_sysclk(cpu_dai) failed with %d.\n", __func__, err); goto out_err; } err = snd_soc_dai_set_tdm_slot(cpu_dai, UX500_CG29XX_DAI_ACTIVE_SLOTS, UX500_CG29XX_DAI_ACTIVE_SLOTS, UX500_CG29XX_DAI_SLOTS, UX500_CG29XX_DAI_SLOT_WIDTH); if (err) { pr_err("%s: cg29xx_set_tdm_slot(cpu_dai) failed with %d.\n", __func__, err); goto out_err; } out_err: return err; }
/** * Set default hardware params */ static int playback_prepare_params(struct gaudio_snd_dev *snd) { struct snd_pcm_substream *substream = snd->substream; struct snd_pcm_hw_params *params; snd_pcm_sframes_t result; /* * SNDRV_PCM_ACCESS_RW_INTERLEAVED, * SNDRV_PCM_FORMAT_S16_LE * CHANNELS: 2 * RATE: 8000 */ snd->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED; snd->format = SNDRV_PCM_FORMAT_S16_LE; snd->channels = 2; snd->rate = 8000; params = kzalloc(sizeof(*params), GFP_KERNEL); if (!params) return -ENOMEM; _snd_pcm_hw_params_any(params); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS, snd->access, 0); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT, snd->format, 0); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS, snd->channels, 0); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE, snd->rate, 0); result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); if (result < 0) pr_err("SNDRV_PCM_IOCTL_DROP failed: %d\n", (int)result); result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, params); if (result < 0) { pr_err("SNDRV_PCM_IOCTL_HW_PARAMS failed: %d\n", (int)result); kfree(params); return result; } result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); if (result < 0) pr_err("Preparing playback failed: %d\n", (int)result); /* Store the hardware parameters */ snd->access = params_access(params); snd->format = params_format(params); snd->channels = params_channels(params); snd->rate = params_rate(params); kfree(params); pr_debug("playback params: access %x, format %x, channels %d, rate %d\n", snd->access, snd->format, snd->channels, snd->rate); return 0; }
static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); unsigned int i2s_reg, reg; unsigned long i2s_value, value; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { i2s_reg = KIRKWOOD_I2S_PLAYCTL; reg = KIRKWOOD_PLAYCTL; } else { i2s_reg = KIRKWOOD_I2S_RECCTL; reg = KIRKWOOD_RECCTL; } /* set dco conf */ kirkwood_set_dco(priv->io, params_rate(params)); i2s_value = readl(priv->io+i2s_reg); i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK; value = readl(priv->io+reg); value &= ~KIRKWOOD_PLAYCTL_SIZE_MASK; /* * Size settings in play/rec i2s control regs and play/rec control * regs must be the same. */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16; value |= KIRKWOOD_PLAYCTL_SIZE_16_C; break; /* * doesn't work... S20_3LE != kirkwood 20bit format ? * case SNDRV_PCM_FORMAT_S20_3LE: i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20; value |= KIRKWOOD_PLAYCTL_SIZE_20; break; */ case SNDRV_PCM_FORMAT_S24_LE: i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24; value |= KIRKWOOD_PLAYCTL_SIZE_24; break; case SNDRV_PCM_FORMAT_S32_LE: i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32; value |= KIRKWOOD_PLAYCTL_SIZE_32; break; default: return -EINVAL; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { value &= ~KIRKWOOD_PLAYCTL_MONO_MASK; if (params_channels(params) == 1) value |= KIRKWOOD_PLAYCTL_MONO_BOTH; else value |= KIRKWOOD_PLAYCTL_MONO_OFF; } writel(i2s_value, priv->io+i2s_reg); writel(value, priv->io+reg); return 0; }
static int capture_prepare_params(struct gaudio_snd_dev *snd) { struct snd_pcm_substream *substream = snd->substream; struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_hw_params *params; struct snd_pcm_sw_params *swparams; unsigned long period_size; unsigned long buffer_size; snd_pcm_sframes_t result = 0; /* * SNDRV_PCM_ACCESS_RW_INTERLEAVED, * SNDRV_PCM_FORMAT_S16_LE * CHANNELS: 1 * RATE: 8000 */ snd->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED; snd->format = SNDRV_PCM_FORMAT_S16_LE; snd->channels = 1; snd->rate = 8000; params = kzalloc(sizeof(*params), GFP_KERNEL); if (!params) { pr_err("Failed to allocate hw params"); return -ENOMEM; } _snd_pcm_hw_params_any(params); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS, snd->access, 0); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT, snd->format, 0); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS, snd->channels, 0); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE, snd->rate, 0); result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); if (result < 0) pr_err("SNDRV_PCM_IOCTL_DROP failed: %d\n", (int)result); result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, params); if (result < 0) { pr_err("SNDRV_PCM_IOCTL_HW_PARAMS failed: %d\n", (int)result); kfree(params); return result; } result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); if (result < 0) pr_err("Preparing capture failed: %d\n", (int)result); /* Store the hardware parameters */ snd->access = params_access(params); snd->format = params_format(params); snd->channels = params_channels(params); snd->rate = params_rate(params); runtime->frame_bits = snd_pcm_format_physical_width(runtime->format); /*Fix the issue:Passing freed pointer "params" as an argument to function "pcm_buffer_size"*/ buffer_size = pcm_buffer_size(params); period_size = pcm_period_size(params); kfree(params); swparams = kzalloc(sizeof(*swparams), GFP_KERNEL); if (!swparams) { pr_err("Failed to allocate sw params"); return -ENOMEM; } swparams->avail_min = period_size/2; swparams->xfer_align = period_size/2; swparams->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; swparams->period_step = 1; swparams->start_threshold = 1; swparams->stop_threshold = INT_MAX; swparams->silence_size = 0; swparams->silence_threshold = 0; result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, swparams); if (result < 0) pr_err("SNDRV_PCM_IOCTL_SW_PARAMS failed: %d\n", (int)result); kfree(swparams); pr_debug("capture params: access %x, format %x, channels %d, rate %d\n", snd->access, snd->format, snd->channels, snd->rate); return result; }
static int msm_hdmi_audio_codec_rx_dai_hw_params( struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { u32 channel_allocation = 0; u32 level_shift = 0; bool down_mix = 0; u32 num_channels = params_channels(params); int rc = 0; struct msm_hdmi_audio_codec_rx_data *codec_data = dev_get_drvdata(dai->codec->dev); rc = codec_data->hdmi_ops.hdmi_cable_status( codec_data->hdmi_core_pdev, 1); pr_info("%s: hdmi status %d\n",__func__,rc); if (IS_ERR_VALUE(rc) || rc == 0) { rc = -EINVAL; dev_err(dai->dev, "%s() HDMI core is not ready 1\n", __func__); return rc; } if (IS_ERR_VALUE(msm_hdmi_audio_codec_return_value)) { dev_err(dai->dev, "%s() HDMI core is not ready 2\n", __func__); return msm_hdmi_audio_codec_return_value; } switch (num_channels) { case 2: channel_allocation = 0; break; case 3: channel_allocation = 0x02; break; case 4: channel_allocation = 0x06; break; case 5: channel_allocation = 0x0A; break; case 6: channel_allocation = 0x0B; break; case 7: channel_allocation = 0x12; break; case 8: channel_allocation = 0x13; break; default: dev_err(dai->dev, "invalid Channels = %u\n", num_channels); return -EINVAL; } dev_dbg(dai->dev, "%s() num_ch %u samplerate %u channel_allocation = %u\n", __func__, num_channels, params_rate(params), channel_allocation); rc = codec_data->hdmi_ops.audio_info_setup( codec_data->hdmi_core_pdev, params_rate(params), num_channels, channel_allocation, level_shift, down_mix); if (IS_ERR_VALUE(rc)) { dev_err(dai->dev, "%s() HDMI core is not ready 3\n", __func__); } return rc; }
/* * Configure the SSC */ static int at32_ssc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; int id = rtd->dai->cpu_dai->id; struct at32_ssc_info *ssc_p = &ssc_info[id]; struct at32_pcm_dma_params *dma_params; int channels, bits; u32 tfmr, rfmr, tcmr, rcmr; int start_event; int ret; /* * Currently, there is only one set of dma_params for each direction. * If more are added, this code will have to be changed to select * the proper set */ dma_params = &ssc_dma_params[id][substream->stream]; dma_params->ssc = ssc_p->ssc; dma_params->substream = substream; ssc_p->dma_params[substream->stream] = dma_params; /* * The cpu_dai->dma_data field is only used to communicate the * appropriate DMA parameters to the PCM driver's hw_params() * function. It should not be used for other purposes as it * is common to all substreams. */ rtd->dai->cpu_dai->dma_data = dma_params; channels = params_channels(params); /* * Determine sample size in bits and the PDC increment */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: bits = 8; dma_params->pdc_xfer_size = 1; break; case SNDRV_PCM_FORMAT_S16: bits = 16; dma_params->pdc_xfer_size = 2; break; case SNDRV_PCM_FORMAT_S24: bits = 24; dma_params->pdc_xfer_size = 4; break; case SNDRV_PCM_FORMAT_S32: bits = 32; dma_params->pdc_xfer_size = 4; break; default: pr_warning("at32-ssc: Unsupported PCM format %d", params_format(params)); return -EINVAL; } pr_debug("at32-ssc: bits = %d, pdc_xfer_size = %d, channels = %d\n", bits, dma_params->pdc_xfer_size, channels); /* * The SSC only supports up to 16-bit samples in I2S format, due * to the size of the Frame Mode Register FSLEN field. */ if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) if (bits > 16) { pr_warning("at32-ssc: " "sample size %d is too large for I2S\n", bits); return -EINVAL; } /* * Compute the SSC register settings */ switch (ssc_p->daifmt & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: /* * I2S format, SSC provides BCLK and LRS clocks. * * The SSC transmit and receive clocks are generated from the * MCK divider, and the BCLK signal is output on the SSC TK line */ pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME master\n"); rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | SSC_BF(RCMR_STTDLY, START_DELAY) | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, SSC_CKS_DIV)); rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | SSC_BF(RFMR_FSLEN, bits - 1) | SSC_BF(RFMR_DATNB, channels - 1) | SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1)); tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) | SSC_BF(TCMR_STTDLY, START_DELAY) | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | SSC_BF(TCMR_CKS, SSC_CKS_DIV)); tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | SSC_BF(TFMR_FSLEN, bits - 1) | SSC_BF(TFMR_DATNB, channels - 1) | SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1)); break; case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: /* * I2S format, CODEC supplies BCLK and LRC clock. * * The SSC transmit clock is obtained from the BCLK signal * on the TK line, and the SSC receive clock is generated from * the transmit clock. * * For single channel data, one sample is transferred on the * falling edge of the LRC clock. For two channel data, one * sample is transferred on both edges of the LRC clock. */ pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME slave\n"); start_event = ((channels == 1) ? SSC_START_FALLING_RF : SSC_START_EDGE_RF); rcmr = (SSC_BF(RCMR_STTDLY, START_DELAY) | SSC_BF(RCMR_START, start_event) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK)); rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1)); tcmr = (SSC_BF(TCMR_STTDLY, START_DELAY) | SSC_BF(TCMR_START, start_event) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | SSC_BF(TCMR_CKS, SSC_CKS_PIN)); tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) | SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1)); break; case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: /* * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. * * The SSC transmit and receive clocks are generated from the * MCK divider, and the BCLK signal is output on the SSC TK line */ pr_debug("at32-ssc: SSC mode is DSP A BCLK / FRAME master\n"); rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | SSC_BF(RCMR_STTDLY, 1) | SSC_BF(RCMR_START, SSC_START_RISING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, SSC_CKS_DIV)); rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) | SSC_BF(RFMR_DATNB, channels - 1) | SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1)); tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) | SSC_BF(TCMR_STTDLY, 1) | SSC_BF(TCMR_START, SSC_START_RISING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_RISING) | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | SSC_BF(TCMR_CKS, SSC_CKS_DIV)); tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) | SSC_BF(TFMR_DATNB, channels - 1) | SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1)); break; case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: default: pr_warning("at32-ssc: unsupported DAI format 0x%x\n", ssc_p->daifmt); return -EINVAL; break; } pr_debug("at32-ssc: RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr); if (!ssc_p->initialized) { /* enable peripheral clock */ pr_debug("at32-ssc: Starting clock\n"); clk_enable(ssc_p->ssc->clk); /* Reset the SSC and its PDC registers */ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0); ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0); ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0); ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0); ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0); ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0); ret = request_irq(ssc_p->ssc->irq, at32_ssc_interrupt, 0, ssc_p->name, ssc_p); if (ret < 0) { pr_warning("at32-ssc: request irq failed (%d)\n", ret); pr_debug("at32-ssc: Stopping clock\n"); clk_disable(ssc_p->ssc->clk); return ret; } ssc_p->initialized = 1; } /* Set SSC clock mode register */ ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div); /* set receive clock mode and format */ ssc_writel(ssc_p->ssc->regs, RCMR, rcmr); ssc_writel(ssc_p->ssc->regs, RFMR, rfmr); /* set transmit clock mode and format */ ssc_writel(ssc_p->ssc->regs, TCMR, tcmr); ssc_writel(ssc_p->ssc->regs, TFMR, tfmr); pr_debug("at32-ssc: SSC initialized\n"); return 0; }
static int tegra_rt5631_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 *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = codec->card; struct tegra_rt5631 *machine = snd_soc_card_get_drvdata(card); int srate, mclk, i2s_daifmt; int err; srate = params_rate(params); switch (srate) { case 64000: case 88200: case 96000: mclk = 128 * srate; break; default: mclk = 384 * srate; break; } /* FIXME: Codec only requires >= 3MHz if OSR==0 */ while (mclk < 6000000) mclk *= 2; err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); if (err < 0) { dev_err(card->dev, "Can't configure clocks\n"); return err; } i2s_daifmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; /* Use DSP mode for mono on Tegra20 */ if ((params_channels(params) != 2) && (machine_is_ventana() || machine_is_harmony() || machine_is_kaen() || machine_is_aebl())) i2s_daifmt |= SND_SOC_DAIFMT_DSP_A; else i2s_daifmt |= SND_SOC_DAIFMT_I2S; err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "codec_dai fmt not set\n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "cpu_dai fmt not set\n"); return err; } err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); return err; } return 0; }
static int msm_hdmi_audio_codec_rx_dai_hw_params( struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { u32 channel_allocation = 0; u32 level_shift = 0; /* 0dB */ bool down_mix = 0; u32 num_channels = params_channels(params); int rc = 0; struct msm_hdmi_audio_codec_rx_data *codec_data = dev_get_drvdata(dai->codec->dev); if (IS_ERR_VALUE(msm_hdmi_audio_codec_return_value)) { dev_err(dai->dev, "%s() HDMI core is not ready\n", __func__); return msm_hdmi_audio_codec_return_value; } /*refer to HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4*/ switch (num_channels) { case 2: channel_allocation = 0; break; case 3: channel_allocation = 0x02;/*default to FL/FR/FC*/ break; case 4: channel_allocation = 0x06;/*default to FL/FR/FC/RC*/ break; case 5: channel_allocation = 0x0A;/*default to FL/FR/FC/RR/RL*/ break; case 6: channel_allocation = 0x0B; break; case 7: channel_allocation = 0x12;/*default to FL/FR/FC/RL/RR/RRC/RLC*/ break; case 8: channel_allocation = 0x13; break; default: dev_err(dai->dev, "invalid Channels = %u\n", num_channels); return -EINVAL; } dev_dbg(dai->dev, "%s() num_ch %u samplerate %u channel_allocation = %u\n", __func__, num_channels, params_rate(params), channel_allocation); rc = codec_data->hdmi_ops.audio_info_setup( codec_data->hdmi_core_pdev, params_rate(params), num_channels, channel_allocation, level_shift, down_mix); if (IS_ERR_VALUE(rc)) { dev_err(dai->dev, "%s() HDMI core is not ready\n", __func__); } return rc; }