Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e85d046e authored by Gopikrishnaiah Anandan's avatar Gopikrishnaiah Anandan Committed by Gerrit - the friendly Code Review server
Browse files

hal: Speaker protection pre-emption fixes

Speaker protection module should acquire the device lock for all global
operations. This change will ensure that the pre-conditions required for
calibration will be met and if any audio/voice usecase is started when
speaker calibration is being done,speaker protection thread should
cancel the calibration.

Change-Id: I0d5fa23657161ec971e851944a0045a01d8248ea
CRs-fixed: 688972
parent cc9bb147
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -178,6 +178,7 @@ int32_t audio_extn_read_xml(struct audio_device *adev, uint32_t mixer_card,
#ifndef SPKR_PROT_ENABLED
#define audio_extn_spkr_prot_init(adev)       (0)
#define audio_extn_spkr_prot_start_processing(snd_device)    (-EINVAL)
#define audio_extn_spkr_prot_calib_cancel(adev) (0)
#define audio_extn_spkr_prot_stop_processing()     (0)
#define audio_extn_spkr_prot_is_enabled() (false)
#define audio_extn_spkr_prot_get_acdb_id(snd_device)         (-EINVAL)
@@ -189,6 +190,7 @@ void audio_extn_spkr_prot_stop_processing();
bool audio_extn_spkr_prot_is_enabled();
int audio_extn_spkr_prot_get_acdb_id(snd_device_t snd_device);
int audio_extn_get_spkr_prot_snd_device(snd_device_t snd_device);
void audio_extn_spkr_prot_calib_cancel(void *adev);
#endif

#ifndef COMPRESS_CAPTURE_ENABLED
+34 −27
Original line number Diff line number Diff line
@@ -143,7 +143,7 @@ static void spkr_prot_set_spkrstatus(bool enable)
   }
}

