OSDN Git Service

soundwire: stream: group sdw_stream_ functions
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Wed, 26 Jan 2022 01:17:09 +0000 (09:17 +0800)
committerVinod Koul <vkoul@kernel.org>
Fri, 11 Feb 2022 06:47:44 +0000 (12:17 +0530)
Group all exported functions prior to split of add in alloc/config
stages necessary for support of multiple calls to hw_params() by
ALSA/ASoC core.

Pure code move, no functionality change.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Rander Wang <rander.wang@intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://lore.kernel.org/r/20220126011715.28204-14-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/soundwire/stream.c

index b7ccfa5..f939121 100644 (file)
@@ -1016,45 +1016,6 @@ static int sdw_master_port_config(struct sdw_master_runtime *m_rt,
 }
 
 /**
- * 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)
-{
-       kfree(stream);
-}
-EXPORT_SYMBOL(sdw_release_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)
-{
-       struct sdw_stream_runtime *stream;
-
-       stream = kzalloc(sizeof(*stream), GFP_KERNEL);
-       if (!stream)
-               return NULL;
-
-       stream->name = stream_name;
-       INIT_LIST_HEAD(&stream->master_list);
-       stream->state = SDW_STREAM_ALLOCATED;
-       stream->m_rt_count = 0;
-
-       return stream;
-}
-EXPORT_SYMBOL(sdw_alloc_stream);
-
-/**
  * sdw_slave_rt_alloc() - Allocate a Slave runtime handle.
  *
  * @slave: Slave handle
@@ -1211,62 +1172,6 @@ static void sdw_release_master_stream(struct sdw_master_runtime *m_rt,
 }
 
 /**
- * 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)
-{
-       struct sdw_master_runtime *m_rt, *_m_rt;
-
-       mutex_lock(&bus->bus_lock);
-
-       list_for_each_entry_safe(m_rt, _m_rt,
-                                &stream->master_list, stream_node) {
-               if (m_rt->bus != bus)
-                       continue;
-
-               sdw_master_port_free(m_rt);
-               sdw_release_master_stream(m_rt, stream);
-               stream->m_rt_count--;
-       }
-
-       if (list_empty(&stream->master_list))
-               stream->state = SDW_STREAM_RELEASED;
-
-       mutex_unlock(&bus->bus_lock);
-
-       return 0;
-}
-EXPORT_SYMBOL(sdw_stream_remove_master);
-
-/**
- * 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)
-{
-       mutex_lock(&slave->bus->bus_lock);
-
-       sdw_slave_port_free(slave, stream);
-       sdw_release_slave_stream(slave, stream);
-
-       mutex_unlock(&slave->bus->bus_lock);
-
-       return 0;
-}
-EXPORT_SYMBOL(sdw_stream_remove_slave);
-
-/**
  * sdw_config_stream() - Configure the allocated stream
  *
  * @dev: SDW device
@@ -1313,269 +1218,100 @@ static int sdw_config_stream(struct device *dev,
 }
 
 /**
- * sdw_stream_add_master() - Allocate and add master runtime to a stream
+ * sdw_get_slave_dpn_prop() - Get Slave port capabilities
  *
- * @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
+ * @slave: Slave handle
+ * @direction: Data direction.
+ * @port_num: Port number
  */
