Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/ethernet/mellanox/mlx5/core/esw/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 2 kB image not shown  

Quellcode-Bibliothek aiu-acodec-ctrl.c

  Sprache: C
 

// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2020 BayLibre, SAS.
// Author: Jerome Brunet <jbrunet@baylibre.com>

#include <linux/bitfield.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>

#include <dt-bindings/sound/meson-aiu.h>
#include "aiu.h"
#include "meson-codec-glue.h"

#define CTRL_DIN_EN   15
#define CTRL_CLK_INV   BIT(14)
#define CTRL_LRCLK_INV   BIT(13)
#define CTRL_I2S_IN_BCLK_SRC  BIT(11)
#define CTRL_DIN_LRCLK_SRC_SHIFT 6
#define CTRL_DIN_LRCLK_SRC  (0x3 << CTRL_DIN_LRCLK_SRC_SHIFT)
#define CTRL_BCLK_MCLK_SRC  GENMASK(54)
#define CTRL_DIN_SKEW   GENMASK(32)
#define CTRL_I2S_OUT_LANE_SRC  0

#define AIU_ACODEC_OUT_CHMAX  2

static const char * const aiu_acodec_ctrl_mux_texts[] = {
 "DISABLED""I2S""PCM",
};

static int aiu_acodec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol,
     struct snd_ctl_elem_value *ucontrol)
{
 struct snd_soc_component *component =
  snd_soc_dapm_kcontrol_component(kcontrol);
 struct snd_soc_dapm_context *dapm =
  snd_soc_dapm_kcontrol_dapm(kcontrol);
 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 unsigned int mux, changed;

 mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
 changed = snd_soc_component_test_bits(component, e->reg,
           CTRL_DIN_LRCLK_SRC,
           FIELD_PREP(CTRL_DIN_LRCLK_SRC,
        mux));

 if (!changed)
  return 0;

 /* Force disconnect of the mux while updating */
 snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL);

 snd_soc_component_update_bits(component, e->reg,
          CTRL_DIN_LRCLK_SRC |
          CTRL_BCLK_MCLK_SRC,
          FIELD_PREP(CTRL_DIN_LRCLK_SRC, mux) |
          FIELD_PREP(CTRL_BCLK_MCLK_SRC, mux));

 snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);

 return 1;
}

static SOC_ENUM_SINGLE_DECL(aiu_acodec_ctrl_mux_enum, AIU_ACODEC_CTRL,
       CTRL_DIN_LRCLK_SRC_SHIFT,
       aiu_acodec_ctrl_mux_texts);

static const struct snd_kcontrol_new aiu_acodec_ctrl_mux =
 SOC_DAPM_ENUM_EXT("ACodec Source", aiu_acodec_ctrl_mux_enum,
     snd_soc_dapm_get_enum_double,
     aiu_acodec_ctrl_mux_put_enum);

static const struct snd_kcontrol_new aiu_acodec_ctrl_out_enable =
 SOC_DAPM_SINGLE_AUTODISABLE("Switch", AIU_ACODEC_CTRL,
        CTRL_DIN_EN, 10);

static const struct snd_soc_dapm_widget aiu_acodec_ctrl_widgets[] = {
 SND_SOC_DAPM_MUX("ACODEC SRC", SND_SOC_NOPM, 00,
    &aiu_acodec_ctrl_mux),
 SND_SOC_DAPM_SWITCH("ACODEC OUT EN", SND_SOC_NOPM, 00,
       &aiu_acodec_ctrl_out_enable),
};

static int aiu_acodec_ctrl_input_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params,
        struct snd_soc_dai *dai)
{
 struct meson_codec_glue_input *data;
 int ret;

 ret = meson_codec_glue_input_hw_params(substream, params, dai);
 if (ret)
  return ret;

 /* The glue will provide 1 lane out of the 4 to the output */
 data = meson_codec_glue_input_get_data(dai);
 data->params.channels_min = min_t(unsigned int, AIU_ACODEC_OUT_CHMAX,
       data->params.channels_min);
 data->params.channels_max = min_t(unsigned int, AIU_ACODEC_OUT_CHMAX,
       data->params.channels_max);

 return 0;
}

static const struct snd_soc_dai_ops aiu_acodec_ctrl_input_ops = {
 .probe  = meson_codec_glue_input_dai_probe,
 .remove  = meson_codec_glue_input_dai_remove,
 .hw_params = aiu_acodec_ctrl_input_hw_params,
 .set_fmt = meson_codec_glue_input_set_fmt,
};