static void spkr_prot_calib_cancel(void *adev)
void audio_extn_spkr_prot_calib_cancel(void *adev)
{
    pthread_t threadid;
    struct audio_usecase *uc_info;
@@ -272,6 +272,7 @@ static int spkr_calibrate(int t0)
    struct audio_usecase *uc_info_rx = NULL, *uc_info_tx = NULL;
    int32_t pcm_dev_rx_id = -1, pcm_dev_tx_id = -1;
    struct timespec ts;
    bool acquire_device = false;

    if (!adev) {
        ALOGE("%s: Invalid params", __func__);
@@ -300,12 +301,10 @@ static int spkr_calibrate(int t0)
    uc_info_rx->type = PCM_PLAYBACK;
    uc_info_rx->in_snd_device = SND_DEVICE_NONE;
    uc_info_rx->out_snd_device = SND_DEVICE_OUT_SPEAKER_PROTECTED;
    pthread_mutex_lock(&adev->lock);
    disable_rx = true;
    list_add_tail(&adev->usecase_list, &uc_info_rx->list);
    enable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
    enable_audio_route(adev, uc_info_rx);
    pthread_mutex_unlock(&adev->lock);

    pcm_dev_rx_id = platform_get_pcm_device_id(uc_info_rx->id, PCM_PLAYBACK);
    ALOGV("%s: pcm device id %d", __func__, pcm_dev_rx_id);
@@ -331,12 +330,10 @@ static int spkr_calibrate(int t0)
    uc_info_tx->in_snd_device = SND_DEVICE_NONE;
    uc_info_tx->out_snd_device = SND_DEVICE_NONE;

    pthread_mutex_lock(&adev->lock);
    disable_tx = true;
    list_add_tail(&adev->usecase_list, &uc_info_tx->list);
    enable_snd_device(adev, SND_DEVICE_IN_CAPTURE_VI_FEEDBACK);
    enable_audio_route(adev, uc_info_tx);
    pthread_mutex_unlock(&adev->lock);

    pcm_dev_tx_id = platform_get_pcm_device_id(uc_info_tx->id, PCM_CAPTURE);
    if (pcm_dev_tx_id < 0) {
@@ -367,6 +364,9 @@ static int spkr_calibrate(int t0)
    clock_gettime(CLOCK_REALTIME, &ts);
    ts.tv_sec += (SLEEP_AFTER_CALIB_START/1000);
    ts.tv_nsec = 0;
    pthread_mutex_lock(&handle.mutex_spkr_prot);
    pthread_mutex_unlock(&adev->lock);
    acquire_device = true;
    (void)pthread_cond_timedwait(&handle.spkr_calib_cancel,
        &handle.mutex_spkr_prot, &ts);
    ALOGD("%s: Speaker calibration done", __func__);
@@ -411,21 +411,10 @@ exit:
        if (handle.pcm_tx)
            pcm_close(handle.pcm_tx);
        handle.pcm_tx = NULL;
        if (!handle.cancel_spkr_calib)
            pthread_mutex_lock(&adev->lock);
        if (disable_rx) {
            list_remove(&uc_info_rx->list);
            disable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
            disable_audio_route(adev, uc_info_rx);
        }
        if (disable_tx) {
            list_remove(&uc_info_tx->list);
            disable_snd_device(adev, SND_DEVICE_IN_CAPTURE_VI_FEEDBACK);
            disable_audio_route(adev, uc_info_tx);
        }
        if (!handle.cancel_spkr_calib)
            pthread_mutex_unlock(&adev->lock);

        /* Clear TX calibration to handset mic */
        platform_send_audio_calibration(adev->platform,
        SND_DEVICE_IN_HANDSET_MIC,
        platform_get_default_app_type(adev->platform), 8000);
        if (!status.status) {
            protCfg.mode = MSM_SPKR_PROT_CALIBRATED;
            protCfg.r0 = status.r0;
@@ -441,6 +430,23 @@ exit:
        }
        if (acdb_fd > 0)
            close(acdb_fd);

        if (!handle.cancel_spkr_calib && cleanup) {
            pthread_mutex_unlock(&handle.spkr_calib_cancelack_mutex);
            pthread_cond_wait(&handle.spkr_calib_cancel,
            &handle.mutex_spkr_prot);
            pthread_mutex_lock(&handle.spkr_calib_cancelack_mutex);
        }
        if (disable_rx) {
            list_remove(&uc_info_rx->list);
            disable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
            disable_audio_route(adev, uc_info_rx);
        }
        if (disable_tx) {
            list_remove(&uc_info_tx->list);
            disable_snd_device(adev, SND_DEVICE_IN_CAPTURE_VI_FEEDBACK);
            disable_audio_route(adev, uc_info_tx);
        }
        if (uc_info_rx) free(uc_info_rx);
        if (uc_info_tx) free(uc_info_tx);
        if (cleanup) {
@@ -448,8 +454,11 @@ exit:
                pthread_cond_signal(&handle.spkr_calibcancel_ack);
            handle.cancel_spkr_calib = 0;
            pthread_mutex_unlock(&handle.spkr_calib_cancelack_mutex);
            pthread_mutex_unlock(&handle.mutex_spkr_prot);
        }
    }
    if (acquire_device)
        pthread_mutex_lock(&adev->lock);
    return status.status;
}

@@ -535,16 +544,16 @@ static void* spkr_calibration_thread(void *context)
            t0 = SAFE_SPKR_TEMP_Q6;
        }
        goahead = false;
        pthread_mutex_lock(&handle.mutex_spkr_prot);
        pthread_mutex_lock(&adev->lock);
        if (is_speaker_in_use(&sec)) {
            ALOGD("%s: Speaker in use retry calibration", __func__);
            pthread_mutex_unlock(&handle.mutex_spkr_prot);
            pthread_mutex_unlock(&adev->lock);
            continue;
        } else {
            ALOGD("%s: speaker idle %ld", __func__, sec);
            if (sec < MIN_SPKR_IDLE_SEC) {
                ALOGD("%s: speaker idle is less retry", __func__);
                pthread_mutex_unlock(&handle.mutex_spkr_prot);
                pthread_mutex_unlock(&adev->lock);
                continue;
            }
            goahead = true;
@@ -552,21 +561,20 @@ static void* spkr_calibration_thread(void *context)
        if (!list_empty(&adev->usecase_list)) {
            ALOGD("%s: Usecase active re-try calibration", __func__);
            goahead = false;
            pthread_mutex_unlock(&handle.mutex_spkr_prot);
            pthread_mutex_unlock(&adev->lock);
        }
        if (goahead) {
                int status;
                status = spkr_calibrate(t0);
                pthread_mutex_unlock(&adev->lock);
                if (status == -EAGAIN) {
                    ALOGE("%s: failed to calibrate try again %s",
                    __func__, strerror(status));
                    pthread_mutex_unlock(&handle.mutex_spkr_prot);
                    continue;
                } else {
                    ALOGE("%s: calibrate status %s", __func__, strerror(status));
                }
                ALOGD("%s: spkr_prot_thread end calibration", __func__);
                pthread_mutex_unlock(&handle.mutex_spkr_prot);
                break;
        }
    }
@@ -692,7 +700,6 @@ int audio_extn_spkr_prot_start_processing(snd_device_t snd_device)
       ALOGE("%s: Invalid params", __func__);
       return -EINVAL;
    }
    spkr_prot_calib_cancel(adev);
    spkr_prot_set_spkrstatus(true);
    uc_info_tx = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
    ALOGV("%s: snd_device(%d: %s)", __func__, snd_device,
+2 −0
Original line number Diff line number Diff line
@@ -340,6 +340,8 @@ int enable_snd_device(struct audio_device *adev,
        return 0;
    }

    if (audio_extn_spkr_prot_is_enabled())
         audio_extn_spkr_prot_calib_cancel(adev);
    /* start usb playback thread */
    if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
       SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)