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

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

Merge "asoc: support non-runtime per-stream, per-device asm channel map"

parents 4cab09cf 3987721c
Loading
Loading
Loading
Loading

asoc/msm-compress-q6-v2.c

100755 → 100644
+1 −0
Original line number Diff line number Diff line
@@ -1886,6 +1886,7 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
			ret = q6asm_enc_cfg_blk_pcm_format_support_v5(
					prtd->audio_client,
					prtd->sample_rate, prtd->num_channels,
					true, NULL,
					bits_per_sample, sample_word_size,
					ASM_LITTLE_ENDIAN, DEFAULT_QF);
		else
+145 −70
Original line number Diff line number Diff line
@@ -59,6 +59,11 @@ struct snd_msm {
	struct snd_pcm *pcm;
};

struct msm_pcm_channel_map {
	bool set_channel_map;
	char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
};

#define CMD_EOS_MIN_TIMEOUT_LENGTH  50
#define CMD_EOS_TIMEOUT_MULTIPLIER  (HZ * 50)
#define MAX_PB_COPY_RETRIES         3
@@ -123,6 +128,8 @@ static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
	.mask = 0,
};

struct msm_pcm_channel_map *chmap_pspd[MSM_FRONTEND_DAI_MM_SIZE][2];

static void msm_pcm_route_event_handler(enum msm_pcm_routing_event event,
					void *priv_data)
{
@@ -324,6 +331,23 @@ static void event_handler(uint32_t opcode,
	}
}

static struct msm_pcm_channel_map *msm_pcm_get_chmap(u64 fe_id,
			int session_type)
{
	if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
		pr_err("%s: invalid FE %llu\n", __func__, fe_id);
		return NULL;
	}

	if ((session_type != SESSION_TYPE_TX) &&
		(session_type != SESSION_TYPE_RX)) {
		pr_err("%s: invalid session type %d\n", __func__, session_type);
		return NULL;
	}

	return chmap_pspd[fe_id][session_type];
}

static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
@@ -333,6 +357,7 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
	struct msm_audio *prtd = runtime->private_data;
	struct msm_plat_data *pdata;
	struct snd_pcm_hw_params *params;
	struct msm_pcm_channel_map *chmap;
	int ret;
	uint32_t fmt_type = FORMAT_LINEAR_PCM;
	uint16_t bits_per_sample;
@@ -356,6 +381,12 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
	}
	params = &soc_prtd->dpcm[substream->stream].hw_params;

	chmap = msm_pcm_get_chmap(soc_prtd->dai_link->id, SESSION_TYPE_RX);
	if (!chmap) {
		pr_err("%s: invalid chmap handle\n", __func__);
		return -EINVAL;
	}

	pr_debug("%s\n", __func__);
	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
@@ -458,8 +489,8 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)

			ret = q6asm_media_format_block_multi_ch_pcm_v5(
				prtd->audio_client, runtime->rate,
				runtime->channels, !prtd->set_channel_map,
				prtd->channel_map, bits_per_sample,
				runtime->channels, !chmap->set_channel_map,
				chmap->channel_map, bits_per_sample,
				sample_word_size, ASM_LITTLE_ENDIAN,
				DEFAULT_QF);
		} else {
@@ -472,7 +503,7 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
		}
	}
	if (ret < 0)
		pr_info("%s: CMD Format block failed\n", __func__);
		pr_err("%s: CMD Format block failed\n", __func__);

	atomic_set(&prtd->out_count, runtime->periods);

@@ -493,6 +524,7 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
	struct msm_plat_data *pdata;
	struct snd_pcm_hw_params *params;
	struct msm_pcm_routing_evt event;
	struct msm_pcm_channel_map *chmap;
	int ret = 0;
	int i = 0;
	uint16_t bits_per_sample = 16;