static const struct snd_soc_dai_ops aiu_acodec_ctrl_output_ops = {
 .startup = meson_codec_glue_output_startup,
};

#define AIU_ACODEC_CTRL_FORMATS     \
 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
  SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | \
  SNDRV_PCM_FMTBIT_S32_LE)

#define AIU_ACODEC_STREAM(xname, xsuffix, xchmax)  \
{        \
 .stream_name = xname " " xsuffix,   \
 .channels_min = 1,     \
 .channels_max = (xchmax),    \
 .rate_min       = 5512,     \
 .rate_max = 192000,    \
 .formats = AIU_ACODEC_CTRL_FORMATS,  \
}

#define AIU_ACODEC_INPUT(xname) {    \
 .name = "ACODEC CTRL " xname,    \
 .playback = AIU_ACODEC_STREAM(xname, "Playback"8), \
 .ops = &aiu_acodec_ctrl_input_ops,   \
}

#define AIU_ACODEC_OUTPUT(xname) {    \
 .name = "ACODEC CTRL " xname,    \
 .capture = AIU_ACODEC_STREAM(xname, "Capture", AIU_ACODEC_OUT_CHMAX), \
 .ops = &aiu_acodec_ctrl_output_ops,   \
}

static struct snd_soc_dai_driver aiu_acodec_ctrl_dai_drv[] = {
 [CTRL_I2S] = AIU_ACODEC_INPUT("ACODEC I2S IN"),
 [CTRL_PCM] = AIU_ACODEC_INPUT("ACODEC PCM IN"),
 [CTRL_OUT] = AIU_ACODEC_OUTPUT("ACODEC OUT"),
};

static const struct snd_soc_dapm_route aiu_acodec_ctrl_routes[] = {
 { "ACODEC SRC""I2S""ACODEC I2S IN Playback" },
 { "ACODEC SRC""PCM""ACODEC PCM IN Playback" },
 { "ACODEC OUT EN""Switch""ACODEC SRC" },
 { "ACODEC OUT Capture", NULL, "ACODEC OUT EN" },
};

static const struct snd_kcontrol_new aiu_acodec_ctrl_controls[] = {
 SOC_SINGLE("ACODEC I2S Lane Select", AIU_ACODEC_CTRL,
     CTRL_I2S_OUT_LANE_SRC, 30),
};

static int aiu_acodec_of_xlate_dai_name(struct snd_soc_component *component,
     const struct of_phandle_args *args,
     const char **dai_name)
{
 return aiu_of_xlate_dai_name(component, args, dai_name, AIU_ACODEC);
}

static int aiu_acodec_ctrl_component_probe(struct snd_soc_component *component)
{
 /*
 * NOTE: Din Skew setting
 * According to the documentation, the following update adds one delay
 * to the din line. Without this, the output saturates. This happens
 * regardless of the link format (i2s or left_j) so it is not clear what
 * it actually does but it seems to be required
 */

 snd_soc_component_update_bits(component, AIU_ACODEC_CTRL,
          CTRL_DIN_SKEW,
          FIELD_PREP(CTRL_DIN_SKEW, 2));

 return 0;
}

static const struct snd_soc_component_driver aiu_acodec_ctrl_component = {
 .name   = "AIU Internal DAC Codec Control",
 .probe   = aiu_acodec_ctrl_component_probe,
 .controls  = aiu_acodec_ctrl_controls,
 .num_controls  = ARRAY_SIZE(aiu_acodec_ctrl_controls),
 .dapm_widgets  = aiu_acodec_ctrl_widgets,
 .num_dapm_widgets = ARRAY_SIZE(aiu_acodec_ctrl_widgets),
 .dapm_routes  = aiu_acodec_ctrl_routes,
 .num_dapm_routes = ARRAY_SIZE(aiu_acodec_ctrl_routes),
 .of_xlate_dai_name = aiu_acodec_of_xlate_dai_name,
 .endianness  = 1,
#ifdef CONFIG_DEBUG_FS
 .debugfs_prefix  = "acodec",
#endif
};

int aiu_acodec_ctrl_register_component(struct device *dev)
{
 return snd_soc_register_component(dev, &aiu_acodec_ctrl_component,
       aiu_acodec_ctrl_dai_drv,
       ARRAY_SIZE(aiu_acodec_ctrl_dai_drv));
}

Messung V0.5 in Prozent
C=97 H=100 G=98

¤ 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.0.10Bemerkung:  (vorverarbeitet am  2026-06-05) ¤

*Bot Zugriff






Wurzel

Bemerkung:

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Anfrage:

Dauer der Verarbeitung:

Sekunden

sprechenden Kalenders