summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/dt-bindings/sound/qcom,q6afe.h22
-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
5 files changed, 689 insertions, 24 deletions
diff --git a/include/dt-bindings/sound/qcom,q6afe.h b/include/dt-bindings/sound/qcom,q6afe.h
index 1df06f8ad5c3..7207ab2b57bf 100644
--- a/include/dt-bindings/sound/qcom,q6afe.h
+++ b/include/dt-bindings/sound/qcom,q6afe.h
@@ -107,6 +107,28 @@
#define QUINARY_TDM_RX_7 102
#define QUINARY_TDM_TX_7 103
#define DISPLAY_PORT_RX 104
+#define WSA_CODEC_DMA_RX_0 105
+#define WSA_CODEC_DMA_TX_0 106
+#define WSA_CODEC_DMA_RX_1 107
+#define WSA_CODEC_DMA_TX_1 108
+#define WSA_CODEC_DMA_TX_2 109
+#define VA_CODEC_DMA_TX_0 110
+#define VA_CODEC_DMA_TX_1 111
+#define VA_CODEC_DMA_TX_2 112
+#define RX_CODEC_DMA_RX_0 113
+#define TX_CODEC_DMA_TX_0 114
+#define RX_CODEC_DMA_RX_1 115
+#define TX_CODEC_DMA_TX_1 116
+#define RX_CODEC_DMA_RX_2 117
+#define TX_CODEC_DMA_TX_2 118
+#define RX_CODEC_DMA_RX_3 119
+#define TX_CODEC_DMA_TX_3 120
+#define RX_CODEC_DMA_RX_4 121
+#define TX_CODEC_DMA_TX_4 122
+#define RX_CODEC_DMA_RX_5 123
+#define TX_CODEC_DMA_TX_5 124
+#define RX_CODEC_DMA_RX_6 125
+#define RX_CODEC_DMA_RX_7 126
#endif /* __DT_BINDINGS_Q6_AFE_H__ */
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"),