@@ -515,6 +547,12 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
		return -EINVAL;
	}

	chmap = msm_pcm_get_chmap(soc_prtd->dai_link->id, SESSION_TYPE_TX);
	if (!chmap) {
		pr_err("%s: invalid chmap handle\n", __func__);
		return -EINVAL;
	}

	if (prtd->enabled == IDLE) {
		pr_debug("%s:perf_mode=%d periods=%d\n", __func__,
			pdata->perf_mode, runtime->periods);
@@ -622,6 +660,8 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
						prtd->audio_client,
						prtd->samp_rate,
						prtd->channel_mode,
						!chmap->set_channel_map,
						chmap->channel_map,
						bits_per_sample,
						sample_word_size,
						ASM_LITTLE_ENDIAN,
@@ -1841,9 +1881,12 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
	struct msm_plat_data *pdata = NULL;
	struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
	struct snd_soc_component *component = NULL;
	u64 fe_id = 0;
	struct msm_pcm_channel_map *chmap;
	u64 fe_id = kcontrol->private_value & 0xFF;
	int session_type = (kcontrol->private_value >> 8) & 0xFF;

	pr_debug("%s", __func__);
	pr_debug("%s: chmap ctl for fe_id: %d, session_type: %d\n",
			__func__, fe_id, session_type);
	substream = snd_pcm_chmap_substream(info, idx);
	if (!substream)
		return -ENODEV;
@@ -1864,6 +1907,17 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
		}
	}

	chmap = msm_pcm_get_chmap(fe_id, session_type);
	if (!chmap) {
		pr_err("%s: invalid chmap handle\n", __func__);
		return -EINVAL;
	}
	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
		chmap->channel_map[i] =
			ucontrol->value.integer.value[i];

	chmap->set_channel_map = true;

	if (!rtd)
		return 0;

@@ -1905,60 +1959,23 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	int i;
	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
	struct snd_pcm_substream *substream;
	struct msm_audio *prtd;
	struct snd_soc_pcm_runtime *rtd = NULL;
	struct msm_plat_data *pdata = NULL;
	struct snd_soc_component *component = NULL;

	pr_debug("%s", __func__);
	substream = snd_pcm_chmap_substream(info, idx);
	if (!substream)
		return -ENODEV;

	rtd = substream->private_data;
	if (rtd) {
		component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
		if (component) {
			pdata = (struct msm_plat_data *)
						dev_get_drvdata(component->dev);
			if (!pdata) {
				pr_err("%s: pdata not found\n", __func__);
				return -ENODEV;
			}
		} else {
			pr_err("%s: component is NULL\n", __func__);
			return -EINVAL;
		}
	}
	int i = 0;
	struct msm_pcm_channel_map *chmap;
	u64 fe_id = kcontrol->private_value & 0xFF;
	int session_type = (kcontrol->private_value >> 8) & 0xFF;

	memset(ucontrol->value.integer.value, 0,
		sizeof(ucontrol->value.integer.value));
	if (!rtd)
		return 0; /* no channels set */
	pr_debug("%s: chmap ctl for fe_id: %d, session_type: %d\n",
			__func__, fe_id, session_type);

	mutex_lock(&pdata->lock);
	if (substream->runtime && substream->ref_count <= 0) {
		pr_err_ratelimited("%s: substream ref_count:%d invalid\n",
				__func__, substream->ref_count);
		mutex_unlock(&pdata->lock);
	chmap = msm_pcm_get_chmap(fe_id, session_type);
	if (!chmap) {
		pr_err("%s: invalid chmap handle\n", __func__);
		return -EINVAL;
	}
	prtd = substream->runtime ? substream->runtime->private_data : NULL;

	if (prtd && prtd->set_channel_map == true) {
	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
		ucontrol->value.integer.value[i] =
					(int)prtd->channel_map[i];
	} else {
		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
			ucontrol->value.integer.value[i] = 0;
	}
			chmap->channel_map[i];

	mutex_unlock(&pdata->lock);
	return 0;
}

