asoc: add new fe for hearing aid

Add a new fe dedicated for hearing aid and the support
of reading data from a new proxy port.

Change-Id: Id2e8ade6bfe5412ca6520d3cff70d6eebad7d7cc
Signed-off-by: Zhou Song <zhous@codeaurora.org>
This commit is contained in:
Zhou Song 2020-03-22 17:57:19 +08:00
commit 83c6033064
5 changed files with 79 additions and 15 deletions

View file

@ -2620,6 +2620,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);
@ -4087,6 +4088,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",
@ -7279,6 +7297,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;

View file

@ -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",

View file

@ -181,6 +181,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)))
@ -855,7 +857,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,
@ -4359,7 +4363,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",
@ -6290,7 +6310,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);
@ -6300,7 +6321,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;
}
@ -6351,7 +6373,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);
@ -6385,7 +6408,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;
}
@ -6463,14 +6487,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__);
@ -6487,7 +6513,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);
@ -7344,7 +7370,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",
@ -7444,6 +7471,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) {

View file

@ -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;

View file

@ -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);