hikey960: Enable Audio DSP in Audio HAL

Enable XAF in Audio HAL if TARGET_ENABLE_DSP_DEVICE=true
  is set in the build
Disable host side XAF logs
To see DSP logs push device/linaro/hifi/xaf/host-apf/tools/dhifimesg
  to /system/bin
then run adb shell dhifimesg

Bug: 64395692
Test: Manual

Change-Id: Iff35ac78deb39c1801a5318074eb0fed28506937
Signed-off-by: Niranjan Yadla <nyadla@cadence.com>
diff --git a/audio/Android.mk b/audio/Android.mk
index fe091a8..c1ba564 100644
--- a/audio/Android.mk
+++ b/audio/Android.mk
@@ -33,5 +33,16 @@
         system/media/audio_utils/include \
         system/media/audio_effects/include
 
+ifeq ($(TARGET_ENABLE_DSP_DEVICE), true)
+LOCAL_CFLAGS += -DENABLE_XAF_DSP_DEVICE
+LOCAL_C_INCLUDES += \
+        $(LOCAL_PATH)/../hifi/xaf/host-apf/include \
+        $(LOCAL_PATH)/../hifi/xaf/host-apf/include/os/android \
+        $(LOCAL_PATH)/../hifi/xaf/host-apf/include/sys/fio\
+        $(LOCAL_PATH)/../hifi/xaf/host-apf/include/audio \
+        $(LOCAL_PATH)/../hifi/xaf/host-apf/utest/include
+
+LOCAL_STATIC_LIBRARIES := libxtensa_proxy
+endif
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/audio/audio_hw.c b/audio/audio_hw.c
index 7b66a1a..ceeea8c 100644
--- a/audio/audio_hw.c
+++ b/audio/audio_hw.c
@@ -59,6 +59,33 @@
 #define CHANNEL_STEREO 2
 #define MIN_WRITE_SLEEP_US      5000
 
+#ifdef ENABLE_XAF_DSP_DEVICE
+#include "xaf-utils-test.h"
+#include "audio/xa_vorbis_dec_api.h"
+#include "audio/xa-audio-decoder-api.h"
+#define NUM_COMP_IN_GRAPH   1
+
+struct alsa_audio_device;
+
+struct xaf_dsp_device {
+    void *p_adev;
+    void *p_decoder;
+    xaf_info_t comp_info;
+    /* ...playback format */
+    xaf_format_t pb_format;
+    xaf_comp_status dec_status;
+    int dec_info[4];
+    void *dec_inbuf[2];
+    int read_length;
+    xf_id_t dec_id;
+    int xaf_started;
+    mem_obj_t* mem_handle;
+    int num_comp;
+    int (*dec_setup)(void *p_comp, struct alsa_audio_device *audio_device);
+    int xafinitdone;
+};
+#endif
+
 struct stub_stream_in {
     struct audio_stream_in stream;
 };
@@ -71,6 +98,10 @@
     struct alsa_stream_in *active_input;
     struct alsa_stream_out *active_output;
     bool mic_mute;
+#ifdef ENABLE_XAF_DSP_DEVICE
+    struct xaf_dsp_device dsp_device;
+    int hifi_dsp_fd;
+#endif
 };
 
 struct alsa_stream_out {
@@ -86,6 +117,134 @@
     unsigned int written;
 };
 
