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

Commit ed065214 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: update asm channel map for push pull mode"

parents 0b26ab3e 5628e8bc
Loading
Loading
Loading
Loading
+120 −73
Original line number Diff line number Diff line
@@ -275,6 +275,8 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
	int dir = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? IN : OUT;
	unsigned long topology;
	int perf_mode;
	bool use_default_chmap = true;
	char *chmap = NULL;

	pdata = (struct msm_plat_data *)
		dev_get_drvdata(soc_prtd->platform->dev);
@@ -311,6 +313,13 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
	if (prtd->enabled)
		return 0;

	if (pdata->ch_map[soc_prtd->dai_link->id]) {
		use_default_chmap =
			!(pdata->ch_map[soc_prtd->dai_link->id]->set_ch_map);
		chmap =
			pdata->ch_map[soc_prtd->dai_link->id]->channel_map;
	}

	switch (runtime->format) {
	case SNDRV_PCM_FORMAT_S24_LE:
		bits_per_sample = 24;
@@ -335,7 +344,8 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
	config.bufsz = params_buffer_bytes(params) / params_periods(params);
	config.bufcnt = params_periods(params);

	ret = q6asm_open_shared_io(prtd->audio_client, &config, dir);
	ret = q6asm_open_shared_io(prtd->audio_client, &config, dir,
				   use_default_chmap, chmap);
	if (ret) {
		pr_err("%s: q6asm_open_write_shared_io failed ret: %d\n",
		       __func__, ret);
@@ -718,89 +728,126 @@ static int msm_pcm_add_volume_control(struct snd_soc_pcm_runtime *rtd)
	return 0;
}

static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
static int msm_pcm_channel_map_put(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_component *pcm = snd_kcontrol_chip(kcontrol);
	u64 fe_id = kcontrol->private_value;
	struct msm_plat_data *pdata = (struct msm_plat_data *)
			snd_soc_component_get_drvdata(pcm);
	int rc = 0, i = 0;

	pr_debug("%s", __func__);
	substream = snd_pcm_chmap_substream(info, idx);
	if (!substream)
		return -ENODEV;
	if (!substream->runtime)
		return 0;
	pr_debug("%s: fe_id- %llu\n", __func__, fe_id);

	prtd = substream->runtime->private_data;
	if (prtd) {
		prtd->set_channel_map = true;
	if (fe_id >= MSM_FRONTEND_DAI_MAX) {
		pr_err("%s Received out of bounds fe_id %llu\n",
			__func__, fe_id);
		rc = -EINVAL;
		goto end;
	}

	if (pdata->ch_map[fe_id]) {
		pdata->ch_map[fe_id]->set_ch_map = true;
		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
				prtd->channel_map[i] =
			pdata->ch_map[fe_id]->channel_map[i] =
				(char)(ucontrol->value.integer.value[i]);
	} else {
		pr_debug("%s: no memory for ch_map, default will be set\n",
			__func__);
	}
end:
	pr_debug("%s: ret %d\n", __func__, rc);
	return rc;
}

static int msm_pcm_channel_map_info(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 8;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 0xFFFFFFFF;
	return 0;
}

static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
static int msm_pcm_channel_map_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;

	pr_debug("%s", __func__);
	substream = snd_pcm_chmap_substream(info, idx);
	if (!substream)
		return -ENODEV;
	memset(ucontrol->value.integer.value, 0,
		sizeof(ucontrol->value.integer.value));
	if (!substream->runtime)
		return 0; /* no channels set */

	prtd = substream->runtime->private_data;
	struct snd_soc_component *pcm = snd_kcontrol_chip(kcontrol);
	u64 fe_id = kcontrol->private_value;
	struct msm_plat_data *pdata = (struct msm_plat_data *)
			snd_soc_component_get_drvdata(pcm);
	int rc = 0, i = 0;

	if (prtd && prtd->set_channel_map == true) {
	pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
	if (fe_id >= MSM_FRONTEND_DAI_MAX) {
		pr_err("%s: Received out of bounds fe_id %llu\n",
			__func__, fe_id);
		rc = -EINVAL;
		goto end;
	}
	if (pdata->ch_map[fe_id]) {
		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
			ucontrol->value.integer.value[i] =
					(int)prtd->channel_map[i];
	} else {
		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
			ucontrol->value.integer.value[i] = 0;
				pdata->ch_map[fe_id]->channel_map[i];
	}

	return 0;
end:
	pr_debug("%s: ret %d\n", __func__, rc);
	return rc;
}

static int msm_pcm_add_chmap_control(struct snd_soc_pcm_runtime *rtd)
static int msm_pcm_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_pcm *pcm = rtd->pcm;
	struct snd_pcm_chmap *chmap_info;
	struct snd_kcontrol *kctl;
	char device_num[12];
	int i, ret;

	pr_debug("%s, Channel map cntrl add\n", __func__);
	ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
				     snd_pcm_std_chmaps,
				     PCM_FORMAT_MAX_NUM_CHANNEL, 0,
				     &chmap_info);
	if (ret)
		return ret;
	const char *mixer_ctl_name = "Playback Channel Map";
	const char *deviceNo       = "NN";
	char *mixer_str = NULL;
	struct msm_plat_data *pdata = NULL;
	int ctl_len = 0;
	struct snd_kcontrol_new fe_channel_map_control[1] = {
		{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "?",
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = msm_pcm_channel_map_info,
		.get = msm_pcm_channel_map_get,
		.put = msm_pcm_channel_map_put,
		.private_value = 0,
		}
	};

	if (!rtd) {
		pr_err("%s: NULL rtd\n", __func__);
		return -EINVAL;
	}

	pr_debug("%s: added new pcm FE with name %s, id %d, cpu dai %s, device no %d\n",
		 __func__, rtd->dai_link->name, rtd->dai_link->id,
		 rtd->dai_link->cpu_dai_name, rtd->pcm->device);

	ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) + 1;
	mixer_str = kzalloc(ctl_len, GFP_KERNEL);
	if (!mixer_str)
		return -ENOMEM;

	snprintf(mixer_str, ctl_len, "%s%d", mixer_ctl_name, rtd->pcm->device);

	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",
		__func__, kctl->id.name);
	kctl->put = msm_pcm_chmap_ctl_put;
	kctl->get = msm_pcm_chmap_ctl_get;
	fe_channel_map_control[0].name = mixer_str;
	fe_channel_map_control[0].private_value = rtd->dai_link->id;
	pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
	snd_soc_add_platform_controls(rtd->platform,
				fe_channel_map_control,
				ARRAY_SIZE(fe_channel_map_control));

	pdata = snd_soc_platform_get_drvdata(rtd->platform);
	pdata->ch_map[rtd->dai_link->id] =
		 kzalloc(sizeof(struct msm_pcm_ch_map), GFP_KERNEL);
	if (!pdata->ch_map[rtd->dai_link->id]) {
		pr_err("%s: Could not allocate memory for channel map\n",
			__func__);
		kfree(mixer_str);
		return -ENOMEM;
	}
	kfree(mixer_str);
	return 0;
}

