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

Commit ab42ea9b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: msm: q6dspv2: vote for Glink Rx thread priority upgrade"

parents e010e7ac b918ec8e
Loading
Loading
Loading
Loading
+102 −1
Original line number Diff line number Diff line
/* Copyright (c) 2010-2014, 2016, 2018 The Linux Foundation.
/* Copyright (c) 2010-2014, 2016, 2018-2019 The Linux Foundation.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
@@ -758,6 +758,107 @@ static void apr_reset_deregister(struct work_struct *work)
	kfree(apr_reset);
}

/**
 * apr_start_rx_rt - Clients call to vote for thread
 * priority upgrade whenever needed.
 *
 * @handle: APR service handle
 *
 * Returns 0 on success or error otherwise.
 */
int apr_start_rx_rt(void *handle)
{
	int rc = 0;
	struct apr_svc *svc = handle;
	uint16_t dest_id = 0;
	uint16_t client_id = 0;

	if (!svc) {
		pr_err("%s: Invalid APR handle\n", __func__);
		return -EINVAL;
	}

	mutex_lock(&svc->m_lock);
	dest_id = svc->dest_id;
	client_id = svc->client_id;

	if ((client_id >= APR_CLIENT_MAX) || (dest_id >= APR_DEST_MAX)) {
		pr_err("%s: %s invalid. client_id = %u, dest_id = %u\n",
			__func__,
			client_id >= APR_CLIENT_MAX ? "Client ID" : "Dest ID",
			client_id, dest_id);
		rc = -EINVAL;
		goto exit;
	}

	if (!client[dest_id][client_id].handle) {
		pr_err("%s: Client handle is NULL\n", __func__);
		rc = -EINVAL;
		goto exit;
	}

	rc = apr_tal_start_rx_rt(client[dest_id][client_id].handle);
	if (rc)
		pr_err("%s: failed to set RT thread priority for APR RX. rc = %d\n",
			__func__, rc);

exit:
	mutex_unlock(&svc->m_lock);
	return rc;
}
EXPORT_SYMBOL(apr_start_rx_rt);

/**
 * apr_end_rx_rt - Clients call to unvote for thread
 * priority upgrade (perviously voted with
 * apr_start_rx_rt()).
 *
 * @handle: APR service handle
 *
 * Returns 0 on success or error otherwise.
 */
int apr_end_rx_rt(void *handle)
{
	int rc = 0;
	struct apr_svc *svc = handle;
	uint16_t dest_id = 0;
	uint16_t client_id = 0;

	if (!svc) {
		pr_err("%s: Invalid APR handle\n", __func__);
		return -EINVAL;
	}

	mutex_lock(&svc->m_lock);
	dest_id = svc->dest_id;
	client_id = svc->client_id;

	if ((client_id >= APR_CLIENT_MAX) || (dest_id >= APR_DEST_MAX)) {
		pr_err("%s: %s invalid. client_id = %u, dest_id = %u\n",
			__func__,
			client_id >= APR_CLIENT_MAX ? "Client ID" : "Dest ID",
			client_id, dest_id);
		rc = -EINVAL;
		goto exit;
	}

	if (!client[dest_id][client_id].handle) {
		pr_err("%s: Client handle is NULL\n", __func__);
		rc = -EINVAL;
		goto exit;
	}

	rc = apr_tal_end_rx_rt(client[dest_id][client_id].handle);
	if (rc)
		pr_err("%s: failed to reset RT thread priority for APR RX. rc = %d\n",
			__func__, rc);

exit:
	mutex_unlock(&svc->m_lock);
	return rc;
}
EXPORT_SYMBOL(apr_end_rx_rt);

