audio: enable 5.1.2 channel mask configuration

- Support query of DP max channels.
- Enable 5.1.2 channel mask configuration.

Change-Id: I0fa6f50fc21189b539ec963f35bd627d4bd261da
diff --git a/hal/edid.c b/hal/edid.c
index f7259c7..175842f 100644
--- a/hal/edid.c
+++ b/hal/edid.c
@@ -388,7 +388,9 @@
 {
     if (!info)
         return;
-    if (info->channel_allocation < 0 || info->channel_allocation > 0x1f) {
+    if (((info->channel_allocation < 0) ||
+         (info->channel_allocation > 0x1f)) &&
+         (info->channel_allocation != 0x2f)) {
         ALOGE("Channel allocation out of supported range");
         return;
     }
@@ -631,6 +633,16 @@
         info->channel_map[6] = PCM_CHANNEL_FLC;
         info->channel_map[7] = PCM_CHANNEL_FRC;
         break;
+    case 0x2f:
+        info->channel_map[0] = PCM_CHANNEL_FL;
+        info->channel_map[1] = PCM_CHANNEL_FR;
+        info->channel_map[2] = PCM_CHANNEL_LFE;
+        info->channel_map[3] = PCM_CHANNEL_FC;
+        info->channel_map[4] = PCM_CHANNEL_LS;
+        info->channel_map[5] = PCM_CHANNEL_RS;
+        info->channel_map[6] = 0; // PCM_CHANNEL_TFL; but not defined by LPASS
+        info->channel_map[7] = 0; // PCM_CHANNEL_TFR; but not defined by LPASS
+        break;
     default:
         break;
     }
@@ -640,6 +652,180 @@
         , info->channel_map[6], info->channel_map[7]);
 }
 
