1719f82d3SEliot Blennerhassett /****************************************************************************** 2719f82d3SEliot Blennerhassett 3719f82d3SEliot Blennerhassett AudioScience HPI driver 4719f82d3SEliot Blennerhassett Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> 5719f82d3SEliot Blennerhassett 6719f82d3SEliot Blennerhassett This program is free software; you can redistribute it and/or modify 7719f82d3SEliot Blennerhassett it under the terms of version 2 of the GNU General Public License as 8719f82d3SEliot Blennerhassett published by the Free Software Foundation; 9719f82d3SEliot Blennerhassett 10719f82d3SEliot Blennerhassett This program is distributed in the hope that it will be useful, 11719f82d3SEliot Blennerhassett but WITHOUT ANY WARRANTY; without even the implied warranty of 12719f82d3SEliot Blennerhassett MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13719f82d3SEliot Blennerhassett GNU General Public License for more details. 14719f82d3SEliot Blennerhassett 15719f82d3SEliot Blennerhassett You should have received a copy of the GNU General Public License 16719f82d3SEliot Blennerhassett along with this program; if not, write to the Free Software 17719f82d3SEliot Blennerhassett Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18719f82d3SEliot Blennerhassett 19719f82d3SEliot Blennerhassett HPI Operating System Specific macros for Linux Kernel driver 20719f82d3SEliot Blennerhassett 21719f82d3SEliot Blennerhassett (C) Copyright AudioScience Inc. 1997-2003 22719f82d3SEliot Blennerhassett ******************************************************************************/ 23719f82d3SEliot Blennerhassett #ifndef _HPIOS_H_ 24719f82d3SEliot Blennerhassett #define _HPIOS_H_ 25719f82d3SEliot Blennerhassett 26719f82d3SEliot Blennerhassett #undef HPI_OS_LINUX_KERNEL 27719f82d3SEliot Blennerhassett #define HPI_OS_LINUX_KERNEL 28719f82d3SEliot Blennerhassett 29719f82d3SEliot Blennerhassett #define HPI_OS_DEFINED 30719f82d3SEliot Blennerhassett #define HPI_KERNEL_MODE 31719f82d3SEliot Blennerhassett 32719f82d3SEliot Blennerhassett #define HPI_REASSIGN_DUPLICATE_ADAPTER_IDX 33719f82d3SEliot Blennerhassett 34719f82d3SEliot Blennerhassett #include <linux/io.h> 35719f82d3SEliot Blennerhassett #include <asm/system.h> 36719f82d3SEliot Blennerhassett #include <linux/ioctl.h> 37719f82d3SEliot Blennerhassett #include <linux/kernel.h> 38719f82d3SEliot Blennerhassett #include <linux/string.h> 39719f82d3SEliot Blennerhassett #include <linux/device.h> 40719f82d3SEliot Blennerhassett #include <linux/firmware.h> 41719f82d3SEliot Blennerhassett #include <linux/interrupt.h> 42719f82d3SEliot Blennerhassett #include <linux/pci.h> 43719f82d3SEliot Blennerhassett 44719f82d3SEliot Blennerhassett #define HPI_NO_OS_FILE_OPS 45719f82d3SEliot Blennerhassett 46719f82d3SEliot Blennerhassett #ifdef CONFIG_64BIT 47719f82d3SEliot Blennerhassett #define HPI64BIT 48719f82d3SEliot Blennerhassett #endif 49719f82d3SEliot Blennerhassett 50719f82d3SEliot Blennerhassett /** Details of a memory area allocated with pci_alloc_consistent 51719f82d3SEliot Blennerhassett Need all info for parameters to pci_free_consistent 52719f82d3SEliot Blennerhassett */ 53719f82d3SEliot Blennerhassett struct consistent_dma_area { 54719f82d3SEliot Blennerhassett struct device *pdev; 55719f82d3SEliot Blennerhassett /* looks like dma-mapping dma_devres ?! */ 56719f82d3SEliot Blennerhassett size_t size; 57719f82d3SEliot Blennerhassett void *vaddr; 58719f82d3SEliot Blennerhassett dma_addr_t dma_handle; 59719f82d3SEliot Blennerhassett }; 60719f82d3SEliot Blennerhassett 61719f82d3SEliot Blennerhassett static inline u16 hpios_locked_mem_get_phys_addr(struct consistent_dma_area 62719f82d3SEliot Blennerhassett *locked_mem_handle, u32 *p_physical_addr) 63719f82d3SEliot Blennerhassett { 64719f82d3SEliot Blennerhassett *p_physical_addr = locked_mem_handle->dma_handle; 65719f82d3SEliot Blennerhassett return 0; 66719f82d3SEliot Blennerhassett } 67719f82d3SEliot Blennerhassett 68719f82d3SEliot Blennerhassett static inline u16 hpios_locked_mem_get_virt_addr(struct consistent_dma_area 69719f82d3SEliot Blennerhassett *locked_mem_handle, void **pp_virtual_addr) 70719f82d3SEliot Blennerhassett { 71719f82d3SEliot Blennerhassett *pp_virtual_addr = locked_mem_handle->vaddr; 72719f82d3SEliot Blennerhassett return 0; 73719f82d3SEliot Blennerhassett } 74719f82d3SEliot Blennerhassett 75719f82d3SEliot Blennerhassett static inline u16 hpios_locked_mem_valid(struct consistent_dma_area 76719f82d3SEliot Blennerhassett *locked_mem_handle) 77719f82d3SEliot Blennerhassett { 78719f82d3SEliot Blennerhassett return locked_mem_handle->size != 0; 79719f82d3SEliot Blennerhassett } 80719f82d3SEliot Blennerhassett 81719f82d3SEliot Blennerhassett struct hpi_ioctl_linux { 82719f82d3SEliot Blennerhassett void __user *phm; 83719f82d3SEliot Blennerhassett void __user *phr; 84719f82d3SEliot Blennerhassett }; 85719f82d3SEliot Blennerhassett 86719f82d3SEliot Blennerhassett /* Conflict?: H is already used by a number of drivers hid, bluetooth hci, 87719f82d3SEliot Blennerhassett and some sound drivers sb16, hdsp, emu10k. AFAIK 0xFC is ununsed command 88719f82d3SEliot Blennerhassett */ 89719f82d3SEliot Blennerhassett #define HPI_IOCTL_LINUX _IOWR('H', 0xFC, struct hpi_ioctl_linux) 90719f82d3SEliot Blennerhassett 91719f82d3SEliot Blennerhassett #define HPI_DEBUG_FLAG_ERROR KERN_ERR 92719f82d3SEliot Blennerhassett #define HPI_DEBUG_FLAG_WARNING KERN_WARNING 93719f82d3SEliot Blennerhassett #define HPI_DEBUG_FLAG_NOTICE KERN_NOTICE 94719f82d3SEliot Blennerhassett #define HPI_DEBUG_FLAG_INFO KERN_INFO 95719f82d3SEliot Blennerhassett #define HPI_DEBUG_FLAG_DEBUG KERN_DEBUG 96719f82d3SEliot Blennerhassett #define HPI_DEBUG_FLAG_VERBOSE KERN_DEBUG /* kernel has no verbose */ 97719f82d3SEliot Blennerhassett 98719f82d3SEliot Blennerhassett #include <linux/spinlock.h> 99719f82d3SEliot Blennerhassett 100719f82d3SEliot Blennerhassett #define HPI_LOCKING 101719f82d3SEliot Blennerhassett 102719f82d3SEliot Blennerhassett struct hpios_spinlock { 103719f82d3SEliot Blennerhassett spinlock_t lock; /* SEE hpios_spinlock */ 104719f82d3SEliot Blennerhassett int lock_context; 105719f82d3SEliot Blennerhassett }; 106719f82d3SEliot Blennerhassett 107719f82d3SEliot Blennerhassett /* The reason for all this evilness is that ALSA calls some of a drivers 108719f82d3SEliot Blennerhassett * operators in atomic context, and some not. But all our functions channel 109719f82d3SEliot Blennerhassett * through the HPI_Message conduit, so we can't handle the different context 110719f82d3SEliot Blennerhassett * per function 111719f82d3SEliot Blennerhassett */ 112719f82d3SEliot Blennerhassett #define IN_LOCK_BH 1 113719f82d3SEliot Blennerhassett #define IN_LOCK_IRQ 0 114719f82d3SEliot Blennerhassett static inline void cond_lock(struct hpios_spinlock *l) 115719f82d3SEliot Blennerhassett { 116719f82d3SEliot Blennerhassett if (irqs_disabled()) { 117719f82d3SEliot Blennerhassett /* NO bh or isr can execute on this processor, 118719f82d3SEliot Blennerhassett so ordinary lock will do 119719f82d3SEliot Blennerhassett */ 120719f82d3SEliot Blennerhassett spin_lock(&((l)->lock)); 121719f82d3SEliot Blennerhassett l->lock_context = IN_LOCK_IRQ; 122719f82d3SEliot Blennerhassett } else { 123719f82d3SEliot Blennerhassett spin_lock_bh(&((l)->lock)); 124719f82d3SEliot Blennerhassett l->lock_context = IN_LOCK_BH; 125719f82d3SEliot Blennerhassett } 126719f82d3SEliot Blennerhassett } 127719f82d3SEliot Blennerhassett 128719f82d3SEliot Blennerhassett static inline void cond_unlock(struct hpios_spinlock *l) 129719f82d3SEliot Blennerhassett { 130719f82d3SEliot Blennerhassett if (l->lock_context == IN_LOCK_BH) 131719f82d3SEliot Blennerhassett spin_unlock_bh(&((l)->lock)); 132719f82d3SEliot Blennerhassett else 133719f82d3SEliot Blennerhassett spin_unlock(&((l)->lock)); 134719f82d3SEliot Blennerhassett } 135719f82d3SEliot Blennerhassett 136719f82d3SEliot Blennerhassett #define hpios_msgxlock_init(obj) spin_lock_init(&(obj)->lock) 137719f82d3SEliot Blennerhassett #define hpios_msgxlock_lock(obj) cond_lock(obj) 138719f82d3SEliot Blennerhassett #define hpios_msgxlock_un_lock(obj) cond_unlock(obj) 139719f82d3SEliot Blennerhassett 140719f82d3SEliot Blennerhassett #define hpios_dsplock_init(obj) spin_lock_init(&(obj)->dsp_lock.lock) 141719f82d3SEliot Blennerhassett #define hpios_dsplock_lock(obj) cond_lock(&(obj)->dsp_lock) 142719f82d3SEliot Blennerhassett #define hpios_dsplock_unlock(obj) cond_unlock(&(obj)->dsp_lock) 143719f82d3SEliot Blennerhassett 144719f82d3SEliot Blennerhassett #ifdef CONFIG_SND_DEBUG 145719f82d3SEliot Blennerhassett #define HPI_DEBUG 146719f82d3SEliot Blennerhassett #endif 147719f82d3SEliot Blennerhassett 148719f82d3SEliot Blennerhassett #define HPI_ALIST_LOCKING 149719f82d3SEliot Blennerhassett #define hpios_alistlock_init(obj) spin_lock_init(&((obj)->list_lock.lock)) 150719f82d3SEliot Blennerhassett #define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock)) 151719f82d3SEliot Blennerhassett #define hpios_alistlock_un_lock(obj) spin_unlock(&((obj)->list_lock.lock)) 152719f82d3SEliot Blennerhassett 153719f82d3SEliot Blennerhassett struct hpi_adapter { 154719f82d3SEliot Blennerhassett /* mutex prevents contention for one card 155719f82d3SEliot Blennerhassett between multiple user programs (via ioctl) */ 156719f82d3SEliot Blennerhassett struct mutex mutex; 157719f82d3SEliot Blennerhassett u16 index; 158719f82d3SEliot Blennerhassett u16 type; 159719f82d3SEliot Blennerhassett 160719f82d3SEliot Blennerhassett /* ALSA card structure */ 161719f82d3SEliot Blennerhassett void *snd_card_asihpi; 162719f82d3SEliot Blennerhassett 163719f82d3SEliot Blennerhassett char *p_buffer; 164719f82d3SEliot Blennerhassett size_t buffer_size; 165719f82d3SEliot Blennerhassett struct pci_dev *pci; 166719f82d3SEliot Blennerhassett void __iomem *ap_remapped_mem_base[HPI_MAX_ADAPTER_MEM_SPACES]; 167719f82d3SEliot Blennerhassett }; 168719f82d3SEliot Blennerhassett 169719f82d3SEliot Blennerhassett static inline void hpios_unmap_io(void __iomem *addr, 170719f82d3SEliot Blennerhassett unsigned long size) 171719f82d3SEliot Blennerhassett { 172719f82d3SEliot Blennerhassett iounmap(addr); 173719f82d3SEliot Blennerhassett } 174719f82d3SEliot Blennerhassett 175719f82d3SEliot Blennerhassett void __iomem *hpios_map_io(struct pci_dev *pci_dev, int idx, 176719f82d3SEliot Blennerhassett unsigned int length); 177719f82d3SEliot Blennerhassett 178719f82d3SEliot Blennerhassett #endif 179