int apr_deregister(void *handle)
{
	struct apr_svc *svc = handle;
+33 −1
Original line number Diff line number Diff line
/* Copyright (c) 2016-2017 The Linux Foundation.
/* Copyright (c) 2016-2017, 2019 The Linux Foundation.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
@@ -358,6 +358,38 @@ unlock:
	return rc ? NULL : apr_ch;
}

int apr_tal_start_rx_rt(struct apr_svc_ch_dev *apr_ch)
{
	int rc = 0;

	if (!apr_ch || !apr_ch->handle) {
		rc = -EINVAL;
		goto exit;
	}

	mutex_lock(&apr_ch->m_lock);
	rc = glink_start_rx_rt(apr_ch->handle);
	mutex_unlock(&apr_ch->m_lock);
exit:
	return rc;
}

int apr_tal_end_rx_rt(struct apr_svc_ch_dev *apr_ch)
{
	int rc = 0;

	if (!apr_ch || !apr_ch->handle) {
		rc = -EINVAL;
		goto exit;
	}

	mutex_lock(&apr_ch->m_lock);
	rc = glink_end_rx_rt(apr_ch->handle);
	mutex_unlock(&apr_ch->m_lock);
exit:
	return rc;
}

int apr_tal_close(struct apr_svc_ch_dev *apr_ch)
{
	int rc;
+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2010-2017, 2019, 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
@@ -196,4 +196,6 @@ int apr_set_q6_state(enum apr_subsys_state state);
void apr_set_subsys_state(void);
const char *apr_get_lpass_subsys_name(void);
uint16_t apr_get_reset_domain(uint16_t proc);
int apr_start_rx_rt(void *handle);
int apr_end_rx_rt(void *handle);
#endif
+9 −1
Original line number Diff line number Diff line
/* Copyright (c) 2010-2011, 2016-2017 The Linux Foundation. All rights reserved.
/* Copyright (c) 2010-2011, 2016-2017, 2019 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
@@ -78,6 +79,9 @@ int apr_tal_rx_intents_config(struct apr_svc_ch_dev *apr_ch,

#if defined(CONFIG_MSM_QDSP6_APRV2_GLINK) || \
	 defined(CONFIG_MSM_QDSP6_APRV3_GLINK)
int apr_tal_start_rx_rt(struct apr_svc_ch_dev *apr_ch);
int apr_tal_end_rx_rt(struct apr_svc_ch_dev *apr_ch);

struct apr_svc_ch_dev {
	void               *handle;
	spinlock_t         w_lock;
@@ -90,6 +94,10 @@ struct apr_svc_ch_dev {
	bool               if_remote_intent_ready;
};
#else
static inline int apr_tal_start_rx_rt(struct apr_svc_ch_dev *apr_ch)
{ return 0; }
static inline int apr_tal_end_rx_rt(struct apr_svc_ch_dev *apr_ch) { return 0; }

struct apr_svc_ch_dev {
	struct smd_channel *ch;
	spinlock_t         lock;
+22 −0
Original line number Diff line number Diff line
@@ -686,8 +686,15 @@ static int msm_pcm_open(struct snd_pcm_substream *substream)
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
	struct msm_audio *prtd;
	struct msm_plat_data *pdata;
	int ret = 0;

	pdata = (struct msm_plat_data *)
		dev_get_drvdata(soc_prtd->platform->dev);
	if (!pdata) {
		pr_err("%s: platform data not populated\n", __func__);
		return -EINVAL;
	}
	prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
	if (prtd == NULL) {
		pr_err("Failed to allocate memory for msm_audio\n");
@@ -767,6 +774,10 @@ static int msm_pcm_open(struct snd_pcm_substream *substream)
	prtd->reset_event = false;
	runtime->private_data = prtd;
	msm_adsp_init_mixer_ctl_pp_event_queue(soc_prtd);
	/* Vote to update the Rx thread priority to RT Thread for playback */
	if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
	    (pdata->perf_mode == LOW_LATENCY_PCM_MODE))
		apr_start_rx_rt(prtd->audio_client->apr);

	return 0;
}
@@ -874,6 +885,7 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
	struct msm_audio *prtd = runtime->private_data;
	struct msm_plat_data *pdata;
	uint32_t timeout;
	int dir = 0;
	int ret = 0;
@@ -883,6 +895,16 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
	if (prtd->audio_client) {
		dir = IN;

		/*
		 * Unvote to downgrade the Rx thread priority from
		 * RT Thread for Low-Latency use case.
		 */
		pdata = (struct msm_plat_data *)
			dev_get_drvdata(soc_prtd->platform->dev);
		if (pdata) {
			if (pdata->perf_mode == LOW_LATENCY_PCM_MODE)
				apr_end_rx_rt(prtd->audio_client->apr);
		}
		/* determine timeout length */
		if (runtime->frame_bits == 0 || runtime->rate == 0) {
			timeout = CMD_EOS_MIN_TIMEOUT_LENGTH;