/*1* Helper functions for indirect PCM data transfer to a simple FIFO in2* hardware (small, no possibility to read "hardware io position",3* updating position done by interrupt, ...)4*5* Copyright (c) by 2007 Joachim Foerster <[email protected]>6*7* Based on "pcm-indirect.h" (alsa-driver-1.0.13) by8*9* Copyright (c) by Takashi Iwai <[email protected]>10* Jaroslav Kysela <[email protected]>11*12* This program is free software; you can redistribute it and/or modify13* it under the terms of the GNU General Public License as published by14* the Free Software Foundation; either version 2 of the License, or15* (at your option) any later version.16*17* This program is distributed in the hope that it will be useful,18* but WITHOUT ANY WARRANTY; without even the implied warranty of19* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the20* GNU General Public License for more details.21*22* You should have received a copy of the GNU General Public License23* along with this program; if not, write to the Free Software24* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.25*/2627#ifndef __SOUND_PCM_INDIRECT2_H28#define __SOUND_PCM_INDIRECT2_H2930/* struct snd_pcm_substream, struct snd_pcm_runtime, snd_pcm_uframes_t */31#include <sound/pcm.h>3233/* Debug options for code which may be removed completely in a final version */34#ifdef CONFIG_SND_DEBUG35#define SND_PCM_INDIRECT2_STAT /* turn on some "statistics" about the36* process of copying bytes from the37* intermediate buffer to the hardware38* fifo and the other way round39*/40#endif4142struct snd_pcm_indirect2 {43unsigned int hw_buffer_size; /* Byte size of hardware buffer */44int hw_ready; /* playback: 1 = hw fifo has room left,45* 0 = hw fifo is full46*/47unsigned int min_multiple;48int min_periods; /* counts number of min. periods until49* min_multiple is reached50*/51int min_period_count; /* counts bytes to count number of52* min. periods53*/5455unsigned int sw_buffer_size; /* Byte size of software buffer */5657/* sw_data: position in intermediate buffer, where we will read (or58* write) from/to next time (to transfer data to/from HW)59*/60unsigned int sw_data; /* Offset to next dst (or src) in sw61* ring buffer62*/63/* easiest case (playback):64* sw_data is nearly the same as ~ runtime->control->appl_ptr, with the65* exception that sw_data is "behind" by the number if bytes ALSA wrote66* to the intermediate buffer last time.67* A call to ack() callback synchronizes both indirectly.68*/6970/* We have no real sw_io pointer here. Usually sw_io is pointing to the71* current playback/capture position _inside_ the hardware. Devices72* with plain FIFOs often have no possibility to publish this position.73* So we say: if sw_data is updated, that means bytes were copied to74* the hardware, we increase sw_io by that amount, because there have75* to be as much bytes which were played. So sw_io will stay behind76* sw_data all the time and has to converge to sw_data at the end of77* playback.78*/79unsigned int sw_io; /* Current software pointer in bytes */8081/* sw_ready: number of bytes ALSA copied to the intermediate buffer, so82* it represents the number of bytes which wait for transfer to the HW83*/84int sw_ready; /* Bytes ready to be transferred to/from hw */8586/* appl_ptr: last known position of ALSA (where ALSA is going to write87* next time into the intermediate buffer88*/89snd_pcm_uframes_t appl_ptr; /* Last seen appl_ptr */9091unsigned int bytes2hw;92int check_alignment;9394#ifdef SND_PCM_INDIRECT2_STAT95unsigned int zeros2hw;96unsigned int mul_elapsed;97unsigned int mul_elapsed_real;98unsigned long firstbytetime;99unsigned long lastbytetime;100unsigned long firstzerotime;101unsigned int byte_sizes[64];102unsigned int zero_sizes[64];103unsigned int min_adds[8];104unsigned int mul_adds[8];105unsigned int zero_times[3750]; /* = 15s */106unsigned int zero_times_saved;107unsigned int zero_times_notsaved;108unsigned int irq_occured;109unsigned int pointer_calls;110unsigned int lastdifftime;111#endif112};113114typedef size_t (*snd_pcm_indirect2_copy_t) (struct snd_pcm_substream *substream,115struct snd_pcm_indirect2 *rec,116size_t bytes);117typedef size_t (*snd_pcm_indirect2_zero_t) (struct snd_pcm_substream *substream,118struct snd_pcm_indirect2 *rec);119120#ifdef SND_PCM_INDIRECT2_STAT121void snd_pcm_indirect2_stat(struct snd_pcm_substream *substream,122struct snd_pcm_indirect2 *rec);123#endif124125snd_pcm_uframes_t126snd_pcm_indirect2_pointer(struct snd_pcm_substream *substream,127struct snd_pcm_indirect2 *rec);128void129snd_pcm_indirect2_playback_interrupt(struct snd_pcm_substream *substream,130struct snd_pcm_indirect2 *rec,131snd_pcm_indirect2_copy_t copy,132snd_pcm_indirect2_zero_t zero);133void134snd_pcm_indirect2_capture_interrupt(struct snd_pcm_substream *substream,135struct snd_pcm_indirect2 *rec,136snd_pcm_indirect2_copy_t copy,137snd_pcm_indirect2_zero_t null);138139#endif /* __SOUND_PCM_INDIRECT2_H */140141142