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

Commit 9f7a305e authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "q6asm: retry asm_open_read and asm_open_loopback during session id conflict"

parents b2e69804 da0a39d6
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -345,11 +345,12 @@ static int msm_pcm_open(struct snd_pcm_substream *substream)
		}

		pcm->audio_client->fedai_id = rtd->dai_link->id;
		pcm->session_id = pcm->audio_client->session;
		pcm->audio_client->perf_mode = pdata->perf_mode;
		pcm->audio_client->stream_type = substream->stream;
		ret = q6asm_open_loopback_v2(pcm->audio_client,
		ret = q6asm_open_loopback_with_retry(pcm->audio_client,
					bits_per_sample);
		pcm->session_id = pcm->audio_client->session;

		if (ret < 0) {
			dev_err(component->dev,
				"%s: pcm out open failed\n", __func__);

asoc/msm-pcm-q6-v2.c

100644 → 100755
+4 −18
Original line number Diff line number Diff line
@@ -435,15 +435,8 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
			return -ENOMEM;
		}
	} else {
		if ((q6core_get_avcs_api_version_per_service(
				APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
				ADSP_ASM_API_VERSION_V2))
			ret = q6asm_open_write_v5(prtd->audio_client,
		ret = q6asm_open_write_with_retry(prtd->audio_client,
				fmt_type, bits_per_sample);
		else
			ret = q6asm_open_write_v4(prtd->audio_client,
				fmt_type, bits_per_sample);

		if (ret < 0) {
			pr_err("%s: q6asm_open_write failed (%d)\n",
			__func__, ret);
@@ -576,16 +569,9 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
		prtd->audio_client->stream_type = SNDRV_PCM_STREAM_CAPTURE;
		prtd->audio_client->fedai_id = soc_prtd->dai_link->id;

		if ((q6core_get_avcs_api_version_per_service(
				APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
				ADSP_ASM_API_VERSION_V2))
			ret = q6asm_open_read_v5(prtd->audio_client,
				FORMAT_LINEAR_PCM,
				bits_per_sample, false, ENC_CFG_ID_NONE);
		else
			ret = q6asm_open_read_v4(prtd->audio_client,
		ret = q6asm_open_read_with_retry(prtd->audio_client,
					FORMAT_LINEAR_PCM,
				bits_per_sample, false, ENC_CFG_ID_NONE);
					bits_per_sample, false);
		if (ret < 0) {
			pr_err("%s: q6asm_open_read failed\n", __func__);
			q6asm_audio_client_free(prtd->audio_client);
+213 −39
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ struct audio_session {
	struct audio_client *ac;
	spinlock_t session_lock;
	struct mutex mutex_lock_per_session;
	bool ignore;
};
/* session id: 0 reserved */
static struct audio_session session[ASM_ACTIVE_STREAMS_ALLOWED + 1];
@@ -585,6 +586,87 @@ static int q6asm_session_alloc(struct audio_client *ac)
	return -ENOMEM;
}

static void q6asm_session_set_ignore(int id)
{
	session[id].ignore = true;
}

static void q6asm_session_clean_ignore(void)
{
	int i;

	for (i = 1; i <= ASM_ACTIVE_STREAMS_ALLOWED; i++)
		session[i].ignore = false;
}

static void q6asm_session_deregister(struct audio_client *ac)
{
	rtac_set_asm_handle(ac->session, NULL);
	apr_deregister(ac->apr2);
	apr_deregister(ac->apr);
	q6asm_mmap_apr_dereg();
	ac->apr2 = NULL;
	ac->apr = NULL;
	ac->mmap_apr = NULL;
}

static int q6asm_session_register(struct audio_client *ac)
{
	ac->apr = apr_register("ADSP", "ASM",
			(apr_fn)q6asm_callback,
			((ac->session) << 8 | 0x0001),
			ac);
	if (ac->apr == NULL) {
		pr_err("%s: Registration with APR failed\n", __func__);
		goto fail_apr1;
	}

	ac->apr2 = apr_register("ADSP", "ASM",
			(apr_fn)q6asm_callback,
			((ac->session) << 8 | 0x0002),
			ac);
	if (ac->apr2 == NULL) {
		pr_err("%s: Registration with APR-2 failed\n", __func__);
		goto fail_apr2;
	}

	rtac_set_asm_handle(ac->session, ac->apr);

	pr_debug("%s: Registering the common port with APR\n", __func__);
	ac->mmap_apr = q6asm_mmap_apr_reg();
	if (ac->mmap_apr == NULL)
		goto fail_mmap;

	return 0;

fail_mmap:
	apr_deregister(ac->apr2);
fail_apr2:
	apr_deregister(ac->apr);
fail_apr1:
	return -EINVAL;
}

static int q6asm_session_try_next(struct audio_client *ac)
{
	int n;
	int s = ac->session;

	for (n = 1; n <= ASM_ACTIVE_STREAMS_ALLOWED; n++) {
		if (++s > ASM_ACTIVE_STREAMS_ALLOWED)
			s -= ASM_ACTIVE_STREAMS_ALLOWED;
		if (!session[s].ignore && !session[s].ac) {
			q6asm_session_deregister(ac);
			session[ac->session].ac = NULL;
			session[s].ac = ac;
			ac->session = s;
			return q6asm_session_register(ac);
		}
	}
	pr_debug("%s: session not available\n", __func__);
	return -EINVAL;
}

static int q6asm_get_session_id_from_audio_client(struct audio_client *ac)
{
	int n;
@@ -1225,13 +1307,7 @@ void q6asm_audio_client_free(struct audio_client *ac)
		}
	}

	rtac_set_asm_handle(ac->session, NULL);
	apr_deregister(ac->apr2);
	apr_deregister(ac->apr);
	q6asm_mmap_apr_dereg();
	ac->apr2 = NULL;
	ac->apr = NULL;
	ac->mmap_apr = NULL;
	q6asm_session_deregister(ac);
	q6asm_session_free(ac);

	pr_debug("%s: APR De-Register\n", __func__);
@@ -1436,34 +1512,11 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
	ac->fptr_cache_ops = NULL;
	/* DSP expects stream id from 1 */
	ac->stream_id = 1;
	ac->apr = apr_register("ADSP", "ASM",
			(apr_fn)q6asm_callback,
			((ac->session) << 8 | 0x0001),
			ac);

	if (ac->apr == NULL) {
		pr_err("%s: Registration with APR failed\n", __func__);
		mutex_unlock(&session_lock);
		goto fail_apr1;
	}
	ac->apr2 = apr_register("ADSP", "ASM",
			(apr_fn)q6asm_callback,
			((ac->session) << 8 | 0x0002),
			ac);

	if (ac->apr2 == NULL) {
		pr_err("%s: Registration with APR-2 failed\n", __func__);
		mutex_unlock(&session_lock);
		goto fail_apr2;
	}

	rtac_set_asm_handle(n, ac->apr);

	pr_debug("%s: Registering the common port with APR\n", __func__);
	ac->mmap_apr = q6asm_mmap_apr_reg();
	if (ac->mmap_apr == NULL) {
	rc = q6asm_session_register(ac);
	if (rc < 0) {
		mutex_unlock(&session_lock);
		goto fail_mmap;
		goto fail_register;
	}

	init_waitqueue_head(&ac->cmd_wait);
@@ -1486,7 +1539,7 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
	rc = send_asm_custom_topology(ac);
	if (rc < 0) {
		mutex_unlock(&session_lock);
		goto fail_mmap;
		goto fail_send;
	}

	pr_debug("%s: session[%d]\n", __func__, ac->session);
@@ -1494,11 +1547,9 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
	mutex_unlock(&session_lock);

	return ac;
fail_mmap:
	apr_deregister(ac->apr2);
fail_apr2:
	apr_deregister(ac->apr);
fail_apr1:
fail_send:
	q6asm_session_deregister(ac);
fail_register:
	q6asm_session_free(ac);
fail_session:
	return NULL;
@@ -3425,6 +3476,53 @@ int q6asm_open_read_v5(struct audio_client *ac, uint32_t format,
}
EXPORT_SYMBOL(q6asm_open_read_v5);

static int q6asm_open_read_version_adaptor(struct audio_client *ac,
			uint32_t format, uint16_t bits_per_sample, bool ts_mode)
{
	if (q6core_get_avcs_api_version_per_service(
			APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
			ADSP_ASM_API_VERSION_V2)
		return q6asm_open_read_v5(ac, FORMAT_LINEAR_PCM,
						bits_per_sample, false, ENC_CFG_ID_NONE);
	else
		return q6asm_open_read_v4(ac, FORMAT_LINEAR_PCM,
						bits_per_sample, false, ENC_CFG_ID_NONE);
}

/*
 * q6asm_open_read_with_retry - Opens audio capture session, with retrying
 * in case of session ID conflict
 *
 * @ac: Client session handle
 * @format: encoder format
 * @bits_per_sample: bit width of capture session
 * @ts_mode: timestamp mode
 */
int q6asm_open_read_with_retry(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample, bool ts_mode)
{
	int i, rc;

	mutex_lock(&session_lock);
	for (i = 0; i < ASM_ACTIVE_STREAMS_ALLOWED; i++) {
		rc = q6asm_open_read_version_adaptor(ac, format,
				bits_per_sample, ts_mode);
		if (rc != -EALREADY)
			break;

		pr_debug("%s: session %d is occupied, try next\n",
				__func__, ac->session);
		q6asm_session_set_ignore(ac->session);
		rc = q6asm_session_try_next(ac);
		if (rc < 0)
			break;
	}
	q6asm_session_clean_ignore();
	mutex_unlock(&session_lock);

	return rc;
}
EXPORT_SYMBOL(q6asm_open_read_with_retry);

/**
 * q6asm_open_write_compressed -
@@ -3756,6 +3854,51 @@ int q6asm_open_write_v4(struct audio_client *ac, uint32_t format,
}
EXPORT_SYMBOL(q6asm_open_write_v4);

static int q6asm_open_write_version_adaptor(struct audio_client *ac,
			uint32_t format, uint16_t bits_per_sample)
{
	if (q6core_get_avcs_api_version_per_service(
			APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
			ADSP_ASM_API_VERSION_V2)
		return q6asm_open_write_v5(ac, format, bits_per_sample);
	else
		return q6asm_open_write_v4(ac, format, bits_per_sample);
}

/*
 * q6asm_open_write_with_retry - Opens audio playback session, with retrying
 * in case of session ID conflict
 *
 * @ac: Client session handle
 * @format: decoder format
 * @bits_per_sample: bit width of playback session
 */
int q6asm_open_write_with_retry(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample)
{
	int i, rc;

	mutex_lock(&session_lock);
	for (i = 0; i < ASM_ACTIVE_STREAMS_ALLOWED; i++) {
		rc = q6asm_open_write_version_adaptor(ac, format,
						bits_per_sample);
		if (rc != -EALREADY)
			break;

		pr_debug("%s: session %d is occupied, try next\n",
				__func__, ac->session);
		q6asm_session_set_ignore(ac->session);
		rc = q6asm_session_try_next(ac);
		if (rc < 0)
			break;
	}
	q6asm_session_clean_ignore();
	mutex_unlock(&session_lock);

	return rc;
}
EXPORT_SYMBOL(q6asm_open_write_with_retry);

int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format,
			       uint16_t bits_per_sample, int32_t stream_id,
			       bool is_gapless_mode)
@@ -4168,6 +4311,37 @@ int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample)
}
EXPORT_SYMBOL(q6asm_open_loopback_v2);

/*
 * q6asm_open_loopback_with_retry - Opens audio loopback session, with retrying
 * in case of session ID conflict
 *
 * @ac: Client session handle
 * @bits_per_sample: bit width of sample
 */
int q6asm_open_loopback_with_retry(struct audio_client *ac,
				uint16_t bits_per_sample)
{
	int i, rc;

	mutex_lock(&session_lock);
	for (i = 0; i < ASM_ACTIVE_STREAMS_ALLOWED; i++) {
		rc = q6asm_open_loopback_v2(ac, bits_per_sample);
		if (rc != -EALREADY)
			break;
		pr_debug("%s: session %d is occupied, try next\n",
					__func__, ac->session);
		q6asm_session_set_ignore(ac->session);
		rc = q6asm_session_try_next(ac);
		if (rc < 0)
			break;
	}
	q6asm_session_clean_ignore();
	mutex_unlock(&session_lock);

	return rc;
}
EXPORT_SYMBOL(q6asm_open_loopback_with_retry);

/**
 * q6asm_open_transcode_loopback -
 *       command to open ASM in transcode loopback mode
+9 −0
Original line number Diff line number Diff line
@@ -304,6 +304,9 @@ int q6asm_open_read_v5(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample, bool ts_mode,
			uint32_t enc_cfg_id);

int q6asm_open_read_with_retry(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample, bool ts_mode);

int q6asm_open_write(struct audio_client *ac, uint32_t format
		/*, uint16_t bits_per_sample*/);

@@ -323,6 +326,9 @@ int q6asm_open_write_v4(struct audio_client *ac, uint32_t format,
int q6asm_open_write_v5(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample);

int q6asm_open_write_with_retry(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample);

int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format,
			       uint16_t bits_per_sample, int32_t stream_id,
			       bool is_gapless_mode);
@@ -357,6 +363,9 @@ int q6asm_open_read_write_v2(struct audio_client *ac, uint32_t rd_format,
int q6asm_open_loopback_v2(struct audio_client *ac,
			   uint16_t bits_per_sample);

int q6asm_open_loopback_with_retry(struct audio_client *ac,
			   uint16_t bits_per_sample);

int q6asm_open_transcode_loopback(struct audio_client *ac,
			   uint16_t bits_per_sample, uint32_t source_format,
			   uint32_t sink_format);