1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * HD-audio core stuff
4 */
5
6#ifndef __SOUND_HDAUDIO_H
7#define __SOUND_HDAUDIO_H
8
9#include <linux/device.h>
10#include <linux/interrupt.h>
11#include <linux/io.h>
12#include <linux/pm_runtime.h>
13#include <linux/timecounter.h>
14#include <sound/core.h>
15#include <sound/pcm.h>
16#include <sound/memalloc.h>
17#include <sound/hda_verbs.h>
18#include <drm/i915_component.h>
19
20/* codec node id */
21typedef u16 hda_nid_t;
22
23struct hdac_bus;
24struct hdac_stream;
25struct hdac_device;
26struct hdac_driver;
27struct hdac_widget_tree;
28struct hda_device_id;
29
30/*
31 * exported bus type
32 */
33extern struct bus_type snd_hda_bus_type;
34
35/*
36 * generic arrays
37 */
38struct snd_array {
39	unsigned int used;
40	unsigned int alloced;
41	unsigned int elem_size;
42	unsigned int alloc_align;
43	void *list;
44};
45
46/*
47 * HD-audio codec base device
48 */
49struct hdac_device {
50	struct device dev;
51	int type;
52	struct hdac_bus *bus;
53	unsigned int addr;		/* codec address */
54	struct list_head list;		/* list point for bus codec_list */
55
56	hda_nid_t afg;			/* AFG node id */
57	hda_nid_t mfg;			/* MFG node id */
58
59	/* ids */
60	unsigned int vendor_id;
61	unsigned int subsystem_id;
62	unsigned int revision_id;
63	unsigned int afg_function_id;
64	unsigned int mfg_function_id;
65	unsigned int afg_unsol:1;
66	unsigned int mfg_unsol:1;
67
68	unsigned int power_caps;	/* FG power caps */
69
70	const char *vendor_name;	/* codec vendor name */
71	const char *chip_name;		/* codec chip name */
72
73	/* verb exec op override */
74	int (*exec_verb)(struct hdac_device *dev, unsigned int cmd,
75			 unsigned int flags, unsigned int *res);
76
77	/* widgets */
78	unsigned int num_nodes;
79	hda_nid_t start_nid, end_nid;
80
81	/* misc flags */
82	atomic_t in_pm;		/* suspend/resume being performed */
83
84	/* sysfs */
85	struct mutex widget_lock;
86	struct hdac_widget_tree *widgets;
87
88	/* regmap */
89	struct regmap *regmap;
90	struct mutex regmap_lock;
91	struct snd_array vendor_verbs;
92	bool lazy_cache:1;	/* don't wake up for writes */
93	bool caps_overwriting:1; /* caps overwrite being in process */
94	bool cache_coef:1;	/* cache COEF read/write too */
95};
96
97/* device/driver type used for matching */
98enum {
99	HDA_DEV_CORE,
100	HDA_DEV_LEGACY,
101	HDA_DEV_ASOC,
102};
103
104enum {
105	SND_SKL_PCI_BIND_AUTO,	/* automatic selection based on pci class */
106	SND_SKL_PCI_BIND_LEGACY,/* bind only with legacy driver */
107	SND_SKL_PCI_BIND_ASOC	/* bind only with ASoC driver */
108};
109
110/* direction */
111enum {
112	HDA_INPUT, HDA_OUTPUT
113};
114
115#define dev_to_hdac_dev(_dev)	container_of(_dev, struct hdac_device, dev)
116
117int snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus,
118			 const char *name, unsigned int addr);
119void snd_hdac_device_exit(struct hdac_device *dev);
120int snd_hdac_device_register(struct hdac_device *codec);
121void snd_hdac_device_unregister(struct hdac_device *codec);
122int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name);
123int snd_hdac_codec_modalias(struct hdac_device *hdac, char *buf, size_t size);
124
125int snd_hdac_refresh_widgets(struct hdac_device *codec);
126
127int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid,
128		  unsigned int verb, unsigned int parm, unsigned int *res);
129int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm,
130			unsigned int *res);
131int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid,
132				int parm);
133int snd_hdac_override_parm(struct hdac_device *codec, hda_nid_t nid,
134			   unsigned int parm, unsigned int val);
135int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid,
136			     hda_nid_t *conn_list, int max_conns);
137int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,
138			   hda_nid_t *start_id);
139unsigned int snd_hdac_calc_stream_format(unsigned int rate,
140					 unsigned int channels,
141					 snd_pcm_format_t format,
142					 unsigned int maxbps,
143					 unsigned short spdif_ctls);
144int snd_hdac_query_supported_pcm(struct hdac_device *codec, hda_nid_t nid,
145				u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
146bool snd_hdac_is_supported_format(struct hdac_device *codec, hda_nid_t nid,
147				  unsigned int format);
148
149int snd_hdac_codec_read(struct hdac_device *hdac, hda_nid_t nid,
150			int flags, unsigned int verb, unsigned int parm);
151int snd_hdac_codec_write(struct hdac_device *hdac, hda_nid_t nid,
152			int flags, unsigned int verb, unsigned int parm);
153bool snd_hdac_check_power_state(struct hdac_device *hdac,
154		hda_nid_t nid, unsigned int target_state);
155unsigned int snd_hdac_sync_power_state(struct hdac_device *hdac,
156		      hda_nid_t nid, unsigned int target_state);
157/**
158 * snd_hdac_read_parm - read a codec parameter
159 * @codec: the codec object
160 * @nid: NID to read a parameter
161 * @parm: parameter to read
162 *
163 * Returns -1 for error.  If you need to distinguish the error more
164 * strictly, use _snd_hdac_read_parm() directly.
165 */
166static inline int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid,
167				     int parm)
168{
169	unsigned int val;
170
171	return _snd_hdac_read_parm(codec, nid, parm, &val) < 0 ? -1 : val;
172}
173
174#ifdef CONFIG_PM
175int snd_hdac_power_up(struct hdac_device *codec);
176int snd_hdac_power_down(struct hdac_device *codec);
177int snd_hdac_power_up_pm(struct hdac_device *codec);
178int snd_hdac_power_down_pm(struct hdac_device *codec);
179int snd_hdac_keep_power_up(struct hdac_device *codec);
180
181/* call this at entering into suspend/resume callbacks in codec driver */
182static inline void snd_hdac_enter_pm(struct hdac_device *codec)
183{
184	atomic_inc(&codec->in_pm);
185}
186
187/* call this at leaving from suspend/resume callbacks in codec driver */
188static inline void snd_hdac_leave_pm(struct hdac_device *codec)
189{
190	atomic_dec(&codec->in_pm);
191}
192
193static inline bool snd_hdac_is_in_pm(struct hdac_device *codec)
194{
195	return atomic_read(&codec->in_pm);
196}
197
198static inline bool snd_hdac_is_power_on(struct hdac_device *codec)
199{
200	return !pm_runtime_suspended(&codec->dev);
201}
202#else
203static inline int snd_hdac_power_up(struct hdac_device *codec) { return 0; }
204static inline int snd_hdac_power_down(struct hdac_device *codec) { return 0; }
205static inline int snd_hdac_power_up_pm(struct hdac_device *codec) { return 0; }
206static inline int snd_hdac_power_down_pm(struct hdac_device *codec) { return 0; }
207static inline int snd_hdac_keep_power_up(struct hdac_device *codec) { return 0; }
208static inline void snd_hdac_enter_pm(struct hdac_device *codec) {}
209static inline void snd_hdac_leave_pm(struct hdac_device *codec) {}
210static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return false; }
211static inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return true; }
212#endif
213
214/*
215 * HD-audio codec base driver
216 */
217struct hdac_driver {
218	struct device_driver driver;
219	int type;
220	const struct hda_device_id *id_table;
221	int (*match)(struct hdac_device *dev, struct hdac_driver *drv);
222	void (*unsol_event)(struct hdac_device *dev, unsigned int event);
223
224	/* fields used by ext bus APIs */
225	int (*probe)(struct hdac_device *dev);
226	int (*remove)(struct hdac_device *dev);
227	void (*shutdown)(struct hdac_device *dev);
228};
229
230#define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver)
231
232const struct hda_device_id *
233hdac_get_device_id(struct hdac_device *hdev, struct hdac_driver *drv);
234
235/*
236 * Bus verb operators
237 */
238struct hdac_bus_ops {
239	/* send a single command */
240	int (*command)(struct hdac_bus *bus, unsigned int cmd);
241	/* get a response from the last command */
242	int (*get_response)(struct hdac_bus *bus, unsigned int addr,
243			    unsigned int *res);
244};
245
246/*
247 * ops used for ASoC HDA codec drivers
248 */
249struct hdac_ext_bus_ops {
250	int (*hdev_attach)(struct hdac_device *hdev);
251	int (*hdev_detach)(struct hdac_device *hdev);
252};
253
254#define HDA_UNSOL_QUEUE_SIZE	64
255#define HDA_MAX_CODECS		8	/* limit by controller side */
256
257/*
258 * CORB/RIRB
259 *
260 * Each CORB entry is 4byte, RIRB is 8byte
261 */
262struct hdac_rb {
263	__le32 *buf;		/* virtual address of CORB/RIRB buffer */
264	dma_addr_t addr;	/* physical address of CORB/RIRB buffer */
265	unsigned short rp, wp;	/* RIRB read/write pointers */
266	int cmds[HDA_MAX_CODECS];	/* number of pending requests */
267	u32 res[HDA_MAX_CODECS];	/* last read value */
268};
269
270/*
271 * HD-audio bus base driver
272 *
273 * @ppcap: pp capabilities pointer
274 * @spbcap: SPIB capabilities pointer
275 * @mlcap: MultiLink capabilities pointer
276 * @gtscap: gts capabilities pointer
277 * @drsmcap: dma resume capabilities pointer
278 * @num_streams: streams supported
279 * @idx: HDA link index
280 * @hlink_list: link list of HDA links
281 * @lock: lock for link and display power mgmt
282 * @cmd_dma_state: state of cmd DMAs: CORB and RIRB
283 */
284struct hdac_bus {
285	struct device *dev;
286	const struct hdac_bus_ops *ops;
287	const struct hdac_ext_bus_ops *ext_ops;
288
289	/* h/w resources */
290	unsigned long addr;
291	void __iomem *remap_addr;
292	int irq;
293
294	void __iomem *ppcap;
295	void __iomem *spbcap;
296	void __iomem *mlcap;
297	void __iomem *gtscap;
298	void __iomem *drsmcap;
299
300	/* codec linked list */
301	struct list_head codec_list;
302	unsigned int num_codecs;
303
304	/* link caddr -> codec */
305	struct hdac_device *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1];
306
307	/* unsolicited event queue */
308	u32 unsol_queue[HDA_UNSOL_QUEUE_SIZE * 2]; /* ring buffer */
309	unsigned int unsol_rp, unsol_wp;
310	struct work_struct unsol_work;
311
312	/* bit flags of detected codecs */
313	unsigned long codec_mask;
314
315	/* bit flags of powered codecs */
316	unsigned long codec_powered;
317
318	/* CORB/RIRB */
319	struct hdac_rb corb;
320	struct hdac_rb rirb;
321	unsigned int last_cmd[HDA_MAX_CODECS];	/* last sent command */
322	wait_queue_head_t rirb_wq;
323
324	/* CORB/RIRB and position buffers */
325	struct snd_dma_buffer rb;
326	struct snd_dma_buffer posbuf;
327	int dma_type;			/* SNDRV_DMA_TYPE_XXX for CORB/RIRB */
328
329	/* hdac_stream linked list */
330	struct list_head stream_list;
331
332	/* operation state */
333	bool chip_init:1;		/* h/w initialized */
334
335	/* behavior flags */
336	bool aligned_mmio:1;		/* aligned MMIO access */
337	bool sync_write:1;		/* sync after verb write */
338	bool use_posbuf:1;		/* use position buffer */
339	bool snoop:1;			/* enable snooping */
340	bool align_bdle_4k:1;		/* BDLE align 4K boundary */
341	bool reverse_assign:1;		/* assign devices in reverse order */
342	bool corbrp_self_clear:1;	/* CORBRP clears itself after reset */
343	bool polling_mode:1;
344	bool needs_damn_long_delay:1;
345
346	int poll_count;
347
348	int bdl_pos_adj;		/* BDL position adjustment */
349
350	/* delay time in us for dma stop */
351	unsigned int dma_stop_delay;
352
353	/* locks */
354	spinlock_t reg_lock;
355	struct mutex cmd_mutex;
356	struct mutex lock;
357
358	/* DRM component interface */
359	struct drm_audio_component *audio_component;
360	long display_power_status;
361	unsigned long display_power_active;
362
363	/* parameters required for enhanced capabilities */
364	int num_streams;
365	int idx;
366
367	/* link management */
368	struct list_head hlink_list;
369	bool cmd_dma_state;
370
371	/* factor used to derive STRIPE control value */
372	unsigned int sdo_limit;
373};
374
375int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
376		      const struct hdac_bus_ops *ops);
377void snd_hdac_bus_exit(struct hdac_bus *bus);
378int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr,
379				    unsigned int cmd, unsigned int *res);
380
381static inline void snd_hdac_codec_link_up(struct hdac_device *codec)
382{
383	set_bit(codec->addr, &codec->bus->codec_powered);
384}
385
386static inline void snd_hdac_codec_link_down(struct hdac_device *codec)
387{
388	clear_bit(codec->addr, &codec->bus->codec_powered);
389}
390
391int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val);
392int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
393			      unsigned int *res);
394int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus);
395
396bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset);
397void snd_hdac_bus_stop_chip(struct hdac_bus *bus);
398void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus);
399void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus);
400void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus);
401void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus);
402int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset);
403
404void snd_hdac_bus_update_rirb(struct hdac_bus *bus);
405int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
406				    void (*ack)(struct hdac_bus *,
407						struct hdac_stream *));
408
409int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus);
410void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus);
411
412#ifdef CONFIG_SND_HDA_ALIGNED_MMIO
413unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask);
414void snd_hdac_aligned_write(unsigned int val, void __iomem *addr,
415			    unsigned int mask);
416#define snd_hdac_aligned_mmio(bus)	(bus)->aligned_mmio
417#else
418#define snd_hdac_aligned_mmio(bus)	false
419#define snd_hdac_aligned_read(addr, mask)	0
420#define snd_hdac_aligned_write(val, addr, mask) do {} while (0)
421#endif
422
423static inline void snd_hdac_reg_writeb(struct hdac_bus *bus, void __iomem *addr,
424				       u8 val)
425{
426	if (snd_hdac_aligned_mmio(bus))
427		snd_hdac_aligned_write(val, addr, 0xff);
428	else
429		writeb(val, addr);
430}
431
432static inline void snd_hdac_reg_writew(struct hdac_bus *bus, void __iomem *addr,
433				       u16 val)
434{
435	if (snd_hdac_aligned_mmio(bus))
436		snd_hdac_aligned_write(val, addr, 0xffff);
437	else
438		writew(val, addr);
439}
440
441static inline u8 snd_hdac_reg_readb(struct hdac_bus *bus, void __iomem *addr)
442{
443	return snd_hdac_aligned_mmio(bus) ?
444		snd_hdac_aligned_read(addr, 0xff) : readb(addr);
445}
446
447static inline u16 snd_hdac_reg_readw(struct hdac_bus *bus, void __iomem *addr)
448{
449	return snd_hdac_aligned_mmio(bus) ?
450		snd_hdac_aligned_read(addr, 0xffff) : readw(addr);
451}
452
453#define snd_hdac_reg_writel(bus, addr, val)	writel(val, addr)
454#define snd_hdac_reg_readl(bus, addr)	readl(addr)
455
456/*
457 * macros for easy use
458 */
459#define _snd_hdac_chip_writeb(chip, reg, value) \
460	snd_hdac_reg_writeb(chip, (chip)->remap_addr + (reg), value)
461#define _snd_hdac_chip_readb(chip, reg) \
462	snd_hdac_reg_readb(chip, (chip)->remap_addr + (reg))
463#define _snd_hdac_chip_writew(chip, reg, value) \
464	snd_hdac_reg_writew(chip, (chip)->remap_addr + (reg), value)
465#define _snd_hdac_chip_readw(chip, reg) \
466	snd_hdac_reg_readw(chip, (chip)->remap_addr + (reg))
467#define _snd_hdac_chip_writel(chip, reg, value) \
468	snd_hdac_reg_writel(chip, (chip)->remap_addr + (reg), value)
469#define _snd_hdac_chip_readl(chip, reg) \
470	snd_hdac_reg_readl(chip, (chip)->remap_addr + (reg))
471
472/* read/write a register, pass without AZX_REG_ prefix */
473#define snd_hdac_chip_writel(chip, reg, value) \
474	_snd_hdac_chip_writel(chip, AZX_REG_ ## reg, value)
475#define snd_hdac_chip_writew(chip, reg, value) \
476	_snd_hdac_chip_writew(chip, AZX_REG_ ## reg, value)
477#define snd_hdac_chip_writeb(chip, reg, value) \
478	_snd_hdac_chip_writeb(chip, AZX_REG_ ## reg, value)
479#define snd_hdac_chip_readl(chip, reg) \
480	_snd_hdac_chip_readl(chip, AZX_REG_ ## reg)
481#define snd_hdac_chip_readw(chip, reg) \
482	_snd_hdac_chip_readw(chip, AZX_REG_ ## reg)
483#define snd_hdac_chip_readb(chip, reg) \
484	_snd_hdac_chip_readb(chip, AZX_REG_ ## reg)
485
486/* update a register, pass without AZX_REG_ prefix */
487#define snd_hdac_chip_updatel(chip, reg, mask, val) \
488	snd_hdac_chip_writel(chip, reg, \
489			     (snd_hdac_chip_readl(chip, reg) & ~(mask)) | (val))
490#define snd_hdac_chip_updatew(chip, reg, mask, val) \
491	snd_hdac_chip_writew(chip, reg, \
492			     (snd_hdac_chip_readw(chip, reg) & ~(mask)) | (val))
493#define snd_hdac_chip_updateb(chip, reg, mask, val) \
494	snd_hdac_chip_writeb(chip, reg, \
495			     (snd_hdac_chip_readb(chip, reg) & ~(mask)) | (val))
496
497/*
498 * HD-audio stream
499 */
500struct hdac_stream {
501	struct hdac_bus *bus;
502	struct snd_dma_buffer bdl; /* BDL buffer */
503	__le32 *posbuf;		/* position buffer pointer */
504	int direction;		/* playback / capture (SNDRV_PCM_STREAM_*) */
505
506	unsigned int bufsize;	/* size of the play buffer in bytes */
507	unsigned int period_bytes; /* size of the period in bytes */
508	unsigned int frags;	/* number for period in the play buffer */
509	unsigned int fifo_size;	/* FIFO size */
510
511	void __iomem *sd_addr;	/* stream descriptor pointer */
512
513	u32 sd_int_sta_mask;	/* stream int status mask */
514
515	/* pcm support */
516	struct snd_pcm_substream *substream;	/* assigned substream,
517						 * set in PCM open
518						 */
519	struct snd_compr_stream *cstream;
520	unsigned int format_val;	/* format value to be set in the
521					 * controller and the codec
522					 */
523	unsigned char stream_tag;	/* assigned stream */
524	unsigned char index;		/* stream index */
525	int assigned_key;		/* last device# key assigned to */
526
527	bool opened:1;
528	bool running:1;
529	bool prepared:1;
530	bool no_period_wakeup:1;
531	bool locked:1;
532	bool stripe:1;			/* apply stripe control */
533
534	u64 curr_pos;
535	/* timestamp */
536	unsigned long start_wallclk;	/* start + minimum wallclk */
537	unsigned long period_wallclk;	/* wallclk for period */
538	struct timecounter  tc;
539	struct cyclecounter cc;
540	int delay_negative_threshold;
541
542	struct list_head list;
543#ifdef CONFIG_SND_HDA_DSP_LOADER
544	/* DSP access mutex */
545	struct mutex dsp_mutex;
546#endif
547};
548
549void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev,
550			  int idx, int direction, int tag);
551struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
552					   struct snd_pcm_substream *substream);
553void snd_hdac_stream_release(struct hdac_stream *azx_dev);
554struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus,
555					int dir, int stream_tag);
556
557int snd_hdac_stream_setup(struct hdac_stream *azx_dev);
558void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev);
559int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev);
560int snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
561				unsigned int format_val);
562void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start);
563void snd_hdac_stream_clear(struct hdac_stream *azx_dev);
564void snd_hdac_stream_stop(struct hdac_stream *azx_dev);
565void snd_hdac_stop_streams(struct hdac_bus *bus);
566void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus);
567void snd_hdac_stream_reset(struct hdac_stream *azx_dev);
568void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set,
569				  unsigned int streams, unsigned int reg);
570void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start,
571			  unsigned int streams);
572void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev,
573				      unsigned int streams);
574int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
575				struct snd_pcm_substream *substream);
576
577/*
578 * macros for easy use
579 */
580/* read/write a register, pass without AZX_REG_ prefix */
581#define snd_hdac_stream_writel(dev, reg, value) \
582	snd_hdac_reg_writel((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
583#define snd_hdac_stream_writew(dev, reg, value) \
584	snd_hdac_reg_writew((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
585#define snd_hdac_stream_writeb(dev, reg, value) \
586	snd_hdac_reg_writeb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
587#define snd_hdac_stream_readl(dev, reg) \
588	snd_hdac_reg_readl((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
589#define snd_hdac_stream_readw(dev, reg) \
590	snd_hdac_reg_readw((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
591#define snd_hdac_stream_readb(dev, reg) \
592	snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
593
594/* update a register, pass without AZX_REG_ prefix */
595#define snd_hdac_stream_updatel(dev, reg, mask, val) \
596	snd_hdac_stream_writel(dev, reg, \
597			       (snd_hdac_stream_readl(dev, reg) & \
598				~(mask)) | (val))
599#define snd_hdac_stream_updatew(dev, reg, mask, val) \
600	snd_hdac_stream_writew(dev, reg, \
601			       (snd_hdac_stream_readw(dev, reg) & \
602				~(mask)) | (val))
603#define snd_hdac_stream_updateb(dev, reg, mask, val) \
604	snd_hdac_stream_writeb(dev, reg, \
605			       (snd_hdac_stream_readb(dev, reg) & \
606				~(mask)) | (val))
607
608#ifdef CONFIG_SND_HDA_DSP_LOADER
609/* DSP lock helpers */
610#define snd_hdac_dsp_lock_init(dev)	mutex_init(&(dev)->dsp_mutex)
611#define snd_hdac_dsp_lock(dev)		mutex_lock(&(dev)->dsp_mutex)
612#define snd_hdac_dsp_unlock(dev)	mutex_unlock(&(dev)->dsp_mutex)
613#define snd_hdac_stream_is_locked(dev)	((dev)->locked)
614/* DSP loader helpers */
615int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
616			 unsigned int byte_size, struct snd_dma_buffer *bufp);
617void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start);
618void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev,
619			  struct snd_dma_buffer *dmab);
620#else /* CONFIG_SND_HDA_DSP_LOADER */
621#define snd_hdac_dsp_lock_init(dev)	do {} while (0)
622#define snd_hdac_dsp_lock(dev)		do {} while (0)
623#define snd_hdac_dsp_unlock(dev)	do {} while (0)
624#define snd_hdac_stream_is_locked(dev)	0
625
626static inline int
627snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
628		     unsigned int byte_size, struct snd_dma_buffer *bufp)
629{
630	return 0;
631}
632
633static inline void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start)
634{
635}
636
637static inline void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev,
638					struct snd_dma_buffer *dmab)
639{
640}
641#endif /* CONFIG_SND_HDA_DSP_LOADER */
642
643
644/*
645 * generic array helpers
646 */
647void *snd_array_new(struct snd_array *array);
648void snd_array_free(struct snd_array *array);
649static inline void snd_array_init(struct snd_array *array, unsigned int size,
650				  unsigned int align)
651{
652	array->elem_size = size;
653	array->alloc_align = align;
654}
655
656static inline void *snd_array_elem(struct snd_array *array, unsigned int idx)
657{
658	return array->list + idx * array->elem_size;
659}
660
661static inline unsigned int snd_array_index(struct snd_array *array, void *ptr)
662{
663	return (unsigned long)(ptr - array->list) / array->elem_size;
664}
665
666/* a helper macro to iterate for each snd_array element */
667#define snd_array_for_each(array, idx, ptr) \
668	for ((idx) = 0, (ptr) = (array)->list; (idx) < (array)->used; \
669	     (ptr) = snd_array_elem(array, ++(idx)))
670
671#endif /* __SOUND_HDAUDIO_H */
672