+#ifdef ENABLE_XAF_DSP_DEVICE
+static int pcm_setup(void *p_pcm, struct alsa_audio_device *audio_device)
+{
+    int param[6];
+
+    param[0] = XA_CODEC_CONFIG_PARAM_SAMPLE_RATE;
+    param[1] = audio_device->dsp_device.pb_format.sample_rate;
+    param[2] = XA_CODEC_CONFIG_PARAM_CHANNELS;
+    param[3] = audio_device->dsp_device.pb_format.channels;
+    param[4] = XA_CODEC_CONFIG_PARAM_PCM_WIDTH;
+    param[5] = audio_device->dsp_device.pb_format.pcm_width;
+
+    XF_CHK_API(xaf_comp_set_config(p_pcm, 3, &param[0]));
+
+    return 0;
+}
+
+void xa_thread_exit_handler(int sig)
+{
+    /* ...unused arg */
+    (void) sig;
+
+    pthread_exit(0);
+}
+
+/*xtensa audio device init*/
+static int xa_device_init(struct alsa_audio_device *audio_device)
+{
+    /* ...initialize playback format */
+    audio_device->dsp_device.p_adev = NULL;
+    audio_device->dsp_device.pb_format.sample_rate = 48000;
+    audio_device->dsp_device.pb_format.channels    = 2;
+    audio_device->dsp_device.pb_format.pcm_width   = 16;
+    audio_device->dsp_device.xafinitdone = 0;
+    audio_frmwk_buf_size = 0; //unused
+    audio_comp_buf_size  = 0; //unused
+    audio_device->dsp_device.num_comp = NUM_COMP_IN_GRAPH;
+    struct sigaction actions;
+    memset(&actions, 0, sizeof(actions));
+    sigemptyset(&actions.sa_mask);
+    actions.sa_flags = 0;
+    actions.sa_handler = xa_thread_exit_handler;
+    sigaction(SIGUSR1,&actions,NULL);
+    /* ...initialize tracing facility */
+    audio_device->dsp_device.xaf_started =1;
+    audio_device->dsp_device.dec_id    = "audio-decoder/pcm";
+    audio_device->dsp_device.dec_setup = pcm_setup;
+    audio_device->dsp_device.mem_handle = mem_init(); //initialize memory handler
+    XF_CHK_API(xaf_adev_open(&audio_device->dsp_device.p_adev, audio_frmwk_buf_size, audio_comp_buf_size, mem_malloc, mem_free));
+    /* ...create decoder component */
+    XF_CHK_API(xaf_comp_create(audio_device->dsp_device.p_adev, &audio_device->dsp_device.p_decoder, audio_device->dsp_device.dec_id, 1, 1, &audio_device->dsp_device.dec_inbuf[0], XAF_DECODER));
+    XF_CHK_API(audio_device->dsp_device.dec_setup(audio_device->dsp_device.p_decoder,audio_device));
+
+    /* ...start decoder component */
+    XF_CHK_API(xaf_comp_process(audio_device->dsp_device.p_adev, audio_device->dsp_device.p_decoder, NULL, 0, XAF_START_FLAG));
+    return 0;
+}
+
+static int xa_device_run(struct audio_stream_out *stream, const void *buffer, size_t frame_size, size_t out_frames, size_t bytes)
+{
+    struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
+    struct alsa_audio_device *adev = out->dev;
+    int ret=0;
+    void *p_comp=adev->dsp_device.p_decoder;
+    xaf_comp_status comp_status;
+    memcpy(adev->dsp_device.dec_inbuf[0],buffer,bytes);
+    adev->dsp_device.read_length=bytes;
+
+    if (adev->dsp_device.xafinitdone == 0) {
+        XF_CHK_API(xaf_comp_process(adev->dsp_device.p_adev, adev->dsp_device.p_decoder, adev->dsp_device.dec_inbuf[0], adev->dsp_device.read_length, XAF_INPUT_READY_FLAG));
+        XF_CHK_API(xaf_comp_get_status(adev->dsp_device.p_adev, adev->dsp_device.p_decoder, &adev->dsp_device.dec_status, &adev->dsp_device.comp_info));
+        ALOGE("PROXY:%s xaf_comp_get_status %d\n",__func__,adev->dsp_device.dec_status);
+        if (adev->dsp_device.dec_status == XAF_INIT_DONE) {
+            adev->dsp_device.xafinitdone = 1;
+            out->written += out_frames;
+            XF_CHK_API(xaf_comp_process(NULL, p_comp, NULL, 0, XAF_EXEC_FLAG));
+        }
+    } else {
+        XF_CHK_API(xaf_comp_process(NULL, adev->dsp_device.p_decoder, adev->dsp_device.dec_inbuf[0], adev->dsp_device.read_length, XAF_INPUT_READY_FLAG));
+        while (1) {
+            XF_CHK_API(xaf_comp_get_status(NULL, p_comp, &comp_status, &adev->dsp_device.comp_info));
+            if (comp_status == XAF_EXEC_DONE) break;
+            if (comp_status == XAF_NEED_INPUT) {
+                 ALOGV("PROXY:%s loop:XAF_NEED_INPUT\n",__func__);
+                 break;
+            }
+            if (comp_status == XAF_OUTPUT_READY) {
+                void *p_buf = (void *)adev->dsp_device.comp_info.buf;
+                int size    = adev->dsp_device.comp_info.length;
+                ret = pcm_mmap_write(out->pcm, p_buf, size);
+                if (ret == 0) {
+                    out->written += out_frames;
+                }
+                XF_CHK_API(xaf_comp_process(NULL, adev->dsp_device.p_decoder, (void *)adev->dsp_device.comp_info.buf, adev->dsp_device.comp_info.length, XAF_NEED_OUTPUT_FLAG));
+            }
+        }
+    }
+    return ret;
+}
+
+static int xa_device_close(struct alsa_audio_device *audio_device)
+{
+    if (audio_device->dsp_device.xaf_started) {
+        xaf_comp_status comp_status;
+        audio_device->dsp_device.xaf_started=0;
+        while (1) {
+            XF_CHK_API(xaf_comp_get_status(NULL, audio_device->dsp_device.p_decoder, &comp_status, &audio_device->dsp_device.comp_info));
+            ALOGV("PROXY:comp_status:%d,audio_device->dsp_device.comp_info.length:%d\n",(int)comp_status,audio_device->dsp_device.comp_info.length);
+            if (comp_status == XAF_EXEC_DONE)
+                break;
+            if (comp_status == XAF_NEED_INPUT) {
+                XF_CHK_API(xaf_comp_process(NULL, audio_device->dsp_device.p_decoder, NULL, 0, XAF_INPUT_OVER_FLAG));
+            }
+
+            if (comp_status == XAF_OUTPUT_READY) {
+                XF_CHK_API(xaf_comp_process(NULL, audio_device->dsp_device.p_decoder, (void *)audio_device->dsp_device.comp_info.buf, audio_device->dsp_device.comp_info.length, XAF_NEED_OUTPUT_FLAG));
+            }
+        }
+
+        /* ...exec done, clean-up */
+        XF_CHK_API(xaf_comp_delete(audio_device->dsp_device.p_decoder));
+        XF_CHK_API(xaf_adev_close(audio_device->dsp_device.p_adev, 0 /*unused*/));
+        mem_exit();
+        XF_CHK_API(print_mem_mcps_info(audio_device->dsp_device.mem_handle, audio_device->dsp_device.num_comp));
+    }
+    return 0;
+}
+#endif
 
 /* must be called with hw device and output stream mutexes locked */
 static int start_output_stream(struct alsa_stream_out *out)
