clear-pkgs-linux-iot-lts2018/0248-ASoC-Intel-CNL-Fetch-A...

229 lines
7.0 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Anil Bhawangirkar <anil.k.bhawangirkar@intel.com>
Date: Wed, 17 Aug 2016 12:19:51 +0530
Subject: [PATCH] ASoC: Intel: CNL: Fetch ACPI data for SoundWire Master
The DSDT table contains information about the SoundWire capabalities
for Master controller and device. This patch add API's which fetch
the SoundWire capabilities for Master.
Change-Id: Iddb147a48faaf67f7fb4ee378e72858cb14e721a
Signed-off-by: Anil Bhawangirkar <anil.k.bhawangirkar@intel.com>
Signed-off-by: Guneshwor Singh <guneshwor.o.singh@intel.com>
---
include/linux/sdw/sdw_cnl.h | 8 +-
sound/soc/intel/skylake/Makefile | 4 +
sound/soc/intel/skylake/cnl-acpi.c | 160 +++++++++++++++++++++++++++++
3 files changed, 169 insertions(+), 3 deletions(-)
create mode 100644 sound/soc/intel/skylake/cnl-acpi.c
diff --git a/include/linux/sdw/sdw_cnl.h b/include/linux/sdw/sdw_cnl.h
index 6a9281c458b7..1a40244e466d 100644
--- a/include/linux/sdw/sdw_cnl.h
+++ b/include/linux/sdw/sdw_cnl.h
@@ -27,7 +27,7 @@
#define SDW_CNL_PM_TIMEOUT 3000 /* ms */
-#define CNL_SDW_MAX_PORTS 15
+#define CNL_SDW_MAX_PORTS 9
/* Maximum number hardware tries to send command if the command failed */
#define CNL_SDW_MAX_CMD_RETRIES 15
@@ -119,7 +119,9 @@ struct cnl_sdw_port *cnl_sdw_alloc_port(struct sdw_master *mstr, int ch_count,
enum sdw_data_direction direction,
enum cnl_sdw_pdi_stream_type stream_type);
void cnl_sdw_free_port(struct sdw_master *mstr, int port_num);
-
-
+int cnl_sdw_get_master_caps(struct device *dev,
+ struct sdw_master_capabilities *m_cap);
+int cnl_sdw_get_master_dev_caps(struct device *dev,
+ struct sdw_master_capabilities *m_cap, int dev_port_num);
#endif
diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile
index 9a3ddb969d4e..7b8cf119aeae 100644
--- a/sound/soc/intel/skylake/Makefile
+++ b/sound/soc/intel/skylake/Makefile
@@ -13,6 +13,10 @@ snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o \
skl-sst-cldma.o skl-sst.o bxt-sst.o cnl-sst.o \
skl-sst-utils.o skl-fwlog.o
+ifdef CONFIG_SDW
+ snd-soc-skl-ipc-objs += cnl-acpi.o
+endif
+
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o
#Skylake Clock device support
diff --git a/sound/soc/intel/skylake/cnl-acpi.c b/sound/soc/intel/skylake/cnl-acpi.c
new file mode 100644
index 000000000000..1bee574f2ab8
--- /dev/null
+++ b/sound/soc/intel/skylake/cnl-acpi.c
@@ -0,0 +1,160 @@
+/*
+ * cnl-acpi.c - Intel CNL Platform ACPI parsing
+ *
+ * Copyright (C) 2016 Intel Corp
+ *
+ * Author: Anil Bhawangirkar <anil.k.bhawangirkar@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/acpi.h>
+#include <acpi/acpixf.h>
+#include <acpi/acexcep.h>
+#include <acpi/actypes.h>
+#include <linux/sdw_bus.h>
+#include <linux/sdw/sdw_cnl.h>
+
+/*
+ * This is SoundWire device path defined for Master and Slave.
+ */
+static acpi_string path_sdw_dev[] = {"SWD0.", "SWD1.", "SWD2.", "SWD3.",
+ "SWD4.", "SWD5.", "SWD6.", "SWD7.", "SWD8."};
+#define DSDT_ACPI_PATH "\\_SB.PCI0.RP01.PXSX.HDAS.SNDW"
+#define SDW_PATH_CTRL_MAX 4
+#define SDW_PATH_DEV_MAX 9
+ACPI_MODULE_NAME("ACPI");
+
+static union acpi_object *sdw_dpn_extract_capab(union acpi_object *obj)
+{
+ union acpi_object *data, *package1, *package2;
+
+ data = &obj->package.elements[1];
+ package1 = &data->package.elements[0];
+ package2 = &package1->package.elements[1];
+ return package2;
+}
+
+static union acpi_object *sdw_scd_extract_capab(union acpi_object *obj)
+{
+ union acpi_object *data, *package1, *package2, *package3;
+
+ data = &obj->package.elements[1];
+ package1 = &data->package.elements[3];
+ package2 = &package1->package.elements[1];
+ package3 = &package2->package.elements[0];
+ return package3;
+}
+
+static union acpi_object *sdw_acpi_init_object(struct device *dev, char path[])
+{
+ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object *obj;
+ acpi_handle handle;
+ acpi_status status;
+
+ status = acpi_get_handle(NULL, DSDT_ACPI_PATH, &handle);
+ if (ACPI_FAILURE(status)) {
+ dev_err(dev, "ACPI Object evaluation is failed...\n");
+ return NULL;
+ }
+
+ status = acpi_evaluate_object(handle, path, NULL, &buf);
+ if (ACPI_FAILURE(status)) {
+ if (status != AE_NOT_FOUND)
+ ACPI_EXCEPTION((AE_INFO, status, "Invalid pathname\n"));
+ return NULL;
+ }
+ obj = buf.pointer;
+ return obj;
+}
+
+static int sdw_fill_master_dpn_caps(struct sdw_master_capabilities *map,
+ union acpi_object *obj)
+{
+ struct sdw_mstr_dpn_capabilities *dpn_cap;
+ union acpi_object *ret_data;
+
+ dpn_cap = &map->sdw_dpn_cap[0];
+ ret_data = sdw_dpn_extract_capab(obj);
+ dpn_cap->dpn_type = ret_data->integer.value;
+ return 0;
+}
+
+static int sdw_fill_master_scd_caps(struct sdw_master_capabilities *map,
+ union acpi_object *obj)
+{
+ union acpi_object *ret_data;
+
+ ret_data = sdw_scd_extract_capab(obj);
+ map->base_clk_freq = ret_data->integer.value;
+ return 0;
+}
+
+static int sdw_acpi_mstr_map_data(struct sdw_master_capabilities *mcap,
+ struct device *dev, acpi_string path_name, char path[])
+{
+ union acpi_object *obj;
+
+ obj = sdw_acpi_init_object(dev, path);
+ if (obj && (obj->type == ACPI_TYPE_PACKAGE)) {
+ if (!strcmp(path_name, "SCD"))
+ sdw_fill_master_scd_caps(mcap, obj);
+ else if (!strcmp(path_name, "DPN"))
+ sdw_fill_master_dpn_caps(mcap, obj);
+ }
+
+ kfree(obj);
+ return 0;
+}
+
+/*
+ * get the ACPI data for SoundWire Master contoller capablities
+ */
+int cnl_sdw_get_master_caps(struct device *dev,
+ struct sdw_master_capabilities *m_cap)
+{
+ acpi_string path_sdw_ctrl = {"SCD"};
+ char path[SDW_PATH_CTRL_MAX];
+
+ strcpy(path, path_sdw_ctrl);
+ sdw_acpi_mstr_map_data(m_cap, dev, path_sdw_ctrl, path);
+ if (!m_cap) {
+ dev_err(dev, "SoundWire controller mapping failed...\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cnl_sdw_get_master_caps);
+
+/*
+ * get the ACPI data for SoundWire Master devices capabilities
+ */
+int cnl_sdw_get_master_dev_caps(struct device *dev,
+ struct sdw_master_capabilities *m_cap, int dev_port_num)
+{
+ acpi_string path_sdw_dpn = {"DPN"};
+ char path[SDW_PATH_DEV_MAX];
+
+ snprintf(path, sizeof(path), "%s%s",
+ path_sdw_dev[dev_port_num], path_sdw_dpn);
+ sdw_acpi_mstr_map_data(m_cap, dev, path_sdw_dpn, path);
+ if (!m_cap) {
+ dev_err(dev, "SoundWire device mapping failed...\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cnl_sdw_get_master_dev_caps);
--
https://clearlinux.org