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

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

Merge "ASoC: dsp: align param size of PSPD matrix"

parents d74d0726 51ff6559
Loading
Loading
Loading
Loading
+119 −0
Original line number Diff line number Diff line
@@ -3894,6 +3894,16 @@ static int msm_compr_probe(struct snd_soc_platform *platform)
	return 0;
}

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

static int msm_compr_volume_info(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_info *uinfo)
{
@@ -4317,6 +4327,112 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
	return 0;
}

static int msm_compr_chmix_cfg_ctl_put(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
	struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
				snd_soc_component_get_drvdata(comp);
	struct snd_compr_stream *cstream = NULL;
	struct snd_soc_pcm_runtime *rtd = NULL;
	u64 fe_id = kcontrol->private_value;
	int ip_channel_cnt, op_channel_cnt;
	int i, index = 0;
	int ch_coeff[PCM_FORMAT_MAX_NUM_CHANNEL * PCM_FORMAT_MAX_NUM_CHANNEL];
	bool use_default_chmap = true;
	char *chmap = NULL;

	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);
		return -EINVAL;
	}
	cstream = pdata->cstream[fe_id];
	if (!cstream) {
		pr_err("%s: stream inactive\n", __func__);
		return -EINVAL;
	}
	rtd = cstream->private_data;
	if (!rtd) {
		pr_err("%s: stream inactive\n", __func__);
		return -EINVAL;
	}

	use_default_chmap = !(pdata->ch_map[rtd->dai_link->id]->set_ch_map);
	chmap = pdata->ch_map[rtd->dai_link->id]->channel_map;

	ip_channel_cnt = ucontrol->value.integer.value[index++];
	op_channel_cnt = ucontrol->value.integer.value[index++];
	/*
	 * wght coeff of first out channel corresponding to each in channel
	 * are sent followed by second out channel for each in channel etc.
	 */
	memset(ch_coeff, 0, sizeof(ch_coeff));
	for (i = 0; i < op_channel_cnt * ip_channel_cnt; i++) {
		ch_coeff[i] =
			ucontrol->value.integer.value[index++];
	}

	msm_pcm_routing_send_chmix_cfg(fe_id, ip_channel_cnt, op_channel_cnt,
			ch_coeff, SESSION_TYPE_RX, use_default_chmap, chmap);

	return 0;
}

static int msm_compr_chmix_cfg_ctl_get(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
{
	return 0;
}

static int msm_compr_add_chmix_cfg_controls(struct snd_soc_pcm_runtime *rtd)
{
	const char *mixer_ctl_name = "Audio Stream";
	const char *deviceNo       = "NN";
	const char *suffix         = "Channel Mix Cfg";
	int ctl_len;
	char *mixer_str = NULL;
	struct snd_kcontrol_new chmix_cfg_controls[1] = {
		{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "?",
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = msm_compr_chmix_cfg_ctl_info,
		.get = msm_compr_chmix_cfg_ctl_get,
		.put = msm_compr_chmix_cfg_ctl_put,
		.private_value = 0,
		}
	};

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

	pr_debug("%s: added new compr 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) + 1 + strlen(deviceNo) + 1 +
		  strlen(suffix) + 1;
	mixer_str = kzalloc(ctl_len, GFP_KERNEL);
	if (!mixer_str)
		return -ENOMEM;

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

	chmix_cfg_controls[0].name = mixer_str;
	chmix_cfg_controls[0].private_value = rtd->dai_link->id;
	pr_debug("%s: Registering new mixer ctl %s", __func__, mixer_str);
	snd_soc_add_platform_controls(rtd->platform,
				      chmix_cfg_controls,
				      ARRAY_SIZE(chmix_cfg_controls));
	kfree(mixer_str);
	return 0;
}

static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
{
	const char *mixer_ctl_name = "Playback Channel Map";
@@ -4513,6 +4629,9 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
	if (rc)
		pr_err("%s: Could not add Compr Channel Map Control\n",
			__func__);
	rc = msm_compr_add_chmix_cfg_controls(rtd);
	if (rc)
		pr_err("%s: add chmix cfg controls failed:%d\n", __func__, rc);
	return 0;
}

+147 −0
Original line number Diff line number Diff line
@@ -1753,6 +1753,150 @@ static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd)
	return 0;
}

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