+
+static void update_channel_mask(edid_audio_info* info)
+{
+    if (!info)
+        return;
+    if (((info->channel_allocation < 0) ||
+         (info->channel_allocation > 0x1f)) &&
+         (info->channel_allocation != 0x2f)) {
+        ALOGE("Channel allocation out of supported range");
+        return;
+    }
+    ALOGV("channel_allocation 0x%x", info->channel_allocation);
+    // Don't distinguish channel mask below?
+    // AUDIO_CHANNEL_OUT_5POINT1 and AUDIO_CHANNEL_OUT_5POINT1_SIDE
+    // AUDIO_CHANNEL_OUT_QUAD and AUDIO_CHANNEL_OUT_QUAD_SIDE
+    switch(info->channel_allocation) {
+    case 0x0:
+        info->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+        break;
+    case 0x1:
+        info->channel_mask = AUDIO_CHANNEL_OUT_2POINT1;
+        break;
+    case 0x2:
+        info->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_CENTER;
+        break;
+    case 0x3:
+        info->channel_mask = AUDIO_CHANNEL_OUT_2POINT1;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_CENTER;
+        break;
+    case 0x4:
+        info->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_BACK_CENTER;
+        break;
+    case 0x5:
+        info->channel_mask = AUDIO_CHANNEL_OUT_2POINT1;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_LOW_FREQUENCY;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_BACK_CENTER;
+        break;
+    case 0x6:
+        info->channel_mask = AUDIO_CHANNEL_OUT_SURROUND;
+        break;
+    case 0x7:
+        info->channel_mask = AUDIO_CHANNEL_OUT_SURROUND;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_LOW_FREQUENCY;
+        break;
+    case 0x8:
+        info->channel_mask = AUDIO_CHANNEL_OUT_QUAD;
+        break;
+    case 0x9:
+        info->channel_mask = AUDIO_CHANNEL_OUT_QUAD;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_LOW_FREQUENCY;
+        break;
+    case 0xa:
+        info->channel_mask = AUDIO_CHANNEL_OUT_PENTA;
+        break;
+    case 0xb:
+        info->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
+        break;
+    case 0xc:
+        info->channel_mask = AUDIO_CHANNEL_OUT_QUAD;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_BACK_CENTER;
+        break;
+    case 0xd:
+        info->channel_mask = AUDIO_CHANNEL_OUT_QUAD;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_LOW_FREQUENCY;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_BACK_CENTER;
+        break;
+    case 0xe:
+        info->channel_mask = AUDIO_CHANNEL_OUT_PENTA;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_BACK_CENTER;
+        break;
+    case 0xf:
+        info->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_BACK_CENTER;
+        break;
+    case 0x10:
+        info->channel_mask = AUDIO_CHANNEL_OUT_QUAD;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_SIDE_LEFT;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_SIDE_RIGHT;
+        break;
+    case 0x11:
+        info->channel_mask = AUDIO_CHANNEL_OUT_QUAD;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_LOW_FREQUENCY;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_SIDE_LEFT;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_SIDE_RIGHT;
+        break;
+    case 0x12:
+        info->channel_mask = AUDIO_CHANNEL_OUT_QUAD;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_SIDE_LEFT;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_SIDE_RIGHT;
+        break;
+    case 0x13:
+        info->channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
+        break;
+    case 0x14:
+        info->channel_mask = AUDIO_CHANNEL_OUT_FRONT_LEFT;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x15:
+        info->channel_mask = AUDIO_CHANNEL_OUT_2POINT1;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x16:
+        info->channel_mask = AUDIO_CHANNEL_OUT_FRONT_LEFT;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x17:
+        info->channel_mask = AUDIO_CHANNEL_OUT_2POINT1;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x18:
+        info->channel_mask = AUDIO_CHANNEL_OUT_FRONT_LEFT;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_BACK_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x19:
+        info->channel_mask = AUDIO_CHANNEL_OUT_2POINT1;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_BACK_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x1a:
+        info->channel_mask = AUDIO_CHANNEL_OUT_SURROUND;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x1b:
+        info->channel_mask = AUDIO_CHANNEL_OUT_SURROUND;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_LOW_FREQUENCY;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x1c:
+        info->channel_mask = AUDIO_CHANNEL_OUT_QUAD;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x1d:
+        info->channel_mask = AUDIO_CHANNEL_OUT_QUAD;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_LOW_FREQUENCY;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x1e:
+        info->channel_mask = AUDIO_CHANNEL_OUT_PENTA;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x1f:
+        info->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
+        info->channel_mask |= AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
+        break;
+    case 0x2f:
+        info->channel_mask = AUDIO_CHANNEL_OUT_5POINT1POINT2;
+        break;
+    default:
+        break;
+    }
+    ALOGD("%s channel mask updated to %d", __func__, info->channel_mask);
+}
+
 static void dump_edid_data(edid_audio_info *info)
 {
 
@@ -715,6 +901,7 @@
     update_channel_map(info);
     update_channel_allocation(info);
     update_channel_map_lpass(info);
+    update_channel_mask(info);
 
     for (i=0; i<info->audio_blocks; i++) {
         ALOGV("AUDIO DESC BLOCK # %d\n",i);
diff --git a/hal/edid.h b/hal/edid.h
index da5c592..f97d0e3 100644
--- a/hal/edid.h
+++ b/hal/edid.h
@@ -57,6 +57,24 @@
 #define PCM_CHANNEL_FRC  14  /* Front right of center.                        */
 #define PCM_CHANNEL_RLC  15  /* Rear left of center.                          */
 #define PCM_CHANNEL_RRC  16  /* Rear right of center.                         */
+#define PCM_CHANNEL_LFE2 17  /* Rear right of center.                         */
+#define PCM_CHANNEL_SL   18  /* Side left channel.                            */
+#define PCM_CHANNEL_SR   19  /* Side right channel                            */
+#define PCM_CHANNEL_TFL  20  /* Top front left channel.                       */
+#define PCM_CHANNEL_TFR  21  /* Top front right channel.                      */
+#define PCM_CHANNEL_TC   22  /* Top center channel.                           */
+#define PCM_CHANNEL_TBL  23  /* Top back left channel.                        */
+#define PCM_CHANNEL_TBR  24  /* Top back right channel.                       */
+#define PCM_CHANNEL_TSL  25  /* Top side left channel                         */
+#define PCM_CHANNEL_TSR  26  /* Top side right channel.                       */
+#define PCM_CHANNEL_TBC  27  /* Top back center channel.                      */
+#define PCM_CHANNEL_BFC  28  /* Bottom front center channel.                  */
+#define PCM_CHANNEL_BFL  29  /* Bottom front left channel.                    */
+#define PCM_CHANNEL_BFR  30  /* Bottom front right channel.                   */
+#define PCM_CHANNEL_LW   31  /* Left wide channel.                            */
+#define PCM_CHANNEL_RW   32  /* Right wide channel.                           */
+#define PCM_CHANNEL_LSD  33  /* Left side direct channel.                     */
+#define PCM_CHANNEL_RSD  34  /* Right side direct channel.                    */
 
 #define MAX_HDMI_CHANNEL_CNT 8
 
@@ -90,6 +108,7 @@
     edid_audio_block_info audio_blocks_array[MAX_EDID_BLOCKS];
     char channel_map[MAX_CHANNELS_SUPPORTED];
     int  channel_allocation;
+    unsigned int  channel_mask;
 } edid_audio_info;
 
 #ifdef HDMI_EDID
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index e5e8c19..1d80893 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -5759,7 +5759,7 @@
         my_data->current_backend_cfg[backend_idx].channels = channels;
 
         if (backend_idx == HDMI_RX_BACKEND)
-            platform_set_edid_channels_configuration(adev->platform, channels);
+            platform_set_edid_channels_configuration(adev->platform, channels, HDMI_RX_BACKEND);
 
         ALOGD("%s:becf: afe: %s set to %s", __func__,
                my_data->current_backend_cfg[backend_idx].channels_mixer_ctl, channel_cnt_str);
@@ -7091,7 +7091,7 @@
     return false;
 }
 
