void aml_spdif_play(void) { _aiu_958_raw_setting_t set; _aiu_958_channel_status_t chstat; struct snd_pcm_substream substream; struct snd_pcm_runtime runtime; substream.runtime = &runtime; runtime.rate = 48000; runtime.format = SNDRV_PCM_FORMAT_S16_LE; runtime.channels = 2; runtime.sample_bits = 16; memset((void *)(&set), 0, sizeof(set)); memset((void *)(&chstat), 0, sizeof(chstat)); set.chan_stat = &chstat; set.chan_stat->chstat0_l = 0x0100; set.chan_stat->chstat0_r = 0x0100; set.chan_stat->chstat1_l = 0X200; set.chan_stat->chstat1_r = 0X200; audio_hw_958_enable(0); if (last_iec_clock != AUDIO_CLK_FREQ_48) { ALSA_PRINT("enterd %s,set_clock:%d,sample_rate=%d\n", __func__, last_iec_clock, AUDIO_CLK_FREQ_48); last_iec_clock = AUDIO_CLK_FREQ_48; audio_set_958_clk(AUDIO_CLK_FREQ_48, AUDIO_CLK_256FS); } audio_util_set_dac_958_format(AUDIO_ALGOUT_DAC_FORMAT_DSP); memset(iec958buf, 0, sizeof(iec958buf)); audio_set_958outbuf((virt_to_phys(iec958buf) + 63) & (~63), 128, 2, 0); audio_set_958_mode(AIU_958_MODE_PCM16, &set); #if OVERCLOCK == 1 || IEC958_OVERCLOCK == 1 WRITE_MPEG_REG_BITS(AIU_CLK_CTRL, 3, 4, 2); /* 512fs divide 4 == 128fs */ #else WRITE_MPEG_REG_BITS(AIU_CLK_CTRL, 1, 4, 2); /* 256fs divide 2 == 128fs */ #endif aout_notifier_call_chain(AOUT_EVENT_IEC_60958_PCM, &substream);
1)NONE-PCM raw output ,only available when ac3/dts audio,when raw output mode is selected by user. 2)PCM output for all audio, when pcm mode is selected by user . 3)PCM output for audios except ac3/dts,when raw output mode is selected by user */ void aml_hw_iec958_init(struct snd_pcm_substream *substream) { _aiu_958_raw_setting_t set; _aiu_958_channel_status_t chstat; unsigned i2s_mode, iec958_mode; unsigned start, size; int sample_rate; struct snd_dma_buffer *buf = &substream->dma_buffer; struct snd_pcm_runtime *runtime = substream->runtime; if (buf == NULL && runtime == NULL) { printk("buf/0x%x runtime/0x%x\n", (unsigned)buf, (unsigned)runtime); return; } i2s_mode = AIU_I2S_MODE_PCM16; sample_rate = AUDIO_CLK_FREQ_48; memset((void *)(&set), 0, sizeof(set)); memset((void *)(&chstat), 0, sizeof(chstat)); set.chan_stat = &chstat; printk("----aml_hw_iec958_init,runtime->rate=%d--\n", runtime->rate); switch (runtime->rate) { case 192000: sample_rate = AUDIO_CLK_FREQ_192; break; case 176400: sample_rate = AUDIO_CLK_FREQ_1764; break; case 96000: sample_rate = AUDIO_CLK_FREQ_96; break; case 88200: sample_rate = AUDIO_CLK_FREQ_882; break; case 48000: sample_rate = AUDIO_CLK_FREQ_48; break; case 44100: sample_rate = AUDIO_CLK_FREQ_441; break; case 32000: sample_rate = AUDIO_CLK_FREQ_32; break; case 8000: sample_rate = AUDIO_CLK_FREQ_8; break; case 11025: sample_rate = AUDIO_CLK_FREQ_11; break; case 16000: sample_rate = AUDIO_CLK_FREQ_16; break; case 22050: sample_rate = AUDIO_CLK_FREQ_22; break; case 12000: sample_rate = AUDIO_CLK_FREQ_12; break; case 24000: sample_rate = AUDIO_CLK_FREQ_22; break; default: sample_rate = AUDIO_CLK_FREQ_441; break; }; audio_hw_958_enable(0); if (last_iec_clock != sample_rate) { ALSA_PRINT("enterd %s,set_clock:%d,sample_rate=%d\n", __func__, last_iec_clock, sample_rate); last_iec_clock = sample_rate; audio_set_958_clk(sample_rate, AUDIO_CLK_256FS); } printk("----aml_hw_iec958_init,runtime->rate=%d,sample_rate=%d--\n", runtime->rate, sample_rate); audio_util_set_dac_958_format(AUDIO_ALGOUT_DAC_FORMAT_DSP); /*clear the same source function as new raw data output */ WRITE_MPEG_REG_BITS(AIU_I2S_MISC, 0, 3, 1); switch (runtime->format) { case SNDRV_PCM_FORMAT_S32_LE: i2s_mode = AIU_I2S_MODE_PCM32; break; case SNDRV_PCM_FORMAT_S24_LE: i2s_mode = AIU_I2S_MODE_PCM24; break; case SNDRV_PCM_FORMAT_S16_LE: i2s_mode = AIU_I2S_MODE_PCM16; break; } /* audio_set_i2s_mode(i2s_mode); */ /* case 1,raw mode enabled */ if (IEC958_mode_codec) { if (IEC958_mode_codec == 1) { /* dts, use raw sync-word mode */ iec958_mode = AIU_958_MODE_RAW; printk("iec958 mode RAW\n"); } else { /* ac3,use the same pcm mode as i2s configuration */ iec958_mode = AIU_958_MODE_PCM_RAW; printk("iec958 mode %s\n", (i2s_mode == AIU_I2S_MODE_PCM32) ? "PCM32_RAW" : ((I2S_MODE == AIU_I2S_MODE_PCM24) ? "PCM24_RAW" : "PCM16_RAW")); } } else { if (i2s_mode == AIU_I2S_MODE_PCM32) iec958_mode = AIU_958_MODE_PCM32; else if (i2s_mode == AIU_I2S_MODE_PCM24) iec958_mode = AIU_958_MODE_PCM24; else iec958_mode = AIU_958_MODE_PCM16; printk("iec958 mode %s\n", (i2s_mode == AIU_I2S_MODE_PCM32) ? "PCM32" : ((i2s_mode == AIU_I2S_MODE_PCM24) ? "PCM24" : "PCM16")); } if (iec958_mode == AIU_958_MODE_PCM16 || iec958_mode == AIU_958_MODE_PCM24 || iec958_mode == AIU_958_MODE_PCM32) { set.chan_stat->chstat0_l = 0x0100; set.chan_stat->chstat0_r = 0x0100; set.chan_stat->chstat1_l = 0x200; set.chan_stat->chstat1_r = 0x200; if (sample_rate == AUDIO_CLK_FREQ_882) { printk("----sample_rate==AUDIO_CLK_FREQ_882---\n"); set.chan_stat->chstat1_l = 0x800; set.chan_stat->chstat1_r = 0x800; } if (sample_rate == AUDIO_CLK_FREQ_96) { printk("----sample_rate==AUDIO_CLK_FREQ_96---\n"); set.chan_stat->chstat1_l = 0xa00; set.chan_stat->chstat1_r = 0xa00; } start = buf->addr; size = snd_pcm_lib_buffer_bytes(substream); audio_set_958outbuf(start, size, runtime->channels, 0); /* audio_set_i2s_mode(AIU_I2S_MODE_PCM16); */ /* audio_set_aiubuf(start, size); */ } else { set.chan_stat->chstat0_l = 0x1902; set.chan_stat->chstat0_r = 0x1902; if (IEC958_mode_codec == 4 || IEC958_mode_codec == 5) { /* DD+ */ if (runtime->rate == 32000) { set.chan_stat->chstat1_l = 0x300; set.chan_stat->chstat1_r = 0x300; } else if (runtime->rate == 44100) { set.chan_stat->chstat1_l = 0xc00; set.chan_stat->chstat1_r = 0xc00; } else { set.chan_stat->chstat1_l = 0Xe00; set.chan_stat->chstat1_r = 0Xe00; } } else { /* DTS,DD */ if (runtime->rate == 32000) { set.chan_stat->chstat1_l = 0x300; set.chan_stat->chstat1_r = 0x300; } else if (runtime->rate == 44100) { set.chan_stat->chstat1_l = 0; set.chan_stat->chstat1_r = 0; } else { set.chan_stat->chstat1_l = 0x200; set.chan_stat->chstat1_r = 0x200; } } start = buf->addr; size = snd_pcm_lib_buffer_bytes(substream); audio_set_958outbuf(start, size, runtime->channels, (iec958_mode == AIU_958_MODE_RAW) ? 1 : 0); memset((void *)buf->area, 0, size); } ALSA_DEBUG("aiu 958 pcm buffer size %d \n", size); audio_set_958_mode(iec958_mode, &set); if (IEC958_mode_codec == 4 || IEC958_mode_codec == 5 || IEC958_mode_codec == 7 || IEC958_mode_codec == 8) { WRITE_MPEG_REG_BITS(AIU_CLK_CTRL, 0, 4, 2); /* 4x than i2s */ printk("IEC958_mode_codec/%d 4x than i2s\n", IEC958_mode_codec); } else { #if OVERCLOCK == 1 || IEC958_OVERCLOCK == 1 WRITE_MPEG_REG_BITS(AIU_CLK_CTRL, 3, 4, 2); /* 512fs divide 4 == 128fs */ #else WRITE_MPEG_REG_BITS(AIU_CLK_CTRL, 1, 4, 2); /* 256fs divide 2 == 128fs */ #endif } if (IEC958_mode_codec == 2) { aout_notifier_call_chain(AOUT_EVENT_RAWDATA_AC_3, substream); } else if (IEC958_mode_codec == 3) { aout_notifier_call_chain(AOUT_EVENT_RAWDATA_DTS, substream); } else if (IEC958_mode_codec == 4) { aout_notifier_call_chain(AOUT_EVENT_RAWDATA_DOBLY_DIGITAL_PLUS,
static int aml_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct aml_runtime_data *prtd = runtime->private_data; audio_stream_t *s = &prtd->s; int iec958 = 0; if(prtd == 0) return 0; switch(runtime->rate){ case 192000: s->sample_rate = AUDIO_CLK_FREQ_192; break; case 176400: s->sample_rate = AUDIO_CLK_FREQ_1764; break; case 96000: s->sample_rate = AUDIO_CLK_FREQ_96; break; case 88200: s->sample_rate = AUDIO_CLK_FREQ_882; break; case 48000: s->sample_rate = AUDIO_CLK_FREQ_48; iec958 = 2; break; case 44100: s->sample_rate = AUDIO_CLK_FREQ_441; iec958 = 0; break; case 32000: s->sample_rate = AUDIO_CLK_FREQ_32; iec958 = 3; break; case 8000: s->sample_rate = AUDIO_CLK_FREQ_8; break; case 11025: s->sample_rate = AUDIO_CLK_FREQ_11; break; case 16000: s->sample_rate = AUDIO_CLK_FREQ_16; break; case 22050: s->sample_rate = AUDIO_CLK_FREQ_22; break; case 12000: s->sample_rate = AUDIO_CLK_FREQ_12; break; case 24000: s->sample_rate = AUDIO_CLK_FREQ_22; break; default: s->sample_rate = AUDIO_CLK_FREQ_441; break; }; // iec958 and i2s clock are separated since M8 #if MESON_CPU_TYPE < MESON_CPU_TYPE_MESON8 audio_set_clk(s->sample_rate, AUDIO_CLK_256FS); audio_util_set_dac_format(AUDIO_ALGOUT_DAC_FORMAT_DSP); #else audio_set_i2s_clk(s->sample_rate, AUDIO_CLK_256FS); audio_set_958_clk(s->sample_rate, AUDIO_CLK_256FS); audio_util_set_dac_i2s_format(AUDIO_ALGOUT_DAC_FORMAT_DSP); audio_util_set_dac_958_format(AUDIO_ALGOUT_DAC_FORMAT_DSP); #endif if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ trigger_underun = 0; aml_hw_i2s_init(runtime); aml_hw_iec958_init(substream); } else{ //printk("aml_pcm_prepare SNDRV_PCM_STREAM_CAPTURE: dma_addr=%x, dma_bytes=%x\n", runtime->dma_addr, runtime->dma_bytes); audio_in_i2s_set_buf(runtime->dma_addr, runtime->dma_bytes*2,audioin_mode); memset((void*)runtime->dma_area,0,runtime->dma_bytes*2); { int * ppp = (int*)(runtime->dma_area+runtime->dma_bytes*2-8); ppp[0] = 0x78787878; ppp[1] = 0x78787878; } } if( IEC958_MODE == AIU_958_MODE_PCM_RAW){ if(IEC958_mode_codec == 4 ){ // need Over clock for dd+ WRITE_MPEG_REG_BITS(AIU_CLK_CTRL, 0, 4, 2); // 4x than i2s audio_notify_hdmi_info(AOUT_EVENT_RAWDATA_DOBLY_DIGITAL_PLUS, substream); }else if(IEC958_mode_codec == 3 ||IEC958_mode_codec == 1 ){ // no-over clock for dts pcm mode audio_notify_hdmi_info(AOUT_EVENT_RAWDATA_DTS, substream); } else //dd audio_notify_hdmi_info(AOUT_EVENT_RAWDATA_AC_3, substream); }else if(IEC958_mode_codec == 1){ audio_notify_hdmi_info(AOUT_EVENT_RAWDATA_DTS, substream); }else{ audio_notify_hdmi_info(AOUT_EVENT_IEC_60958_PCM, substream); } #if 0 printk("Audio Parameters:\n"); printk("\tsample rate: %d\n", runtime->rate); printk("\tchannel: %d\n", runtime->channels); printk("\tsample bits: %d\n", runtime->sample_bits); printk("\tformat: %s\n", snd_pcm_format_name(runtime->format)); printk("\tperiod size: %ld\n", runtime->period_size); printk("\tperiods: %d\n", runtime->periods); printk("\tiec958 mode: %d, raw=%d, codec=%d\n", IEC958_MODE, IEC958_mode_raw, IEC958_mode_codec); #endif return 0; }