Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/media/usb/gspca/stv06xx/   (Office von Apache Version 25.8.3.2©)  Datei vom 24.10.2025 mit Größe 1 kB image not shown  

Quelle  mt8365-dai-pcm.c

  Sprache: C
 

// SPDX-License-Identifier: GPL-2.0
/*
 * MediaTek 8365 ALSA SoC Audio DAI PCM Control
 *
 * Copyright (c) 2024 MediaTek Inc.
 * Authors: Jia Zeng <jia.zeng@mediatek.com>
 *          Alexandre Mergnat <amergnat@baylibre.com>
 */


#include <linux/bitops.h>
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include "mt8365-afe-clk.h"
#include "mt8365-afe-common.h"

struct mt8365_pcm_intf_data {
 bool slave_mode;
 bool lrck_inv;
 bool bck_inv;
 unsigned int format;
};

/* DAI Drivers */

static void mt8365_dai_enable_pcm1(struct mtk_base_afe *afe)
{
 regmap_update_bits(afe->regmap, PCM_INTF_CON1,
      PCM_INTF_CON1_EN, PCM_INTF_CON1_EN);
}

static void mt8365_dai_disable_pcm1(struct mtk_base_afe *afe)
{
 regmap_update_bits(afe->regmap, PCM_INTF_CON1,
      PCM_INTF_CON1_EN, 0x0);
}

static int mt8365_dai_configure_pcm1(struct snd_pcm_substream *substream,
         struct snd_soc_dai *dai)
{
 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
 struct mt8365_afe_private *afe_priv = afe->platform_priv;
 struct mt8365_pcm_intf_data *pcm_priv = afe_priv->dai_priv[MT8365_AFE_IO_PCM1];
 bool slave_mode = pcm_priv->slave_mode;
 bool lrck_inv = pcm_priv->lrck_inv;
 bool bck_inv = pcm_priv->bck_inv;
 unsigned int fmt = pcm_priv->format;
 unsigned int bit_width = dai->symmetric_sample_bits;
 unsigned int val = 0;

 if (!slave_mode) {
  val |= PCM_INTF_CON1_MASTER_MODE |
         PCM_INTF_CON1_BYPASS_ASRC;

  if (lrck_inv)
   val |= PCM_INTF_CON1_SYNC_OUT_INV;
  if (bck_inv)
   val |= PCM_INTF_CON1_BCLK_OUT_INV;
 } else {
  val |= PCM_INTF_CON1_SLAVE_MODE;

  if (lrck_inv)
   val |= PCM_INTF_CON1_SYNC_IN_INV;
  if (bck_inv)
   val |= PCM_INTF_CON1_BCLK_IN_INV;

  /* TODO: add asrc setting */
 }

 val |= FIELD_PREP(PCM_INTF_CON1_FORMAT_MASK, fmt);

 if (fmt == MT8365_PCM_FORMAT_PCMA ||
     fmt == MT8365_PCM_FORMAT_PCMB)
  val |= PCM_INTF_CON1_SYNC_LEN(1);
 else
  val |= PCM_INTF_CON1_SYNC_LEN(bit_width);

 switch (substream->runtime->rate) {
 case 48000:
  val |= PCM_INTF_CON1_FS_48K;
  break;
 case 32000:
  val |= PCM_INTF_CON1_FS_32K;
  break;
 case 16000:
  val |= PCM_INTF_CON1_FS_16K;
  break;
 case 8000:
  val |= PCM_INTF_CON1_FS_8K;
  break;
 default:
  return -EINVAL;
 }

 if (bit_width > 16)
  val |= PCM_INTF_CON1_24BIT | PCM_INTF_CON1_64BCK;
 else
  val |= PCM_INTF_CON1_16BIT | PCM_INTF_CON1_32BCK;

 val |= PCM_INTF_CON1_EXT_MODEM;

 regmap_update_bits(afe->regmap, PCM_INTF_CON1,
      PCM_INTF_CON1_CONFIG_MASK, val);

 return 0;
}

static int mt8365_dai_pcm1_startup(struct snd_pcm_substream *substream,
       struct snd_soc_dai *dai)
{
 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);

 if (snd_soc_dai_active(dai))
  return 0;

 mt8365_afe_enable_main_clk(afe);

 return 0;
}

static void mt8365_dai_pcm1_shutdown(struct snd_pcm_substream *substream,
         struct snd_soc_dai *dai)
{
 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);

 if (snd_soc_dai_active(dai))
  return;

 mt8365_dai_disable_pcm1(afe);
 mt8365_afe_disable_main_clk(afe);
}

static int mt8365_dai_pcm1_prepare(struct snd_pcm_substream *substream,
       struct snd_soc_dai *dai)
{
 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
 int ret;

 if ((snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK) +
     snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE)) > 1) {
  dev_info(afe->dev, "%s '%s' active(%u-%u) already\n",
    __func__, snd_pcm_stream_str(substream),
    snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK),
    snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE));
  return 0;
 }

 ret = mt8365_dai_configure_pcm1(substream, dai);
 if (ret)
  return ret;

 mt8365_dai_enable_pcm1(afe);

 return 0;
}