-int platform_set_edid_channels_configuration(void *platform, int channels) {
+int platform_set_edid_channels_configuration(void *platform, int channels, int backend_idx __unused) {
 
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 7f33967..71090ca 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1155,7 +1155,8 @@
 }
 
 int platform_set_edid_channels_configuration(void *platform __unused,
-                                             int channels __unused)
+                                             int channels __unused,
+                                             int backend_idx __unused)
 {
     return 0;
 }
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 02bac29..269c648 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -141,6 +141,7 @@
  * device for voice usecase
  */
 #define AUDIO_PARAMETER_KEY_DP_FOR_VOICE_USECASE "dp_for_voice"
+#define AUDIO_PARAMETER_KEY_DP_CHANNEL_MASK "dp_channel_mask"
 
 #define EVENT_EXTERNAL_SPK_1 "qc_ext_spk_1"
 #define EVENT_EXTERNAL_SPK_2 "qc_ext_spk_2"
@@ -5247,6 +5248,16 @@
         str_parms_add_str(reply, AUDIO_PARAMETER_KEY_DP_FOR_VOICE_USECASE, value);
     }
 
+    ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_DP_CHANNEL_MASK,
+                            value, sizeof(value));
+    if (ret >= 0) {
+        ret = platform_get_edid_info(platform);
+        edid_audio_info *info = (edid_audio_info *)my_data->edid_info;
+        if (ret == 0 && info != NULL) {
+            str_parms_add_int(reply, AUDIO_PARAMETER_KEY_DP_CHANNEL_MASK, info->channel_mask);
+        }
+    }
+
     /* Handle audio calibration keys */
     get_audiocal(platform, query, reply);
     native_audio_get_params(query, reply, value, sizeof(value));
@@ -5716,8 +5727,9 @@
         mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
         my_data->current_backend_cfg[backend_idx].channels = channels;
 
-        if (backend_idx == HDMI_RX_BACKEND)
-            platform_set_edid_channels_configuration(adev->platform, channels);
+        if ((backend_idx == HDMI_RX_BACKEND) ||
+                (backend_idx == DISP_PORT_RX_BACKEND))
+            platform_set_edid_channels_configuration(adev->platform, channels, backend_idx);
 
         ALOGD("%s:becf: afe: %s set to %s ", __func__,
                my_data->current_backend_cfg[backend_idx].channels_mixer_ctl,
@@ -6710,8 +6722,13 @@
                 channel_map[3] = PCM_CHANNEL_LFE;
                 channel_map[4] = PCM_CHANNEL_LB;
                 channel_map[5] = PCM_CHANNEL_RB;
-                channel_map[6] = PCM_CHANNEL_LS;
-                channel_map[7] = PCM_CHANNEL_RS;
+                if (channel_mask == AUDIO_CHANNEL_OUT_5POINT1POINT2) {
+                    channel_map[6] = PCM_CHANNEL_TFL;
+                    channel_map[7] = PCM_CHANNEL_TFR;
+                } else {
+                    channel_map[6] = PCM_CHANNEL_LS;
+                    channel_map[7] = PCM_CHANNEL_RS;
+                }
                 break;
             default:
                 ALOGE("unsupported channels %d for setting channel map", channels);
@@ -7038,7 +7055,7 @@
     return 0;
 }
 
-int platform_set_edid_channels_configuration(void *platform, int channels) {
+int platform_set_edid_channels_configuration(void *platform, int channels, int backend_idx) {
 
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
@@ -7048,13 +7065,18 @@
     char default_channelMap[MAX_CHANNELS_SUPPORTED] = {0};
     struct audio_device_config_param *adev_device_cfg_ptr = adev->device_cfg_params;
 
+    if ((backend_idx != HDMI_RX_BACKEND) &&
+            (backend_idx != DISP_PORT_RX_BACKEND)) {
+        ALOGE("%s: Invalid backend idx %d", __func__, backend_idx);
+        return -EINVAL;
+    }
+
     ret = platform_get_edid_info(platform);
     info = (edid_audio_info *)my_data->edid_info;
-    adev_device_cfg_ptr += HDMI_RX_BACKEND;
+    adev_device_cfg_ptr += backend_idx;
     if(ret == 0 && info != NULL) {
         if (channels > 2) {
-
-            ALOGV("%s:able to get HDMI sink capabilities multi channel playback",
+            ALOGV("%s:able to get HDMI/DP sink capabilities multi channel playback",
                    __func__);
             for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
                 if (info->audio_blocks_array[i].format_id == LPCM &&
diff --git a/hal/platform_api.h b/hal/platform_api.h
index d487525..53a4888 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -213,7 +213,7 @@
                                        int snd_id,
                                        snd_device_t snd_device,
                                        struct mix_matrix_params mm_params);
-int platform_set_edid_channels_configuration(void *platform, int channels);
+int platform_set_edid_channels_configuration(void *platform, int channels, int backend_idx);
 unsigned char platform_map_to_edid_format(int format);
 bool platform_is_edid_supported_format(void *platform, int format);
 bool platform_is_edid_supported_sample_rate(void *platform, int sample_rate);