Browse Source

Merge "asoc: add new fe for hearing aid"

qctecmdr 4 years ago
parent
commit
0b521bbfad
5 changed files with 79 additions and 15 deletions
  1. 22 0
      asoc/msm-dai-q6-v2.c
  2. 14 4
      asoc/msm-pcm-afe-v2.c
  3. 39 9
      dsp/q6afe.c
  4. 2 1
      dsp/q6audio-v2.c
  5. 2 1
      include/dsp/q6afe-v2.h

+ 22 - 0
asoc/msm-dai-q6-v2.c

@@ -2621,6 +2621,7 @@ static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream,
 	case RT_PROXY_DAI_001_RX:
 	case RT_PROXY_DAI_002_TX:
 	case RT_PROXY_DAI_002_RX:
+	case RT_PROXY_DAI_003_TX:
 	case RT_PROXY_PORT_002_TX:
 	case RT_PROXY_PORT_002_RX:
 		rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
@@ -4088,6 +4089,23 @@ static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai[] = {
 	},
 };
 
+static struct snd_soc_dai_driver msm_dai_q6_afe_cap_dai = {
+	.capture = {
+		.stream_name = "AFE-PROXY TX1",
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+		SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 8,
+		.rate_min =     8000,
+		.rate_max =     48000,
+	},
+	.ops = &msm_dai_q6_ops,
+	.id = RT_PROXY_DAI_003_TX,
+	.probe = msm_dai_q6_dai_probe,
+	.remove = msm_dai_q6_dai_remove,
+};
+
 static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
 	.playback = {
 		.stream_name = "Internal BT-SCO Playback",
@@ -7280,6 +7298,10 @@ register_afe_capture:
 			pr_err("%s: Device not found stream name %s\n",
 			__func__, stream_name);
 		break;
+        case RT_PROXY_DAI_003_TX:
+		rc = snd_soc_register_component(&pdev->dev,
+			&msm_dai_q6_component, &msm_dai_q6_afe_cap_dai, 1);
+		break;
 	case VOICE_PLAYBACK_TX:
 		strlcpy(stream_name, "Voice Farend Playback", 80);
 		goto register_voice_playback;

+ 14 - 4
asoc/msm-pcm-afe-v2.c

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
  */
 
 
@@ -124,7 +124,9 @@ static enum hrtimer_restart afe_hrtimer_rec_callback(struct hrtimer *hrt)
 		container_of(hrt, struct pcm_afe_info, hrt);
 	struct snd_pcm_substream *substream = prtd->substream;
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	u32 mem_map_handle = 0;
+	int port_id = rtd->cpu_dai->id;
 	int ret;
 
 	mem_map_handle = afe_req_mmap_handle(prtd->audio_client);
@@ -138,7 +140,7 @@ static enum hrtimer_restart afe_hrtimer_rec_callback(struct hrtimer *hrt)
 		ret = afe_rt_proxy_port_read(
 		(prtd->dma_addr + (prtd->dsp_cnt
 		* snd_pcm_lib_period_bytes(prtd->substream))), mem_map_handle,
-		snd_pcm_lib_period_bytes(prtd->substream));
+		snd_pcm_lib_period_bytes(prtd->substream), port_id);
 		if (ret < 0) {
 			pr_err("%s: AFE port read fails: %d\n", __func__, ret);
 			prtd->start = 0;
@@ -256,15 +258,19 @@ static void pcm_afe_process_rx_pkt(uint32_t opcode,
 	unsigned long dsp_flags;
 	struct snd_pcm_substream *substream = NULL;
 	struct snd_pcm_runtime *runtime = NULL;
+	struct snd_soc_pcm_runtime *rtd = NULL;
 	uint16_t event;
 	uint64_t period_bytes;
 	uint64_t bytes_one_sec;
 	uint32_t mem_map_handle = 0;
+	int port_id = 0;
 
 	if (prtd == NULL)
 		return;
 	substream =  prtd->substream;
 	runtime = substream->runtime;
+	rtd = substream->private_data;
+	port_id = rtd->cpu_dai->id;
 	pr_debug("%s\n", __func__);
 	spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
 	switch (opcode) {
@@ -305,7 +311,8 @@ static void pcm_afe_process_rx_pkt(uint32_t opcode,
 						prtd->substream))),
 					mem_map_handle,
 					snd_pcm_lib_period_bytes(
-						prtd->substream));
+						prtd->substream),
+					port_id);
 				prtd->dsp_cnt++;
 			}
 			break;