static int mt8365_dai_pcm1_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
 struct mt8365_afe_private *afe_priv = afe->platform_priv;
 struct mt8365_pcm_intf_data *pcm_priv = afe_priv->dai_priv[MT8365_AFE_IO_PCM1];

 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 case SND_SOC_DAIFMT_I2S:
  pcm_priv->format = MT8365_PCM_FORMAT_I2S;
  break;
 default:
  return -EINVAL;
 }

 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 case SND_SOC_DAIFMT_NB_NF:
  pcm_priv->bck_inv = false;
  pcm_priv->lrck_inv = false;
  break;
 case SND_SOC_DAIFMT_NB_IF:
  pcm_priv->bck_inv = false;
  pcm_priv->lrck_inv = true;
  break;
 case SND_SOC_DAIFMT_IB_NF:
  pcm_priv->bck_inv = true;
  pcm_priv->lrck_inv = false;
  break;
 case SND_SOC_DAIFMT_IB_IF:
  pcm_priv->bck_inv = true;
  pcm_priv->lrck_inv = true;
  break;
 default:
  return -EINVAL;
 }

 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 case SND_SOC_DAIFMT_CBP_CFP:
  pcm_priv->slave_mode = true;
  break;
 case SND_SOC_DAIFMT_CBC_CFC:
  pcm_priv->slave_mode = false;
  break;
 default:
  return -EINVAL;
 }

 return 0;
}

static const struct snd_soc_dai_ops mt8365_dai_pcm1_ops = {
 .startup = mt8365_dai_pcm1_startup,
 .shutdown = mt8365_dai_pcm1_shutdown,
 .prepare = mt8365_dai_pcm1_prepare,
 .set_fmt = mt8365_dai_pcm1_set_fmt,
};

static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
 {
  .name = "PCM1",
  .id = MT8365_AFE_IO_PCM1,
  .playback = {
   .stream_name = "PCM1 Playback",
   .channels_min = 1,
   .channels_max = 2,
   .rates = SNDRV_PCM_RATE_8000 |
     SNDRV_PCM_RATE_16000 |
     SNDRV_PCM_RATE_32000 |
     SNDRV_PCM_RATE_48000,
   .formats = SNDRV_PCM_FMTBIT_S16_LE |
       SNDRV_PCM_FMTBIT_S32_LE,
  },
  .capture = {
   .stream_name = "PCM1 Capture",
   .channels_min = 1,
   .channels_max = 2,
   .rates = SNDRV_PCM_RATE_8000 |
     SNDRV_PCM_RATE_16000 |
     SNDRV_PCM_RATE_32000 |
     SNDRV_PCM_RATE_48000,
   .formats = SNDRV_PCM_FMTBIT_S16_LE |
       SNDRV_PCM_FMTBIT_S32_LE,
  },
  .ops = &mt8365_dai_pcm1_ops,
  .symmetric_rate = 1,
  .symmetric_sample_bits = 1,
 }
};

/* DAI widget */

static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
 SND_SOC_DAPM_OUTPUT("PCM1 Out"),
 SND_SOC_DAPM_INPUT("PCM1 In"),
};

/* DAI route */

static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
 {"PCM1 Playback", NULL, "O07"},
 {"PCM1 Playback", NULL, "O08"},
 {"PCM1 Out", NULL, "PCM1 Playback"},

 {"I09", NULL, "PCM1 Capture"},
 {"I22", NULL, "PCM1 Capture"},
 {"PCM1 Capture", NULL, "PCM1 In"},
};

static int init_pcmif_priv_data(struct mtk_base_afe *afe)
{
 struct mt8365_afe_private *afe_priv = afe->platform_priv;
 struct mt8365_pcm_intf_data *pcmif_priv;

 pcmif_priv = devm_kzalloc(afe->dev, sizeof(struct mt8365_pcm_intf_data),
      GFP_KERNEL);
 if (!pcmif_priv)
  return -ENOMEM;

 afe_priv->dai_priv[MT8365_AFE_IO_PCM1] = pcmif_priv;
 return 0;
}

int mt8365_dai_pcm_register(struct mtk_base_afe *afe)
{
 struct mtk_base_afe_dai *dai;

 dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
 if (!dai)
  return -ENOMEM;

 list_add(&dai->list, &afe->sub_dais);
 dai->dai_drivers = mtk_dai_pcm_driver;
 dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver);
 dai->dapm_widgets = mtk_dai_pcm_widgets;
 dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets);
 dai->dapm_routes = mtk_dai_pcm_routes;
 dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes);
 return init_pcmif_priv_data(afe);
}

Messung V0.5 in Prozent
C=95 H=95 G=94

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-04-28) ¤

*© Formatika GbR, Deutschland






Versionsinformation zu Columbo

Bemerkung:

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Anfrage:

Dauer der Verarbeitung:

Sekunden

sprechenden Kalenders