soundwire: Add stream configuration APIs
authorSanyog Kale <sanyog.r.kale@intel.com>
Thu, 26 Apr 2018 13:08:33 +0000 (18:38 +0530)
committerVinod Koul <vkoul@kernel.org>
Fri, 11 May 2018 16:17:06 +0000 (21:47 +0530)
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 <vkoul@kernel.org>
drivers/soundwire/bus.c
drivers/soundwire/stream.c
include/linux/soundwire/sdw.h

index 084bf71..dcc0ff9 100644 (file)
@@ -17,6 +17,7 @@
  */
 int sdw_add_bus_master(struct sdw_bus *bus)
 {
+       struct sdw_master_prop *prop = NULL;
        int ret;
 
        if (!bus->dev) {
@@ -79,9 +80,17 @@ int sdw_add_bus_master(struct sdw_bus *bus)
        }
 
        /*
+        * 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;
 
index bcc9220..8974a0f 100644 (file)
@@ -1233,3 +1233,247 @@ struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave,
 
        return NULL;
 }
+
+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_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 */
+       /* 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;
+       }
+
+       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_PREPARED;
+
+       return ret;
+
+restore_params:
+       memcpy(&bus->params, &params, sizeof(params));
+       return ret;
+}
+
+/**
+ * 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);
+
+       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);
+       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;
+       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_ENABLED;
+       return 0;
+}
+
+/**
+ * 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);
+
+       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);
+       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;
+       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_DISABLED;
+
+       /* 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_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);
+
+       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);
+       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;
+       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;
+       }
+
+       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;
+
+       /* 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_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);
+
+       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);
+       return ret;
+}
+EXPORT_SYMBOL(sdw_deprepare_stream);
index 61d6712..399cfb2 100644 (file)
@@ -791,6 +791,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 */