fm: Support device loopback using set param.

 - Add support for FM device loopback and device routing
   using set param.

Change-Id: Ie49aa1cc5afd182c166bc13309bead86839d16db
diff --git a/hal/audio_extn/fm.c b/hal/audio_extn/fm.c
index 24facea..49b36c6 100644
--- a/hal/audio_extn/fm.c
+++ b/hal/audio_extn/fm.c
@@ -44,6 +44,7 @@
 #define AUDIO_PARAMETER_KEY_REC_PLAY_CONC "rec_play_conc_on"
 #define AUDIO_PARAMETER_KEY_FM_MUTE "fm_mute"
 #define AUDIO_PARAMETER_KEY_FM_RESTORE_VOLUME "fm_restore_volume"
+#define AUDIO_PARAMETER_KEY_FM_ROUTING "fm_routing"
 #define FM_LOOPBACK_DRAIN_TIME_MS 2
 
 static struct pcm_config pcm_config_fm = {
@@ -64,6 +65,7 @@
     bool is_fm_muted;
     float fm_volume;
     bool restart_fm;
+    audio_devices_t fm_device;
     card_status_t card_status;
 };
 
@@ -74,6 +76,7 @@
   .is_fm_running = 0,
   .is_fm_muted = 0,
   .restart_fm = 0,
+  .fm_device = 0,
   .card_status = CARD_STATUS_ONLINE,
 };
 
@@ -153,29 +156,44 @@
     disable_snd_device(adev, uc_info->in_snd_device);
 
     list_remove(&uc_info->list);
+    free(uc_info->stream.out);
     free(uc_info);
 
     ALOGD("%s: exit: status(%d)", __func__, ret);
     return ret;
 }
 
-static int32_t fm_start(struct audio_device *adev)
+
+static int32_t fm_start(struct audio_device *adev, audio_devices_t outputDevices)
 {
+    struct stream_out *fm_out;
     int32_t ret = 0;
     struct audio_usecase *uc_info;
     int32_t pcm_dev_rx_id, pcm_dev_tx_id;
 
-    ALOGD("%s: enter", __func__);
+    ALOGD("%s: Start FM over output device %d ", __func__, outputDevices);
+
+    fm_out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
+    if (!fm_out)
+        return -ENOMEM;
+
+    fm_out->sample_rate = 48000;
+    fm_out->format = AUDIO_FORMAT_PCM_16_BIT;
+    fm_out->usecase = USECASE_AUDIO_PLAYBACK_FM;
+    fm_out->config = pcm_config_fm;
+    fm_out->devices = outputDevices;
 
     uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
 
-    if (!uc_info)
+    if (!uc_info) {
+        free(fm_out);
         return -ENOMEM;
+    }
 
     uc_info->id = USECASE_AUDIO_PLAYBACK_FM;
     uc_info->type = PCM_PLAYBACK;
-    uc_info->stream.out = adev->primary_output;
-    uc_info->devices = adev->primary_output->devices;
+    uc_info->stream.out = fm_out;
+    uc_info->devices = outputDevices;
     uc_info->in_snd_device = SND_DEVICE_NONE;
     uc_info->out_snd_device = SND_DEVICE_NONE;
 
@@ -221,6 +239,7 @@
     pcm_start(fmmod.fm_pcm_tx);
 
     fmmod.is_fm_running = true;
+    fmmod.fm_device = fm_out->devices;
     fm_set_volume(adev, fmmod.fm_volume, false);
 
     ALOGD("%s: exit: status(%d)", __func__, ret);
@@ -268,7 +287,7 @@
     if (fmmod.restart_fm && (fmmod.card_status == CARD_STATUS_ONLINE)) {
         ALOGD("sound card is ONLINE, restart FM");
         fmmod.restart_fm = 0;
-        fm_start(adev);
+        fm_start(adev, fmmod.fm_device);
     }
 
     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HANDLE_FM,
@@ -279,8 +298,8 @@
         if (val != 0) {
             if(val & AUDIO_DEVICE_OUT_FM
                && fmmod.is_fm_running == false) {
-                adev->primary_output->devices = val & ~AUDIO_DEVICE_OUT_FM;
-                fm_start(adev);
+                audio_devices_t OutputDevice = val & ~AUDIO_DEVICE_OUT_FM;
+                fm_start(adev, OutputDevice);
             } else if (!(val & AUDIO_DEVICE_OUT_FM)
                      && fmmod.is_fm_running == true) {
                 fm_set_volume(adev, 0, false);
@@ -290,6 +309,21 @@
        }
     }
 
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FM_ROUTING,
+                            value, sizeof(value));
+    if (ret >= 0 && fmmod.is_fm_running) {
+        val = atoi(value);
+        ALOGD("%s: FM usecase", __func__);
+        if (val != 0) {
+            if(val & AUDIO_DEVICE_OUT_FM) {
+                audio_devices_t OutputDevice = val & ~AUDIO_DEVICE_OUT_FM;
+                fm_set_volume(adev, 0, false);
+                fm_stop(adev);
+                fm_start(adev, OutputDevice);
+            }
+        }
+    }
+
     memset(value, 0, sizeof(value));
     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FM_VOLUME,
                             value, sizeof(value));