static int sun4i_codec_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 sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); unsigned long clk_freq; int ret, hwrate; clk_freq = sun4i_codec_get_mod_freq(params); if (!clk_freq) return -EINVAL; ret = clk_set_rate(scodec->clk_module, clk_freq); if (ret) return ret; hwrate = sun4i_codec_get_hw_rate(params); if (hwrate < 0) return hwrate; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) return sun4i_codec_hw_params_playback(scodec, params, hwrate); return sun4i_codec_hw_params_capture(scodec, params, hwrate); }
static int sun4i_codec_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 sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); unsigned long clk_freq; int ret, hwrate; u32 val; if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) return -ENOTSUPP; clk_freq = sun4i_codec_get_mod_freq(params); if (!clk_freq) return -EINVAL; ret = clk_set_rate(scodec->clk_module, clk_freq); if (ret) return ret; hwrate = sun4i_codec_get_hw_rate(params); if (hwrate < 0) return hwrate; /* Set DAC sample rate */ regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, 7 << SUN4I_CODEC_DAC_FIFOC_DAC_FS, hwrate << SUN4I_CODEC_DAC_FIFOC_DAC_FS); /* Set the number of channels we want to use */ if (params_channels(params) == 1) val = BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN); else val = 0; regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN), val); /* Set the number of sample bits to either 16 or 24 bits */ if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) { regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS), BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS)); /* Set TX FIFO mode to padding the LSBs with 0 */ regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE), 0); scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; } else { regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS), 0); /* Set TX FIFO mode to repeat the MSB */ regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC, BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE), BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE)); scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; } return 0; }