@@ -180,6 +339,9 @@
 
     pthread_mutex_lock(&out->dev->lock);
     pthread_mutex_lock(&out->lock);
+#ifdef ENABLE_XAF_DSP_DEVICE
+    xa_device_close(out->dev);
+#endif
     status = do_output_standby(out);
     pthread_mutex_unlock(&out->lock);
     pthread_mutex_unlock(&out->dev->lock);
@@ -256,6 +418,11 @@
     pthread_mutex_lock(&adev->lock);
     pthread_mutex_lock(&out->lock);
     if (out->standby) {
+#ifdef ENABLE_XAF_DSP_DEVICE
+        if (adev->hifi_dsp_fd >= 0) {
+            xa_device_init(adev);
+        }
+#endif
         ret = start_output_stream(out);
         if (ret != 0) {
             pthread_mutex_unlock(&adev->lock);
@@ -266,11 +433,19 @@
 
     pthread_mutex_unlock(&adev->lock);
 
-
-    ret = pcm_mmap_write(out->pcm, buffer, out_frames * frame_size);
-    if (ret == 0) {
-        out->written += out_frames;
+#ifdef ENABLE_XAF_DSP_DEVICE
+    /*fallback to original audio processing*/
+    if (adev->dsp_device.p_adev != NULL) {
+        ret = xa_device_run(stream, buffer,frame_size, out_frames, bytes);
+    } else {
+#endif
+        ret = pcm_mmap_write(out->pcm, buffer, out_frames * frame_size);
+        if (ret == 0) {
+            out->written += out_frames;
+        }
+#ifdef ENABLE_XAF_DSP_DEVICE
     }
+#endif
 exit:
     pthread_mutex_unlock(&out->lock);
 
@@ -628,7 +803,14 @@
 
 static int adev_close(hw_device_t *device)
 {
+#ifdef ENABLE_XAF_DSP_DEVICE
+    struct alsa_audio_device *adev = (struct alsa_audio_device *)device;
+#endif
     ALOGV("adev_close");
+#ifdef ENABLE_XAF_DSP_DEVICE
+    if (adev->hifi_dsp_fd >= 0)
+        close(adev->hifi_dsp_fd);
+#endif
     free(device);
     return 0;
 }
@@ -672,7 +854,14 @@
     adev->devices = AUDIO_DEVICE_NONE;
 
     *device = &adev->hw_device.common;
-
+#ifdef ENABLE_XAF_DSP_DEVICE
+    adev->hifi_dsp_fd = open(HIFI_DSP_MISC_DRIVER, O_WRONLY, 0);
+    if (adev->hifi_dsp_fd < 0) {
+        ALOGW("hifi_dsp: Error opening device %d", errno);
+    } else {
+        ALOGI("hifi_dsp: Open device");
+    }
+#endif
     return 0;
 }
 
diff --git a/hifi/xaf/host-apf/Android.mk b/hifi/xaf/host-apf/Android.mk
index aa859d0..28e7101 100644
--- a/hifi/xaf/host-apf/Android.mk
+++ b/hifi/xaf/host-apf/Android.mk
@@ -23,7 +23,7 @@
 	utest/xaf-utils-test.c	\
 	utest/xaf-mem-test.c
 
-C_FLAGS := -DXF_TRACE=1 -Wall -Werror #-Wno-everything
+C_FLAGS := -DXF_TRACE=0 -Wall -Werror -Wno-everything
 
 LOCAL_C_INCLUDES := $(common_C_INCLUDES)
 LOCAL_CFLAGS := $(C_FLAGS)