From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
The sdw_stream_add_slave/master() functions are called from the .hw_params stage. We need to make sure the functions can be called multiple times.
In this version, we assume that only 'audio' parameters provide in the hw_params() can change. If the number of ports could change dynamically depending on the stream configuration (number of channels, etc), we would need to free-up all the stream resources and reallocate them.
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 --- drivers/soundwire/stream.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index a52a9ab0eea1..ccf3c99dd579 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -898,6 +898,11 @@ static void sdw_port_free(struct sdw_port_runtime *p_rt) kfree(p_rt); }
+static bool sdw_slave_port_allocated(struct sdw_slave_runtime *s_rt) +{ + return !list_empty(&s_rt->port_list); +} + static void sdw_slave_port_free(struct sdw_slave *slave, struct sdw_stream_runtime *stream) { @@ -972,6 +977,11 @@ static int sdw_slave_port_config(struct sdw_slave *slave, return 0; }
+static bool sdw_master_port_allocated(struct sdw_master_runtime *m_rt) +{ + return !list_empty(&m_rt->port_list); +} + static void sdw_master_port_free(struct sdw_master_runtime *m_rt) { struct sdw_port_runtime *p_rt, *_p_rt; @@ -1856,12 +1866,17 @@ int sdw_stream_add_master(struct sdw_bus *bus, } skip_alloc_master_rt:
+ if (sdw_master_port_allocated(m_rt)) + goto skip_alloc_master_port; + ret = sdw_master_port_alloc(m_rt, num_ports); if (ret) goto alloc_error;
stream->m_rt_count++;
+skip_alloc_master_port: + ret = sdw_master_rt_config(m_rt, stream_config); if (ret < 0) goto unlock; @@ -1970,6 +1985,10 @@ int sdw_stream_add_slave(struct sdw_slave *slave, }
skip_alloc_master_rt: + s_rt = sdw_slave_rt_find(slave, stream); + if (s_rt) + goto skip_alloc_slave_rt; + s_rt = sdw_slave_rt_alloc(slave, m_rt); if (!s_rt) { dev_err(&slave->dev, "Slave runtime alloc failed for stream:%s\n", stream->name); @@ -1978,10 +1997,15 @@ int sdw_stream_add_slave(struct sdw_slave *slave, goto alloc_error; }
+skip_alloc_slave_rt: + if (sdw_slave_port_allocated(s_rt)) + goto skip_port_alloc; + ret = sdw_slave_port_alloc(slave, s_rt, num_ports); if (ret) goto alloc_error;
+skip_port_alloc: ret = sdw_master_rt_config(m_rt, stream_config); if (ret) goto unlock;