162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * HD-audio core stuff
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef __SOUND_HDAUDIO_H
762306a36Sopenharmony_ci#define __SOUND_HDAUDIO_H
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/device.h>
1062306a36Sopenharmony_ci#include <linux/interrupt.h>
1162306a36Sopenharmony_ci#include <linux/io.h>
1262306a36Sopenharmony_ci#include <linux/io-64-nonatomic-lo-hi.h>
1362306a36Sopenharmony_ci#include <linux/iopoll.h>
1462306a36Sopenharmony_ci#include <linux/pci.h>
1562306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1662306a36Sopenharmony_ci#include <linux/timecounter.h>
1762306a36Sopenharmony_ci#include <sound/core.h>
1862306a36Sopenharmony_ci#include <sound/pcm.h>
1962306a36Sopenharmony_ci#include <sound/memalloc.h>
2062306a36Sopenharmony_ci#include <sound/hda_verbs.h>
2162306a36Sopenharmony_ci#include <drm/i915_component.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* codec node id */
2462306a36Sopenharmony_citypedef u16 hda_nid_t;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistruct hdac_bus;
2762306a36Sopenharmony_cistruct hdac_stream;
2862306a36Sopenharmony_cistruct hdac_device;
2962306a36Sopenharmony_cistruct hdac_driver;
3062306a36Sopenharmony_cistruct hdac_widget_tree;
3162306a36Sopenharmony_cistruct hda_device_id;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/*
3462306a36Sopenharmony_ci * exported bus type
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_ciextern struct bus_type snd_hda_bus_type;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/*
3962306a36Sopenharmony_ci * generic arrays
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_cistruct snd_array {
4262306a36Sopenharmony_ci	unsigned int used;
4362306a36Sopenharmony_ci	unsigned int alloced;
4462306a36Sopenharmony_ci	unsigned int elem_size;
4562306a36Sopenharmony_ci	unsigned int alloc_align;
4662306a36Sopenharmony_ci	void *list;
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/*
5062306a36Sopenharmony_ci * HD-audio codec base device
5162306a36Sopenharmony_ci */
5262306a36Sopenharmony_cistruct hdac_device {
5362306a36Sopenharmony_ci	struct device dev;
5462306a36Sopenharmony_ci	int type;
5562306a36Sopenharmony_ci	struct hdac_bus *bus;
5662306a36Sopenharmony_ci	unsigned int addr;		/* codec address */
5762306a36Sopenharmony_ci	struct list_head list;		/* list point for bus codec_list */
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	hda_nid_t afg;			/* AFG node id */
6062306a36Sopenharmony_ci	hda_nid_t mfg;			/* MFG node id */
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	/* ids */
6362306a36Sopenharmony_ci	unsigned int vendor_id;
6462306a36Sopenharmony_ci	unsigned int subsystem_id;
6562306a36Sopenharmony_ci	unsigned int revision_id;
6662306a36Sopenharmony_ci	unsigned int afg_function_id;
6762306a36Sopenharmony_ci	unsigned int mfg_function_id;
6862306a36Sopenharmony_ci	unsigned int afg_unsol:1;
6962306a36Sopenharmony_ci	unsigned int mfg_unsol:1;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	unsigned int power_caps;	/* FG power caps */
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	const char *vendor_name;	/* codec vendor name */
7462306a36Sopenharmony_ci	const char *chip_name;		/* codec chip name */
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	/* verb exec op override */
7762306a36Sopenharmony_ci	int (*exec_verb)(struct hdac_device *dev, unsigned int cmd,
7862306a36Sopenharmony_ci			 unsigned int flags, unsigned int *res);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	/* widgets */
8162306a36Sopenharmony_ci	unsigned int num_nodes;
8262306a36Sopenharmony_ci	hda_nid_t start_nid, end_nid;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	/* misc flags */
8562306a36Sopenharmony_ci	atomic_t in_pm;		/* suspend/resume being performed */
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	/* sysfs */
8862306a36Sopenharmony_ci	struct mutex widget_lock;
8962306a36Sopenharmony_ci	struct hdac_widget_tree *widgets;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	/* regmap */
9262306a36Sopenharmony_ci	struct regmap *regmap;
9362306a36Sopenharmony_ci	struct mutex regmap_lock;
9462306a36Sopenharmony_ci	struct snd_array vendor_verbs;
9562306a36Sopenharmony_ci	bool lazy_cache:1;	/* don't wake up for writes */
9662306a36Sopenharmony_ci	bool caps_overwriting:1; /* caps overwrite being in process */
9762306a36Sopenharmony_ci	bool cache_coef:1;	/* cache COEF read/write too */
9862306a36Sopenharmony_ci	unsigned int registered:1; /* codec was registered */
9962306a36Sopenharmony_ci};
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/* device/driver type used for matching */
10262306a36Sopenharmony_cienum {
10362306a36Sopenharmony_ci	HDA_DEV_CORE,
10462306a36Sopenharmony_ci	HDA_DEV_LEGACY,
10562306a36Sopenharmony_ci	HDA_DEV_ASOC,
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cienum {
10962306a36Sopenharmony_ci	SND_SKL_PCI_BIND_AUTO,	/* automatic selection based on pci class */
11062306a36Sopenharmony_ci	SND_SKL_PCI_BIND_LEGACY,/* bind only with legacy driver */
11162306a36Sopenharmony_ci	SND_SKL_PCI_BIND_ASOC	/* bind only with ASoC driver */
11262306a36Sopenharmony_ci};
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/* direction */
11562306a36Sopenharmony_cienum {
11662306a36Sopenharmony_ci	HDA_INPUT, HDA_OUTPUT
11762306a36Sopenharmony_ci};
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci#define dev_to_hdac_dev(_dev)	container_of(_dev, struct hdac_device, dev)
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ciint snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus,
12262306a36Sopenharmony_ci			 const char *name, unsigned int addr);
12362306a36Sopenharmony_civoid snd_hdac_device_exit(struct hdac_device *dev);
12462306a36Sopenharmony_ciint snd_hdac_device_register(struct hdac_device *codec);
12562306a36Sopenharmony_civoid snd_hdac_device_unregister(struct hdac_device *codec);
12662306a36Sopenharmony_ciint snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name);
12762306a36Sopenharmony_ciint snd_hdac_codec_modalias(const struct hdac_device *hdac, char *buf, size_t size);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ciint snd_hdac_refresh_widgets(struct hdac_device *codec);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ciint snd_hdac_read(struct hdac_device *codec, hda_nid_t nid,
13262306a36Sopenharmony_ci		  unsigned int verb, unsigned int parm, unsigned int *res);
13362306a36Sopenharmony_ciint _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm,
13462306a36Sopenharmony_ci			unsigned int *res);
13562306a36Sopenharmony_ciint snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid,
13662306a36Sopenharmony_ci				int parm);
13762306a36Sopenharmony_ciint snd_hdac_override_parm(struct hdac_device *codec, hda_nid_t nid,
13862306a36Sopenharmony_ci			   unsigned int parm, unsigned int val);
13962306a36Sopenharmony_ciint snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid,
14062306a36Sopenharmony_ci			     hda_nid_t *conn_list, int max_conns);
14162306a36Sopenharmony_ciint snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,
14262306a36Sopenharmony_ci			   hda_nid_t *start_id);
14362306a36Sopenharmony_ciunsigned int snd_hdac_calc_stream_format(unsigned int rate,
14462306a36Sopenharmony_ci					 unsigned int channels,
14562306a36Sopenharmony_ci					 snd_pcm_format_t format,
14662306a36Sopenharmony_ci					 unsigned int maxbps,
14762306a36Sopenharmony_ci					 unsigned short spdif_ctls);
14862306a36Sopenharmony_ciint snd_hdac_query_supported_pcm(struct hdac_device *codec, hda_nid_t nid,
14962306a36Sopenharmony_ci				u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
15062306a36Sopenharmony_cibool snd_hdac_is_supported_format(struct hdac_device *codec, hda_nid_t nid,
15162306a36Sopenharmony_ci				  unsigned int format);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ciint snd_hdac_codec_read(struct hdac_device *hdac, hda_nid_t nid,
15462306a36Sopenharmony_ci			int flags, unsigned int verb, unsigned int parm);
15562306a36Sopenharmony_ciint snd_hdac_codec_write(struct hdac_device *hdac, hda_nid_t nid,
15662306a36Sopenharmony_ci			int flags, unsigned int verb, unsigned int parm);
15762306a36Sopenharmony_cibool snd_hdac_check_power_state(struct hdac_device *hdac,
15862306a36Sopenharmony_ci		hda_nid_t nid, unsigned int target_state);
15962306a36Sopenharmony_ciunsigned int snd_hdac_sync_power_state(struct hdac_device *hdac,
16062306a36Sopenharmony_ci		      hda_nid_t nid, unsigned int target_state);
16162306a36Sopenharmony_ci/**
16262306a36Sopenharmony_ci * snd_hdac_read_parm - read a codec parameter
16362306a36Sopenharmony_ci * @codec: the codec object
16462306a36Sopenharmony_ci * @nid: NID to read a parameter
16562306a36Sopenharmony_ci * @parm: parameter to read
16662306a36Sopenharmony_ci *
16762306a36Sopenharmony_ci * Returns -1 for error.  If you need to distinguish the error more
16862306a36Sopenharmony_ci * strictly, use _snd_hdac_read_parm() directly.
16962306a36Sopenharmony_ci */
17062306a36Sopenharmony_cistatic inline int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid,
17162306a36Sopenharmony_ci				     int parm)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	unsigned int val;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	return _snd_hdac_read_parm(codec, nid, parm, &val) < 0 ? -1 : val;
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci#ifdef CONFIG_PM
17962306a36Sopenharmony_ciint snd_hdac_power_up(struct hdac_device *codec);
18062306a36Sopenharmony_ciint snd_hdac_power_down(struct hdac_device *codec);
18162306a36Sopenharmony_ciint snd_hdac_power_up_pm(struct hdac_device *codec);
18262306a36Sopenharmony_ciint snd_hdac_power_down_pm(struct hdac_device *codec);
18362306a36Sopenharmony_ciint snd_hdac_keep_power_up(struct hdac_device *codec);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/* call this at entering into suspend/resume callbacks in codec driver */
18662306a36Sopenharmony_cistatic inline void snd_hdac_enter_pm(struct hdac_device *codec)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	atomic_inc(&codec->in_pm);
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci/* call this at leaving from suspend/resume callbacks in codec driver */
19262306a36Sopenharmony_cistatic inline void snd_hdac_leave_pm(struct hdac_device *codec)
19362306a36Sopenharmony_ci{
19462306a36Sopenharmony_ci	atomic_dec(&codec->in_pm);
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic inline bool snd_hdac_is_in_pm(struct hdac_device *codec)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	return atomic_read(&codec->in_pm);
20062306a36Sopenharmony_ci}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_cistatic inline bool snd_hdac_is_power_on(struct hdac_device *codec)
20362306a36Sopenharmony_ci{
20462306a36Sopenharmony_ci	return !pm_runtime_suspended(&codec->dev);
20562306a36Sopenharmony_ci}
20662306a36Sopenharmony_ci#else
20762306a36Sopenharmony_cistatic inline int snd_hdac_power_up(struct hdac_device *codec) { return 0; }
20862306a36Sopenharmony_cistatic inline int snd_hdac_power_down(struct hdac_device *codec) { return 0; }
20962306a36Sopenharmony_cistatic inline int snd_hdac_power_up_pm(struct hdac_device *codec) { return 0; }
21062306a36Sopenharmony_cistatic inline int snd_hdac_power_down_pm(struct hdac_device *codec) { return 0; }
21162306a36Sopenharmony_cistatic inline int snd_hdac_keep_power_up(struct hdac_device *codec) { return 0; }
21262306a36Sopenharmony_cistatic inline void snd_hdac_enter_pm(struct hdac_device *codec) {}
21362306a36Sopenharmony_cistatic inline void snd_hdac_leave_pm(struct hdac_device *codec) {}
21462306a36Sopenharmony_cistatic inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return false; }
21562306a36Sopenharmony_cistatic inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return true; }
21662306a36Sopenharmony_ci#endif
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci/*
21962306a36Sopenharmony_ci * HD-audio codec base driver
22062306a36Sopenharmony_ci */
22162306a36Sopenharmony_cistruct hdac_driver {
22262306a36Sopenharmony_ci	struct device_driver driver;
22362306a36Sopenharmony_ci	int type;
22462306a36Sopenharmony_ci	const struct hda_device_id *id_table;
22562306a36Sopenharmony_ci	int (*match)(struct hdac_device *dev, struct hdac_driver *drv);
22662306a36Sopenharmony_ci	void (*unsol_event)(struct hdac_device *dev, unsigned int event);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	/* fields used by ext bus APIs */
22962306a36Sopenharmony_ci	int (*probe)(struct hdac_device *dev);
23062306a36Sopenharmony_ci	int (*remove)(struct hdac_device *dev);
23162306a36Sopenharmony_ci	void (*shutdown)(struct hdac_device *dev);
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci#define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver)
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ciconst struct hda_device_id *
23762306a36Sopenharmony_cihdac_get_device_id(struct hdac_device *hdev, struct hdac_driver *drv);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci/*
24062306a36Sopenharmony_ci * Bus verb operators
24162306a36Sopenharmony_ci */
24262306a36Sopenharmony_cistruct hdac_bus_ops {
24362306a36Sopenharmony_ci	/* send a single command */
24462306a36Sopenharmony_ci	int (*command)(struct hdac_bus *bus, unsigned int cmd);
24562306a36Sopenharmony_ci	/* get a response from the last command */
24662306a36Sopenharmony_ci	int (*get_response)(struct hdac_bus *bus, unsigned int addr,
24762306a36Sopenharmony_ci			    unsigned int *res);
24862306a36Sopenharmony_ci	/* notify of codec link power-up/down */
24962306a36Sopenharmony_ci	void (*link_power)(struct hdac_device *hdev, bool enable);
25062306a36Sopenharmony_ci};
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci/*
25362306a36Sopenharmony_ci * ops used for ASoC HDA codec drivers
25462306a36Sopenharmony_ci */
25562306a36Sopenharmony_cistruct hdac_ext_bus_ops {
25662306a36Sopenharmony_ci	int (*hdev_attach)(struct hdac_device *hdev);
25762306a36Sopenharmony_ci	int (*hdev_detach)(struct hdac_device *hdev);
25862306a36Sopenharmony_ci};
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci#define HDA_UNSOL_QUEUE_SIZE	64
26162306a36Sopenharmony_ci#define HDA_MAX_CODECS		8	/* limit by controller side */
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci/*
26462306a36Sopenharmony_ci * CORB/RIRB
26562306a36Sopenharmony_ci *
26662306a36Sopenharmony_ci * Each CORB entry is 4byte, RIRB is 8byte
26762306a36Sopenharmony_ci */
26862306a36Sopenharmony_cistruct hdac_rb {
26962306a36Sopenharmony_ci	__le32 *buf;		/* virtual address of CORB/RIRB buffer */
27062306a36Sopenharmony_ci	dma_addr_t addr;	/* physical address of CORB/RIRB buffer */
27162306a36Sopenharmony_ci	unsigned short rp, wp;	/* RIRB read/write pointers */
27262306a36Sopenharmony_ci	int cmds[HDA_MAX_CODECS];	/* number of pending requests */
27362306a36Sopenharmony_ci	u32 res[HDA_MAX_CODECS];	/* last read value */
27462306a36Sopenharmony_ci};
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci/*
27762306a36Sopenharmony_ci * HD-audio bus base driver
27862306a36Sopenharmony_ci *
27962306a36Sopenharmony_ci * @ppcap: pp capabilities pointer
28062306a36Sopenharmony_ci * @spbcap: SPIB capabilities pointer
28162306a36Sopenharmony_ci * @mlcap: MultiLink capabilities pointer
28262306a36Sopenharmony_ci * @gtscap: gts capabilities pointer
28362306a36Sopenharmony_ci * @drsmcap: dma resume capabilities pointer
28462306a36Sopenharmony_ci * @num_streams: streams supported
28562306a36Sopenharmony_ci * @idx: HDA link index
28662306a36Sopenharmony_ci * @hlink_list: link list of HDA links
28762306a36Sopenharmony_ci * @lock: lock for link and display power mgmt
28862306a36Sopenharmony_ci * @cmd_dma_state: state of cmd DMAs: CORB and RIRB
28962306a36Sopenharmony_ci */
29062306a36Sopenharmony_cistruct hdac_bus {
29162306a36Sopenharmony_ci	struct device *dev;
29262306a36Sopenharmony_ci	const struct hdac_bus_ops *ops;
29362306a36Sopenharmony_ci	const struct hdac_ext_bus_ops *ext_ops;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	/* h/w resources */
29662306a36Sopenharmony_ci	unsigned long addr;
29762306a36Sopenharmony_ci	void __iomem *remap_addr;
29862306a36Sopenharmony_ci	int irq;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	void __iomem *ppcap;
30162306a36Sopenharmony_ci	void __iomem *spbcap;
30262306a36Sopenharmony_ci	void __iomem *mlcap;
30362306a36Sopenharmony_ci	void __iomem *gtscap;
30462306a36Sopenharmony_ci	void __iomem *drsmcap;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	/* codec linked list */
30762306a36Sopenharmony_ci	struct list_head codec_list;
30862306a36Sopenharmony_ci	unsigned int num_codecs;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	/* link caddr -> codec */
31162306a36Sopenharmony_ci	struct hdac_device *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1];
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	/* unsolicited event queue */
31462306a36Sopenharmony_ci	u32 unsol_queue[HDA_UNSOL_QUEUE_SIZE * 2]; /* ring buffer */
31562306a36Sopenharmony_ci	unsigned int unsol_rp, unsol_wp;
31662306a36Sopenharmony_ci	struct work_struct unsol_work;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	/* bit flags of detected codecs */
31962306a36Sopenharmony_ci	unsigned long codec_mask;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	/* bit flags of powered codecs */
32262306a36Sopenharmony_ci	unsigned long codec_powered;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	/* CORB/RIRB */
32562306a36Sopenharmony_ci	struct hdac_rb corb;
32662306a36Sopenharmony_ci	struct hdac_rb rirb;
32762306a36Sopenharmony_ci	unsigned int last_cmd[HDA_MAX_CODECS];	/* last sent command */
32862306a36Sopenharmony_ci	wait_queue_head_t rirb_wq;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	/* CORB/RIRB and position buffers */
33162306a36Sopenharmony_ci	struct snd_dma_buffer rb;
33262306a36Sopenharmony_ci	struct snd_dma_buffer posbuf;
33362306a36Sopenharmony_ci	int dma_type;			/* SNDRV_DMA_TYPE_XXX for CORB/RIRB */
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	/* hdac_stream linked list */
33662306a36Sopenharmony_ci	struct list_head stream_list;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	/* operation state */
33962306a36Sopenharmony_ci	bool chip_init:1;		/* h/w initialized */
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	/* behavior flags */
34262306a36Sopenharmony_ci	bool aligned_mmio:1;		/* aligned MMIO access */
34362306a36Sopenharmony_ci	bool sync_write:1;		/* sync after verb write */
34462306a36Sopenharmony_ci	bool use_posbuf:1;		/* use position buffer */
34562306a36Sopenharmony_ci	bool snoop:1;			/* enable snooping */
34662306a36Sopenharmony_ci	bool align_bdle_4k:1;		/* BDLE align 4K boundary */
34762306a36Sopenharmony_ci	bool reverse_assign:1;		/* assign devices in reverse order */
34862306a36Sopenharmony_ci	bool corbrp_self_clear:1;	/* CORBRP clears itself after reset */
34962306a36Sopenharmony_ci	bool polling_mode:1;
35062306a36Sopenharmony_ci	bool needs_damn_long_delay:1;
35162306a36Sopenharmony_ci	bool not_use_interrupts:1;	/* prohibiting the RIRB IRQ */
35262306a36Sopenharmony_ci	bool access_sdnctl_in_dword:1;	/* accessing the sdnctl register by dword */
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	int poll_count;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	int bdl_pos_adj;		/* BDL position adjustment */
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	/* delay time in us for dma stop */
35962306a36Sopenharmony_ci	unsigned int dma_stop_delay;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	/* locks */
36262306a36Sopenharmony_ci	spinlock_t reg_lock;
36362306a36Sopenharmony_ci	struct mutex cmd_mutex;
36462306a36Sopenharmony_ci	struct mutex lock;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	/* DRM component interface */
36762306a36Sopenharmony_ci	struct drm_audio_component *audio_component;
36862306a36Sopenharmony_ci	long display_power_status;
36962306a36Sopenharmony_ci	unsigned long display_power_active;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	/* parameters required for enhanced capabilities */
37262306a36Sopenharmony_ci	int num_streams;
37362306a36Sopenharmony_ci	int idx;
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	/* link management */
37662306a36Sopenharmony_ci	struct list_head hlink_list;
37762306a36Sopenharmony_ci	bool cmd_dma_state;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	/* factor used to derive STRIPE control value */
38062306a36Sopenharmony_ci	unsigned int sdo_limit;
38162306a36Sopenharmony_ci};
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ciint snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
38462306a36Sopenharmony_ci		      const struct hdac_bus_ops *ops);
38562306a36Sopenharmony_civoid snd_hdac_bus_exit(struct hdac_bus *bus);
38662306a36Sopenharmony_ciint snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr,
38762306a36Sopenharmony_ci				    unsigned int cmd, unsigned int *res);
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_civoid snd_hdac_codec_link_up(struct hdac_device *codec);
39062306a36Sopenharmony_civoid snd_hdac_codec_link_down(struct hdac_device *codec);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ciint snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val);
39362306a36Sopenharmony_ciint snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
39462306a36Sopenharmony_ci			      unsigned int *res);
39562306a36Sopenharmony_ciint snd_hdac_bus_parse_capabilities(struct hdac_bus *bus);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cibool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset);
39862306a36Sopenharmony_civoid snd_hdac_bus_stop_chip(struct hdac_bus *bus);
39962306a36Sopenharmony_civoid snd_hdac_bus_init_cmd_io(struct hdac_bus *bus);
40062306a36Sopenharmony_civoid snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus);
40162306a36Sopenharmony_civoid snd_hdac_bus_enter_link_reset(struct hdac_bus *bus);
40262306a36Sopenharmony_civoid snd_hdac_bus_exit_link_reset(struct hdac_bus *bus);
40362306a36Sopenharmony_ciint snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset);
40462306a36Sopenharmony_civoid snd_hdac_bus_link_power(struct hdac_device *hdev, bool enable);
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_civoid snd_hdac_bus_update_rirb(struct hdac_bus *bus);
40762306a36Sopenharmony_ciint snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
40862306a36Sopenharmony_ci				    void (*ack)(struct hdac_bus *,
40962306a36Sopenharmony_ci						struct hdac_stream *));
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ciint snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus);
41262306a36Sopenharmony_civoid snd_hdac_bus_free_stream_pages(struct hdac_bus *bus);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci#ifdef CONFIG_SND_HDA_ALIGNED_MMIO
41562306a36Sopenharmony_ciunsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask);
41662306a36Sopenharmony_civoid snd_hdac_aligned_write(unsigned int val, void __iomem *addr,
41762306a36Sopenharmony_ci			    unsigned int mask);
41862306a36Sopenharmony_ci#define snd_hdac_aligned_mmio(bus)	(bus)->aligned_mmio
41962306a36Sopenharmony_ci#else
42062306a36Sopenharmony_ci#define snd_hdac_aligned_mmio(bus)	false
42162306a36Sopenharmony_ci#define snd_hdac_aligned_read(addr, mask)	0
42262306a36Sopenharmony_ci#define snd_hdac_aligned_write(val, addr, mask) do {} while (0)
42362306a36Sopenharmony_ci#endif
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_cistatic inline void snd_hdac_reg_writeb(struct hdac_bus *bus, void __iomem *addr,
42662306a36Sopenharmony_ci				       u8 val)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	if (snd_hdac_aligned_mmio(bus))
42962306a36Sopenharmony_ci		snd_hdac_aligned_write(val, addr, 0xff);
43062306a36Sopenharmony_ci	else
43162306a36Sopenharmony_ci		writeb(val, addr);
43262306a36Sopenharmony_ci}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_cistatic inline void snd_hdac_reg_writew(struct hdac_bus *bus, void __iomem *addr,
43562306a36Sopenharmony_ci				       u16 val)
43662306a36Sopenharmony_ci{
43762306a36Sopenharmony_ci	if (snd_hdac_aligned_mmio(bus))
43862306a36Sopenharmony_ci		snd_hdac_aligned_write(val, addr, 0xffff);
43962306a36Sopenharmony_ci	else
44062306a36Sopenharmony_ci		writew(val, addr);
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_cistatic inline u8 snd_hdac_reg_readb(struct hdac_bus *bus, void __iomem *addr)
44462306a36Sopenharmony_ci{
44562306a36Sopenharmony_ci	return snd_hdac_aligned_mmio(bus) ?
44662306a36Sopenharmony_ci		snd_hdac_aligned_read(addr, 0xff) : readb(addr);
44762306a36Sopenharmony_ci}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_cistatic inline u16 snd_hdac_reg_readw(struct hdac_bus *bus, void __iomem *addr)
45062306a36Sopenharmony_ci{
45162306a36Sopenharmony_ci	return snd_hdac_aligned_mmio(bus) ?
45262306a36Sopenharmony_ci		snd_hdac_aligned_read(addr, 0xffff) : readw(addr);
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci#define snd_hdac_reg_writel(bus, addr, val)	writel(val, addr)
45662306a36Sopenharmony_ci#define snd_hdac_reg_readl(bus, addr)	readl(addr)
45762306a36Sopenharmony_ci#define snd_hdac_reg_writeq(bus, addr, val)	writeq(val, addr)
45862306a36Sopenharmony_ci#define snd_hdac_reg_readq(bus, addr)		readq(addr)
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci/*
46162306a36Sopenharmony_ci * macros for easy use
46262306a36Sopenharmony_ci */
46362306a36Sopenharmony_ci#define _snd_hdac_chip_writeb(chip, reg, value) \
46462306a36Sopenharmony_ci	snd_hdac_reg_writeb(chip, (chip)->remap_addr + (reg), value)
46562306a36Sopenharmony_ci#define _snd_hdac_chip_readb(chip, reg) \
46662306a36Sopenharmony_ci	snd_hdac_reg_readb(chip, (chip)->remap_addr + (reg))
46762306a36Sopenharmony_ci#define _snd_hdac_chip_writew(chip, reg, value) \
46862306a36Sopenharmony_ci	snd_hdac_reg_writew(chip, (chip)->remap_addr + (reg), value)
46962306a36Sopenharmony_ci#define _snd_hdac_chip_readw(chip, reg) \
47062306a36Sopenharmony_ci	snd_hdac_reg_readw(chip, (chip)->remap_addr + (reg))
47162306a36Sopenharmony_ci#define _snd_hdac_chip_writel(chip, reg, value) \
47262306a36Sopenharmony_ci	snd_hdac_reg_writel(chip, (chip)->remap_addr + (reg), value)
47362306a36Sopenharmony_ci#define _snd_hdac_chip_readl(chip, reg) \
47462306a36Sopenharmony_ci	snd_hdac_reg_readl(chip, (chip)->remap_addr + (reg))
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci/* read/write a register, pass without AZX_REG_ prefix */
47762306a36Sopenharmony_ci#define snd_hdac_chip_writel(chip, reg, value) \
47862306a36Sopenharmony_ci	_snd_hdac_chip_writel(chip, AZX_REG_ ## reg, value)
47962306a36Sopenharmony_ci#define snd_hdac_chip_writew(chip, reg, value) \
48062306a36Sopenharmony_ci	_snd_hdac_chip_writew(chip, AZX_REG_ ## reg, value)
48162306a36Sopenharmony_ci#define snd_hdac_chip_writeb(chip, reg, value) \
48262306a36Sopenharmony_ci	_snd_hdac_chip_writeb(chip, AZX_REG_ ## reg, value)
48362306a36Sopenharmony_ci#define snd_hdac_chip_readl(chip, reg) \
48462306a36Sopenharmony_ci	_snd_hdac_chip_readl(chip, AZX_REG_ ## reg)
48562306a36Sopenharmony_ci#define snd_hdac_chip_readw(chip, reg) \
48662306a36Sopenharmony_ci	_snd_hdac_chip_readw(chip, AZX_REG_ ## reg)
48762306a36Sopenharmony_ci#define snd_hdac_chip_readb(chip, reg) \
48862306a36Sopenharmony_ci	_snd_hdac_chip_readb(chip, AZX_REG_ ## reg)
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci/* update a register, pass without AZX_REG_ prefix */
49162306a36Sopenharmony_ci#define snd_hdac_chip_updatel(chip, reg, mask, val) \
49262306a36Sopenharmony_ci	snd_hdac_chip_writel(chip, reg, \
49362306a36Sopenharmony_ci			     (snd_hdac_chip_readl(chip, reg) & ~(mask)) | (val))
49462306a36Sopenharmony_ci#define snd_hdac_chip_updatew(chip, reg, mask, val) \
49562306a36Sopenharmony_ci	snd_hdac_chip_writew(chip, reg, \
49662306a36Sopenharmony_ci			     (snd_hdac_chip_readw(chip, reg) & ~(mask)) | (val))
49762306a36Sopenharmony_ci#define snd_hdac_chip_updateb(chip, reg, mask, val) \
49862306a36Sopenharmony_ci	snd_hdac_chip_writeb(chip, reg, \
49962306a36Sopenharmony_ci			     (snd_hdac_chip_readb(chip, reg) & ~(mask)) | (val))
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci/* update register macro */
50262306a36Sopenharmony_ci#define snd_hdac_updatel(addr, reg, mask, val)		\
50362306a36Sopenharmony_ci	writel(((readl(addr + reg) & ~(mask)) | (val)), addr + reg)
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci#define snd_hdac_updatew(addr, reg, mask, val)		\
50662306a36Sopenharmony_ci	writew(((readw(addr + reg) & ~(mask)) | (val)), addr + reg)
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci/*
50962306a36Sopenharmony_ci * HD-audio stream
51062306a36Sopenharmony_ci */
51162306a36Sopenharmony_cistruct hdac_stream {
51262306a36Sopenharmony_ci	struct hdac_bus *bus;
51362306a36Sopenharmony_ci	struct snd_dma_buffer bdl; /* BDL buffer */
51462306a36Sopenharmony_ci	__le32 *posbuf;		/* position buffer pointer */
51562306a36Sopenharmony_ci	int direction;		/* playback / capture (SNDRV_PCM_STREAM_*) */
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	unsigned int bufsize;	/* size of the play buffer in bytes */
51862306a36Sopenharmony_ci	unsigned int period_bytes; /* size of the period in bytes */
51962306a36Sopenharmony_ci	unsigned int frags;	/* number for period in the play buffer */
52062306a36Sopenharmony_ci	unsigned int fifo_size;	/* FIFO size */
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	void __iomem *sd_addr;	/* stream descriptor pointer */
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	void __iomem *spib_addr; /* software position in buffers stream pointer */
52562306a36Sopenharmony_ci	void __iomem *fifo_addr; /* software position Max fifos stream pointer */
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	void __iomem *dpibr_addr; /* DMA position in buffer resume pointer */
52862306a36Sopenharmony_ci	u32 dpib;		/* DMA position in buffer */
52962306a36Sopenharmony_ci	u32 lpib;		/* Linear position in buffer */
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	u32 sd_int_sta_mask;	/* stream int status mask */
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	/* pcm support */
53462306a36Sopenharmony_ci	struct snd_pcm_substream *substream;	/* assigned substream,
53562306a36Sopenharmony_ci						 * set in PCM open
53662306a36Sopenharmony_ci						 */
53762306a36Sopenharmony_ci	struct snd_compr_stream *cstream;
53862306a36Sopenharmony_ci	unsigned int format_val;	/* format value to be set in the
53962306a36Sopenharmony_ci					 * controller and the codec
54062306a36Sopenharmony_ci					 */
54162306a36Sopenharmony_ci	unsigned char stream_tag;	/* assigned stream */
54262306a36Sopenharmony_ci	unsigned char index;		/* stream index */
54362306a36Sopenharmony_ci	int assigned_key;		/* last device# key assigned to */
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	bool opened:1;
54662306a36Sopenharmony_ci	bool running:1;
54762306a36Sopenharmony_ci	bool prepared:1;
54862306a36Sopenharmony_ci	bool no_period_wakeup:1;
54962306a36Sopenharmony_ci	bool locked:1;
55062306a36Sopenharmony_ci	bool stripe:1;			/* apply stripe control */
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	u64 curr_pos;
55362306a36Sopenharmony_ci	/* timestamp */
55462306a36Sopenharmony_ci	unsigned long start_wallclk;	/* start + minimum wallclk */
55562306a36Sopenharmony_ci	unsigned long period_wallclk;	/* wallclk for period */
55662306a36Sopenharmony_ci	struct timecounter  tc;
55762306a36Sopenharmony_ci	struct cyclecounter cc;
55862306a36Sopenharmony_ci	int delay_negative_threshold;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	struct list_head list;
56162306a36Sopenharmony_ci#ifdef CONFIG_SND_HDA_DSP_LOADER
56262306a36Sopenharmony_ci	/* DSP access mutex */
56362306a36Sopenharmony_ci	struct mutex dsp_mutex;
56462306a36Sopenharmony_ci#endif
56562306a36Sopenharmony_ci};
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_civoid snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev,
56862306a36Sopenharmony_ci			  int idx, int direction, int tag);
56962306a36Sopenharmony_cistruct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
57062306a36Sopenharmony_ci					   struct snd_pcm_substream *substream);
57162306a36Sopenharmony_civoid snd_hdac_stream_release_locked(struct hdac_stream *azx_dev);
57262306a36Sopenharmony_civoid snd_hdac_stream_release(struct hdac_stream *azx_dev);
57362306a36Sopenharmony_cistruct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus,
57462306a36Sopenharmony_ci					int dir, int stream_tag);
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ciint snd_hdac_stream_setup(struct hdac_stream *azx_dev);
57762306a36Sopenharmony_civoid snd_hdac_stream_cleanup(struct hdac_stream *azx_dev);
57862306a36Sopenharmony_ciint snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev);
57962306a36Sopenharmony_ciint snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
58062306a36Sopenharmony_ci				unsigned int format_val);
58162306a36Sopenharmony_civoid snd_hdac_stream_start(struct hdac_stream *azx_dev);
58262306a36Sopenharmony_civoid snd_hdac_stream_stop(struct hdac_stream *azx_dev);
58362306a36Sopenharmony_civoid snd_hdac_stop_streams(struct hdac_bus *bus);
58462306a36Sopenharmony_civoid snd_hdac_stop_streams_and_chip(struct hdac_bus *bus);
58562306a36Sopenharmony_civoid snd_hdac_stream_reset(struct hdac_stream *azx_dev);
58662306a36Sopenharmony_civoid snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set,
58762306a36Sopenharmony_ci				  unsigned int streams, unsigned int reg);
58862306a36Sopenharmony_civoid snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start,
58962306a36Sopenharmony_ci			  unsigned int streams);
59062306a36Sopenharmony_civoid snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev,
59162306a36Sopenharmony_ci				      unsigned int streams);
59262306a36Sopenharmony_ciint snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
59362306a36Sopenharmony_ci				struct snd_pcm_substream *substream);
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_civoid snd_hdac_stream_spbcap_enable(struct hdac_bus *chip,
59662306a36Sopenharmony_ci				   bool enable, int index);
59762306a36Sopenharmony_ciint snd_hdac_stream_set_spib(struct hdac_bus *bus,
59862306a36Sopenharmony_ci			     struct hdac_stream *azx_dev, u32 value);
59962306a36Sopenharmony_ciint snd_hdac_stream_get_spbmaxfifo(struct hdac_bus *bus,
60062306a36Sopenharmony_ci				   struct hdac_stream *azx_dev);
60162306a36Sopenharmony_civoid snd_hdac_stream_drsm_enable(struct hdac_bus *bus,
60262306a36Sopenharmony_ci				 bool enable, int index);
60362306a36Sopenharmony_ciint snd_hdac_stream_wait_drsm(struct hdac_stream *azx_dev);
60462306a36Sopenharmony_ciint snd_hdac_stream_set_dpibr(struct hdac_bus *bus,
60562306a36Sopenharmony_ci			      struct hdac_stream *azx_dev, u32 value);
60662306a36Sopenharmony_ciint snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci/*
60962306a36Sopenharmony_ci * macros for easy use
61062306a36Sopenharmony_ci */
61162306a36Sopenharmony_ci/* read/write a register, pass without AZX_REG_ prefix */
61262306a36Sopenharmony_ci#define snd_hdac_stream_writel(dev, reg, value) \
61362306a36Sopenharmony_ci	snd_hdac_reg_writel((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
61462306a36Sopenharmony_ci#define snd_hdac_stream_writew(dev, reg, value) \
61562306a36Sopenharmony_ci	snd_hdac_reg_writew((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
61662306a36Sopenharmony_ci#define snd_hdac_stream_writeb(dev, reg, value) \
61762306a36Sopenharmony_ci	snd_hdac_reg_writeb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
61862306a36Sopenharmony_ci#define snd_hdac_stream_readl(dev, reg) \
61962306a36Sopenharmony_ci	snd_hdac_reg_readl((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
62062306a36Sopenharmony_ci#define snd_hdac_stream_readw(dev, reg) \
62162306a36Sopenharmony_ci	snd_hdac_reg_readw((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
62262306a36Sopenharmony_ci#define snd_hdac_stream_readb(dev, reg) \
62362306a36Sopenharmony_ci	snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
62462306a36Sopenharmony_ci#define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
62562306a36Sopenharmony_ci	read_poll_timeout_atomic(snd_hdac_reg_readb, val, cond, delay_us, timeout_us, \
62662306a36Sopenharmony_ci				 false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
62762306a36Sopenharmony_ci#define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
62862306a36Sopenharmony_ci	read_poll_timeout_atomic(snd_hdac_reg_readl, val, cond, delay_us, timeout_us, \
62962306a36Sopenharmony_ci				 false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci/* update a register, pass without AZX_REG_ prefix */
63262306a36Sopenharmony_ci#define snd_hdac_stream_updatel(dev, reg, mask, val) \
63362306a36Sopenharmony_ci	snd_hdac_stream_writel(dev, reg, \
63462306a36Sopenharmony_ci			       (snd_hdac_stream_readl(dev, reg) & \
63562306a36Sopenharmony_ci				~(mask)) | (val))
63662306a36Sopenharmony_ci#define snd_hdac_stream_updatew(dev, reg, mask, val) \
63762306a36Sopenharmony_ci	snd_hdac_stream_writew(dev, reg, \
63862306a36Sopenharmony_ci			       (snd_hdac_stream_readw(dev, reg) & \
63962306a36Sopenharmony_ci				~(mask)) | (val))
64062306a36Sopenharmony_ci#define snd_hdac_stream_updateb(dev, reg, mask, val) \
64162306a36Sopenharmony_ci	snd_hdac_stream_writeb(dev, reg, \
64262306a36Sopenharmony_ci			       (snd_hdac_stream_readb(dev, reg) & \
64362306a36Sopenharmony_ci				~(mask)) | (val))
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci#ifdef CONFIG_SND_HDA_DSP_LOADER
64662306a36Sopenharmony_ci/* DSP lock helpers */
64762306a36Sopenharmony_ci#define snd_hdac_dsp_lock_init(dev)	mutex_init(&(dev)->dsp_mutex)
64862306a36Sopenharmony_ci#define snd_hdac_dsp_lock(dev)		mutex_lock(&(dev)->dsp_mutex)
64962306a36Sopenharmony_ci#define snd_hdac_dsp_unlock(dev)	mutex_unlock(&(dev)->dsp_mutex)
65062306a36Sopenharmony_ci#define snd_hdac_stream_is_locked(dev)	((dev)->locked)
65162306a36Sopenharmony_ci/* DSP loader helpers */
65262306a36Sopenharmony_ciint snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
65362306a36Sopenharmony_ci			 unsigned int byte_size, struct snd_dma_buffer *bufp);
65462306a36Sopenharmony_civoid snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start);
65562306a36Sopenharmony_civoid snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev,
65662306a36Sopenharmony_ci			  struct snd_dma_buffer *dmab);
65762306a36Sopenharmony_ci#else /* CONFIG_SND_HDA_DSP_LOADER */
65862306a36Sopenharmony_ci#define snd_hdac_dsp_lock_init(dev)	do {} while (0)
65962306a36Sopenharmony_ci#define snd_hdac_dsp_lock(dev)		do {} while (0)
66062306a36Sopenharmony_ci#define snd_hdac_dsp_unlock(dev)	do {} while (0)
66162306a36Sopenharmony_ci#define snd_hdac_stream_is_locked(dev)	0
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_cistatic inline int
66462306a36Sopenharmony_cisnd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
66562306a36Sopenharmony_ci		     unsigned int byte_size, struct snd_dma_buffer *bufp)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	return 0;
66862306a36Sopenharmony_ci}
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_cistatic inline void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start)
67162306a36Sopenharmony_ci{
67262306a36Sopenharmony_ci}
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_cistatic inline void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev,
67562306a36Sopenharmony_ci					struct snd_dma_buffer *dmab)
67662306a36Sopenharmony_ci{
67762306a36Sopenharmony_ci}
67862306a36Sopenharmony_ci#endif /* CONFIG_SND_HDA_DSP_LOADER */
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci/*
68262306a36Sopenharmony_ci * generic array helpers
68362306a36Sopenharmony_ci */
68462306a36Sopenharmony_civoid *snd_array_new(struct snd_array *array);
68562306a36Sopenharmony_civoid snd_array_free(struct snd_array *array);
68662306a36Sopenharmony_cistatic inline void snd_array_init(struct snd_array *array, unsigned int size,
68762306a36Sopenharmony_ci				  unsigned int align)
68862306a36Sopenharmony_ci{
68962306a36Sopenharmony_ci	array->elem_size = size;
69062306a36Sopenharmony_ci	array->alloc_align = align;
69162306a36Sopenharmony_ci}
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_cistatic inline void *snd_array_elem(struct snd_array *array, unsigned int idx)
69462306a36Sopenharmony_ci{
69562306a36Sopenharmony_ci	return array->list + idx * array->elem_size;
69662306a36Sopenharmony_ci}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_cistatic inline unsigned int snd_array_index(struct snd_array *array, void *ptr)
69962306a36Sopenharmony_ci{
70062306a36Sopenharmony_ci	return (unsigned long)(ptr - array->list) / array->elem_size;
70162306a36Sopenharmony_ci}
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci/* a helper macro to iterate for each snd_array element */
70462306a36Sopenharmony_ci#define snd_array_for_each(array, idx, ptr) \
70562306a36Sopenharmony_ci	for ((idx) = 0, (ptr) = (array)->list; (idx) < (array)->used; \
70662306a36Sopenharmony_ci	     (ptr) = snd_array_elem(array, ++(idx)))
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci/*
70962306a36Sopenharmony_ci * Device matching
71062306a36Sopenharmony_ci */
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci#define HDA_CONTROLLER_IS_HSW(pci) (pci_match_id((struct pci_device_id []){ \
71362306a36Sopenharmony_ci			{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_0) }, \
71462306a36Sopenharmony_ci			{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_2) }, \
71562306a36Sopenharmony_ci			{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_3) }, \
71662306a36Sopenharmony_ci			{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_BDW) }, \
71762306a36Sopenharmony_ci			{ } \
71862306a36Sopenharmony_ci		}, pci))
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci#define HDA_CONTROLLER_IS_APL(pci) (pci_match_id((struct pci_device_id []){ \
72162306a36Sopenharmony_ci			{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_APL) }, \
72262306a36Sopenharmony_ci			{ } \
72362306a36Sopenharmony_ci		}, pci))
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci#define HDA_CONTROLLER_IN_GPU(pci) (pci_match_id((struct pci_device_id []){ \
72662306a36Sopenharmony_ci			{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG1) }, \
72762306a36Sopenharmony_ci			{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_0) }, \
72862306a36Sopenharmony_ci			{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_1) }, \
72962306a36Sopenharmony_ci			{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_2) }, \
73062306a36Sopenharmony_ci			{ } \
73162306a36Sopenharmony_ci		}, pci) || HDA_CONTROLLER_IS_HSW(pci))
73262306a36Sopenharmony_ci
73362306a36Sopenharmony_ci#endif /* __SOUND_HDAUDIO_H */
734