示例#1
0
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;
}
示例#2
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;
}
示例#3
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;
}