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

Quelle  aiu-fifo.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 <linux/clk.h>
#include <linux/dma-mapping.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>

#include "aiu-fifo.h"

#define AIU_MEM_START 0x00
#define AIU_MEM_RD 0x04
#define AIU_MEM_END 0x08
#define AIU_MEM_MASKS 0x0c
#define  AIU_MEM_MASK_CH_RD GENMASK(7, 0)
#define  AIU_MEM_MASK_CH_MEM GENMASK(15, 8)
#define AIU_MEM_CONTROL 0x10
#define  AIU_MEM_CONTROL_INIT BIT(0)
#define  AIU_MEM_CONTROL_FILL_EN BIT(1)
#define  AIU_MEM_CONTROL_EMPTY_EN BIT(2)

static struct snd_soc_dai *aiu_fifo_dai(struct snd_pcm_substream *ss)
{
 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(ss);

 return snd_soc_rtd_to_cpu(rtd, 0);
}

snd_pcm_uframes_t aiu_fifo_pointer(struct snd_soc_component *component,
       struct snd_pcm_substream *substream)
{
 struct snd_soc_dai *dai = aiu_fifo_dai(substream);
 struct aiu_fifo *fifo = snd_soc_dai_dma_data_get_playback(dai);
 struct snd_pcm_runtime *runtime = substream->runtime;
 unsigned int addr;

 addr = snd_soc_component_read(component, fifo->mem_offset + AIU_MEM_RD);

 return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr);
}

static void aiu_fifo_enable(struct snd_soc_dai *dai, bool enable)
{
 struct snd_soc_component *component = dai->component;
 struct aiu_fifo *fifo = snd_soc_dai_dma_data_get_playback(dai);
 unsigned int en_mask = (AIU_MEM_CONTROL_FILL_EN |
    AIU_MEM_CONTROL_EMPTY_EN);

 snd_soc_component_update_bits(component,
          fifo->mem_offset + AIU_MEM_CONTROL,
          en_mask, enable ? en_mask : 0);
}

int aiu_fifo_trigger(struct snd_pcm_substream *substream, int cmd,
       struct snd_soc_dai *dai)
{
 switch (cmd) {
 case SNDRV_PCM_TRIGGER_START:
 case SNDRV_PCM_TRIGGER_RESUME:
 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  aiu_fifo_enable(dai, true);
  break;
 case SNDRV_PCM_TRIGGER_SUSPEND:
 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 case SNDRV_PCM_TRIGGER_STOP:
  aiu_fifo_enable(dai, false);
  break;
 default:
  return -EINVAL;
 }

 return 0;
}

int aiu_fifo_prepare(struct snd_pcm_substream *substream,
       struct snd_soc_dai *dai)
{
 struct snd_soc_component *component = dai->component;
 struct aiu_fifo *fifo = snd_soc_dai_dma_data_get_playback(dai);

 snd_soc_component_update_bits(component,
          fifo->mem_offset + AIU_MEM_CONTROL,
          AIU_MEM_CONTROL_INIT,
          AIU_MEM_CONTROL_INIT);
 snd_soc_component_update_bits(component,
          fifo->mem_offset + AIU_MEM_CONTROL,
          AIU_MEM_CONTROL_INIT, 0);
 return 0;
}

int aiu_fifo_hw_params(struct snd_pcm_substream *substream,
         struct snd_pcm_hw_params *params,
         struct snd_soc_dai *dai)
{
 struct snd_pcm_runtime *runtime = substream->runtime;
 struct snd_soc_component *component = dai->component;
 struct aiu_fifo *fifo = snd_soc_dai_dma_data_get_playback(dai);
 dma_addr_t end;

 /* Setup the fifo boundaries */
 end = runtime->dma_addr + runtime->dma_bytes - fifo->fifo_block;
 snd_soc_component_write(component, fifo->mem_offset + AIU_MEM_START,
    runtime->dma_addr);
 snd_soc_component_write(component, fifo->mem_offset + AIU_MEM_RD,
    runtime->dma_addr);
 snd_soc_component_write(component, fifo->mem_offset + AIU_MEM_END,
    end);

 /* Setup the fifo to read all the memory - no skip */
 snd_soc_component_update_bits(component,
          fifo->mem_offset + AIU_MEM_MASKS,
          AIU_MEM_MASK_CH_RD | AIU_MEM_MASK_CH_MEM,
          FIELD_PREP(AIU_MEM_MASK_CH_RD, 0xff) |
          FIELD_PREP(AIU_MEM_MASK_CH_MEM, 0xff));

 return 0;
}

static irqreturn_t aiu_fifo_isr(int irq, void *dev_id)
{
 struct snd_pcm_substream *playback = dev_id;

 snd_pcm_period_elapsed(playback);

 return IRQ_HANDLED;
}

int aiu_fifo_startup(struct snd_pcm_substream *substream,
       struct snd_soc_dai *dai)
{
 struct aiu_fifo *fifo = snd_soc_dai_dma_data_get_playback(dai);
 int ret;

 snd_soc_set_runtime_hwparams(substream, fifo->pcm);

 /*
 * Make sure the buffer and period size are multiple of the fifo burst
 * size
 */

 ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
      SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
      fifo->fifo_block);
 if (ret)
  return ret;

 ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
      SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
      fifo->fifo_block);
 if (ret)
  return ret;

 ret = clk_prepare_enable(fifo->pclk);
 if (ret)
  return ret;

 ret = request_irq(fifo->irq, aiu_fifo_isr, 0, dev_name(dai->dev),
     substream);
 if (ret)
  clk_disable_unprepare(fifo->pclk);

 return ret;
}

void aiu_fifo_shutdown(struct snd_pcm_substream *substream,
         struct snd_soc_dai *dai)
{
 struct aiu_fifo *fifo = snd_soc_dai_dma_data_get_playback(dai);

 free_irq(fifo->irq, substream);
 clk_disable_unprepare(fifo->pclk);
}

int aiu_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd,
       struct snd_soc_dai *dai)
{
 struct snd_card *card = rtd->card->snd_card;
 struct aiu_fifo *fifo = snd_soc_dai_dma_data_get_playback(dai);
 size_t size = fifo->pcm->buffer_bytes_max;
 int ret;

 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
 if (ret)
  return ret;

 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
           card->dev, size, size);

 return 0;
}

int aiu_fifo_dai_probe(struct snd_soc_dai *dai)
{
 struct aiu_fifo *fifo;

 fifo = kzalloc(sizeof(*fifo), GFP_KERNEL);
 if (!fifo)
  return -ENOMEM;

 snd_soc_dai_dma_data_set_playback(dai, fifo);

 return 0;
}

int aiu_fifo_dai_remove(struct snd_soc_dai *dai)
{
 struct aiu_fifo *fifo = snd_soc_dai_dma_data_get_playback(dai);

 kfree(fifo);

 return 0;
}

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

¤ Dauer der Verarbeitung: 0.13 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.