clear-pkgs-linux-iot-lts2018/0431-ASoC-Intel-common-Prov...

117 lines
4.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pardha Saradhi K <pardha.saradhi.kesapragada@intel.com>
Date: Thu, 30 Mar 2017 22:57:48 +0530
Subject: [PATCH] ASoC: Intel: common: Provide an interface to send IPCs
directly
This patch adds support for an IPC Tx function that can
be called directly rather than adding new Tx messages to the Queue.
Hence the new logic to send IPCs will be -
If the DSP is not busy, send IPCs directly.
Else add to the queue
Change-Id: I9d58872a051c9d704c60cf25a2e3b69c3b580818
Signed-off-by: Pardha Saradhi K <pardha.saradhi.kesapragada@intel.com>
Reviewed-on:
Reviewed-by: Koul, Vinod <vinod.koul@intel.com>
Tested-by: Tr, HarishkumarX <harishkumarx.tr@intel.com>
Reviewed-on:
Reviewed-by: Shaik, ShahinaX <shahinax.shaik@intel.com>
Reviewed-by: Kale, Sanyog R <sanyog.r.kale@intel.com>
Tested-by: Madiwalar, MadiwalappaX <madiwalappax.madiwalar@intel.com>
---
sound/soc/intel/common/sst-ipc.c | 11 +++++++--
sound/soc/intel/common/sst-ipc.h | 1 +
sound/soc/intel/skylake/skl-sst-ipc.c | 34 +++++++++++++++++++++++++++
3 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c
index 8a62daa1965b..fd93d58b9033 100644
--- a/sound/soc/intel/common/sst-ipc.c
+++ b/sound/soc/intel/common/sst-ipc.c
@@ -127,8 +127,15 @@ static int ipc_tx_message(struct sst_generic_ipc *ipc, u64 header,
ipc->ops.tx_data_copy(msg, tx_data, tx_bytes);
list_add_tail(&msg->list, &ipc->tx_list);
- schedule_work(&ipc->kwork);
- spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
+
+ if ((ipc->ops.is_dsp_busy && ipc->ops.is_dsp_busy(ipc->dsp)) ||
+ (ipc->ops.direct_tx_msg == NULL)) {
+ schedule_work(&ipc->kwork);
+ spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
+ } else {
+ spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
+ ipc->ops.direct_tx_msg(ipc);
+ }
if (wait)
return tx_wait_done(ipc, msg, rx_data,
diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h
index 4cfa9e37ac28..eae3fa7d1aef 100644
--- a/sound/soc/intel/common/sst-ipc.h
+++ b/sound/soc/intel/common/sst-ipc.h
@@ -47,6 +47,7 @@ struct sst_generic_ipc;
struct sst_plat_ipc_ops {
void (*tx_msg)(struct sst_generic_ipc *, struct ipc_message *);
+ void (*direct_tx_msg)(struct sst_generic_ipc *);
void (*shim_dbg)(struct sst_generic_ipc *, const char *);
void (*tx_data_copy)(struct ipc_message *, char *, size_t);
u64 (*reply_msg_match)(u64 header, u64 *mask);
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c
index 6efc9502d06e..9370c474c618 100644
--- a/sound/soc/intel/skylake/skl-sst-ipc.c
+++ b/sound/soc/intel/skylake/skl-sst-ipc.c
@@ -343,6 +343,39 @@ static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp)
return (hipci & SKL_ADSP_REG_HIPCI_BUSY);
}
+static void skl_ipc_tx_msgs_direct(struct sst_generic_ipc *ipc)
+{
+ struct ipc_message *msg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ipc->dsp->spinlock, flags);
+
+ if (list_empty(&ipc->tx_list) || ipc->pending) {
+ spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
+ return;
+ }
+
+ /* if the DSP is busy, we will TX messages after IRQ.
+ * also postpone if we are in the middle of procesing completion irq*/
+ if (ipc->ops.is_dsp_busy && ipc->ops.is_dsp_busy(ipc->dsp)) {
+ dev_dbg(ipc->dev, "skl_ipc_tx_msgs_direct dsp busy\n");
+ spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
+ return;
+ }
+
+ msg = list_first_entry(&ipc->tx_list, struct ipc_message, list);
+ list_move(&msg->list, &ipc->rx_list);
+
+ dev_dbg(ipc->dev, "skl_ipc_tx_msgs_direct sending message, header - %#.16lx\n",
+ (unsigned long)msg->header);
+ print_hex_dump_debug("Params:", DUMP_PREFIX_OFFSET, 8, 4,
+ msg->tx_data, msg->tx_size, false);
+ if (ipc->ops.tx_msg != NULL)
+ ipc->ops.tx_msg(ipc, msg);
+
+ spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
+}
+
/* Lock to be held by caller */
static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
{
@@ -854,6 +887,7 @@ int skl_ipc_init(struct device *dev, struct skl_sst *skl)
ipc->ops.tx_msg = skl_ipc_tx_msg;
ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
+ ipc->ops.direct_tx_msg = skl_ipc_tx_msgs_direct;
ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy;
return 0;
--
https://clearlinux.org