linux/sound/drivers/pcm-indirect2.h
<<
>>
Prefs
   1/*
   2 * Helper functions for indirect PCM data transfer to a simple FIFO in
   3 * hardware (small, no possibility to read "hardware io position",
   4 * updating position done by interrupt, ...)
   5 *
   6 *  Copyright (c) by 2007  Joachim Foerster <JOFT@gmx.de>
   7 *
   8 *  Based on "pcm-indirect.h" (alsa-driver-1.0.13) by
   9 *
  10 *  Copyright (c) by Takashi Iwai <tiwai@suse.de>
  11 *                   Jaroslav Kysela <perex@suse.cz>
  12 *
  13 *   This program is free software; you can redistribute it and/or modify
  14 *   it under the terms of the GNU General Public License as published by
  15 *   the Free Software Foundation; either version 2 of the License, or
  16 *   (at your option) any later version.
  17 *
  18 *   This program is distributed in the hope that it will be useful,
  19 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 *   GNU General Public License for more details.
  22 *
  23 *   You should have received a copy of the GNU General Public License
  24 *   along with this program; if not, write to the Free Software
  25 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26 */
  27
  28#ifndef __SOUND_PCM_INDIRECT2_H
  29#define __SOUND_PCM_INDIRECT2_H
  30
  31/* struct snd_pcm_substream, struct snd_pcm_runtime, snd_pcm_uframes_t */
  32#include <sound/pcm.h>
  33
  34/* Debug options for code which may be removed completely in a final version */
  35#ifdef CONFIG_SND_DEBUG
  36#define SND_PCM_INDIRECT2_STAT    /* turn on some "statistics" about the
  37                                   * process of copying bytes from the
  38                                   * intermediate buffer to the hardware
  39                                   * fifo and the other way round
  40                                   */
  41#endif
  42
  43struct snd_pcm_indirect2 {
  44        unsigned int hw_buffer_size;  /* Byte size of hardware buffer */
  45        int hw_ready;                 /* playback: 1 = hw fifo has room left,
  46                                       * 0 = hw fifo is full
  47                                       */
  48        unsigned int min_multiple;
  49        int min_periods;              /* counts number of min. periods until
  50                                       * min_multiple is reached
  51                                       */
  52        int min_period_count;         /* counts bytes to count number of
  53                                       * min. periods
  54                                       */
  55
  56        unsigned int sw_buffer_size;  /* Byte size of software buffer */
  57
  58        /* sw_data: position in intermediate buffer, where we will read (or
  59         *          write) from/to next time (to transfer data to/from HW)
  60         */
  61        unsigned int sw_data;         /* Offset to next dst (or src) in sw
  62                                       * ring buffer
  63                                       */
  64        /* easiest case (playback):
  65         * sw_data is nearly the same as ~ runtime->control->appl_ptr, with the
  66         * exception that sw_data is "behind" by the number if bytes ALSA wrote
  67         * to the intermediate buffer last time.
  68         * A call to ack() callback synchronizes both indirectly.
  69         */
  70
  71        /* We have no real sw_io pointer here. Usually sw_io is pointing to the
  72         * current playback/capture position _inside_ the hardware. Devices
  73         * with plain FIFOs often have no possibility to publish this position.
  74         * So we say: if sw_data is updated, that means bytes were copied to
  75         * the hardware, we increase sw_io by that amount, because there have
  76         * to be as much bytes which were played. So sw_io will stay behind
  77         * sw_data all the time and has to converge to sw_data at the end of
  78         * playback.
  79         */
  80        unsigned int sw_io;           /* Current software pointer in bytes */
  81
  82        /* sw_ready: number of bytes ALSA copied to the intermediate buffer, so
  83         * it represents the number of bytes which wait for transfer to the HW
  84         */
  85        int sw_ready;             /* Bytes ready to be transferred to/from hw */
  86
  87        /* appl_ptr: last known position of ALSA (where ALSA is going to write
  88         * next time into the intermediate buffer
  89         */
  90        snd_pcm_uframes_t appl_ptr;   /* Last seen appl_ptr */
  91
  92        unsigned int bytes2hw;
  93        int check_alignment;
  94
  95#ifdef SND_PCM_INDIRECT2_STAT
  96        unsigned int zeros2hw;
  97        unsigned int mul_elapsed;
  98        unsigned int mul_elapsed_real;
  99        unsigned long firstbytetime;
 100        unsigned long lastbytetime;
 101        unsigned long firstzerotime;
 102        unsigned int byte_sizes[64];
 103        unsigned int zero_sizes[64];
 104        unsigned int min_adds[8];
 105        unsigned int mul_adds[8];
 106        unsigned int zero_times[3750];  /* = 15s */
 107        unsigned int zero_times_saved;
 108        unsigned int zero_times_notsaved;
 109        unsigned int irq_occured;
 110        unsigned int pointer_calls;
 111        unsigned int lastdifftime;
 112#endif
 113};
 114
 115typedef size_t (*snd_pcm_indirect2_copy_t) (struct snd_pcm_substream *substream,
 116                                           struct snd_pcm_indirect2 *rec,
 117                                           size_t bytes);
 118typedef size_t (*snd_pcm_indirect2_zero_t) (struct snd_pcm_substream *substream,
 119                                           struct snd_pcm_indirect2 *rec);
 120
 121#ifdef SND_PCM_INDIRECT2_STAT
 122void snd_pcm_indirect2_stat(struct snd_pcm_substream *substream,
 123                                   struct snd_pcm_indirect2 *rec);
 124#endif
 125
 126snd_pcm_uframes_t
 127snd_pcm_indirect2_pointer(struct snd_pcm_substream *substream,
 128                          struct snd_pcm_indirect2 *rec);
 129void
 130snd_pcm_indirect2_playback_interrupt(struct snd_pcm_substream *substream,
 131                                     struct snd_pcm_indirect2 *rec,
 132                                     snd_pcm_indirect2_copy_t copy,
 133                                     snd_pcm_indirect2_zero_t zero);
 134void
 135snd_pcm_indirect2_capture_interrupt(struct snd_pcm_substream *substream,
 136                                    struct snd_pcm_indirect2 *rec,
 137                                    snd_pcm_indirect2_copy_t copy,
 138                                    snd_pcm_indirect2_zero_t null);
 139
 140#endif /* __SOUND_PCM_INDIRECT2_H */
 141