/* digital_raw: 0 2ch PCM 1 spdif passthrough ,for DTS,DD 2 HDMI passthrough for DD,DTSHD,TrueHD 3 Multi-channel PCM HDMI passthrough */ static void set_multichs_prop() { char * infobuf; int channel = 0; int dgraw = 0; dgraw = amsysfs_get_sysfs_int("/sys/class/audiodsp/digital_raw"); infobuf = (char *)malloc(1024 * sizeof(char)); property_set(PCM_88_96_SUPPORT,"0"); if(infobuf == NULL){ adec_print("%s: malloc infobuf failed.\n",__FUNCTION__); }else{ int fd = open("/sys/class/amhdmitx/amhdmitx0/aud_cap", O_RDONLY); if(fd != -1){ int nread = read(fd, infobuf, 1024); int i; nread = nread - 5; for(i = 0; i < nread; i++) { if((infobuf[i] == 'P') && (infobuf[i+1] == 'C') && (infobuf[i+2] == 'M')){ if(dgraw == 3){ // if configured mutli-channel output,check if the HDMI sink support multi-channel PCM output if(infobuf[i+5] == '8'){ property_set(MULTICH_SUPPORT_PROPERTY,"hdmi8"); channel = channel < 8 ? 8 : channel; } if(infobuf[i+5] == '6'){ property_set(MULTICH_SUPPORT_PROPERTY,"hdmi6"); channel = channel < 6 ? 6 : channel; } if(infobuf[i+5] == '2'){ property_set(MULTICH_SUPPORT_PROPERTY,"hdmi2"); channel = channel < 2 ? 2 : channel; } } else{ property_set(MULTICH_SUPPORT_PROPERTY,"hdmi2"); channel = channel < 2 ? 2 : channel; } }else if( ( (infobuf[i] == '8') && (infobuf[i+1] == '8') && (infobuf[i+2] == '.')&& (infobuf[i+3] == '2')) ||((infobuf[i] == '9') && (infobuf[i+1] == '6'))) { property_set(PCM_88_96_SUPPORT,"1"); } } if(channel == 0) property_set(MULTICH_SUPPORT_PROPERTY,"speaker"); adec_print("%s: aud_cap support channel number: %d ch\n", __FUNCTION__, channel); close(fd); free(infobuf); infobuf = NULL; } else{ adec_print("%s: open hdmi driver aud_cap node failed \n", __FUNCTION__); free(infobuf); infobuf = NULL; } } }
/** * \brief stop output * \param audec pointer to audec * \return 0 on success otherwise negative error code */ int alsa_stop_raw(struct aml_audio_dec* audec) { alsa_param_t *alsa_params; int res = 0; int dgraw = amsysfs_get_sysfs_int("/sys/class/audiodsp/digital_raw"); if(audec->aout_ops.private_data_raw) { alsa_params = (alsa_param_t *)audec->aout_ops.private_data_raw; } else { adec_print("OUT SETTING::PCM\n"); return -1; } //resume the spdif card, otherwise the output will block if(alsa_params->pause_flag == 1){ while ((res = snd_pcm_pause(alsa_params->handle, 0)) == -EAGAIN) { usleep(1000); } } alsa_params->pause_flag = 0; //we should clear pause flag ,as we can stop from paused state alsa_params->stop_flag = 1; alsa_params->wait_flag = 0; pthread_cond_signal(&alsa_params->playback_cond); pthread_join(alsa_params->playback_tid, NULL); pthread_mutex_destroy(&alsa_params->playback_mutex); pthread_cond_destroy(&alsa_params->playback_cond); snd_pcm_drop(alsa_params->handle); snd_pcm_close(alsa_params->handle); free(alsa_params); audec->aout_ops.private_data_raw = NULL; adec_print("exit alsa out raw stop\n"); if((AUDIO_SPDIF_PASSTHROUGH == dgraw)||(AUDIO_HDMI_PASSTHROUGH == dgraw)){ if((audec->format == ACODEC_FMT_AC3) ||(audec->format == ACODEC_FMT_EAC3) ){ amsysfs_set_sysfs_int("/sys/class/audiodsp/digital_codec",0); } } return 0; }
/** * \brief output initialization * \param audec pointer to audec * \return 0 on success otherwise negative error code */ int alsa_init_raw(struct aml_audio_dec* audec) { int err = 0; pthread_t tid; alsa_param_t *alsa_param; audio_out_operations_t *out_ops = &audec->aout_ops; int sound_card_id = 0; int sound_dev_id = 0; char sound_card_dev[10] = {0}; int dgraw = amsysfs_get_sysfs_int("/sys/class/audiodsp/digital_raw"); if((AUDIO_SPDIF_PASSTHROUGH == dgraw)||(AUDIO_HDMI_PASSTHROUGH == dgraw)){ if(audec->format == ACODEC_FMT_AC3){ amsysfs_set_sysfs_int("/sys/class/audiodsp/digital_codec",2); audec->codec_type=1; }else if(audec->format == ACODEC_FMT_EAC3){ amsysfs_set_sysfs_int("/sys/class/audiodsp/digital_codec",4); audec->codec_type=4; } } if(AUDIO_PCM_OUTPUT == dgraw) { adec_print("OUT SETTING::PCM\n"); out_ops->private_data_raw = NULL; return -1; } alsa_param = (alsa_param_t *)malloc(sizeof(alsa_param_t)); if (!alsa_param) { adec_print("alloc alsa_param failed, not enough memory!"); return -1; } memset(alsa_param, 0, sizeof(alsa_param_t)); if (audec->samplerate >= (88200 + 96000) / 2) { alsa_param->flag = 1; alsa_param->oversample = -1; alsa_param->rate = 48000; } else if (audec->samplerate >= (64000 + 88200) / 2) { alsa_param->flag = 1; alsa_param->oversample = -1; alsa_param->rate = 44100; } else if (audec->samplerate >= (48000 + 64000) / 2) { alsa_param->flag = 1; alsa_param->oversample = -1; alsa_param->rate = 32000; } else if (audec->samplerate >= (44100 + 48000) / 2) { alsa_param->oversample = 0; alsa_param->rate = 48000; if (audec->channels == 1) { alsa_param->flag = 1; } else if (audec->channels == 2) { alsa_param->flag = 0; } } else if (audec->samplerate >= (32000 + 44100) / 2) { alsa_param->oversample = 0; alsa_param->rate = 44100; if (audec->channels == 1) { alsa_param->flag = 1; } else if (audec->channels == 2) { alsa_param->flag = 0; } } else if (audec->samplerate >= (24000 + 32000) / 2) { alsa_param->oversample = 0; alsa_param->rate = 32000; if (audec->channels == 1) { alsa_param->flag = 1; } else if (audec->channels == 2) { alsa_param->flag = 0; } } else if (audec->samplerate >= (22050 + 24000) / 2) { alsa_param->flag = 1; alsa_param->oversample = 1; alsa_param->rate = 48000; } else if (audec->samplerate >= (16000 + 22050) / 2) { alsa_param->flag = 1; alsa_param->oversample = 1; alsa_param->rate = 44100; } else if (audec->samplerate >= (12000 + 16000) / 2) { alsa_param->flag = 1; alsa_param->oversample = 1; alsa_param->rate = 32000; } else if (audec->samplerate >= (11025 + 12000) / 2) { alsa_param->flag = 1; alsa_param->oversample = 2; alsa_param->rate = 48000; } else if (audec->samplerate >= (8000 + 11025) / 2) { alsa_param->flag = 1; alsa_param->oversample = 2; alsa_param->rate = 44100; } else { alsa_param->flag = 1; alsa_param->oversample = 2; alsa_param->rate = 32000; } alsa_param->channelcount = 2; alsa_param->realchanl = audec->channels; //alsa_param->rate = audec->samplerate; alsa_param->format = SND_PCM_FORMAT_S16_LE; alsa_param->wait_flag=0; sound_card_id = alsa_get_aml_card(); if (sound_card_id < 0) { sound_card_id = 0; adec_print("[%s::%d]--[get aml card fail, use default]\n",__FUNCTION__, __LINE__); } adec_print("[%s::%d]--[alsa_get_aml_card return:%d]\n",__FUNCTION__, __LINE__,sound_card_id); sound_dev_id = alsa_get_spdif_port(); if (sound_dev_id < 0) { sound_dev_id = 0; adec_print("[%s::%d]--[get aml card device fail, use default]\n",__FUNCTION__, __LINE__); } adec_print("[%s::%d]--[sound_dev_id(spdif) return:%d]\n",__FUNCTION__, __LINE__,sound_dev_id); sprintf(sound_card_dev, "hw:%d,%d", sound_card_id, sound_dev_id); adec_print("[%s::%d]--[sound_card_dev:%s]\n",__FUNCTION__, __LINE__,sound_card_dev); err = snd_pcm_open(&alsa_param->handle, sound_card_dev, SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { adec_print("[%s::%d]--[audio open error: %s]\n", __FUNCTION__, __LINE__,snd_strerror(err)); snd_pcm_drop(alsa_param->handle); snd_pcm_close(alsa_param->handle); return -1; } else { adec_print("[%s::%d]--[audio open(snd_pcm_open) successfully]\n", __FUNCTION__, __LINE__); } readi_func = snd_pcm_readi; writei_func = snd_pcm_writei; readn_func = snd_pcm_readn; writen_func = snd_pcm_writen; set_params_raw(alsa_param); out_ops->private_data_raw = (void *)alsa_param; /*TODO: create play thread */ pthread_mutex_init(&alsa_param->playback_mutex, NULL); pthread_cond_init(&alsa_param->playback_cond, NULL); err = pthread_create(&tid, NULL, (void *)alsa_playback_raw_loop, (void *)audec); if (err != 0) { adec_print("alsa_playback_raw_loop thread create failed!"); snd_pcm_close(alsa_param->handle); return -1; } adec_print("Create alsa_playback_raw_loop thread success ! tid = %d\n", tid); alsa_param->playback_tid = tid; alsactl_parser(); return 0; }
static int get_sysfs_int(const char *path) { return amsysfs_get_sysfs_int(path); }