summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2020-09-10 13:29:30 +0100
committerMark Brown <broonie@kernel.org>2020-09-10 13:29:30 +0100
commita0822e3eeaab3c8d99569bd4af1b5b0aab9b7ce3 (patch)
treeb6a7586e526a870ef89e05bcb8970320562f88fa /sound
parent36760d44be7eb2b65e302ee038ded89654abc0ca (diff)
parent1fdbcfa9fdee6f9cc00129f0f5ed0ff29cfef646 (diff)
Merge series "ASoC: q6dsp: Add support to Codec Ports." from Srinivas Kandagatla <srinivas.kandagatla@linaro.org>:
LPASS IP on SoCs like SM8250 has Digital Codec part integrated into it. This ports are exposed in Q6DSP as Codec ports. This patchset adds support to those q6afe ports along with q6routing and q6afe-dai. This patchset has been tested along with other patches on Qualcomm Robotics RB5 Platform with Soundwire and WSA8815 Codec. Thanks, srini Srinivas Kandagatla (8): ASoC: q6dsp: q6afe: add support to Codec DMA ports ASoC: q6dsp: q6routing: add support to Codec DMA ports ASoC: q6dsp: q6afe: prepare afe_apr_send_pkt to take response opcode ASoC: q6dsp: q6afe: add global q6afe waitqueue ASoC: q6dsp: q6afe: add lpass hw voting support ASoC: q6dsp: q6afe: update q6afe_set_param to support global clocks ASoC: q6dsp: q6afe: add codec lpass clocks ASoC: q6dsp: q6afe-dai: add support to Codec DMA ports include/dt-bindings/sound/qcom,q6afe.h | 22 ++ sound/soc/qcom/qdsp6/q6afe-dai.c | 229 ++++++++++++++++++ sound/soc/qcom/qdsp6/q6afe.c | 308 +++++++++++++++++++++++-- sound/soc/qcom/qdsp6/q6afe.h | 33 ++- sound/soc/qcom/qdsp6/q6routing.c | 121 +++++++++- 5 files changed, 689 insertions(+), 24 deletions(-) -- 2.21.0
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/qcom/qdsp6/q6afe-dai.c229
-rw-r--r--sound/soc/qcom/qdsp6/q6afe.c308
-rw-r--r--sound/soc/qcom/qdsp6/q6afe.h33
-rw-r--r--sound/soc/qcom/qdsp6/q6routing.c121
4 files changed, 667 insertions, 24 deletions
diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c
index 0168af849272..d58b86a98114 100644
--- a/sound/soc/qcom/qdsp6/q6afe-dai.c
+++ b/sound/soc/qcom/qdsp6/q6afe-dai.c
@@ -55,6 +55,48 @@
.remove = msm_dai_q6_dai_remove, \
}
+#define Q6AFE_CDC_DMA_RX_DAI(did) { \
+ .playback = { \
+ .stream_name = #did" Playback", \
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+ SNDRV_PCM_RATE_176400, \
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE, \
+ .channels_min = 1, \
+ .channels_max = 8, \
+ .rate_min = 8000, \
+ .rate_max = 176400, \
+ }, \
+ .name = #did, \
+ .ops = &q6dma_ops, \
+ .id = did, \
+ .probe = msm_dai_q6_dai_probe, \
+ .remove = msm_dai_q6_dai_remove, \
+ }
+
+#define Q6AFE_CDC_DMA_TX_DAI(did) { \
+ .capture = { \
+ .stream_name = #did" Capture", \
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+ SNDRV_PCM_RATE_176400, \
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE, \
+ .channels_min = 1, \
+ .channels_max = 8, \
+ .rate_min = 8000, \
+ .rate_max = 176400, \
+ }, \
+ .name = #did, \
+ .ops = &q6dma_ops, \
+ .id = did, \
+ .probe = msm_dai_q6_dai_probe, \
+ .remove = msm_dai_q6_dai_remove, \
+ }
+
struct q6afe_dai_priv_data {
uint32_t sd_line_mask;
uint32_t sync_mode;
@@ -307,6 +349,90 @@ static int q6tdm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+
+static int q6dma_set_channel_map(struct snd_soc_dai *dai,
+ unsigned int tx_num, unsigned int *tx_ch_mask,
+ unsigned int rx_num, unsigned int *rx_ch_mask)
+{
+
+ struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
+ struct q6afe_cdc_dma_cfg *cfg = &dai_data->port_config[dai->id].dma_cfg;
+ int ch_mask;
+ int rc = 0;
+
+ switch (dai->id) {
+ case WSA_CODEC_DMA_TX_0:
+ case WSA_CODEC_DMA_TX_1:
+ case WSA_CODEC_DMA_TX_2:
+ case VA_CODEC_DMA_TX_0:
+ case VA_CODEC_DMA_TX_1:
+ case VA_CODEC_DMA_TX_2:
+ case TX_CODEC_DMA_TX_0:
+ case TX_CODEC_DMA_TX_1:
+ case TX_CODEC_DMA_TX_2:
+ case TX_CODEC_DMA_TX_3:
+ case TX_CODEC_DMA_TX_4:
+ case TX_CODEC_DMA_TX_5:
+ if (!tx_ch_mask) {
+ dev_err(dai->dev, "tx slot not found\n");
+ return -EINVAL;
+ }
+
+ if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
+ dev_err(dai->dev, "invalid tx num %d\n",
+ tx_num);
+ return -EINVAL;
+ }
+ ch_mask = *tx_ch_mask;
+
+ break;
+ case WSA_CODEC_DMA_RX_0:
+ case WSA_CODEC_DMA_RX_1:
+ case RX_CODEC_DMA_RX_0:
+ case RX_CODEC_DMA_RX_1:
+ case RX_CODEC_DMA_RX_2:
+ case RX_CODEC_DMA_RX_3:
+ case RX_CODEC_DMA_RX_4:
+ case RX_CODEC_DMA_RX_5:
+ case RX_CODEC_DMA_RX_6:
+ case RX_CODEC_DMA_RX_7:
+ /* rx */
+ if (!rx_ch_mask) {
+ dev_err(dai->dev, "rx slot not found\n");
+ return -EINVAL;
+ }
+ if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
+ dev_err(dai->dev, "invalid rx num %d\n",
+ rx_num);
+ return -EINVAL;
+ }
+ ch_mask = *rx_ch_mask;
+
+ break;
+ default:
+ dev_err(dai->dev, "%s: invalid dai id 0x%x\n",
+ __func__, dai->id);
+ return -EINVAL;
+ }
+
+ cfg->active_channels_mask = ch_mask;
+
+ return rc;
+}
+
+static int q6dma_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);
+ struct q6afe_cdc_dma_cfg *cfg = &dai_data->port_config[dai->id].dma_cfg;
+
+ cfg->bit_width = params_width(params);
+ cfg->sample_rate = params_rate(params);
+ cfg->num_channels = params_channels(params);
+
+ return 0;
+}
static void q6afe_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -362,6 +488,10 @@ static int q6afe_dai_prepare(struct snd_pcm_substream *substream,
q6afe_tdm_port_prepare(dai_data->port[dai->id],
&dai_data->port_config[dai->id].tdm);
break;
+ case WSA_CODEC_DMA_RX_0 ... RX_CODEC_DMA_RX_7:
+ q6afe_cdc_dma_port_prepare(dai_data->port[dai->id],
+ &dai_data->port_config[dai->id].dma_cfg);
+ break;
default:
return -EINVAL;
}
@@ -430,6 +560,7 @@ static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai,
freq, dir);
case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR:
case Q6AFE_LPASS_CLK_ID_MCLK_1 ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1:
+ case Q6AFE_LPASS_CLK_ID_WSA_CORE_MCLK ... Q6AFE_LPASS_CLK_ID_VA_CORE_2X_MCLK:
return q6afe_port_set_sysclk(port, clk_id,
Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
Q6AFE_LPASS_CLK_ROOT_DEFAULT,
@@ -562,6 +693,29 @@ static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {
{"PRI_MI2S_TX", NULL, "Primary MI2S Capture"},
{"SEC_MI2S_TX", NULL, "Secondary MI2S Capture"},
{"QUAT_MI2S_TX", NULL, "Quaternary MI2S Capture"},
+
+ {"WSA_CODEC_DMA_RX_0 Playback", NULL, "WSA_CODEC_DMA_RX_0"},
+ {"WSA_CODEC_DMA_TX_0", NULL, "WSA_CODEC_DMA_TX_0 Capture"},
+ {"WSA_CODEC_DMA_RX_1 Playback", NULL, "WSA_CODEC_DMA_RX_1"},
+ {"WSA_CODEC_DMA_TX_1", NULL, "WSA_CODEC_DMA_TX_1 Capture"},
+ {"WSA_CODEC_DMA_TX_2", NULL, "WSA_CODEC_DMA_TX_2 Capture"},
+ {"VA_CODEC_DMA_TX_0", NULL, "VA_CODEC_DMA_TX_0 Capture"},
+ {"VA_CODEC_DMA_TX_1", NULL, "VA_CODEC_DMA_TX_1 Capture"},
+ {"VA_CODEC_DMA_TX_2", NULL, "VA_CODEC_DMA_TX_2 Capture"},
+ {"RX_CODEC_DMA_RX_0 Playback", NULL, "RX_CODEC_DMA_RX_0"},
+ {"TX_CODEC_DMA_TX_0", NULL, "TX_CODEC_DMA_TX_0 Capture"},
+ {"RX_CODEC_DMA_RX_1 Playback", NULL, "RX_CODEC_DMA_RX_1"},
+ {"TX_CODEC_DMA_TX_1", NULL, "TX_CODEC_DMA_TX_1 Capture"},
+ {"RX_CODEC_DMA_RX_2 Playback", NULL, "RX_CODEC_DMA_RX_2"},
+ {"TX_CODEC_DMA_TX_2", NULL, "TX_CODEC_DMA_TX_2 Capture"},
+ {"RX_CODEC_DMA_RX_3 Playback", NULL, "RX_CODEC_DMA_RX_3"},
+ {"TX_CODEC_DMA_TX_3", NULL, "TX_CODEC_DMA_TX_3 Capture"},
+ {"RX_CODEC_DMA_RX_4 Playback", NULL, "RX_CODEC_DMA_RX_4"},
+ {"TX_CODEC_DMA_TX_4", NULL, "TX_CODEC_DMA_TX_4 Capture"},
+ {"RX_CODEC_DMA_RX_5 Playback", NULL, "RX_CODEC_DMA_RX_5"},
+ {"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"},
};
static const struct snd_soc_dai_ops q6hdmi_ops = {
@@ -594,6 +748,14 @@ static const struct snd_soc_dai_ops q6tdm_ops = {
.hw_params = q6tdm_hw_params,
};
+static const struct snd_soc_dai_ops q6dma_ops = {
+ .prepare = q6afe_dai_prepare,
+ .shutdown = q6afe_dai_shutdown,
+ .set_sysclk = q6afe_mi2s_set_sysclk,
+ .set_channel_map = q6dma_set_channel_map,
+ .hw_params = q6dma_hw_params,
+};
+
static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
{
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
@@ -1128,6 +1290,28 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
.probe = msm_dai_q6_dai_probe,
.remove = msm_dai_q6_dai_remove,
},
+ Q6AFE_CDC_DMA_RX_DAI(WSA_CODEC_DMA_RX_0),
+ Q6AFE_CDC_DMA_TX_DAI(WSA_CODEC_DMA_TX_0),
+ Q6AFE_CDC_DMA_RX_DAI(WSA_CODEC_DMA_RX_1),
+ Q6AFE_CDC_DMA_TX_DAI(WSA_CODEC_DMA_TX_1),
+ Q6AFE_CDC_DMA_TX_DAI(WSA_CODEC_DMA_TX_2),
+ Q6AFE_CDC_DMA_TX_DAI(VA_CODEC_DMA_TX_0),
+ Q6AFE_CDC_DMA_TX_DAI(VA_CODEC_DMA_TX_1),
+ Q6AFE_CDC_DMA_TX_DAI(VA_CODEC_DMA_TX_2),
+ Q6AFE_CDC_DMA_RX_DAI(RX_CODEC_DMA_RX_0),
+ Q6AFE_CDC_DMA_TX_DAI(TX_CODEC_DMA_TX_0),
+ Q6AFE_CDC_DMA_RX_DAI(RX_CODEC_DMA_RX_1),
+ Q6AFE_CDC_DMA_TX_DAI(TX_CODEC_DMA_TX_1),
+ Q6AFE_CDC_DMA_RX_DAI(RX_CODEC_DMA_RX_2),
+ Q6AFE_CDC_DMA_TX_DAI(TX_CODEC_DMA_TX_2),
+ Q6AFE_CDC_DMA_RX_DAI(RX_CODEC_DMA_RX_3),
+ Q6AFE_CDC_DMA_TX_DAI(TX_CODEC_DMA_TX_3),
+ Q6AFE_CDC_DMA_RX_DAI(RX_CODEC_DMA_RX_4),
+ Q6AFE_CDC_DMA_TX_DAI(TX_CODEC_DMA_TX_4),
+ Q6AFE_CDC_DMA_RX_DAI(RX_CODEC_DMA_RX_5),
+ Q6AFE_CDC_DMA_TX_DAI(TX_CODEC_DMA_TX_5),
+ Q6AFE_CDC_DMA_RX_DAI(RX_CODEC_DMA_RX_6),
+ Q6AFE_CDC_DMA_RX_DAI(RX_CODEC_DMA_RX_7),
};
static int q6afe_of_xlate_dai_name(struct snd_soc_component *component,
@@ -1350,6 +1534,51 @@ static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = {
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_7", NULL,
0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("DISPLAY_PORT_RX", "NULL", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_IN("WSA_CODEC_DMA_RX_0", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_0", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("WSA_CODEC_DMA_RX_1", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_1", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_2", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_0", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_1", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_2", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_0", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_0", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_1", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_1", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_2", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_2", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_3", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_3", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_4", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_4", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_5", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_5", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_6", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_7", "NULL",
+ 0, SND_SOC_NOPM, 0, 0),
};
static const struct snd_soc_component_driver q6afe_dai_component = {
diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c
index e0945f7a58c8..688878a002a4 100644
--- a/sound/soc/qcom/qdsp6/q6afe.c
+++ b/sound/soc/qcom/qdsp6/q6afe.c
@@ -42,6 +42,10 @@
#define AFE_PARAM_ID_I2S_CONFIG 0x0001020D
#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_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
/* I2S config specific */
#define AFE_API_VERSION_I2S_CONFIG 0x1
@@ -299,22 +303,71 @@
#define AFE_PORT_ID_QUINARY_TDM_TX_7 \
(AFE_PORT_ID_QUINARY_TDM_TX + 0x0E)
+/* AFE WSA Codec DMA Rx port 0 */
+#define AFE_PORT_ID_WSA_CODEC_DMA_RX_0 0xB000
+/* AFE WSA Codec DMA Tx port 0 */
+#define AFE_PORT_ID_WSA_CODEC_DMA_TX_0 0xB001
+/* AFE WSA Codec DMA Rx port 1 */
+#define AFE_PORT_ID_WSA_CODEC_DMA_RX_1 0xB002
+/* AFE WSA Codec DMA Tx port 1 */
+#define AFE_PORT_ID_WSA_CODEC_DMA_TX_1 0xB003
+/* AFE WSA Codec DMA Tx port 2 */
+#define AFE_PORT_ID_WSA_CODEC_DMA_TX_2 0xB005
+/* AFE VA Codec DMA Tx port 0 */
+#define AFE_PORT_ID_VA_CODEC_DMA_TX_0 0xB021
+/* AFE VA Codec DMA Tx port 1 */
+#define AFE_PORT_ID_VA_CODEC_DMA_TX_1 0xB023
+/* AFE VA Codec DMA Tx port 2 */
+#define AFE_PORT_ID_VA_CODEC_DMA_TX_2 0xB025
+/* AFE Rx Codec DMA Rx port 0 */
+#define AFE_PORT_ID_RX_CODEC_DMA_RX_0 0xB030
+/* AFE Tx Codec DMA Tx port 0 */
+#define AFE_PORT_ID_TX_CODEC_DMA_TX_0 0xB031
+/* AFE Rx Codec DMA Rx port 1 */
+#define AFE_PORT_ID_RX_CODEC_DMA_RX_1 0xB032
+/* AFE Tx Codec DMA Tx port 1 */
+#define AFE_PORT_ID_TX_CODEC_DMA_TX_1 0xB033
+/* AFE Rx Codec DMA Rx port 2 */
+#define AFE_PORT_ID_RX_CODEC_DMA_RX_2 0xB034
+/* AFE Tx Codec DMA Tx port 2 */
+#define AFE_PORT_ID_TX_CODEC_DMA_TX_2 0xB035
+/* AFE Rx Codec DMA Rx port 3 */
+#define AFE_PORT_ID_RX_CODEC_DMA_RX_3 0xB036
+/* AFE Tx Codec DMA Tx port 3 */
+#define AFE_PORT_ID_TX_CODEC_DMA_TX_3 0xB037
+/* AFE Rx Codec DMA Rx port 4 */
+#define AFE_PORT_ID_RX_CODEC_DMA_RX_4 0xB038
+/* AFE Tx Codec DMA Tx port 4 */
+#define AFE_PORT_ID_TX_CODEC_DMA_TX_4 0xB039
+/* AFE Rx Codec DMA Rx port 5 */
+#define AFE_PORT_ID_RX_CODEC_DMA_RX_5 0xB03A
+/* AFE Tx Codec DMA Tx port 5 */
+#define AFE_PORT_ID_TX_CODEC_DMA_TX_5 0xB03B
+/* AFE Rx Codec DMA Rx port 6 */
+#define AFE_PORT_ID_RX_CODEC_DMA_RX_6 0xB03C
+/* AFE Rx Codec DMA Rx port 7 */
+#define AFE_PORT_ID_RX_CODEC_DMA_RX_7 0xB03E
+
#define Q6AFE_LPASS_MODE_CLK1_VALID 1
#define Q6AFE_LPASS_MODE_CLK2_VALID 2
#define Q6AFE_LPASS_CLK_SRC_INTERNAL 1
#define Q6AFE_LPASS_CLK_ROOT_DEFAULT 0
#define AFE_API_VERSION_TDM_CONFIG 1
#define AFE_API_VERSION_SLOT_MAPPING_CONFIG 1
+#define AFE_API_VERSION_CODEC_DMA_CONFIG 1
#define TIMEOUT_MS 1000
#define AFE_CMD_RESP_AVAIL 0
#define AFE_CMD_RESP_NONE 1
+#define AFE_CLK_TOKEN 1024
struct q6afe {
struct apr_device *apr;
struct device *dev;
struct q6core_svc_api_info ainfo;
struct mutex lock;
+ struct aprv2_ibasic_rsp_result_t result;
+ wait_queue_head_t wait;
struct list_head port_list;
spinlock_t port_list_lock;
};
@@ -448,11 +501,21 @@ struct afe_param_id_tdm_cfg {
u32 slot_mask;
} __packed;
+struct afe_param_id_cdc_dma_cfg {
+ u32 cdc_dma_cfg_minor_version;
+ u32 sample_rate;
+ u16 bit_width;
+ u16 data_format;
+ u16 num_channels;
+ u16 active_channels_mask;
+} __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;
} __packed;
@@ -486,6 +549,18 @@ struct q6afe_port {
struct list_head node;
};
+struct afe_cmd_remote_lpass_core_hw_vote_request {
+ uint32_t hw_block_id;
+ char client_name[8];
+} __packed;
+
+struct afe_cmd_remote_lpass_core_hw_devote_request {
+ uint32_t hw_block_id;
+ uint32_t client_handle;
+} __packed;
+
+
+
struct afe_port_map {
int port_id;
int token;
@@ -707,6 +782,50 @@ static struct afe_port_map port_maps[AFE_PORT_MAX] = {
QUINARY_TDM_TX_7, 0, 1},
[DISPLAY_PORT_RX] = { AFE_PORT_ID_HDMI_OVER_DP_RX,
DISPLAY_PORT_RX, 1, 1},
+ [WSA_CODEC_DMA_RX_0] = { AFE_PORT_ID_WSA_CODEC_DMA_RX_0,
+ WSA_CODEC_DMA_RX_0, 1, 1},
+ [WSA_CODEC_DMA_TX_0] = { AFE_PORT_ID_WSA_CODEC_DMA_TX_0,
+ WSA_CODEC_DMA_TX_0, 0, 1},
+ [WSA_CODEC_DMA_RX_1] = { AFE_PORT_ID_WSA_CODEC_DMA_RX_1,
+ WSA_CODEC_DMA_RX_1, 1, 1},
+ [WSA_CODEC_DMA_TX_1] = { AFE_PORT_ID_WSA_CODEC_DMA_TX_1,
+ WSA_CODEC_DMA_TX_1, 0, 1},
+ [WSA_CODEC_DMA_TX_2] = { AFE_PORT_ID_WSA_CODEC_DMA_TX_2,
+ WSA_CODEC_DMA_TX_2, 0, 1},
+ [VA_CODEC_DMA_TX_0] = { AFE_PORT_ID_VA_CODEC_DMA_TX_0,
+ VA_CODEC_DMA_TX_0, 0, 1},
+ [VA_CODEC_DMA_TX_1] = { AFE_PORT_ID_VA_CODEC_DMA_TX_1,
+ VA_CODEC_DMA_TX_1, 0, 1},
+ [VA_CODEC_DMA_TX_2] = { AFE_PORT_ID_VA_CODEC_DMA_TX_2,
+ VA_CODEC_DMA_TX_2, 0, 1},
+ [RX_CODEC_DMA_RX_0] = { AFE_PORT_ID_RX_CODEC_DMA_RX_0,
+ RX_CODEC_DMA_RX_0, 1, 1},
+ [TX_CODEC_DMA_TX_0] = { AFE_PORT_ID_TX_CODEC_DMA_TX_0,
+ TX_CODEC_DMA_TX_0, 0, 1},
+ [RX_CODEC_DMA_RX_1] = { AFE_PORT_ID_RX_CODEC_DMA_RX_1,
+ RX_CODEC_DMA_RX_1, 1, 1},
+ [TX_CODEC_DMA_TX_1] = { AFE_PORT_ID_TX_CODEC_DMA_TX_1,
+ TX_CODEC_DMA_TX_1, 0, 1},
+ [RX_CODEC_DMA_RX_2] = { AFE_PORT_ID_RX_CODEC_DMA_RX_2,
+ RX_CODEC_DMA_RX_2, 1, 1},
+ [TX_CODEC_DMA_TX_2] = { AFE_PORT_ID_TX_CODEC_DMA_TX_2,
+ TX_CODEC_DMA_TX_2, 0, 1},
+ [RX_CODEC_DMA_RX_3] = { AFE_PORT_ID_RX_CODEC_DMA_RX_3,
+ RX_CODEC_DMA_RX_3, 1, 1},
+ [TX_CODEC_DMA_TX_3] = { AFE_PORT_ID_TX_CODEC_DMA_TX_3,
+ TX_CODEC_DMA_TX_3, 0, 1},
+ [RX_CODEC_DMA_RX_4] = { AFE_PORT_ID_RX_CODEC_DMA_RX_4,
+ RX_CODEC_DMA_RX_4, 1, 1},
+ [TX_CODEC_DMA_TX_4] = { AFE_PORT_ID_TX_CODEC_DMA_TX_4,
+ TX_CODEC_DMA_TX_4, 0, 1},
+ [RX_CODEC_DMA_RX_5] = { AFE_PORT_ID_RX_CODEC_DMA_RX_5,
+ RX_CODEC_DMA_RX_5, 1, 1},
+ [TX_CODEC_DMA_TX_5] = { AFE_PORT_ID_TX_CODEC_DMA_TX_5,
+ TX_CODEC_DMA_TX_5, 0, 1},
+ [RX_CODEC_DMA_RX_6] = { AFE_PORT_ID_RX_CODEC_DMA_RX_6,
+ 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},
};
static void q6afe_port_free(struct kref *ref)
@@ -769,6 +888,9 @@ static int q6afe_callback(struct apr_device *adev, struct apr_resp_pkt *data)
port->result = *res;
wake_up(&port->wait);
kref_put(&port->refcount, q6afe_port_free);
+ } else if (hdr->token == AFE_CLK_TOKEN) {
+ afe->result = *res;
+ wake_up(&afe->wait);
}
break;
default:
@@ -777,6 +899,11 @@ static int q6afe_callback(struct apr_device *adev, struct apr_resp_pkt *data)
}
}
break;
+ case AFE_CMD_RSP_REMOTE_LPASS_CORE_HW_VOTE_REQUEST:
+ afe->result.opcode = hdr->opcode;
+ afe->result.status = res->status;
+ wake_up(&afe->wait);
+ break;
default:
break;
}
@@ -801,15 +928,23 @@ int q6afe_get_port_id(int index)
EXPORT_SYMBOL_GPL(q6afe_get_port_id);
static int afe_apr_send_pkt(struct q6afe *afe, struct apr_pkt *pkt,
- struct q6afe_port *port)
+ struct q6afe_port *port, uint32_t rsp_opcode)
{
wait_queue_head_t *wait = &port->wait;
- struct apr_hdr *hdr = &pkt->hdr;
+ struct aprv2_ibasic_rsp_result_t *result;
int ret;
mutex_lock(&afe->lock);
- port->result.opcode = 0;
- port->result.status = 0;
+ if (port) {
+ wait = &port->wait;
+ result = &port->result;
+ } else {
+ result = &afe->result;
+ wait = &afe->wait;
+ }
+
+ result->opcode = 0;
+ result->status = 0;
ret = apr_send_pkt(afe->apr, pkt);
if (ret < 0) {
@@ -818,13 +953,13 @@ static int afe_apr_send_pkt(struct q6afe *afe, struct apr_pkt *pkt,
goto err;
}
- ret = wait_event_timeout(*wait, (port->result.opcode == hdr->opcode),
+ ret = wait_event_timeout(*wait, (result->opcode == rsp_opcode),
msecs_to_jiffies(TIMEOUT_MS));
if (!ret) {
ret = -ETIMEDOUT;
- } else if (port->result.status > 0) {
+ } else if (result->status > 0) {
dev_err(afe->dev, "DSP returned error[%x]\n",
- port->result.status);
+ result->status);
ret = -EINVAL;
} else {
ret = 0;
@@ -836,14 +971,13 @@ err:
return ret;
}
-static int q6afe_port_set_param(struct q6afe_port *port, void *data,
- int param_id, int module_id, int psize)
+static int q6afe_set_param(struct q6afe *afe, struct q6afe_port *port,
+ void *data, int param_id, int module_id, int psize,
+ int token)
{
struct afe_svc_cmd_set_param *param;
struct afe_port_param_data_v2 *pdata;
- struct q6afe *afe = port->afe;
struct apr_pkt *pkt;
- u16 port_id = port->id;
int ret, pkt_size;
void *p, *pl;
@@ -864,7 +998,7 @@ static int q6afe_port_set_param(struct q6afe_port *port, void *data,
pkt->hdr.pkt_size = pkt_size;
pkt->hdr.src_port = 0;
pkt->hdr.dest_port = 0;
- pkt->hdr.token = port->token;
+ pkt->hdr.token = token;
pkt->hdr.opcode = AFE_SVC_CMD_SET_PARAM;
param->payload_size = sizeof(*pdata) + psize;
@@ -875,15 +1009,21 @@ static int q6afe_port_set_param(struct q6afe_port *port, void *data,
pdata->param_id = param_id;
pdata->param_size = psize;
- ret = afe_apr_send_pkt(afe, pkt, port);
+ ret = afe_apr_send_pkt(afe, pkt, port, AFE_SVC_CMD_SET_PARAM);
if (ret)
- dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
- port_id, ret);
+ dev_err(afe->dev, "AFE set params failed %d\n", ret);
kfree(pkt);
return ret;
}
+static int q6afe_port_set_param(struct q6afe_port *port, void *data,
+ int param_id, int module_id, int psize)
+{
+ return q6afe_set_param(port->afe, port, data, param_id, module_id,
+ psize, port->token);
+}
+
static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data,
int param_id, int module_id, int psize)
{
@@ -924,7 +1064,7 @@ static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data,
pdata->param_id = param_id;
pdata->param_size = psize;
- ret = afe_apr_send_pkt(afe, pkt, port);
+ ret = afe_apr_send_pkt(afe, pkt, port, AFE_PORT_CMD_SET_PARAM_V2);
if (ret)
dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
port_id, ret);
@@ -933,7 +1073,7 @@ static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data,
return ret;
}
-static int q6afe_set_lpass_clock(struct q6afe_port *port,
+static int q6afe_port_set_lpass_clock(struct q6afe_port *port,
struct afe_clk_cfg *cfg)
{
return q6afe_port_set_param_v2(port, cfg,
@@ -958,6 +1098,25 @@ static int q6afe_set_digital_codec_core_clock(struct q6afe_port *port,
sizeof(*cfg));
}
+int q6afe_set_lpass_clock(struct device *dev, int clk_id, int attri,
+ int clk_root, unsigned int freq)
+{
+ struct q6afe *afe = dev_get_drvdata(dev->parent);
+ struct afe_clk_set cset = {0,};
+
+ cset.clk_set_minor_version = AFE_API_VERSION_CLOCK_SET;
+ cset.clk_id = clk_id;
+ cset.clk_freq_in_hz = freq;
+ cset.clk_attri = attri;
+ cset.clk_root = clk_root;
+ cset.enable = !!freq;
+
+ return q6afe_set_param(afe, NULL, &cset, AFE_PARAM_ID_CLOCK_SET,
+ AFE_MODULE_CLOCK_SET, sizeof(cset),
+ AFE_CLK_TOKEN);
+}
+EXPORT_SYMBOL_GPL(q6afe_set_lpass_clock);
+
int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id,
int clk_src, int clk_root,
unsigned int freq, int dir)
@@ -980,7 +1139,7 @@ int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id,
ccfg.clk_src = clk_src;
ccfg.clk_root = clk_root;
ccfg.clk_set_mode = Q6AFE_LPASS_MODE_CLK1_VALID;
- ret = q6afe_set_lpass_clock(port, &ccfg);
+ ret = q6afe_port_set_lpass_clock(port, &ccfg);
break;
case LPAIF_OSR_CLK:
@@ -989,11 +1148,12 @@ int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id,
ccfg.clk_src = clk_src;
ccfg.clk_root = clk_root;
ccfg.clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID;
- ret = q6afe_set_lpass_clock(port, &ccfg);
+ ret = q6afe_port_set_lpass_clock(port, &ccfg);
break;
case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR:
case Q6AFE_LPASS_CLK_ID_MCLK_1 ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1:
case Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT ... Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT:
+ case Q6AFE_LPASS_CLK_ID_WSA_CORE_MCLK ... Q6AFE_LPASS_CLK_ID_VA_CORE_2X_MCLK:
cset.clk_set_minor_version = AFE_API_VERSION_CLOCK_SET;
cset.clk_id = clk_id;
cset.clk_freq_in_hz = freq;
@@ -1054,7 +1214,7 @@ int q6afe_port_stop(struct q6afe_port *port)
stop->port_id = port_id;
stop->reserved = 0;
- ret = afe_apr_send_pkt(afe, pkt, port);
+ ret = afe_apr_send_pkt(afe, pkt, port, AFE_PORT_CMD_DEVICE_STOP);
if (ret)
dev_err(afe->dev, "AFE close failed %d\n", ret);
@@ -1289,6 +1449,28 @@ int q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg)
EXPORT_SYMBOL_GPL(q6afe_i2s_port_prepare);
/**
+ * q6afe_dam_port_prepare() - Prepare dma afe port.
+ *
+ * @port: Instance of afe port
+ * @cfg: DMA configuration for the afe port
+ *
+ */
+void q6afe_cdc_dma_port_prepare(struct q6afe_port *port,
+ struct q6afe_cdc_dma_cfg *cfg)
+{
+ union afe_port_config *pcfg = &port->port_cfg;
+ struct afe_param_id_cdc_dma_cfg *dma_cfg = &pcfg->dma_cfg;
+
+ dma_cfg->cdc_dma_cfg_minor_version = AFE_API_VERSION_CODEC_DMA_CONFIG;
+ dma_cfg->sample_rate = cfg->sample_rate;
+ dma_cfg->bit_width = cfg->bit_width;
+ dma_cfg->data_format = cfg->data_format;
+ dma_cfg->num_channels = cfg->num_channels;
+ if (!cfg->active_channels_mask)
+ dma_cfg->active_channels_mask = (1 << cfg->num_channels) - 1;
+}
+EXPORT_SYMBOL_GPL(q6afe_cdc_dma_port_prepare);
+/**
* q6afe_port_start() - Start a afe port
*
* @port: Instance of port to start
@@ -1344,7 +1526,7 @@ int q6afe_port_start(struct q6afe_port *port)
start->port_id = port_id;
- ret = afe_apr_send_pkt(afe, pkt, port);
+ ret = afe_apr_send_pkt(afe, pkt, port, AFE_PORT_CMD_DEVICE_START);
if (ret)
dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
port_id, ret);
@@ -1420,7 +1602,9 @@ struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id)
case AFE_PORT_ID_PRIMARY_TDM_RX ... AFE_PORT_ID_QUINARY_TDM_TX_7:
cfg_type = AFE_PARAM_ID_TDM_CONFIG;
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;
default:
dev_err(dev, "Invalid port id 0x%x\n", port_id);
return ERR_PTR(-EINVAL);
@@ -1458,6 +1642,85 @@ void q6afe_port_put(struct q6afe_port *port)
}
EXPORT_SYMBOL_GPL(q6afe_port_put);
+int q6afe_unvote_lpass_core_hw(struct device *dev, uint32_t hw_block_id,
+ uint32_t client_handle)
+{
+ struct q6afe *afe = dev_get_drvdata(dev->parent);
+ struct afe_cmd_remote_lpass_core_hw_devote_request *vote_cfg;
+ struct apr_pkt *pkt;
+ int ret = 0;
+ int pkt_size;
+ void *p;
+
+ pkt_size = APR_HDR_SIZE + sizeof(*vote_cfg);
+ p = kzalloc(pkt_size, GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ pkt = p;
+ vote_cfg = p + APR_HDR_SIZE;
+
+ pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ pkt->hdr.pkt_size = pkt_size;
+ pkt->hdr.src_port = 0;
+ pkt->hdr.dest_port = 0;
+ pkt->hdr.token = hw_block_id;
+ pkt->hdr.opcode = AFE_CMD_REMOTE_LPASS_CORE_HW_DEVOTE_REQUEST;
+ vote_cfg->hw_block_id = hw_block_id;
+ vote_cfg->client_handle = client_handle;
+
+ ret = apr_send_pkt(afe->apr, pkt);
+ if (ret < 0)
+ dev_err(afe->dev, "AFE failed to unvote (%d)\n", hw_block_id);
+
+ kfree(pkt);
+ return ret;
+}
+EXPORT_SYMBOL(q6afe_unvote_lpass_core_hw);
+
+int q6afe_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id,
+ char *client_name, uint32_t *client_handle)
+{
+ struct q6afe *afe = dev_get_drvdata(dev->parent);
+ struct afe_cmd_remote_lpass_core_hw_vote_request *vote_cfg;
+ struct apr_pkt *pkt;
+ int ret = 0;
+ int pkt_size;
+ void *p;
+
+ pkt_size = APR_HDR_SIZE + sizeof(*vote_cfg);
+ p = kzalloc(pkt_size, GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ pkt = p;
+ vote_cfg = p + APR_HDR_SIZE;
+
+ pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ pkt->hdr.pkt_size = pkt_size;
+ pkt->hdr.src_port = 0;
+ pkt->hdr.dest_port = 0;
+ pkt->hdr.token = hw_block_id;
+ pkt->hdr.opcode = AFE_CMD_REMOTE_LPASS_CORE_HW_VOTE_REQUEST;
+ vote_cfg->hw_block_id = hw_block_id;
+ strlcpy(vote_cfg->client_name, client_name,
+ sizeof(vote_cfg->client_name));
+
+ ret = afe_apr_send_pkt(afe, pkt, NULL,
+ AFE_CMD_RSP_REMOTE_LPASS_CORE_HW_VOTE_REQUEST);
+ if (ret)
+ dev_err(afe->dev, "AFE failed to vote (%d)\n", hw_block_id);
+
+
+ kfree(pkt);
+ return ret;
+}
+EXPORT_SYMBOL(q6afe_vote_lpass_core_hw);
+
static int q6afe_probe(struct apr_device *adev)
{
struct q6afe *afe;
@@ -1470,6 +1733,7 @@ static int q6afe_probe(struct apr_device *adev)
q6core_get_svc_api_info(adev->svc_id, &afe->ainfo);
afe->apr = adev;
mutex_init(&afe->lock);
+ init_waitqueue_head(&afe->wait);
afe->dev = dev;
INIT_LIST_HEAD(&afe->port_list);
spin_lock_init(&afe->port_list_lock);
diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h
index c7ed5422baff..22e10269aa10 100644
--- a/sound/soc/qcom/qdsp6/q6afe.h
+++ b/sound/soc/qcom/qdsp6/q6afe.h
@@ -5,7 +5,7 @@
#include <dt-bindings/sound/qcom,q6afe.h>
-#define AFE_PORT_MAX 105
+#define AFE_PORT_MAX 127
#define MSM_AFE_PORT_TYPE_RX 0
#define MSM_AFE_PORT_TYPE_TX 1
@@ -133,6 +133,19 @@
/* Clock ID for INT MCLK1 */
#define Q6AFE_LPASS_CLK_ID_INT_MCLK_1 0x306
+#define Q6AFE_LPASS_CLK_ID_WSA_CORE_MCLK 0x309
+#define Q6AFE_LPASS_CLK_ID_WSA_CORE_NPL_MCLK 0x30a
+#define Q6AFE_LPASS_CLK_ID_TX_CORE_MCLK 0x30c
+#define Q6AFE_LPASS_CLK_ID_TX_CORE_NPL_MCLK 0x30d
+#define Q6AFE_LPASS_CLK_ID_RX_CORE_MCLK 0x30e
+#define Q6AFE_LPASS_CLK_ID_RX_CORE_NPL_MCLK 0x30f
+#define Q6AFE_LPASS_CLK_ID_VA_CORE_MCLK 0x30b
+#define Q6AFE_LPASS_CLK_ID_VA_CORE_2X_MCLK 0x310
+
+#define Q6AFE_LPASS_CORE_AVTIMER_BLOCK 0x2
+#define Q6AFE_LPASS_CORE_HW_MACRO_BLOCK 0x3
+#define Q6AFE_LPASS_CORE_HW_DCODEC_BLOCK 0x4
+
/* Clock attribute for invalid use (reserved for internal usage) */
#define Q6AFE_LPASS_CLK_ATTRIBUTE_INVALID 0x0
/* Clock attribute for no couple case */
@@ -184,11 +197,21 @@ struct q6afe_tdm_cfg {
u16 ch_mapping[AFE_MAX_CHAN_COUNT];
};
+struct q6afe_cdc_dma_cfg {
+ u16 sample_rate;
+ u16 bit_width;
+ u16 data_format;
+ u16 num_channels;
+ u16 active_channels_mask;
+};
+
+
struct q6afe_port_config {
struct q6afe_hdmi_cfg hdmi;
struct q6afe_slim_cfg slim;
struct q6afe_i2s_cfg i2s_cfg;
struct q6afe_tdm_cfg tdm;
+ struct q6afe_cdc_dma_cfg dma_cfg;
};
struct q6afe_port;
@@ -204,8 +227,16 @@ void q6afe_slim_port_prepare(struct q6afe_port *port,
struct q6afe_slim_cfg *cfg);
int q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg);
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 q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id,
int clk_src, int clk_root,
unsigned int freq, int dir);
+int q6afe_set_lpass_clock(struct device *dev, int clk_id, int clk_src,
+ int clk_root, unsigned int freq);
+int q6afe_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id,
+ char *client_name, uint32_t *client_handle);
+int q6afe_unvote_lpass_core_hw(struct device *dev, uint32_t hw_block_id,
+ uint32_t client_handle);
#endif /* __Q6AFE_H__ */
diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c
index 25d23e0266c7..b12539fae6ed 100644
--- a/sound/soc/qcom/qdsp6/q6routing.c
+++ b/sound/soc/qcom/qdsp6/q6routing.c
@@ -113,7 +113,19 @@
{ mix_name, "QUIN_TDM_TX_4", "QUIN_TDM_TX_4"}, \
{ mix_name, "QUIN_TDM_TX_5", "QUIN_TDM_TX_5"}, \
{ mix_name, "QUIN_TDM_TX_6", "QUIN_TDM_TX_6"}, \
- { mix_name, "QUIN_TDM_TX_7", "QUIN_TDM_TX_7"}
+ { mix_name, "QUIN_TDM_TX_7", "QUIN_TDM_TX_7"}, \
+ { mix_name, "WSA_CODEC_DMA_TX_0", "WSA_CODEC_DMA_TX_0"}, \
+ { mix_name, "WSA_CODEC_DMA_TX_1", "WSA_CODEC_DMA_TX_1"}, \
+ { mix_name, "WSA_CODEC_DMA_TX_2", "WSA_CODEC_DMA_TX_2"}, \
+ { mix_name, "VA_CODEC_DMA_TX_0", "VA_CODEC_DMA_TX_0"}, \
+ { mix_name, "VA_CODEC_DMA_TX_1", "VA_CODEC_DMA_TX_1"}, \
+ { mix_name, "VA_CODEC_DMA_TX_2", "VA_CODEC_DMA_TX_2"}, \
+ { mix_name, "TX_CODEC_DMA_TX_0", "TX_CODEC_DMA_TX_0"}, \
+ { mix_name, "TX_CODEC_DMA_TX_1", "TX_CODEC_DMA_TX_1"}, \
+ { mix_name, "TX_CODEC_DMA_TX_2", "TX_CODEC_DMA_TX_2"}, \
+ { mix_name, "TX_CODEC_DMA_TX_3", "TX_CODEC_DMA_TX_3"}, \
+ { mix_name, "TX_CODEC_DMA_TX_4", "TX_CODEC_DMA_TX_4"}, \
+ { mix_name, "TX_CODEC_DMA_TX_5", "TX_CODEC_DMA_TX_5"}
#define Q6ROUTING_TX_MIXERS(id) \
SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, \
@@ -268,6 +280,42 @@
msm_routing_put_audio_mixer), \
SOC_SINGLE_EXT("QUIN_TDM_TX_7", QUINARY_TDM_TX_7, \
id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("WSA_CODEC_DMA_TX_0", WSA_CODEC_DMA_TX_0, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("WSA_CODEC_DMA_TX_1", WSA_CODEC_DMA_TX_1, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("WSA_CODEC_DMA_TX_2", WSA_CODEC_DMA_TX_2, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("VA_CODEC_DMA_TX_0", VA_CODEC_DMA_TX_0, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("VA_CODEC_DMA_TX_1", VA_CODEC_DMA_TX_1, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("VA_CODEC_DMA_TX_2", VA_CODEC_DMA_TX_2, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("TX_CODEC_DMA_TX_0", TX_CODEC_DMA_TX_0, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("TX_CODEC_DMA_TX_1", TX_CODEC_DMA_TX_1, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("TX_CODEC_DMA_TX_2", TX_CODEC_DMA_TX_2, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("TX_CODEC_DMA_TX_3", TX_CODEC_DMA_TX_3, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("TX_CODEC_DMA_TX_4", TX_CODEC_DMA_TX_4, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
+ msm_routing_put_audio_mixer), \
+ SOC_SINGLE_EXT("TX_CODEC_DMA_TX_5", TX_CODEC_DMA_TX_5, \
+ id, 1, 0, msm_routing_get_audio_mixer, \
msm_routing_put_audio_mixer),
struct session_data {
@@ -609,6 +657,36 @@ static const struct snd_kcontrol_new quin_tdm_rx_6_mixer_controls[] = {
static const struct snd_kcontrol_new quin_tdm_rx_7_mixer_controls[] = {
Q6ROUTING_RX_MIXERS(QUINARY_TDM_RX_7) };
+static const struct snd_kcontrol_new wsa_codec_dma_rx_0_mixer_controls[] = {
+ Q6ROUTING_RX_MIXERS(WSA_CODEC_DMA_RX_0) };
+
+static const struct snd_kcontrol_new wsa_codec_dma_rx_1_mixer_controls[] = {
+ Q6ROUTING_RX_MIXERS(WSA_CODEC_DMA_RX_1) };
+
+static const struct snd_kcontrol_new rx_codec_dma_rx_0_mixer_controls[] = {
+ Q6ROUTING_RX_MIXERS(RX_CODEC_DMA_RX_0) };
+
+static const struct snd_kcontrol_new rx_codec_dma_rx_1_mixer_controls[] = {
+ Q6ROUTING_RX_MIXERS(RX_CODEC_DMA_RX_1) };
+
+static const struct snd_kcontrol_new rx_codec_dma_rx_2_mixer_controls[] = {
+ Q6ROUTING_RX_MIXERS(RX_CODEC_DMA_RX_2) };
+
+static const struct snd_kcontrol_new rx_codec_dma_rx_3_mixer_controls[] = {
+ Q6ROUTING_RX_MIXERS(RX_CODEC_DMA_RX_3) };
+
+static const struct snd_kcontrol_new rx_codec_dma_rx_4_mixer_controls[] = {
+ Q6ROUTING_RX_MIXERS(RX_CODEC_DMA_RX_4) };
+
+static const struct snd_kcontrol_new rx_codec_dma_rx_5_mixer_controls[] = {
+ Q6ROUTING_RX_MIXERS(RX_CODEC_DMA_RX_5) };
+
+static const struct snd_kcontrol_new rxcodec_dma_rx_6_mixer_controls[] = {
+ Q6ROUTING_RX_MIXERS(RX_CODEC_DMA_RX_6) };
+
+static const struct snd_kcontrol_new rx_codec_dma_rx_7_mixer_controls[] = {
+ Q6ROUTING_RX_MIXERS(RX_CODEC_DMA_RX_7) };
+
static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
Q6ROUTING_TX_MIXERS(MSM_FRONTEND_DAI_MULTIMEDIA1) };
@@ -819,6 +897,37 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
SND_SOC_DAPM_MIXER("QUIN_TDM_RX_7 Audio Mixer", SND_SOC_NOPM, 0, 0,
quin_tdm_rx_7_mixer_controls,
ARRAY_SIZE(quin_tdm_rx_7_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("WSA_CODEC_DMA_RX_0 Audio Mixer", SND_SOC_NOPM, 0, 0,
+ wsa_codec_dma_rx_0_mixer_controls,
+ ARRAY_SIZE(wsa_codec_dma_rx_0_mixer_controls)),
+ SND_SOC_DAPM_MIXER("WSA_CODEC_DMA_RX_1 Audio Mixer", SND_SOC_NOPM, 0, 0,
+ wsa_codec_dma_rx_1_mixer_controls,
+ ARRAY_SIZE(wsa_codec_dma_rx_1_mixer_controls)),
+ SND_SOC_DAPM_MIXER("RX_CODEC_DMA_RX_0 Audio Mixer", SND_SOC_NOPM, 0, 0,
+ rx_codec_dma_rx_0_mixer_controls,
+ ARRAY_SIZE(rx_codec_dma_rx_0_mixer_controls)),
+ SND_SOC_DAPM_MIXER("RX_CODEC_DMA_RX_1 Audio Mixer", SND_SOC_NOPM, 0, 0,
+ rx_codec_dma_rx_1_mixer_controls,
+ ARRAY_SIZE(rx_codec_dma_rx_1_mixer_controls)),
+ SND_SOC_DAPM_MIXER("RX_CODEC_DMA_RX_2 Audio Mixer", SND_SOC_NOPM, 0, 0,
+ rx_codec_dma_rx_2_mixer_controls,
+ ARRAY_SIZE(rx_codec_dma_rx_2_mixer_controls)),
+ SND_SOC_DAPM_MIXER("RX_CODEC_DMA_RX_3 Audio Mixer", SND_SOC_NOPM, 0, 0,
+ rx_codec_dma_rx_3_mixer_controls,
+ ARRAY_SIZE(rx_codec_dma_rx_3_mixer_controls)),
+ SND_SOC_DAPM_MIXER("RX_CODEC_DMA_RX_4 Audio Mixer", SND_SOC_NOPM, 0, 0,
+ rx_codec_dma_rx_4_mixer_controls,
+ ARRAY_SIZE(rx_codec_dma_rx_4_mixer_controls)),
+ SND_SOC_DAPM_MIXER("RX_CODEC_DMA_RX_5 Audio Mixer", SND_SOC_NOPM, 0, 0,
+ rx_codec_dma_rx_5_mixer_controls,
+ ARRAY_SIZE(rx_codec_dma_rx_5_mixer_controls)),
+ SND_SOC_DAPM_MIXER("RX_CODEC_DMA_RX_6 Audio Mixer", SND_SOC_NOPM, 0, 0,
+ rxcodec_dma_rx_6_mixer_controls,
+ ARRAY_SIZE(rxcodec_dma_rx_6_mixer_controls)),
+ 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("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,
@@ -901,6 +1010,16 @@ static const struct snd_soc_dapm_route intercon[] = {
Q6ROUTING_RX_DAPM_ROUTE("QUIN_TDM_RX_5 Audio Mixer", "QUIN_TDM_RX_5"),
Q6ROUTING_RX_DAPM_ROUTE("QUIN_TDM_RX_6 Audio Mixer", "QUIN_TDM_RX_6"),
Q6ROUTING_RX_DAPM_ROUTE("QUIN_TDM_RX_7 Audio Mixer", "QUIN_TDM_RX_7"),
+ Q6ROUTING_RX_DAPM_ROUTE("WSA_CODEC_DMA_RX_0 Audio Mixer", "WSA_CODEC_DMA_RX_0"),
+ Q6ROUTING_RX_DAPM_ROUTE("WSA_CODEC_DMA_RX_1 Audio Mixer", "WSA_CODEC_DMA_RX_1"),
+ Q6ROUTING_RX_DAPM_ROUTE("RX_CODEC_DMA_RX_0 Audio Mixer", "RX_CODEC_DMA_RX_0"),
+ Q6ROUTING_RX_DAPM_ROUTE("RX_CODEC_DMA_RX_1 Audio Mixer", "RX_CODEC_DMA_RX_1"),
+ Q6ROUTING_RX_DAPM_ROUTE("RX_CODEC_DMA_RX_2 Audio Mixer", "RX_CODEC_DMA_RX_2"),
+ Q6ROUTING_RX_DAPM_ROUTE("RX_CODEC_DMA_RX_3 Audio Mixer", "RX_CODEC_DMA_RX_3"),
+ Q6ROUTING_RX_DAPM_ROUTE("RX_CODEC_DMA_RX_4 Audio Mixer", "RX_CODEC_DMA_RX_4"),
+ 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_TX_DAPM_ROUTE("MultiMedia1 Mixer"),
Q6ROUTING_TX_DAPM_ROUTE("MultiMedia2 Mixer"),
Q6ROUTING_TX_DAPM_ROUTE("MultiMedia3 Mixer"),