Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2//
  3// Copyright(c) 2021-2022 Intel Corporation
  4//
  5// Authors: Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
  6//          Cezary Rojewski <cezary.rojewski@intel.com>
  7//
  8
  9#include <sound/soc.h>
 10#include "avs.h"
 11#include "control.h"
 12#include "messages.h"
 13#include "path.h"
 14
 15static struct avs_dev *avs_get_kcontrol_adev(struct snd_kcontrol *kcontrol)
 16{
 17	struct snd_soc_dapm_widget *w;
 18
 19	w = snd_soc_dapm_kcontrol_widget(kcontrol);
 20
 21	return to_avs_dev(w->dapm->component->dev);
 22}
 23
 24static struct avs_path_module *avs_get_volume_module(struct avs_dev *adev, u32 id)
 25{
 26	struct avs_path *path;
 27	struct avs_path_pipeline *ppl;
 28	struct avs_path_module *mod;
 29
 30	spin_lock(&adev->path_list_lock);
 31	list_for_each_entry(path, &adev->path_list, node) {
 32		list_for_each_entry(ppl, &path->ppl_list, node) {
 33			list_for_each_entry(mod, &ppl->mod_list, node) {
 34				if (guid_equal(&mod->template->cfg_ext->type, &AVS_PEAKVOL_MOD_UUID)
 35				    && mod->template->ctl_id == id) {
 36					spin_unlock(&adev->path_list_lock);
 37					return mod;
 38				}
 39			}
 40		}
 41	}
 42	spin_unlock(&adev->path_list_lock);
 43
 44	return NULL;
 45}
 46
 47int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 48{
 49	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
 50	struct avs_control_data *ctl_data = (struct avs_control_data *)mc->dobj.private;
 51	struct avs_dev *adev = avs_get_kcontrol_adev(kcontrol);
 52	struct avs_volume_cfg *dspvols = NULL;
 53	struct avs_path_module *active_module;
 54	size_t num_dspvols;
 55	int ret = 0;
 56
 57	/* prevent access to modules while path is being constructed */
 58	mutex_lock(&adev->path_mutex);
 59
 60	active_module = avs_get_volume_module(adev, ctl_data->id);
 61	if (active_module) {
 62		ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id,
 63						 active_module->instance_id, &dspvols,
 64						 &num_dspvols);
 65		if (!ret)
 66			ucontrol->value.integer.value[0] = dspvols[0].target_volume;
 67
 68		ret = AVS_IPC_RET(ret);
 69		kfree(dspvols);
 70	} else {
 71		ucontrol->value.integer.value[0] = ctl_data->volume;
 72	}
 73
 74	mutex_unlock(&adev->path_mutex);
 75	return ret;
 76}
 77
 78int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 79{
 80	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
 81	struct avs_control_data *ctl_data = (struct avs_control_data *)mc->dobj.private;
 82	struct avs_dev *adev = avs_get_kcontrol_adev(kcontrol);
 83	long *volume = &ctl_data->volume;
 84	struct avs_path_module *active_module;
 85	struct avs_volume_cfg dspvol = {0};
 86	long ctlvol = ucontrol->value.integer.value[0];
 87	int ret = 0, changed = 0;
 88
 89	if (ctlvol < 0 || ctlvol > mc->max)
 90		return -EINVAL;
 91
 92	/* prevent access to modules while path is being constructed */
 93	mutex_lock(&adev->path_mutex);
 94
 95	if (*volume != ctlvol) {
 96		*volume = ctlvol;
 97		changed = 1;
 98	}
 99
100	active_module = avs_get_volume_module(adev, ctl_data->id);
101	if (active_module) {
102		dspvol.channel_id = AVS_ALL_CHANNELS_MASK;
103		dspvol.target_volume = *volume;
104
105		ret = avs_ipc_peakvol_set_volume(adev, active_module->module_id,
106						 active_module->instance_id, &dspvol);
107		ret = AVS_IPC_RET(ret);
108	}
109
110	mutex_unlock(&adev->path_mutex);
111
112	return ret ? ret : changed;
113}
v6.8
  1// SPDX-License-Identifier: GPL-2.0-only
  2//
  3// Copyright(c) 2021-2022 Intel Corporation. All rights reserved.
  4//
  5// Authors: Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
  6//          Cezary Rojewski <cezary.rojewski@intel.com>
  7//
  8
  9#include <sound/soc.h>
 10#include "avs.h"
 11#include "control.h"
 12#include "messages.h"
 13#include "path.h"
 14
 15static struct avs_dev *avs_get_kcontrol_adev(struct snd_kcontrol *kcontrol)
 16{
 17	struct snd_soc_dapm_widget *w;
 18
 19	w = snd_soc_dapm_kcontrol_widget(kcontrol);
 20
 21	return to_avs_dev(w->dapm->component->dev);
 22}
 23
 24static struct avs_path_module *avs_get_volume_module(struct avs_dev *adev, u32 id)
 25{
 26	struct avs_path *path;
 27	struct avs_path_pipeline *ppl;
 28	struct avs_path_module *mod;
 29
 30	spin_lock(&adev->path_list_lock);
 31	list_for_each_entry(path, &adev->path_list, node) {
 32		list_for_each_entry(ppl, &path->ppl_list, node) {
 33			list_for_each_entry(mod, &ppl->mod_list, node) {
 34				if (guid_equal(&mod->template->cfg_ext->type, &AVS_PEAKVOL_MOD_UUID)
 35				    && mod->template->ctl_id == id) {
 36					spin_unlock(&adev->path_list_lock);
 37					return mod;
 38				}
 39			}
 40		}
 41	}
 42	spin_unlock(&adev->path_list_lock);
 43
 44	return NULL;
 45}
 46
 47int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 48{
 49	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
 50	struct avs_control_data *ctl_data = (struct avs_control_data *)mc->dobj.private;
 51	struct avs_dev *adev = avs_get_kcontrol_adev(kcontrol);
 52	struct avs_volume_cfg *dspvols = NULL;
 53	struct avs_path_module *active_module;
 54	size_t num_dspvols;
 55	int ret = 0;
 56
 57	/* prevent access to modules while path is being constructed */
 58	mutex_lock(&adev->path_mutex);
 59
 60	active_module = avs_get_volume_module(adev, ctl_data->id);
 61	if (active_module) {
 62		ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id,
 63						 active_module->instance_id, &dspvols,
 64						 &num_dspvols);
 65		if (!ret)
 66			ucontrol->value.integer.value[0] = dspvols[0].target_volume;
 67
 68		ret = AVS_IPC_RET(ret);
 69		kfree(dspvols);
 70	} else {
 71		ucontrol->value.integer.value[0] = ctl_data->volume;
 72	}
 73
 74	mutex_unlock(&adev->path_mutex);
 75	return ret;
 76}
 77
 78int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 79{
 80	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
 81	struct avs_control_data *ctl_data = (struct avs_control_data *)mc->dobj.private;
 82	struct avs_dev *adev = avs_get_kcontrol_adev(kcontrol);
 83	long *volume = &ctl_data->volume;
 84	struct avs_path_module *active_module;
 85	struct avs_volume_cfg dspvol = {0};
 86	long ctlvol = ucontrol->value.integer.value[0];
 87	int ret = 0, changed = 0;
 88
 89	if (ctlvol < 0 || ctlvol > mc->max)
 90		return -EINVAL;
 91
 92	/* prevent access to modules while path is being constructed */
 93	mutex_lock(&adev->path_mutex);
 94
 95	if (*volume != ctlvol) {
 96		*volume = ctlvol;
 97		changed = 1;
 98	}
 99
100	active_module = avs_get_volume_module(adev, ctl_data->id);
101	if (active_module) {
102		dspvol.channel_id = AVS_ALL_CHANNELS_MASK;
103		dspvol.target_volume = *volume;
104
105		ret = avs_ipc_peakvol_set_volume(adev, active_module->module_id,
106						 active_module->instance_id, &dspvol);
107		ret = AVS_IPC_RET(ret);
108	}
109
110	mutex_unlock(&adev->path_mutex);
111
112	return ret ? ret : changed;
113}