static int msm_pcm_chmix_cfg_ctl_put(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *usr_info = snd_kcontrol_chip(kcontrol);
	struct snd_soc_platform *platform;
	struct msm_plat_data *pdata;
	struct snd_pcm_substream *substream;
	struct msm_audio *prtd;
	u64 fe_id = kcontrol->private_value;
	int ip_channel_cnt, op_channel_cnt;
	int i, index = 0, ret = 0;
	int ch_coeff[PCM_FORMAT_MAX_NUM_CHANNEL * PCM_FORMAT_MAX_NUM_CHANNEL];
	bool use_default_chmap = true;
	char *ch_map = NULL;

	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);
		ret = -EINVAL;
		goto done;
	}

	if (!usr_info) {
		pr_err("%s: usr_info is null\n", __func__);
		ret = -EINVAL;
		goto done;
	}
	platform = snd_soc_component_to_platform(usr_info);
	if (!platform) {
		pr_err("%s: platform is null\n", __func__);
		ret = -EINVAL;
		goto done;
	}
	pdata = dev_get_drvdata(platform->dev);
	if (!pdata) {
		pr_err("%s: pdata is null\n", __func__);
		ret = -EINVAL;
		goto done;
	}
	substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;

	if (!substream) {
		pr_err("%s substream not found\n", __func__);
		return -ENODEV;
	}
	if (!substream->runtime) {
		pr_err("%s substream runtime not found\n", __func__);
		ret = -EINVAL;
		goto done;
	}
	prtd = substream->runtime->private_data;
	if (!prtd) {
		pr_err("%s: stream inactive\n", __func__);
		ret = -EINVAL;
		goto done;
	}
	use_default_chmap = !prtd->set_channel_map;
	ch_map = prtd->channel_map;
	ip_channel_cnt = ucontrol->value.integer.value[index++];
	op_channel_cnt = ucontrol->value.integer.value[index++];
	/*
	 * wght coeff of first out channel corresponding to each in channel
	 * are sent followed by second out channel for each in channel etc.
	 */
	memset(ch_coeff, 0, sizeof(ch_coeff));
	for (i = 0; i < op_channel_cnt * ip_channel_cnt; i++) {
		ch_coeff[i] =
			ucontrol->value.integer.value[index++];
	}

	msm_pcm_routing_send_chmix_cfg(fe_id, ip_channel_cnt, op_channel_cnt,
			ch_coeff, SESSION_TYPE_RX, use_default_chmap, ch_map);
done:
	return ret;
}

static int msm_pcm_chmix_cfg_ctl_get(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
{
	return 0;
}

static int msm_pcm_add_chmix_cfg_controls(struct snd_soc_pcm_runtime *rtd)
{
	const char *mixer_ctl_name = "Audio Stream";
	const char *deviceNo       = "NN";
	const char *suffix         = "Channel Mix Cfg";
	char *mixer_str = NULL;
	int ctl_len = 0;
	struct msm_plat_data *pdata;
	struct snd_kcontrol_new chmix_cfg_controls[1] = {
		{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "?",
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = msm_pcm_chmix_cfg_ctl_info,
		.get = msm_pcm_chmix_cfg_ctl_get,
		.put = msm_pcm_chmix_cfg_ctl_put,
		.private_value = 0,
		}
	};

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

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

	snprintf(mixer_str, ctl_len, "%s %d %s",
		 mixer_ctl_name, rtd->pcm->device, suffix);
	chmix_cfg_controls[0].name = mixer_str;
	chmix_cfg_controls[0].private_value = rtd->dai_link->id;
	pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
	pdata = dev_get_drvdata(rtd->platform->dev);
	if (pdata) {
		if (!pdata->pcm)
			pdata->pcm = rtd->pcm;
		snd_soc_add_platform_controls(rtd->platform,
					      chmix_cfg_controls,
					      ARRAY_SIZE(chmix_cfg_controls));
	} else {
		pr_err("%s: NULL pdata\n", __func__);
		return -EINVAL;
	}
	kfree(mixer_str);
	return 0;
}

static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd)
{
	int ret = 0;
@@ -1765,6 +1909,9 @@ static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd)
	if (ret)
		pr_err("%s: pcm add app type controls failed:%d\n",
			__func__, ret);
	ret = msm_pcm_add_chmix_cfg_controls(rtd);
	if (ret)
		pr_err("%s: add chmix cfg controls failed:%d\n", __func__, ret);
	return ret;
}

