OSDN Git Service

soundwire: intel: Add pre/post bank switch ops
authorShreyas NC <shreyas.nc@intel.com>
Fri, 27 Jul 2018 09:14:17 +0000 (14:44 +0530)
committerVinod Koul <vkoul@kernel.org>
Mon, 27 Aug 2018 04:19:48 +0000 (09:49 +0530)
To support multi link on Intel platforms, we need to update
SDW SHIM registers.

So, add pre/post bank switch ops for the same in Intel driver.

Signed-off-by: Sanyog Kale <sanyog.r.kale@intel.com>
Signed-off-by: Shreyas NC <shreyas.nc@intel.com>
Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/soundwire/intel.c

index 0a8990e..da7f91f 100644 (file)
@@ -398,6 +398,69 @@ static int intel_config_stream(struct sdw_intel *sdw,
 }
 
 /*
+ * 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,
 };
 
 /*