Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 48949722 authored by Vinod Koul's avatar Vinod Koul
Browse files

soundwire: Handle multiple master instances in a stream



For each SoundWire stream operation, we need to parse master
list and operate upon all master runtime.

This is a preparatory patch to do the boilerplate conversion
of stream handling from single master runtime to handle a
list of master runtime. The code to support bank switch for
multiple master instances is added in the next patch.

Signed-off-by: default avatarSanyog Kale <sanyog.r.kale@intel.com>
Signed-off-by: default avatarShreyas NC <shreyas.nc@intel.com>
Acked-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 0c4a1049
Loading
Loading
Loading
Loading
+188 −123
Original line number Diff line number Diff line
@@ -681,18 +681,22 @@ static int sdw_bank_switch(struct sdw_bus *bus)

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;
	struct sdw_bus *bus = m_rt->bus;
	struct sdw_bus *bus = NULL;
	int ret = 0;


	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);
				dev_err(bus->dev,
					"Pre bank switch op failed: %d", ret);
				return ret;
			}
		}
@@ -703,6 +707,11 @@ static int do_bank_switch(struct sdw_stream_runtime *stream)
			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) {
@@ -712,6 +721,7 @@ static int do_bank_switch(struct sdw_stream_runtime *stream)
					"Post bank switch op failed: %d", ret);
			}
		}
	}

	return ret;
}
@@ -754,6 +764,21 @@ struct sdw_stream_runtime *sdw_alloc_stream(char *stream_name)
}
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
 *
@@ -770,12 +795,11 @@ static struct sdw_master_runtime
{
	struct sdw_master_runtime *m_rt;

	m_rt = stream->m_rt;

	/*
	 * check if Master is already allocated (as a result of Slave adding
	 * it first), if so skip allocation and go to configure
	 */
	m_rt = sdw_find_master_rt(bus, stream);
	if (m_rt)
		goto stream_config;

@@ -786,7 +810,7 @@ static struct sdw_master_runtime
	/* Initialization of Master runtime handle */
	INIT_LIST_HEAD(&m_rt->port_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);

@@ -844,20 +868,24 @@ static void sdw_slave_port_release(struct sdw_bus *bus,
			struct sdw_stream_runtime *stream)
{
	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;

	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) {

			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);
			}
		}
	}
}

/**
 * sdw_release_slave_stream() - Free Slave(s) runtime handle
@@ -871,8 +899,9 @@ static void sdw_release_slave_stream(struct sdw_slave *slave,
			struct sdw_stream_runtime *stream)
{
	struct sdw_slave_runtime *s_rt, *_s_rt;
	struct sdw_master_runtime *m_rt = stream->m_rt;
	struct sdw_master_runtime *m_rt;

	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) {
@@ -884,10 +913,12 @@ static void sdw_release_slave_stream(struct sdw_slave *slave,
			}
		}
	}
}

/**
 * sdw_release_master_stream() - Free Master runtime handle
 *
 * @m_rt: Master runtime node
 * @stream: Stream runtime handle.
 *
 * 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
 * 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;

	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);
	}

	list_del(&m_rt->stream_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,
		struct sdw_stream_runtime *stream)
{
	struct sdw_master_runtime *m_rt, *_m_rt;

	mutex_lock(&bus->bus_lock);

	sdw_release_master_stream(stream);
	sdw_master_port_release(bus, stream->m_rt);
	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;
	kfree(stream->m_rt);
	stream->m_rt = NULL;

	mutex_unlock(&bus->bus_lock);

@@ -1128,7 +1170,7 @@ int sdw_stream_add_master(struct sdw_bus *bus,
	goto unlock;

stream_error:
	sdw_release_master_stream(stream);
	sdw_release_master_stream(m_rt, stream);
unlock:
	mutex_unlock(&bus->bus_lock);
	return ret;
@@ -1206,7 +1248,7 @@ int sdw_stream_add_slave(struct sdw_slave *slave,
	 * we hit error so cleanup the stream, release all Slave(s) and
	 * Master runtime
	 */
	sdw_release_master_stream(stream);
	sdw_release_master_stream(m_rt, stream);
