post_proc: Support Headphone:X in offload and non tunnel modes

Support Headphone:X in offload and non tunnel modes

Change-Id: Ib30d60bce67cb43556d58a2387735ce715d035a4
Signed-off-by: Alexy Joseph <alexyj@codeaurora.org>
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index e253159..880838a 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -59,6 +59,10 @@
 
 LOCAL_CFLAGS += -O2 -fvisibility=hidden
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DTS_EAGLE)), true)
+LOCAL_CFLAGS += -DHW_ACC_HPX
+endif
+
 LOCAL_MODULE:= libhwacceffectswrapper
 
 include $(BUILD_STATIC_LIBRARY)
diff --git a/post_proc/EffectsHwAcc.cpp b/post_proc/EffectsHwAcc.cpp
index d88a199..0e4c55a 100644
--- a/post_proc/EffectsHwAcc.cpp
+++ b/post_proc/EffectsHwAcc.cpp
@@ -343,5 +343,33 @@
     }
 }
 
+#ifdef HW_ACC_HPX
+void EffectsHwAcc::updateHPXState(uint32_t state)
+{
+    EffectsBufferProvider *pHwAccbp = mBufferProvider;
+    if (pHwAccbp) {
+        ALOGV("updateHPXState: %d", state);
+        int cmdStatus, status;
+        uint32_t replySize = sizeof(int);
+        uint32_t data = state;
+        uint32_t size = (sizeof(effect_param_t) + 2 * sizeof(int32_t));
+        uint32_t buf32[size];
+        effect_param_t *param = (effect_param_t *)buf32;
+
+        param->psize = sizeof(int32_t);
+        *(int32_t *)param->data = HW_ACCELERATOR_HPX_STATE;
+        param->vsize = sizeof(int32_t);
+        memcpy((param->data + param->psize), &data, param->vsize);
+        status = (*pHwAccbp->mEffectsHandle)->command(pHwAccbp->mEffectsHandle,
+                                          EFFECT_CMD_SET_PARAM,
+                                          sizeof(effect_param_t) + param->psize +
+                                          param->vsize,
+                                          param, &replySize, &cmdStatus);
+
+        if ((status != 0) || (cmdStatus != 0))
+            ALOGE("error %d while updating HW ACC HPX BYPASS state", status);
+    }
+}
+#endif
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/post_proc/EffectsHwAcc.h b/post_proc/EffectsHwAcc.h
index 919332b..6420a9b 100644
--- a/post_proc/EffectsHwAcc.h
+++ b/post_proc/EffectsHwAcc.h
@@ -48,6 +48,10 @@
                             int frameCount);
     virtual void setBufferProvider(AudioBufferProvider **bufferProvider,
                            AudioBufferProvider **trackBufferProvider);
+#ifdef HW_ACC_HPX
+    virtual void updateHPXState(uint32_t state);
+#endif
+
     /* AudioBufferProvider that wraps a track AudioBufferProvider by a call to
        h/w accelerated effect */
     class EffectsBufferProvider : public AudioBufferProvider {
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index 871b087..410e17b 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -326,6 +326,132 @@
     return ret;
 }
 
+__attribute__ ((visibility ("default")))
+int offload_effects_bundle_set_hpx_state(bool hpx_state)
+{
+    int ret = 0;
+    struct listnode *node;
+
+    ALOGV("%s hpx state: %d", __func__, hpx_state);
+
+    if (lib_init() != 0)
+        return init_status;
+
+    pthread_mutex_lock(&lock);
+
+    if (hpx_state) {
+        /* set ramp down */
+        list_for_each(node, &active_outputs_list) {
+            output_context_t *out_ctxt = node_to_item(node,
+                                                      output_context_t,
+                                                      outputs_list_node);
+            struct soft_volume_params vol;
+            vol.master_gain = 0x0;
+            offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
+                              OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
+        }
+        /* wait for ramp down duration - 30msec */
+        usleep(30000);
+        /* disable effects modules */
+        list_for_each(node, &active_outputs_list) {
+            struct listnode *fx_node;
+            output_context_t *out_ctxt = node_to_item(node,
+                                                      output_context_t,
+                                                      outputs_list_node);
+            list_for_each(fx_node, &out_ctxt->effects_list) {
+                effect_context_t *fx_ctxt = node_to_item(fx_node,
+                                                         effect_context_t,
+                                                         output_node);
+                if ((fx_ctxt->state == EFFECT_STATE_ACTIVE) &&
+                    (fx_ctxt->ops.stop != NULL))
+                    fx_ctxt->ops.stop(fx_ctxt, out_ctxt);
+            }
+            out_ctxt->ctl = NULL;
+        }
+        /* set the channel mixer */
+        list_for_each(node, &active_outputs_list) {
+            /* send command to set channel mixer */
+        }
+        /* enable hpx modules */
+        list_for_each(node, &active_outputs_list) {
+            output_context_t *out_ctxt = node_to_item(node,
+                                                      output_context_t,
+                                                      outputs_list_node);
+            offload_hpx_send_params(out_ctxt->ref_ctl,
+                                    OFFLOAD_SEND_HPX_STATE_ON);
+        }
+        /* wait for transition state - 50msec */
+        usleep(50000);
+        /* set ramp up */
+        list_for_each(node, &active_outputs_list) {
+            output_context_t *out_ctxt = node_to_item(node,
+                                                      output_context_t,
+                                                      outputs_list_node);
+            struct soft_volume_params vol;
+            vol.master_gain = 0x2000;
+            offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
+                              OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
+        }
+    } else {
+        /* set ramp down */
+        list_for_each(node, &active_outputs_list) {
+            output_context_t *out_ctxt = node_to_item(node,
+                                                      output_context_t,
+                                                      outputs_list_node);
+            struct soft_volume_params vol;
+            vol.master_gain = 0x0;
+            offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
+                              OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
+        }
+        /* wait for ramp down duration - 30msec */
+        usleep(30000);
+        /* disable effects modules */
+        list_for_each(node, &active_outputs_list) {
+            output_context_t *out_ctxt = node_to_item(node,
+                                                      output_context_t,
+                                                      outputs_list_node);
+            offload_hpx_send_params(out_ctxt->ref_ctl,
+                                    OFFLOAD_SEND_HPX_STATE_OFF);
+        }
+        /* set the channel mixer */
+        list_for_each(node, &active_outputs_list) {
+            /* send command to set channel mixer */
+        }
+        /* enable effects modules */
+        list_for_each(node, &active_outputs_list) {
+            struct listnode *fx_node;
+            output_context_t *out_ctxt = node_to_item(node,
+                                                      output_context_t,
+                                                      outputs_list_node);
+            out_ctxt->ctl = out_ctxt->ref_ctl;
+            list_for_each(fx_node, &out_ctxt->effects_list) {
+                effect_context_t *fx_ctxt = node_to_item(fx_node,
+                                                         effect_context_t,
+                                                         output_node);
+                if ((fx_ctxt->state == EFFECT_STATE_ACTIVE) &&
+                    (fx_ctxt->ops.start != NULL))
+                    fx_ctxt->ops.start(fx_ctxt, out_ctxt);
+            }
+        }
+        /* wait for transition state - 50msec */
+        usleep(50000);
+        /* set ramp up */
+        list_for_each(node, &active_outputs_list) {
+            output_context_t *out_ctxt = node_to_item(node,
+                                                      output_context_t,
+                                                      outputs_list_node);
+            struct soft_volume_params vol;
+            vol.master_gain = 0x2000;
+            offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
+                              OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
+        }
+    }
+
+exit:
+    pthread_mutex_unlock(&lock);
+    return ret;
+}
+
 /*
  * Effect operations
  */
