Loading Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +21 −2 Original line number Diff line number Diff line Loading @@ -391,6 +391,18 @@ Required properties: group configuration. - pinctrl-x: Defines pinctrl state for each pin group. * msm-pcm-loopback-low-latency Required properties: - compatible : "qcom,msm-pcm-loopback" Optional properties - qcom,msm-pcm-loopback-low-latency : Flag indicating whether the device node is of type low latency. Example: qcom,msm-pcm { Loading @@ -404,6 +416,11 @@ Example: qcom,msm-pcm-low-latency; }; qcom,msm-pcm-loopback-low-latency { compatible = "qcom,msm-pcm-loopback"; qcom,msm-pcm-loopback-low-latency; }; qcom,msm-pcm-routing { compatible = "qcom,msm-pcm-routing"; }; Loading Loading @@ -1965,13 +1982,15 @@ Example: asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>, <&loopback>, <&compress>, <&hostless>, <&afe>, <&lsm>, <&routing>, <&compr>; <&afe>, <&lsm>, <&routing>, <&compr>, <&loopback1>; asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1", "msm-pcm-dsp.2", "msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback", "msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe", "msm-lsm-client", "msm-pcm-routing", "msm-compr-dsp"; "msm-pcm-routing", "msm-compr-dsp", "msm-pcm-loopback.1"; asoc-cpu = <&dai_pri_auxpcm>, <&dai_sec_auxpcm>, <&dai_hdmi>, <&dai_mi2s>, <&dai_mi2s_quat>, <&afe_pcm_rx>, <&afe_pcm_tx>, Loading include/sound/apr_audio-v2.h +132 −0 Original line number Diff line number Diff line Loading @@ -5185,6 +5185,138 @@ struct asm_stream_cmd_open_loopback_v2 { /* Reserved for future use. This field must be set to zero. */ } __packed; #define ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK 0x00010DBA /* Bitmask for the stream's Performance mode. */ #define ASM_BIT_MASK_STREAM_PERF_MODE_FLAG_IN_OPEN_TRANSCODE_LOOPBACK \ (0x70000000UL) /* Bit shift for the stream's Performance mode. */ #define ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_TRANSCODE_LOOPBACK 28 /* Bitmask for the decoder converter enable flag. */ #define ASM_BIT_MASK_DECODER_CONVERTER_FLAG (0x00000078UL) /* Shift value for the decoder converter enable flag. */ #define ASM_SHIFT_DECODER_CONVERTER_FLAG 3 /* Converter mode is None (Default). */ #define ASM_CONVERTER_MODE_NONE 0 /* Converter mode is DDP-to-DD. */ #define ASM_DDP_DD_CONVERTER_MODE 1 /* Identifies a special converter mode where source and sink formats * are the same but postprocessing must applied. Therefore, Decode * @rarrow Re-encode is necessary. */ #define ASM_POST_PROCESS_CONVERTER_MODE 2 struct asm_stream_cmd_open_transcode_loopback_t { struct apr_hdr hdr; u32 mode_flags; /* Mode Flags specifies the performance mode in which this stream * is to be opened. * Supported values{for bits 30 to 28}(stream_perf_mode flag) * * #ASM_LEGACY_STREAM_SESSION -- This mode ensures backward * compatibility to the original behavior * of ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK * * #ASM_LOW_LATENCY_STREAM_SESSION -- Opens a loopback session by using * shortened buffers in low latency POPP * - Recommendation: Do not enable high latency algorithms. They might * negate the benefits of opening a low latency stream, and they * might also suffer quality degradation from unexpected jitter. * - This Low Latency mode is supported only for PCM In and PCM Out * loopbacks. An error is returned if Low Latency mode is opened for * other transcode loopback modes. * - To configure this subfield, use * ASM_BIT_MASK_STREAM_PERF_MODE_FLAG_IN_OPEN_TRANSCODE_LOOPBACK and * ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_TRANSCODE_LOOPBACK. * * Supported values{for bits 6 to 3} (decoder-converter compatibility) * #ASM_CONVERTER_MODE_NONE (0x0) -- Default * #ASM_DDP_DD_CONVERTER_MODE (0x1) * #ASM_POST_PROCESS_CONVERTER_MODE (0x2) * 0x3-0xF -- Reserved for future use * - Use #ASM_BIT_MASK_DECODER_CONVERTER_FLAG and * ASM_SHIFT_DECODER_CONVERTER_FLAG to set this bit * All other bits are reserved; clients must set them to 0. */ u32 src_format_id; /* Specifies the media format of the input audio stream. * * Supported values * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2 * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 * - #ASM_MEDIA_FMT_DTS * - #ASM_MEDIA_FMT_EAC3_DEC * - #ASM_MEDIA_FMT_EAC3 * - #ASM_MEDIA_FMT_AC3_DEC * - #ASM_MEDIA_FMT_AC3 */ u32 sink_format_id; /* Specifies the media format of the output stream. * * Supported values * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2 * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 * - #ASM_MEDIA_FMT_DTS (not supported in Low Latency mode) * - #ASM_MEDIA_FMT_EAC3_DEC (not supported in Low Latency mode) * - #ASM_MEDIA_FMT_EAC3 (not supported in Low Latency mode) * - #ASM_MEDIA_FMT_AC3_DEC (not supported in Low Latency mode) * - #ASM_MEDIA_FMT_AC3 (not supported in Low Latency mode) */ u32 audproc_topo_id; /* Postprocessing topology ID, which specifies the topology (order of * processing) of postprocessing algorithms. * * Supported values * - #ASM_STREAM_POSTPROC_TOPO_ID_DEFAULT * - #ASM_STREAM_POSTPROC_TOPO_ID_PEAKMETER * - #ASM_STREAM_POSTPROC_TOPO_ID_MCH_PEAK_VOL * - #ASM_STREAM_POSTPROC_TOPO_ID_NONE * Topologies can be added through #ASM_CMD_ADD_TOPOLOGIES. * This field is ignored for the Converter mode, in which no * postprocessing is performed. */ u16 src_endpoint_type; /* Specifies the source endpoint that provides the input samples. * * Supported values * - 0 -- Tx device matrix or stream router (gateway to the hardware * ports) * - All other values are reserved * Clients must set this field to 0. Otherwise, an error is returned. */ u16 sink_endpoint_type; /* Specifies the sink endpoint type. * * Supported values * - 0 -- Rx device matrix or stream router (gateway to the hardware * ports) * - All other values are reserved * Clients must set this field to 0. Otherwise, an error is returned. */ u16 bits_per_sample; /* Number of bits per sample processed by the ASM modules. * Supported values 16, 24 */ u16 reserved; /* This field must be set to 0. */ } __packed; #define ASM_STREAM_CMD_CLOSE 0x00010BCD #define ASM_STREAM_CMD_FLUSH 0x00010BCE Loading sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c +29 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <sound/control.h> #include <sound/tlv.h> #include <asm/dma.h> #include <sound/q6audio-v2.h> #include "msm-pcm-routing-v2.h" Loading Loading @@ -65,6 +66,10 @@ static struct fe_dai_session_map session_map[LOOPBACK_SESSION_MAX] = { { {}, NULL}, }; struct msm_pcm_pdata { int perf_mode; }; static void stop_pcm(struct msm_pcm_loopback *pcm); static int msm_pcm_loopback_get_session(struct snd_soc_pcm_runtime *rtd, struct msm_pcm_loopback **pcm); Loading Loading @@ -233,6 +238,7 @@ static int msm_pcm_open(struct snd_pcm_substream *substream) struct msm_pcm_routing_evt event; struct asm_session_mtmx_strtr_param_window_v2_t asm_mtmx_strtr_window; uint32_t param_id; struct msm_pcm_pdata *pdata; ret = msm_pcm_loopback_get_session(rtd, &pcm); if (ret) Loading @@ -258,6 +264,15 @@ static int msm_pcm_open(struct snd_pcm_substream *substream) if (pcm->audio_client != NULL) stop_pcm(pcm); pdata = (struct msm_pcm_pdata *) dev_get_drvdata(rtd->platform->dev); if (!pdata) { dev_err(rtd->platform->dev, "%s: platform data not populated\n", __func__); mutex_unlock(&pcm->lock); return -EINVAL; } pcm->audio_client = q6asm_audio_client_alloc( (app_cb)msm_pcm_loopback_event_handler, pcm); if (!pcm->audio_client) { Loading @@ -267,7 +282,7 @@ static int msm_pcm_open(struct snd_pcm_substream *substream) return -ENOMEM; } pcm->session_id = pcm->audio_client->session; pcm->audio_client->perf_mode = false; pcm->audio_client->perf_mode = pdata->perf_mode; ret = q6asm_open_loopback_v2(pcm->audio_client, bits_per_sample); if (ret < 0) { Loading Loading @@ -694,10 +709,23 @@ static struct snd_soc_platform_driver msm_soc_platform = { static int msm_pcm_probe(struct platform_device *pdev) { struct msm_pcm_pdata *pdata; dev_dbg(&pdev->dev, "%s: dev name %s\n", __func__, dev_name(&pdev->dev)); pdata = kzalloc(sizeof(struct msm_pcm_pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; if (of_property_read_bool(pdev->dev.of_node, "qcom,msm-pcm-loopback-low-latency")) pdata->perf_mode = LOW_LATENCY_PCM_MODE; else pdata->perf_mode = LEGACY_PCM_MODE; dev_set_drvdata(&pdev->dev, pdata); return snd_soc_register_platform(&pdev->dev, &msm_soc_platform); } Loading sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +63 −0 Original line number Diff line number Diff line Loading @@ -4029,6 +4029,57 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = { msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mmul9_mixer_controls[] = { SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("VOC_REC_DL", MSM_BACKEND_DAI_INCALL_RECORD_RX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("SLIM_6_TX", MSM_BACKEND_DAI_SLIMBUS_6_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_1", MSM_BACKEND_DAI_TERT_TDM_TX_1, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_2", MSM_BACKEND_DAI_TERT_TDM_TX_2, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_3", MSM_BACKEND_DAI_TERT_TDM_TX_3, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_TX_1, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_TX_2, MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_TX_3, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = { SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX, MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer, Loading Loading @@ -7277,6 +7328,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { mmul6_mixer_controls, ARRAY_SIZE(mmul6_mixer_controls)), SND_SOC_DAPM_MIXER("MultiMedia8 Mixer", SND_SOC_NOPM, 0, 0, mmul8_mixer_controls, ARRAY_SIZE(mmul8_mixer_controls)), SND_SOC_DAPM_MIXER("MultiMedia9 Mixer", SND_SOC_NOPM, 0, 0, mmul9_mixer_controls, ARRAY_SIZE(mmul9_mixer_controls)), SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0, auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)), SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0, Loading Loading @@ -8002,6 +8055,15 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia8 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia8 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, {"MultiMedia9 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"MultiMedia9 Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"MultiMedia9 Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, {"MultiMedia9 Mixer", "TERT_TDM_TX_3", "TERT_TDM_TX_3"}, {"MultiMedia9 Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"}, {"MultiMedia9 Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, {"MultiMedia9 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia9 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, Loading Loading @@ -8100,6 +8162,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"MM_UL5", NULL, "MultiMedia5 Mixer"}, {"MM_UL6", NULL, "MultiMedia6 Mixer"}, {"MM_UL8", NULL, "MultiMedia8 Mixer"}, {"MM_UL9", NULL, "MultiMedia9 Mixer"}, {"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, Loading sound/soc/msm/qdsp6v2/q6asm.c +58 −20 Original line number Diff line number Diff line Loading @@ -1674,6 +1674,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) case ASM_STREAM_CMD_OPEN_PUSH_MODE_READ: case ASM_STREAM_CMD_OPEN_READWRITE_V2: case ASM_STREAM_CMD_OPEN_LOOPBACK_V2: case ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK: case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2: case ASM_STREAM_CMD_SET_ENCDEC_PARAM: case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE: Loading Loading @@ -2819,7 +2820,6 @@ int q6asm_open_read_write_v2(struct audio_client *ac, uint32_t rd_format, int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample) { int rc = 0x00; struct asm_stream_cmd_open_loopback_v2 open; if (ac == NULL) { pr_err("%s: APR handle NULL\n", __func__); Loading @@ -2831,6 +2831,42 @@ int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample) } pr_debug("%s: session[%d]\n", __func__, ac->session); if (ac->perf_mode == LOW_LATENCY_PCM_MODE) { struct asm_stream_cmd_open_transcode_loopback_t open; q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE); atomic_set(&ac->cmd_state, -1); open.hdr.opcode = ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK; open.mode_flags = 0; open.src_endpoint_type = 0; open.sink_endpoint_type = 0; open.src_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; open.sink_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; /* source endpoint : matrix */ open.audproc_topo_id = q6asm_get_asm_topology_cal(); ac->app_type = q6asm_get_asm_app_type_cal(); if (ac->perf_mode == LOW_LATENCY_PCM_MODE) open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION; else open.mode_flags |= ASM_LEGACY_STREAM_SESSION; ac->topology = open.audproc_topo_id; open.bits_per_sample = bits_per_sample; open.reserved = 0; pr_debug("%s: opening a transcode_loopback with mode_flags =[%d] session[%d]\n", __func__, open.mode_flags, ac->session); rc = apr_send_pkt(ac->apr, (uint32_t *) &open); if (rc < 0) { pr_err("%s: open failed op[0x%x]rc[%d]\n", __func__, open.hdr.opcode, rc); rc = -EINVAL; goto fail_cmd; } } else {/*if(ac->perf_mode == LEGACY_PCM_MODE)*/ struct asm_stream_cmd_open_loopback_v2 open; q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE); atomic_set(&ac->cmd_state, -1); open.hdr.opcode = ASM_STREAM_CMD_OPEN_LOOPBACK_V2; Loading @@ -2845,15 +2881,17 @@ int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample) ac->topology = open.postprocopo_id; open.bits_per_sample = bits_per_sample; open.reserved = 0; pr_debug("%s: opening a loopback_v2 with mode_flags =[%d] session[%d]\n", __func__, open.mode_flags, ac->session); rc = apr_send_pkt(ac->apr, (uint32_t *) &open); if (rc < 0) { pr_err("%s: open failed op[0x%x]rc[%d]\n", __func__, open.hdr.opcode, rc); pr_err("%s: open failed op[0x%x]rc[%d]\n", __func__, open.hdr.opcode, rc); rc = -EINVAL; goto fail_cmd; } } rc = wait_event_timeout(ac->cmd_wait, (atomic_read(&ac->cmd_state) >= 0), 5*HZ); if (!rc) { Loading Loading
Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +21 −2 Original line number Diff line number Diff line Loading @@ -391,6 +391,18 @@ Required properties: group configuration. - pinctrl-x: Defines pinctrl state for each pin group. * msm-pcm-loopback-low-latency Required properties: - compatible : "qcom,msm-pcm-loopback" Optional properties - qcom,msm-pcm-loopback-low-latency : Flag indicating whether the device node is of type low latency. Example: qcom,msm-pcm { Loading @@ -404,6 +416,11 @@ Example: qcom,msm-pcm-low-latency; }; qcom,msm-pcm-loopback-low-latency { compatible = "qcom,msm-pcm-loopback"; qcom,msm-pcm-loopback-low-latency; }; qcom,msm-pcm-routing { compatible = "qcom,msm-pcm-routing"; }; Loading Loading @@ -1965,13 +1982,15 @@ Example: asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>, <&loopback>, <&compress>, <&hostless>, <&afe>, <&lsm>, <&routing>, <&compr>; <&afe>, <&lsm>, <&routing>, <&compr>, <&loopback1>; asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1", "msm-pcm-dsp.2", "msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback", "msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe", "msm-lsm-client", "msm-pcm-routing", "msm-compr-dsp"; "msm-pcm-routing", "msm-compr-dsp", "msm-pcm-loopback.1"; asoc-cpu = <&dai_pri_auxpcm>, <&dai_sec_auxpcm>, <&dai_hdmi>, <&dai_mi2s>, <&dai_mi2s_quat>, <&afe_pcm_rx>, <&afe_pcm_tx>, Loading
include/sound/apr_audio-v2.h +132 −0 Original line number Diff line number Diff line Loading @@ -5185,6 +5185,138 @@ struct asm_stream_cmd_open_loopback_v2 { /* Reserved for future use. This field must be set to zero. */ } __packed; #define ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK 0x00010DBA /* Bitmask for the stream's Performance mode. */ #define ASM_BIT_MASK_STREAM_PERF_MODE_FLAG_IN_OPEN_TRANSCODE_LOOPBACK \ (0x70000000UL) /* Bit shift for the stream's Performance mode. */ #define ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_TRANSCODE_LOOPBACK 28 /* Bitmask for the decoder converter enable flag. */ #define ASM_BIT_MASK_DECODER_CONVERTER_FLAG (0x00000078UL) /* Shift value for the decoder converter enable flag. */ #define ASM_SHIFT_DECODER_CONVERTER_FLAG 3 /* Converter mode is None (Default). */ #define ASM_CONVERTER_MODE_NONE 0 /* Converter mode is DDP-to-DD. */ #define ASM_DDP_DD_CONVERTER_MODE 1 /* Identifies a special converter mode where source and sink formats * are the same but postprocessing must applied. Therefore, Decode * @rarrow Re-encode is necessary. */ #define ASM_POST_PROCESS_CONVERTER_MODE 2 struct asm_stream_cmd_open_transcode_loopback_t { struct apr_hdr hdr; u32 mode_flags; /* Mode Flags specifies the performance mode in which this stream * is to be opened. * Supported values{for bits 30 to 28}(stream_perf_mode flag) * * #ASM_LEGACY_STREAM_SESSION -- This mode ensures backward * compatibility to the original behavior * of ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK * * #ASM_LOW_LATENCY_STREAM_SESSION -- Opens a loopback session by using * shortened buffers in low latency POPP * - Recommendation: Do not enable high latency algorithms. They might * negate the benefits of opening a low latency stream, and they * might also suffer quality degradation from unexpected jitter. * - This Low Latency mode is supported only for PCM In and PCM Out * loopbacks. An error is returned if Low Latency mode is opened for * other transcode loopback modes. * - To configure this subfield, use * ASM_BIT_MASK_STREAM_PERF_MODE_FLAG_IN_OPEN_TRANSCODE_LOOPBACK and * ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_TRANSCODE_LOOPBACK. * * Supported values{for bits 6 to 3} (decoder-converter compatibility) * #ASM_CONVERTER_MODE_NONE (0x0) -- Default * #ASM_DDP_DD_CONVERTER_MODE (0x1) * #ASM_POST_PROCESS_CONVERTER_MODE (0x2) * 0x3-0xF -- Reserved for future use * - Use #ASM_BIT_MASK_DECODER_CONVERTER_FLAG and * ASM_SHIFT_DECODER_CONVERTER_FLAG to set this bit * All other bits are reserved; clients must set them to 0. */ u32 src_format_id; /* Specifies the media format of the input audio stream. * * Supported values * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2 * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 * - #ASM_MEDIA_FMT_DTS * - #ASM_MEDIA_FMT_EAC3_DEC * - #ASM_MEDIA_FMT_EAC3 * - #ASM_MEDIA_FMT_AC3_DEC * - #ASM_MEDIA_FMT_AC3 */ u32 sink_format_id; /* Specifies the media format of the output stream. * * Supported values * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2 * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 * - #ASM_MEDIA_FMT_DTS (not supported in Low Latency mode) * - #ASM_MEDIA_FMT_EAC3_DEC (not supported in Low Latency mode) * - #ASM_MEDIA_FMT_EAC3 (not supported in Low Latency mode) * - #ASM_MEDIA_FMT_AC3_DEC (not supported in Low Latency mode) * - #ASM_MEDIA_FMT_AC3 (not supported in Low Latency mode) */ u32 audproc_topo_id; /* Postprocessing topology ID, which specifies the topology (order of * processing) of postprocessing algorithms. * * Supported values * - #ASM_STREAM_POSTPROC_TOPO_ID_DEFAULT * - #ASM_STREAM_POSTPROC_TOPO_ID_PEAKMETER * - #ASM_STREAM_POSTPROC_TOPO_ID_MCH_PEAK_VOL * - #ASM_STREAM_POSTPROC_TOPO_ID_NONE * Topologies can be added through #ASM_CMD_ADD_TOPOLOGIES. * This field is ignored for the Converter mode, in which no * postprocessing is performed. */ u16 src_endpoint_type; /* Specifies the source endpoint that provides the input samples. * * Supported values * - 0 -- Tx device matrix or stream router (gateway to the hardware * ports) * - All other values are reserved * Clients must set this field to 0. Otherwise, an error is returned. */ u16 sink_endpoint_type; /* Specifies the sink endpoint type. * * Supported values * - 0 -- Rx device matrix or stream router (gateway to the hardware * ports) * - All other values are reserved * Clients must set this field to 0. Otherwise, an error is returned. */ u16 bits_per_sample; /* Number of bits per sample processed by the ASM modules. * Supported values 16, 24 */ u16 reserved; /* This field must be set to 0. */ } __packed; #define ASM_STREAM_CMD_CLOSE 0x00010BCD #define ASM_STREAM_CMD_FLUSH 0x00010BCE Loading
sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c +29 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <sound/control.h> #include <sound/tlv.h> #include <asm/dma.h> #include <sound/q6audio-v2.h> #include "msm-pcm-routing-v2.h" Loading Loading @@ -65,6 +66,10 @@ static struct fe_dai_session_map session_map[LOOPBACK_SESSION_MAX] = { { {}, NULL}, }; struct msm_pcm_pdata { int perf_mode; }; static void stop_pcm(struct msm_pcm_loopback *pcm); static int msm_pcm_loopback_get_session(struct snd_soc_pcm_runtime *rtd, struct msm_pcm_loopback **pcm); Loading Loading @@ -233,6 +238,7 @@ static int msm_pcm_open(struct snd_pcm_substream *substream) struct msm_pcm_routing_evt event; struct asm_session_mtmx_strtr_param_window_v2_t asm_mtmx_strtr_window; uint32_t param_id; struct msm_pcm_pdata *pdata; ret = msm_pcm_loopback_get_session(rtd, &pcm); if (ret) Loading @@ -258,6 +264,15 @@ static int msm_pcm_open(struct snd_pcm_substream *substream) if (pcm->audio_client != NULL) stop_pcm(pcm); pdata = (struct msm_pcm_pdata *) dev_get_drvdata(rtd->platform->dev); if (!pdata) { dev_err(rtd->platform->dev, "%s: platform data not populated\n", __func__); mutex_unlock(&pcm->lock); return -EINVAL; } pcm->audio_client = q6asm_audio_client_alloc( (app_cb)msm_pcm_loopback_event_handler, pcm); if (!pcm->audio_client) { Loading @@ -267,7 +282,7 @@ static int msm_pcm_open(struct snd_pcm_substream *substream) return -ENOMEM; } pcm->session_id = pcm->audio_client->session; pcm->audio_client->perf_mode = false; pcm->audio_client->perf_mode = pdata->perf_mode; ret = q6asm_open_loopback_v2(pcm->audio_client, bits_per_sample); if (ret < 0) { Loading Loading @@ -694,10 +709,23 @@ static struct snd_soc_platform_driver msm_soc_platform = { static int msm_pcm_probe(struct platform_device *pdev) { struct msm_pcm_pdata *pdata; dev_dbg(&pdev->dev, "%s: dev name %s\n", __func__, dev_name(&pdev->dev)); pdata = kzalloc(sizeof(struct msm_pcm_pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; if (of_property_read_bool(pdev->dev.of_node, "qcom,msm-pcm-loopback-low-latency")) pdata->perf_mode = LOW_LATENCY_PCM_MODE; else pdata->perf_mode = LEGACY_PCM_MODE; dev_set_drvdata(&pdev->dev, pdata); return snd_soc_register_platform(&pdev->dev, &msm_soc_platform); } Loading
sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +63 −0 Original line number Diff line number Diff line Loading @@ -4029,6 +4029,57 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = { msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mmul9_mixer_controls[] = { SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("VOC_REC_DL", MSM_BACKEND_DAI_INCALL_RECORD_RX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("SLIM_6_TX", MSM_BACKEND_DAI_SLIMBUS_6_TX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_1", MSM_BACKEND_DAI_TERT_TDM_TX_1, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_2", MSM_BACKEND_DAI_TERT_TDM_TX_2, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_3", MSM_BACKEND_DAI_TERT_TDM_TX_3, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_TX_1, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_TX_2, MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_TX_3, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = { SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX, MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer, Loading Loading @@ -7277,6 +7328,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { mmul6_mixer_controls, ARRAY_SIZE(mmul6_mixer_controls)), SND_SOC_DAPM_MIXER("MultiMedia8 Mixer", SND_SOC_NOPM, 0, 0, mmul8_mixer_controls, ARRAY_SIZE(mmul8_mixer_controls)), SND_SOC_DAPM_MIXER("MultiMedia9 Mixer", SND_SOC_NOPM, 0, 0, mmul9_mixer_controls, ARRAY_SIZE(mmul9_mixer_controls)), SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0, auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)), SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0, Loading Loading @@ -8002,6 +8055,15 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia8 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia8 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, {"MultiMedia9 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"MultiMedia9 Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"MultiMedia9 Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, {"MultiMedia9 Mixer", "TERT_TDM_TX_3", "TERT_TDM_TX_3"}, {"MultiMedia9 Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"}, {"MultiMedia9 Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, {"MultiMedia9 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia9 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, Loading Loading @@ -8100,6 +8162,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"MM_UL5", NULL, "MultiMedia5 Mixer"}, {"MM_UL6", NULL, "MultiMedia6 Mixer"}, {"MM_UL8", NULL, "MultiMedia8 Mixer"}, {"MM_UL9", NULL, "MultiMedia9 Mixer"}, {"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, Loading
sound/soc/msm/qdsp6v2/q6asm.c +58 −20 Original line number Diff line number Diff line Loading @@ -1674,6 +1674,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) case ASM_STREAM_CMD_OPEN_PUSH_MODE_READ: case ASM_STREAM_CMD_OPEN_READWRITE_V2: case ASM_STREAM_CMD_OPEN_LOOPBACK_V2: case ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK: case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2: case ASM_STREAM_CMD_SET_ENCDEC_PARAM: case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE: Loading Loading @@ -2819,7 +2820,6 @@ int q6asm_open_read_write_v2(struct audio_client *ac, uint32_t rd_format, int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample) { int rc = 0x00; struct asm_stream_cmd_open_loopback_v2 open; if (ac == NULL) { pr_err("%s: APR handle NULL\n", __func__); Loading @@ -2831,6 +2831,42 @@ int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample) } pr_debug("%s: session[%d]\n", __func__, ac->session); if (ac->perf_mode == LOW_LATENCY_PCM_MODE) { struct asm_stream_cmd_open_transcode_loopback_t open; q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE); atomic_set(&ac->cmd_state, -1); open.hdr.opcode = ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK; open.mode_flags = 0; open.src_endpoint_type = 0; open.sink_endpoint_type = 0; open.src_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; open.sink_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; /* source endpoint : matrix */ open.audproc_topo_id = q6asm_get_asm_topology_cal(); ac->app_type = q6asm_get_asm_app_type_cal(); if (ac->perf_mode == LOW_LATENCY_PCM_MODE) open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION; else open.mode_flags |= ASM_LEGACY_STREAM_SESSION; ac->topology = open.audproc_topo_id; open.bits_per_sample = bits_per_sample; open.reserved = 0; pr_debug("%s: opening a transcode_loopback with mode_flags =[%d] session[%d]\n", __func__, open.mode_flags, ac->session); rc = apr_send_pkt(ac->apr, (uint32_t *) &open); if (rc < 0) { pr_err("%s: open failed op[0x%x]rc[%d]\n", __func__, open.hdr.opcode, rc); rc = -EINVAL; goto fail_cmd; } } else {/*if(ac->perf_mode == LEGACY_PCM_MODE)*/ struct asm_stream_cmd_open_loopback_v2 open; q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE); atomic_set(&ac->cmd_state, -1); open.hdr.opcode = ASM_STREAM_CMD_OPEN_LOOPBACK_V2; Loading @@ -2845,15 +2881,17 @@ int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample) ac->topology = open.postprocopo_id; open.bits_per_sample = bits_per_sample; open.reserved = 0; pr_debug("%s: opening a loopback_v2 with mode_flags =[%d] session[%d]\n", __func__, open.mode_flags, ac->session); rc = apr_send_pkt(ac->apr, (uint32_t *) &open); if (rc < 0) { pr_err("%s: open failed op[0x%x]rc[%d]\n", __func__, open.hdr.opcode, rc); pr_err("%s: open failed op[0x%x]rc[%d]\n", __func__, open.hdr.opcode, rc); rc = -EINVAL; goto fail_cmd; } } rc = wait_event_timeout(ac->cmd_wait, (atomic_read(&ac->cmd_state) >= 0), 5*HZ); if (!rc) { Loading