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