Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41fe2559 authored by Derek Chen's avatar Derek Chen Committed by Gerrit - the friendly Code Review server
Browse files

ASoC: msm: qdsp6v2: add support for ADM_OPEN_V6 for multi-mic ec



Add support for ADM_CMD_DEVICE_OPEN_V6 when the mixer path
specifies to use the multi-mic-echo-reference, which configures
the EndPoint2 for Echo Reference.

CRs-fixed: 1022080
Change-Id: I474f39a3437fa18003f4342e003d689b95837699
Signed-off-by: default avatarDerek Chen <chenche@codeaurora.org>
parent cc957303
Loading
Loading
Loading
Loading
+144 −1
Original line number Diff line number Diff line
@@ -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,9 +256,132 @@ 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;

@@ -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
+7 −1
Original line number Diff line number Diff line
/* 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);
+128 −6
Original line number Diff line number Diff line
@@ -91,6 +91,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;
@@ -1344,6 +1347,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]
@@ -1439,7 +1443,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;

@@ -2241,10 +2246,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);
@@ -2393,10 +2452,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;
		}
@@ -2420,7 +2478,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);
@@ -2708,7 +2806,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)
@@ -4324,6 +4443,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);