hal: Add changes to send pspd coefficients during out_write

Add support to send matrix mixer coefficients in out_write
as older kernel version does not have support to save the
channel weightage values.
Add flag to check and resend matrix mixer coefficients during
device switch.

Change-Id: I8c8991b2b7bbfc60e300b9a965e4d488b2eabb8d
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index fc72590..e7b044f 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -373,27 +373,56 @@
     char mixer_ctl_name[128] = {0};
     struct audio_custom_mtmx_params_info *pinfo = &params->info;
     int i = 0, err = 0;
+    int cust_ch_mixer_cfg[128], len = 0;
 
     ALOGI("%s: ip_channels %d, op_channels %d, pcm_device_id %d",
           __func__, pinfo->ip_channels, pinfo->op_channels, pcm_device_id);
 
-    for (i = 0; i < (int)pinfo->op_channels; i++) {
-         snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "%s %d %s %d",
-                  mixer_name_prefix, pcm_device_id, mixer_name_suffix, i+1);
-         ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
-         if (!ctl) {
-             ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
-                   __func__, mixer_ctl_name);
-             return -EINVAL;
-         }
+    if (adev->use_old_pspd_mix_ctrl) {
+        /*
+         * Below code is to ensure backward compatibilty with older
+         * kernel version. Use old mixer control to set mixer coefficients
+         */
+        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+         "Audio Stream %d Channel Mix Cfg", pcm_device_id);
 
-         err = mixer_ctl_set_array(ctl,
-                                   &params->coeffs[pinfo->ip_channels * i],
-                                   pinfo->ip_channels);
-         if (err) {
-             ALOGE("%s: ERROR. Mixer ctl set failed", __func__);
-             return -EINVAL;
-         }
+        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
+                  __func__, mixer_ctl_name);
+            return -EINVAL;
+        }
+        cust_ch_mixer_cfg[len++] = pinfo->ip_channels;
+        cust_ch_mixer_cfg[len++] = pinfo->op_channels;
+        for (i = 0; i < (int) (pinfo->op_channels * pinfo->ip_channels); i++) {
+            ALOGV("%s: coeff[%d] %d", __func__, i, params->coeffs[i]);
+            cust_ch_mixer_cfg[len++] = params->coeffs[i];
+        }
+        err = mixer_ctl_set_array(ctl, cust_ch_mixer_cfg, len);
+        if (err) {
+            ALOGE("%s: ERROR. Mixer ctl set failed", __func__);
+            return -EINVAL;
+        }
+        ALOGD("%s: Mixer ctl set for %s success", __func__, mixer_ctl_name);
+    } else {
+        for (i = 0; i < (int)pinfo->op_channels; i++) {
+            snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "%s %d %s %d",
+                    mixer_name_prefix, pcm_device_id, mixer_name_suffix, i+1);
+
+            ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+            if (!ctl) {
+                ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
+                      __func__, mixer_ctl_name);
+                 return -EINVAL;
+            }
+            err = mixer_ctl_set_array(ctl,
+                                      &params->coeffs[pinfo->ip_channels * i],
+                                      pinfo->ip_channels);
+            if (err) {
+                ALOGE("%s: ERROR. Mixer ctl set failed", __func__);
+                return -EINVAL;
+            }
+        }
     }
     return 0;
 }
@@ -489,28 +518,27 @@
     info.id = feature_id;
     info.usecase_id = usecase->id;
     for (i = 0, ret = 0; i < num_devices; i++) {
-         info.snd_device = new_snd_devices[i];
-         platform_get_codec_backend_cfg(adev, info.snd_device, &backend_cfg);
-         if (usecase->type == PCM_PLAYBACK) {
-             info.ip_channels = audio_channel_count_from_out_mask(
-                                    usecase->stream.out->channel_mask);
-             info.op_channels = backend_cfg.channels;
-         } else {
-             info.ip_channels = backend_cfg.channels;
-             info.op_channels = audio_channel_count_from_in_mask(
-                                    usecase->stream.in->channel_mask);
-         }
-
-         params = platform_get_custom_mtmx_params(adev->platform, &info);
-         if (params) {
-             if (enable)
-                 ret = update_custom_mtmx_coefficients(adev, params,
-                                                       pcm_device_id);
-             if (ret < 0)
-                 ALOGE("%s: error updating mtmx coeffs err:%d", __func__, ret);
-             else
-                 set_custom_mtmx_params(adev, &info, pcm_device_id, enable);
-         }
+        info.snd_device = new_snd_devices[i];
+        platform_get_codec_backend_cfg(adev, info.snd_device, &backend_cfg);
+        if (usecase->type == PCM_PLAYBACK) {
+            info.ip_channels = audio_channel_count_from_out_mask(
+                                   usecase->stream.out->channel_mask);
+            info.op_channels = backend_cfg.channels;
+        } else {
+            info.ip_channels = backend_cfg.channels;
+            info.op_channels = audio_channel_count_from_in_mask(
+                                   usecase->stream.in->channel_mask);
+        }
+        params = platform_get_custom_mtmx_params(adev->platform, &info);
+        if (params) {
+            if (enable)
+                ret = update_custom_mtmx_coefficients(adev, params,
+                                                      pcm_device_id);
+            if (ret < 0)
+                ALOGE("%s: error updating mtmx coeffs err:%d", __func__, ret);
+            else
+                set_custom_mtmx_params(adev, &info, pcm_device_id, enable);
+        }
     }
 }
 
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index b0aff8e..ab99b47 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1107,6 +1107,8 @@
     audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
     audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
     audio_extn_set_custom_mtmx_params(adev, usecase, false);
