Merge "ASoC: msm: qdsp6v2: add support for ADM_OPEN_V6 for multi-mic ec"
This commit is contained in:
commit
d089fe1071
3 changed files with 279 additions and 8 deletions
|
@ -97,6 +97,16 @@ struct adm_cmd_matrix_map_routings_v5 {
|
|||
*/
|
||||
#define ADM_CMD_DEVICE_OPEN_V5 0x00010326
|
||||
|
||||
/* This command allows a client to open a COPP/Voice Proc the
|
||||
* way as ADM_CMD_DEVICE_OPEN_V5 but supports multiple endpoint2
|
||||
* channels.
|
||||
*
|
||||
* @return
|
||||
* #ADM_CMDRSP_DEVICE_OPEN_V6 with the resulting status and
|
||||
* COPP ID.
|
||||
*/
|
||||
#define ADM_CMD_DEVICE_OPEN_V6 0x00010356
|
||||
|
||||
/* Definition for a low latency stream session. */
|
||||
#define ADM_LOW_LATENCY_DEVICE_SESSION 0x2000
|
||||
|
||||
|
@ -246,12 +256,135 @@ struct adm_cmd_device_open_v5 {
|
|||
/* Array of channel mapping of buffers that the audio COPP
|
||||
* sends to the endpoint. Channel[i] mapping describes channel
|
||||
* I inside the buffer, where 0 < i < dev_num_channel.
|
||||
* This value is relevent only for an audio Rx COPP.
|
||||
* This value is relevant only for an audio Rx COPP.
|
||||
* For the voice processor block and Tx audio block, this field
|
||||
* is set to zero and is ignored.
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
/* ADM device open command payload of the
|
||||
* #ADM_CMD_DEVICE_OPEN_V6 command.
|
||||
*/
|
||||
struct adm_cmd_device_open_v6 {
|
||||
struct apr_hdr hdr;
|
||||
u16 flags;
|
||||
/* Reserved for future use. Clients must set this field
|
||||
* to zero.
|
||||
*/
|
||||
|
||||
u16 mode_of_operation;
|
||||
/* Specifies whether the COPP must be opened on the Tx or Rx
|
||||
* path. Use the ADM_CMD_COPP_OPEN_MODE_OF_OPERATION_* macros for
|
||||
* supported values and interpretation.
|
||||
* Supported values:
|
||||
* - 0x1 -- Rx path COPP
|
||||
* - 0x2 -- Tx path live COPP
|
||||
* - 0x3 -- Tx path nonlive COPP
|
||||
* Live connections cause sample discarding in the Tx device
|
||||
* matrix if the destination output ports do not pull them
|
||||
* fast enough. Nonlive connections queue the samples
|
||||
* indefinitely.
|
||||
*/
|
||||
|
||||
u16 endpoint_id_1;
|
||||
/* Logical and physical endpoint ID of the audio path.
|
||||
* If the ID is a voice processor Tx block, it receives near
|
||||
* samples. Supported values: Any pseudoport, AFE Rx port,
|
||||
* or AFE Tx port For a list of valid IDs, refer to
|
||||
* @xhyperref{Q4,[Q4]}.
|
||||
* Q4 = Hexagon Multimedia: AFE Interface Specification
|
||||
*/
|
||||
|
||||
u16 endpoint_id_2;
|
||||
/* Logical and physical endpoint ID 2 for a voice processor
|
||||
* Tx block.
|
||||
* This is not applicable to audio COPP.
|
||||
* Supported values:
|
||||
* - AFE Rx port
|
||||
* - 0xFFFF -- Endpoint 2 is unavailable and the voice
|
||||
* processor Tx
|
||||
* block ignores this endpoint
|
||||
* When the voice processor Tx block is created on the audio
|
||||
* record path,
|
||||
* it can receive far-end samples from an AFE Rx port if the
|
||||
* voice call
|
||||
* is active. The ID of the AFE port is provided in this
|
||||
* field.
|
||||
* For a list of valid IDs, refer @xhyperref{Q4,[Q4]}.
|
||||
*/
|
||||
|
||||
u32 topology_id;
|
||||
/* Audio COPP topology ID; 32-bit GUID. */
|
||||
|
||||
u16 dev_num_channel;
|
||||
/* Number of channels the audio COPP sends to/receives from
|
||||
* the endpoint.
|
||||
* Supported values: 1 to 8.
|
||||
* The value is ignored for the voice processor Tx block,
|
||||
* where channel
|
||||
* configuration is derived from the topology ID.
|
||||
*/
|
||||
|
||||
u16 bit_width;
|
||||
/* Bit width (in bits) that the audio COPP sends to/receives
|
||||
* from the
|
||||
* endpoint. The value is ignored for the voice processing
|
||||
* Tx block,
|
||||
* where the PCM width is 16 bits.
|
||||
*/
|
||||
|
||||
u32 sample_rate;
|
||||
/* Sampling rate at which the audio COPP/voice processor
|
||||
* Tx block
|
||||
* interfaces with the endpoint.
|
||||
* Supported values for voice processor Tx: 8000, 16000,
|
||||
* 48000 Hz
|
||||
* Supported values for audio COPP: >0 and <=192 kHz
|
||||
*/
|
||||
|
||||
u8 dev_channel_mapping[8];
|
||||
/* Array of channel mapping of buffers that the audio COPP
|
||||
* sends to the endpoint. Channel[i] mapping describes channel
|
||||
* I inside the buffer, where 0 < i < dev_num_channel.
|
||||
* This value is relevant only for an audio Rx COPP.
|
||||
* For the voice processor block and Tx audio block, this field
|
||||
* is set to zero and is ignored.
|
||||
*/
|
||||
|
||||
u16 dev_num_channel_eid2;
|
||||
/* Number of channels the voice processor block sends
|
||||
* to/receives from the endpoint2.
|
||||
* Supported values: 1 to 8.
|
||||
* The value is ignored for audio COPP or if endpoint_id_2 is
|
||||
* set to 0xFFFF.
|
||||
*/
|
||||
|
||||
u16 bit_width_eid2;
|
||||
/* Bit width (in bits) that the voice processor sends
|
||||
* to/receives from the endpoint2.
|
||||
* Supported values: 16 and 24.
|
||||
* The value is ignored for audio COPP or if endpoint_id_2 is
|
||||
* set to 0xFFFF.
|
||||
*/
|
||||
|
||||
u32 sample_rate_eid2;
|
||||
/* Sampling rate at which the voice processor Tx block
|
||||
* interfaces with the endpoint2.
|
||||
* Supported values for Tx voice processor: >0 and <=384 kHz
|
||||
* The value is ignored for audio COPP or if endpoint_id_2 is
|
||||
* set to 0xFFFF.
|
||||
*/
|
||||
|
||||
u8 dev_channel_mapping_eid2[8];
|
||||
/* Array of channel mapping of buffers that the voice processor
|
||||
* sends to the endpoint. Channel[i] mapping describes channel
|
||||
* I inside the buffer, where 0 < i < dev_num_channel.
|
||||
* This value is relevant only for the Tx voice processor.
|
||||
* The values are ignored for audio COPP or if endpoint_id_2 is
|
||||
* set to 0xFFFF.
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This command allows the client to close a COPP and disconnect
|
||||
* the device session.
|
||||
|
@ -368,6 +501,16 @@ struct adm_cmd_rsp_device_open_v5 {
|
|||
/* Reserved. This field must be set to zero.*/
|
||||
} __packed;
|
||||
|
||||
/* Returns the status and COPP ID to an #ADM_CMD_DEVICE_OPEN_V6 command.
|
||||
*/
|
||||
#define ADM_CMDRSP_DEVICE_OPEN_V6 0x00010357
|
||||
|
||||
/* Payload of the #ADM_CMDRSP_DEVICE_OPEN_V6 message,
|
||||
* which returns the
|
||||
* status and COPP ID to an #ADM_CMD_DEVICE_OPEN_V6 command
|
||||
* is the exact same as ADM_CMDRSP_DEVICE_OPEN_V5.
|
||||
*/
|
||||
|
||||
/* This command allows a query of one COPP parameter.
|
||||
*/
|
||||
#define ADM_CMD_GET_PP_PARAMS_V5 0x0001032A
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -102,6 +102,12 @@ int adm_connect_afe_port(int mode, int session_id, int port_id);
|
|||
|
||||
void adm_ec_ref_rx_id(int port_id);
|
||||
|
||||
void adm_num_ec_ref_rx_chans(int num_chans);
|
||||
|
||||
void adm_ec_ref_rx_bit_width(int bit_width);
|
||||
|
||||
void adm_ec_ref_rx_sampling_rate(int sampling_rate);
|
||||
|
||||
int adm_get_lowlatency_copp_id(int port_id);
|
||||
|
||||
int adm_set_multi_ch_map(char *channel_map, int path);
|
||||
|
|
|
@ -102,6 +102,9 @@ struct adm_ctl {
|
|||
|
||||
int set_custom_topology;
|
||||
int ec_ref_rx;
|
||||
int num_ec_ref_rx_chans;
|
||||
int ec_ref_rx_bit_width;
|
||||
int ec_ref_rx_sampling_rate;
|
||||
};
|
||||
|
||||
static struct adm_ctl this_adm;
|
||||
|
@ -1355,6 +1358,7 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
|
|||
*/
|
||||
case ADM_CMD_DEVICE_OPEN_V5:
|
||||
case ADM_CMD_DEVICE_CLOSE_V5:
|
||||
case ADM_CMD_DEVICE_OPEN_V6:
|
||||
pr_debug("%s: Basic callback received, wake up.\n",
|
||||
__func__);
|
||||
atomic_set(&this_adm.copp.stat[port_idx]
|
||||
|
@ -1450,7 +1454,8 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
|
|||
}
|
||||
|
||||
switch (data->opcode) {
|
||||
case ADM_CMDRSP_DEVICE_OPEN_V5: {
|
||||
case ADM_CMDRSP_DEVICE_OPEN_V5:
|
||||
case ADM_CMDRSP_DEVICE_OPEN_V6: {
|
||||
struct adm_cmd_rsp_device_open_v5 *open =
|
||||
(struct adm_cmd_rsp_device_open_v5 *)data->payload;
|
||||
|
||||
|
@ -2257,10 +2262,64 @@ inval_ch_mod:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int adm_arrange_mch_ep2_map(struct adm_cmd_device_open_v6 *open_v6,
|
||||
int channel_mode)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
memset(open_v6->dev_channel_mapping_eid2, 0,
|
||||
PCM_FORMAT_MAX_NUM_CHANNEL);
|
||||
|
||||
if (channel_mode == 1) {
|
||||
open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FC;
|
||||
} else if (channel_mode == 2) {
|
||||
open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
|
||||
open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
|
||||
} else if (channel_mode == 3) {
|
||||
open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
|
||||
open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
|
||||
open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
|
||||
} else if (channel_mode == 4) {
|
||||
open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
|
||||
open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
|
||||
open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LS;
|
||||
open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_RS;
|
||||
} else if (channel_mode == 5) {
|
||||
open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
|
||||
open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
|
||||
open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_FC;
|
||||
open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_LS;
|
||||
open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_RS;
|
||||
} else if (channel_mode == 6) {
|
||||
open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
|
||||
open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
|
||||
open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
|
||||
open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
|
||||
open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
|
||||
open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
|
||||
} else if (channel_mode == 8) {
|
||||
open_v6->dev_channel_mapping_eid2[0] = PCM_CHANNEL_FL;
|
||||
open_v6->dev_channel_mapping_eid2[1] = PCM_CHANNEL_FR;
|
||||
open_v6->dev_channel_mapping_eid2[2] = PCM_CHANNEL_LFE;
|
||||
open_v6->dev_channel_mapping_eid2[3] = PCM_CHANNEL_FC;
|
||||
open_v6->dev_channel_mapping_eid2[4] = PCM_CHANNEL_LS;
|
||||
open_v6->dev_channel_mapping_eid2[5] = PCM_CHANNEL_RS;
|
||||
open_v6->dev_channel_mapping_eid2[6] = PCM_CHANNEL_LB;
|
||||
open_v6->dev_channel_mapping_eid2[7] = PCM_CHANNEL_RB;
|
||||
} else {
|
||||
pr_err("%s: invalid num_chan %d\n", __func__,
|
||||
channel_mode);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
|
||||
int perf_mode, uint16_t bit_width, int app_type, int acdb_id)
|
||||
{
|
||||
struct adm_cmd_device_open_v5 open;
|
||||
struct adm_cmd_device_open_v6 open_v6;
|
||||
int ret = 0;
|
||||
int port_idx, copp_idx, flags;
|
||||
int tmp_port = q6audio_get_port_id(port_id);
|
||||
|
@ -2409,10 +2468,9 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
|
|||
open.flags = flags;
|
||||
open.mode_of_operation = path;
|
||||
open.endpoint_id_1 = tmp_port;
|
||||
|
||||
if (this_adm.ec_ref_rx == -1) {
|
||||
open.endpoint_id_2 = 0xFFFF;
|
||||
} else if (this_adm.ec_ref_rx && (path != 1)) {
|
||||
|
||||
if (this_adm.ec_ref_rx && (path != 1)) {
|
||||
open.endpoint_id_2 = this_adm.ec_ref_rx;
|
||||
this_adm.ec_ref_rx = -1;
|
||||
}
|
||||
|
@ -2436,7 +2494,47 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
|
|||
|
||||
atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
|
||||
|
||||
if ((this_adm.num_ec_ref_rx_chans != 0) && (path != 1) &&
|
||||
(open.endpoint_id_2 != 0xFFFF)) {
|
||||
memcpy(&open_v6, &open,
|
||||
sizeof(struct adm_cmd_device_open_v5));
|
||||
open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
|
||||
open_v6.hdr.pkt_size = sizeof(open_v6);
|
||||
open_v6.dev_num_channel_eid2 =
|
||||
this_adm.num_ec_ref_rx_chans;
|
||||
this_adm.num_ec_ref_rx_chans = 0;
|
||||
|
||||
if (this_adm.ec_ref_rx_bit_width != 0) {
|
||||
open_v6.bit_width_eid2 =
|
||||
this_adm.ec_ref_rx_bit_width;
|
||||
this_adm.ec_ref_rx_bit_width = 0;
|
||||
} else {
|
||||
open_v6.bit_width_eid2 = bit_width;
|
||||
}
|
||||
|
||||
if (this_adm.ec_ref_rx_sampling_rate != 0) {
|
||||
open_v6.sample_rate_eid2 =
|
||||
this_adm.ec_ref_rx_sampling_rate;
|
||||
this_adm.ec_ref_rx_sampling_rate = 0;
|
||||
} else {
|
||||
open_v6.sample_rate_eid2 = rate;
|
||||
}
|
||||
|
||||
pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
|
||||
__func__, open_v6.dev_num_channel_eid2,
|
||||
open_v6.bit_width_eid2,
|
||||
open_v6.sample_rate_eid2);
|
||||
|
||||
ret = adm_arrange_mch_ep2_map(&open_v6,
|
||||
open_v6.dev_num_channel_eid2);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open_v6);
|
||||
} else {
|
||||
ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
|
||||
}
|
||||
if (ret < 0) {
|
||||
pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
|
||||
__func__, tmp_port, port_id, ret);
|
||||
|
@ -2729,7 +2827,28 @@ fail_cmd:
|
|||
void adm_ec_ref_rx_id(int port_id)
|
||||
{
|
||||
this_adm.ec_ref_rx = port_id;
|
||||
pr_debug("%s: ec_ref_rx:%d", __func__, this_adm.ec_ref_rx);
|
||||
pr_debug("%s: ec_ref_rx:%d\n", __func__, this_adm.ec_ref_rx);
|
||||
}
|
||||
|
||||
void adm_num_ec_ref_rx_chans(int num_chans)
|
||||
{
|
||||
this_adm.num_ec_ref_rx_chans = num_chans;
|
||||
pr_debug("%s: num_ec_ref_rx_chans:%d\n",
|
||||
__func__, this_adm.num_ec_ref_rx_chans);
|
||||
}
|
||||
|
||||
void adm_ec_ref_rx_bit_width(int bit_width)
|
||||
{
|
||||
this_adm.ec_ref_rx_bit_width = bit_width;
|
||||
pr_debug("%s: ec_ref_rx_bit_width:%d\n",
|
||||
__func__, this_adm.ec_ref_rx_bit_width);
|
||||
}
|
||||
|
||||
void adm_ec_ref_rx_sampling_rate(int sampling_rate)
|
||||
{
|
||||
this_adm.ec_ref_rx_sampling_rate = sampling_rate;
|
||||
pr_debug("%s: ec_ref_rx_sampling_rate:%d\n",
|
||||
__func__, this_adm.ec_ref_rx_sampling_rate);
|
||||
}
|
||||
|
||||
int adm_close(int port_id, int perf_mode, int copp_idx)
|
||||
|
@ -4345,6 +4464,9 @@ static int __init adm_init(void)
|
|||
int i = 0, j;
|
||||
this_adm.apr = NULL;
|
||||
this_adm.ec_ref_rx = -1;
|
||||
this_adm.num_ec_ref_rx_chans = 0;
|
||||
this_adm.ec_ref_rx_bit_width = 0;
|
||||
this_adm.ec_ref_rx_sampling_rate = 0;
|
||||
atomic_set(&this_adm.matrix_map_stat, 0);
|
||||
init_waitqueue_head(&this_adm.matrix_map_wait);
|
||||
atomic_set(&this_adm.adm_stat, 0);
|
||||
|
|
Loading…
Add table
Reference in a new issue