// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright(c) 2021-2022 Intel Corporation. All rights reserved.
//
// Authors: Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
//          Cezary Rojewski <cezary.rojewski@intel.com>
//

#include <sound/soc.h>
#include "avs.h"
#include "control.h"
#include "messages.h"
#include "path.h"

static struct avs_dev *avs_get_kcontrol_adev(struct snd_kcontrol *kcontrol)
{
	struct snd_soc_dapm_widget *w;

	w = snd_soc_dapm_kcontrol_widget(kcontrol);

	return to_avs_dev(w->dapm->component->dev);
}

static struct avs_path_module *avs_get_volume_module(struct avs_dev *adev, u32 id)
{
	struct avs_path *path;
	struct avs_path_pipeline *ppl;
	struct avs_path_module *mod;

	spin_lock(&adev->path_list_lock);
	list_for_each_entry(path, &adev->path_list, node) {
		list_for_each_entry(ppl, &path->ppl_list, node) {
			list_for_each_entry(mod, &ppl->mod_list, node) {
				if (guid_equal(&mod->template->cfg_ext->type, &AVS_PEAKVOL_MOD_UUID)
				    && mod->template->ctl_id == id) {
					spin_unlock(&adev->path_list_lock);
					return mod;
				}
			}
		}
	}
	spin_unlock(&adev->path_list_lock);

	return NULL;
}

int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
	struct avs_control_data *ctl_data = (struct avs_control_data *)mc->dobj.private;
	struct avs_dev *adev = avs_get_kcontrol_adev(kcontrol);
	struct avs_volume_cfg *dspvols = NULL;
	struct avs_path_module *active_module;
	size_t num_dspvols;
	int ret = 0;

	/* prevent access to modules while path is being constructed */
	mutex_lock(&adev->path_mutex);

	active_module = avs_get_volume_module(adev, ctl_data->id);
	if (active_module) {
		ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id,
						 active_module->instance_id, &dspvols,
						 &num_dspvols);
		if (!ret)
			ucontrol->value.integer.value[0] = dspvols[0].target_volume;

		ret = AVS_IPC_RET(ret);
		kfree(dspvols);
	} else {
		ucontrol->value.integer.value[0] = ctl_data->volume;
	}

	mutex_unlock(&adev->path_mutex);
	return ret;
}

int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
	struct avs_control_data *ctl_data = (struct avs_control_data *)mc->dobj.private;
	struct avs_dev *adev = avs_get_kcontrol_adev(kcontrol);
	long *volume = &ctl_data->volume;
	struct avs_path_module *active_module;
	struct avs_volume_cfg dspvol = {0};
	long ctlvol = ucontrol->value.integer.value[0];
	int ret = 0, changed = 0;

	if (ctlvol < 0 || ctlvol > mc->max)
		return -EINVAL;

	/* prevent access to modules while path is being constructed */
	mutex_lock(&adev->path_mutex);

	if (*volume != ctlvol) {
		*volume = ctlvol;
		changed = 1;
	}

	active_module = avs_get_volume_module(adev, ctl_data->id);
	if (active_module) {
		dspvol.channel_id = AVS_ALL_CHANNELS_MASK;
		dspvol.target_volume = *volume;

		ret = avs_ipc_peakvol_set_volume(adev, active_module->module_id,
						 active_module->instance_id, &dspvol);
		ret = AVS_IPC_RET(ret);
	}

	mutex_unlock(&adev->path_mutex);

	return ret ? ret : changed;
}
