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

Commit 0a4cef07 authored by Vignesh Kulothungan's avatar Vignesh Kulothungan
Browse files

soc: pcm: add qtime mixer control



Add qtime mixer control to receive qtime value in pcm driver.
Add mechanism to delay asm using the time value received.
Update platform data structure to hold pointers to all pcm's
created in a platform.

CRs-Fixed: 2419295
Change-Id: I623e568196357af7909f3113d998df3c64501420
Signed-off-by: default avatarVignesh Kulothungan <vigneshk@codeaurora.org>
parent 40e2c439
Loading
Loading
Loading
Loading
+114 −14
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -632,8 +632,17 @@ static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		if (prtd->qtime_lsw) {
			pr_debug("%s: Trigger start at msw: %u, lsw: %u msec",
				__func__, prtd->qtime_msw, prtd->qtime_lsw);
			ret = q6asm_run_nowait(prtd->audio_client, 1,
					prtd->qtime_msw, prtd->qtime_lsw);
			prtd->qtime_lsw = 0;
			prtd->qtime_msw = 0;
		} else {
			pr_debug("%s: Trigger start\n", __func__);
			ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
		}
		break;
	case SNDRV_PCM_TRIGGER_STOP:
		pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
@@ -1164,7 +1173,8 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
		goto done;
	}

	substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
	substream = pdata->pcm[kcontrol->private_value]->
			streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
	if (!substream) {
		pr_err("%s substream not found\n", __func__);
		ret = -EINVAL;
@@ -1434,7 +1444,8 @@ static int msm_pcm_compress_ctl_get(struct snd_kcontrol *kcontrol,
		pr_err("%s pdata is NULL\n", __func__);
		return -ENODEV;
	}
	substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
	substream = pdata->pcm[kcontrol->private_value]->
			streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
	if (!substream) {
		pr_err("%s substream not found\n", __func__);
		return -EINVAL;
@@ -1464,7 +1475,8 @@ static int msm_pcm_compress_ctl_put(struct snd_kcontrol *kcontrol,
		pr_err("%s pdata is NULL\n", __func__);
		return -ENODEV;
	}
	substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
	substream = pdata->pcm[kcontrol->private_value]->
			streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
	pr_debug("%s: compress : 0x%x\n", __func__, compress);
	if (!substream) {
		pr_err("%s substream not found\n", __func__);
@@ -1524,15 +1536,13 @@ static int msm_pcm_add_compress_control(struct snd_soc_pcm_runtime *rtd)
	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;
		pdata->pcm[rtd->dai_link->id] = rtd->pcm;
		snd_soc_add_platform_controls(rtd->platform,
					      pcm_compress_control,
					      ARRAY_SIZE
					      (pcm_compress_control));
		pr_debug("%s: add control success plt = %pK\n",
				 __func__, rtd->platform);
		}
	} else {
		pr_err("%s: NULL pdata\n", __func__);
		ret = -EINVAL;
@@ -1786,6 +1796,90 @@ static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd)
	return 0;
}

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

static int msm_pcm_qtimer_ctl_put(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
	struct snd_soc_platform *platform = snd_soc_component_to_platform(comp);
	struct msm_plat_data *pdata = dev_get_drvdata(platform->dev);
	struct snd_pcm_substream *substream;
	struct msm_audio *prtd;

	if (!pdata) {
		pr_err("%s pdata is NULL\n", __func__);
		return -ENODEV;
	}

	substream = pdata->pcm[kcontrol->private_value]->
			streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
	if (!substream) {
		pr_err("%s substream not found\n", __func__);
		return -EINVAL;
	}

	if (!substream->runtime) {
		pr_err("%s substream runtime not found\n", __func__);
		return 0;
	}

	prtd = substream->runtime->private_data;
	if (prtd) {
		prtd->qtime_lsw = ucontrol->value.integer.value[0];
		prtd->qtime_msw = ucontrol->value.integer.value[1];
	}

	return 0;
}

static int msm_pcm_add_qtimer_control(struct snd_soc_pcm_runtime *rtd)
{
	const char *mixer_ctl_name = "QTimer";
	const char *deviceNo = "NN";
	char *mixer_str = NULL;
	int ctl_len = 0, ret = 0;
	struct snd_kcontrol_new qtimer_control[1] = {
		{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "?",
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = msm_pcm_qtimer_ctl_info,
		.put = msm_pcm_qtimer_ctl_put,
		.private_value = 0,
		}
	};

	ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
	mixer_str = kzalloc(ctl_len, GFP_KERNEL);
	if (!mixer_str) {
		ret = -ENOMEM;
		goto done;
	}

	snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
	qtimer_control[0].name = mixer_str;
	qtimer_control[0].private_value = rtd->dai_link->id;
	ret = snd_soc_add_platform_controls(rtd->platform,
		qtimer_control,
		ARRAY_SIZE(qtimer_control));
	if (ret < 0)
		pr_err("%s: failed add ctl %s. err = %d\n",
			__func__, mixer_str, ret);

	kfree(mixer_str);
done:
	return ret;
}

static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd)
{
	int ret = 0;
@@ -1798,6 +1892,12 @@ 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_qtimer_control(rtd);
	if (ret)
		pr_err("%s: pcm add qtimer controls failed:%d\n",
			__func__, ret);

	return ret;
}

+4 −2
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 Google, Inc.
 * Copyright (C) 2008 HTC Corporation
 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2017,2019 The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
@@ -110,6 +110,8 @@ struct msm_audio {
	bool meta_data_mode;
	uint32_t volume;
	bool compress_enable;
	uint32_t qtime_lsw;
	uint32_t qtime_msw;
	/* array of frame info */
	struct msm_audio_in_frame_info in_frame_info[CAPTURE_MAX_NUM_PERIODS];
};
@@ -124,7 +126,7 @@ struct output_meta_data_st {

struct msm_plat_data {
	int perf_mode;
	struct snd_pcm *pcm;
	struct snd_pcm *pcm[MSM_FRONTEND_DAI_MAX];
	struct msm_pcm_ch_map *ch_map[MSM_FRONTEND_DAI_MAX];
};