+77 −1
Original line number Diff line number Diff line
@@ -792,6 +792,79 @@ static bool is_mm_lsm_fe_id(int fe_id)
	return rc;
}
/*
 * msm_pcm_routing_send_chmix_cfg
 *
 * Receives fe_id, ip_channel_cnt, op_channel_cnt, channel weight, session_type
 * use_default_chmap and channel map to map in channel mixer and send to
 * adm programmable matrix.
 *
 * fe_id - Passed value, frontend id which is wanted
 * ip_channel_cnt - Passed value, number of input channels
 * op_channel_cnt - Passed value, number of output channels
 * ch_wght_coeff - Passed reference, weights for each output channel
 * session_type - Passed value, session_type for RX or TX
 * use_default_chmap - true if default channel map  to be used
 * ch_map - input/output channel map for playback/capture session respectively
 */
int msm_pcm_routing_send_chmix_cfg(int fe_id, int ip_channel_cnt,
				   int op_channel_cnt, int *ch_wght_coeff,
				   int session_type, bool use_default_chmap,
				   char *channel_map)
{
	int rc = 0, idx = 0, i, j;
	int be_index = 0, port_id, index = 0;
	unsigned int session_id = 0;
	pr_debug("%s: fe_id[%d] ip_ch[%d] op_ch[%d] sess_type [%d]\n",
		 __func__, fe_id, ip_channel_cnt, op_channel_cnt, session_type);
	if (!use_default_chmap && (channel_map == NULL)) {
		pr_err("%s: No valid chan map and can't use default\n",
			__func__);
		return -EINVAL;
	}
	if ((ch_wght_coeff == NULL) || (op_channel_cnt > ADM_MAX_CHANNELS) ||
	     (ip_channel_cnt > ADM_MAX_CHANNELS)) {
		pr_err("%s: Invalid channels or null coefficients\n", __func__);
		return -EINVAL;
	}
	for (be_index = 0; be_index < MSM_BACKEND_DAI_MAX; be_index++) {
		port_id = msm_bedais[be_index].port_id;
		if (!msm_bedais[be_index].active ||
			!test_bit(fe_id, &msm_bedais[be_index].fe_sessions[0]))
			continue;
		session_id = fe_dai_map[fe_id][session_type].strm_id;
		channel_mixer[fe_id].input_channels[0] = ip_channel_cnt;
		channel_mixer[fe_id].output_channel = op_channel_cnt;
		channel_mixer[fe_id].rule = 0;
		for (j = 0; j < op_channel_cnt; j++) {
			for (i = 0; i < ip_channel_cnt; i++)
				channel_mixer[fe_id].channel_weight[j][i] =
						ch_wght_coeff[index++];
		}
		for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
			unsigned long copp =
				session_copp_map[fe_id][session_type][be_index];
			if (!test_bit(idx, &copp))
				continue;
			rc = adm_programable_channel_mixer(port_id,
					idx, session_id, session_type,
					channel_mixer + fe_id, 0,
					use_default_chmap, channel_map);
			if (rc < 0)
				pr_err("%s: err setting channel mix config\n",
					__func__);
		}
	}
	return 0;
}
int msm_pcm_routing_reg_stream_app_type_cfg(
	int fedai_id, int session_type, int be_id,
	struct msm_pcm_stream_app_type_cfg *cfg_data)
