xref: /kernel/linux/linux-6.6/sound/pci/asihpi/hpios.h (revision 62306a36)
162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/******************************************************************************
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci    AudioScience HPI driver
562306a36Sopenharmony_ci    Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci
862306a36Sopenharmony_ciHPI Operating System Specific macros for Linux Kernel driver
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci(C) Copyright AudioScience Inc. 1997-2003
1162306a36Sopenharmony_ci******************************************************************************/
1262306a36Sopenharmony_ci#ifndef _HPIOS_H_
1362306a36Sopenharmony_ci#define _HPIOS_H_
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#undef HPI_OS_LINUX_KERNEL
1662306a36Sopenharmony_ci#define HPI_OS_LINUX_KERNEL
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define HPI_OS_DEFINED
1962306a36Sopenharmony_ci#define HPI_BUILD_KERNEL_MODE
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include <linux/io.h>
2262306a36Sopenharmony_ci#include <linux/ioctl.h>
2362306a36Sopenharmony_ci#include <linux/kernel.h>
2462306a36Sopenharmony_ci#include <linux/string.h>
2562306a36Sopenharmony_ci#include <linux/device.h>
2662306a36Sopenharmony_ci#include <linux/firmware.h>
2762306a36Sopenharmony_ci#include <linux/interrupt.h>
2862306a36Sopenharmony_ci#include <linux/pci.h>
2962306a36Sopenharmony_ci#include <linux/mutex.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define HPI_NO_OS_FILE_OPS
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/** Details of a memory area allocated with  pci_alloc_consistent
3462306a36Sopenharmony_ciNeed all info for parameters to pci_free_consistent
3562306a36Sopenharmony_ci*/
3662306a36Sopenharmony_cistruct consistent_dma_area {
3762306a36Sopenharmony_ci	struct device *pdev;
3862306a36Sopenharmony_ci	/* looks like dma-mapping dma_devres ?! */
3962306a36Sopenharmony_ci	size_t size;
4062306a36Sopenharmony_ci	void *vaddr;
4162306a36Sopenharmony_ci	dma_addr_t dma_handle;
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic inline u16 hpios_locked_mem_get_phys_addr(struct consistent_dma_area
4562306a36Sopenharmony_ci	*locked_mem_handle, u32 *p_physical_addr)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	*p_physical_addr = locked_mem_handle->dma_handle;
4862306a36Sopenharmony_ci	return 0;
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic inline u16 hpios_locked_mem_get_virt_addr(struct consistent_dma_area
5262306a36Sopenharmony_ci	*locked_mem_handle, void **pp_virtual_addr)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	*pp_virtual_addr = locked_mem_handle->vaddr;
5562306a36Sopenharmony_ci	return 0;
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic inline u16 hpios_locked_mem_valid(struct consistent_dma_area
5962306a36Sopenharmony_ci	*locked_mem_handle)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	return locked_mem_handle->size != 0;
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistruct hpi_ioctl_linux {
6562306a36Sopenharmony_ci	void __user *phm;
6662306a36Sopenharmony_ci	void __user *phr;
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci/* Conflict?: H is already used by a number of drivers hid, bluetooth hci,
7062306a36Sopenharmony_ci   and some sound drivers sb16, hdsp, emu10k. AFAIK 0xFC is unused command
7162306a36Sopenharmony_ci*/
7262306a36Sopenharmony_ci#define HPI_IOCTL_LINUX _IOWR('H', 0xFC, struct hpi_ioctl_linux)
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci#define HPI_DEBUG_FLAG_ERROR   KERN_ERR
7562306a36Sopenharmony_ci#define HPI_DEBUG_FLAG_WARNING KERN_WARNING
7662306a36Sopenharmony_ci#define HPI_DEBUG_FLAG_NOTICE  KERN_NOTICE
7762306a36Sopenharmony_ci#define HPI_DEBUG_FLAG_INFO    KERN_INFO
7862306a36Sopenharmony_ci#define HPI_DEBUG_FLAG_DEBUG   KERN_DEBUG
7962306a36Sopenharmony_ci#define HPI_DEBUG_FLAG_VERBOSE KERN_DEBUG	/* kernel has no verbose */
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#include <linux/spinlock.h>
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#define HPI_LOCKING
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistruct hpios_spinlock {
8662306a36Sopenharmony_ci	spinlock_t lock;	/* SEE hpios_spinlock */
8762306a36Sopenharmony_ci	int lock_context;
8862306a36Sopenharmony_ci};
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/* The reason for all this evilness is that ALSA calls some of a drivers
9162306a36Sopenharmony_ci * operators in atomic context, and some not.  But all our functions channel
9262306a36Sopenharmony_ci * through the HPI_Message conduit, so we can't handle the different context
9362306a36Sopenharmony_ci * per function
9462306a36Sopenharmony_ci */
9562306a36Sopenharmony_ci#define IN_LOCK_BH 1
9662306a36Sopenharmony_ci#define IN_LOCK_IRQ 0
9762306a36Sopenharmony_cistatic inline void cond_lock(struct hpios_spinlock *l)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	if (irqs_disabled()) {
10062306a36Sopenharmony_ci		/* NO bh or isr can execute on this processor,
10162306a36Sopenharmony_ci		   so ordinary lock will do
10262306a36Sopenharmony_ci		 */
10362306a36Sopenharmony_ci		spin_lock(&((l)->lock));
10462306a36Sopenharmony_ci		l->lock_context = IN_LOCK_IRQ;
10562306a36Sopenharmony_ci	} else {
10662306a36Sopenharmony_ci		spin_lock_bh(&((l)->lock));
10762306a36Sopenharmony_ci		l->lock_context = IN_LOCK_BH;
10862306a36Sopenharmony_ci	}
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic inline void cond_unlock(struct hpios_spinlock *l)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	if (l->lock_context == IN_LOCK_BH)
11462306a36Sopenharmony_ci		spin_unlock_bh(&((l)->lock));
11562306a36Sopenharmony_ci	else
11662306a36Sopenharmony_ci		spin_unlock(&((l)->lock));
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci#define hpios_msgxlock_init(obj)      spin_lock_init(&(obj)->lock)
12062306a36Sopenharmony_ci#define hpios_msgxlock_lock(obj)   cond_lock(obj)
12162306a36Sopenharmony_ci#define hpios_msgxlock_unlock(obj) cond_unlock(obj)
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci#define hpios_dsplock_init(obj)       spin_lock_init(&(obj)->dsp_lock.lock)
12462306a36Sopenharmony_ci#define hpios_dsplock_lock(obj)    cond_lock(&(obj)->dsp_lock)
12562306a36Sopenharmony_ci#define hpios_dsplock_unlock(obj)  cond_unlock(&(obj)->dsp_lock)
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci#ifdef CONFIG_SND_DEBUG
12862306a36Sopenharmony_ci#define HPI_BUILD_DEBUG
12962306a36Sopenharmony_ci#endif
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci#define HPI_ALIST_LOCKING
13262306a36Sopenharmony_ci#define hpios_alistlock_init(obj)    spin_lock_init(&((obj)->list_lock.lock))
13362306a36Sopenharmony_ci#define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock))
13462306a36Sopenharmony_ci#define hpios_alistlock_unlock(obj) spin_unlock(&((obj)->list_lock.lock))
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistruct snd_card;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci/** pci drvdata points to an instance of this struct */
13962306a36Sopenharmony_cistruct hpi_adapter {
14062306a36Sopenharmony_ci	struct hpi_adapter_obj *adapter;
14162306a36Sopenharmony_ci	struct snd_card *snd_card;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	int irq;
14462306a36Sopenharmony_ci	int interrupt_mode;
14562306a36Sopenharmony_ci	void (*interrupt_callback) (struct hpi_adapter *);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	/* mutex prevents contention for one card
14862306a36Sopenharmony_ci	   between multiple user programs (via ioctl) */
14962306a36Sopenharmony_ci	struct mutex mutex;
15062306a36Sopenharmony_ci	char *p_buffer;
15162306a36Sopenharmony_ci	size_t buffer_size;
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci#endif
155