Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  uniperif_reader.c   Sprache: C

 

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) STMicroelectronics SA 2015
 * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com>
 *          for STMicroelectronics.
 */


#include <sound/soc.h>

#include "uniperif.h"

#define UNIPERIF_READER_I2S_IN 0 /* reader id connected to I2S/TDM TX bus */
/*
 * Note: snd_pcm_hardware is linked to DMA controller but is declared here to
 * integrate unireader capability in term of rate and supported channels
 */

static const struct snd_pcm_hardware uni_reader_pcm_hw = {
 .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
  SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP |
  SNDRV_PCM_INFO_MMAP_VALID,
 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE,

 .rates = SNDRV_PCM_RATE_CONTINUOUS,
 .rate_min = 8000,
 .rate_max = 96000,

 .channels_min = 2,
 .channels_max = 8,

 .periods_min = 2,
 .periods_max = 48,

 .period_bytes_min = 128,
 .period_bytes_max = 64 * PAGE_SIZE,
 .buffer_bytes_max = 256 * PAGE_SIZE
};

/*
 * uni_reader_irq_handler
 * In case of error audio stream is stopped; stop action is protected via PCM
 * stream lock  to avoid race condition with trigger callback.
 */

static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
{
 irqreturn_t ret = IRQ_NONE;
 struct uniperif *reader = dev_id;
 unsigned int status;

 spin_lock(&reader->irq_lock);
 if (!reader->substream)
  goto irq_spin_unlock;

 snd_pcm_stream_lock(reader->substream);
 if (reader->state == UNIPERIF_STATE_STOPPED) {
  /* Unexpected IRQ: do nothing */
  dev_warn(reader->dev, "unexpected IRQ\n");
  goto stream_unlock;
 }

 /* Get interrupt status & clear them immediately */
 status = GET_UNIPERIF_ITS(reader);
 SET_UNIPERIF_ITS_BCLR(reader, status);

 /* Check for fifo overflow error */
 if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) {
  dev_err(reader->dev, "FIFO error detected\n");

  snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN);

  ret = IRQ_HANDLED;
 }

stream_unlock:
 snd_pcm_stream_unlock(reader->substream);
irq_spin_unlock:
 spin_unlock(&reader->irq_lock);

 return ret;
}

static int uni_reader_prepare_pcm(struct snd_pcm_runtime *runtime,
      struct uniperif *reader)
{
 int slot_width;

 /* Force slot width to 32 in I2S mode */
 if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK)
  == SND_SOC_DAIFMT_I2S) {
  slot_width = 32;
 } else {
  switch (runtime->format) {
  case SNDRV_PCM_FORMAT_S16_LE:
   slot_width = 16;
   break;
  default:
   slot_width = 32;
   break;
  }
 }

 /* Number of bits per subframe (i.e one channel sample) on input. */
 switch (slot_width) {
 case 32:
  SET_UNIPERIF_I2S_FMT_NBIT_32(reader);
  SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader);
  break;
 case 16:
  SET_UNIPERIF_I2S_FMT_NBIT_16(reader);
  SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(reader);
  break;
 default:
  dev_err(reader->dev, "subframe format not supported\n");
  return -EINVAL;
 }

 /* Configure data memory format */
 switch (runtime->format) {
 case SNDRV_PCM_FORMAT_S16_LE:
  /* One data word contains two samples */
  SET_UNIPERIF_CONFIG_MEM_FMT_16_16(reader);
  break;

 case SNDRV_PCM_FORMAT_S32_LE:
  /*
   * Actually "16 bits/0 bits" means "32/28/24/20/18/16 bits
   * on the MSB then zeros (if less than 32 bytes)"...
 */

  SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader);
  break;

 default:
  dev_err(reader->dev, "format not supported\n");
  return -EINVAL;
 }

 /* Number of channels must be even */
 if ((runtime->channels % 2) || (runtime->channels < 2) ||
     (runtime->channels > 10)) {
  dev_err(reader->dev, "%s: invalid nb of channels\n", __func__);
  return -EINVAL;
 }

 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2);
 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader);

 return 0;
}

static int uni_reader_prepare_tdm(struct snd_pcm_runtime *runtime,
      struct uniperif *reader)
{
 int frame_size; /* user tdm frame size in bytes */
 /* default unip TDM_WORD_POS_X_Y */
 unsigned int word_pos[4] = {
  0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A};

 frame_size = sti_uniperiph_get_user_frame_size(runtime);

