1/* 2 * ath-pcm.h -- ALSA PCM interface for the QCA Wasp based audio interface 3 * 4 * Copyright (c) 2013 The Linux Foundation. All rights reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#ifndef _ATH_PCM_H_ 20#define _ATH_PCM_H_ 21 22#include <linux/sound.h> 23#include <linux/list.h> 24#include <linux/spinlock.h> 25 26extern spinlock_t ath79_pcm_lock; 27 28struct ath79_pcm_desc { 29 unsigned int OWN : 1, /* bit 31 */ 30 EOM : 1, /* bit 30 */ 31 rsvd1 : 6, /* bit 29-24 */ 32 size : 12, /* bit 23-12 */ 33 length : 12, /* bit 11-00 */ 34 rsvd2 : 4, /* bit 31-28 */ 35 BufPtr : 28, /* bit 27-00 */ 36 rsvd3 : 4, /* bit 31-28 */ 37 NextPtr : 28; /* bit 27-00 */ 38 39 unsigned int Va[6]; 40 unsigned int Ua[6]; 41 unsigned int Ca[6]; 42 unsigned int Vb[6]; 43 unsigned int Ub[6]; 44 unsigned int Cb[6]; 45 46 /* Software specific data 47 * These data are not taken into account by the HW */ 48 struct list_head list; /* List linking all the buffer in virt@ space */ 49 dma_addr_t phys; /* Physical address of the descriptor */ 50}; 51 52struct ath79_pcm_rt_priv { 53 struct list_head dma_head; 54 struct ath79_pcm_desc *last_played; 55 unsigned int elapsed_size; 56 unsigned int delay_time; 57 int direction; 58}; 59 60/* Replaces struct ath_i2s_softc */ 61struct ath79_pcm_pltfm_priv { 62 struct snd_pcm_substream *playback; 63 struct snd_pcm_substream *capture; 64}; 65 66/* platform data */ 67extern struct snd_soc_platform_driver ath79_soc_platform; 68 69void ath79_mbox_interrupt_ack(u32); 70void ath79_mbox_dma_start(struct ath79_pcm_rt_priv *); 71void ath79_mbox_dma_stop(struct ath79_pcm_rt_priv *); 72void ath79_mbox_dma_prepare(struct ath79_pcm_rt_priv *); 73int ath79_mbox_dma_map(struct ath79_pcm_rt_priv *, dma_addr_t, int,int); 74void ath79_mbox_dma_unmap(struct ath79_pcm_rt_priv *); 75int ath79_mbox_dma_init(struct device *); 76void ath79_mbox_dma_exit(void); 77void ath79_mbox_dma_reset(void); 78 79static inline unsigned int ath79_pcm_set_own_bits(struct ath79_pcm_rt_priv *rtpriv) 80{ 81 struct ath79_pcm_desc *desc; 82 unsigned int size_played = 0; 83 84 spin_lock(&ath79_pcm_lock); 85 list_for_each_entry(desc, &rtpriv->dma_head, list) { 86 if (desc->OWN == 0) { 87 desc->OWN = 1; 88 size_played += desc->size; 89 } 90 } 91 spin_unlock(&ath79_pcm_lock); 92 return size_played; 93} 94 95static inline void ath79_pcm_clear_own_bits(struct ath79_pcm_rt_priv *rtpriv) 96{ 97 struct ath79_pcm_desc *desc; 98 99 spin_lock(&ath79_pcm_lock); 100 list_for_each_entry(desc, &rtpriv->dma_head, list) { 101 if (desc->OWN == 1) { 102 desc->OWN = 0; 103 } 104 } 105 spin_unlock(&ath79_pcm_lock); 106} 107 108static inline struct ath79_pcm_desc *ath79_pcm_get_last_played(struct ath79_pcm_rt_priv *rtpriv) 109{ 110 struct ath79_pcm_desc *desc, *prev; 111 112 spin_lock(&ath79_pcm_lock); 113 prev = list_entry(rtpriv->dma_head.prev, struct ath79_pcm_desc, list); 114 list_for_each_entry(desc, &rtpriv->dma_head, list) { 115 if (desc->OWN == 1 && prev->OWN == 0) { 116 return desc; 117 } 118 prev = desc; 119 } 120 spin_unlock(&ath79_pcm_lock); 121 122 /* If we didn't find the last played buffer, return NULL */ 123 return NULL; 124} 125 126#endif /* _ATH_PCM_H_ */ 127