Skip to content

Commit

Permalink
Merge tag 'soundwire-4.20-rc1' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
gregkh committed Oct 2, 2018
2 parents 91c45a7 + 502c00d commit 018d52e
Show file tree
Hide file tree
Showing 8 changed files with 482 additions and 136 deletions.
36 changes: 36 additions & 0 deletions Documentation/driver-api/soundwire/stream.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
================================

Expand Down Expand Up @@ -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);


Expand All @@ -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,
Expand Down Expand Up @@ -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);


Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);


Expand All @@ -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);


Expand All @@ -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,
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -13619,7 +13619,7 @@ F: sound/soc/
F: include/sound/soc*

SOUNDWIRE SUBSYSTEM
M: Vinod Koul <[email protected]>
M: Vinod Koul <[email protected]>
M: Sanyog Kale <[email protected]>
R: Pierre-Louis Bossart <[email protected]>
L: [email protected] (moderated for non-subscribers)
Expand Down
6 changes: 6 additions & 0 deletions drivers/soundwire/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions drivers/soundwire/bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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;
};

Expand Down
68 changes: 65 additions & 3 deletions drivers/soundwire/intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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,
};

/*
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/soundwire/intel_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level,
struct acpi_device *adev;

if (acpi_bus_get_device(handle, &adev)) {
dev_err(&adev->dev, "Couldn't find ACPI handle\n");
pr_err("%s: Couldn't find ACPI handle\n", __func__);
return AE_NOT_FOUND;
}

Expand Down
Loading

0 comments on commit 018d52e

Please sign in to comment.