void aml_spdif_play(void) { #if 1 struct _aiu_958_raw_setting_t set; struct _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 (old_samplerate != AUDIO_CLK_FREQ_48) { pr_info("enterd %s,set_clock:%d,sample_rate=%d\n", __func__, old_samplerate, AUDIO_CLK_FREQ_48); old_samplerate = AUDIO_CLK_FREQ_48; aml_set_spdif_clk(48000 * 512, 0); } /* Todo, div can be changed, for most case, div = 2 */ /* audio_set_spdif_clk_div(); */ /* 958 divisor: 0=no div; 1=div by 2; 2=div by 3; 3=div by 4. */ if (IEC958_mode_codec == 4 || IEC958_mode_codec == 5 || IEC958_mode_codec == 7 || IEC958_mode_codec == 8) { pr_info("set 4x audio clk for 958\n"); aml_cbus_update_bits(AIU_CLK_CTRL, 3 << 4, 0 << 4); } else if (0) { pr_info("share the same clock\n"); aml_cbus_update_bits(AIU_CLK_CTRL, 3 << 4, 1 << 4); } else { pr_info("set normal 512 fs /4 fs\n"); aml_cbus_update_bits(AIU_CLK_CTRL, 3 << 4, 3 << 4); } /* enable 958 divider */ aml_cbus_update_bits(AIU_CLK_CTRL, 1 << 1, 1 << 1); 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, 0); audio_set_958_mode(AIU_958_MODE_PCM16, &set); #if OVERCLOCK == 1 || IEC958_OVERCLOCK == 1 /* 512fs divide 4 == 128fs */ aml_cbus_update_bits(AIU_CLK_CTRL, 0x3 << 4, 0x3 << 4); #else /* 256fs divide 2 == 128fs */ aml_cbus_update_bits(AIU_CLK_CTRL, 0x3 << 4, 0x1 << 4); #endif aout_notifier_call_chain(AOUT_EVENT_IEC_60958_PCM, &substream); audio_hw_958_enable(1); #endif }
void aml_alsa_hw_reprepare(void) { /* diable 958 module before call initiation */ audio_hw_958_enable(0); aml_hw_iec958_init(); }
void am_i2s_trigger_output(void) { audio_stream_t *s = NULL; if (g_prtd == NULL) { printk("am_i2s_trigger_output g_prtd == NULL \n"); return ; } s = &g_prtd->s; if (s == NULL) { printk("am_i2s_trigger_output g_prtd->s== NULL \n"); return ; } if (s->audio_trigger_disable == 1) { unsigned int pts_audio, pts_scr; //unsigned int pts_audio_cur = 0; int sync_mode; pts_audio = tsync_get_firstapts(); pts_scr = timestamp_pcrscr_get(); sync_mode = tsync_get_mode(); // when pcr chase to apts,start audio playback if ((sync_mode == TSYNC_MODE_PCRMASTER) && ((pts_audio <= pts_scr))) { s->disable_count = 0; s->audio_trigger_disable = 0; if (s->device_type == AML_AUDIO_I2SOUT) { printk("trigger aiu i2s playback enable audio %x pcr %x disable count %d \n", pts_audio, pts_scr, s->disable_count); audio_out_i2s_enable(1); audio_hw_958_enable(1); } else if (s->device_type == AML_AUDIO_SPDIFOUT) { printk("trigger aiu 958 playback enable audio %x pcr %x disable count %d\n", pts_audio, pts_scr, s->disable_count); audio_hw_958_enable(1); } } } else { printk("s->audio_trigger_disable %d \n", s->audio_trigger_disable); } }
__LINE__); aout_notifier_call_chain(AOUT_EVENT_IEC_60958_PCM, substream); } return 0; } static int aml_dai_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_pcm_runtime *rtd = substream->runtime; int *ppp = NULL; ALSA_TRACE(); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* TODO */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ALSA_PRINT("aiu i2s playback enable\n\n"); audio_out_i2s_enable(1); if (IEC958_mode_codec == 0) { ALSA_PRINT("audio_hw_958_enable 1\n"); audio_hw_958_enable(1); } } else { audio_in_i2s_enable(1); ppp = (int *)(rtd->dma_area + rtd->dma_bytes * 2 - 8); ppp[0] = 0x78787878; ppp[1] = 0x78787878; } break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ALSA_PRINT("aiu i2s playback disable\n\n"); audio_out_i2s_enable(0); if (IEC958_mode_codec == 0) { ALSA_PRINT("audio_hw_958_enable 0\n"); audio_hw_958_enable(0); } } else {
WRITE_MPEG_REG(AIU_958_CHSTAT_R0, 0x1902); WRITE_MPEG_REG(AIU_958_CHSTAT_R1, 0x900); aout_notifier_call_chain(AOUT_EVENT_RAWDATA_MAT_MLP, substream); } else { aout_notifier_call_chain(AOUT_EVENT_IEC_60958_PCM, substream); } ALSA_PRINT("spdif dma %x,phy addr %x\n", (unsigned)runtime->dma_area, (unsigned)runtime->dma_addr); }
ALSA_TRACE(); return 0; } static int aml_dai_spdif_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = NULL; ALSA_TRACE(); rtd = (struct snd_soc_pcm_runtime *)substream->private_data; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ALSA_PRINT("aiu 958 playback enable\n"); audio_hw_958_enable(1); } else { ALSA_PRINT("spdif in capture enable\n"); audio_in_spdif_enable(1); } break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ALSA_PRINT("aiu 958 playback disable\n"); audio_hw_958_enable(0); } else { ALSA_PRINT("spdif in capture disable\n"); audio_in_spdif_enable(0); } break; default: return -EINVAL;
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);
static int aml_i2s_copy_playback(struct snd_pcm_runtime *runtime, int channel, snd_pcm_uframes_t pos, void __user *buf, snd_pcm_uframes_t count, struct snd_pcm_substream *substream) { int res = 0; int n; int i = 0, j = 0; int align = runtime->channels * 32 / runtime->byte_align; char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, pos); struct aml_runtime_data *prtd = runtime->private_data; struct snd_dma_buffer *buffer = &substream->dma_buffer; struct aml_audio_buffer *tmp_buf = buffer->private_data; void *ubuf = tmp_buf->buffer_start; audio_stream_t *s = &prtd->s; int force_reinit_958 = 0; force_reinit_958 = (IEC958_mode_codec == 0 && (READ_MPEG_REG(AIU_MEM_IEC958_START_PTR) != READ_MPEG_REG(AIU_MEM_I2S_START_PTR))); if (s && s->device_type == AML_AUDIO_I2SOUT && (trigger_underrun) && kernel_android_50 == 1) { printk("i2s out trigger underrun force_reinit_958/%d trigger_underrun/%d IEC958_mode_codec/%d IEC958_START_PTR/0x%x I2S_START_PTR/0x%x\n", force_reinit_958, trigger_underrun, IEC958_mode_codec, READ_MPEG_REG(AIU_MEM_IEC958_START_PTR), READ_MPEG_REG(AIU_MEM_I2S_START_PTR)); //trigger_underrun = 0; return -EFAULT; } if (s && s->device_type == AML_AUDIO_I2SOUT && force_reinit_958 && kernel_android_50 == 1) { printk("i2s out trigger underrun force_reinit_958/%d", force_reinit_958); audio_hw_958_enable(0); aml_hw_iec958_init(substream); audio_hw_958_enable(1); } if (s->device_type == AML_AUDIO_I2SOUT) { aml_i2s_alsa_write_addr = frames_to_bytes(runtime, pos); } n = frames_to_bytes(runtime, count); if (aml_i2s_playback_enable == 0 && s->device_type == AML_AUDIO_I2SOUT) { return res; } res = copy_from_user(ubuf, buf, n); if (res) { return -EFAULT; } if (access_ok(VERIFY_READ, buf, frames_to_bytes(runtime, count))) { if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) { int16_t * tfrom, *to, *left, *right; tfrom = (int16_t*)ubuf; to = (int16_t*)hwbuf; left = to; right = to + 16; if (pos % align) { printk("audio data unligned: pos=%d, n=%d, align=%d\n", (int)pos, n, align); } if (set_android_gain_enable == 0) { for (j = 0; j < n; j += 64) { for (i = 0; i < 16; i++) { *left++ = (*tfrom++) ; *right++ = (*tfrom++); } left += 16; right += 16; } } else { for (j = 0; j < n; j += 64) { for (i = 0; i < 16; i++) { *left++ = (int16_t)(((*tfrom++) * android_left_gain) >> 8); *right++ = (int16_t)(((*tfrom++) * android_right_gain) >> 8); } left += 16; right += 16; } } } else if (runtime->format == SNDRV_PCM_FORMAT_S24_LE && I2S_MODE == AIU_I2S_MODE_PCM24) {
static int aml_i2s_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *rtd = substream->runtime; struct aml_runtime_data *prtd = rtd->private_data; audio_stream_t *s = &prtd->s; int ret = 0; unsigned int pts_audio, pts_scr; unsigned int diff = 0; int sync_mode; ALSA_TRACE(); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: #if USE_HRTIMER == 0 && !defined(USE_HW_TIMER) del_timer_sync(&prtd->timer); #endif spin_lock(&s->lock); #if USE_HRTIMER == 0 && !defined(USE_HW_TIMER) prtd->timer.expires = jiffies + 1; del_timer(&prtd->timer); add_timer(&prtd->timer); #endif pts_audio = tsync_get_firstapts(); pts_scr = timestamp_pcrscr_get(); sync_mode = tsync_get_mode(); #if 1 if (pts_audio > pts_scr) diff = pts_audio - pts_scr; else diff = pts_scr - pts_audio; if (IEC958_mode_codec == 0 && sync_mode == TSYNC_MODE_PCRMASTER && pts_audio > pts_scr && (pts_audio - pts_scr) < 90 * MAX_APTS_SCR_DELTA) { printk("aiu i2s playback enable trigger mode sync_mode %d audio %x pcr %x diff %d \n", sync_mode, pts_audio, pts_scr, diff); s->audio_trigger_disable = 1; } else #endif { printk("aiu i2s/958 playback enable sync_mode %d audio %x pcr %x diff %d IEC958_mode_codec %d\n", sync_mode, pts_audio, pts_scr, diff, IEC958_mode_codec); s->disable_count = 0; s->audio_trigger_disable = 0; if (IEC958_mode_codec == 0) { printk("aiu i2s/958 playback enable sync_mode %d audio %x pcr %x diff %d \n", sync_mode, pts_audio, pts_scr, diff); audio_out_i2s_enable(1); audio_hw_958_enable(1); } } s->active = 1; spin_unlock(&s->lock); break; /* SNDRV_PCM_TRIGGER_START */ case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_STOP: // TODO spin_lock(&s->lock); s->audio_trigger_disable = 0; s->disable_count = 0; if (IEC958_mode_codec == 0) { printk("aiu i2s playback disable\n"); audio_out_i2s_enable(0); printk("aiu 958 playback disable\n"); audio_hw_958_enable(0); } s->active = 0; spin_unlock(&s->lock); break; default: ret = -EINVAL; } /* if(clock_gating_status&clock_gating_playback){ if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) aml_pcm_work.substream = substream; } else aml_pcm_work.substream = substream; if (clock_gating_status) { schedule_work(&aml_pcm_work.aml_codec_workqueue); } */ //schedule_work(&aml_pcm_work.aml_codec_workqueue); return ret; }
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,
void aml_hw_iec958_init(struct snd_pcm_substream *substream) { struct _aiu_958_raw_setting_t set; struct _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) { pr_info("buf/%p runtime/%p\n", buf, 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; 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); pr_info("----aml_hw_iec958_init,runtime->rate=%d,sample_rate=%d--\n", runtime->rate, sample_rate); /* int srate; */ /* srate = params_rate(params); */ if (old_samplerate != sample_rate) { old_samplerate = sample_rate; aml_set_spdif_clk(runtime->rate * 512, 0); } /* Todo, div can be changed, for most case, div = 2 */ /* audio_set_spdif_clk_div(); */ /* 958 divisor: 0=no div; 1=div by 2; 2=div by 3; 3=div by 4. */ if (IEC958_mode_codec == 4 || IEC958_mode_codec == 5 || IEC958_mode_codec == 7 || IEC958_mode_codec == 8) { pr_info("set 4x audio clk for 958\n"); aml_cbus_update_bits(AIU_CLK_CTRL, 3 << 4, 0 << 4); } else if (0) { pr_info("share the same clock\n"); aml_cbus_update_bits(AIU_CLK_CTRL, 3 << 4, 1 << 4); } else { pr_info("set normal 512 fs /4 fs\n"); aml_cbus_update_bits(AIU_CLK_CTRL, 3 << 4, 3 << 4); } /* enable 958 divider */ aml_cbus_update_bits(AIU_CLK_CTRL, 1 << 1, 1 << 1); audio_util_set_dac_958_format(AUDIO_ALGOUT_DAC_FORMAT_DSP); /*clear the same source function as new raw data output */ audio_i2s_958_same_source(0); 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; pr_info("iec958 mode RAW\n"); } else { /* ac3,use the same pcm mode as i2s configuration */ iec958_mode = AIU_958_MODE_PCM_RAW; pr_info("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; pr_info("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) { pr_info("----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) { pr_info("----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, 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, (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 == 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, substream); } else if (IEC958_mode_codec == 5) { aout_notifier_call_chain(AOUT_EVENT_RAWDATA_DTS_HD, substream); } else if (IEC958_mode_codec == 7 || IEC958_mode_codec == 8) { aml_write_cbus(AIU_958_CHSTAT_L0, 0x1902); aml_write_cbus(AIU_958_CHSTAT_L1, 0x900); aml_write_cbus(AIU_958_CHSTAT_R0, 0x1902); aml_write_cbus(AIU_958_CHSTAT_R1, 0x900); if (IEC958_mode_codec == 8) aout_notifier_call_chain(AOUT_EVENT_RAWDATA_DTS_HD_MA, substream); else aout_notifier_call_chain(AOUT_EVENT_RAWDATA_MAT_MLP, substream); } else { aout_notifier_call_chain(AOUT_EVENT_IEC_60958_PCM, substream); } }
static void aml_spdif_play_stop(void) { audio_hw_958_enable(0); }