static int sun5i_sndi2s_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 long rate = params_rate(params); u32 mclk_div=0, mpll=0, bclk_div=0, mult_fs=0; get_clock_divder(rate, 32, &mclk_div, &mpll, &bclk_div, &mult_fs); ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; ret = snd_soc_dai_set_sysclk(cpu_dai, 0 , mpll, 0); if (ret < 0) return ret; ret = snd_soc_dai_set_sysclk(codec_dai, 0 , mpll, 0); if (ret < 0) return ret; ret = snd_soc_dai_set_clkdiv(cpu_dai, SUN5I_DIV_MCLK, mclk_div); if (ret < 0) return ret; ret = snd_soc_dai_set_clkdiv(cpu_dai, SUN5I_DIV_BCLK, bclk_div); if (ret < 0) return ret; ret = snd_soc_dai_set_clkdiv(codec_dai, 0, mult_fs); if (ret < 0) return ret; return 0; }
static int sun6i_sndspdif_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 long rate = params_rate(params); unsigned int fmt = 0; u32 mclk_div=0, mpll=0, bclk_div=0, mult_fs=0; get_clock_divder(rate, 32, &mclk_div, &mpll, &bclk_div, &mult_fs); if (ret < 0) return ret; /*add the pcm and raw data select interface*/ switch(params_channels(params)) { case 1:/*pcm mode*/ case 2: fmt = 0; break; case 4:/*raw data mode*/ fmt = 1; break; default: return -EINVAL; } ret = snd_soc_dai_set_fmt(cpu_dai, fmt);//0:pcm,1:raw data if (ret < 0) return ret; ret = snd_soc_dai_set_sysclk(cpu_dai, 0 , mpll, 0); if (ret < 0) return ret; ret = snd_soc_dai_set_clkdiv(cpu_dai, SUN6I_DIV_MCLK, mclk_div); if (ret < 0) return ret; ret = snd_soc_dai_set_clkdiv(cpu_dai, SUN6I_DIV_BCLK, bclk_div); if (ret < 0) return ret; return 0; }
static int sunxi_sndspdif_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 long rate = params_rate(params); unsigned int fmt = 0; u32 mclk_div=0, mpll=0, bclk_div=0, mult_fs=0; get_clock_divder(rate, 32, &mclk_div, &mpll, &bclk_div, &mult_fs); if (ret < 0) return ret; #ifdef CONFIG_SND_SUNXI_SOC_SUPPORT_AUDIO_RAW /*fmt:1:pcm; >1:rawdata*/ fmt = params_raw(params); #else fmt = spdif_format; #endif if(fmt > 1){ fmt = 1; }else{ fmt = 0; } ret = snd_soc_dai_set_fmt(cpu_dai, fmt);//0:pcm,1:raw data if (ret < 0) return ret; ret = snd_soc_dai_set_sysclk(cpu_dai, 0 , mpll, 0); if (ret < 0) return ret; ret = snd_soc_dai_set_clkdiv(cpu_dai, SUNXI_DIV_MCLK, mclk_div); if (ret < 0) return ret; return 0; }
static int daudio2_hdmi_spdif_en(int hdmi_en, int spdif_en) { int reg_val = 0; int freq = 22579200; int sample_rate = 44100; int sample_resolution = 16; int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; unsigned int spdif_mclk_div=0; unsigned int spdif_mpll=0, spdif_bclk_div=0, spdif_mult_fs=0; if (hdmi_en) { tdm2_set_rate(freq); tdm2_set_fmt(fmt); tdm2_set_clkdiv(sample_rate); tdm2_hw_params(sample_resolution); hdmi_para.ca = 0x0; hdmi_para.data_raw = 1; hdmi_para.channel_num = 2; hdmi_para.sample_rate = sample_rate; hdmi_para.sample_bit = sample_resolution; tdm2_prepare_tmp(); if (!g_hdmi_func.hdmi_set_audio_para) { printk(KERN_WARNING "hdmi video isn't insmod, hdmi interface is null\n"); return 0; } /*Global Enable Digital Audio Interface*/ reg_val = readl(SUNXI_DAUDIO2_VBASE + SUNXI_DAUDIOCTL); reg_val |= SUNXI_DAUDIOCTL_GEN; writel(reg_val, SUNXI_DAUDIO2_VBASE + SUNXI_DAUDIOCTL); msleep(10); reg_val = readl(SUNXI_DAUDIO2_VBASE + SUNXI_DAUDIOFCTL); reg_val |= SUNXI_DAUDIOFCTL_TXTL(112); writel(reg_val, SUNXI_DAUDIO2_VBASE + SUNXI_DAUDIOFCTL); /*flush TX FIFO*/ reg_val = readl(SUNXI_DAUDIO2_VBASE + SUNXI_DAUDIOFCTL); reg_val |= SUNXI_DAUDIOFCTL_FTX; writel(reg_val, SUNXI_DAUDIO2_VBASE + SUNXI_DAUDIOFCTL); /* * set the first pcm param, need set the hdmi audio pcm param * set the data_raw param, need set the hdmi audio raw param */ mutex_lock(&open_hdmi_mutex); if (atomic_read(&hdmi_open_num) < 1) { g_hdmi_func.hdmi_set_audio_para(&hdmi_para); g_hdmi_func.hdmi_audio_enable(1, 1); tdm2_tx_enable(1, 1); } //tdm2_tx_enable(1, 1); atomic_inc(&hdmi_open_num); mutex_unlock(&open_hdmi_mutex); } else { mutex_lock(&open_hdmi_mutex); if(atomic_read(&hdmi_open_num) > 0) { atomic_dec(&hdmi_open_num); if(atomic_read(&hdmi_open_num) == 0) { g_hdmi_func.hdmi_audio_enable(0, 1); tdm2_tx_enable(0, 0); } } mutex_unlock(&open_hdmi_mutex); } if (spdif_en) { spdif_set_fmt(0); get_clock_divder(sample_rate, 32, &spdif_mclk_div, &spdif_mpll, &spdif_bclk_div, &spdif_mult_fs); spdif_set_clkdiv(SUNXI_DIV_MCLK, spdif_mclk_div); spdif_hw_params(sample_resolution); spdif_txctrl_enable(1, 2, 1); g_hdmi_func.hdmi_audio_enable(0, 1); } else { spdif_txctrl_enable(0, 1, 0); } return 0; }