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

Commit 1d28145c authored by Chaithanya Krishna Bacharaju's avatar Chaithanya Krishna Bacharaju Committed by Gerrit - the friendly Code Review server
Browse files

ASoC: msm: qdsp6v2: Extend LSM support to 48khz, 24bit and 4 channel



Enhance LSM code to support maximum configuration of 48khz, 24bit
and 4 channel.

Change-Id: I03895c983527d87389ca69e85235b1def5b4a2fa
Signed-off-by: default avatarChaithanya Krishna Bacharaju <chaithan@codeaurora.org>
Signed-off-by: default avatarRevathi Uddaraju <revathiu@codeaurora.org>
parent 078c3505
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -8369,6 +8369,7 @@ struct asm_dts_eagle_param_get {
#define LSM_PARAM_ID_SWMAD_MODEL			(0x00012C19)
#define LSM_PARAM_ID_SWMAD_ENABLE			(0x00012C1A)
#define LSM_PARAM_ID_POLLING_ENABLE			(0x00012C1B)
#define LSM_PARAM_ID_MEDIA_FMT				(0x00012C1E)
#define LSM_PARAM_ID_FWK_MODE_CONFIG			(0x00012C27)

/* HW MAD specific */
+22 −2
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@

#define ADM_LSM_PORT_ID 0xADCB

#define LSM_MAX_NUM_CHANNELS 8

typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token,
		       uint32_t *payload, void *priv);

@@ -51,11 +53,12 @@ struct lsm_lab_buffer {
	uint32_t mem_map_handle;
};

struct lsm_lab_hw_params {
struct lsm_hw_params {
	u16 sample_rate;
	u16 sample_size;
	u32 buf_sz;
	u32 period_count;
	u16 num_chs;
};

struct lsm_client {
@@ -81,7 +84,7 @@ struct lsm_client {
	bool		lab_enable;
	bool		lab_started;
	struct lsm_lab_buffer *lab_buffer;
	struct lsm_lab_hw_params hw_params;
	struct lsm_hw_params hw_params;
	bool		use_topology;
	int		session_state;
	bool		poll_enable;
@@ -153,6 +156,15 @@ struct lsm_param_fwk_mode_cfg {
	uint32_t	mode;
} __packed;

struct lsm_param_media_fmt {
	struct lsm_param_payload_common common;
	uint32_t	minor_version;
	uint32_t	sample_rate;
	uint16_t	num_channels;
	uint16_t	bit_width;
	uint8_t		channel_mapping[LSM_MAX_NUM_CHANNELS];
} __packed;

/*
 * This param cannot be sent in this format.
 * The actual number of confidence level values
@@ -285,6 +297,13 @@ struct lsm_cmd_set_fwk_mode_cfg {
	struct lsm_param_fwk_mode_cfg fwk_mode_cfg;
} __packed;

struct lsm_cmd_set_media_fmt {
	struct apr_hdr  msg_hdr;
	struct lsm_set_params_hdr params_hdr;
	struct lsm_param_media_fmt media_fmt;
} __packed;


struct lsm_client *q6lsm_client_alloc(lsm_app_cb cb, void *priv);
void q6lsm_client_free(struct lsm_client *client);
int q6lsm_open(struct lsm_client *client, uint16_t app_id);
@@ -316,4 +335,5 @@ void q6lsm_sm_set_param_data(struct lsm_client *client,
int q6lsm_set_port_connected(struct lsm_client *client);
int q6lsm_polling_enable(struct lsm_client *client, bool poll_enable);
int q6lsm_set_fwk_mode_cfg(struct lsm_client *client, uint32_t event_mode);
int q6lsm_set_media_fmt_params(struct lsm_client *client);
#endif /* __Q6LSM_H__ */
+48 −32
Original line number Diff line number Diff line
@@ -2127,12 +2127,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
		.capture = {
			.stream_name = "Listen 1 Audio Service Capture",
			.aif_name = "LSM1_UL_HL",
			.rates = SNDRV_PCM_RATE_16000,
			.formats = SNDRV_PCM_FMTBIT_S16_LE,
			.rates = (SNDRV_PCM_RATE_16000 |
				  SNDRV_PCM_RATE_48000),
			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
				    SNDRV_PCM_FMTBIT_S24_LE),
			.channels_min = 1,
			.channels_max = 1,
			.channels_max = 4,
			.rate_min = 16000,
			.rate_max = 16000,
			.rate_max = 48000,
		},
		.ops = &msm_fe_dai_ops,
		.name = "LSM1",
@@ -2142,12 +2144,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
		.capture = {
			.stream_name = "Listen 2 Audio Service Capture",
			.aif_name = "LSM2_UL_HL",
			.rates = SNDRV_PCM_RATE_16000,
			.formats = SNDRV_PCM_FMTBIT_S16_LE,
			.rates = (SNDRV_PCM_RATE_16000 |
				  SNDRV_PCM_RATE_48000),
			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
				    SNDRV_PCM_FMTBIT_S24_LE),
			.channels_min = 1,
			.channels_max = 1,
			.channels_max = 4,
			.rate_min = 16000,
			.rate_max = 16000,
			.rate_max = 48000,
		},
		.ops = &msm_fe_dai_ops,
		.name = "LSM2",
@@ -2157,12 +2161,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
		.capture = {
			.stream_name = "Listen 3 Audio Service Capture",
			.aif_name = "LSM3_UL_HL",
			.rates = SNDRV_PCM_RATE_16000,
			.formats = SNDRV_PCM_FMTBIT_S16_LE,
			.rates = (SNDRV_PCM_RATE_16000 |
				  SNDRV_PCM_RATE_48000),
			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
				    SNDRV_PCM_FMTBIT_S24_LE),
			.channels_min = 1,
			.channels_max = 1,
			.channels_max = 4,
			.rate_min = 16000,
			.rate_max = 16000,
			.rate_max = 48000,
		},
		.ops = &msm_fe_dai_ops,
		.name = "LSM3",
