All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vinod Koul <vinod.koul@intel.com>
To: Greg KH <gregkh@linuxfoundation.org>
Cc: ALSA <alsa-devel@alsa-project.org>,
	tiwai@suse.de,
	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>,
	liam.r.girdwood@linux.intel.com, patches.audio@intel.com,
	broonie@kernel.org, Vinod Koul <vinod.koul@intel.com>
Subject: [PATCH 07/13] soundwire: Add stream configuration APIs
Date: Wed, 28 Mar 2018 15:08:32 +0530	[thread overview]
Message-ID: <1522229918-4748-8-git-send-email-vinod.koul@intel.com> (raw)
In-Reply-To: <1522229918-4748-1-git-send-email-vinod.koul@intel.com>

Add APIs for prepare, enable, disable and de-prepare stream.

Signed-off-by: Sanyog Kale <sanyog.r.kale@intel.com>
Signed-off-by: Shreyas NC <shreyas.nc@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
---
 drivers/soundwire/bus.c       |  14 ++++
 drivers/soundwire/bus.h       |   6 ++
 drivers/soundwire/runtime.c   | 164 ++++++++++++++++++++++++++++++++++++++++++
 drivers/soundwire/stream.c    | 151 ++++++++++++++++++++++++++++++++++++++
 include/linux/soundwire/sdw.h |   4 ++
 5 files changed, 339 insertions(+)

diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 6cdb08b8781b..6f319bfde569 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -17,6 +17,7 @@
  */
 int sdw_add_bus_master(struct sdw_bus *bus)
 {
+	struct sdw_master_prop *prop = NULL;
 	int ret;
 
 	if (!bus->dev) {
@@ -78,6 +79,19 @@ int sdw_add_bus_master(struct sdw_bus *bus)
 		return ret;
 	}
 
+	/*
+	 * Initialize clock values based on Master properties. The max
+	 * frequency is read from max_freq property. Current assumption
+	 * is that the bus will start at highest clock frequency when
+	 * powered on.
+	 *
+	 * Default active bank will be 0 as out of reset the Slaves have to
+	 * start with bank 0 (Table 40 of Spec)
+	 */
+
+	prop = &bus->prop;
+	bus->params.max_dr_freq = prop->max_freq * SDW_DOUBLE_RATE_FACTOR;
+	bus->params.curr_dr_freq = bus->params.max_dr_freq;
 	bus->params.curr_bank = SDW_BANK0;
 	bus->params.next_bank = SDW_BANK1;
 
diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h
index 03a56a7feba1..60419e56bdb7 100644
--- a/drivers/soundwire/bus.h
+++ b/drivers/soundwire/bus.h
@@ -46,6 +46,7 @@ struct sdw_msg {
 };
 
 #define SDW_DOUBLE_RATE_FACTOR		2
+#define SDW_FREQ_MOD_FACTOR		3000
 
 extern int rows[SDW_FRAME_ROWS];
 extern int cols[SDW_FRAME_COLS];
@@ -114,6 +115,11 @@ struct sdw_master_runtime {
 	struct list_head bus_node;
 };
 
+int _sdw_prepare_stream(struct sdw_stream_runtime *stream);
+int _sdw_enable_stream(struct sdw_stream_runtime *stream);
+int _sdw_deprepare_stream(struct sdw_stream_runtime *stream);
+int _sdw_disable_stream(struct sdw_stream_runtime *stream);
+
 struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave,
 				enum sdw_data_direction direction,
 				unsigned int port_num);
diff --git a/drivers/soundwire/runtime.c b/drivers/soundwire/runtime.c
index 9bc876d23a4c..d19c36329033 100644
--- a/drivers/soundwire/runtime.c
+++ b/drivers/soundwire/runtime.c
@@ -741,3 +741,167 @@ static int do_bank_switch(struct sdw_stream_runtime *stream)
 err:
 	return ret;
 }
