|
@@ -681,35 +681,45 @@ error_1:
|
|
|
|
|
|
static int do_bank_switch(struct sdw_stream_runtime *stream)
|
|
static int do_bank_switch(struct sdw_stream_runtime *stream)
|
|
{
|
|
{
|
|
- struct sdw_master_runtime *m_rt = stream->m_rt;
|
|
|
|
|
|
+ struct sdw_master_runtime *m_rt = NULL;
|
|
const struct sdw_master_ops *ops;
|
|
const struct sdw_master_ops *ops;
|
|
- struct sdw_bus *bus = m_rt->bus;
|
|
|
|
|
|
+ struct sdw_bus *bus = NULL;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
- ops = bus->ops;
|
|
|
|
|
|
|
|
- /* Pre-bank switch */
|
|
|
|
- if (ops->pre_bank_switch) {
|
|
|
|
- ret = ops->pre_bank_switch(bus);
|
|
|
|
|
|
+ list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
|
|
|
+ bus = m_rt->bus;
|
|
|
|
+ ops = bus->ops;
|
|
|
|
+
|
|
|
|
+ /* Pre-bank switch */
|
|
|
|
+ if (ops->pre_bank_switch) {
|
|
|
|
+ ret = ops->pre_bank_switch(bus);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(bus->dev,
|
|
|
|
+ "Pre bank switch op failed: %d", ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Bank switch */
|
|
|
|
+ ret = sdw_bank_switch(bus);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
- dev_err(bus->dev, "Pre bank switch op failed: %d", ret);
|
|
|
|
|
|
+ dev_err(bus->dev, "Bank switch failed: %d", ret);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /* Bank switch */
|
|
|
|
- ret = sdw_bank_switch(bus);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_err(bus->dev, "Bank switch failed: %d", ret);
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
|
|
+ list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
|
|
|
+ bus = m_rt->bus;
|
|
|
|
+ ops = bus->ops;
|
|
|
|
|
|
- /* Post-bank switch */
|
|
|
|
- if (ops->post_bank_switch) {
|
|
|
|
- ret = ops->post_bank_switch(bus);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_err(bus->dev,
|
|
|
|
|
|
+ /* Post-bank switch */
|
|
|
|
+ if (ops->post_bank_switch) {
|
|
|
|
+ ret = ops->post_bank_switch(bus);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(bus->dev,
|
|
"Post bank switch op failed: %d", ret);
|
|
"Post bank switch op failed: %d", ret);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -754,6 +764,21 @@ struct sdw_stream_runtime *sdw_alloc_stream(char *stream_name)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(sdw_alloc_stream);
|
|
EXPORT_SYMBOL(sdw_alloc_stream);
|
|
|
|
|
|
|
|
+static struct sdw_master_runtime
|
|
|
|
+*sdw_find_master_rt(struct sdw_bus *bus,
|
|
|
|
+ struct sdw_stream_runtime *stream)
|
|
|
|
+{
|
|
|
|
+ struct sdw_master_runtime *m_rt = NULL;
|
|
|
|
+
|
|
|
|
+ /* Retrieve Bus handle if already available */
|
|
|
|
+ list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
|
|
|
+ if (m_rt->bus == bus)
|
|
|
|
+ return m_rt;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* sdw_alloc_master_rt() - Allocates and initialize Master runtime handle
|
|
* sdw_alloc_master_rt() - Allocates and initialize Master runtime handle
|
|
*
|
|
*
|
|
@@ -770,12 +795,11 @@ static struct sdw_master_runtime
|
|
{
|
|
{
|
|
struct sdw_master_runtime *m_rt;
|
|
struct sdw_master_runtime *m_rt;
|
|
|
|
|
|
- m_rt = stream->m_rt;
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* check if Master is already allocated (as a result of Slave adding
|
|
* check if Master is already allocated (as a result of Slave adding
|
|
* it first), if so skip allocation and go to configure
|
|
* it first), if so skip allocation and go to configure
|
|
*/
|
|
*/
|
|
|
|
+ m_rt = sdw_find_master_rt(bus, stream);
|
|
if (m_rt)
|
|
if (m_rt)
|
|
goto stream_config;
|
|
goto stream_config;
|
|
|
|
|
|
@@ -786,7 +810,7 @@ static struct sdw_master_runtime
|
|
/* Initialization of Master runtime handle */
|
|
/* Initialization of Master runtime handle */
|
|
INIT_LIST_HEAD(&m_rt->port_list);
|
|
INIT_LIST_HEAD(&m_rt->port_list);
|
|
INIT_LIST_HEAD(&m_rt->slave_rt_list);
|
|
INIT_LIST_HEAD(&m_rt->slave_rt_list);
|
|
- stream->m_rt = m_rt;
|
|
|
|
|
|
+ list_add_tail(&m_rt->stream_node, &stream->master_list);
|
|
|
|
|
|
list_add_tail(&m_rt->bus_node, &bus->m_rt_list);
|
|
list_add_tail(&m_rt->bus_node, &bus->m_rt_list);
|
|
|
|
|
|
@@ -844,17 +868,21 @@ static void sdw_slave_port_release(struct sdw_bus *bus,
|
|
struct sdw_stream_runtime *stream)
|
|
struct sdw_stream_runtime *stream)
|
|
{
|
|
{
|
|
struct sdw_port_runtime *p_rt, *_p_rt;
|
|
struct sdw_port_runtime *p_rt, *_p_rt;
|
|
- struct sdw_master_runtime *m_rt = stream->m_rt;
|
|
|
|
|
|
+ struct sdw_master_runtime *m_rt;
|
|
struct sdw_slave_runtime *s_rt;
|
|
struct sdw_slave_runtime *s_rt;
|
|
|
|
|
|
- list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) {
|
|
|
|
- if (s_rt->slave != slave)
|
|
|
|
- continue;
|
|
|
|
|
|
+ list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
|
|
|
+ list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) {
|
|
|
|
|
|
- list_for_each_entry_safe(p_rt, _p_rt,
|
|
|
|
- &s_rt->port_list, port_node) {
|
|
|
|
- list_del(&p_rt->port_node);
|
|
|
|
- kfree(p_rt);
|
|
|
|
|
|
+ if (s_rt->slave != slave)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ list_for_each_entry_safe(p_rt, _p_rt,
|
|
|
|
+ &s_rt->port_list, port_node) {
|
|
|
|
+
|
|
|
|
+ list_del(&p_rt->port_node);
|
|
|
|
+ kfree(p_rt);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -871,16 +899,18 @@ static void sdw_release_slave_stream(struct sdw_slave *slave,
|
|
struct sdw_stream_runtime *stream)
|
|
struct sdw_stream_runtime *stream)
|
|
{
|
|
{
|
|
struct sdw_slave_runtime *s_rt, *_s_rt;
|
|
struct sdw_slave_runtime *s_rt, *_s_rt;
|
|
- struct sdw_master_runtime *m_rt = stream->m_rt;
|
|
|
|
-
|
|
|
|
- /* Retrieve Slave runtime handle */
|
|
|
|
- list_for_each_entry_safe(s_rt, _s_rt,
|
|
|
|
- &m_rt->slave_rt_list, m_rt_node) {
|
|
|
|
|
|
+ struct sdw_master_runtime *m_rt;
|
|
|
|
|
|
- if (s_rt->slave == slave) {
|
|
|
|
- list_del(&s_rt->m_rt_node);
|
|
|
|
- kfree(s_rt);
|
|
|
|
- return;
|
|
|
|
|
|
+ list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
|
|
|
+ /* Retrieve Slave runtime handle */
|
|
|
|
+ list_for_each_entry_safe(s_rt, _s_rt,
|
|
|
|
+ &m_rt->slave_rt_list, m_rt_node) {
|
|
|
|
+
|
|
|
|
+ if (s_rt->slave == slave) {
|
|
|
|
+ list_del(&s_rt->m_rt_node);
|
|
|
|
+ kfree(s_rt);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -888,6 +918,7 @@ static void sdw_release_slave_stream(struct sdw_slave *slave,
|
|
/**
|
|
/**
|
|
* sdw_release_master_stream() - Free Master runtime handle
|
|
* sdw_release_master_stream() - Free Master runtime handle
|
|
*
|
|
*
|
|
|
|
+ * @m_rt: Master runtime node
|
|
* @stream: Stream runtime handle.
|
|
* @stream: Stream runtime handle.
|
|
*
|
|
*
|
|
* This function is to be called with bus_lock held
|
|
* This function is to be called with bus_lock held
|
|
@@ -895,9 +926,9 @@ static void sdw_release_slave_stream(struct sdw_slave *slave,
|
|
* handle. If this is called first then sdw_release_slave_stream() will have
|
|
* handle. If this is called first then sdw_release_slave_stream() will have
|
|
* no effect as Slave(s) runtime handle would already be freed up.
|
|
* no effect as Slave(s) runtime handle would already be freed up.
|
|
*/
|
|
*/
|
|
-static void sdw_release_master_stream(struct sdw_stream_runtime *stream)
|
|
|
|
|
|
+static void sdw_release_master_stream(struct sdw_master_runtime *m_rt,
|
|
|
|
+ struct sdw_stream_runtime *stream)
|
|
{
|
|
{
|
|
- struct sdw_master_runtime *m_rt = stream->m_rt;
|
|
|
|
struct sdw_slave_runtime *s_rt, *_s_rt;
|
|
struct sdw_slave_runtime *s_rt, *_s_rt;
|
|
|
|
|
|
list_for_each_entry_safe(s_rt, _s_rt, &m_rt->slave_rt_list, m_rt_node) {
|
|
list_for_each_entry_safe(s_rt, _s_rt, &m_rt->slave_rt_list, m_rt_node) {
|
|
@@ -905,7 +936,9 @@ static void sdw_release_master_stream(struct sdw_stream_runtime *stream)
|
|
sdw_release_slave_stream(s_rt->slave, stream);
|
|
sdw_release_slave_stream(s_rt->slave, stream);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ list_del(&m_rt->stream_node);
|
|
list_del(&m_rt->bus_node);
|
|
list_del(&m_rt->bus_node);
|
|
|
|
+ kfree(m_rt);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -919,13 +952,22 @@ static void sdw_release_master_stream(struct sdw_stream_runtime *stream)
|
|
int sdw_stream_remove_master(struct sdw_bus *bus,
|
|
int sdw_stream_remove_master(struct sdw_bus *bus,
|
|
struct sdw_stream_runtime *stream)
|
|
struct sdw_stream_runtime *stream)
|
|
{
|
|
{
|
|
|
|
+ struct sdw_master_runtime *m_rt, *_m_rt;
|
|
|
|
+
|
|
mutex_lock(&bus->bus_lock);
|
|
mutex_lock(&bus->bus_lock);
|
|
|
|
|
|
- sdw_release_master_stream(stream);
|
|
|
|
- sdw_master_port_release(bus, stream->m_rt);
|
|
|
|
- stream->state = SDW_STREAM_RELEASED;
|
|
|
|
- kfree(stream->m_rt);
|
|
|
|
- stream->m_rt = NULL;
|
|
|
|
|
|
+ list_for_each_entry_safe(m_rt, _m_rt,
|
|
|
|
+ &stream->master_list, stream_node) {
|
|
|
|
+
|
|
|
|
+ if (m_rt->bus != bus)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ sdw_master_port_release(bus, m_rt);
|
|
|
|
+ sdw_release_master_stream(m_rt, stream);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (list_empty(&stream->master_list))
|
|
|
|
+ stream->state = SDW_STREAM_RELEASED;
|
|
|
|
|
|
mutex_unlock(&bus->bus_lock);
|
|
mutex_unlock(&bus->bus_lock);
|
|
|
|
|
|
@@ -1128,7 +1170,7 @@ int sdw_stream_add_master(struct sdw_bus *bus,
|
|
goto unlock;
|
|
goto unlock;
|
|
|
|
|
|
stream_error:
|
|
stream_error:
|
|
- sdw_release_master_stream(stream);
|
|
|
|
|
|
+ sdw_release_master_stream(m_rt, stream);
|
|
unlock:
|
|
unlock:
|
|
mutex_unlock(&bus->bus_lock);
|
|
mutex_unlock(&bus->bus_lock);
|
|
return ret;
|
|
return ret;
|
|
@@ -1206,7 +1248,7 @@ stream_error:
|
|
* we hit error so cleanup the stream, release all Slave(s) and
|
|
* we hit error so cleanup the stream, release all Slave(s) and
|
|
* Master runtime
|
|
* Master runtime
|
|
*/
|
|
*/
|
|
- sdw_release_master_stream(stream);
|
|
|
|
|
|
+ sdw_release_master_stream(m_rt, stream);
|
|
error:
|
|
error:
|
|
mutex_unlock(&slave->bus->bus_lock);
|
|
mutex_unlock(&slave->bus->bus_lock);
|
|
return ret;
|
|
return ret;
|
|
@@ -1275,6 +1317,8 @@ static void sdw_acquire_bus_lock(struct sdw_stream_runtime *stream)
|
|
* @stream: SoundWire stream
|
|
* @stream: SoundWire stream
|
|
*
|
|
*
|
|
* Release the previously held bus_lock after reconfiguring the bus.
|
|
* 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 void sdw_release_bus_lock(struct sdw_stream_runtime *stream)
|
|
{
|
|
{
|
|
@@ -1290,31 +1334,36 @@ static void sdw_release_bus_lock(struct sdw_stream_runtime *stream)
|
|
|
|
|
|
static int _sdw_prepare_stream(struct sdw_stream_runtime *stream)
|
|
static int _sdw_prepare_stream(struct sdw_stream_runtime *stream)
|
|
{
|
|
{
|
|
- struct sdw_master_runtime *m_rt = stream->m_rt;
|
|
|
|
- struct sdw_bus *bus = m_rt->bus;
|
|
|
|
|
|
+ struct sdw_master_runtime *m_rt = NULL;
|
|
|
|
+ struct sdw_bus *bus = NULL;
|
|
struct sdw_master_prop *prop = NULL;
|
|
struct sdw_master_prop *prop = NULL;
|
|
struct sdw_bus_params params;
|
|
struct sdw_bus_params params;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- prop = &bus->prop;
|
|
|
|
- memcpy(¶ms, &bus->params, sizeof(params));
|
|
|
|
|
|
+ /* 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(¶ms, &bus->params, sizeof(params));
|
|
|
|
|
|
- /* TODO: Support Asynchronous mode */
|
|
|
|
- if ((prop->max_freq % stream->params.rate) != 0) {
|
|
|
|
- dev_err(bus->dev, "Async mode not supported");
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
|
|
+ /* TODO: Support Asynchronous mode */
|
|
|
|
+ if ((prop->max_freq % stream->params.rate) != 0) {
|
|
|
|
+ dev_err(bus->dev, "Async mode not supported");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
|
|
- /* Increment cumulative bus bandwidth */
|
|
|
|
- /* TODO: Update this during Device-Device support */
|
|
|
|
- bus->params.bandwidth += m_rt->stream->params.rate *
|
|
|
|
- m_rt->ch_count * m_rt->stream->params.bps;
|
|
|
|
|
|
+ /* Increment cumulative bus bandwidth */
|
|
|
|
+ /* TODO: Update this during Device-Device support */
|
|
|
|
+ bus->params.bandwidth += m_rt->stream->params.rate *
|
|
|
|
+ m_rt->ch_count * m_rt->stream->params.bps;
|
|
|
|
+
|
|
|
|
+ /* Program params */
|
|
|
|
+ ret = sdw_program_params(bus);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(bus->dev, "Program params failed: %d", ret);
|
|
|
|
+ goto restore_params;
|
|
|
|
+ }
|
|
|
|
|
|
- /* Program params */
|
|
|
|
- ret = sdw_program_params(bus);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_err(bus->dev, "Program params failed: %d", ret);
|
|
|
|
- goto restore_params;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
ret = do_bank_switch(stream);
|
|
ret = do_bank_switch(stream);
|
|
@@ -1323,12 +1372,16 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream)
|
|
goto restore_params;
|
|
goto restore_params;
|
|
}
|
|
}
|
|
|
|
|
|
- /* Prepare port(s) on the new clock configuration */
|
|
|
|
- ret = sdw_prep_deprep_ports(m_rt, true);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_err(bus->dev, "Prepare port(s) failed ret = %d",
|
|
|
|
- ret);
|
|
|
|
- return ret;
|
|
|
|
|
|
+ list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
|
|
|
+ bus = m_rt->bus;
|
|
|
|
+
|
|
|
|
+ /* Prepare port(s) on the new clock configuration */
|
|
|
|
+ ret = sdw_prep_deprep_ports(m_rt, true);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(bus->dev, "Prepare port(s) failed ret = %d",
|
|
|
|
+ ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
stream->state = SDW_STREAM_PREPARED;
|
|
stream->state = SDW_STREAM_PREPARED;
|
|
@@ -1356,35 +1409,40 @@ int sdw_prepare_stream(struct sdw_stream_runtime *stream)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- mutex_lock(&stream->m_rt->bus->bus_lock);
|
|
|
|
|
|
+ sdw_acquire_bus_lock(stream);
|
|
|
|
|
|
ret = _sdw_prepare_stream(stream);
|
|
ret = _sdw_prepare_stream(stream);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
pr_err("Prepare for stream:%s failed: %d", stream->name, ret);
|
|
pr_err("Prepare for stream:%s failed: %d", stream->name, ret);
|
|
|
|
|
|
- mutex_unlock(&stream->m_rt->bus->bus_lock);
|
|
|
|
|
|
+ sdw_release_bus_lock(stream);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(sdw_prepare_stream);
|
|
EXPORT_SYMBOL(sdw_prepare_stream);
|
|
|
|
|
|
static int _sdw_enable_stream(struct sdw_stream_runtime *stream)
|
|
static int _sdw_enable_stream(struct sdw_stream_runtime *stream)
|
|
{
|
|
{
|
|
- struct sdw_master_runtime *m_rt = stream->m_rt;
|
|
|
|
- struct sdw_bus *bus = m_rt->bus;
|
|
|
|
|
|
+ struct sdw_master_runtime *m_rt = NULL;
|
|
|
|
+ struct sdw_bus *bus = NULL;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- /* Program params */
|
|
|
|
- ret = sdw_program_params(bus);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_err(bus->dev, "Program params failed: %d", ret);
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
|
|
+ /* Enable 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;
|
|
|
|
|
|
- /* Enable port(s) */
|
|
|
|
- ret = sdw_enable_disable_ports(m_rt, true);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_err(bus->dev, "Enable port(s) failed ret: %d", ret);
|
|
|
|
- return ret;
|
|
|
|
|
|
+ /* Program params */
|
|
|
|
+ ret = sdw_program_params(bus);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(bus->dev, "Program params failed: %d", ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Enable port(s) */
|
|
|
|
+ ret = sdw_enable_disable_ports(m_rt, true);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(bus->dev, "Enable port(s) failed ret: %d", ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
ret = do_bank_switch(stream);
|
|
ret = do_bank_switch(stream);
|
|
@@ -1413,37 +1471,42 @@ int sdw_enable_stream(struct sdw_stream_runtime *stream)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- mutex_lock(&stream->m_rt->bus->bus_lock);
|
|
|
|
|
|
+ sdw_acquire_bus_lock(stream);
|
|
|
|
|
|
ret = _sdw_enable_stream(stream);
|
|
ret = _sdw_enable_stream(stream);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
pr_err("Enable for stream:%s failed: %d", stream->name, ret);
|
|
pr_err("Enable for stream:%s failed: %d", stream->name, ret);
|
|
|
|
|
|
- mutex_unlock(&stream->m_rt->bus->bus_lock);
|
|
|
|
|
|
+ sdw_release_bus_lock(stream);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(sdw_enable_stream);
|
|
EXPORT_SYMBOL(sdw_enable_stream);
|
|
|
|
|
|
static int _sdw_disable_stream(struct sdw_stream_runtime *stream)
|
|
static int _sdw_disable_stream(struct sdw_stream_runtime *stream)
|
|
{
|
|
{
|
|
- struct sdw_master_runtime *m_rt = stream->m_rt;
|
|
|
|
- struct sdw_bus *bus = m_rt->bus;
|
|
|
|
|
|
+ struct sdw_master_runtime *m_rt = NULL;
|
|
|
|
+ struct sdw_bus *bus = NULL;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- /* Disable port(s) */
|
|
|
|
- ret = sdw_enable_disable_ports(m_rt, false);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_err(bus->dev, "Disable port(s) failed: %d", ret);
|
|
|
|
- return ret;
|
|
|
|
|
|
+ list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
|
|
|
+ bus = m_rt->bus;
|
|
|
|
+ /* Disable port(s) */
|
|
|
|
+ ret = sdw_enable_disable_ports(m_rt, false);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(bus->dev, "Disable port(s) failed: %d", ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
stream->state = SDW_STREAM_DISABLED;
|
|
stream->state = SDW_STREAM_DISABLED;
|
|
|
|
|
|
- /* Program params */
|
|
|
|
- ret = sdw_program_params(bus);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_err(bus->dev, "Program params failed: %d", ret);
|
|
|
|
- return ret;
|
|
|
|
|
|
+ list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
|
|
|
+ bus = m_rt->bus;
|
|
|
|
+ /* Program params */
|
|
|
|
+ ret = sdw_program_params(bus);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(bus->dev, "Program params failed: %d", ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
return do_bank_switch(stream);
|
|
return do_bank_switch(stream);
|
|
@@ -1465,43 +1528,46 @@ int sdw_disable_stream(struct sdw_stream_runtime *stream)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- mutex_lock(&stream->m_rt->bus->bus_lock);
|
|
|
|
|
|
+ sdw_acquire_bus_lock(stream);
|
|
|
|
|
|
ret = _sdw_disable_stream(stream);
|
|
ret = _sdw_disable_stream(stream);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
pr_err("Disable for stream:%s failed: %d", stream->name, ret);
|
|
pr_err("Disable for stream:%s failed: %d", stream->name, ret);
|
|
|
|
|
|
- mutex_unlock(&stream->m_rt->bus->bus_lock);
|
|
|
|
|
|
+ sdw_release_bus_lock(stream);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(sdw_disable_stream);
|
|
EXPORT_SYMBOL(sdw_disable_stream);
|
|
|
|
|
|
static int _sdw_deprepare_stream(struct sdw_stream_runtime *stream)
|
|
static int _sdw_deprepare_stream(struct sdw_stream_runtime *stream)
|
|
{
|
|
{
|
|
- struct sdw_master_runtime *m_rt = stream->m_rt;
|
|
|
|
- struct sdw_bus *bus = m_rt->bus;
|
|
|
|
|
|
+ struct sdw_master_runtime *m_rt = NULL;
|
|
|
|
+ struct sdw_bus *bus = NULL;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
- /* De-prepare port(s) */
|
|
|
|
- ret = sdw_prep_deprep_ports(m_rt, false);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_err(bus->dev, "De-prepare port(s) failed: %d", ret);
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
|
|
+ list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
|
|
|
+ bus = m_rt->bus;
|
|
|
|
+ /* De-prepare port(s) */
|
|
|
|
+ ret = sdw_prep_deprep_ports(m_rt, false);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(bus->dev, "De-prepare port(s) failed: %d", ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
|
|
- stream->state = SDW_STREAM_DEPREPARED;
|
|
|
|
|
|
+ /* TODO: Update this during Device-Device support */
|
|
|
|
+ bus->params.bandwidth -= m_rt->stream->params.rate *
|
|
|
|
+ m_rt->ch_count * m_rt->stream->params.bps;
|
|
|
|
|
|
- /* TODO: Update this during Device-Device support */
|
|
|
|
- bus->params.bandwidth -= m_rt->stream->params.rate *
|
|
|
|
- m_rt->ch_count * m_rt->stream->params.bps;
|
|
|
|
|
|
+ /* Program params */
|
|
|
|
+ ret = sdw_program_params(bus);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(bus->dev, "Program params failed: %d", ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
|
|
- /* Program params */
|
|
|
|
- ret = sdw_program_params(bus);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_err(bus->dev, "Program params failed: %d", ret);
|
|
|
|
- return ret;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ stream->state = SDW_STREAM_DEPREPARED;
|
|
return do_bank_switch(stream);
|
|
return do_bank_switch(stream);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1521,13 +1587,12 @@ int sdw_deprepare_stream(struct sdw_stream_runtime *stream)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- mutex_lock(&stream->m_rt->bus->bus_lock);
|
|
|
|
-
|
|
|
|
|
|
+ sdw_acquire_bus_lock(stream);
|
|
ret = _sdw_deprepare_stream(stream);
|
|
ret = _sdw_deprepare_stream(stream);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
pr_err("De-prepare for stream:%d failed: %d", ret, ret);
|
|
pr_err("De-prepare for stream:%d failed: %d", ret, ret);
|
|
|
|
|
|
- mutex_unlock(&stream->m_rt->bus->bus_lock);
|
|
|
|
|
|
+ sdw_release_bus_lock(stream);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(sdw_deprepare_stream);
|
|
EXPORT_SYMBOL(sdw_deprepare_stream);
|