flounder: fix crackling sound and no sound after voip call

Tfa9895 need pcm output continously during fw loading. Reopen pcm
with larger stop_threshold only for the case.

Bug 18024252

Change-Id: I93b0610d44129c2cc4b52b3188f4b79121c0c8df
diff --git a/audio/hal/audio_hw.c b/audio/hal/audio_hw.c
index 356171e..8b7fc20 100644
--- a/audio/hal/audio_hw.c
+++ b/audio/hal/audio_hw.c
@@ -110,7 +110,7 @@
         .period_count = PLAYBACK_PERIOD_COUNT,
         .format = PCM_FORMAT_S16_LE,
         .start_threshold = PLAYBACK_START_THRESHOLD,
-        .stop_threshold = INT_MAX/2,
+        .stop_threshold = PLAYBACK_STOP_THRESHOLD,
         .silence_threshold = 0,
         .avail_min = PLAYBACK_AVAILABLE_MIN,
     },
@@ -2886,6 +2886,7 @@
     size_t frame_size = audio_stream_out_frame_size(stream);
     size_t frames_wr = 0, frames_rq = 0;
     unsigned char *data = NULL;
+    struct pcm_config config;
 #ifdef PREPROCESSING_ENABLED
     size_t in_frames = bytes / frame_size;
     size_t out_frames = in_frames;
@@ -3014,27 +3015,71 @@
                     out->echo_reference->write(out->echo_reference, &b);
                  }
 #endif
-                if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
-                    pthread_mutex_lock(&adev->tfa9895_lock);
-                    if (adev->tfa9895_mode_change == 0x1) {
+                if (adev->tfa9895_mode_change == 0x1) {
+                    if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
+                        pthread_mutex_lock(&adev->tfa9895_lock);
                         data = (unsigned char *)
                                 calloc(pcm_frames_to_bytes(pcm_device->pcm, out->config.period_size),
                                         sizeof(unsigned char));
                         if (data) {
                             int i;
-                            for (i = out->config.period_count; i > 0; i--)
-                                pcm_write(pcm_device->pcm, (void *)data,
-                                    pcm_frames_to_bytes(pcm_device->pcm, out->config.period_size));
-                            /* TODO: Hold on 100 ms and wait i2s signal ready
+
+                            // reopen pcm with stop_threshold = INT_MAX/2
+                            memcpy(&config, &pcm_device->pcm_profile->config,
+                                    sizeof(struct pcm_config));
+                            config.stop_threshold = INT_MAX/2;
+
+                            if (pcm_device->pcm)
+                                pcm_close(pcm_device->pcm);
+
+                            for (i = 0; i < RETRY_NUMBER; i++) {
+                                pcm_device->pcm = pcm_open(pcm_device->pcm_profile->card,
+                                        pcm_device->pcm_profile->id,
+                                        PCM_OUT | PCM_MONOTONIC, &config);
+                                if (pcm_device->pcm != NULL && pcm_is_ready(pcm_device->pcm))
+                                    break;
+                                else
+                                    usleep(10000);
+                            }
+                            if (i >= RETRY_NUMBER)
+                                ALOGE("%s: failed to reopen pcm device", __func__);
+
+                            if (pcm_device->pcm) {
+                                for (i = out->config.period_count; i > 0; i--)
+                                    pcm_write(pcm_device->pcm, (void *)data,
+                                           pcm_frames_to_bytes(pcm_device->pcm,
+                                           out->config.period_size));
+                                /* TODO: Hold on 100 ms and wait i2s signal ready
                                      before giving dsp related i2c commands */
-                            usleep(100000);
-                            adev->tfa9895_mode_change &= ~0x1;
-                            ALOGD("@@##checking - 2: tfa9895_config_thread: "
+                                usleep(100000);
+                                adev->tfa9895_mode_change &= ~0x1;
+                                ALOGD("@@##checking - 2: tfa9895_config_thread: "
                                     "adev->tfa9895_mode_change=%d", adev->tfa9895_mode_change);
-                            adev->tfa9895_init =
-                                adev->htc_acoustic_set_amp_mode(adev->mode, AUDIO_DEVICE_OUT_SPEAKER,
-                                                                    0, 0, false);
+                                adev->tfa9895_init =
+                                        adev->htc_acoustic_set_amp_mode(
+                                                adev->mode, AUDIO_DEVICE_OUT_SPEAKER, 0, 0, false);
+                            }
                             free(data);
+
+                            // reopen pcm with normal stop_threshold
+                            if (pcm_device->pcm)
+                                pcm_close(pcm_device->pcm);
+
+                            for (i = 0; i < RETRY_NUMBER; i++) {
+                                pcm_device->pcm = pcm_open(pcm_device->pcm_profile->card,
+                                        pcm_device->pcm_profile->id,
+                                        PCM_OUT | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
+                                if (pcm_device->pcm != NULL && pcm_is_ready(pcm_device->pcm))
+                                    break;
+                                else
+                                    usleep(10000);
+                            }
+                            if (i >= RETRY_NUMBER) {
+                                ALOGE("%s: failed to reopen pcm device, error return", __func__);
+                                pthread_mutex_unlock(&adev->tfa9895_lock);
+                                pthread_mutex_unlock(&out->lock);
+                                return -1;
+                            }
                         }
                     }
                     pthread_mutex_unlock(&adev->tfa9895_lock);