+
+/**
+ * _sdw_deprepare_stream: De-prepare stream
+ *
+ * @stream: Stream runtime handle
+ */
+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;
+	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;
+	}
+
+	bus->params.bandwidth -= m_rt->stream->params.rate *
+		m_rt->ch_count * m_rt->stream->params.bps;
+
+	if (!bus->params.bandwidth) {
+		bus->params.row = 0;
+		bus->params.col = 0;
+		goto exit;
+
+	}
+
+	/* 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);
+
+exit:
+	stream->state = SDW_STREAM_DEPREPARE;
+
+	return ret;
+}
+
+/**
+ * _sdw_disable_stream: Disable stream
+ *
+ * @stream: Stream runtime handle
+ */
+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;
+	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;
+	}
+
+	stream->state = SDW_STREAM_DISABLE;
+
+	/* 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);
+}
+
+/**
+ * _sdw_enable_stream: Enable stream
+ *
+ * @stream: Stream runtime handle
+ */
+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;
+	int 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);
+	if (ret < 0) {
+		dev_err(bus->dev, "Bank switch failed: %d", ret);
+		return ret;
+	}
+
+	stream->state = SDW_STREAM_ENABLE;
+	return 0;
+}
+
+/**
+ * sdw_prepare_stream: Prepare stream
+ *
+ * @stream: Stream runtime handle
+ */
+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_prop *prop = NULL;
+	struct sdw_bus_params params;
+	int ret;
+
+	prop = &bus->prop;
+	memcpy(&params, &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;
+	}
+
+	/* Increment cumulative bus bandwidth */
+	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;
+	}
+
+	ret = do_bank_switch(stream);
+	if (ret < 0) {
+		dev_err(bus->dev, "Bank switch failed: %d", ret);
+		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;
+	}
+
+	stream->state = SDW_STREAM_PREPARE;
+
+	return ret;
+
+restore_params:
+	memcpy(&bus->params, &params, sizeof(params));
+	return ret;
+}
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index a29447e9a2f0..f7efb7296877 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -525,3 +525,154 @@ struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave,
 
 	return NULL;
 }
+
+/**
+ * sdw_prepare_stream: Prepare SoundWire stream
+ *
+ * @stream: Soundwire stream
+ *
+ * Documentation/soundwire/stream.txt explains this API in detail
+ */
+int sdw_prepare_stream(struct sdw_stream_runtime *stream)
+{
+	int ret = 0;
+
+	if (!stream) {
+		pr_err("SoundWire: Handle not found for stream");
+		return -EINVAL;
+	}
+
+	mutex_lock(&stream->m_rt->bus->bus_lock);
+
+	if (stream->state == SDW_STREAM_DISABLE)
+		goto error;
+
+	if ((stream->state != SDW_STREAM_CONFIG) &&
+		(stream->state != SDW_STREAM_DEPREPARE)) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	ret = _sdw_prepare_stream(stream);
+	if (ret < 0) {
+		pr_err("Prepare for stream:%s failed: %d", stream->name, ret);
+		goto error;
+	}
+
+error:
+	mutex_unlock(&stream->m_rt->bus->bus_lock);
+	return ret;
+}
+EXPORT_SYMBOL(sdw_prepare_stream);
+
+/**
+ * sdw_enable_stream: Enable SoundWire stream
+ *
+ * @stream: Soundwire stream
+ *
+ * Documentation/soundwire/stream.txt explains this API in detail
+ */
+int sdw_enable_stream(struct sdw_stream_runtime *stream)
+{
+	int ret = 0;
+
+	if (!stream) {
+		pr_err("SoundWire: Handle not found for stream");
+		return -EINVAL;
+	}
+
+	mutex_lock(&stream->m_rt->bus->bus_lock);
+
+	if (stream->state == SDW_STREAM_ENABLE)
+		goto error;
+
+	if ((stream->state != SDW_STREAM_PREPARE) &&
+		(stream->state != SDW_STREAM_DISABLE)) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	ret = _sdw_enable_stream(stream);
+	if (ret < 0) {
+		pr_err("Enable for stream:%s failed: %d", stream->name, ret);
+		goto error;
+	}
+
+error:
+	mutex_unlock(&stream->m_rt->bus->bus_lock);
+	return ret;
+}
+EXPORT_SYMBOL(sdw_enable_stream);
+
+/**
+ * sdw_disable_stream: Disable SoundWire stream
+ *
+ * @stream: Soundwire stream
+ *
+ * Documentation/soundwire/stream.txt explains this API in detail
+ */
+int sdw_disable_stream(struct sdw_stream_runtime *stream)
+{
+	int ret = 0;
+
+	if (!stream) {
+		pr_err("SoundWire: Handle not found for stream");
+		return -EINVAL;
+	}
+
+	mutex_lock(&stream->m_rt->bus->bus_lock);
+
+	if (stream->state == SDW_STREAM_DISABLE)
+		goto error;
+
+	if (stream->state != SDW_STREAM_ENABLE) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	ret = _sdw_disable_stream(stream);
+	if (ret < 0) {
+		pr_err("Disable for stream:%s failed: %d", stream->name, ret);
+		goto error;
+	}
+
+error:
+	mutex_unlock(&stream->m_rt->bus->bus_lock);
+	return ret;
+}
+EXPORT_SYMBOL(sdw_disable_stream);
+
+/**
+ * sdw_deprepare_stream: Deprepare SoundWire stream
+ *
+ * @stream: Soundwire stream
+ *
+ * Documentation/soundwire/stream.txt explains this API in detail
+ */
+int sdw_deprepare_stream(struct sdw_stream_runtime *stream)
+{
+	int ret = 0;
+
+	if (!stream) {
+		pr_err("SoundWire: Handle not found for stream");
+		return -EINVAL;
+	}
+
+	mutex_lock(&stream->m_rt->bus->bus_lock);
+
+	if (stream->state != SDW_STREAM_DISABLE) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	ret = _sdw_deprepare_stream(stream);
+	if (ret < 0) {
+		pr_err("De-prepare for stream:%d failed: %d", ret, ret);
+		goto error;
+	}
+
+error:
+	mutex_unlock(&stream->m_rt->bus->bus_lock);
+	return ret;
+}
+EXPORT_SYMBOL(sdw_deprepare_stream);
diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h
index 7c7d9d6b730f..9b583a8ae3dd 100644
--- a/include/linux/soundwire/sdw.h
+++ b/include/linux/soundwire/sdw.h
@@ -796,6 +796,10 @@ int sdw_stream_remove_master(struct sdw_bus *bus,
 		struct sdw_stream_runtime *stream);
 int sdw_stream_remove_slave(struct sdw_slave *slave,
 		struct sdw_stream_runtime *stream);