@@ -2172,12 +2178,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
		.capture = {
			.stream_name = "Listen 4 Audio Service Capture",
			.aif_name = "LSM4_UL_HL",
			.rates = SNDRV_PCM_RATE_16000,
			.formats = SNDRV_PCM_FMTBIT_S16_LE,
			.rates = (SNDRV_PCM_RATE_16000 |
				  SNDRV_PCM_RATE_48000),
			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
				    SNDRV_PCM_FMTBIT_S24_LE),
			.channels_min = 1,
			.channels_max = 1,
			.channels_max = 4,
			.rate_min = 16000,
			.rate_max = 16000,
			.rate_max = 48000,
		},
		.ops = &msm_fe_dai_ops,
		.name = "LSM4",
@@ -2187,12 +2195,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
		.capture = {
			.stream_name = "Listen 5 Audio Service Capture",
			.aif_name = "LSM5_UL_HL",
			.rates = SNDRV_PCM_RATE_16000,
			.formats = SNDRV_PCM_FMTBIT_S16_LE,
			.rates = (SNDRV_PCM_RATE_16000 |
				  SNDRV_PCM_RATE_48000),
			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
				    SNDRV_PCM_FMTBIT_S24_LE),
			.channels_min = 1,
			.channels_max = 1,
			.channels_max = 4,
			.rate_min = 16000,
			.rate_max = 16000,
			.rate_max = 48000,
		},
		.ops = &msm_fe_dai_ops,
		.name = "LSM5",
@@ -2202,12 +2212,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
		.capture = {
			.stream_name = "Listen 6 Audio Service Capture",
			.aif_name = "LSM6_UL_HL",
			.rates = SNDRV_PCM_RATE_16000,
			.formats = SNDRV_PCM_FMTBIT_S16_LE,
			.rates = (SNDRV_PCM_RATE_16000 |
				  SNDRV_PCM_RATE_48000),
			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
				    SNDRV_PCM_FMTBIT_S24_LE),
			.channels_min = 1,
			.channels_max = 1,
			.channels_max = 4,
			.rate_min = 16000,
			.rate_max = 16000,
			.rate_max = 48000,
		},
		.ops = &msm_fe_dai_ops,
		.name = "LSM6",
@@ -2217,12 +2229,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
		.capture = {
			.stream_name = "Listen 7 Audio Service Capture",
			.aif_name = "LSM7_UL_HL",
			.rates = SNDRV_PCM_RATE_16000,
			.formats = SNDRV_PCM_FMTBIT_S16_LE,
			.rates = (SNDRV_PCM_RATE_16000 |
				  SNDRV_PCM_RATE_48000),
			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
				    SNDRV_PCM_FMTBIT_S24_LE),
			.channels_min = 1,
			.channels_max = 1,
			.channels_max = 4,
			.rate_min = 16000,
			.rate_max = 16000,
			.rate_max = 48000,
		},
		.ops = &msm_fe_dai_ops,
		.name = "LSM7",