@@ -1971,24 +1988,82 @@ static int msm_pcm_add_chmap_controls(struct snd_soc_pcm_runtime *rtd)
	int i, ret = 0;

	pr_debug("%s, Channel map cntrl add\n", __func__);

	if (rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream &&
			!chmap_pspd[rtd->dai_link->id][SESSION_TYPE_RX]) {

		chmap_pspd[rtd->dai_link->id][SESSION_TYPE_RX] =
			kzalloc(sizeof(struct msm_pcm_channel_map), GFP_KERNEL);
		if (!chmap_pspd[rtd->dai_link->id][SESSION_TYPE_RX]) {
			ret = -ENOMEM;
			goto fail;
		}

		ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
					     snd_pcm_std_chmaps,
				     PCM_FORMAT_MAX_NUM_CHANNEL_V8, 0,
					     PCM_FORMAT_MAX_NUM_CHANNEL_V8,
					     (rtd->dai_link->id) | (SESSION_TYPE_RX << 8),
					     &chmap_info);
		if (ret < 0) {
			pr_err("%s, channel map cntrl add failed\n", __func__);
		return ret;
			goto fail;
		}
		kctl = chmap_info->kctl;
		for (i = 0; i < kctl->count; i++)
			kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;

		snprintf(device_num, sizeof(device_num), "%d", pcm->device);
		strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
		pr_debug("%s, Overwriting channel map control name to: %s\n",
			__func__, kctl->id.name);

		kctl->put = msm_pcm_chmap_ctl_put;
		kctl->get = msm_pcm_chmap_ctl_get;
	}

	if (rtd->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream &&
			!chmap_pspd[rtd->dai_link->id][SESSION_TYPE_TX]) {

		chmap_pspd[rtd->dai_link->id][SESSION_TYPE_TX] =
			kzalloc(sizeof(struct msm_pcm_channel_map), GFP_KERNEL);
		if (!chmap_pspd[rtd->dai_link->id][SESSION_TYPE_TX]) {
			ret = -ENOMEM;
			goto fail;
		}

		ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE,
					     snd_pcm_std_chmaps,
					     PCM_FORMAT_MAX_NUM_CHANNEL_V8,
					     (rtd->dai_link->id) | (SESSION_TYPE_TX << 8),
					     &chmap_info);
		if (ret < 0) {
			pr_err("%s, channel map cntrl add failed\n", __func__);
			goto fail;
		}
		kctl = chmap_info->kctl;
		for (i = 0; i < kctl->count; i++)
			kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;

		snprintf(device_num, sizeof(device_num), "%d", pcm->device);
		strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
		pr_debug("%s, Overwriting channel map control name to: %s\n",
			__func__, kctl->id.name);

		kctl->put = msm_pcm_chmap_ctl_put;
		kctl->get = msm_pcm_chmap_ctl_get;
	}

	return 0;

fail:
	pr_err("%s: failed add chmap ctls, err = %d\n", __func__, ret);

	kfree(chmap_pspd[rtd->dai_link->id][SESSION_TYPE_RX]);
	kfree(chmap_pspd[rtd->dai_link->id][SESSION_TYPE_TX]);
	chmap_pspd[rtd->dai_link->id][SESSION_TYPE_RX] = NULL;
	chmap_pspd[rtd->dai_link->id][SESSION_TYPE_TX] = NULL;

	return ret;
}

#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+15 −3
Original line number Diff line number Diff line
@@ -5529,13 +5529,17 @@ EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v2);

static int __q6asm_enc_cfg_blk_pcm_v5(struct audio_client *ac,
				      uint32_t rate, uint32_t channels,
				      bool use_default_chmap,
				      char *channel_map,
				      uint16_t bits_per_sample,
				      uint16_t sample_word_size,
				      uint16_t endianness,
				      uint16_t mode)
{
	return q6asm_enc_cfg_blk_pcm_v5(ac, rate, channels,
					bits_per_sample, true, false, NULL,
					bits_per_sample,
					use_default_chmap, false,
					channel_map,
					sample_word_size, endianness, mode);
}

@@ -5644,20 +5648,28 @@ EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v4);
 * @rate: sample rate
 * @channels: number of channels
 * @bits_per_sample: bit width of encoder session
 * @use_default_chmap: true if default channel map to be used
 * @channel_map: input channel map
 * @sample_word_size: Size in bits of the word that holds a sample of a channel
 * @endianness: endianness of the pcm data
 * @mode: Mode to provide additional info about the pcm input data
 */
int q6asm_enc_cfg_blk_pcm_format_support_v5(struct audio_client *ac,
					    uint32_t rate, uint32_t channels,
					    bool use_default_chmap,
					    char *channel_map,
					    uint16_t bits_per_sample,
					    uint16_t sample_word_size,
					    uint16_t endianness,
					    uint16_t mode)
{
	 return __q6asm_enc_cfg_blk_pcm_v5(ac, rate, channels,
					   bits_per_sample, sample_word_size,
					   endianness, mode);
					   use_default_chmap,
					   channel_map,
					   bits_per_sample,
					   sample_word_size,
					   endianness,
					   mode);
}

EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v5);
+7 −5
Original line number Diff line number Diff line
@@ -479,6 +479,8 @@ int q6asm_enc_cfg_blk_pcm_format_support_v4(struct audio_client *ac,

int q6asm_enc_cfg_blk_pcm_format_support_v5(struct audio_client *ac,
					    uint32_t rate, uint32_t channels,
					    bool use_default_chmap,
					    char *channel_map,
					    uint16_t bits_per_sample,
					    uint16_t sample_word_size,
					    uint16_t endianness,