18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/****************************************************************************** 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci AudioScience HPI driver 58c2ecf20Sopenharmony_ci Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ciHPI Operating System Specific macros for Linux Kernel driver 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci(C) Copyright AudioScience Inc. 1997-2003 118c2ecf20Sopenharmony_ci******************************************************************************/ 128c2ecf20Sopenharmony_ci#ifndef _HPIOS_H_ 138c2ecf20Sopenharmony_ci#define _HPIOS_H_ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#undef HPI_OS_LINUX_KERNEL 168c2ecf20Sopenharmony_ci#define HPI_OS_LINUX_KERNEL 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define HPI_OS_DEFINED 198c2ecf20Sopenharmony_ci#define HPI_BUILD_KERNEL_MODE 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <linux/io.h> 228c2ecf20Sopenharmony_ci#include <linux/ioctl.h> 238c2ecf20Sopenharmony_ci#include <linux/kernel.h> 248c2ecf20Sopenharmony_ci#include <linux/string.h> 258c2ecf20Sopenharmony_ci#include <linux/device.h> 268c2ecf20Sopenharmony_ci#include <linux/firmware.h> 278c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 288c2ecf20Sopenharmony_ci#include <linux/pci.h> 298c2ecf20Sopenharmony_ci#include <linux/mutex.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define HPI_NO_OS_FILE_OPS 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/** Details of a memory area allocated with pci_alloc_consistent 348c2ecf20Sopenharmony_ciNeed all info for parameters to pci_free_consistent 358c2ecf20Sopenharmony_ci*/ 368c2ecf20Sopenharmony_cistruct consistent_dma_area { 378c2ecf20Sopenharmony_ci struct device *pdev; 388c2ecf20Sopenharmony_ci /* looks like dma-mapping dma_devres ?! */ 398c2ecf20Sopenharmony_ci size_t size; 408c2ecf20Sopenharmony_ci void *vaddr; 418c2ecf20Sopenharmony_ci dma_addr_t dma_handle; 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic inline u16 hpios_locked_mem_get_phys_addr(struct consistent_dma_area 458c2ecf20Sopenharmony_ci *locked_mem_handle, u32 *p_physical_addr) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci *p_physical_addr = locked_mem_handle->dma_handle; 488c2ecf20Sopenharmony_ci return 0; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic inline u16 hpios_locked_mem_get_virt_addr(struct consistent_dma_area 528c2ecf20Sopenharmony_ci *locked_mem_handle, void **pp_virtual_addr) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci *pp_virtual_addr = locked_mem_handle->vaddr; 558c2ecf20Sopenharmony_ci return 0; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic inline u16 hpios_locked_mem_valid(struct consistent_dma_area 598c2ecf20Sopenharmony_ci *locked_mem_handle) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci return locked_mem_handle->size != 0; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistruct hpi_ioctl_linux { 658c2ecf20Sopenharmony_ci void __user *phm; 668c2ecf20Sopenharmony_ci void __user *phr; 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci/* Conflict?: H is already used by a number of drivers hid, bluetooth hci, 708c2ecf20Sopenharmony_ci and some sound drivers sb16, hdsp, emu10k. AFAIK 0xFC is unused command 718c2ecf20Sopenharmony_ci*/ 728c2ecf20Sopenharmony_ci#define HPI_IOCTL_LINUX _IOWR('H', 0xFC, struct hpi_ioctl_linux) 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#define HPI_DEBUG_FLAG_ERROR KERN_ERR 758c2ecf20Sopenharmony_ci#define HPI_DEBUG_FLAG_WARNING KERN_WARNING 768c2ecf20Sopenharmony_ci#define HPI_DEBUG_FLAG_NOTICE KERN_NOTICE 778c2ecf20Sopenharmony_ci#define HPI_DEBUG_FLAG_INFO KERN_INFO 788c2ecf20Sopenharmony_ci#define HPI_DEBUG_FLAG_DEBUG KERN_DEBUG 798c2ecf20Sopenharmony_ci#define HPI_DEBUG_FLAG_VERBOSE KERN_DEBUG /* kernel has no verbose */ 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define HPI_LOCKING 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistruct hpios_spinlock { 868c2ecf20Sopenharmony_ci spinlock_t lock; /* SEE hpios_spinlock */ 878c2ecf20Sopenharmony_ci int lock_context; 888c2ecf20Sopenharmony_ci}; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* The reason for all this evilness is that ALSA calls some of a drivers 918c2ecf20Sopenharmony_ci * operators in atomic context, and some not. But all our functions channel 928c2ecf20Sopenharmony_ci * through the HPI_Message conduit, so we can't handle the different context 938c2ecf20Sopenharmony_ci * per function 948c2ecf20Sopenharmony_ci */ 958c2ecf20Sopenharmony_ci#define IN_LOCK_BH 1 968c2ecf20Sopenharmony_ci#define IN_LOCK_IRQ 0 978c2ecf20Sopenharmony_cistatic inline void cond_lock(struct hpios_spinlock *l) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci if (irqs_disabled()) { 1008c2ecf20Sopenharmony_ci /* NO bh or isr can execute on this processor, 1018c2ecf20Sopenharmony_ci so ordinary lock will do 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci spin_lock(&((l)->lock)); 1048c2ecf20Sopenharmony_ci l->lock_context = IN_LOCK_IRQ; 1058c2ecf20Sopenharmony_ci } else { 1068c2ecf20Sopenharmony_ci spin_lock_bh(&((l)->lock)); 1078c2ecf20Sopenharmony_ci l->lock_context = IN_LOCK_BH; 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic inline void cond_unlock(struct hpios_spinlock *l) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci if (l->lock_context == IN_LOCK_BH) 1148c2ecf20Sopenharmony_ci spin_unlock_bh(&((l)->lock)); 1158c2ecf20Sopenharmony_ci else 1168c2ecf20Sopenharmony_ci spin_unlock(&((l)->lock)); 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci#define hpios_msgxlock_init(obj) spin_lock_init(&(obj)->lock) 1208c2ecf20Sopenharmony_ci#define hpios_msgxlock_lock(obj) cond_lock(obj) 1218c2ecf20Sopenharmony_ci#define hpios_msgxlock_unlock(obj) cond_unlock(obj) 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci#define hpios_dsplock_init(obj) spin_lock_init(&(obj)->dsp_lock.lock) 1248c2ecf20Sopenharmony_ci#define hpios_dsplock_lock(obj) cond_lock(&(obj)->dsp_lock) 1258c2ecf20Sopenharmony_ci#define hpios_dsplock_unlock(obj) cond_unlock(&(obj)->dsp_lock) 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci#ifdef CONFIG_SND_DEBUG 1288c2ecf20Sopenharmony_ci#define HPI_BUILD_DEBUG 1298c2ecf20Sopenharmony_ci#endif 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci#define HPI_ALIST_LOCKING 1328c2ecf20Sopenharmony_ci#define hpios_alistlock_init(obj) spin_lock_init(&((obj)->list_lock.lock)) 1338c2ecf20Sopenharmony_ci#define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock)) 1348c2ecf20Sopenharmony_ci#define hpios_alistlock_unlock(obj) spin_unlock(&((obj)->list_lock.lock)) 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistruct snd_card; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/** pci drvdata points to an instance of this struct */ 1398c2ecf20Sopenharmony_cistruct hpi_adapter { 1408c2ecf20Sopenharmony_ci struct hpi_adapter_obj *adapter; 1418c2ecf20Sopenharmony_ci struct snd_card *snd_card; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci int irq; 1448c2ecf20Sopenharmony_ci int interrupt_mode; 1458c2ecf20Sopenharmony_ci void (*interrupt_callback) (struct hpi_adapter *); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci /* mutex prevents contention for one card 1488c2ecf20Sopenharmony_ci between multiple user programs (via ioctl) */ 1498c2ecf20Sopenharmony_ci struct mutex mutex; 1508c2ecf20Sopenharmony_ci char *p_buffer; 1518c2ecf20Sopenharmony_ci size_t buffer_size; 1528c2ecf20Sopenharmony_ci}; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci#endif 155