Commit 018d52e8 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'soundwire-4.20-rc1' of...

Merge tag 'soundwire-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire into char-misc-next

Vinod writes:

soundwire updates for 4.20-rc1

 - support for multi-link streaming
 - updates in intel driver for multi-link streaming
 - Update Vinod's email
 - Fix rst formatting

* tag 'soundwire-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire:
  Documentation: soundwire: fix stream.rst markup warnings
  soundwire: intel: Remove duplicate assignment
  MAINTAINERS: Update Vinod's email
  soundwire: intel: Fix uninitialized adev deref
  soundwire: intel: Add pre/post bank switch ops
  soundwire: keep track of Masters in a stream
  soundwire: Add support for multi link bank switch
  soundwire: Handle multiple master instances in a stream
  soundwire: Add support to lock across bus instances
  soundwire: Initialize completion for defer messages
  Documentation: soundwire: Add documentation for multi link
parents 91c45a7a 502c00d9
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -101,6 +101,34 @@ interface. ::
	+--------------------+                             |                |
							   +----------------+

Example 5: Stereo Stream with L and R channel is rendered by 2 Masters, each
rendering one channel, and is received by two different Slaves, each
receiving one channel. Both Masters and both Slaves are using single port. ::

	+---------------+                    Clock Signal  +---------------+
	|    Master     +----------------------------------+     Slave     |
	|   Interface   |                                  |   Interface   |
	|       1       |                                  |       1       |
	|               |                     Data Signal  |               |
	|       L       +----------------------------------+       L       |
	|     (Data)    |     Data Direction               |     (Data)    |
	+---------------+  +----------------------->       +---------------+

	+---------------+                    Clock Signal  +---------------+
	|    Master     +----------------------------------+     Slave     |
	|   Interface   |                                  |   Interface   |
	|       2       |                                  |       2       |
	|               |                     Data Signal  |               |
	|       R       +----------------------------------+       R       |
	|     (Data)    |     Data Direction               |     (Data)    |
	+---------------+  +----------------------->       +---------------+

Note: In multi-link cases like above, to lock, one would acquire a global
lock and then go on locking bus instances. But, in this case the caller
framework(ASoC DPCM) guarantees that stream operations on a card are
always serialized. So, there is no race condition and hence no need for
global lock.

SoundWire Stream Management flow
================================

@@ -174,6 +202,7 @@ per stream. From ASoC DPCM framework, this stream state maybe linked to
.startup() operation.

  .. code-block:: c

  int sdw_alloc_stream(char * stream_name);