@@ -543,6 +550,8 @@ static int msm_afe_capture_copy(struct snd_pcm_substream *substream,
 	int ret = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct pcm_afe_info *prtd = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	int port_id = rtd->cpu_dai->id;
 	char *hwbuf = runtime->dma_area + hwoff;
 	u32 mem_map_handle = 0;
 
@@ -562,7 +571,8 @@ static int msm_afe_capture_copy(struct snd_pcm_substream *substream,
 				(prtd->dsp_cnt *
 				snd_pcm_lib_period_bytes(prtd->substream))),
 				mem_map_handle,
-				snd_pcm_lib_period_bytes(prtd->substream));
+				snd_pcm_lib_period_bytes(prtd->substream),
+				port_id);
 
 		if (ret) {
 			pr_err("%s: AFE proxy port read failed %d\n",

+ 39 - 9
dsp/q6afe.c

@@ -186,6 +186,8 @@ static int pcm_afe_instance[2];
 static int proxy_afe_instance[2];
 bool afe_close_done[2] = {true, true};
 
+static bool proxy_afe_started = false;
+
 #define SIZEOF_CFG_CMD(y) \
 		(sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
 
@@ -871,7 +873,9 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
 			}
 			break;
 		}
-		case RT_PROXY_PORT_001_RX: {
+		case RT_PROXY_PORT_001_RX:
+		case RT_PROXY_PORT_002_RX:
+		{
 			if (this_afe.rx_cb) {
 				this_afe.rx_cb(data->opcode, data->token,
 					data->payload,
@@ -4574,7 +4578,23 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
 		ret = -EINVAL;
 		return ret;
 	}
-
+	if (port_id == RT_PROXY_PORT_002_RX) {
+		if (proxy_afe_started) {
+			pr_debug("%s: afe port already started, port id 0x%x\n",
+				__func__, RT_PROXY_PORT_002_RX);
+			return 0;
+		} else {
+			proxy_afe_started = true;
+		}
+	}
+	if (port_id == RT_PROXY_DAI_003_TX) {
+		port_id = VIRTUAL_ID_TO_PORTID(port_id);
+		if (proxy_afe_started) {
+			pr_debug("%s: reconfigure afe port again\n", __func__);
+			afe_close(port_id);
+		}
+		proxy_afe_started = true;
+	}
 	if ((port_id == RT_PROXY_DAI_001_RX) ||
 		(port_id == RT_PROXY_DAI_002_TX)) {
 		pr_debug("%s: before incrementing pcm_afe_instance %d port_id 0x%x\n",
@@ -6505,7 +6525,8 @@ int afe_register_get_events(u16 port_id,
 		rtac_set_afe_handle(this_afe.apr);
 	}
 	if ((port_id == RT_PROXY_DAI_002_RX) ||
-		(port_id == RT_PROXY_DAI_001_TX)) {
+		(port_id == RT_PROXY_DAI_001_TX) ||
+		(port_id == RT_PROXY_DAI_003_TX)) {
 		port_id = VIRTUAL_ID_TO_PORTID(port_id);
 	} else {
 		pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
@@ -6515,7 +6536,8 @@ int afe_register_get_events(u16 port_id,
 	if (port_id == RT_PROXY_PORT_001_TX) {
 		this_afe.tx_cb = cb;
 		this_afe.tx_private_data = private_data;
-	} else if (port_id == RT_PROXY_PORT_001_RX) {
+	} else if (port_id == RT_PROXY_PORT_001_RX ||
+			port_id == RT_PROXY_PORT_002_RX) {
 		this_afe.rx_cb = cb;
 		this_afe.rx_private_data = private_data;
 	}
@@ -6566,7 +6588,8 @@ int afe_unregister_get_events(u16 port_id)
 	}
 
 	if ((port_id == RT_PROXY_DAI_002_RX) ||
-		(port_id == RT_PROXY_DAI_001_TX)) {
+		(port_id == RT_PROXY_DAI_001_TX) ||
+		(port_id == RT_PROXY_DAI_003_TX)) {
 		port_id = VIRTUAL_ID_TO_PORTID(port_id);
 	} else {
 		pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
@@ -6600,7 +6623,8 @@ int afe_unregister_get_events(u16 port_id)
 	if (port_id == RT_PROXY_PORT_001_TX) {
 		this_afe.tx_cb = NULL;
 		this_afe.tx_private_data = NULL;
-	} else if (port_id == RT_PROXY_PORT_001_RX) {
+	} else if (port_id == RT_PROXY_PORT_001_RX ||
+			port_id == RT_PROXY_PORT_002_RX) {
 		this_afe.rx_cb = NULL;
 		this_afe.rx_private_data = NULL;
 	}
@@ -6678,14 +6702,16 @@ EXPORT_SYMBOL(afe_rt_proxy_port_write);
  * @buf_addr_p: Physical buffer address to fill read data
  * @mem_map_handle: memory map handle for buffer read
  * @bytes: number of bytes to read
+ * @id: afe virtual port id
  *
  * Returns 0 on success or error on failure
  */
 int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
-		u32 mem_map_handle, int bytes)
+		u32 mem_map_handle, int bytes, int id)
 {
 	int ret = 0;
 	struct afe_port_data_cmd_rt_proxy_port_read_v2 afecmd_rd;
+	int port_id = VIRTUAL_ID_TO_PORTID(id);
 
 	if (this_afe.apr == NULL) {
 		pr_err("%s: register to AFE is not done\n", __func__);
@@ -6702,7 +6728,7 @@ int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
 	afecmd_rd.hdr.dest_port = 0;
 	afecmd_rd.hdr.token = 0;
 	afecmd_rd.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2;
-	afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
+	afecmd_rd.port_id = port_id;
 	afecmd_rd.buffer_address_lsw = lower_32_bits(buf_addr_p);
 	afecmd_rd.buffer_address_msw =
 				msm_audio_populate_upper_32_bits(buf_addr_p);
@@ -7559,7 +7585,8 @@ int afe_convert_virtual_to_portid(u16 port_id)
 		if (port_id == RT_PROXY_DAI_001_RX ||
 		    port_id == RT_PROXY_DAI_001_TX ||
 		    port_id == RT_PROXY_DAI_002_RX ||
-		    port_id == RT_PROXY_DAI_002_TX) {
+		    port_id == RT_PROXY_DAI_002_TX ||
+		    port_id == RT_PROXY_DAI_003_TX) {
 			ret = VIRTUAL_ID_TO_PORTID(port_id);
 		} else {
 			pr_err("%s: wrong port 0x%x\n",
@@ -7659,6 +7686,9 @@ int afe_close(int port_id)
 		afe_close_done[port_id & 0x1] = true;
 	}
 
+	if (port_id == RT_PROXY_PORT_002_RX && proxy_afe_started)
+		proxy_afe_started = false;
+
 	port_id = q6audio_convert_virtual_to_portid(port_id);
 	index = q6audio_get_port_index(port_id);
 	if (index < 0 || index >= AFE_MAX_PORTS) {

+ 2 - 1
dsp/q6audio-v2.c

@@ -791,7 +791,8 @@ int q6audio_convert_virtual_to_portid(u16 port_id)
 		if (port_id == RT_PROXY_DAI_001_RX ||
 			port_id == RT_PROXY_DAI_001_TX ||
 			port_id == RT_PROXY_DAI_002_RX ||
-			port_id == RT_PROXY_DAI_002_TX)
+			port_id == RT_PROXY_DAI_002_TX ||
+			port_id == RT_PROXY_DAI_003_TX)
 			ret = VIRTUAL_ID_TO_PORTID(port_id);
 		else
 			ret = -EINVAL;

+ 2 - 1
include/dsp/q6afe-v2.h

@@ -34,6 +34,7 @@
 #define RT_PROXY_DAI_001_TX	0xF0
 #define RT_PROXY_DAI_002_RX	0xF1
 #define RT_PROXY_DAI_002_TX	0xE1
+#define RT_PROXY_DAI_003_TX	0xF2
 #define VIRTUAL_ID_TO_PORTID(val) ((val & 0xF) | 0x2000)
 
 #define AFE_CLK_VERSION_V1    1
@@ -387,7 +388,7 @@ int afe_unregister_get_events(u16 port_id);
 int afe_rt_proxy_port_write(phys_addr_t buf_addr_p,
 			u32 mem_map_handle, int bytes);
 int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
-			u32 mem_map_handle, int bytes);
+			u32 mem_map_handle, int bytes, int id);
 void afe_set_cal_mode(u16 port_id, enum afe_cal_mode afe_cal_mode);
 void afe_set_vad_cfg(u32 vad_enable, u32 preroll_config,
 		     u32 port_id);