static int jz_spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { int channels = params_channels(params); int fmt_width = snd_pcm_format_width(params_format(params)); struct jz_spdif *jz_spdif = dev_get_drvdata(dai->dev); struct device *aic = jz_spdif->aic; struct jz_aic *jz_aic = dev_get_drvdata(aic); enum dma_slave_buswidth buswidth; int trigger; unsigned long sample_rate = params_rate(params); spdif_DEBUG_MSG("enter %s, substream = %s\n", __func__, (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? "playback" : "capture"); if (!((1 << params_format(params)) & JZ_SPDIF_FORMATS) || channels > 2) { dev_err(dai->dev, "hw params not inval channel %d params %x\n", channels, params_format(params)); return -EINVAL; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { __i2s_channel(aic, channels); /* format */ if (fmt_width == 16){ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; __spdif_set_max_wl(aic,0); __spdif_set_sample_size(aic,1); }else if(fmt_width == 24){ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; __spdif_set_max_wl(aic,1); __spdif_set_sample_size(aic,5); }else{ return -EINVAL; } jz_spdif->tx_dma_data.buswidth = buswidth; jz_spdif->tx_dma_data.max_burst = (SPDIF_TFIFO_DEPTH * buswidth)/2; trigger = SPDIF_TFIFO_DEPTH - (jz_spdif->tx_dma_data.max_burst/(int)buswidth); __i2s_set_transmit_trigger(aic,trigger/2); snd_soc_dai_set_dma_data(dai, substream, (void *)&jz_spdif->tx_dma_data); } else { printk("spdif is not a capture device!\n"); return -EINVAL; } /* sample rate */ unsigned long tmp_rate = 0; tmp_rate = jz_spdif_set_rate(aic,jz_aic,sample_rate); if(tmp_rate < 0) printk("set spdif clk failed!!\n"); /* signed transfer */ if(snd_pcm_format_signed(params_format(params))) __spdif_clear_signn(aic); else __spdif_set_signn(aic); return 0; }
static int jz_spdif_probe(struct snd_soc_dai *dai) { struct jz_spdif *jz_spdif = dev_get_drvdata(dai->dev); struct device *aic = jz_spdif->aic; unsigned int reg_tmp; spdif_DEBUG_MSG("enter %s\n", __func__); __i2s_disable_transmit_dma(aic); __i2s_disable_receive_dma(aic); __i2s_disable_replay(aic); __i2s_disable_record(aic); __i2s_disable_loopback(aic); __aic_disable(aic); reg_tmp = jz_aic_read_reg(aic, SPCTRL); reg_tmp |= (SPCTRL_SPDIF_I2S_MASK | SPCTRL_M_TRIG_MASK | SPCTRL_M_FFUR_MASK | SPCTRL_INVALID_MASK); jz_aic_write_reg(aic, SPCTRL, reg_tmp); __i2s_stop_bitclk(aic); __i2s_external_codec(aic); __i2s_bclk_output(aic); __i2s_sync_output(aic); __aic_select_i2s(aic); __i2s_send_rfirst(aic); __spdif_set_dtype(aic,0); __spdif_set_ch1num(aic,0); __spdif_set_ch2num(aic,1); __spdif_set_srcnum(aic,0); __interface_select_spdif(aic); __spdif_play_lastsample(aic); __spdif_init_set_low(aic); __spdif_choose_consumer(aic); __spdif_clear_audion(aic); __spdif_set_copyn(aic); __spdif_clear_pre(aic); __spdif_choose_chmd(aic); __spdif_set_category_code_normal(aic); __spdif_set_clkacu(aic, 0); __spdif_set_sample_size(aic, 1); __spdif_set_valid(aic); __spdif_mask_trig(aic); __spdif_disable_underrun_intr(aic); /*select spdif trans*/ printk("spdif cpu dai prob ok\n"); return 0; }