diff options
Diffstat (limited to 'drivers/soundwire/cadence_master.h')
| -rw-r--r-- | drivers/soundwire/cadence_master.h | 162 |
1 files changed, 97 insertions, 65 deletions
diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h index eb902b19c5a4..9373426c7f63 100644 --- a/drivers/soundwire/cadence_master.h +++ b/drivers/soundwire/cadence_master.h @@ -1,24 +1,33 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) -// Copyright(c) 2015-17 Intel Corporation. +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* Copyright(c) 2015-17 Intel Corporation. */ #include <sound/soc.h> #ifndef __SDW_CADENCE_H #define __SDW_CADENCE_H +#define SDW_CADENCE_GSYNC_KHZ 4 /* 4 kHz */ +#define SDW_CADENCE_GSYNC_HZ (SDW_CADENCE_GSYNC_KHZ * 1000) + +/* + * The Cadence IP supports up to 32 entries in the FIFO, though implementations + * can configure the IP to have a smaller FIFO. + */ +#define CDNS_MCP_IP_MAX_CMD_LEN 32 + +#define SDW_CADENCE_MCP_IP_OFFSET 0x4000 + /** * struct sdw_cdns_pdi: PDI (Physical Data Interface) instance * - * @assigned: pdi assigned * @num: pdi number * @intel_alh_id: link identifier * @l_ch_num: low channel for PDI * @h_ch_num: high channel for PDI * @ch_count: total channel count for PDI * @dir: data direction - * @type: stream type, PDM or PCM + * @type: stream type, (only PCM supported) */ struct sdw_cdns_pdi { - bool assigned; int num; int intel_alh_id; int l_ch_num; @@ -29,23 +38,6 @@ struct sdw_cdns_pdi { }; /** - * struct sdw_cdns_port: Cadence port structure - * - * @num: port number - * @assigned: port assigned - * @ch: channel count - * @direction: data port direction - * @pdi: pdi for this port - */ -struct sdw_cdns_port { - unsigned int num; - bool assigned; - unsigned int ch; - enum sdw_data_direction direction; - struct sdw_cdns_pdi *pdi; -}; - -/** * struct sdw_cdns_streams: Cadence stream data structure * * @num_bd: number of bidirectional streams @@ -78,37 +70,36 @@ struct sdw_cdns_streams { * @pcm_bd: number of bidirectional PCM streams supported * @pcm_in: number of input PCM streams supported * @pcm_out: number of output PCM streams supported - * @pdm_bd: number of bidirectional PDM streams supported - * @pdm_in: number of input PDM streams supported - * @pdm_out: number of output PDM streams supported */ struct sdw_cdns_stream_config { unsigned int pcm_bd; unsigned int pcm_in; unsigned int pcm_out; - unsigned int pdm_bd; - unsigned int pdm_in; - unsigned int pdm_out; }; /** - * struct sdw_cdns_dma_data: Cadence DMA data + * struct sdw_cdns_dai_runtime: Cadence DAI runtime data * * @name: SoundWire stream name - * @nr_ports: Number of ports - * @port: Ports + * @stream: stream runtime + * @pdi: PDI used for this dai * @bus: Bus handle * @stream_type: Stream type * @link_id: Master link id + * @suspended: status set when suspended, to be used in .prepare + * @paused: status set in .trigger, to be used in suspend + * @direction: stream direction */ -struct sdw_cdns_dma_data { +struct sdw_cdns_dai_runtime { char *name; struct sdw_stream_runtime *stream; - int nr_ports; - struct sdw_cdns_port **port; + struct sdw_cdns_pdi *pdi; struct sdw_bus *bus; enum sdw_stream_type stream_type; int link_id; + bool suspended; + bool paused; + int direction; }; /** @@ -116,36 +107,56 @@ struct sdw_cdns_dma_data { * @dev: Linux device * @bus: Bus handle * @instance: instance number + * @ip_offset: version-dependent offset to access IP_MCP registers and fields * @response_buf: SoundWire response buffer * @tx_complete: Tx completion - * @defer: Defer pointer * @ports: Data ports * @num_ports: Total number of data ports * @pcm: PCM streams - * @pdm: PDM streams * @registers: Cadence registers * @link_up: Link status * @msg_count: Messages sent on bus + * @dai_runtime_array: runtime context for each allocated DAI. + * @status_update_lock: protect concurrency between interrupt-based and delayed work + * status update */ struct sdw_cdns { struct device *dev; struct sdw_bus bus; unsigned int instance; - u32 response_buf[0x80]; + u32 ip_offset; + + /* + * The datasheet says the RX FIFO AVAIL can be 2 entries more + * than the FIFO capacity, so allow for this. + */ + u32 response_buf[CDNS_MCP_IP_MAX_CMD_LEN + 2]; + struct completion tx_complete; - struct sdw_defer *defer; struct sdw_cdns_port *ports; int num_ports; struct sdw_cdns_streams pcm; - struct sdw_cdns_streams pdm; + + int pdi_loopback_source; + int pdi_loopback_target; void __iomem *registers; bool link_up; unsigned int msg_count; + bool interrupt_enabled; + + struct work_struct work; + struct delayed_work attach_dwork; + + struct list_head list; + + struct sdw_cdns_dai_runtime **dai_runtime_array; + + struct mutex status_update_lock; /* add mutual exclusion to sdw_handle_slave_status() */ }; #define bus_to_cdns(_bus) container_of(_bus, struct sdw_cdns, bus) @@ -153,47 +164,68 @@ struct sdw_cdns { /* Exported symbols */ int sdw_cdns_probe(struct sdw_cdns *cdns); -extern struct sdw_master_ops sdw_cdns_master_ops; irqreturn_t sdw_cdns_irq(int irq, void *dev_id); irqreturn_t sdw_cdns_thread(int irq, void *dev_id); +int sdw_cdns_soft_reset(struct sdw_cdns *cdns); int sdw_cdns_init(struct sdw_cdns *cdns); int sdw_cdns_pdi_init(struct sdw_cdns *cdns, - struct sdw_cdns_stream_config config); -int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns); - -int sdw_cdns_get_stream(struct sdw_cdns *cdns, - struct sdw_cdns_streams *stream, - u32 ch, u32 dir); -int sdw_cdns_alloc_stream(struct sdw_cdns *cdns, - struct sdw_cdns_streams *stream, - struct sdw_cdns_port *port, u32 ch, u32 dir); -void sdw_cdns_config_stream(struct sdw_cdns *cdns, struct sdw_cdns_port *port, - u32 ch, u32 dir, struct sdw_cdns_pdi *pdi); - -void sdw_cdns_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai); -int sdw_cdns_pcm_set_stream(struct snd_soc_dai *dai, - void *stream, int direction); -int sdw_cdns_pdm_set_stream(struct snd_soc_dai *dai, - void *stream, int direction); + struct sdw_cdns_stream_config config); +int sdw_cdns_exit_reset(struct sdw_cdns *cdns); +int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state); -enum sdw_command_response -cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num); +bool sdw_cdns_is_clock_stop(struct sdw_cdns *cdns); +int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake); +int sdw_cdns_clock_restart(struct sdw_cdns *cdns, bool bus_reset); + +#ifdef CONFIG_DEBUG_FS +void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root); +#endif + +struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns, + struct sdw_cdns_streams *stream, + u32 ch, u32 dir, int dai_id); +void sdw_cdns_config_stream(struct sdw_cdns *cdns, + u32 ch, u32 dir, struct sdw_cdns_pdi *pdi); enum sdw_command_response cdns_xfer_msg(struct sdw_bus *bus, struct sdw_msg *msg); enum sdw_command_response -cdns_xfer_msg_defer(struct sdw_bus *bus, - struct sdw_msg *msg, struct sdw_defer *defer); +cdns_xfer_msg_defer(struct sdw_bus *bus); -enum sdw_command_response -cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num); +u32 cdns_read_ping_status(struct sdw_bus *bus); int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params); int cdns_set_sdw_stream(struct snd_soc_dai *dai, - void *stream, bool pcm, int direction); + void *stream, int direction); + +void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string, + bool initial_delay, int reset_iterations); + +void sdw_cdns_config_update(struct sdw_cdns *cdns); +int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns); + +/* SoundWire BPT/BRA helpers to format data */ +int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */ + int row, int col, unsigned int data_bytes, + unsigned int requested_bytes_per_frame, + unsigned int *data_per_frame, unsigned int *pdi0_buffer_size, + unsigned int *pdi1_buffer_size, unsigned int *num_frames); + +int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data, int data_size, + int data_per_frame, u8 *dma_buffer, int dma_buffer_size, + int *dma_buffer_total_bytes); + +int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_size, + int data_per_frame, u8 *dma_buffer, int dma_buffer_size, + int *dma_buffer_total_bytes); + +int sdw_cdns_check_write_response(struct device *dev, u8 *dma_buffer, + int dma_buffer_size, int num_frames); + +int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buffer_size, + u8 *buffer, int buffer_size, int num_frames, int data_per_frame); #endif /* __SDW_CADENCE_H */ |
