]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ASoC: qcom: qdsp6: Introduce USB AFE port to q6dsp
authorWesley Cheng <quic_wcheng@quicinc.com>
Wed, 9 Apr 2025 19:47:55 +0000 (12:47 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 11 Apr 2025 11:02:32 +0000 (13:02 +0200)
The QC ADSP is able to support USB playback endpoints, so that the main
application processor can be placed into lower CPU power modes.  This adds
the required AFE port configurations and port start command to start an
audio session.

Specifically, the QC ADSP can support all potential endpoints that are
exposed by the audio data interface.  This includes isochronous data
endpoints, in either synchronous mode or asynchronous mode. In the latter
case both implicit or explicit feedback endpoints are supported.  The size
of audio samples sent per USB frame (microframe) will be adjusted based on
information received on the feedback endpoint.

Some pre-requisites are needed before issuing the AFE port start command,
such as setting the USB AFE dev_token.  This carries information about the
available USB SND cards and PCM devices that have been discovered on the
USB bus.  The dev_token field is used by the audio DSP to notify the USB
offload driver of which card and PCM index to enable playback on.

Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
Acked-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20250409194804.3773260-23-quic_wcheng@quicinc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
sound/soc/qcom/qdsp6/q6afe-dai.c
sound/soc/qcom/qdsp6/q6afe.c
sound/soc/qcom/qdsp6/q6afe.h
sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c
sound/soc/qcom/qdsp6/q6dsp-lpass-ports.h
sound/soc/qcom/qdsp6/q6routing.c

index 7d9628cda87534dd3cad8bcb1e0faa7b8e5dd770..0f47aadaabe171bcab42de260609b832557f74f5 100644 (file)
@@ -92,6 +92,39 @@ static int q6hdmi_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int q6afe_usb_hw_params(struct snd_pcm_substream *substream,
+                              struct snd_pcm_hw_params *params,
+                              struct snd_soc_dai *dai)
+{
+       struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
+       int channels = params_channels(params);
+       int rate = params_rate(params);
+       struct q6afe_usb_cfg *usb = &dai_data->port_config[dai->id].usb_audio;
+
+       usb->sample_rate = rate;
+       usb->num_channels = channels;
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_U16_LE:
+       case SNDRV_PCM_FORMAT_S16_LE:
+               usb->bit_width = 16;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+       case SNDRV_PCM_FORMAT_S24_3LE:
+               usb->bit_width = 24;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               usb->bit_width = 32;
+               break;
+       default:
+               dev_err(dai->dev, "%s: invalid format %d\n",
+                       __func__, params_format(params));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int q6i2s_hw_params(struct snd_pcm_substream *substream,
                           struct snd_pcm_hw_params *params,
                           struct snd_soc_dai *dai)
@@ -394,6 +427,10 @@ static int q6afe_dai_prepare(struct snd_pcm_substream *substream,
                q6afe_cdc_dma_port_prepare(dai_data->port[dai->id],
                                           &dai_data->port_config[dai->id].dma_cfg);
                break;
+       case USB_RX:
+               q6afe_usb_port_prepare(dai_data->port[dai->id],
+                                      &dai_data->port_config[dai->id].usb_audio);
+               break;
        default:
                return -EINVAL;
        }
@@ -622,6 +659,9 @@ static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {
        {"TX_CODEC_DMA_TX_5", NULL, "TX_CODEC_DMA_TX_5 Capture"},
        {"RX_CODEC_DMA_RX_6 Playback", NULL, "RX_CODEC_DMA_RX_6"},
        {"RX_CODEC_DMA_RX_7 Playback", NULL, "RX_CODEC_DMA_RX_7"},
+
+       /* USB playback AFE port receives data for playback, hence use the RX port */
+       {"USB Playback", NULL, "USB_RX"},
 };
 
 static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
@@ -649,6 +689,23 @@ static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
        return 0;
 }
 
+static const struct snd_soc_dai_ops q6afe_usb_ops = {
+       .probe          = msm_dai_q6_dai_probe,
+       .prepare        = q6afe_dai_prepare,
+       .hw_params      = q6afe_usb_hw_params,
+       /*
+        * Shutdown callback required to stop the USB AFE port, which is enabled
+        * by the prepare() stage.  This stops the audio traffic on the USB AFE
+        * port on the Q6DSP.
+        */
+       .shutdown       = q6afe_dai_shutdown,
+       /*
+        * Startup callback not needed, as AFE port start command passes the PCM
+        * parameters within the AFE command, which is provided by the PCM core
+        * during the prepare() stage.
+        */
+};
+
 static const struct snd_soc_dai_ops q6hdmi_ops = {
        .probe                  = msm_dai_q6_dai_probe,
        .remove                 = msm_dai_q6_dai_remove,
@@ -947,6 +1004,8 @@ static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = {
                0, SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_7", "NULL",
                0, SND_SOC_NOPM, 0, 0),
+
+       SND_SOC_DAPM_AIF_IN("USB_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
 };
 
 static const struct snd_soc_component_driver q6afe_dai_component = {
@@ -1061,6 +1120,7 @@ static int q6afe_dai_dev_probe(struct platform_device *pdev)
        cfg.q6i2s_ops = &q6i2s_ops;
        cfg.q6tdm_ops = &q6tdm_ops;
        cfg.q6dma_ops = &q6dma_ops;
+       cfg.q6usb_ops = &q6afe_usb_ops;
        dais = q6dsp_audio_ports_set_config(dev, &cfg, &num_dais);
 
        return devm_snd_soc_register_component(dev, &q6afe_dai_component, dais, num_dais);
index ef7557be5d66479ac9a3837edc16d36a0b2cbff7..fef0135588f3feb93227447baa0f8d050f083e48 100644 (file)
@@ -35,6 +35,8 @@
 #define AFE_MODULE_TDM                 0x0001028A
 
 #define AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG 0x00010235
+#define AFE_PARAM_ID_USB_AUDIO_DEV_PARAMS    0x000102A5
+#define AFE_PARAM_ID_USB_AUDIO_DEV_LPCM_FMT 0x000102AA
 
 #define AFE_PARAM_ID_LPAIF_CLK_CONFIG  0x00010238
 #define AFE_PARAM_ID_INT_DIGITAL_CDC_CLK_CONFIG        0x00010239
@@ -44,6 +46,7 @@
 #define AFE_PARAM_ID_TDM_CONFIG        0x0001029D
 #define AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG  0x00010297
 #define AFE_PARAM_ID_CODEC_DMA_CONFIG  0x000102B8
+#define AFE_PARAM_ID_USB_AUDIO_CONFIG    0x000102A4
 #define AFE_CMD_REMOTE_LPASS_CORE_HW_VOTE_REQUEST      0x000100f4
 #define AFE_CMD_RSP_REMOTE_LPASS_CORE_HW_VOTE_REQUEST   0x000100f5
 #define AFE_CMD_REMOTE_LPASS_CORE_HW_DEVOTE_REQUEST    0x000100f6
 #define AFE_PORT_CONFIG_I2S_WS_SRC_INTERNAL    0x1
 #define AFE_LINEAR_PCM_DATA                            0x0
 
+#define AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG 0x1
 
 /* Port IDs */
 #define AFE_API_VERSION_HDMI_CONFIG    0x1
 #define AFE_PORT_ID_MULTICHAN_HDMI_RX  0x100E
 #define AFE_PORT_ID_HDMI_OVER_DP_RX    0x6020
 
+/* USB AFE port */
+#define AFE_PORT_ID_USB_RX                       0x7000
+
 #define AFE_API_VERSION_SLIMBUS_CONFIG 0x1
 /* Clock set API version */
 #define AFE_API_VERSION_CLOCK_SET 1
@@ -513,12 +520,96 @@ struct afe_param_id_cdc_dma_cfg {
        u16     active_channels_mask;
 } __packed;
 
+struct afe_param_id_usb_cfg {
+/* Minor version used for tracking USB audio device configuration.
+ * Supported values: AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG
+ */
+       u32     cfg_minor_version;
+/* Sampling rate of the port.
+ * Supported values:
+ * - AFE_PORT_SAMPLE_RATE_8K
+ * - AFE_PORT_SAMPLE_RATE_11025
+ * - AFE_PORT_SAMPLE_RATE_12K
+ * - AFE_PORT_SAMPLE_RATE_16K
+ * - AFE_PORT_SAMPLE_RATE_22050
+ * - AFE_PORT_SAMPLE_RATE_24K
+ * - AFE_PORT_SAMPLE_RATE_32K
+ * - AFE_PORT_SAMPLE_RATE_44P1K
+ * - AFE_PORT_SAMPLE_RATE_48K
+ * - AFE_PORT_SAMPLE_RATE_96K
+ * - AFE_PORT_SAMPLE_RATE_192K
+ */
+       u32     sample_rate;
+/* Bit width of the sample.
+ * Supported values: 16, 24
+ */
+       u16     bit_width;
+/* Number of channels.
+ * Supported values: 1 and 2
+ */
+       u16     num_channels;
+/* Data format supported by the USB. The supported value is
+ * 0 (#AFE_USB_AUDIO_DATA_FORMAT_LINEAR_PCM).
+ */
+       u16     data_format;
+/* this field must be 0 */
+       u16     reserved;
+/* device token of actual end USB audio device */
+       u32     dev_token;
+/* endianness of this interface */
+       u32     endian;
+/* service interval */
+       u32     service_interval;
+} __packed;
+
+/**
+ * struct afe_param_id_usb_audio_dev_params
+ * @cfg_minor_version: Minor version used for tracking USB audio device
+ * configuration.
+ * Supported values:
+ *     AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG
+ * @dev_token: device token of actual end USB audio device
+ **/
+struct afe_param_id_usb_audio_dev_params {
+       u32     cfg_minor_version;
+       u32     dev_token;
+} __packed;
+
+/**
+ * struct afe_param_id_usb_audio_dev_lpcm_fmt
+ * @cfg_minor_version: Minor version used for tracking USB audio device
+ * configuration.
+ * Supported values:
+ *     AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG
+ * @endian: endianness of this interface
+ **/
+struct afe_param_id_usb_audio_dev_lpcm_fmt {
+       u32     cfg_minor_version;
+       u32     endian;
+} __packed;
+
+#define AFE_PARAM_ID_USB_AUDIO_SVC_INTERVAL     0x000102B7
+
+/**
+ * struct afe_param_id_usb_audio_svc_interval
+ * @cfg_minor_version: Minor version used for tracking USB audio device
+ * configuration.
+ * Supported values:
+ *     AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG
+ * @svc_interval: service interval
+ **/
+struct afe_param_id_usb_audio_svc_interval {
+       u32     cfg_minor_version;
+       u32     svc_interval;
+} __packed;
+
 union afe_port_config {
        struct afe_param_id_hdmi_multi_chan_audio_cfg hdmi_multi_ch;
        struct afe_param_id_slimbus_cfg           slim_cfg;
        struct afe_param_id_i2s_cfg     i2s_cfg;
        struct afe_param_id_tdm_cfg     tdm_cfg;
        struct afe_param_id_cdc_dma_cfg dma_cfg;
+       struct afe_param_id_usb_cfg usb_cfg;
 } __packed;
 
 
@@ -833,6 +924,7 @@ static struct afe_port_map port_maps[AFE_PORT_MAX] = {
                                RX_CODEC_DMA_RX_6, 1, 1},
        [RX_CODEC_DMA_RX_7] = { AFE_PORT_ID_RX_CODEC_DMA_RX_7,
                                RX_CODEC_DMA_RX_7, 1, 1},
+       [USB_RX] = { AFE_PORT_ID_USB_RX, USB_RX, 1, 1},
 };
 
 static void q6afe_port_free(struct kref *ref)
@@ -1290,6 +1382,99 @@ void q6afe_tdm_port_prepare(struct q6afe_port *port,
 }
 EXPORT_SYMBOL_GPL(q6afe_tdm_port_prepare);
 
+/**
+ * afe_port_send_usb_dev_param() - Send USB dev token
+ *
+ * @port: Instance of afe port
+ * @cardidx: USB SND card index to reference
+ * @pcmidx: USB SND PCM device index to reference
+ *
+ * The USB dev token carries information about which USB SND card instance and
+ * PCM device to execute the offload on.  This information is carried through
+ * to the stream enable QMI request, which is handled by the offload class
+ * driver.  The information is parsed to determine which USB device to query
+ * the required resources for.
+ */
+int afe_port_send_usb_dev_param(struct q6afe_port *port, int cardidx, int pcmidx)
+{
+       struct afe_param_id_usb_audio_dev_params usb_dev;
+       int ret;
+
+       memset(&usb_dev, 0, sizeof(usb_dev));
+
+       usb_dev.cfg_minor_version = AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG;
+       usb_dev.dev_token = (cardidx << 16) | (pcmidx << 8);
+       ret = q6afe_port_set_param_v2(port, &usb_dev,
+                                     AFE_PARAM_ID_USB_AUDIO_DEV_PARAMS,
+                                     AFE_MODULE_AUDIO_DEV_INTERFACE,
+                                     sizeof(usb_dev));
+       if (ret)
+               dev_err(port->afe->dev, "%s: AFE device param cmd failed %d\n",
+                       __func__, ret);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(afe_port_send_usb_dev_param);
+
+static int afe_port_send_usb_params(struct q6afe_port *port, struct q6afe_usb_cfg *cfg)
+{
+       union afe_port_config *pcfg = &port->port_cfg;
+       struct afe_param_id_usb_audio_dev_lpcm_fmt lpcm_fmt;
+       struct afe_param_id_usb_audio_svc_interval svc_int;
+       int ret;
+
+       if (!pcfg) {
+               dev_err(port->afe->dev, "%s: Error, no configuration data\n", __func__);
+               return -EINVAL;
+       }
+
+       memset(&lpcm_fmt, 0, sizeof(lpcm_fmt));
+       memset(&svc_int, 0, sizeof(svc_int));
+
+       lpcm_fmt.cfg_minor_version = AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG;
+       lpcm_fmt.endian = pcfg->usb_cfg.endian;
+       ret = q6afe_port_set_param_v2(port, &lpcm_fmt,
+                                     AFE_PARAM_ID_USB_AUDIO_DEV_LPCM_FMT,
+                                     AFE_MODULE_AUDIO_DEV_INTERFACE, sizeof(lpcm_fmt));
+       if (ret) {
+               dev_err(port->afe->dev, "%s: AFE device param cmd LPCM_FMT failed %d\n",
+                       __func__, ret);
+               return ret;
+       }
+
+       svc_int.cfg_minor_version = AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG;
+       svc_int.svc_interval = pcfg->usb_cfg.service_interval;
+       ret = q6afe_port_set_param_v2(port, &svc_int,
+                                     AFE_PARAM_ID_USB_AUDIO_SVC_INTERVAL,
+                                     AFE_MODULE_AUDIO_DEV_INTERFACE, sizeof(svc_int));
+       if (ret)
+               dev_err(port->afe->dev, "%s: AFE device param cmd svc_interval failed %d\n",
+                       __func__, ret);
+
+       return ret;
+}
+
+/**
+ * q6afe_usb_port_prepare() - Prepare usb afe port.
+ *
+ * @port: Instance of afe port
+ * @cfg: USB configuration for the afe port
+ *
+ */
+void q6afe_usb_port_prepare(struct q6afe_port *port,
+                           struct q6afe_usb_cfg *cfg)
+{
+       union afe_port_config *pcfg = &port->port_cfg;
+
+       pcfg->usb_cfg.cfg_minor_version = AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG;
+       pcfg->usb_cfg.sample_rate = cfg->sample_rate;
+       pcfg->usb_cfg.num_channels = cfg->num_channels;
+       pcfg->usb_cfg.bit_width = cfg->bit_width;
+
+       afe_port_send_usb_params(port, cfg);
+}
+EXPORT_SYMBOL_GPL(q6afe_usb_port_prepare);
+
 /**
  * q6afe_hdmi_port_prepare() - Prepare hdmi afe port.
  *
@@ -1612,7 +1797,10 @@ struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id)
                break;
        case AFE_PORT_ID_WSA_CODEC_DMA_RX_0 ... AFE_PORT_ID_RX_CODEC_DMA_RX_7:
                cfg_type = AFE_PARAM_ID_CODEC_DMA_CONFIG;
-       break;
+               break;
+       case AFE_PORT_ID_USB_RX:
+               cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG;
+               break;
        default:
                dev_err(dev, "Invalid port id 0x%x\n", port_id);
                return ERR_PTR(-EINVAL);
index 65d0676075e1361c9481319a682e51b544874b61..a29abe4ce436804cf79752264219e56503618e31 100644 (file)
@@ -3,7 +3,7 @@
 #ifndef __Q6AFE_H__
 #define __Q6AFE_H__
 
-#define AFE_PORT_MAX           129
+#define AFE_PORT_MAX           137
 
 #define MSM_AFE_PORT_TYPE_RX 0
 #define MSM_AFE_PORT_TYPE_TX 1
@@ -203,6 +203,36 @@ struct q6afe_cdc_dma_cfg {
        u16     active_channels_mask;
 };
 
+/**
+ * struct q6afe_usb_cfg
+ * @cfg_minor_version: Minor version used for tracking USB audio device
+ * configuration.
+ * Supported values:
+ *     AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG
+ * @sample_rate: Sampling rate of the port
+ *    Supported values:
+ *      AFE_PORT_SAMPLE_RATE_8K
+ *      AFE_PORT_SAMPLE_RATE_11025
+ *      AFE_PORT_SAMPLE_RATE_12K
+ *      AFE_PORT_SAMPLE_RATE_16K
+ *      AFE_PORT_SAMPLE_RATE_22050
+ *      AFE_PORT_SAMPLE_RATE_24K
+ *      AFE_PORT_SAMPLE_RATE_32K
+ *      AFE_PORT_SAMPLE_RATE_44P1K
+ *      AFE_PORT_SAMPLE_RATE_48K
+ *      AFE_PORT_SAMPLE_RATE_96K
+ *      AFE_PORT_SAMPLE_RATE_192K
+ * @bit_width: Bit width of the sample.
+ *    Supported values: 16, 24
+ * @num_channels: Number of channels
+ *    Supported values: 1, 2
+ **/
+struct q6afe_usb_cfg {
+       u32     cfg_minor_version;
+       u32     sample_rate;
+       u16     bit_width;
+       u16     num_channels;
+};
 
 struct q6afe_port_config {
        struct q6afe_hdmi_cfg hdmi;
@@ -210,6 +240,7 @@ struct q6afe_port_config {
        struct q6afe_i2s_cfg i2s_cfg;
        struct q6afe_tdm_cfg tdm;
        struct q6afe_cdc_dma_cfg dma_cfg;
+       struct q6afe_usb_cfg usb_audio;
 };
 
 struct q6afe_port;
@@ -219,6 +250,8 @@ int q6afe_port_start(struct q6afe_port *port);
 int q6afe_port_stop(struct q6afe_port *port);
 void q6afe_port_put(struct q6afe_port *port);
 int q6afe_get_port_id(int index);
+void q6afe_usb_port_prepare(struct q6afe_port *port,
+                           struct q6afe_usb_cfg *cfg);
 void q6afe_hdmi_port_prepare(struct q6afe_port *port,
                            struct q6afe_hdmi_cfg *cfg);
 void q6afe_slim_port_prepare(struct q6afe_port *port,
@@ -228,6 +261,7 @@ void q6afe_tdm_port_prepare(struct q6afe_port *port, struct q6afe_tdm_cfg *cfg);
 void q6afe_cdc_dma_port_prepare(struct q6afe_port *port,
                                struct q6afe_cdc_dma_cfg *cfg);
 
+int afe_port_send_usb_dev_param(struct q6afe_port *port, int cardidx, int pcmidx);
 int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id,
                          int clk_src, int clk_root,
                          unsigned int freq, int dir);
index 4919001de08b3eec87098c5280e3ee0702952b15..4eed54b071a5c48bc20675b7efd05cd1e1f5c105 100644 (file)
        }
 
 static struct snd_soc_dai_driver q6dsp_audio_fe_dais[] = {
+       {
+               .playback = {
+                       .stream_name = "USB Playback",
+                       .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
+                                       SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
+                                       SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+                                       SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+                                       SNDRV_PCM_RATE_192000,
+                       .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
+                                       SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE |
+                                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |
+                                       SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE,
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rate_min = 8000,
+                       .rate_max = 192000,
+               },
+               .id = USB_RX,
+               .name = "USB_RX",
+       },
        {
                .playback = {
                        .stream_name = "HDMI Playback",
@@ -624,6 +644,9 @@ struct snd_soc_dai_driver *q6dsp_audio_ports_set_config(struct device *dev,
                case WSA_CODEC_DMA_RX_0 ... RX_CODEC_DMA_RX_7:
                        q6dsp_audio_fe_dais[i].ops = cfg->q6dma_ops;
                        break;
+               case USB_RX:
+                       q6dsp_audio_fe_dais[i].ops = cfg->q6usb_ops;
+                       break;
                default:
                        break;
                }
index 7f052c8a125777c557c30df210e4fdb1fa5723e9..d8dde6dd0aca7192769b246bdc42d26f776a075e 100644 (file)
@@ -11,6 +11,7 @@ struct q6dsp_audio_port_dai_driver_config {
        const struct snd_soc_dai_ops *q6i2s_ops;
        const struct snd_soc_dai_ops *q6tdm_ops;
        const struct snd_soc_dai_ops *q6dma_ops;
+       const struct snd_soc_dai_ops *q6usb_ops;
 };
 
 struct snd_soc_dai_driver *q6dsp_audio_ports_set_config(struct device *dev,
index 90228699ba7d490ae5abee3811b43f3131974eb4..f49243daa517f2f4d42e5e30e94ac1581118fd54 100644 (file)
@@ -435,6 +435,7 @@ static struct session_data *get_session_from_id(struct msm_routing_data *data,
 
        return NULL;
 }
+
 /**
  * q6routing_stream_close() - Deregister a stream
  *
@@ -515,6 +516,9 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol,
        return 1;
 }
 
+static const struct snd_kcontrol_new usb_rx_mixer_controls[] = {
+       Q6ROUTING_RX_MIXERS(USB_RX) };
+
 static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
        Q6ROUTING_RX_MIXERS(HDMI_RX) };
 
@@ -933,6 +937,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
        SND_SOC_DAPM_MIXER("RX_CODEC_DMA_RX_7 Audio Mixer", SND_SOC_NOPM, 0, 0,
                rx_codec_dma_rx_7_mixer_controls,
                ARRAY_SIZE(rx_codec_dma_rx_7_mixer_controls)),
+       SND_SOC_DAPM_MIXER("USB_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+                          usb_rx_mixer_controls,
+                          ARRAY_SIZE(usb_rx_mixer_controls)),
        SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
                mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
        SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
@@ -949,7 +956,6 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
                mmul7_mixer_controls, ARRAY_SIZE(mmul7_mixer_controls)),
        SND_SOC_DAPM_MIXER("MultiMedia8 Mixer", SND_SOC_NOPM, 0, 0,
                mmul8_mixer_controls, ARRAY_SIZE(mmul8_mixer_controls)),
-
 };
 
 static const struct snd_soc_dapm_route intercon[] = {
@@ -1026,6 +1032,7 @@ static const struct snd_soc_dapm_route intercon[] = {
        Q6ROUTING_RX_DAPM_ROUTE("RX_CODEC_DMA_RX_5 Audio Mixer", "RX_CODEC_DMA_RX_5"),
        Q6ROUTING_RX_DAPM_ROUTE("RX_CODEC_DMA_RX_6 Audio Mixer", "RX_CODEC_DMA_RX_6"),
        Q6ROUTING_RX_DAPM_ROUTE("RX_CODEC_DMA_RX_7 Audio Mixer", "RX_CODEC_DMA_RX_7"),
+       Q6ROUTING_RX_DAPM_ROUTE("USB_RX Audio Mixer", "USB_RX"),
        Q6ROUTING_TX_DAPM_ROUTE("MultiMedia1 Mixer"),
        Q6ROUTING_TX_DAPM_ROUTE("MultiMedia2 Mixer"),
        Q6ROUTING_TX_DAPM_ROUTE("MultiMedia3 Mixer"),