18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
28c2ecf20Sopenharmony_ci/* Copyright(c) 2015-17 Intel Corporation. */
38c2ecf20Sopenharmony_ci#include <sound/soc.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#ifndef __SDW_CADENCE_H
68c2ecf20Sopenharmony_ci#define __SDW_CADENCE_H
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define SDW_CADENCE_GSYNC_KHZ		4 /* 4 kHz */
98c2ecf20Sopenharmony_ci#define SDW_CADENCE_GSYNC_HZ		(SDW_CADENCE_GSYNC_KHZ * 1000)
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/*
128c2ecf20Sopenharmony_ci * The Cadence IP supports up to 32 entries in the FIFO, though implementations
138c2ecf20Sopenharmony_ci * can configure the IP to have a smaller FIFO.
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_ci#define CDNS_MCP_IP_MAX_CMD_LEN		32
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/**
188c2ecf20Sopenharmony_ci * struct sdw_cdns_pdi: PDI (Physical Data Interface) instance
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * @num: pdi number
218c2ecf20Sopenharmony_ci * @intel_alh_id: link identifier
228c2ecf20Sopenharmony_ci * @l_ch_num: low channel for PDI
238c2ecf20Sopenharmony_ci * @h_ch_num: high channel for PDI
248c2ecf20Sopenharmony_ci * @ch_count: total channel count for PDI
258c2ecf20Sopenharmony_ci * @dir: data direction
268c2ecf20Sopenharmony_ci * @type: stream type, PDM or PCM
278c2ecf20Sopenharmony_ci */
288c2ecf20Sopenharmony_cistruct sdw_cdns_pdi {
298c2ecf20Sopenharmony_ci	int num;
308c2ecf20Sopenharmony_ci	int intel_alh_id;
318c2ecf20Sopenharmony_ci	int l_ch_num;
328c2ecf20Sopenharmony_ci	int h_ch_num;
338c2ecf20Sopenharmony_ci	int ch_count;
348c2ecf20Sopenharmony_ci	enum sdw_data_direction dir;
358c2ecf20Sopenharmony_ci	enum sdw_stream_type type;
368c2ecf20Sopenharmony_ci};
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/**
398c2ecf20Sopenharmony_ci * struct sdw_cdns_streams: Cadence stream data structure
408c2ecf20Sopenharmony_ci *
418c2ecf20Sopenharmony_ci * @num_bd: number of bidirectional streams
428c2ecf20Sopenharmony_ci * @num_in: number of input streams
438c2ecf20Sopenharmony_ci * @num_out: number of output streams
448c2ecf20Sopenharmony_ci * @num_ch_bd: number of bidirectional stream channels
458c2ecf20Sopenharmony_ci * @num_ch_bd: number of input stream channels
468c2ecf20Sopenharmony_ci * @num_ch_bd: number of output stream channels
478c2ecf20Sopenharmony_ci * @num_pdi: total number of PDIs
488c2ecf20Sopenharmony_ci * @bd: bidirectional streams
498c2ecf20Sopenharmony_ci * @in: input streams
508c2ecf20Sopenharmony_ci * @out: output streams
518c2ecf20Sopenharmony_ci */
528c2ecf20Sopenharmony_cistruct sdw_cdns_streams {
538c2ecf20Sopenharmony_ci	unsigned int num_bd;
548c2ecf20Sopenharmony_ci	unsigned int num_in;
558c2ecf20Sopenharmony_ci	unsigned int num_out;
568c2ecf20Sopenharmony_ci	unsigned int num_ch_bd;
578c2ecf20Sopenharmony_ci	unsigned int num_ch_in;
588c2ecf20Sopenharmony_ci	unsigned int num_ch_out;
598c2ecf20Sopenharmony_ci	unsigned int num_pdi;
608c2ecf20Sopenharmony_ci	struct sdw_cdns_pdi *bd;
618c2ecf20Sopenharmony_ci	struct sdw_cdns_pdi *in;
628c2ecf20Sopenharmony_ci	struct sdw_cdns_pdi *out;
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/**
668c2ecf20Sopenharmony_ci * struct sdw_cdns_stream_config: stream configuration
678c2ecf20Sopenharmony_ci *
688c2ecf20Sopenharmony_ci * @pcm_bd: number of bidirectional PCM streams supported
698c2ecf20Sopenharmony_ci * @pcm_in: number of input PCM streams supported
708c2ecf20Sopenharmony_ci * @pcm_out: number of output PCM streams supported
718c2ecf20Sopenharmony_ci * @pdm_bd: number of bidirectional PDM streams supported
728c2ecf20Sopenharmony_ci * @pdm_in: number of input PDM streams supported
738c2ecf20Sopenharmony_ci * @pdm_out: number of output PDM streams supported
748c2ecf20Sopenharmony_ci */
758c2ecf20Sopenharmony_cistruct sdw_cdns_stream_config {
768c2ecf20Sopenharmony_ci	unsigned int pcm_bd;
778c2ecf20Sopenharmony_ci	unsigned int pcm_in;
788c2ecf20Sopenharmony_ci	unsigned int pcm_out;
798c2ecf20Sopenharmony_ci	unsigned int pdm_bd;
808c2ecf20Sopenharmony_ci	unsigned int pdm_in;
818c2ecf20Sopenharmony_ci	unsigned int pdm_out;
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/**
858c2ecf20Sopenharmony_ci * struct sdw_cdns_dma_data: Cadence DMA data
868c2ecf20Sopenharmony_ci *
878c2ecf20Sopenharmony_ci * @name: SoundWire stream name
888c2ecf20Sopenharmony_ci * @stream: stream runtime
898c2ecf20Sopenharmony_ci * @pdi: PDI used for this dai
908c2ecf20Sopenharmony_ci * @bus: Bus handle
918c2ecf20Sopenharmony_ci * @stream_type: Stream type
928c2ecf20Sopenharmony_ci * @link_id: Master link id
938c2ecf20Sopenharmony_ci * @hw_params: hw_params to be applied in .prepare step
948c2ecf20Sopenharmony_ci * @suspended: status set when suspended, to be used in .prepare
958c2ecf20Sopenharmony_ci */
968c2ecf20Sopenharmony_cistruct sdw_cdns_dma_data {
978c2ecf20Sopenharmony_ci	char *name;
988c2ecf20Sopenharmony_ci	struct sdw_stream_runtime *stream;
998c2ecf20Sopenharmony_ci	struct sdw_cdns_pdi *pdi;
1008c2ecf20Sopenharmony_ci	struct sdw_bus *bus;
1018c2ecf20Sopenharmony_ci	enum sdw_stream_type stream_type;
1028c2ecf20Sopenharmony_ci	int link_id;
1038c2ecf20Sopenharmony_ci	struct snd_pcm_hw_params *hw_params;
1048c2ecf20Sopenharmony_ci	bool suspended;
1058c2ecf20Sopenharmony_ci};
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci/**
1088c2ecf20Sopenharmony_ci * struct sdw_cdns - Cadence driver context
1098c2ecf20Sopenharmony_ci * @dev: Linux device
1108c2ecf20Sopenharmony_ci * @bus: Bus handle
1118c2ecf20Sopenharmony_ci * @instance: instance number
1128c2ecf20Sopenharmony_ci * @response_buf: SoundWire response buffer
1138c2ecf20Sopenharmony_ci * @tx_complete: Tx completion
1148c2ecf20Sopenharmony_ci * @defer: Defer pointer
1158c2ecf20Sopenharmony_ci * @ports: Data ports
1168c2ecf20Sopenharmony_ci * @num_ports: Total number of data ports
1178c2ecf20Sopenharmony_ci * @pcm: PCM streams
1188c2ecf20Sopenharmony_ci * @pdm: PDM streams
1198c2ecf20Sopenharmony_ci * @registers: Cadence registers
1208c2ecf20Sopenharmony_ci * @link_up: Link status
1218c2ecf20Sopenharmony_ci * @msg_count: Messages sent on bus
1228c2ecf20Sopenharmony_ci */
1238c2ecf20Sopenharmony_cistruct sdw_cdns {
1248c2ecf20Sopenharmony_ci	struct device *dev;
1258c2ecf20Sopenharmony_ci	struct sdw_bus bus;
1268c2ecf20Sopenharmony_ci	unsigned int instance;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	/*
1298c2ecf20Sopenharmony_ci	 * The datasheet says the RX FIFO AVAIL can be 2 entries more
1308c2ecf20Sopenharmony_ci	 * than the FIFO capacity, so allow for this.
1318c2ecf20Sopenharmony_ci	 */
1328c2ecf20Sopenharmony_ci	u32 response_buf[CDNS_MCP_IP_MAX_CMD_LEN + 2];
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	struct completion tx_complete;
1358c2ecf20Sopenharmony_ci	struct sdw_defer *defer;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	struct sdw_cdns_port *ports;
1388c2ecf20Sopenharmony_ci	int num_ports;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	struct sdw_cdns_streams pcm;
1418c2ecf20Sopenharmony_ci	struct sdw_cdns_streams pdm;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	void __iomem *registers;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	bool link_up;
1468c2ecf20Sopenharmony_ci	unsigned int msg_count;
1478c2ecf20Sopenharmony_ci	bool interrupt_enabled;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	struct work_struct work;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	struct list_head list;
1528c2ecf20Sopenharmony_ci};
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci#define bus_to_cdns(_bus) container_of(_bus, struct sdw_cdns, bus)
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci/* Exported symbols */
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ciint sdw_cdns_probe(struct sdw_cdns *cdns);
1598c2ecf20Sopenharmony_ciextern struct sdw_master_ops sdw_cdns_master_ops;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ciirqreturn_t sdw_cdns_irq(int irq, void *dev_id);
1628c2ecf20Sopenharmony_ciirqreturn_t sdw_cdns_thread(int irq, void *dev_id);
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ciint sdw_cdns_init(struct sdw_cdns *cdns);
1658c2ecf20Sopenharmony_ciint sdw_cdns_pdi_init(struct sdw_cdns *cdns,
1668c2ecf20Sopenharmony_ci		      struct sdw_cdns_stream_config config);
1678c2ecf20Sopenharmony_ciint sdw_cdns_exit_reset(struct sdw_cdns *cdns);
1688c2ecf20Sopenharmony_ciint sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cibool sdw_cdns_is_clock_stop(struct sdw_cdns *cdns);
1718c2ecf20Sopenharmony_ciint sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake);
1728c2ecf20Sopenharmony_ciint sdw_cdns_clock_restart(struct sdw_cdns *cdns, bool bus_reset);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
1758c2ecf20Sopenharmony_civoid sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root);
1768c2ecf20Sopenharmony_ci#endif
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistruct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns,
1798c2ecf20Sopenharmony_ci					struct sdw_cdns_streams *stream,
1808c2ecf20Sopenharmony_ci					u32 ch, u32 dir, int dai_id);
1818c2ecf20Sopenharmony_civoid sdw_cdns_config_stream(struct sdw_cdns *cdns,
1828c2ecf20Sopenharmony_ci			    u32 ch, u32 dir, struct sdw_cdns_pdi *pdi);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cienum sdw_command_response
1858c2ecf20Sopenharmony_cicdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cienum sdw_command_response
1888c2ecf20Sopenharmony_cicdns_xfer_msg(struct sdw_bus *bus, struct sdw_msg *msg);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cienum sdw_command_response
1918c2ecf20Sopenharmony_cicdns_xfer_msg_defer(struct sdw_bus *bus,
1928c2ecf20Sopenharmony_ci		    struct sdw_msg *msg, struct sdw_defer *defer);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cienum sdw_command_response
1958c2ecf20Sopenharmony_cicdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ciint cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ciint cdns_set_sdw_stream(struct snd_soc_dai *dai,
2008c2ecf20Sopenharmony_ci			void *stream, bool pcm, int direction);
2018c2ecf20Sopenharmony_ci#endif /* __SDW_CADENCE_H */
202