]> git.alsa-project.org Git - alsa-utils.git/commitdiff
topology: nhlt: intel: support more device types and directions
authorBrent Lu <brent.lu@intel.com>
Tue, 25 Jul 2023 14:58:17 +0000 (22:58 +0800)
committerJaroslav Kysela <perex@perex.cz>
Tue, 1 Aug 2023 07:43:17 +0000 (09:43 +0200)
In current NHLT table the device type of all SSP endpoints are set to
BT Sideband(0) instead of SSP Analog Codec(4) and the direction only
supports Render(0) and Capture(1).

Here we introduce two new quirks from topology to set the device type
correctly and support two more directions: Render with loopback(2)
and Feedback for render(3) for speakers with echo reference or IV
sense feedback.

Fixes: https://github.com/alsa-project/alsa-utils/pull/226
Signed-off-by: Brent Lu <brent.lu@intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
topology/nhlt/intel/ssp-nhlt.c
topology/nhlt/intel/ssp/ssp-internal.h
topology/nhlt/intel/ssp/ssp-process.c
topology/nhlt/intel/ssp/ssp-process.h

index f1e4fc3c0f85e1a56bd8b1be2f4890cf7f66b2f4..7a1a013ff482f62d3f44ecb9141a417ce537bce3 100644 (file)
@@ -456,6 +456,8 @@ int nhlt_ssp_get_ep(struct intel_nhlt_params *nhlt, struct endpoint_descriptor *
        uint32_t bits_per_sample;
        uint32_t virtualbus_id;
        uint32_t formats_count;
+       uint32_t device_type;
+       uint32_t direction = dir;
        uint8_t *ep_target;
        size_t blob_size;
        int ret;
@@ -471,7 +473,8 @@ int nhlt_ssp_get_ep(struct intel_nhlt_params *nhlt, struct endpoint_descriptor *
         * vendor_blob sizeof(vendor_blob)
         */
 
-       ret = ssp_get_params(nhlt, dai_index, &virtualbus_id, &formats_count);
+       ret = ssp_get_params(nhlt, dai_index, &virtualbus_id, &formats_count,
+                            &device_type, &direction);
        if (ret < 0) {
                fprintf(stderr, "nhlt_ssp_get_ep: ssp_get_params failed\n");
                return ret;
@@ -483,9 +486,9 @@ int nhlt_ssp_get_ep(struct intel_nhlt_params *nhlt, struct endpoint_descriptor *
        ep.device_id = NHLT_DEVICE_ID_INTEL_I2S_TDM;
        ep.revision_id = 0;
        ep.subsystem_id = 0;
-       ep.device_type = 0;
+       ep.device_type = device_type;
 
-       ep.direction = dir;
+       ep.direction = direction;
        /* ssp device index */
        ep.virtualbus_id = virtualbus_id;
        /* ssp config */
index ab6a8753d01a7fcc78757471431c760789533a0d..23a8489b6b5a129d85be82fc8770dee140204b9a 100644 (file)
@@ -353,6 +353,8 @@ struct intel_ssp_params {
 #define SSP_INTEL_QUIRK_PSPSTWFDFD     (1 << 4)
 #define SSP_INTEL_QUIRK_PSPSRWFDFD     (1 << 5)
 #define SSP_INTEL_QUIRK_LBM            (1 << 6)
+#define SSP_INTEL_QUIRK_BT_SIDEBAND    (1 << 7)
+#define SSP_INTEL_QUIRK_RENDER_FEEDBACK        (1 << 8)
 
 #define SSP_INTEL_FRAME_PULSE_WIDTH_MAX                38
 #define SSP_INTEL_SLOT_PADDING_MAX             31
index e5ff26c887ee04c74f303b889dde213561445bee..237eaec06df871fe77f75b6950e56d8eb0149f39 100644 (file)
@@ -768,7 +768,7 @@ int ssp_get_dir(struct intel_nhlt_params *nhlt, int dai_index, uint8_t *dir)
 }
 
 int ssp_get_params(struct intel_nhlt_params *nhlt, int dai_index, uint32_t *virtualbus_id,
-                  uint32_t *formats_count)
+                  uint32_t *formats_count, uint32_t *device_type, uint32_t *direction)
 {
        struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
 
@@ -777,6 +777,16 @@ int ssp_get_params(struct intel_nhlt_params *nhlt, int dai_index, uint32_t *virt
 
        *virtualbus_id = ssp->ssp_dai_index[dai_index];
        *formats_count = ssp->ssp_hw_config_count[dai_index];
+       if (ssp->ssp_prm[dai_index].quirks & SSP_INTEL_QUIRK_BT_SIDEBAND)
+               *device_type = NHLT_DEVICE_TYPE_SSP_BT_SIDEBAND;
+       else
+               *device_type = NHLT_DEVICE_TYPE_SSP_ANALOG;
+       if (ssp->ssp_prm[dai_index].quirks & SSP_INTEL_QUIRK_RENDER_FEEDBACK) {
+               if (*direction == NHLT_ENDPOINT_DIRECTION_RENDER)
+                       *direction = NHLT_ENDPOINT_DIRECTION_RENDER_WITH_LOOPBACK;
+               else if (*direction == NHLT_ENDPOINT_DIRECTION_CAPTURE)
+                       *direction = NHLT_ENDPOINT_DIRECTION_FEEDBACK_FOR_RENDER;
+       }
 
        return 0;
 }
@@ -874,6 +884,8 @@ int ssp_set_params(struct intel_nhlt_params *nhlt, const char *dir, int dai_inde
                   int version)
 {
        struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
+       char delim[] = ",";
+       char *buf, *token = NULL;
 
        if (!ssp)
                return -EINVAL;
@@ -903,10 +915,34 @@ int ssp_set_params(struct intel_nhlt_params *nhlt, const char *dir, int dai_inde
                ssp->ssp_prm[ssp->ssp_count].tdm_per_slot_padding_flag = 1;
        else
                ssp->ssp_prm[ssp->ssp_count].tdm_per_slot_padding_flag = 0;
-       if (quirks && !strcmp(quirks, "lbm_mode"))
-               ssp->ssp_prm[ssp->ssp_count].quirks = 64; /* 1 << 6 */
-       else
-               ssp->ssp_prm[ssp->ssp_count].quirks = 0;
+
+       ssp->ssp_prm[ssp->ssp_count].quirks = 0;
+
+       if (quirks) {
+               buf = strdup(quirks);
+               if (!buf)
+                       return -ENOMEM;
+
+               token = strtok(buf, delim);
+
+               while (token) {
+                       if (!strcmp(token, "lbm_mode"))
+                               ssp->ssp_prm[ssp->ssp_count].quirks |= SSP_INTEL_QUIRK_LBM;
+                       else if (!strcmp(token, "bt_sideband"))
+                               ssp->ssp_prm[ssp->ssp_count].quirks |= SSP_INTEL_QUIRK_BT_SIDEBAND;
+                       else if (!strcmp(token, "render_feedback")) {
+                               if (!strcmp(dir, "duplex"))
+                                       ssp->ssp_prm[ssp->ssp_count].quirks |= SSP_INTEL_QUIRK_RENDER_FEEDBACK;
+                       } else {
+                               fprintf(stderr, "ssp_set_params(): unknown quirk %s\n", token);
+                               return -EINVAL;
+                       }
+
+                       token = strtok(NULL, delim);
+               }
+
+               free(buf);
+       }
 
        /* reset hw config count for this ssp instance */
        ssp->ssp_hw_config_count[ssp->ssp_count] = 0;
index 6830fa1885b314448d490a76117146c8539b5f76..ea80482af0e7c422ebb8693eecfc3691b0fcd7f8 100644 (file)
@@ -55,7 +55,7 @@ int ssp_link_set_params(struct intel_nhlt_params *nhlt, int clock_source);
 int ssp_calculate(struct intel_nhlt_params *nhlt);
 /* get spec parameters when building the nhlt endpoint */
 int ssp_get_params(struct intel_nhlt_params *nhlt, int dai_index, uint32_t *virtualbus_id,
-                  uint32_t *formats_count);
+                  uint32_t *formats_count, uint32_t *device_type, uint32_t *direction);
 int ssp_get_hw_params(struct intel_nhlt_params *nhlt, int dai_index, int hw_index,
                      uint32_t *sample_rate, uint16_t *channel_count, uint32_t *bits_per_sample);
 int ssp_get_dir(struct intel_nhlt_params *nhlt, int dai_index, uint8_t *dir);