@@ -1155,11 +1202,11 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
	if (!card->dev->coherent_dma_mask)
		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);

	ret = msm_pcm_add_chmap_control(rtd);
	if (ret) {
		pr_err("%s failed to add chmap cntls\n", __func__);
		goto exit;
	}
	ret = msm_pcm_add_channel_map_control(rtd);
	if (ret)
		pr_err("%s: Could not add pcm Channel Map Control\n",
			__func__);

	ret = msm_pcm_add_volume_control(rtd);
	if (ret) {
		pr_err("%s: Could not add pcm Volume Control %d\n",
@@ -1181,7 +1228,7 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
	if (ret)
		pr_err("%s: Could not add hw dep node\n", __func__);
	pcm->nonatomic = true;
exit:

	return ret;
}

+7 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
#define _MSM_PCM_H
#include <dsp/apr_audio-v2.h>
#include <dsp/q6asm-v2.h>

#include "msm-pcm-routing-v2.h"


/* Support unconventional sample rates 12000, 24000 as well */
@@ -125,6 +125,12 @@ struct output_meta_data_st {
struct msm_plat_data {
	int perf_mode;
	struct snd_pcm *pcm;
	struct msm_pcm_ch_map *ch_map[MSM_FRONTEND_DAI_MAX];
};

struct msm_pcm_ch_map {
	bool set_ch_map;
	char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL];
};

#endif /*_MSM_PCM_H*/
+20 −5
Original line number Diff line number Diff line
@@ -4027,11 +4027,13 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac,
 * parameters
 *   config - session parameters (channels, bits_per_sample, sr)
 *   dir - stream direction (IN for playback, OUT for capture)
 *   use_default_chmap: true if default channel map to be used
 *   channel_map: input channel map
 * returns 0 if successful, error code otherwise
 */
int q6asm_open_shared_io(struct audio_client *ac,
			 struct shared_io_config *config,
			 int dir)
			 int dir, bool use_default_chmap, u8 *channel_map)
{
	struct asm_stream_cmd_open_shared_io *open;
	u8 *channel_mapping;
@@ -4041,6 +4043,12 @@ int q6asm_open_shared_io(struct audio_client *ac,
	if (!ac || !config)
		return -EINVAL;

	if (!use_default_chmap && (channel_map == NULL)) {
		pr_err("%s: No valid chan map and can't use default\n",
			__func__);
		return -EINVAL;
	}

	bufsz = config->bufsz;
	bufcnt = config->bufcnt;
	num_watermarks = 0;
@@ -4137,11 +4145,18 @@ int q6asm_open_shared_io(struct audio_client *ac,

	memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);

	rc = q6asm_map_channels(channel_mapping, config->channels, false);
	if (use_default_chmap) {
		rc = q6asm_map_channels(channel_mapping, config->channels,
					false);
		if (rc) {
		pr_err("%s: Map channels failed, ret: %d\n", __func__, rc);
			pr_err("%s: Map channels failed, ret: %d\n",
				 __func__, rc);
			goto done;
		}
	} else {
		memcpy(channel_mapping, channel_map,
				PCM_FORMAT_MAX_NUM_CHANNEL);
	}

	open->num_watermark_levels = num_watermarks;
	for (i = 0; i < num_watermarks; i++) {
+2 −1
Original line number Diff line number Diff line
@@ -303,7 +303,8 @@ int q6asm_open_write_v2(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample);

int q6asm_open_shared_io(struct audio_client *ac,
			 struct shared_io_config *c, int dir);
			 struct shared_io_config *c, int dir,
			 bool use_default_chmap, u8 *channel_map);

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