@@ -2232,12 +2246,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
		.capture = {
			.stream_name = "Listen 8 Audio Service Capture",
			.aif_name = "LSM8_UL_HL",
			.rates = SNDRV_PCM_RATE_16000,
			.formats = SNDRV_PCM_FMTBIT_S16_LE,
			.rates = (SNDRV_PCM_RATE_16000 |
				  SNDRV_PCM_RATE_48000),
			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
				    SNDRV_PCM_FMTBIT_S24_LE),
			.channels_min = 1,
			.channels_max = 1,
			.channels_max = 4,
			.rate_min = 16000,
			.rate_max = 16000,
			.rate_max = 48000,
		},
		.ops = &msm_fe_dai_ops,
		.name = "LSM8",
+36 −19
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@

#define CAPTURE_MIN_NUM_PERIODS     2
#define CAPTURE_MAX_NUM_PERIODS     8
#define CAPTURE_MAX_PERIOD_SIZE     4096
#define CAPTURE_MAX_PERIOD_SIZE     61440
#define CAPTURE_MIN_PERIOD_SIZE     320
#define LISTEN_MAX_STATUS_PAYLOAD_SIZE 256

@@ -53,12 +53,14 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = {
				SNDRV_PCM_INFO_BLOCK_TRANSFER |
				SNDRV_PCM_INFO_INTERLEAVED |
				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
	.formats =              SNDRV_PCM_FMTBIT_S16_LE,
	.rates =                SNDRV_PCM_RATE_16000,
	.formats =              (SNDRV_PCM_FMTBIT_S16_LE |
				SNDRV_PCM_FMTBIT_S24_LE),
	.rates =		(SNDRV_PCM_RATE_16000 |
				SNDRV_PCM_RATE_48000),
	.rate_min =             16000,
	.rate_max =             16000,
	.rate_max =             48000,
	.channels_min =         1,
	.channels_max =         1,
	.channels_max =         4,
	.buffer_bytes_max =     CAPTURE_MAX_NUM_PERIODS *
				CAPTURE_MAX_PERIOD_SIZE,
	.period_bytes_min =	CAPTURE_MIN_PERIOD_SIZE,
@@ -70,7 +72,7 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = {

/* Conventional and unconventional sample rate supported */
static unsigned int supported_sample_rates[] = {
	16000,
	16000, 48000,
};

static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
@@ -2033,6 +2035,10 @@ static int msm_lsm_prepare(struct snd_pcm_substream *substream)
		return -EINVAL;
	}

	if (q6lsm_set_media_fmt_params(prtd->lsm_client))
		dev_dbg(rtd->dev,
			"%s: failed to set lsm media fmt params\n", __func__);

	if (prtd->lsm_client->session_state == IDLE) {
		ret = msm_pcm_routing_reg_phy_compr_stream(
				rtd->dai_link->be_id,
@@ -2124,7 +2130,7 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream,
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct lsm_priv *prtd = runtime->private_data;
	struct lsm_lab_hw_params *hw_params = NULL;
	struct lsm_hw_params *hw_params = NULL;
	struct snd_soc_pcm_runtime *rtd;

	if (!substream->private_data) {
@@ -2140,25 +2146,36 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream,
		return -EINVAL;
	}
	hw_params = &prtd->lsm_client->hw_params;
	hw_params->sample_rate = params_rate(params);
	hw_params->sample_size =
	(params_format(params) == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 0;
	hw_params->num_chs = params_channels(params);
	hw_params->period_count = params_periods(params);
	if (hw_params->sample_rate != 16000 || hw_params->sample_size != 16 ||
		hw_params->period_count == 0) {
	hw_params->sample_rate = params_rate(params);
	if (((hw_params->sample_rate != 16000) &&
		(hw_params->sample_rate != 48000)) ||
		(hw_params->period_count == 0)) {
		dev_err(rtd->dev,
			"%s: Invalid params sample rate %d sample size %d period count %d",
			"%s: Invalid Params sample rate %d period count %d\n",
			__func__, hw_params->sample_rate,
			hw_params->sample_size,
			hw_params->period_count);
		return -EINVAL;
	}

	if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) {
		hw_params->sample_size = 16;
	} else if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE) {
		hw_params->sample_size = 24;
	} else {
		dev_err(rtd->dev, "%s: Invalid Format 0x%x\n",
			__func__, params_format(params));
		return -EINVAL;
	}

	hw_params->buf_sz = params_buffer_bytes(params) /
			hw_params->period_count;
	dev_dbg(rtd->dev,
		"%s: sample rate %d sample size %d buffer size %d period count %d\n",
		__func__, hw_params->sample_rate, hw_params->sample_size,
		hw_params->buf_sz, hw_params->period_count);
		"%s: channels %d sample rate %d sample size %d buffer size %d period count %d\n",
		__func__, hw_params->num_chs, hw_params->sample_rate,
		hw_params->sample_size, hw_params->buf_sz,
		hw_params->period_count);
	return 0;
}

+94 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@
#define LSM_ALIGN_BOUNDARY 512
#define LSM_SAMPLE_RATE 16000
#define QLSM_PARAM_ID_MINOR_VERSION 1
#define QLSM_PARAM_ID_MINOR_VERSION_2 2

static int lsm_afe_port;

enum {
@@ -912,6 +914,98 @@ int q6lsm_set_fwk_mode_cfg(struct lsm_client *client,
	return rc;
}

static int q6lsm_arrange_mch_map(struct lsm_param_media_fmt *media_fmt,
			 int channel_count)
{
	int rc = 0;

	memset(media_fmt->channel_mapping, 0, LSM_MAX_NUM_CHANNELS);

	switch (channel_count) {
	case 1:
		media_fmt->channel_mapping[0] = PCM_CHANNEL_FC;
		break;
	case 2:
		media_fmt->channel_mapping[0] = PCM_CHANNEL_FL;
		media_fmt->channel_mapping[1] = PCM_CHANNEL_FR;
		break;
	case 3:
		media_fmt->channel_mapping[0] = PCM_CHANNEL_FL;
		media_fmt->channel_mapping[1] = PCM_CHANNEL_FR;
		media_fmt->channel_mapping[2] = PCM_CHANNEL_FC;
		break;
	case 4:
		media_fmt->channel_mapping[0] = PCM_CHANNEL_FL;
		media_fmt->channel_mapping[1] = PCM_CHANNEL_FR;
		media_fmt->channel_mapping[2] = PCM_CHANNEL_LS;
		media_fmt->channel_mapping[3] = PCM_CHANNEL_RS;
		break;
	default:
		pr_err("%s: invalid num_chan %d\n", __func__, channel_count);
		rc = -EINVAL;
		break;
	}
	return rc;
}

int q6lsm_set_media_fmt_params(struct lsm_client *client)
{
	int rc = 0;
	struct lsm_cmd_set_media_fmt cmd;
	struct lsm_module_param_ids media_fmt_ids;
	struct apr_hdr  *msg_hdr;
	struct lsm_param_media_fmt *media_fmt;
	u32 data_payload_size, param_size, set_param_opcode;
	struct lsm_hw_params param = client->hw_params;

	if (client->use_topology) {
		set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2;
		media_fmt_ids.module_id = LSM_MODULE_ID_FRAMEWORK;
		media_fmt_ids.param_id = LSM_PARAM_ID_MEDIA_FMT;
	} else {
		pr_debug("%s: Ignore sending media format\n", __func__);
		goto err_ret;
	}

	msg_hdr = &cmd.msg_hdr;
	q6lsm_add_hdr(client, msg_hdr,
		      sizeof(struct lsm_cmd_set_media_fmt), true);
	msg_hdr->opcode = set_param_opcode;
	data_payload_size = sizeof(struct lsm_cmd_set_media_fmt) -
			    sizeof(struct apr_hdr) -
			    sizeof(struct lsm_set_params_hdr);
	q6lsm_set_param_hdr_info(&cmd.params_hdr,
				 data_payload_size, 0, 0, 0);
	media_fmt = &cmd.media_fmt;

	param_size = (sizeof(struct lsm_param_media_fmt) -
		      sizeof(media_fmt->common));
	q6lsm_set_param_common(&media_fmt->common,
			       &media_fmt_ids, param_size,
			       set_param_opcode);

	media_fmt->minor_version = QLSM_PARAM_ID_MINOR_VERSION_2;
	media_fmt->sample_rate = param.sample_rate;
	media_fmt->num_channels = param.num_chs;
	media_fmt->bit_width = param.sample_size;

	rc = q6lsm_arrange_mch_map(media_fmt, media_fmt->num_channels);
	if (rc)
		goto err_ret;

	pr_debug("%s: sample rate= %d, channels %d bit width %d\n",
		 __func__, media_fmt->sample_rate, media_fmt->num_channels,
		 media_fmt->bit_width);

	rc = q6lsm_apr_send_pkt(client, client->apr,
				&cmd, true, NULL);
	if (rc)
		pr_err("%s: Failed set_params opcode 0x%x, rc %d\n",
		       __func__, msg_hdr->opcode, rc);
err_ret:
	return rc;
}

int q6lsm_set_data(struct lsm_client *client,
			   enum lsm_detection_mode mode,
			   bool detectfailure)