OSDN Git Service

ASoC: msm: Upgrade AFE TDM Driver to support 32 Channels
authorCong Tang <congt@codeaurora.org>
Thu, 23 Nov 2017 03:28:19 +0000 (11:28 +0800)
committerCong Tang <congt@codeaurora.org>
Mon, 5 Mar 2018 10:30:08 +0000 (18:30 +0800)
HLOS update AFE TDM driver to support 32 channels playback
and capture since ADSP firmware has already support on this.
Only TDM interface would support 32 channels ability.

Change-Id: I22c23a4b8b43fcbe9950b5df5e8a8faa374efce4
Signed-off-by: Cong Tang <congt@codeaurora.org>
include/sound/apr_audio-v2.h
include/sound/q6afe-v2.h
sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
sound/soc/msm/qdsp6v2/q6afe.c

index cd85a4a..65316c6 100644 (file)
@@ -132,6 +132,9 @@ struct module_instance_info {
 /* Begin service specific definitions and structures */
 
 #define ADSP_ADM_VERSION    0x00070000
+#define ADSP_ASM_API_VERSION_V2   2
+#define ADSP_ADM_API_VERSION_V3  3
+#define ADSP_AFE_API_VERSION_V3  3
 
 #define ADM_CMD_SHARED_MEM_MAP_REGIONS    0x00010322
 #define ADM_CMDRSP_SHARED_MEM_MAP_REGIONS 0x00010323
index b1c3b0b..5031e62 100644 (file)
@@ -368,4 +368,5 @@ int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
 void afe_set_routing_callback(routing_cb);
 int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
                u16 port);
+int afe_get_svc_version(uint32_t service_id);
 #endif /* __Q6AFE_V2_H__ */
index 292b3d0..27daa3a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,7 @@
 #include <sound/q6afe-v2.h>
 #include <sound/msm-dai-q6-v2.h>
 #include <sound/pcm_params.h>
+#include <sound/q6core.h>
 
 #define MSM_DAI_PRI_AUXPCM_DT_DEV_ID 1
 #define MSM_DAI_SEC_AUXPCM_DT_DEV_ID 2
@@ -6160,6 +6161,9 @@ static int msm_dai_q6_tdm_set_tdm_slot(struct snd_soc_dai *dai,
        case 16:
                cap_mask = 0xFFFF;
                break;
+       case 32:
+               cap_mask = 0xFFFFFFFF;
+               break;
        default:
                dev_err(dai->dev, "%s: invalid slots %d\n",
                        __func__, slots);
@@ -6292,6 +6296,8 @@ static int msm_dai_q6_tdm_set_channel_map(struct snd_soc_dai *dai,
                dev_get_drvdata(dai->dev);
        struct afe_param_id_slot_mapping_cfg *slot_mapping =
                &dai_data->port_cfg.slot_mapping;
+       struct afe_param_id_slot_mapping_cfg_v2 *slot_mapping_v2 =
+               &dai_data->port_cfg.slot_mapping_v2;
        int i = 0;
 
        dev_dbg(dai->dev, "%s: dai id = 0x%x\n", __func__, dai->id);
@@ -6329,23 +6335,49 @@ static int msm_dai_q6_tdm_set_channel_map(struct snd_soc_dai *dai,
        case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
        case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
        case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
-               if (!rx_slot) {
-                       dev_err(dai->dev, "%s: rx slot not found\n", __func__);
-                       return -EINVAL;
-               }
-               if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
-                       dev_err(dai->dev, "%s: invalid rx num %d\n", __func__,
-                               rx_num);
-                       return -EINVAL;
-               }
+               if (afe_get_svc_version(APR_SVC_AFE) >=
+                               ADSP_AFE_API_VERSION_V3) {
+                       if (!rx_slot) {
+                               dev_err(dai->dev, "%s: rx slot not found\n",
+                                               __func__);
+                               return -EINVAL;
+                       }
+                       if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT_V2) {
+                               dev_err(dai->dev, "%s: invalid rx num %d\n",
+                                               __func__,
+                                       rx_num);
+                               return -EINVAL;
+                       }
 
-               for (i = 0; i < rx_num; i++)
-                       slot_mapping->offset[i] = rx_slot[i];
-               for (i = rx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++)
-                       slot_mapping->offset[i] =
-                               AFE_SLOT_MAPPING_OFFSET_INVALID;
+                       for (i = 0; i < rx_num; i++)
+                               slot_mapping_v2->offset[i] = rx_slot[i];
+                       for (i = rx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT_V2;
+                                       i++)
+                               slot_mapping_v2->offset[i] =
+                                       AFE_SLOT_MAPPING_OFFSET_INVALID;
 
-               slot_mapping->num_channel = rx_num;
+                       slot_mapping_v2->num_channel = rx_num;
+               } else {
+                       if (!rx_slot) {
+                               dev_err(dai->dev, "%s: rx slot not found\n",
+                                               __func__);
+                               return -EINVAL;
+                       }
+                       if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
+                               dev_err(dai->dev, "%s: invalid rx num %d\n",
+                                               __func__,
+                                       rx_num);
+                               return -EINVAL;
+                       }
+
+                       for (i = 0; i < rx_num; i++)
+                               slot_mapping->offset[i] = rx_slot[i];
+                       for (i = rx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++)
+                               slot_mapping->offset[i] =
+                                       AFE_SLOT_MAPPING_OFFSET_INVALID;
+
+                       slot_mapping->num_channel = rx_num;
+               }
                break;
        case AFE_PORT_ID_PRIMARY_TDM_TX:
        case AFE_PORT_ID_PRIMARY_TDM_TX_1:
@@ -6379,23 +6411,49 @@ static int msm_dai_q6_tdm_set_channel_map(struct snd_soc_dai *dai,
        case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
        case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
        case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
-               if (!tx_slot) {
-                       dev_err(dai->dev, "%s: tx slot not found\n", __func__);
-                       return -EINVAL;
-               }
-               if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
-                       dev_err(dai->dev, "%s: invalid tx num %d\n", __func__,
-                               tx_num);
-                       return -EINVAL;
-               }
+               if (afe_get_svc_version(APR_SVC_AFE) >=
+                               ADSP_AFE_API_VERSION_V3) {
+                       if (!tx_slot) {
+                               dev_err(dai->dev, "%s: tx slot not found\n",
+                                               __func__);
+                               return -EINVAL;
+                       }
+                       if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT_V2) {
+                               dev_err(dai->dev, "%s: invalid tx num %d\n",
+                                               __func__,
+                                       tx_num);
+                               return -EINVAL;
+                       }
+
+                       for (i = 0; i < tx_num; i++)
+                               slot_mapping_v2->offset[i] = tx_slot[i];
+                       for (i = tx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT_V2;
+                                       i++)
+                               slot_mapping_v2->offset[i] =
+                                       AFE_SLOT_MAPPING_OFFSET_INVALID;
 
-               for (i = 0; i < tx_num; i++)
-                       slot_mapping->offset[i] = tx_slot[i];
-               for (i = tx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++)
-                       slot_mapping->offset[i] =
-                               AFE_SLOT_MAPPING_OFFSET_INVALID;
+                       slot_mapping_v2->num_channel = tx_num;
+               } else {
+                       if (!tx_slot) {
+                               dev_err(dai->dev, "%s: tx slot not found\n",
+                                               __func__);
+                               return -EINVAL;
+                       }
+                       if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
+                               dev_err(dai->dev, "%s: invalid tx num %d\n",
+                                               __func__,
+                                       tx_num);
+                               return -EINVAL;
+                       }
 
