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

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

Merge changes I914c68a9,I2003e40c into msm-4.4

* changes:
  ASoC: msm: qdsp6v2: latency mode support for transcode loopback
  ASoC: msm: volume control support for DSP transcode loopback
parents a5a9ec77 97390bee
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -138,6 +138,11 @@ struct snd_compr_audio_info {
#define SNDRV_COMPRESS_CLK_REC_MODE_NONE 0
#define SNDRV_COMPRESS_CLK_REC_MODE_AUTO 1

enum sndrv_compress_latency_mode {
	SNDRV_COMPRESS_LEGACY_LATENCY_MODE = 0,
	SNDRV_COMPRESS_LOW_LATENCY_MODE = 1,
};

/**
 * enum sndrv_compress_encoder
 * @SNDRV_COMPRESS_ENCODER_PADDING: no of samples appended by the encoder at the
@@ -164,6 +169,7 @@ enum sndrv_compress_encoder {
	SNDRV_COMPRESS_START_DELAY = 9,
	SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK = 10,
	SNDRV_COMPRESS_ADJUST_SESSION_CLOCK = 11,
	SNDRV_COMPRESS_LATENCY_MODE = 12,
};

#define SNDRV_COMPRESS_PATH_DELAY SNDRV_COMPRESS_PATH_DELAY
@@ -174,6 +180,7 @@ enum sndrv_compress_encoder {
#define SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK \
			SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK
#define SNDRV_COMPRESS_ADJUST_SESSION_CLOCK SNDRV_COMPRESS_ADJUST_SESSION_CLOCK
#define SNDRV_COMPRESS_LATENCY_MODE SNDRV_COMPRESS_LATENCY_MODE

/**
 * struct snd_compr_metadata - compressed stream metadata
+173 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <sound/control.h>
#include <sound/q6asm-v2.h>
#include <sound/q6core.h>
#include <sound/q6audio-v2.h>
#include <sound/pcm_params.h>
#include <sound/timer.h>
#include <sound/tlv.h>
@@ -41,6 +42,8 @@
#include "msm-qti-pp-config.h"

#define LOOPBACK_SESSION_MAX_NUM_STREAMS 2
/* Max volume corresponding to 24dB */
#define TRANSCODE_LR_VOL_MAX_STEPS 0xFFFF

#define APP_TYPE_CONFIG_IDX_APP_TYPE 0
#define APP_TYPE_CONFIG_IDX_ACDB_ID 1
@@ -52,6 +55,8 @@ static DEFINE_MUTEX(transcode_loopback_session_lock);
struct trans_loopback_pdata {
	struct snd_compr_stream *cstream[MSM_FRONTEND_DAI_MAX];
	int32_t ion_fd[MSM_FRONTEND_DAI_MAX];
	uint32_t master_gain;
	int perf_mode;
};

struct loopback_stream {
@@ -403,6 +408,8 @@ static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,
	struct msm_transcode_loopback *trans = runtime->private_data;
	struct snd_soc_pcm_runtime *soc_pcm_rx;
	struct snd_soc_pcm_runtime *soc_pcm_tx;
	struct snd_soc_pcm_runtime *rtd;
	struct trans_loopback_pdata *pdata;
	uint32_t bit_width = 16;
	int ret = 0;

@@ -413,6 +420,9 @@ static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,

	mutex_lock(&trans->lock);

	rtd = snd_pcm_substream_chip(cstream);
	pdata = snd_soc_platform_get_drvdata(rtd->platform);

	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
		if (codec_param->codec.id == SND_AUDIOCODEC_PCM) {
			trans->sink.codec_format =
@@ -494,7 +504,7 @@ static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,
		pr_debug("%s: ASM client allocated, callback %pK\n", __func__,
						loopback_event_handler);
		trans->session_id = trans->audio_client->session;
		trans->audio_client->perf_mode = false;
		trans->audio_client->perf_mode = pdata->perf_mode;
		ret = q6asm_open_transcode_loopback(trans->audio_client,
					bit_width,
					trans->source.codec_format,
@@ -513,7 +523,7 @@ static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,
		if (trans->source.codec_format != FORMAT_LINEAR_PCM)
			msm_pcm_routing_reg_phy_compr_stream(
					soc_pcm_tx->dai_link->be_id,
					trans->audio_client->perf_mode,
					false,
					trans->session_id,
					SNDRV_PCM_STREAM_CAPTURE,
					COMPRESSED_PASSTHROUGH_GEN);
@@ -526,7 +536,7 @@ static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,
		/* Opening Rx ADM in LOW_LATENCY mode by default */
		msm_pcm_routing_reg_phy_stream(
					soc_pcm_rx->dai_link->be_id,
					true,
					trans->audio_client->perf_mode,
					trans->session_id,
					SNDRV_PCM_STREAM_PLAYBACK);
		pr_debug("%s: Successfully opened ADM sessions\n", __func__);
@@ -559,6 +569,46 @@ static int msm_transcode_loopback_get_caps(struct snd_compr_stream *cstream,
	return 0;
}

static int msm_transcode_loopback_set_metadata(struct snd_compr_stream *cstream,
				struct snd_compr_metadata *metadata)
{
	struct snd_soc_pcm_runtime *rtd;
	struct trans_loopback_pdata *pdata;

	if (!metadata || !cstream) {
		pr_err("%s: Invalid arguments\n", __func__);
		return -EINVAL;
	}

	rtd = snd_pcm_substream_chip(cstream);
	pdata = snd_soc_platform_get_drvdata(rtd->platform);

	switch (metadata->key) {
	case SNDRV_COMPRESS_LATENCY_MODE:
	{
		switch (metadata->value[0]) {
		case SNDRV_COMPRESS_LEGACY_LATENCY_MODE:
			pdata->perf_mode = LEGACY_PCM_MODE;
			break;
		case SNDRV_COMPRESS_LOW_LATENCY_MODE:
			pdata->perf_mode = LOW_LATENCY_PCM_MODE;
			break;
		default:
			pr_debug("%s: Unsupported latency mode %d, default to Legacy\n",
					__func__, metadata->value[0]);
			pdata->perf_mode = LEGACY_PCM_MODE;
			break;
		}
	}
		break;
	default:
		pr_debug("%s: Unsupported metadata %d\n",
				__func__, metadata->key);
		break;
	}
	return 0;
}

static int msm_transcode_stream_cmd_put(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
@@ -813,6 +863,80 @@ done:
	return ret;
}

static int msm_transcode_set_volume(struct snd_compr_stream *cstream,
				uint32_t master_gain)
{
	int rc = 0;
	struct msm_transcode_loopback *prtd;
	struct snd_soc_pcm_runtime *rtd;

	pr_debug("%s: master_gain %d\n", __func__, master_gain);
	if (!cstream || !cstream->runtime) {
		pr_err("%s: session not active\n", __func__);
		return -EPERM;
	}
	rtd = cstream->private_data;
	prtd = cstream->runtime->private_data;

	if (!rtd || !rtd->platform || !prtd || !prtd->audio_client) {
		pr_err("%s: invalid rtd, prtd or audio client", __func__);
		return -EINVAL;
	}

	rc = q6asm_set_volume(prtd->audio_client, master_gain);
	if (rc < 0)
		pr_err("%s: Send vol gain command failed rc=%d\n",
		       __func__, rc);

	return rc;
}

static int msm_transcode_volume_put(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
	unsigned long fe_id = kcontrol->private_value;
	struct trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
			snd_soc_component_get_drvdata(comp);
	struct snd_compr_stream *cstream = NULL;
	uint32_t ret = 0;

	if (fe_id >= MSM_FRONTEND_DAI_MAX) {
		pr_err("%s Received out of bounds fe_id %lu\n",
			__func__, fe_id);
		return -EINVAL;
	}

	cstream = pdata->cstream[fe_id];
	pdata->master_gain = ucontrol->value.integer.value[0];

	pr_debug("%s: fe_id %lu master_gain %d\n",
		 __func__, fe_id, pdata->master_gain);
	if (cstream)
		ret = msm_transcode_set_volume(cstream, pdata->master_gain);
	return ret;
}

static int msm_transcode_volume_get(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
	unsigned long fe_id = kcontrol->private_value;

	struct trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
			snd_soc_component_get_drvdata(comp);

	if (fe_id >= MSM_FRONTEND_DAI_MAX) {
		pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id);
		return -EINVAL;
	}

	pr_debug("%s: fe_id %lu\n", __func__, fe_id);
	ucontrol->value.integer.value[0] = pdata->master_gain;

	return 0;
}

static int msm_transcode_stream_cmd_control(
			struct snd_soc_pcm_runtime *rtd)
{
@@ -1089,6 +1213,7 @@ static int msm_transcode_add_app_type_cfg_control(

	if (!rtd) {
		pr_err("%s NULL rtd\n", __func__);

		return -EINVAL;
	}

@@ -1114,6 +1239,44 @@ static int msm_transcode_add_app_type_cfg_control(

	return rc;
}
static int msm_transcode_volume_info(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = TRANSCODE_LR_VOL_MAX_STEPS;
	return 0;
}

static int msm_transcode_add_volume_control(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_kcontrol_new fe_volume_control[1] = {
		{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Transcode Loopback Rx Volume",
		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
			  SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = msm_transcode_volume_info,
		.get = msm_transcode_volume_get,
		.put = msm_transcode_volume_put,
		.private_value = 0,
		}
	};

	if (!rtd) {
		pr_err("%s NULL rtd\n", __func__);
		return -EINVAL;
	}
	if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
		fe_volume_control[0].private_value = rtd->dai_link->be_id;
		pr_debug("Registering new mixer ctl %s",
			     fe_volume_control[0].name);
		snd_soc_add_platform_controls(rtd->platform, fe_volume_control,
						ARRAY_SIZE(fe_volume_control));
	}
	return 0;
}

static int msm_transcode_loopback_new(struct snd_soc_pcm_runtime *rtd)
{
@@ -1148,6 +1311,11 @@ static int msm_transcode_loopback_new(struct snd_soc_pcm_runtime *rtd)
		pr_err("%s: Could not add Compr App Type Cfg Control\n",
			__func__);

	rc = msm_transcode_add_volume_control(rtd);
	if (rc)
		pr_err("%s: Could not add transcode volume Control\n",
			__func__);

	return 0;
}

@@ -1157,6 +1325,7 @@ static struct snd_compr_ops msm_transcode_loopback_ops = {
	.trigger		= msm_transcode_loopback_trigger,
	.set_params		= msm_transcode_loopback_set_params,
	.get_caps		= msm_transcode_loopback_get_caps,
	.set_metadata		= msm_transcode_loopback_set_metadata,
};


@@ -1171,6 +1340,7 @@ static int msm_transcode_loopback_probe(struct snd_soc_platform *platform)
	if (!pdata)
		return -ENOMEM;

	pdata->perf_mode = LOW_LATENCY_PCM_MODE;
	snd_soc_platform_set_drvdata(platform, pdata);
	return 0;
}