@@ -1326,6 +1399,8 @@ static int msm_pcm_routing_channel_mixer(int fe_id, bool perf_mode,
	int sess_type = 0;
	int i = 0, j = 0, be_id;
	int ret = 0;
	bool use_default_chmap = true;
	char *ch_map = NULL;
	if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
		pr_err("%s: invalid FE %d\n", __func__, fe_id);
@@ -1368,7 +1443,8 @@ static int msm_pcm_routing_channel_mixer(int fe_id, bool perf_mode,
			ret = adm_programable_channel_mixer(
					msm_bedais[be_id].port_id,
					copp_idx, dspst_id, sess_type,
					channel_mixer + fe_id, i);
					channel_mixer + fe_id, i,
					use_default_chmap, ch_map);
		}
	}
+4 −0
Original line number Diff line number Diff line
@@ -525,4 +525,8 @@ int msm_pcm_routing_reg_stream_app_type_cfg(
int msm_pcm_routing_get_stream_app_type_cfg(
	int fedai_id, int session_type, int *be_id,
	struct msm_pcm_stream_app_type_cfg *cfg_data);
int msm_pcm_routing_send_chmix_cfg(int fe_id, int ip_channel_cnt,
				int op_channel_cnt, int *ch_wght_coeff,
				int session_type, bool use_default_chmap,
				char *channel_map);
#endif /*_MSM_PCM_H*/
+94 −81
Original line number Diff line number Diff line
@@ -635,18 +635,21 @@ static int adm_populate_channel_weight(u16 *ptr,
 * session_type - Passed value, session_type for RX or TX
 * ch_mixer - Passed value, ch_mixer for which channel mixer config is needed
 * channel_index - Passed value, channel_index for which channel is needed
 * use_default_chmap - true if default channel map  to be used
 * ch_map - input/output channel map for playback/capture session respectively
 */
int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
				  int session_type,
				  struct msm_pcm_channel_mixer *ch_mixer,
				  int channel_index)
				  int channel_index, bool use_default_chmap,
				  char *ch_map)
{
	struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
	struct adm_param_data_v5 data_v5;
	int ret = 0, port_idx, sz = 0, param_size = 0;
	u16 *adm_pspd_params;
	u16 *ptr;
	int index = 0;
	int index = 0, i;

	pr_debug("%s: port_id = %d\n", __func__, port_id);
	port_id = afe_convert_virtual_to_portid(port_id);
@@ -671,7 +674,8 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
			ch_mixer->input_channels[channel_index] +
			ch_mixer->input_channels[channel_index] *
			ch_mixer->output_channel);
	roundup(param_size, 4);
	/* Params size should be multiple of 4 bytes i.e 32bit aligned */
	param_size = round_up(param_size, 4);

	sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
			sizeof(struct default_chmixer_param_id_coeff) +
@@ -713,6 +717,10 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
	adm_pspd_params[3] = ch_mixer->input_channels[channel_index];
	index = 4;

	if ((session_type == SESSION_TYPE_TX) && !use_default_chmap && ch_map) {
		for (i = 0; i < ch_mixer->output_channel; i++)
			adm_pspd_params[index++] = ch_map[i];
	} else {
		if (ch_mixer->output_channel == 1) {
			adm_pspd_params[index] = PCM_CHANNEL_FC;
		} else if (ch_mixer->output_channel == 2) {
@@ -750,8 +758,13 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
			adm_pspd_params[index + 6] = PCM_CHANNEL_LB;
			adm_pspd_params[index + 7] = PCM_CHANNEL_RB;
		}

		index = index + ch_mixer->output_channel;
	}

	if ((session_type == SESSION_TYPE_RX) && !use_default_chmap && ch_map) {
		for (i = 0; i < ch_mixer->input_channels[channel_index]; i++)
			adm_pspd_params[index++] = ch_map[i];
	} else {
		if (ch_mixer->input_channels[channel_index] == 1) {
			adm_pspd_params[index] = PCM_CHANNEL_FC;
		} else if (ch_mixer->input_channels[channel_index] == 2) {
@@ -789,8 +802,8 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
			adm_pspd_params[index + 6] = PCM_CHANNEL_LB;
			adm_pspd_params[index + 7] = PCM_CHANNEL_RB;
		}

		index = index + ch_mixer->input_channels[channel_index];
	}
	ret = adm_populate_channel_weight(&adm_pspd_params[index],
					ch_mixer, channel_index);
	if (ret) {
Loading