-               slot_mapping->num_channel = tx_num;
+                       for (i = 0; i < tx_num; i++)
+                               slot_mapping->offset[i] = tx_slot[i];
+                       for (i = tx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++)
+                               slot_mapping->offset[i] =
+                                       AFE_SLOT_MAPPING_OFFSET_INVALID;
+
+                       slot_mapping->num_channel = tx_num;
+               }
                break;
        default:
                dev_err(dai->dev, "%s: invalid dai id 0x%x\n",
@@ -6419,6 +6477,8 @@ static int msm_dai_q6_tdm_hw_params(struct snd_pcm_substream *substream,
                &dai_data->port_cfg.tdm;
        struct afe_param_id_slot_mapping_cfg *slot_mapping =
                &dai_data->port_cfg.slot_mapping;
+       struct afe_param_id_slot_mapping_cfg_v2 *slot_mapping_v2 =
+               &dai_data->port_cfg.slot_mapping_v2;
        struct afe_param_id_custom_tdm_header_cfg *custom_tdm_header =
                &dai_data->port_cfg.custom_tdm_header;
 
@@ -6426,7 +6486,7 @@ static int msm_dai_q6_tdm_hw_params(struct snd_pcm_substream *substream,
                __func__, dev_name(dai->dev));
 
        if ((params_channels(params) == 0) ||
-               (params_channels(params) > 8)) {
+               (params_channels(params) > 32)) {
                dev_err(dai->dev, "%s: invalid param channels %d\n",
                        __func__, params_channels(params));
                return -EINVAL;
@@ -6514,32 +6574,88 @@ static int msm_dai_q6_tdm_hw_params(struct snd_pcm_substream *substream,
                tdm->ctrl_data_out_enable,
                tdm->ctrl_invert_sync_pulse,
                tdm->ctrl_sync_data_delay);
+       if (afe_get_svc_version(APR_SVC_AFE) >=
+                       ADSP_AFE_API_VERSION_V3) {
+               /*
+                * update slot mapping v2 config param
+                * NOTE: channels/rate/bitwidth are per stream property
+                */
+               slot_mapping_v2->bitwidth = dai_data->bitwidth;
 
-       /*
-        * update slot mapping config param
-        * NOTE: channels/rate/bitwidth are per stream property
-        */
-       slot_mapping->bitwidth = dai_data->bitwidth;
-
-       pr_debug("%s: SLOT MAPPING:\n"
+       pr_debug("%s: SLOT MAPPING_V2:\n"
                "num_channel=%d bitwidth=%d data_align=0x%x\n",
                __func__,
-               slot_mapping->num_channel,
-               slot_mapping->bitwidth,
-               slot_mapping->data_align_type);
-       pr_debug("%s: SLOT MAPPING:\n"
+               slot_mapping_v2->num_channel,
+               slot_mapping_v2->bitwidth,
+               slot_mapping_v2->data_align_type);
+       pr_debug("%s: SLOT MAPPING V2:\n"
                "offset[0]=0x%x offset[1]=0x%x offset[2]=0x%x offset[3]=0x%x\n"
-               "offset[4]=0x%x offset[5]=0x%x offset[6]=0x%x offset[7]=0x%x\n",
+               "offset[4]=0x%x offset[5]=0x%x offset[6]=0x%x offset[7]=0x%x\n"
+               "offset[8]=0x%x offset[9]=0x%x offset[10]=0x%x offset[11]=0x%x\n"
+               "offset[12]=0x%x offset[13]=0x%x offset[14]=0x%x offset[15]=0x%x\n"
+               "offset[16]=0x%x offset[17]=0x%x offset[18]=0x%x offset[19]=0x%x\n"
+               "offset[20]=0x%x offset[21]=0x%x offset[22]=0x%x offset[23]=0x%x\n"
+               "offset[24]=0x%x offset[25]=0x%x offset[26]=0x%x offset[27]=0x%x\n"
+               "offset[28]=0x%x offset[29]=0x%x offset[30]=0x%x offset[31]=0x%x\n",
                __func__,
-               slot_mapping->offset[0],
-               slot_mapping->offset[1],
-               slot_mapping->offset[2],
-               slot_mapping->offset[3],
-               slot_mapping->offset[4],
-               slot_mapping->offset[5],
-               slot_mapping->offset[6],
-               slot_mapping->offset[7]);
+               slot_mapping_v2->offset[0],
+               slot_mapping_v2->offset[1],
+               slot_mapping_v2->offset[2],
+               slot_mapping_v2->offset[3],
+               slot_mapping_v2->offset[4],
+               slot_mapping_v2->offset[5],
+               slot_mapping_v2->offset[6],
+               slot_mapping_v2->offset[7],
+               slot_mapping_v2->offset[8],
+               slot_mapping_v2->offset[9],
+               slot_mapping_v2->offset[10],
+               slot_mapping_v2->offset[11],
+               slot_mapping_v2->offset[12],
+               slot_mapping_v2->offset[13],
+               slot_mapping_v2->offset[14],
+               slot_mapping_v2->offset[15],
+               slot_mapping_v2->offset[16],
+               slot_mapping_v2->offset[17],
+               slot_mapping_v2->offset[18],
+               slot_mapping_v2->offset[19],
+               slot_mapping_v2->offset[20],
+               slot_mapping_v2->offset[21],
+               slot_mapping_v2->offset[22],
+               slot_mapping_v2->offset[23],
+               slot_mapping_v2->offset[24],
+               slot_mapping_v2->offset[25],
+               slot_mapping_v2->offset[26],
+               slot_mapping_v2->offset[27],
+               slot_mapping_v2->offset[28],
+               slot_mapping_v2->offset[29],
+               slot_mapping_v2->offset[30],
+               slot_mapping_v2->offset[31]);
+       } else {
+               /*
+                * update slot mapping config param
+                * NOTE: channels/rate/bitwidth are per stream property
+                */
+               slot_mapping->bitwidth = dai_data->bitwidth;
 
+               pr_debug("%s: SLOT MAPPING:\n"
+                       "num_channel=%d bitwidth=%d data_align=0x%x\n",
+                       __func__,
+                       slot_mapping->num_channel,
+                       slot_mapping->bitwidth,
+                       slot_mapping->data_align_type);
+               pr_debug("%s: SLOT MAPPING:\n"
+                       "offset[0]=0x%x offset[1]=0x%x offset[2]=0x%x offset[3]=0x%x\n"
+                       "offset[4]=0x%x offset[5]=0x%x offset[6]=0x%x offset[7]=0x%x\n",
+                       __func__,
+                       slot_mapping->offset[0],
+                       slot_mapping->offset[1],
+                       slot_mapping->offset[2],
+                       slot_mapping->offset[3],
+                       slot_mapping->offset[4],
+                       slot_mapping->offset[5],
+                       slot_mapping->offset[6],
+                       slot_mapping->offset[7]);
+       }
        /*
         * update custom header config param
         * NOTE: channels/rate/bitwidth are per playback stream property.
@@ -8121,6 +8237,9 @@ static int msm_dai_q6_tdm_dev_probe(struct platform_device *pdev)
        dai_data->port_cfg.slot_mapping.minor_version =
                AFE_API_VERSION_SLOT_MAPPING_CONFIG;
 
+       dai_data->port_cfg.slot_mapping_v2.minor_version =
+               AFE_API_VERSION_SLOT_MAPPING_CONFIG_V2;
+
        /* CUSTOM TDM HEADER CFG */
        custom_tdm_header = &dai_data->port_cfg.custom_tdm_header;
        if (of_find_property(pdev->dev.of_node,
index 9658020..352ea92 100644 (file)
@@ -28,6 +28,7 @@
 #include <sound/audio_cal_utils.h>
 #include <sound/adsp_err.h>
 #include <linux/qdsp6v2/apr_tal.h>
+#include <sound/q6core.h>
 
 #define WAKELOCK_TIMEOUT       5000
 enum {
@@ -144,6 +145,39 @@ static int afe_get_cal_hw_delay(int32_t path,
                                struct audio_cal_hw_delay_entry *entry);
 static int remap_cal_data(struct cal_block_data *cal_block, int cal_index);
 
+int afe_get_svc_version(uint32_t service_id)
+{
+       int ret = 0;
+       static int afe_cached_version;
+       size_t ver_size;
+       struct avcs_fwk_ver_info *ver_info = NULL;
+
+       if (service_id == AVCS_SERVICE_ID_ALL) {
+               pr_err("%s: Invalid service id: %d", __func__,
+                                       AVCS_SERVICE_ID_ALL);
+               return -EINVAL;
+       }
+
+       if (afe_cached_version != 0)
+               return afe_cached_version;
+
+       ver_size = sizeof(struct avcs_get_fwk_version) +
+                       sizeof(struct avs_svc_api_info);
+       ver_info = kzalloc(ver_size, GFP_KERNEL);
+       if (ver_info == NULL)
+               return -ENOMEM;
+
+       ret = q6core_get_service_version(service_id, ver_info, ver_size);
+       if (ret < 0)
+               goto done;
+
+       ret = ver_info->services[0].api_version;
+       afe_cached_version = ret;
+done:
+       kfree(ver_info);
+       return ret;
+}
+
 int afe_get_topology(int port_id)
 {
        int topology;
@@ -2447,6 +2481,36 @@ fail_cmd:
        return ret;
 }
 
+static int afe_send_slot_mapping_cfg_v2(
+       struct afe_param_id_slot_mapping_cfg_v2 *slot_mapping_cfg,
+       u16 port_id)
+{
+       struct param_hdr_v3 param_hdr = {0};
+       int ret = 0;
+
+       if (!slot_mapping_cfg) {
+               pr_err("%s: Error, no configuration data\n", __func__);
+               return -EINVAL;
+       }
+
+       pr_debug("%s: port id: 0x%x\n", __func__, port_id);
+
+       param_hdr.module_id = AFE_MODULE_TDM;
+       param_hdr.instance_id = INSTANCE_ID_0;
+       param_hdr.param_id = AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG;
+       param_hdr.param_size = sizeof(struct afe_param_id_slot_mapping_cfg_v2);
+
+       ret = q6afe_pack_and_set_param_in_band(port_id,
+                                              q6audio_get_port_index(port_id),
+                                              param_hdr,
+                                              (u8 *) slot_mapping_cfg);
+       if (ret < 0)
+               pr_err("%s: AFE send slot mapping for port 0x%x failed ret = %d\n",
+                               __func__, port_id, ret);
+       return ret;
+}
+
+
 int afe_send_slot_mapping_cfg(
        struct afe_param_id_slot_mapping_cfg *slot_mapping_cfg,
        u16 port_id)
@@ -2603,8 +2667,15 @@ int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
        }
        /* slot mapping is not need if there is only one group */
        if (num_groups > 1) {
-               ret = afe_send_slot_mapping_cfg(&tdm_port->slot_mapping,
-                                               port_id);
+               if (afe_get_svc_version(APR_SVC_AFE) >=
+                               ADSP_AFE_API_VERSION_V3)
+                       ret = afe_send_slot_mapping_cfg_v2(
+                                       &tdm_port->slot_mapping_v2,
+                                       port_id);
+               else
+                       ret = afe_send_slot_mapping_cfg(
+                                       &tdm_port->slot_mapping,
+                                       port_id);
                if (ret < 0) {
                        pr_err("%s: afe send failed %d\n", __func__, ret);
                        goto fail_cmd;