// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) // Copyright(c) 2015-18 Intel Corporation. /* * stream.c - SoundWire Bus stream operations. */ #include <linux/delay.h> #include <linux/device.h> #include <linux/init.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/slab.h> #include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> #include <sound/soc.h> #include "bus.h" /* * Array of supported rows and columns as per MIPI SoundWire Specification 1.1 * * The rows are arranged as per the array index value programmed * in register. The index 15 has dummy value 0 in order to fill hole. */ int sdw_rows[SDW_FRAME_ROWS] = …; EXPORT_SYMBOL(…); int sdw_cols[SDW_FRAME_COLS] = …; EXPORT_SYMBOL(…); int sdw_find_col_index(int col) { … } EXPORT_SYMBOL(…); int sdw_find_row_index(int row) { … } EXPORT_SYMBOL(…); static int _sdw_program_slave_port_params(struct sdw_bus *bus, struct sdw_slave *slave, struct sdw_transport_params *t_params, enum sdw_dpn_type type) { … } static int sdw_program_slave_port_params(struct sdw_bus *bus, struct sdw_slave_runtime *s_rt, struct sdw_port_runtime *p_rt) { … } static int sdw_program_master_port_params(struct sdw_bus *bus, struct sdw_port_runtime *p_rt) { … } /** * sdw_program_port_params() - Programs transport parameters of Master(s) * and Slave(s) * * @m_rt: Master stream runtime */ static int sdw_program_port_params(struct sdw_master_runtime *m_rt) { … } /** * sdw_enable_disable_slave_ports: Enable/disable slave data port * * @bus: bus instance * @s_rt: slave runtime * @p_rt: port runtime * @en: enable or disable operation * * This function only sets the enable/disable bits in the relevant bank, the * actual enable/disable is done with a bank switch */ static int sdw_enable_disable_slave_ports(struct sdw_bus *bus, struct sdw_slave_runtime *s_rt, struct sdw_port_runtime *p_rt, bool en) { … } static int sdw_enable_disable_master_ports(struct sdw_master_runtime *m_rt, struct sdw_port_runtime *p_rt, bool en) { … } /** * sdw_enable_disable_ports() - Enable/disable port(s) for Master and * Slave(s) * * @m_rt: Master stream runtime * @en: mode (enable/disable) */ static int sdw_enable_disable_ports(struct sdw_master_runtime *m_rt, bool en) { … } static int sdw_do_port_prep(struct sdw_slave_runtime *s_rt, struct sdw_prepare_ch prep_ch, enum sdw_port_prep_ops cmd) { … } static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, struct sdw_slave_runtime *s_rt, struct sdw_port_runtime *p_rt, bool prep) { … } static int sdw_prep_deprep_master_ports(struct sdw_master_runtime *m_rt, struct sdw_port_runtime *p_rt, bool prep) { … } /** * sdw_prep_deprep_ports() - Prepare/De-prepare port(s) for Master(s) and * Slave(s) * * @m_rt: Master runtime handle * @prep: Prepare or De-prepare */ static int sdw_prep_deprep_ports(struct sdw_master_runtime *m_rt, bool prep) { … } /** * sdw_notify_config() - Notify bus configuration * * @m_rt: Master runtime handle * * This function notifies the Master(s) and Slave(s) of the * new bus configuration. */ static int sdw_notify_config(struct sdw_master_runtime *m_rt) { … } /** * sdw_program_params() - Program transport and port parameters for Master(s) * and Slave(s) * * @bus: SDW bus instance * @prepare: true if sdw_program_params() is called by _prepare. */ static int sdw_program_params(struct sdw_bus *bus, bool prepare) { … } static int sdw_bank_switch(struct sdw_bus *bus, int m_rt_count) { … } /** * sdw_ml_sync_bank_switch: Multilink register bank switch * * @bus: SDW bus instance * @multi_link: whether this is a multi-link stream with hardware-based sync * * Caller function should free the buffers on error */ static int sdw_ml_sync_bank_switch(struct sdw_bus *bus, bool multi_link) { … } static int do_bank_switch(struct sdw_stream_runtime *stream) { … } static struct sdw_port_runtime *sdw_port_alloc(struct list_head *port_list) { … } static int sdw_port_config(struct sdw_port_runtime *p_rt, const struct sdw_port_config *port_config, int port_index) { … } static void sdw_port_free(struct sdw_port_runtime *p_rt) { … } static bool sdw_slave_port_allocated(struct sdw_slave_runtime *s_rt) { … } static void sdw_slave_port_free(struct sdw_slave *slave, struct sdw_stream_runtime *stream) { … } static int sdw_slave_port_alloc(struct sdw_slave *slave, struct sdw_slave_runtime *s_rt, unsigned int num_config) { … } static int sdw_slave_port_is_valid_range(struct device *dev, int num) { … } static int sdw_slave_port_config(struct sdw_slave *slave, struct sdw_slave_runtime *s_rt, const struct sdw_port_config *port_config) { … } static bool sdw_master_port_allocated(struct sdw_master_runtime *m_rt) { … } static void sdw_master_port_free(struct sdw_master_runtime *m_rt) { … } static int sdw_master_port_alloc(struct sdw_master_runtime *m_rt, unsigned int num_ports) { … } static int sdw_master_port_config(struct sdw_master_runtime *m_rt, const struct sdw_port_config *port_config) { … } /** * sdw_slave_rt_alloc() - Allocate a Slave runtime handle. * * @slave: Slave handle * @m_rt: Master runtime handle * * This function is to be called with bus_lock held. */ static struct sdw_slave_runtime *sdw_slave_rt_alloc(struct sdw_slave *slave, struct sdw_master_runtime *m_rt) { … } /** * sdw_slave_rt_config() - Configure a Slave runtime handle. * * @s_rt: Slave runtime handle * @stream_config: Stream configuration * * This function is to be called with bus_lock held. */ static int sdw_slave_rt_config(struct sdw_slave_runtime *s_rt, struct sdw_stream_config *stream_config) { … } static struct sdw_slave_runtime *sdw_slave_rt_find(struct sdw_slave *slave, struct sdw_stream_runtime *stream) { … } /** * sdw_slave_rt_free() - Free Slave(s) runtime handle * * @slave: Slave handle. * @stream: Stream runtime handle. * * This function is to be called with bus_lock held. */ static void sdw_slave_rt_free(struct sdw_slave *slave, struct sdw_stream_runtime *stream) { … } static struct sdw_master_runtime *sdw_master_rt_find(struct sdw_bus *bus, struct sdw_stream_runtime *stream) { … } /** * sdw_master_rt_alloc() - Allocates a Master runtime handle * * @bus: SDW bus instance * @stream: Stream runtime handle. * * This function is to be called with bus_lock held. */ static struct sdw_master_runtime *sdw_master_rt_alloc(struct sdw_bus *bus, struct sdw_stream_runtime *stream) { … } /** * sdw_master_rt_config() - Configure Master runtime handle * * @m_rt: Master runtime handle * @stream_config: Stream configuration * * This function is to be called with bus_lock held. */ static int sdw_master_rt_config(struct sdw_master_runtime *m_rt, struct sdw_stream_config *stream_config) { … } /** * sdw_master_rt_free() - Free Master runtime handle * * @m_rt: Master runtime node * @stream: Stream runtime handle. * * This function is to be called with bus_lock held * It frees the Master runtime handle and associated Slave(s) runtime * handle. If this is called first then sdw_slave_rt_free() will have * no effect as Slave(s) runtime handle would already be freed up. */ static void sdw_master_rt_free(struct sdw_master_runtime *m_rt, struct sdw_stream_runtime *stream) { … } /** * sdw_config_stream() - Configure the allocated stream * * @dev: SDW device * @stream: SoundWire stream * @stream_config: Stream configuration for audio stream * @is_slave: is API called from Slave or Master * * This function is to be called with bus_lock held. */ static int sdw_config_stream(struct device *dev, struct sdw_stream_runtime *stream, struct sdw_stream_config *stream_config, bool is_slave) { … } /** * sdw_get_slave_dpn_prop() - Get Slave port capabilities * * @slave: Slave handle * @direction: Data direction. * @port_num: Port number */ struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave, enum sdw_data_direction direction, unsigned int port_num) { … } /** * sdw_acquire_bus_lock: Acquire bus lock for all Master runtime(s) * * @stream: SoundWire stream * * Acquire bus_lock for each of the master runtime(m_rt) part of this * stream to reconfigure the bus. * NOTE: This function is called from SoundWire stream ops and is * expected that a global lock is held before acquiring bus_lock. */ static void sdw_acquire_bus_lock(struct sdw_stream_runtime *stream) { … } /** * sdw_release_bus_lock: Release bus lock for all Master runtime(s) * * @stream: SoundWire stream * * Release the previously held bus_lock after reconfiguring the bus. * NOTE: This function is called from SoundWire stream ops and is * expected that a global lock is held before releasing bus_lock. */ static void sdw_release_bus_lock(struct sdw_stream_runtime *stream) { … } static int _sdw_prepare_stream(struct sdw_stream_runtime *stream, bool update_params) { … } /** * sdw_prepare_stream() - Prepare SoundWire stream * * @stream: Soundwire stream * * Documentation/driver-api/soundwire/stream.rst explains this API in detail */ int sdw_prepare_stream(struct sdw_stream_runtime *stream) { … } EXPORT_SYMBOL(…); static int _sdw_enable_stream(struct sdw_stream_runtime *stream) { … } /** * sdw_enable_stream() - Enable SoundWire stream * * @stream: Soundwire stream * * Documentation/driver-api/soundwire/stream.rst explains this API in detail */ int sdw_enable_stream(struct sdw_stream_runtime *stream) { … } EXPORT_SYMBOL(…); static int _sdw_disable_stream(struct sdw_stream_runtime *stream) { … } /** * sdw_disable_stream() - Disable SoundWire stream * * @stream: Soundwire stream * * Documentation/driver-api/soundwire/stream.rst explains this API in detail */ int sdw_disable_stream(struct sdw_stream_runtime *stream) { … } EXPORT_SYMBOL(…); static int _sdw_deprepare_stream(struct sdw_stream_runtime *stream) { … } /** * sdw_deprepare_stream() - Deprepare SoundWire stream * * @stream: Soundwire stream * * Documentation/driver-api/soundwire/stream.rst explains this API in detail */ int sdw_deprepare_stream(struct sdw_stream_runtime *stream) { … } EXPORT_SYMBOL(…); static int set_stream(struct snd_pcm_substream *substream, struct sdw_stream_runtime *sdw_stream) { … } /** * sdw_alloc_stream() - Allocate and return stream runtime * * @stream_name: SoundWire stream name * * Allocates a SoundWire stream runtime instance. * sdw_alloc_stream should be called only once per stream. Typically * invoked from ALSA/ASoC machine/platform driver. */ struct sdw_stream_runtime *sdw_alloc_stream(const char *stream_name) { … } EXPORT_SYMBOL(…); /** * sdw_startup_stream() - Startup SoundWire stream * * @sdw_substream: Soundwire stream * * Documentation/driver-api/soundwire/stream.rst explains this API in detail */ int sdw_startup_stream(void *sdw_substream) { … } EXPORT_SYMBOL(…); /** * sdw_shutdown_stream() - Shutdown SoundWire stream * * @sdw_substream: Soundwire stream * * Documentation/driver-api/soundwire/stream.rst explains this API in detail */ void sdw_shutdown_stream(void *sdw_substream) { … } EXPORT_SYMBOL(…); /** * sdw_release_stream() - Free the assigned stream runtime * * @stream: SoundWire stream runtime * * sdw_release_stream should be called only once per stream */ void sdw_release_stream(struct sdw_stream_runtime *stream) { … } EXPORT_SYMBOL(…); /** * sdw_stream_add_master() - Allocate and add master runtime to a stream * * @bus: SDW Bus instance * @stream_config: Stream configuration for audio stream * @port_config: Port configuration for audio stream * @num_ports: Number of ports * @stream: SoundWire stream */ int sdw_stream_add_master(struct sdw_bus *bus, struct sdw_stream_config *stream_config, const struct sdw_port_config *port_config, unsigned int num_ports, struct sdw_stream_runtime *stream) { … } EXPORT_SYMBOL(…); /** * sdw_stream_remove_master() - Remove master from sdw_stream * * @bus: SDW Bus instance * @stream: SoundWire stream * * This removes and frees port_rt and master_rt from a stream */ int sdw_stream_remove_master(struct sdw_bus *bus, struct sdw_stream_runtime *stream) { … } EXPORT_SYMBOL(…); /** * sdw_stream_add_slave() - Allocate and add master/slave runtime to a stream * * @slave: SDW Slave instance * @stream_config: Stream configuration for audio stream * @stream: SoundWire stream * @port_config: Port configuration for audio stream * @num_ports: Number of ports * * It is expected that Slave is added before adding Master * to the Stream. * */ int sdw_stream_add_slave(struct sdw_slave *slave, struct sdw_stream_config *stream_config, const struct sdw_port_config *port_config, unsigned int num_ports, struct sdw_stream_runtime *stream) { … } EXPORT_SYMBOL(…); /** * sdw_stream_remove_slave() - Remove slave from sdw_stream * * @slave: SDW Slave instance * @stream: SoundWire stream * * This removes and frees port_rt and slave_rt from a stream */ int sdw_stream_remove_slave(struct sdw_slave *slave, struct sdw_stream_runtime *stream) { … } EXPORT_SYMBOL(…);