+    if (usecase->stream.out != NULL)
+        usecase->stream.out->pspd_coeff_sent = false;
     ALOGV("%s: exit", __func__);
     return 0;
 }
@@ -4915,6 +4917,7 @@
     int channels = 0;
     const size_t frame_size = audio_stream_out_frame_size(stream);
     const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
+    struct audio_usecase *usecase = NULL;
 
     ATRACE_BEGIN("out_write");
     lock_output_stream(out);
@@ -5037,6 +5040,20 @@
         adev->is_channel_status_set = true;
     }
 
+    if ((adev->use_old_pspd_mix_ctrl == true) &&
+        (out->pspd_coeff_sent == false)) {
+        /*
+         * Need to resend pspd coefficients after stream started for
+         * older kernel version as it does not save the coefficients
+         * and also stream has to be started for coeff to apply.
+         */
+        usecase = get_usecase_from_list(adev, out->usecase);
+        if (usecase != NULL) {
+            audio_extn_set_custom_mtmx_params(adev, usecase, true);
+            out->pspd_coeff_sent = true;
+        }
+    }
+
     if (is_offload_usecase(out->usecase)) {
         ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
         if (out->send_new_metadata) {
@@ -6617,6 +6634,7 @@
     out->dynamic_pm_qos_config_supported = 0;
     out->set_dual_mono = false;
     out->prev_card_status_offline = false;
+    out->pspd_coeff_sent = false;
 
     if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
         (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
@@ -8742,6 +8760,8 @@
 {
     int ret;
     char value[PROPERTY_VALUE_MAX] = {0};
+    char mixer_ctl_name[128] = {0};
+    struct mixer_ctl *ctl = NULL;
 
     ALOGD("%s: enter", __func__);
     if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
@@ -8830,6 +8850,7 @@
     adev->perf_lock_opts_size = 2;
     adev->dsp_bit_width_enforce_mode = 0;
     adev->enable_hfp = false;
+    adev->use_old_pspd_mix_ctrl = false;
 
     /* Loads platform specific libraries dynamically */
     adev->platform = platform_init(adev);
@@ -9030,6 +9051,22 @@
     if (adev->device_cfg_params == NULL)
         ALOGE("%s: Memory allocation failed for Device config params", __func__);
 
+    /*
+     * Check if new PSPD matrix mixer control is supported. If not
+     * supported, then set flag so that old mixer ctrl is sent while
+     * sending pspd coefficients on older kernel version. Query mixer
+     * control for default pcm id and channel value one.
+     */
+    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+            "AudStr %d ChMixer Weight Ch %d", 0, 1);
+
+    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
+              __func__, mixer_ctl_name);
+        adev->use_old_pspd_mix_ctrl = true;
+    }
+
     ALOGV("%s: exit", __func__);
     return 0;
 }
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index db3474f..69c13e9 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -375,6 +375,7 @@
     bool prev_card_status_offline;
 
     error_log_t *error_log;
+    bool pspd_coeff_sent;
 };
 
 struct stream_in {
@@ -599,9 +600,9 @@
      * or other capabilities are present for the device corresponding to that usecase.
      */
     struct pcm_params *use_case_table[AUDIO_USECASE_MAX];
-
     struct listnode active_inputs_list;
     struct listnode active_outputs_list;
+    bool use_old_pspd_mix_ctrl;
 };
 
 int select_devices(struct audio_device *adev,
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 92b8bfb..279a2c2 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -3141,6 +3141,8 @@
         strdup("SLIM_0_RX Format");
     my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
         strdup("SLIM_0_RX SampleRate");
+    my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].channels_mixer_ctl =
+        strdup("SLIM_0_RX Channels");
 
     my_data->current_backend_cfg[DSD_NATIVE_BACKEND].bitwidth_mixer_ctl =
         strdup("SLIM_2_RX Format");
@@ -9886,4 +9888,3 @@
 {
     return -ENOSYS;
 }
-