Example #1
0
/*
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;
        }
    }
}
Example #2
0
/**
 * \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;
}
Example #3
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);
}