static int jz_spdif_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { #ifndef CONFIG_JZ_ASOC_DMA_HRTIMER_MODE struct jz_pcm_runtime_data *prtd = substream->runtime->private_data; #endif spdif_DEBUG_MSG("enter %s, substream = %s cmd = %d\n", __func__, (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? "playback" : "capture", cmd); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: #ifndef CONFIG_JZ_ASOC_DMA_HRTIMER_MODE if (atomic_read(&prtd->stopped_pending)) return -EPIPE; #endif if(jz_spdif_start_substream(substream, dai)) return -EINVAL; break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: #ifndef CONFIG_JZ_ASOC_DMA_HRTIMER_MODE if (atomic_read(&prtd->stopped_pending)) return 0; #endif jz_spdif_stop_substream(substream, dai); break; } /*dump_registers(aic);*/ return 0; }
static int jz_spdif_stop_substream(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct jz_spdif *jz_spdif = dev_get_drvdata(dai->dev); struct device *aic = jz_spdif->aic; spdif_DEBUG_MSG("enter %s, substream = %s\n", __func__, (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? "playback" : "capture"); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (jz_spdif_debug) __aic_dis_tur_int(aic); if (__spdif_is_enable_transmit_dma(aic)) { __spdif_disable_transmit_dma(aic); __spdif_clear_underrun(aic); #ifdef CONFIG_JZ_ASOC_DMA_HRTIMER_MODE /*hrtime mode: stop will be happen in any where, make sure there is * no data transfer on ahb bus before stop dma */ while(!__spdif_test_underrun(aic)); #endif } __spdif_disable(aic); __spdif_clear_underrun(aic); } else { printk("spdif is not a capture device!\n"); return -EINVAL; } return 0; }
static int jz_spdif_start_substream(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct jz_spdif *jz_spdif = dev_get_drvdata(dai->dev); struct device *aic = jz_spdif->aic; int rst_test = 0xfff; spdif_DEBUG_MSG("enter %s, substream = %s\n", __func__, (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? "playback" : "capture"); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { __spdif_reset(aic); while(__spdif_get_reset(aic)) { if (rst_test-- <= 0){ printk("spdif rst err\n"); return -EINVAL; } } __spdif_enable_transmit_dma(aic); __spdif_clear_underrun(aic); __spdif_enable(aic); __aic_enable(aic); } else { printk("spdif is not a capture device!\n"); return -EINVAL; } return 0; }
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; }
static void jz_spdif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct jz_spdif *jz_spdif = dev_get_drvdata(dai->dev); struct device *aic = jz_spdif->aic; enum aic_mode work_mode = AIC_SPDIF_MODE; spdif_DEBUG_MSG("enter %s, substream = %s\n", __func__,(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? "playback" : "capture"); work_mode = aic_set_work_mode(jz_spdif->aic, work_mode, false); BUG_ON((work_mode != AIC_NO_MODE)); jz_spdif_stop_substream(substream, dai); __aic_disable(aic); return; }
static int jz_spdif_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct jz_spdif *jz_spdif = dev_get_drvdata(dai->dev); struct device *aic = jz_spdif->aic; enum aic_mode work_mode = AIC_SPDIF_MODE; spdif_DEBUG_MSG("enter %s, substream = %s\n", __func__, (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? "playback" : "capture"); work_mode = aic_set_work_mode(aic, work_mode, true); if (work_mode != AIC_SPDIF_MODE) { dev_warn(jz_spdif->aic, "Aic now is working on %s mode, open spdif mode failed\n", aic_work_mode_str(work_mode)); return -EPERM; } printk("start set AIC register....\n"); return 0; }