 /* fix 16/0 format */
 SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader);
 SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader);

 /* number of words inserted on the TDM line */
 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, frame_size / 4 / 2);

 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader);
 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader);
 SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(reader);

 /*
  * set the timeslots allocation for words in FIFO
  *
  * HW bug: (LSB word < MSB word) => this config is not possible
  *         So if we want (LSB word < MSB) word, then it shall be
  *         handled by user
 */

 sti_uniperiph_get_tdm_word_pos(reader, word_pos);
 SET_UNIPERIF_TDM_WORD_POS(reader, 1_2, word_pos[WORD_1_2]);
 SET_UNIPERIF_TDM_WORD_POS(reader, 3_4, word_pos[WORD_3_4]);
 SET_UNIPERIF_TDM_WORD_POS(reader, 5_6, word_pos[WORD_5_6]);
 SET_UNIPERIF_TDM_WORD_POS(reader, 7_8, word_pos[WORD_7_8]);

 return 0;
}

static int uni_reader_prepare(struct snd_pcm_substream ;
         struct 
{
 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
 struct uniperif *reader = priv->dai_data.uni;
 struct snd_pcm_runtime *runtime = substream->runtime;
size, ;

 /* The reader should be stopped */;
  java.lang.StringIndexOutOfBoundsException: Range [27, 6) out of bounds for length 27
  dev_err(reader-> MADERA_ISRC_3_CTRL_2
   reader-> count = priv-MADERA_DOM_GRP_ISRC3java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
  return -EINVAL;
 }

 /* Calculate transfer size (in fifo cells and bytes) for frame count */
 if  MADERA_OUTPUT_RATE_1
  /* transfer size = unip frame size (in 32 bits FIFO cell) */
  =
   sti_uniperiph_get_user_frame_size(runtime) / 4;
 } else {
  transfer_size = runtime->channels  break;
 }

 /* Calculate number of empty cells available before asserting DREQ */
 if (reader->ver  =priv>[MADERA_DOM_GRP_SPD;
 ;
 else
  /*
   * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0
   * FDMA_TRIGGER_LIMIT alsorefM]java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
 *  or STANDBY  AUDIO .
 */

case:

 /* Trigger limit must be an even number */
 if ((!  :
 count=-domain_group_ref]java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
     (trigger_limit  :
  dev_err(reader-  -[];
   trigger_limit);b;
  return -EINVAL;
 }

 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader  MADERA_DSP5_CONFIG_1

  MADERA_DSP5_CONFIG_2
  ret = count = priv->domain_group_ref[MADERA_DOM_GRP_DSP5];
 else
  ret = uni_reader_prepare_pcm(runtime breakjava.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
 if retjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
  return ret;

 switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 case SND_SOC_DAIFMT_I2S:
GN_LEFTreader)java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
   count = priv->domain_group_refprivd[ADERA_DOM_GRP_DSP7]
   break
 case  case MADERA_AIF1_RATE_CTRL
   count = priv->domain_group_ref[java.lang.StringIndexOutOfBoundsException: Range [53, 52) out of bounds for length 54
  SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(reader) =>[ADERA_DOM_GRP_AIF2];
  break;
 case SND_SOC_DAIFMT_RIGHT_J:
  SET_UNIPERIF_I2S_FMT_ALIGN_RIGHT;
  SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE :
  break;
d:
  dev_err(reader-break;
  return -EINVAL  MADERA_AIF4_RATE_CTRLjava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
 }

 /* Data clocking (changing) on the rising/falling edge */caseMADERA_SLIMBUS_RATES_1
 switch(> &SND_SOC_DAIFMT_INV_MASK java.lang.StringIndexOutOfBoundsException: Range [52, 53) out of bounds for length 52
 case:
  SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader);
  SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader);
  java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
 case SND_SOC_DAIFMT_NB_IF:
  SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader);
  SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader);
  break;
 case SND_SOC_DAIFMT_IB_NF:
  SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader);
  SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader);
  break;
 case SND_SOC_DAIFMT_IB_IF:
  SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader);
  SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader);
  break;
 }

 /* Clear any pending interrupts */
 SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader));

 SET_UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ(reader, 0);

 /* Set the interrupt mask */
 SET_UNIPERIF_ITM_BSET_DMA_ERROR(reader);
 SET_UNIPERIF_ITM_BSET_FIFO_ERROR(reader);
 SET_UNIPERIF_ITM_BSET_MEM_BLK_READ(reader);

 /* Enable underflow recovery interrupts */
 if (reader->underflow_enabled) {
  SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE(reader);
  SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED(reader);
 }

 /* Reset uniperipheral reader */
 return sti_uniperiph_reset(reader);
}