+int sdw_prepare_stream(struct sdw_stream_runtime *stream);
+int sdw_enable_stream(struct sdw_stream_runtime *stream);
+int sdw_disable_stream(struct sdw_stream_runtime *stream);
+int sdw_deprepare_stream(struct sdw_stream_runtime *stream);
 
 /* messaging and data APIs */
 
-- 
2.7.4

  parent reply	other threads:[~2018-03-28  9:34 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-28  9:38 [PATCH 00/13] soundwire: Add stream support Vinod Koul
2018-03-28  9:38 ` [PATCH 01/13] soundwire: Add more documentation Vinod Koul
2018-03-30  1:47   ` Pierre-Louis Bossart
2018-03-30  6:38     ` Vinod Koul
2018-03-28  9:38 ` [PATCH 02/13] soundwire: Add support for SoundWire stream management Vinod Koul
2018-03-30  1:57   ` Pierre-Louis Bossart
2018-03-30  6:42     ` Vinod Koul
2018-03-30  6:44       ` Vinod Koul
2018-03-28  9:38 ` [PATCH 03/13] soundwire: Add support for port management Vinod Koul
2018-03-28  9:38 ` [PATCH 04/13] soundwire: Add Master and Slave port programming Vinod Koul
2018-03-28  9:38 ` [PATCH 05/13] soundwire: Add helpers for ports operations Vinod Koul
2018-03-28  9:38 ` [PATCH 06/13] soundwire: Add bank switch routine Vinod Koul
2018-03-28  9:38 ` Vinod Koul [this message]
2018-03-28  9:38 ` [PATCH 08/13] ASoC: Add SoundWire stream programming interface Vinod Koul
2018-03-30  3:05   ` Takashi Sakamoto
2018-03-30  6:03     ` Greg KH
2018-04-02  6:26       ` Takashi Sakamoto
2018-04-03 12:03         ` Takashi Iwai
2018-04-05  5:03           ` Takashi Sakamoto
2018-04-05  6:38             ` Vinod Koul
2018-03-28  9:38 ` [PATCH 09/13] soundwire: Remove cdns_master_ops Vinod Koul
2018-03-28  9:38 ` [PATCH 10/13] soundwire: cdns: Add port routines Vinod Koul
2018-03-28  9:38 ` [PATCH 11/13] soundwire: cdns: Add stream routines Vinod Koul
2018-03-28  9:38 ` [PATCH 12/13] soundwire: intel: Add stream initialization Vinod Koul
2018-03-28  9:38 ` [PATCH 13/13] soundwire: intel: Add audio DAI ops Vinod Koul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1522229918-4748-8-git-send-email-vinod.koul@intel.com \
    --to=vinod.koul@intel.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=liam.r.girdwood@linux.intel.com \
    --cc=patches.audio@intel.com \
    --cc=pierre-louis.bossart@linux.intel.com \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.