clear-pkgs-linux-iot-lts2018/0266-ASoC-Intel-Skylake-gen...

247 lines
6.9 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mousumi Jana <mousumix.jana@intel.com>
Date: Wed, 25 Nov 2015 22:52:40 +0530
Subject: [PATCH] ASoC: Intel: Skylake: generic IPC message support
Debugfs provides an interface to send generic ipc message.
This feature can be used to send any IPC command by
passing it as a binary blob to the interface.
Change-Id: Ic712c303a8e4559e2628e7507f16828913860a26
Signed-off-by: Mousumi Jana <mousumix.jana@intel.com>
Reviewed-on:
Reviewed-by: Babu, Ramesh <ramesh.babu@intel.com>
Tested-by: Babu, Ramesh <ramesh.babu@intel.com>
---
sound/soc/intel/skylake/skl-debug.c | 157 ++++++++++++++++++++++++-
sound/soc/intel/skylake/skl-topology.h | 8 ++
sound/soc/intel/skylake/skl.h | 1 +
3 files changed, 165 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c
index f9db7ea..23a5251 100644
--- a/sound/soc/intel/skylake/skl-debug.c
+++ b/sound/soc/intel/skylake/skl-debug.c
@@ -24,10 +24,14 @@
#include "../common/sst-dsp-priv.h"
#include "skl-nhlt.h"
-#define MOD_BUF PAGE_SIZE
+#define MOD_BUF (2 * PAGE_SIZE)
#define FW_REG_BUF PAGE_SIZE
#define FW_REG_SIZE 0x60
#define MAX_SSP 4
+#define MAX_SZ 1025
+#define IPC_MOD_LARGE_CONFIG_GET 3
+#define IPC_MOD_LARGE_CONFIG_SET 4
+#define MOD_BUF1 (3 * PAGE_SIZE)
struct nhlt_blob {
size_t size;
@@ -44,6 +48,7 @@ struct skl_debug {
u8 fw_read_buff[FW_REG_BUF];
struct nhlt_blob ssp_blob[2*MAX_SSP];
struct nhlt_blob dmic_blob;
+ u32 ipc_data[MAX_SZ];
};
struct nhlt_specific_cfg
@@ -126,6 +131,155 @@ static const struct file_operations nhlt_fops = {
.llseek = default_llseek,
};
+static ssize_t mod_control_read(struct file *file,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct skl_debug *d = file->private_data;
+ char *state;
+ char *buf1;
+ int ret;
+ unsigned int ofs = 0;
+
+ if (d->ipc_data[0] == 0) {
+ state = d->skl->mod_set_get_status ? "Fail\n" : "success\n";
+ return simple_read_from_buffer(user_buf, count, ppos,
+ state, strlen(state));
+ }
+
+ state = d->skl->mod_set_get_status ? "Fail\n" : "success\n";
+ buf1 = kzalloc(MOD_BUF1, GFP_KERNEL);
+ if (!buf1)
+ return -ENOMEM;
+
+ ret = snprintf(buf1, MOD_BUF1,
+ "%s\nLARGE PARAM DATA\n", state);
+
+ for (ofs = 0 ; ofs < d->ipc_data[0] ; ofs += 16) {
+ ret += snprintf(buf1 + ret, MOD_BUF1 - ret, "0x%.4x : ", ofs);
+ hex_dump_to_buffer(&(d->ipc_data[1]) + ofs, 16, 16, 4,
+ buf1 + ret, MOD_BUF1 - ret, 0);
+ ret += strlen(buf1 + ret);
+ if (MOD_BUF1 - ret > 0)
+ buf1[ret++] = '\n';
+ }
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf1, ret);
+ kfree(buf1);
+ return ret;
+
+}
+
+static ssize_t mod_control_write(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct skl_debug *d = file->private_data;
+ struct mod_set_get *mod_set_get;
+ char *buf;
+ int retval, type;
+ ssize_t written;
+ u32 size, mbsz;
+ u32 *large_data;
+ int large_param_size;
+
+ struct skl_sst *ctx = d->skl->skl_sst;
+ struct skl_ipc_large_config_msg msg;
+ struct skl_ipc_header header = {0};
+ u64 *ipc_header = (u64 *)(&header);
+
+ buf = kzalloc(MOD_BUF, GFP_KERNEL);
+ written = simple_write_to_buffer(buf, MOD_BUF, ppos,
+ user_buf, count);
+ size = written;
+ print_hex_dump(KERN_DEBUG, "buf :", DUMP_PREFIX_OFFSET, 8, 4,
+ buf, size, false);
+
+ mod_set_get = (struct mod_set_get *)buf;
+ header.primary = mod_set_get->primary;
+ header.extension = mod_set_get->extension;
+
+ mbsz = mod_set_get->size - (sizeof(u32)*2);
+ print_hex_dump(KERN_DEBUG, "header mailbox:", DUMP_PREFIX_OFFSET, 8, 4,
+ mod_set_get->mailbx, size-12, false);
+ type = ((0x1f000000) & (mod_set_get->primary))>>24;
+
+ switch (type) {
+
+ case IPC_MOD_LARGE_CONFIG_GET:
+ msg.module_id = (header.primary) & 0x0000ffff;
+ msg.instance_id = ((header.primary) & 0x00ff0000)>>16;
+ msg.large_param_id = ((header.extension) & 0x0ff00000)>>20;
+ msg.param_data_size = (header.extension) & 0x000fffff;
+ large_param_size = msg.param_data_size;
+
+ large_data = kzalloc(large_param_size, GFP_KERNEL);
+ if (!large_data)
+ return -ENOMEM;
+
+ if (mbsz)
+ retval = skl_ipc_get_large_config(&ctx->ipc, &msg,
+ large_data, &(mod_set_get->mailbx[0]), mbsz);
+ else
+ retval = skl_ipc_get_large_config(&ctx->ipc,
+ &msg, large_data, NULL, 0);
+
+ d->ipc_data[0] = msg.param_data_size;
+ memcpy(&d->ipc_data[1], large_data, msg.param_data_size);
+ kfree(large_data);
+ break;
+
+ case IPC_MOD_LARGE_CONFIG_SET:
+ d->ipc_data[0] = 0;
+ msg.module_id = (header.primary) & 0x0000ffff;
+ msg.instance_id = ((header.primary) & 0x00ff0000)>>16;
+ msg.large_param_id = ((header.extension) & 0x0ff00000)>>20;
+ msg.param_data_size = (header.extension) & 0x000fffff;
+
+ retval = skl_ipc_set_large_config(&ctx->ipc, &msg,
+ (u32 *)(&mod_set_get->mailbx));
+ d->ipc_data[0] = 0;
+ break;
+
+ default:
+ if (mbsz)
+ retval = sst_ipc_tx_message_wait(&ctx->ipc, *ipc_header,
+ mod_set_get->mailbx, mbsz, NULL, 0);
+
+ else
+ retval = sst_ipc_tx_message_wait(&ctx->ipc, *ipc_header,
+ NULL, 0, NULL, 0);
+
+ d->ipc_data[0] = 0;
+ break;
+
+ }
+ if (retval)
+ d->skl->mod_set_get_status = 1;
+ else
+ d->skl->mod_set_get_status = 0;
+
+ /* Userspace has been fiddling around behind the kernel's back */
+ add_taint(TAINT_USER, LOCKDEP_NOW_UNRELIABLE);
+ kfree(buf);
+ return written;
+}
+
+static const struct file_operations set_get_ctrl_fops = {
+ .open = simple_open,
+ .read = mod_control_read,
+ .write = mod_control_write,
+ .llseek = default_llseek,
+};
+
+static int skl_init_mod_set_get(struct skl_debug *d)
+{
+ if (!debugfs_create_file("set_get_ctrl", 0644, d->modules, d,
+ &set_get_ctrl_fops)) {
+ dev_err(d->dev, "module set get ctrl debugfs init failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf,
int max_pin, ssize_t size, bool direction)
{
@@ -437,6 +591,7 @@ struct skl_debug *skl_debugfs_init(struct skl *skl)
}
skl_init_nhlt(d);
+ skl_init_mod_set_get(d);
return d;
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h
index 9415270..c6158d3 100644
--- a/sound/soc/intel/skylake/skl-topology.h
+++ b/sound/soc/intel/skylake/skl-topology.h
@@ -506,6 +506,14 @@ static inline struct skl *get_skl_ctx(struct device *dev)
}
struct skl_probe_config;
+
+struct mod_set_get {
+ u32 size;
+ u32 primary;
+ u32 extension;
+ u32 mailbx[1024];
+};
+
int skl_tplg_be_update_params(struct snd_soc_dai *dai,
struct skl_pipe_params *params);
int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps,
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h
index 4056ea3..4c7cb27 100644
--- a/sound/soc/intel/skylake/skl.h
+++ b/sound/soc/intel/skylake/skl.h
@@ -104,6 +104,7 @@ struct skl {
struct skl_fw_config cfg;
struct snd_soc_acpi_mach *mach;
bool nhlt_override;
+ bool mod_set_get_status;
};
#define skl_to_bus(s) (&(s)->hbus)
--
https://clearlinux.org