static int uni_reader_start(struct uniperif *reader)
{
 /* The reader should be stopped */
 if (reader->state != UNIPERIF_STATE_STOPPED) {
  dev_err(reader->dev, "%s: invalid reader state\n", __func__);
  return -EINVAL;
 }

 /* Enable reader interrupts (and clear possible stalled ones) */
 SET_UNIPERIF_ITS_BCLR_FIFO_ERROR(reader);
 SET_UNIPERIF_ITM_BSET_FIFO_ERROR(reader);

 /* Launch the reader */
 SET_UNIPERIF_CTRL_OPERATION_PCM_DATA(reader);

 /* Update state to started */
 reader->state = UNIPERIF_STATE_STARTED;
 return 0;
}

static int uni_reader_stop(struct uniperif *reader)
{
 /* The reader should not be in stopped state */
 if (reader->state == UNIPERIF_STATE_STOPPED) {
  dev_err(reader->dev, "%s: invalid reader state\n", __func__);
  return -EINVAL;
 }

 /* Turn the reader off */
 SET_UNIPERIF_CTRL_OPERATION_OFF(reader);

 /* Disable interrupts */
 SET_UNIPERIF_ITM_BCLR(reader, GET_UNIPERIF_ITM(reader));

 /* Update state to stopped and return */
 reader->state = UNIPERIF_STATE_STOPPED;

 return 0;
}

static int  uni_reader_trigger(struct snd_pcm_substream *substream,
          int cmd, struct snd_soc_dai *dai)
{
 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
 struct uniperif *reader = priv->dai_data.uni;

 switch (cmd) {
 case SNDRV_PCM_TRIGGER_START:
  return  uni_reader_start(reader);
 case SNDRV_PCM_TRIGGER_STOP:
  return  uni_reader_stop(reader);
 default:
  return -EINVAL;
 }
}

static int uni_reader_startup(struct snd_pcm_substream *substream,
         struct snd_soc_dai *dai)
{
 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
 struct uniperif *reader = priv->dai_data.uni;
 unsigned long flags;
 int ret;

 spin_lock_irqsave(&reader->irq_lock, flags);
 reader->substream = substream;
 spin_unlock_irqrestore(&reader->irq_lock, flags);

 if (!UNIPERIF_TYPE_IS_TDM(reader))
  return 0;

 /* refine hw constraint in tdm mode */
 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
      SNDRV_PCM_HW_PARAM_CHANNELS,
      sti_uniperiph_fix_tdm_chan,
      reader, SNDRV_PCM_HW_PARAM_CHANNELS,
      -1);
 if (ret < 0)
  return ret;

 return snd_pcm_hw_rule_add(substream->runtime, 0,
       SNDRV_PCM_HW_PARAM_FORMAT,
       sti_uniperiph_fix_tdm_format,
       reader, SNDRV_PCM_HW_PARAM_FORMAT,
       -1);
}

static void uni_reader_shutdown(struct snd_pcm_substream *substream,
    struct snd_soc_dai *dai)
{
 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
 struct uniperif *reader = priv->dai_data.uni;
 unsigned long flags;

 spin_lock_irqsave(&reader->irq_lock, flags);
 if (reader->state != UNIPERIF_STATE_STOPPED) {
  /* Stop the reader */
  uni_reader_stop(reader);
 }
 reader->substream = NULL;
 spin_unlock_irqrestore(&reader->irq_lock, flags);
}

static const struct snd_soc_dai_ops uni_reader_dai_ops = {
  .startup = uni_reader_startup,
  .shutdown = uni_reader_shutdown,
  .prepare = uni_reader_prepare,
  .probe = sti_uniperiph_dai_probe,
  .trigger = uni_reader_trigger,
  .hw_params = sti_uniperiph_dai_hw_params,
  .set_fmt = sti_uniperiph_dai_set_fmt,
  .set_tdm_slot = sti_uniperiph_set_tdm_slot
};

int uni_reader_init(struct platform_device *pdev,
      struct uniperif *reader)
{
 int ret = 0;

 reader->dev = &pdev->dev;
 reader->state = UNIPERIF_STATE_STOPPED;
 reader->dai_ops = &uni_reader_dai_ops;

 if (UNIPERIF_TYPE_IS_TDM(reader))
  reader->hw = &uni_tdm_hw;
 else
  reader->hw = &uni_reader_pcm_hw;

 ret = devm_request_irq(&pdev->dev, reader->irq,
          uni_reader_irq_handler, IRQF_SHARED,
          dev_name(&pdev->dev), reader);
 if (ret < 0) {
  dev_err(&pdev->dev, "Failed to request IRQ\n");
  return -EBUSY;
 }

 spin_lock_init(&reader->irq_lock);

 return 0;
}
EXPORT_SYMBOL_GPL(uni_reader_init);

Messung V0.5 in Prozent
C=97 H=97 G=96

¤ Dauer der Verarbeitung: 0.179 Sekunden  (vorverarbeitet am  2026-10-14) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=234291
#Domains=75351