@@ -200,6 +229,7 @@ only be invoked once by respective Master(s) and Slave(s). From ASoC DPCM
framework, this stream state is linked to .hw_params() operation.

  .. code-block:: c

  int sdw_stream_add_master(struct sdw_bus * bus,
		struct sdw_stream_config * stream_config,
		struct sdw_ports_config * ports_config,
@@ -245,6 +275,7 @@ stream. From ASoC DPCM framework, this stream state is linked to
.prepare() operation.

  .. code-block:: c

  int sdw_prepare_stream(struct sdw_stream_runtime * stream);


@@ -274,6 +305,7 @@ stream. From ASoC DPCM framework, this stream state is linked to
.trigger() start operation.

  .. code-block:: c

  int sdw_enable_stream(struct sdw_stream_runtime * stream);

SDW_STREAM_DISABLED
@@ -301,6 +333,7 @@ per stream. From ASoC DPCM framework, this stream state is linked to
.trigger() stop operation.

  .. code-block:: c

  int sdw_disable_stream(struct sdw_stream_runtime * stream);


@@ -325,6 +358,7 @@ per stream. From ASoC DPCM framework, this stream state is linked to
.trigger() stop operation.

  .. code-block:: c

  int sdw_deprepare_stream(struct sdw_stream_runtime * stream);


@@ -349,6 +383,7 @@ all the Master(s) and Slave(s) associated with stream. From ASoC DPCM
framework, this stream state is linked to .hw_free() operation.

  .. code-block:: c

  int sdw_stream_remove_master(struct sdw_bus * bus,
		struct sdw_stream_runtime * stream);
  int sdw_stream_remove_slave(struct sdw_slave * slave,
@@ -361,6 +396,7 @@ stream assigned as part of ALLOCATED state.
In .shutdown() the data structure maintaining stream state are freed up.

  .. code-block:: c

  void sdw_release_stream(struct sdw_stream_runtime * stream);

Not Supported
+1 −1
Original line number Diff line number Diff line
@@ -13619,7 +13619,7 @@ F: sound/soc/
F:	include/sound/soc*

SOUNDWIRE SUBSYSTEM
M:	Vinod Koul <vinod.koul@intel.com>
M:	Vinod Koul <vkoul@kernel.org>
M:	Sanyog Kale <sanyog.r.kale@intel.com>
R:	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
+6 −0
Original line number Diff line number Diff line
@@ -35,6 +35,11 @@ int sdw_add_bus_master(struct sdw_bus *bus)
	INIT_LIST_HEAD(&bus->slaves);
	INIT_LIST_HEAD(&bus->m_rt_list);

	/*
	 * Initialize multi_link flag
	 * TODO: populate this flag by reading property from FW node
	 */
	bus->multi_link = false;
	if (bus->ops->read_prop) {
		ret = bus->ops->read_prop(bus);
		if (ret < 0) {
@@ -175,6 +180,7 @@ static inline int do_transfer_defer(struct sdw_bus *bus,

	defer->msg = msg;
	defer->length = msg->len;
	init_completion(&defer->complete);

	for (i = 0; i <= retry; i++) {
		resp = bus->ops->xfer_msg_defer(bus, msg, defer);
+4 −0
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@
#ifndef __SDW_BUS_H
#define __SDW_BUS_H

#define DEFAULT_BANK_SWITCH_TIMEOUT 3000

#if IS_ENABLED(CONFIG_ACPI)
int sdw_acpi_find_slaves(struct sdw_bus *bus);
#else
@@ -99,6 +101,7 @@ struct sdw_slave_runtime {
 * this stream, can be zero.
 * @slave_rt_list: Slave runtime list
 * @port_list: List of Master Ports configured for this stream, can be zero.
 * @stream_node: sdw_stream_runtime master_list node
 * @bus_node: sdw_bus m_rt_list node
 */
struct sdw_master_runtime {
@@ -108,6 +111,7 @@ struct sdw_master_runtime {
	unsigned int ch_count;
	struct list_head slave_rt_list;
	struct list_head port_list;
	struct list_head stream_node;
	struct list_head bus_node;
};

+65 −3
Original line number Diff line number Diff line
@@ -397,6 +397,69 @@ static int intel_config_stream(struct sdw_intel *sdw,
	return -EIO;
}

/*
 * bank switch routines
 */

static int intel_pre_bank_switch(struct sdw_bus *bus)
{
	struct sdw_cdns *cdns = bus_to_cdns(bus);
	struct sdw_intel *sdw = cdns_to_intel(cdns);
	void __iomem *shim = sdw->res->shim;
	int sync_reg;

	/* Write to register only for multi-link */
	if (!bus->multi_link)
		return 0;

	/* Read SYNC register */
	sync_reg = intel_readl(shim, SDW_SHIM_SYNC);
	sync_reg |= SDW_SHIM_SYNC_CMDSYNC << sdw->instance;
	intel_writel(shim, SDW_SHIM_SYNC, sync_reg);

	return 0;
}

static int intel_post_bank_switch(struct sdw_bus *bus)
{
	struct sdw_cdns *cdns = bus_to_cdns(bus);
	struct sdw_intel *sdw = cdns_to_intel(cdns);
	void __iomem *shim = sdw->res->shim;
	int sync_reg, ret;

	/* Write to register only for multi-link */
	if (!bus->multi_link)
		return 0;

	/* Read SYNC register */
	sync_reg = intel_readl(shim, SDW_SHIM_SYNC);

	/*
	 * post_bank_switch() ops is called from the bus in loop for
	 * all the Masters in the steam with the expectation that
	 * we trigger the bankswitch for the only first Master in the list
	 * and do nothing for the other Masters
	 *
	 * So, set the SYNCGO bit only if CMDSYNC bit is set for any Master.
	 */
	if (!(sync_reg & SDW_SHIM_SYNC_CMDSYNC_MASK))
		return 0;

	/*
	 * Set SyncGO bit to synchronously trigger a bank switch for
	 * all the masters. A write to SYNCGO bit clears CMDSYNC bit for all
	 * the Masters.
	 */
	sync_reg |= SDW_SHIM_SYNC_SYNCGO;

	ret = intel_clear_bit(shim, SDW_SHIM_SYNC, sync_reg,
					SDW_SHIM_SYNC_SYNCGO);
	if (ret < 0)
		dev_err(sdw->cdns.dev, "Post bank switch failed: %d", ret);

	return ret;
}

/*
 * DAI routines
 */
@@ -750,6 +813,8 @@ static struct sdw_master_ops sdw_intel_ops = {
	.xfer_msg_defer = cdns_xfer_msg_defer,
	.reset_page_addr = cdns_reset_page_addr,
	.set_bus_conf = cdns_bus_conf,
	.pre_bank_switch = intel_pre_bank_switch,
	.post_bank_switch = intel_post_bank_switch,
};

/*
@@ -780,9 +845,6 @@ static int intel_probe(struct platform_device *pdev)
	sdw_intel_ops.read_prop = intel_prop_read;
	sdw->cdns.bus.ops = &sdw_intel_ops;

	sdw_intel_ops.read_prop = intel_prop_read;
	sdw->cdns.bus.ops = &sdw_intel_ops;

	platform_set_drvdata(pdev, sdw);

	ret = sdw_add_bus_master(&sdw->cdns.bus);
Loading