-int sdw_stream_add_master(struct sdw_bus *bus,
-                         struct sdw_stream_config *stream_config,
-                         struct sdw_port_config *port_config,
-                         unsigned int num_ports,
-                         struct sdw_stream_runtime *stream)
+struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave,
+                                           enum sdw_data_direction direction,
+                                           unsigned int port_num)
 {
-       struct sdw_master_runtime *m_rt;
-       int ret;
-
-       mutex_lock(&bus->bus_lock);
+       struct sdw_dpn_prop *dpn_prop;
+       u8 num_ports;
+       int i;
 
-       /*
-        * For multi link streams, add the second master only if
-        * the bus supports it.
-        * Check if bus->multi_link is set
-        */
-       if (!bus->multi_link && stream->m_rt_count > 0) {
-               dev_err(bus->dev,
-                       "Multilink not supported, link %d\n", bus->link_id);
-               ret = -EINVAL;
-               goto unlock;
+       if (direction == SDW_DATA_DIR_TX) {
+               num_ports = hweight32(slave->prop.source_ports);
+               dpn_prop = slave->prop.src_dpn_prop;
+       } else {
+               num_ports = hweight32(slave->prop.sink_ports);
+               dpn_prop = slave->prop.sink_dpn_prop;
        }
 
-       /*
-        * check if Master is already allocated (e.g. as a result of Slave adding
-        * it first), if so skip allocation and go to configuration
-        */
-       m_rt = sdw_master_rt_find(bus, stream);
-       if (m_rt)
-               goto skip_alloc_master_rt;
-
-       m_rt = sdw_master_rt_alloc(bus, stream);
-       if (!m_rt) {
-               dev_err(bus->dev, "Master runtime alloc failed for stream:%s\n", stream->name);
-               ret = -ENOMEM;
-               goto unlock;
+       for (i = 0; i < num_ports; i++) {
+               if (dpn_prop[i].num == port_num)
+                       return &dpn_prop[i];
        }
 
-       ret = sdw_master_rt_config(m_rt, stream_config);
-       if (ret < 0)
-               goto unlock;
-
-skip_alloc_master_rt:
-       ret = sdw_config_stream(bus->dev, stream, stream_config, false);
-       if (ret)
-               goto stream_error;
-
-       ret = sdw_master_port_alloc(m_rt, num_ports);
-       if (ret)
-               goto stream_error;
-
-       ret = sdw_master_port_config(m_rt, port_config);
-       if (ret)
-               goto stream_error;
+       return NULL;
+}
 
-       stream->m_rt_count++;
+/**
+ * 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)
+{
+       struct sdw_master_runtime *m_rt;
+       struct sdw_bus *bus;
 
-       goto unlock;
+       /* Iterate for all Master(s) in Master list */
+       list_for_each_entry(m_rt, &stream->master_list, stream_node) {
+               bus = m_rt->bus;
 
-stream_error:
-       sdw_release_master_stream(m_rt, stream);
-unlock:
-       mutex_unlock(&bus->bus_lock);
-       return ret;
+               mutex_lock(&bus->bus_lock);
+       }
 }
-EXPORT_SYMBOL(sdw_stream_add_master);
 
 /**
- * sdw_stream_add_slave() - Allocate and add master/slave runtime to a stream
+ * sdw_release_bus_lock: Release bus lock for all Master runtime(s)
  *
- * @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.
  *
+ * 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.
  */
-int sdw_stream_add_slave(struct sdw_slave *slave,
-                        struct sdw_stream_config *stream_config,
-                        struct sdw_port_config *port_config,
-                        unsigned int num_ports,
-                        struct sdw_stream_runtime *stream)
+static void sdw_release_bus_lock(struct sdw_stream_runtime *stream)
+{
+       struct sdw_master_runtime *m_rt;
+       struct sdw_bus *bus;
+
+       /* Iterate for all Master(s) in Master list */
+       list_for_each_entry_reverse(m_rt, &stream->master_list, stream_node) {
+               bus = m_rt->bus;
+               mutex_unlock(&bus->bus_lock);
+       }
+}
+
+static int _sdw_prepare_stream(struct sdw_stream_runtime *stream,
+                              bool update_params)
 {
-       struct sdw_slave_runtime *s_rt;
        struct sdw_master_runtime *m_rt;
+       struct sdw_bus *bus = NULL;
+       struct sdw_master_prop *prop;
+       struct sdw_bus_params params;
        int ret;
 
-       mutex_lock(&slave->bus->bus_lock);
+       /* Prepare  Master(s) and Slave(s) port(s) associated with stream */
+       list_for_each_entry(m_rt, &stream->master_list, stream_node) {
+               bus = m_rt->bus;
+               prop = &bus->prop;
+               memcpy(&params, &bus->params, sizeof(params));
 
-       /*
-        * check if Master is already allocated, if so skip allocation
-        * and go to configuration
-        */
-       m_rt = sdw_master_rt_find(slave->bus, stream);
-       if (m_rt)
-               goto skip_alloc_master_rt;
-
-       /*
-        * If this API is invoked by Slave first then m_rt is not valid.
-        * So, allocate m_rt and add Slave to it.
-        */
-       m_rt = sdw_master_rt_alloc(slave->bus, stream);
-       if (!m_rt) {
-               dev_err(&slave->dev, "Master runtime alloc failed for stream:%s\n", stream->name);
-               ret = -ENOMEM;
-               goto error;
-       }
-       ret =  sdw_master_rt_config(m_rt, stream_config);
-       if (ret < 0)
-               goto stream_error;
-
-skip_alloc_master_rt:
-       s_rt = sdw_slave_rt_alloc(slave);
-       if (!s_rt) {
-               dev_err(&slave->dev, "Slave runtime alloc failed for stream:%s\n", stream->name);
-               ret = -ENOMEM;
-               goto stream_error;
-       }
-       list_add_tail(&s_rt->m_rt_node, &m_rt->slave_rt_list);
-
-       ret = sdw_slave_rt_config(s_rt, stream_config);
-       if (ret)
-               goto stream_error;
-
-       ret = sdw_config_stream(&slave->dev, stream, stream_config, true);
-       if (ret)
-               goto stream_error;
-
-       ret = sdw_slave_port_alloc(slave, s_rt, num_ports);
-       if (ret)
-               goto stream_error;
-
-       ret = sdw_slave_port_config(slave, s_rt, port_config);
-       if (ret)
-               goto stream_error;
-
-       /*
-        * Change stream state to CONFIGURED on first Slave add.
-        * Bus is not aware of number of Slave(s) in a stream at this
-        * point so cannot depend on all Slave(s) to be added in order to
-        * change stream state to CONFIGURED.
-        */
-       stream->state = SDW_STREAM_CONFIGURED;
-       goto error;
-
-stream_error:
-       /*
-        * we hit error so cleanup the stream, release all Slave(s) and
-        * Master runtime
-        */
-       sdw_release_master_stream(m_rt, stream);
-error:
-       mutex_unlock(&slave->bus->bus_lock);
-       return ret;
-}
-EXPORT_SYMBOL(sdw_stream_add_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)
-{
-       struct sdw_dpn_prop *dpn_prop;
-       u8 num_ports;
-       int i;
-
-       if (direction == SDW_DATA_DIR_TX) {
-               num_ports = hweight32(slave->prop.source_ports);
-               dpn_prop = slave->prop.src_dpn_prop;
-       } else {
-               num_ports = hweight32(slave->prop.sink_ports);
-               dpn_prop = slave->prop.sink_dpn_prop;
-       }
-
-       for (i = 0; i < num_ports; i++) {
-               if (dpn_prop[i].num == port_num)
-                       return &dpn_prop[i];
-       }
-
-       return NULL;
-}
-
-/**
- * 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)
-{
-       struct sdw_master_runtime *m_rt;
-       struct sdw_bus *bus;
-
-       /* Iterate for all Master(s) in Master list */
-       list_for_each_entry(m_rt, &stream->master_list, stream_node) {
-               bus = m_rt->bus;
-
-               mutex_lock(&bus->bus_lock);
-       }
-}
-
-/**
- * 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)
-{
-       struct sdw_master_runtime *m_rt;
-       struct sdw_bus *bus;
-
-       /* Iterate for all Master(s) in Master list */
-       list_for_each_entry_reverse(m_rt, &stream->master_list, stream_node) {
-               bus = m_rt->bus;
-               mutex_unlock(&bus->bus_lock);
-       }
-}
-
-static int _sdw_prepare_stream(struct sdw_stream_runtime *stream,
-                              bool update_params)
-{
-       struct sdw_master_runtime *m_rt;
-       struct sdw_bus *bus = NULL;
-       struct sdw_master_prop *prop;
-       struct sdw_bus_params params;
-       int ret;
-
-       /* Prepare  Master(s) and Slave(s) port(s) associated with stream */
-       list_for_each_entry(m_rt, &stream->master_list, stream_node) {
-               bus = m_rt->bus;
-               prop = &bus->prop;
-               memcpy(&params, &bus->params, sizeof(params));
-
-               /* TODO: Support Asynchronous mode */
-               if ((prop->max_clk_freq % stream->params.rate) != 0) {
-                       dev_err(bus->dev, "Async mode not supported\n");
-                       return -EINVAL;
-               }
+               /* TODO: Support Asynchronous mode */
+               if ((prop->max_clk_freq % stream->params.rate) != 0) {
+                       dev_err(bus->dev, "Async mode not supported\n");
+                       return -EINVAL;
+               }
 
                if (!update_params)
                        goto program_params;
@@ -1940,6 +1676,32 @@ static int set_stream(struct snd_pcm_substream *substream,
 }
 
 /**
+ * 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)
+{
+       struct sdw_stream_runtime *stream;
+
+       stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+       if (!stream)
+               return NULL;
+
+       stream->name = stream_name;
+       INIT_LIST_HEAD(&stream->master_list);
+       stream->state = SDW_STREAM_ALLOCATED;
+       stream->m_rt_count = 0;
+
+       return stream;
+}
+EXPORT_SYMBOL(sdw_alloc_stream);
+
+/**
  * sdw_startup_stream() - Startup SoundWire stream
  *
  * @sdw_substream: Soundwire stream
@@ -2015,3 +1777,241 @@ void sdw_shutdown_stream(void *sdw_substream)
        set_stream(substream, NULL);
 }
 EXPORT_SYMBOL(sdw_shutdown_stream);
+
+/**
+ * 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)
+{
+       kfree(stream);
+}
+EXPORT_SYMBOL(sdw_release_stream);
+
+/**
+ * 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,
+                         struct sdw_port_config *port_config,
+                         unsigned int num_ports,
+                         struct sdw_stream_runtime *stream)
+{
+       struct sdw_master_runtime *m_rt;
+       int ret;
+
+       mutex_lock(&bus->bus_lock);
+
+       /*
+        * For multi link streams, add the second master only if
+        * the bus supports it.
+        * Check if bus->multi_link is set
+        */
+       if (!bus->multi_link && stream->m_rt_count > 0) {
+               dev_err(bus->dev,
+                       "Multilink not supported, link %d\n", bus->link_id);
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       /*
+        * check if Master is already allocated (e.g. as a result of Slave adding
+        * it first), if so skip allocation and go to configuration
+        */
+       m_rt = sdw_master_rt_find(bus, stream);
+       if (m_rt)
+               goto skip_alloc_master_rt;
+
+       m_rt = sdw_master_rt_alloc(bus, stream);
+       if (!m_rt) {
+               dev_err(bus->dev, "Master runtime alloc failed for stream:%s\n", stream->name);
+               ret = -ENOMEM;
+               goto unlock;
+       }
+
+       ret = sdw_master_rt_config(m_rt, stream_config);
+       if (ret < 0)
+               goto unlock;
+
+skip_alloc_master_rt:
+       ret = sdw_config_stream(bus->dev, stream, stream_config, false);
+       if (ret)
+               goto stream_error;
+
+       ret = sdw_master_port_alloc(m_rt, num_ports);
+       if (ret)
+               goto stream_error;
+
+       ret = sdw_master_port_config(m_rt, port_config);
+       if (ret)
+               goto stream_error;
+
+       stream->m_rt_count++;
+
+       goto unlock;
+
+stream_error:
+       sdw_release_master_stream(m_rt, stream);
+unlock:
+       mutex_unlock(&bus->bus_lock);
+       return ret;
+}
+EXPORT_SYMBOL(sdw_stream_add_master);
+
+/**
+ * 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)
+{
+       struct sdw_master_runtime *m_rt, *_m_rt;
+
+       mutex_lock(&bus->bus_lock);
+
+       list_for_each_entry_safe(m_rt, _m_rt,
+                                &stream->master_list, stream_node) {
+               if (m_rt->bus != bus)
+                       continue;
+
+               sdw_master_port_free(m_rt);
+               sdw_release_master_stream(m_rt, stream);
+               stream->m_rt_count--;
+       }
+
+       if (list_empty(&stream->master_list))
+               stream->state = SDW_STREAM_RELEASED;
+
+       mutex_unlock(&bus->bus_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(sdw_stream_remove_master);
+
+/**
+ * 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,
+                        struct sdw_port_config *port_config,
+                        unsigned int num_ports,
+                        struct sdw_stream_runtime *stream)
+{
+       struct sdw_slave_runtime *s_rt;
+       struct sdw_master_runtime *m_rt;
+       int ret;
+
+       mutex_lock(&slave->bus->bus_lock);
+
+       /*
+        * check if Master is already allocated, if so skip allocation
+        * and go to configuration
+        */
+       m_rt = sdw_master_rt_find(slave->bus, stream);
+       if (m_rt)
+               goto skip_alloc_master_rt;
+
+       /*
+        * If this API is invoked by Slave first then m_rt is not valid.
+        * So, allocate m_rt and add Slave to it.
+        */
+       m_rt = sdw_master_rt_alloc(slave->bus, stream);
+       if (!m_rt) {
+               dev_err(&slave->dev, "Master runtime alloc failed for stream:%s\n", stream->name);
+               ret = -ENOMEM;
+               goto error;
+       }
+       ret =  sdw_master_rt_config(m_rt, stream_config);
+       if (ret < 0)
+               goto stream_error;
+
+skip_alloc_master_rt:
+       s_rt = sdw_slave_rt_alloc(slave);
+       if (!s_rt) {
+               dev_err(&slave->dev, "Slave runtime alloc failed for stream:%s\n", stream->name);
+               ret = -ENOMEM;
+               goto stream_error;
+       }
+       list_add_tail(&s_rt->m_rt_node, &m_rt->slave_rt_list);
+
+       ret = sdw_slave_rt_config(s_rt, stream_config);
+       if (ret)
+               goto stream_error;
+
+       ret = sdw_config_stream(&slave->dev, stream, stream_config, true);
+       if (ret)
+               goto stream_error;
+
+       ret = sdw_slave_port_alloc(slave, s_rt, num_ports);
+       if (ret)
+               goto stream_error;
+
+       ret = sdw_slave_port_config(slave, s_rt, port_config);
+       if (ret)
+               goto stream_error;
+
+       /*
+        * Change stream state to CONFIGURED on first Slave add.
+        * Bus is not aware of number of Slave(s) in a stream at this
+        * point so cannot depend on all Slave(s) to be added in order to
+        * change stream state to CONFIGURED.
+        */
+       stream->state = SDW_STREAM_CONFIGURED;
+       goto error;
+
+stream_error:
+       /*
+        * we hit error so cleanup the stream, release all Slave(s) and
+        * Master runtime
+        */
+       sdw_release_master_stream(m_rt, stream);
+error:
+       mutex_unlock(&slave->bus->bus_lock);
+       return ret;
+}
+EXPORT_SYMBOL(sdw_stream_add_slave);
+
+/**
+ * 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)
+{
+       mutex_lock(&slave->bus->bus_lock);
+
+       sdw_slave_port_free(slave, stream);
+       sdw_release_slave_stream(slave, stream);
+
+       mutex_unlock(&slave->bus->bus_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(sdw_stream_remove_slave);