Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/sound/soc/intel/avs/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  control.c   Sprache: C

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

#include <linux/cleanup.h>
#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) {
    guid_t *type = &mod->template->cfg_ext->type;

    if ((guid_equal(type, &AVS_PEAKVOL_MOD_UUID) ||
         guid_equal(type, &AVS_GAIN_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 *kctl, struct snd_ctl_elem_value *uctl)
{
 struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
 struct avs_control_data *ctl_data = mc->dobj.private;
 struct avs_path_module *active_module;
 struct avs_volume_cfg *dspvols;
 struct avs_dev *adev;
 size_t num_dspvols;
 int ret, i;

 adev = avs_get_kcontrol_adev(kctl);

 /* Prevent access to modules while path is being constructed. */
 guard(mutex)(&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)
   return AVS_IPC_RET(ret);

  /* Do not copy more than the control can store. */
  num_dspvols = min_t(u32, num_dspvols, SND_SOC_TPLG_MAX_CHAN);
  for (i = 0; i < num_dspvols; i++)
   ctl_data->values[i] = dspvols[i].target_volume;
  kfree(dspvols);
 }

 memcpy(uctl->value.integer.value, ctl_data->values, sizeof(ctl_data->values));
 return 0;
}

int avs_control_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
{
 struct avs_path_module *active_module;
 struct avs_control_data *ctl_data;
 struct soc_mixer_control *mc;
 struct avs_dev *adev;
 long *input;
 int ret, i;

 mc = (struct soc_mixer_control *)kctl->private_value;
 ctl_data = mc->dobj.private;
 adev = avs_get_kcontrol_adev(kctl);
 input = uctl->value.integer.value;
 i = 0;

 /* mc->num_channels can be 0. */
 do {
  if (input[i] < mc->min || input[i] > mc->max)
   return -EINVAL;
 } while (++i < mc->num_channels);

 if (!memcmp(ctl_data->values, input, sizeof(ctl_data->values)))
  return 0;

 /* Prevent access to modules while path is being constructed. */
 guard(mutex)(&adev->path_mutex);

 active_module = avs_get_volume_module(adev, ctl_data->id);
 if (active_module) {
  ret = avs_peakvol_set_volume(adev, active_module, mc, input);
  if (ret)
   return ret;
 }

 memcpy(ctl_data->values, input, sizeof(ctl_data->values));
 return 1;
}

int avs_control_volume_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
{
 struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;

 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 uinfo->count = max_t(u32, 1, mc->num_channels);
 uinfo->value.integer.min = 0;
 uinfo->value.integer.max = mc->max;
 return 0;
}

int avs_control_mute_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
{
 struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
 struct avs_control_data *ctl_data = mc->dobj.private;
 struct avs_path_module *active_module;
 struct avs_mute_cfg *dspmutes;
 struct avs_dev *adev;
 size_t num_dspmutes;
 int ret, i;

 adev = avs_get_kcontrol_adev(kctl);

 /* Prevent access to modules while path is being constructed. */
 guard(mutex)(&adev->path_mutex);

 active_module = avs_get_volume_module(adev, ctl_data->id);
 if (active_module) {
  ret = avs_ipc_peakvol_get_mute(adev, active_module->module_id,
            active_module->instance_id, &dspmutes,
            &num_dspmutes);
  if (ret)
   return AVS_IPC_RET(ret);

  /* Do not copy more than the control can store. */
  num_dspmutes = min_t(u32, num_dspmutes, SND_SOC_TPLG_MAX_CHAN);
  for (i = 0; i < num_dspmutes; i++)
   ctl_data->values[i] = !dspmutes[i].mute;
  kfree(dspmutes);
 }

 memcpy(uctl->value.integer.value, ctl_data->values, sizeof(ctl_data->values));
 return 0;
}

int avs_control_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
{
 struct avs_path_module *active_module;
 struct avs_control_data *ctl_data;
 struct soc_mixer_control *mc;
 struct avs_dev *adev;
 long *input;
 int ret, i;

 mc = (struct soc_mixer_control *)kctl->private_value;
 ctl_data = mc->dobj.private;
 adev = avs_get_kcontrol_adev(kctl);
 input = uctl->value.integer.value;
 i = 0;

 /* mc->num_channels can be 0. */
 do {
  if (input[i] < mc->min || input[i] > mc->max)
   return -EINVAL;
 } while (++i < mc->num_channels);

 if (!memcmp(ctl_data->values, input, sizeof(ctl_data->values)))
  return 0;

 /* Prevent access to modules while path is being constructed. */
 guard(mutex)(&adev->path_mutex);

 active_module = avs_get_volume_module(adev, ctl_data->id);
 if (active_module) {
  ret = avs_peakvol_set_mute(adev, active_module, mc, input);
  if (ret)
   return ret;
 }

 memcpy(ctl_data->values, input, sizeof(ctl_data->values));
 return 1;
}

int avs_control_mute_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
{
 struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;

 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 uinfo->count = max_t(u32, 1, mc->num_channels);
 uinfo->value.integer.min = 0;
 uinfo->value.integer.max = mc->max;
 return 0;
}

Messung V0.5
C=94 H=89 G=91

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.