error:
	mutex_unlock(&slave->bus->bus_lock);
	return ret;
@@ -1275,6 +1317,8 @@ static void sdw_acquire_bus_lock(struct sdw_stream_runtime *stream)
 * @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)
{
@@ -1290,12 +1334,15 @@ static void sdw_release_bus_lock(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_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));

@@ -1317,12 +1364,17 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream)
			goto restore_params;
		}

	}

	ret = do_bank_switch(stream);
	if (ret < 0) {
		dev_err(bus->dev, "Bank switch failed: %d", ret);
		goto restore_params;
	}

	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) {
@@ -1330,6 +1382,7 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream)
					ret);
			return ret;
		}
	}

	stream->state = SDW_STREAM_PREPARED;

@@ -1356,23 +1409,27 @@ int sdw_prepare_stream(struct sdw_stream_runtime *stream)
		return -EINVAL;
	}

	mutex_lock(&stream->m_rt->bus->bus_lock);
	sdw_acquire_bus_lock(stream);

	ret = _sdw_prepare_stream(stream);
	if (ret < 0)
		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;
}
EXPORT_SYMBOL(sdw_prepare_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;

	/* 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;

		/* Program params */
		ret = sdw_program_params(bus);
		if (ret < 0) {
@@ -1386,6 +1443,7 @@ static int _sdw_enable_stream(struct sdw_stream_runtime *stream)
			dev_err(bus->dev, "Enable port(s) failed ret: %d", ret);
			return ret;
		}
	}

	ret = do_bank_switch(stream);
	if (ret < 0) {
@@ -1413,38 +1471,43 @@ int sdw_enable_stream(struct sdw_stream_runtime *stream)
		return -EINVAL;
	}

	mutex_lock(&stream->m_rt->bus->bus_lock);
	sdw_acquire_bus_lock(stream);

	ret = _sdw_enable_stream(stream);
	if (ret < 0)
		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;
}
EXPORT_SYMBOL(sdw_enable_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;

	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;

	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);
}
@@ -1465,23 +1528,25 @@ int sdw_disable_stream(struct sdw_stream_runtime *stream)
		return -EINVAL;
	}

	mutex_lock(&stream->m_rt->bus->bus_lock);
	sdw_acquire_bus_lock(stream);

	ret = _sdw_disable_stream(stream);
	if (ret < 0)
		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;
}
EXPORT_SYMBOL(sdw_disable_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;

	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) {
@@ -1489,8 +1554,6 @@ static int _sdw_deprepare_stream(struct sdw_stream_runtime *stream)
			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;
@@ -1502,6 +1565,9 @@ static int _sdw_deprepare_stream(struct sdw_stream_runtime *stream)
			return ret;
		}

	}

	stream->state = SDW_STREAM_DEPREPARED;
	return do_bank_switch(stream);
}

@@ -1521,13 +1587,12 @@ int sdw_deprepare_stream(struct sdw_stream_runtime *stream)
		return -EINVAL;
	}

	mutex_lock(&stream->m_rt->bus->bus_lock);

	sdw_acquire_bus_lock(stream);
	ret = _sdw_deprepare_stream(stream);
	if (ret < 0)
		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;
}
EXPORT_SYMBOL(sdw_deprepare_stream);
+0 −2
Original line number Diff line number Diff line
@@ -768,7 +768,6 @@ struct sdw_stream_params {
 * @params: Stream parameters
 * @state: Current state of the stream
 * @type: Stream type PCM or PDM
 * @m_rt: Master runtime
 * @master_list: List of Master runtime(s) in this stream.
 * master_list can contain only one m_rt per Master instance
 * for a stream
@@ -778,7 +777,6 @@ struct sdw_stream_runtime {
	struct sdw_stream_params params;
	enum sdw_stream_state state;
	enum sdw_stream_type type;
	struct sdw_master_runtime *m_rt;
	struct list_head master_list;
};