diff --git a/post_proc/effect_api.c b/post_proc/effect_api.c
index 61f6f00..7c1968e 100644
--- a/post_proc/effect_api.c
+++ b/post_proc/effect_api.c
@@ -882,3 +882,38 @@
 
     return 0;
 }
+
+static int hpx_send_params(eff_mode_t mode, void *ctl,
+                           unsigned param_send_flags)
+{
+    int param_values[128] = {0};
+    int *p_param_values = param_values;
+    uint32_t i;
+
+    ALOGV("%s", __func__);
+    if (param_send_flags & OFFLOAD_SEND_HPX_STATE_OFF) {
+        *p_param_values++ = DTS_EAGLE_MODULE_ENABLE;
+        *p_param_values++ = 0; /* hpx off*/
+    } else if (param_send_flags & OFFLOAD_SEND_HPX_STATE_ON) {
+        *p_param_values++ = DTS_EAGLE_MODULE_ENABLE;
+        *p_param_values++ = 1; /* hpx on*/
+    }
+
+    if ((mode == OFFLOAD) && ctl)
+        mixer_ctl_set_array(ctl, param_values, ARRAY_SIZE(param_values));
+    else {
+        if (ioctl(*(int *)ctl, AUDIO_EFFECTS_SET_PP_PARAMS, param_values) < 0)
+            ALOGE("%s: sending h/w acc hpx state params fail[%d]", __func__, errno);
+    }
+    return 0;
+}
+
+int offload_hpx_send_params(struct mixer_ctl *ctl, unsigned param_send_flags)
+{
+    return hpx_send_params(OFFLOAD, (void *)ctl, param_send_flags);
+}
+
+int hw_acc_hpx_send_params(int fd, unsigned param_send_flags)
+{
+    return hpx_send_params(HW_ACCELERATOR, (void *)&fd, param_send_flags);
+}
diff --git a/post_proc/effect_api.h b/post_proc/effect_api.h
index d3b1d81..e05924a 100644
--- a/post_proc/effect_api.h
+++ b/post_proc/effect_api.h
@@ -192,6 +192,12 @@
 int offload_transition_soft_volume_send_params(struct mixer_ctl *ctl,
                                                struct soft_volume_params vol,
                                                unsigned param_send_flags);
+
+#define OFFLOAD_SEND_HPX_STATE_ON       (1 << 0)
+#define OFFLOAD_SEND_HPX_STATE_OFF      (OFFLOAD_SEND_HPX_STATE_ON << 1)
+int offload_hpx_send_params(struct mixer_ctl *ctl, unsigned param_send_flags);
+int hw_acc_hpx_send_params(int fd, unsigned param_send_flags);
+
 #if __cplusplus
 } //extern "C"
 #endif
diff --git a/post_proc/hw_accelerator.c b/post_proc/hw_accelerator.c
index b49337a..fd95db0 100644
--- a/post_proc/hw_accelerator.c
+++ b/post_proc/hw_accelerator.c
@@ -111,7 +111,14 @@
     p->status = 0;
 
     switch (param) {
-    /* Placeholder for effects to use set param */
+    case HW_ACCELERATOR_HPX_STATE: {
+        int hpxState = (uint32_t)(*(int32_t *)value);
+        if (hpxState)
+            hw_acc_hpx_send_params(hw_acc_ctxt->fd, OFFLOAD_SEND_HPX_STATE_ON);
+        else
+            hw_acc_hpx_send_params(hw_acc_ctxt->fd, OFFLOAD_SEND_HPX_STATE_OFF);
+        break;
+    }
     default:
         p->status = -EINVAL;
         break;