diff options
Diffstat (limited to 'include/sound/pcm.h')
| -rw-r--r-- | include/sound/pcm.h | 158 |
1 files changed, 117 insertions, 41 deletions
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 0d1112815be..d854fb31c00 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -35,7 +35,7 @@ #define snd_pcm_chip(pcm) ((pcm)->private_data) #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) -#include "pcm_oss.h" +#include <sound/pcm_oss.h> #endif /* @@ -71,6 +71,8 @@ struct snd_pcm_ops { int (*prepare)(struct snd_pcm_substream *substream); int (*trigger)(struct snd_pcm_substream *substream, int cmd); snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream); + int (*wall_clock)(struct snd_pcm_substream *substream, + struct timespec *audio_ts); int (*copy)(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *buf, snd_pcm_uframes_t count); @@ -179,6 +181,8 @@ struct snd_pcm_ops { #define SNDRV_PCM_FMTBIT_G723_24_1B _SNDRV_PCM_FMTBIT(G723_24_1B) #define SNDRV_PCM_FMTBIT_G723_40 _SNDRV_PCM_FMTBIT(G723_40) #define SNDRV_PCM_FMTBIT_G723_40_1B _SNDRV_PCM_FMTBIT(G723_40_1B) +#define SNDRV_PCM_FMTBIT_DSD_U8 _SNDRV_PCM_FMTBIT(DSD_U8) +#define SNDRV_PCM_FMTBIT_DSD_U16_LE _SNDRV_PCM_FMTBIT(DSD_U16_LE) #ifdef SNDRV_LITTLE_ENDIAN #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE @@ -281,6 +285,7 @@ struct snd_pcm_runtime { unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */ unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */ snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */ + u64 hw_ptr_wrap; /* offset for hw_ptr due to boundary wrap-around */ /* -- HW params -- */ snd_pcm_access_t access; /* access mode */ @@ -376,10 +381,9 @@ struct snd_pcm_substream { struct pm_qos_request latency_pm_qos_req; /* pm_qos request */ size_t buffer_bytes_max; /* limit ring buffer size */ struct snd_dma_buffer dma_buffer; - unsigned int dma_buf_id; size_t dma_max; /* -- hardware operations -- */ - struct snd_pcm_ops *ops; + const struct snd_pcm_ops *ops; /* -- runtime information -- */ struct snd_pcm_runtime *runtime; /* -- timer section -- */ @@ -437,6 +441,7 @@ struct snd_pcm_str { struct snd_info_entry *proc_xrun_debug_entry; #endif #endif + struct snd_kcontrol *chmap_kctl; /* channel-mapping controls */ }; struct snd_pcm { @@ -655,7 +660,7 @@ static inline snd_pcm_sframes_t snd_pcm_capture_hw_avail(struct snd_pcm_runtime * * Checks whether enough free space is available on the playback buffer. * - * Returns non-zero if available, or zero if not. + * Return: Non-zero if available, or zero if not. */ static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream) { @@ -669,7 +674,7 @@ static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream) * * Checks whether enough capture data is available on the capture buffer. * - * Returns non-zero if available, or zero if not. + * Return: Non-zero if available, or zero if not. */ static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream) { @@ -681,10 +686,10 @@ static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream) * snd_pcm_playback_data - check whether any data exists on the playback buffer * @substream: the pcm substream instance * - * Checks whether any data exists on the playback buffer. If stop_threshold - * is bigger or equal to boundary, then this function returns always non-zero. + * Checks whether any data exists on the playback buffer. * - * Returns non-zero if exists, or zero if not. + * Return: Non-zero if any data exists, or zero if not. If stop_threshold + * is bigger or equal to boundary, then this function returns always non-zero. */ static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream) { @@ -701,7 +706,7 @@ static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream) * * Checks whether the playback buffer is empty. * - * Returns non-zero if empty, or zero if not. + * Return: Non-zero if empty, or zero if not. */ static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream) { @@ -715,7 +720,7 @@ static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream) * * Checks whether the capture buffer is empty. * - * Returns non-zero if empty, or zero if not. + * Return: Non-zero if empty, or zero if not. */ static inline int snd_pcm_capture_empty(struct snd_pcm_substream *substream) { @@ -810,7 +815,7 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, unsigned int cond, snd_pcm_hw_param_t var, - struct snd_pcm_hw_constraint_list *l); + const struct snd_pcm_hw_constraint_list *l); int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, unsigned int cond, snd_pcm_hw_param_t var, @@ -848,7 +853,7 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format); * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian * @format: the format to check * - * Returns 1 if the given PCM format is CPU-endian, 0 if + * Return: 1 if the given PCM format is CPU-endian, 0 if * opposite, or a negative error code if endian not specified. */ int snd_pcm_format_cpu_endian(snd_pcm_format_t format); @@ -863,9 +868,10 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format); /* in bits */ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples); const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format); int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames); -snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian); +snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsigned, int big_endian); -void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, struct snd_pcm_ops *ops); +void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, + const struct snd_pcm_ops *ops); void snd_pcm_set_sync(struct snd_pcm_substream *substream); int snd_pcm_lib_interleave_len(struct snd_pcm_substream *substream); int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, @@ -893,6 +899,9 @@ extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates; int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate); +unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit); +unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a, + unsigned int rates_b); static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream, struct snd_dma_buffer *bufp) @@ -923,7 +932,7 @@ static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime, struct timespec *tv) { if (runtime->tstamp_type == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC) - do_posix_clock_monotonic_gettime(tv); + ktime_get_ts(tv); else getnstimeofday(tv); } @@ -958,7 +967,7 @@ struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream, * contiguous in kernel virtual space, but not in physical memory. Use this * if the buffer is accessed by kernel code but not by device DMA. * - * Returns 1 if the buffer was changed, 0 if not changed, or a negative error + * Return: 1 if the buffer was changed, 0 if not changed, or a negative error * code. */ static int snd_pcm_lib_alloc_vmalloc_buffer @@ -970,6 +979,9 @@ static int snd_pcm_lib_alloc_vmalloc_buffer * * This function works like snd_pcm_lib_alloc_vmalloc_buffer(), but uses * vmalloc_32(), i.e., the pages are allocated from 32-bit-addressable memory. + * + * Return: 1 if the buffer was changed, 0 if not changed, or a negative error + * code. */ static int snd_pcm_lib_alloc_vmalloc_32_buffer (struct snd_pcm_substream *substream, size_t size); @@ -981,53 +993,42 @@ static int snd_pcm_lib_alloc_vmalloc_32_buffer _snd_pcm_lib_alloc_vmalloc_buffer \ (subs, size, GFP_KERNEL | GFP_DMA32 | __GFP_ZERO) +#define snd_pcm_get_dma_buf(substream) ((substream)->runtime->dma_buffer_p) + #ifdef CONFIG_SND_DMA_SGBUF /* * SG-buffer handling */ #define snd_pcm_substream_sgbuf(substream) \ - ((substream)->runtime->dma_buffer_p->private_data) - -static inline dma_addr_t -snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) -{ - struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream); - return snd_sgbuf_get_addr(sg, ofs); -} - -static inline void * -snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs) -{ - struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream); - return snd_sgbuf_get_ptr(sg, ofs); -} + snd_pcm_get_dma_buf(substream)->private_data struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset); -unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, - unsigned int ofs, unsigned int size); - #else /* !SND_DMA_SGBUF */ /* * fake using a continuous buffer */ +#define snd_pcm_sgbuf_ops_page NULL +#endif /* SND_DMA_SGBUF */ + static inline dma_addr_t snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) { - return substream->runtime->dma_addr + ofs; + return snd_sgbuf_get_addr(snd_pcm_get_dma_buf(substream), ofs); } static inline void * snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs) { - return substream->runtime->dma_area + ofs; + return snd_sgbuf_get_ptr(snd_pcm_get_dma_buf(substream), ofs); } -#define snd_pcm_sgbuf_ops_page NULL - -#define snd_pcm_sgbuf_get_chunk_size(subs, ofs, size) (size) - -#endif /* SND_DMA_SGBUF */ +static inline unsigned int +snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, + unsigned int ofs, unsigned int size) +{ + return snd_sgbuf_get_chunk_size(snd_pcm_get_dma_buf(substream), ofs, size); +} /* handle mmap counter - PCM mmap callback should handle this counter properly */ static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) @@ -1073,4 +1074,79 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) const char *snd_pcm_format_name(snd_pcm_format_t format); +/** + * snd_pcm_stream_str - Get a string naming the direction of a stream + * @substream: the pcm substream instance + * + * Return: A string naming the direction of the stream. + */ +static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return "Playback"; + else + return "Capture"; +} + +/* + * PCM channel-mapping control API + */ +/* array element of channel maps */ +struct snd_pcm_chmap_elem { + unsigned char channels; + unsigned char map[15]; +}; + +/* channel map information; retrieved via snd_kcontrol_chip() */ +struct snd_pcm_chmap { + struct snd_pcm *pcm; /* assigned PCM instance */ + int stream; /* PLAYBACK or CAPTURE */ + struct snd_kcontrol *kctl; + const struct snd_pcm_chmap_elem *chmap; + unsigned int max_channels; + unsigned int channel_mask; /* optional: active channels bitmask */ + void *private_data; /* optional: private data pointer */ +}; + +/* get the PCM substream assigned to the given chmap info */ +static inline struct snd_pcm_substream * +snd_pcm_chmap_substream(struct snd_pcm_chmap *info, unsigned int idx) +{ + struct snd_pcm_substream *s; + for (s = info->pcm->streams[info->stream].substream; s; s = s->next) + if (s->number == idx) + return s; + return NULL; +} + +/* ALSA-standard channel maps (RL/RR prior to C/LFE) */ +extern const struct snd_pcm_chmap_elem snd_pcm_std_chmaps[]; +/* Other world's standard channel maps (C/LFE prior to RL/RR) */ +extern const struct snd_pcm_chmap_elem snd_pcm_alt_chmaps[]; + +/* bit masks to be passed to snd_pcm_chmap.channel_mask field */ +#define SND_PCM_CHMAP_MASK_24 ((1U << 2) | (1U << 4)) +#define SND_PCM_CHMAP_MASK_246 (SND_PCM_CHMAP_MASK_24 | (1U << 6)) +#define SND_PCM_CHMAP_MASK_2468 (SND_PCM_CHMAP_MASK_246 | (1U << 8)) + +int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream, + const struct snd_pcm_chmap_elem *chmap, + int max_channels, + unsigned long private_value, + struct snd_pcm_chmap **info_ret); + +/* Strong-typed conversion of pcm_format to bitwise */ +static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format) +{ + return 1ULL << (__force int) pcm_format; +} + +/* printk helpers */ +#define pcm_err(pcm, fmt, args...) \ + dev_err((pcm)->card->dev, fmt, ##args) +#define pcm_warn(pcm, fmt, args...) \ + dev_warn((pcm)->card->dev, fmt, ##args) +#define pcm_dbg(pcm, fmt, args...) \ + dev_dbg((pcm)->card->dev, fmt, ##args) + #endif /* __SOUND_PCM_H */ |
