/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) *//* Copyright(c) 2015-17 Intel Corporation. */ #ifndef __SDW_INTEL_LOCAL_H#define __SDW_INTEL_LOCAL_H struct hdac_bus; /** * struct sdw_intel_link_res - Soundwire Intel link resource structure, * typically populated by the controller driver. * @hw_ops: platform-specific ops * @mmio_base: mmio base of SoundWire registers * @registers: Link IO registers base * @ip_offset: offset for MCP_IP registers * @shim: Audio shim pointer * @shim_vs: Audio vendor-specific shim pointer * @alh: ALH (Audio Link Hub) pointer * @irq: Interrupt line * @ops: Shim callback ops * @dev: device implementing hw_params and free callbacks * @shim_lock: mutex to handle access to shared SHIM registers * @shim_mask: global pointer to check SHIM register initialization * @clock_stop_quirks: mask defining requested behavior on pm_suspend * @mic_privacy: ACE version supports microphone privacy * @link_mask: global mask needed for power-up/down sequences * @cdns: Cadence master descriptor * @list: used to walk-through all masters exposed by the same controller * @hbus: hdac_bus pointer, needed for power management */struct sdw_intel_link_res { const struct sdw_intel_hw_ops *hw_ops; void __iomem *mmio_base; /* not strictly needed, useful for debug */ void __iomem *registers; u32 ip_offset; void __iomem *shim; void __iomem *shim_vs; void __iomem *alh; int irq; const struct sdw_intel_ops *ops; struct device *dev; struct mutex *shim_lock; /* protect shared registers */ u32 *shim_mask; u32 clock_stop_quirks; bool mic_privacy; u32 link_mask; struct sdw_cdns *cdns; struct list_head list; struct hdac_bus *hbus;}; /** * struct sdw_intel_bpt - SoundWire Intel BPT context * @bpt_tx_stream: BPT TX stream * @dmab_tx_bdl: BPT TX buffer descriptor list * @bpt_rx_stream: BPT RX stream * @dmab_rx_bdl: BPT RX buffer descriptor list * @pdi0_buffer_size: PDI0 buffer size * @pdi1_buffer_size: PDI1 buffer size * @num_frames: number of frames * @data_per_frame: data per frame */struct sdw_intel_bpt { struct hdac_ext_stream *bpt_tx_stream; struct snd_dma_buffer dmab_tx_bdl; struct hdac_ext_stream *bpt_rx_stream; struct snd_dma_buffer dmab_rx_bdl; unsigned int pdi0_buffer_size; unsigned int pdi1_buffer_size; unsigned int num_frames; unsigned int data_per_frame;}; struct sdw_intel { struct sdw_cdns cdns; int instance; struct sdw_intel_link_res *link_res; bool startup_done; struct sdw_intel_bpt bpt_ctx;#ifdef CONFIG_DEBUG_FS struct dentry *debugfs;#endif}; struct sdw_intel_prop { u16 clde; u16 doaise2; u16 dodse2; u16 clds; u16 clss; u16 doaise; u16 doais; u16 dodse; u16 dods;}; enum intel_pdi_type { INTEL_PDI_IN = 0, INTEL_PDI_OUT = 1, INTEL_PDI_BD = 2,}; /* * Read, write helpers for HW registers */static inline int intel_readl(void __iomem *base, int offset){ return readl(base + offset);} static inline void intel_writel(void __iomem *base, int offset, int value){ writel(value, base + offset);} static inline u16 intel_readw(void __iomem *base, int offset){ return readw(base + offset);} static inline void intel_writew(void __iomem *base, int offset, u16 value){ writew(value, base + offset);} #define cdns_to_intel(_cdns) container_of(_cdns, struct sdw_intel, cdns) #define INTEL_MASTER_RESET_ITERATIONS 10 #define SDW_INTEL_DELAYED_ENUMERATION_MS 100 #define SDW_INTEL_CHECK_OPS(sdw, cb) ((sdw) && (sdw)->link_res && (sdw)->link_res->hw_ops && \ (sdw)->link_res->hw_ops->cb)#define SDW_INTEL_OPS(sdw, cb) ((sdw)->link_res->hw_ops->cb) #ifdef CONFIG_DEBUG_FSvoid intel_ace2x_debugfs_init(struct sdw_intel *sdw);void intel_ace2x_debugfs_exit(struct sdw_intel *sdw);#elsestatic inline void intel_ace2x_debugfs_init(struct sdw_intel *sdw) {}static inline void intel_ace2x_debugfs_exit(struct sdw_intel *sdw) {}#endif static inline void sdw_intel_debugfs_init(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, debugfs_init)) SDW_INTEL_OPS(sdw, debugfs_init)(sdw);} static inline void sdw_intel_debugfs_exit(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, debugfs_exit)) SDW_INTEL_OPS(sdw, debugfs_exit)(sdw);} static inline int sdw_intel_register_dai(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, register_dai)) return SDW_INTEL_OPS(sdw, register_dai)(sdw); return -ENOTSUPP;} static inline void sdw_intel_check_clock_stop(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, check_clock_stop)) SDW_INTEL_OPS(sdw, check_clock_stop)(sdw);} static inline int sdw_intel_start_bus(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, start_bus)) return SDW_INTEL_OPS(sdw, start_bus)(sdw); return -ENOTSUPP;} static inline int sdw_intel_start_bus_after_reset(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, start_bus_after_reset)) return SDW_INTEL_OPS(sdw, start_bus_after_reset)(sdw); return -ENOTSUPP;} static inline int sdw_intel_start_bus_after_clock_stop(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, start_bus_after_clock_stop)) return SDW_INTEL_OPS(sdw, start_bus_after_clock_stop)(sdw); return -ENOTSUPP;} static inline int sdw_intel_stop_bus(struct sdw_intel *sdw, bool clock_stop){ if (SDW_INTEL_CHECK_OPS(sdw, stop_bus)) return SDW_INTEL_OPS(sdw, stop_bus)(sdw, clock_stop); return -ENOTSUPP;} static inline int sdw_intel_link_power_up(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, link_power_up)) return SDW_INTEL_OPS(sdw, link_power_up)(sdw); return -ENOTSUPP;} static inline int sdw_intel_link_power_down(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, link_power_down)) return SDW_INTEL_OPS(sdw, link_power_down)(sdw); return -ENOTSUPP;} static inline int sdw_intel_shim_check_wake(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, shim_check_wake)) return SDW_INTEL_OPS(sdw, shim_check_wake)(sdw); return -ENOTSUPP;} static inline void sdw_intel_shim_wake(struct sdw_intel *sdw, bool wake_enable){ if (SDW_INTEL_CHECK_OPS(sdw, shim_wake)) SDW_INTEL_OPS(sdw, shim_wake)(sdw, wake_enable);} static inline void sdw_intel_sync_arm(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, sync_arm)) SDW_INTEL_OPS(sdw, sync_arm)(sdw);} static inline int sdw_intel_sync_go_unlocked(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, sync_go_unlocked)) return SDW_INTEL_OPS(sdw, sync_go_unlocked)(sdw); return -ENOTSUPP;} static inline int sdw_intel_sync_go(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, sync_go)) return SDW_INTEL_OPS(sdw, sync_go)(sdw); return -ENOTSUPP;} static inline bool sdw_intel_sync_check_cmdsync_unlocked(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, sync_check_cmdsync_unlocked)) return SDW_INTEL_OPS(sdw, sync_check_cmdsync_unlocked)(sdw); return false;} static inline int sdw_intel_get_link_count(struct sdw_intel *sdw){ if (SDW_INTEL_CHECK_OPS(sdw, get_link_count)) return SDW_INTEL_OPS(sdw, get_link_count)(sdw); return 4; /* default on older generations */} /* common bus management */int intel_start_bus(struct sdw_intel *sdw);int intel_start_bus_after_reset(struct sdw_intel *sdw);void intel_check_clock_stop(struct sdw_intel *sdw);int intel_start_bus_after_clock_stop(struct sdw_intel *sdw);int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop); /* common bank switch routines */int intel_pre_bank_switch(struct sdw_intel *sdw);int intel_post_bank_switch(struct sdw_intel *sdw); #endif /* __SDW_INTEL_LOCAL_H */
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* Copyright(c) 2015-17 Intel Corporation. */
#ifndef __SDW_INTEL_LOCAL_H
#define __SDW_INTEL_LOCAL_H
struct hdac_bus;
/**
* struct sdw_intel_link_res - Soundwire Intel link resource structure,
* typically populated by the controller driver.
* @hw_ops: platform-specific ops
* @mmio_base: mmio base of SoundWire registers
* @registers: Link IO registers base
* @ip_offset: offset for MCP_IP registers
* @shim: Audio shim pointer
* @shim_vs: Audio vendor-specific shim pointer
* @alh: ALH (Audio Link Hub) pointer
* @irq: Interrupt line
* @ops: Shim callback ops
* @dev: device implementing hw_params and free callbacks
* @shim_lock: mutex to handle access to shared SHIM registers
* @shim_mask: global pointer to check SHIM register initialization
* @clock_stop_quirks: mask defining requested behavior on pm_suspend
* @mic_privacy: ACE version supports microphone privacy
* @link_mask: global mask needed for power-up/down sequences
* @cdns: Cadence master descriptor
* @list: used to walk-through all masters exposed by the same controller
* @hbus: hdac_bus pointer, needed for power management
*/
struct sdw_intel_link_res {
const struct sdw_intel_hw_ops *hw_ops;
void __iomem *mmio_base; /* not strictly needed, useful for debug */
void __iomem *registers;
u32 ip_offset;
void __iomem *shim;
void __iomem *shim_vs;
void __iomem *alh;
int irq;
const struct sdw_intel_ops *ops;
struct device *dev;
struct mutex *shim_lock; /* protect shared registers */
u32 *shim_mask;
u32 clock_stop_quirks;
bool mic_privacy;
u32 link_mask;
struct sdw_cdns *cdns;
struct list_head list;
struct hdac_bus *hbus;
};
/**
* struct sdw_intel_bpt - SoundWire Intel BPT context
* @bpt_tx_stream: BPT TX stream
* @dmab_tx_bdl: BPT TX buffer descriptor list
* @bpt_rx_stream: BPT RX stream
* @dmab_rx_bdl: BPT RX buffer descriptor list
* @pdi0_buffer_size: PDI0 buffer size
* @pdi1_buffer_size: PDI1 buffer size
* @num_frames: number of frames
* @data_per_frame: data per frame
*/
struct sdw_intel_bpt {
struct hdac_ext_stream *bpt_tx_stream;
struct snd_dma_buffer dmab_tx_bdl;
struct hdac_ext_stream *bpt_rx_stream;
struct snd_dma_buffer dmab_rx_bdl;
unsigned int pdi0_buffer_size;
unsigned int pdi1_buffer_size;
unsigned int num_frames;
unsigned int data_per_frame;
};
struct sdw_intel {
struct sdw_cdns cdns;
int instance;
struct sdw_intel_link_res *link_res;
bool startup_done;
struct sdw_intel_bpt bpt_ctx;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs;
#endif
};
struct sdw_intel_prop {
u16 clde;
u16 doaise2;
u16 dodse2;
u16 clds;
u16 clss;
u16 doaise;
u16 doais;
u16 dodse;
u16 dods;
};
enum intel_pdi_type {
INTEL_PDI_IN = 0,
INTEL_PDI_OUT = 1,
INTEL_PDI_BD = 2,
};
/*
* Read, write helpers for HW registers
*/
static inline int intel_readl(void __iomem *base, int offset)
{
return readl(base + offset);
}
static inline void intel_writel(void __iomem *base, int offset, int value)
{
writel(value, base + offset);
}
static inline u16 intel_readw(void __iomem *base, int offset)
{
return readw(base + offset);
}
static inline void intel_writew(void __iomem *base, int offset, u16 value)
{
writew(value, base + offset);
}
#define cdns_to_intel(_cdns) container_of(_cdns, struct sdw_intel, cdns)
#define INTEL_MASTER_RESET_ITERATIONS 10
#define SDW_INTEL_DELAYED_ENUMERATION_MS 100
#define SDW_INTEL_CHECK_OPS(sdw, cb) ((sdw) && (sdw)->link_res && (sdw)->link_res->hw_ops && \
(sdw)->link_res->hw_ops->cb)
#define SDW_INTEL_OPS(sdw, cb) ((sdw)->link_res->hw_ops->cb)
#ifdef CONFIG_DEBUG_FS
void intel_ace2x_debugfs_init(struct sdw_intel *sdw);
void intel_ace2x_debugfs_exit(struct sdw_intel *sdw);
#else
static inline void intel_ace2x_debugfs_init(struct sdw_intel *sdw) {}
static inline void intel_ace2x_debugfs_exit(struct sdw_intel *sdw) {}
#endif
static inline void sdw_intel_debugfs_init(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, debugfs_init))
SDW_INTEL_OPS(sdw, debugfs_init)(sdw);
}
static inline void sdw_intel_debugfs_exit(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, debugfs_exit))
SDW_INTEL_OPS(sdw, debugfs_exit)(sdw);
}
static inline int sdw_intel_register_dai(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, register_dai))
return SDW_INTEL_OPS(sdw, register_dai)(sdw);
return -ENOTSUPP;
}
static inline void sdw_intel_check_clock_stop(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, check_clock_stop))
SDW_INTEL_OPS(sdw, check_clock_stop)(sdw);
}
static inline int sdw_intel_start_bus(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, start_bus))
return SDW_INTEL_OPS(sdw, start_bus)(sdw);
return -ENOTSUPP;
}
static inline int sdw_intel_start_bus_after_reset(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, start_bus_after_reset))
return SDW_INTEL_OPS(sdw, start_bus_after_reset)(sdw);
return -ENOTSUPP;
}
static inline int sdw_intel_start_bus_after_clock_stop(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, start_bus_after_clock_stop))
return SDW_INTEL_OPS(sdw, start_bus_after_clock_stop)(sdw);
return -ENOTSUPP;
}
static inline int sdw_intel_stop_bus(struct sdw_intel *sdw, bool clock_stop)
{
if (SDW_INTEL_CHECK_OPS(sdw, stop_bus))
return SDW_INTEL_OPS(sdw, stop_bus)(sdw, clock_stop);
return -ENOTSUPP;
}
static inline int sdw_intel_link_power_up(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, link_power_up))
return SDW_INTEL_OPS(sdw, link_power_up)(sdw);
return -ENOTSUPP;
}
static inline int sdw_intel_link_power_down(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, link_power_down))
return SDW_INTEL_OPS(sdw, link_power_down)(sdw);
return -ENOTSUPP;
}
static inline int sdw_intel_shim_check_wake(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, shim_check_wake))
return SDW_INTEL_OPS(sdw, shim_check_wake)(sdw);
return -ENOTSUPP;
}
static inline void sdw_intel_shim_wake(struct sdw_intel *sdw, bool wake_enable)
{
if (SDW_INTEL_CHECK_OPS(sdw, shim_wake))
SDW_INTEL_OPS(sdw, shim_wake)(sdw, wake_enable);
}
static inline void sdw_intel_sync_arm(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, sync_arm))
SDW_INTEL_OPS(sdw, sync_arm)(sdw);
}
static inline int sdw_intel_sync_go_unlocked(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, sync_go_unlocked))
return SDW_INTEL_OPS(sdw, sync_go_unlocked)(sdw);
return -ENOTSUPP;
}
static inline int sdw_intel_sync_go(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, sync_go))
return SDW_INTEL_OPS(sdw, sync_go)(sdw);
return -ENOTSUPP;
}
static inline bool sdw_intel_sync_check_cmdsync_unlocked(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, sync_check_cmdsync_unlocked))
return SDW_INTEL_OPS(sdw, sync_check_cmdsync_unlocked)(sdw);
return false;
}
static inline int sdw_intel_get_link_count(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, get_link_count))
return SDW_INTEL_OPS(sdw, get_link_count)(sdw);
return 4; /* default on older generations */
}
/* common bus management */
int intel_start_bus(struct sdw_intel *sdw);
int intel_start_bus_after_reset(struct sdw_intel *sdw);
void intel_check_clock_stop(struct sdw_intel *sdw);
int intel_start_bus_after_clock_stop(struct sdw_intel *sdw);
int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop);
/* common bank switch routines */
int intel_pre_bank_switch(struct sdw_intel *sdw);
int intel_post_bank_switch(struct sdw_intel *sdw);
#endif /* __SDW_INTEL_LOCAL_H */