Browse Source

audio-lnx: Initial change for techpack of audio drivers.

Add snapshot for audio drivers for SDM targets. The code is
migrated from msm-4.9 kernel at the below cutoff -

(74ff856e8d6: "net: ipc_router: Add dynamic enable/disable
wakeup source feature")

This changes are done for new techpack addition
for audio kernel. Migrate all audio kernel drivers
to this techpack.

Change-Id: I33d580af3ba86a5cb777583efc5d4cdaf2882d93
Signed-off-by: Asish Bhattacharya <[email protected]>
Asish Bhattacharya 7 years ago
parent
commit
8e2277f79f
100 changed files with 42694 additions and 0 deletions
  1. 23 0
      Makefile
  2. 24 0
      NOTICE
  3. 7 0
      drivers/Makefile
  4. 2 0
      drivers/base/Makefile
  5. 2 0
      drivers/base/regmap/Makefile
  6. 1 0
      drivers/base/regmap/internal.h
  7. 216 0
      drivers/base/regmap/regmap-swr.c
  8. 8 0
      drivers/mfd/Makefile
  9. 253 0
      drivers/mfd/msm-cdc-pinctrl.c
  10. 456 0
      drivers/mfd/msm-cdc-supply.c
  11. 1611 0
      drivers/mfd/wcd9335-regmap.c
  12. 1325 0
      drivers/mfd/wcd9335-tables.c
  13. 1957 0
      drivers/mfd/wcd934x-regmap.c
  14. 2155 0
      drivers/mfd/wcd934x-tables.c
  15. 55 0
      drivers/mfd/wcd9xxx-core-init.c
  16. 1714 0
      drivers/mfd/wcd9xxx-core.c
  17. 853 0
      drivers/mfd/wcd9xxx-irq.c
  18. 68 0
      drivers/mfd/wcd9xxx-regmap.h
  19. 443 0
      drivers/mfd/wcd9xxx-rst.c
  20. 584 0
      drivers/mfd/wcd9xxx-slimslave.c
  21. 1198 0
      drivers/mfd/wcd9xxx-utils.c
  22. 5 0
      drivers/misc/Makefile
  23. 19 0
      drivers/misc/qcom/Kconfig
  24. 1 0
      drivers/misc/qcom/Makefile
  25. 6 0
      drivers/misc/qcom/qdsp6v2/Makefile
  26. 709 0
      drivers/misc/qcom/qdsp6v2/aac_in.c
  27. 402 0
      drivers/misc/qcom/qdsp6v2/amrnb_in.c
  28. 400 0
      drivers/misc/qcom/qdsp6v2/amrwb_in.c
  29. 474 0
      drivers/misc/qcom/qdsp6v2/audio_aac.c
  30. 435 0
      drivers/misc/qcom/qdsp6v2/audio_alac.c
  31. 226 0
      drivers/misc/qcom/qdsp6v2/audio_amrnb.c
  32. 231 0
      drivers/misc/qcom/qdsp6v2/audio_amrwb.c
  33. 397 0
      drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c
  34. 359 0
      drivers/misc/qcom/qdsp6v2/audio_ape.c
  35. 184 0
      drivers/misc/qcom/qdsp6v2/audio_evrc.c
  36. 396 0
      drivers/misc/qcom/qdsp6v2/audio_g711alaw.c
  37. 396 0
      drivers/misc/qcom/qdsp6v2/audio_g711mlaw.c
  38. 778 0
      drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c
  39. 188 0
      drivers/misc/qcom/qdsp6v2/audio_mp3.c
  40. 523 0
      drivers/misc/qcom/qdsp6v2/audio_multi_aac.c
  41. 191 0
      drivers/misc/qcom/qdsp6v2/audio_qcelp.c
  42. 954 0
      drivers/misc/qcom/qdsp6v2/audio_utils.c
  43. 114 0
      drivers/misc/qcom/qdsp6v2/audio_utils.h
  44. 2142 0
      drivers/misc/qcom/qdsp6v2/audio_utils_aio.c
  45. 232 0
      drivers/misc/qcom/qdsp6v2/audio_utils_aio.h
  46. 345 0
      drivers/misc/qcom/qdsp6v2/audio_wma.c
  47. 418 0
      drivers/misc/qcom/qdsp6v2/audio_wmapro.c
  48. 410 0
      drivers/misc/qcom/qdsp6v2/evrc_in.c
  49. 382 0
      drivers/misc/qcom/qdsp6v2/g711alaw_in.c
  50. 385 0
      drivers/misc/qcom/qdsp6v2/g711mlaw_in.c
  51. 37 0
      drivers/misc/qcom/qdsp6v2/q6audio_common.h
  52. 106 0
      drivers/misc/qcom/qdsp6v2/q6audio_v2.c
  53. 223 0
      drivers/misc/qcom/qdsp6v2/q6audio_v2_aio.c
  54. 410 0
      drivers/misc/qcom/qdsp6v2/qcelp_in.c
  55. 2 0
      drivers/misc/qcom/qdsp6v2/ultrasound/Makefile
  56. 1467 0
      drivers/misc/qcom/qdsp6v2/ultrasound/q6usm.c
  57. 130 0
      drivers/misc/qcom/qdsp6v2/ultrasound/q6usm.h
  58. 2465 0
      drivers/misc/qcom/qdsp6v2/ultrasound/usf.c
  59. 422 0
      drivers/misc/qcom/qdsp6v2/ultrasound/usfcdev.c
  60. 28 0
      drivers/misc/qcom/qdsp6v2/ultrasound/usfcdev.h
  61. 2 0
      drivers/pinctrl/Makefile
  62. 1 0
      drivers/pinctrl/core.h
  63. 1 0
      drivers/pinctrl/pinctrl-utils.h
  64. 3 0
      drivers/pinctrl/qcom/Makefile
  65. 647 0
      drivers/pinctrl/qcom/pinctrl-lpi.c
  66. 435 0
      drivers/pinctrl/qcom/pinctrl-wcd.c
  67. 5 0
      drivers/soc/Makefile
  68. 1 0
      drivers/soc/qcom/Makefile
  69. 8 0
      drivers/soc/qcom/qdsp6v2/Makefile
  70. 316 0
      drivers/soc/qcom/qdsp6v2/adsp-loader.c
  71. 976 0
      drivers/soc/qcom/qdsp6v2/apr.c
  72. 451 0
      drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
  73. 67 0
      drivers/soc/qcom/qdsp6v2/apr_v2.c
  74. 65 0
      drivers/soc/qcom/qdsp6v2/apr_v3.c
  75. 636 0
      drivers/soc/qcom/qdsp6v2/audio_notifier.c
  76. 147 0
      drivers/soc/qcom/qdsp6v2/audio_pdr.c
  77. 66 0
      drivers/soc/qcom/qdsp6v2/audio_ssr.c
  78. 280 0
      drivers/soc/qcom/qdsp6v2/cdsp-loader.c
  79. 853 0
      drivers/soc/qcom/qdsp6v2/msm_audio_ion.c
  80. 17 0
      drivers/soundwire/Kconfig
  81. 5 0
      drivers/soundwire/Makefile
  82. 1032 0
      drivers/soundwire/soundwire.c
  83. 1880 0
      drivers/soundwire/swr-wcd-ctrl.c
  84. 106 0
      drivers/soundwire/swr-wcd-ctrl.h
  85. 204 0
      drivers/soundwire/swrm_registers.h
  86. 2 0
      include/Kbuild
  87. 24 0
      include/linux/avtimer_kernel.h
  88. 49 0
      include/linux/mfd/msm-cdc-pinctrl.h
  89. 48 0
      include/linux/mfd/msm-cdc-supply.h
  90. 55 0
      include/linux/mfd/wcd9335/irq.h
  91. 1348 0
      include/linux/mfd/wcd9335/registers.h
  92. 56 0
      include/linux/mfd/wcd934x/irq.h
  93. 1848 0
      include/linux/mfd/wcd934x/registers.h
  94. 440 0
      include/linux/mfd/wcd9xxx/core.h
  95. 197 0
      include/linux/mfd/wcd9xxx/pdata.h
  96. 37 0
      include/linux/mfd/wcd9xxx/wcd9xxx-irq.h
  97. 119 0
      include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
  98. 40 0
      include/linux/mfd/wcd9xxx/wcd9xxx-utils.h
  99. 190 0
      include/linux/qdsp6v2/apr.h
  100. 90 0
      include/linux/qdsp6v2/apr_tal.h

+ 23 - 0
Makefile

@@ -0,0 +1,23 @@
+# auto-detect subdirs
+ifeq ($(CONFIG_ARCH_SDM845), y)
+include $(srctree)/techpack/audio/config/sdm845auto.conf
+export
+endif
+
+# Use USERINCLUDE when you must reference the UAPI directories only.
+USERINCLUDE     += \
+                -I$(srctree)/techpack/audio/include/uapi \
+
+# Use LINUXINCLUDE when you must reference the include/ directory.
+# Needed to be compatible with the O= option
+LINUXINCLUDE    += \
+                -I$(srctree)/techpack/audio/include/uapi \
+                -I$(srctree)/techpack/audio/include
+
+ifeq ($(CONFIG_ARCH_SDM845), y)
+LINUXINCLUDE    += \
+                -include $(srctree)/techpack/audio/config/sdm845autoconf.h
+endif
+
+obj-y           += drivers/
+obj-y           += sound/

+ 24 - 0
NOTICE

@@ -0,0 +1,24 @@
+Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 and
+only version 2 as published by the Free Software Foundation.
+
+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.
+________________________________________
+
+Copyright (C) 2008 Google, Inc.
+Copyright (C) 2008 HTC Corporation
+Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.

+ 7 - 0
drivers/Makefile

@@ -0,0 +1,7 @@
+
+obj-y		+= mfd/
+obj-y		+= misc/
+obj-y		+= soc/
+obj-y		+= soundwire/
+obj-y		+= base/
+obj-y		+= pinctrl/

+ 2 - 0
drivers/base/Makefile

@@ -0,0 +1,2 @@
+
+obj-y		+= regmap/

+ 2 - 0
drivers/base/regmap/Makefile

@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_REGMAP_SWR) += regmap-swr.o

+ 1 - 0
drivers/base/regmap/internal.h

@@ -0,0 +1 @@
+../../../../../drivers/base/regmap/internal.h

+ 216 - 0
drivers/base/regmap/regmap-swr.c

@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/device.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/soundwire/soundwire.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "internal.h"
+
+static int regmap_swr_gather_write(void *context,
+				const void *reg, size_t reg_size,
+				const void *val, size_t val_len)
+{
+	struct device *dev = context;
+	struct swr_device *swr = to_swr_device(dev);
+	struct regmap *map = dev_get_regmap(dev, NULL);
+	size_t addr_bytes;
+	size_t val_bytes;
+	int i, ret = 0;
+	u16 reg_addr = 0;
+	u8 *value;
+
+	if (map == NULL) {
+		dev_err(dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+	addr_bytes = map->format.reg_bytes;
+	if (swr == NULL) {
+		dev_err(dev, "%s: swr device is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (reg_size != addr_bytes) {
+		dev_err(dev, "%s: reg size %zd bytes not supported\n",
+			__func__, reg_size);
+		return -EINVAL;
+	}
+	reg_addr = *(u16 *)reg;
+	val_bytes = map->format.val_bytes;
+	/* val_len = val_bytes * val_count */
+	for (i = 0; i < (val_len / val_bytes); i++) {
+		value = (u8 *)val + (val_bytes * i);
+		ret = swr_write(swr, swr->dev_num, (reg_addr + i), value);
+		if (ret < 0) {
+			dev_err(dev, "%s: write reg 0x%x failed, err %d\n",
+				__func__, (reg_addr + i), ret);
+			break;
+		}
+	}
+	return ret;
+}
+
+static int regmap_swr_raw_multi_reg_write(void *context, const void *data,
+					  size_t count)
+{
+	struct device *dev = context;
+	struct swr_device *swr = to_swr_device(dev);
+	struct regmap *map = dev_get_regmap(dev, NULL);
+	size_t addr_bytes;
+	size_t val_bytes;
+	size_t pad_bytes;
+	size_t num_regs;
+	int i = 0;
+	int ret = 0;
+	u16 *reg;
+	u8 *val;
+	u8 *buf;
+
+	if (swr == NULL) {
+		dev_err(dev, "%s: swr device is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (map == NULL) {
+		dev_err(dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	addr_bytes = map->format.reg_bytes;
+	val_bytes = map->format.val_bytes;
+	pad_bytes = map->format.pad_bytes;
+
+	if (addr_bytes + val_bytes + pad_bytes == 0) {
+		dev_err(dev, "%s: sum of addr, value and pad is 0\n", __func__);
+		return -EINVAL;
+	}
+	num_regs = count / (addr_bytes + val_bytes + pad_bytes);
+
+	reg = kcalloc(num_regs, sizeof(u16), GFP_KERNEL);
+	if (!reg)
+		return -ENOMEM;
+
+	val = kcalloc(num_regs, sizeof(u8), GFP_KERNEL);
+	if (!val) {
+		ret = -ENOMEM;
+		goto mem_fail;
+	}
+
+	buf = (u8 *)data;
+	for (i = 0; i < num_regs; i++) {
+		reg[i] = *(u16 *)buf;
+		buf += (map->format.reg_bytes + map->format.pad_bytes);
+		val[i] = *buf;
+		buf += map->format.val_bytes;
+	}
+	ret = swr_bulk_write(swr, swr->dev_num, reg, val, num_regs);
+	if (ret)
+		dev_err(dev, "%s: multi reg write failed\n", __func__);
+
+	kfree(val);
+mem_fail:
+	kfree(reg);
+	return ret;
+}
+
+static int regmap_swr_write(void *context, const void *data, size_t count)
+{
+	struct device *dev = context;
+	struct regmap *map = dev_get_regmap(dev, NULL);
+	size_t addr_bytes;
+	size_t val_bytes;
+	size_t pad_bytes;
+
+	if (map == NULL) {
+		dev_err(dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+	addr_bytes = map->format.reg_bytes;
+	val_bytes = map->format.val_bytes;
+	pad_bytes = map->format.pad_bytes;
+
+	WARN_ON(count < addr_bytes);
+
+	if (count > (addr_bytes + val_bytes + pad_bytes))
+		return regmap_swr_raw_multi_reg_write(context, data, count);
+	else
+		return regmap_swr_gather_write(context, data, addr_bytes,
+					       (data + addr_bytes),
+					       (count - addr_bytes));
+}
+
+static int regmap_swr_read(void *context,
+			const void *reg, size_t reg_size,
+			void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct swr_device *swr = to_swr_device(dev);
+	struct regmap *map = dev_get_regmap(dev, NULL);
+	size_t addr_bytes;
+	int ret = 0;
+	u16 reg_addr = 0;
+
+	if (map == NULL) {
+		dev_err(dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+	addr_bytes = map->format.reg_bytes;
+	if (swr == NULL) {
+		dev_err(dev, "%s: swr is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (reg_size != addr_bytes) {
+		dev_err(dev, "%s: register size %zd bytes not supported\n",
+			__func__, reg_size);
+		return -EINVAL;
+	}
+	reg_addr = *(u16 *)reg;
+	ret = swr_read(swr, swr->dev_num, reg_addr, val, val_size);
+	if (ret < 0)
+		dev_err(dev, "%s: codec reg 0x%x read failed %d\n",
+			__func__, reg_addr, ret);
+	return ret;
+}
+
+static struct regmap_bus regmap_swr = {
+	.write = regmap_swr_write,
+	.gather_write = regmap_swr_gather_write,
+	.read = regmap_swr_read,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+struct regmap *__regmap_init_swr(struct swr_device *swr,
+				 const struct regmap_config *config,
+				 struct lock_class_key *lock_key,
+				 const char *lock_name)
+{
+	return __regmap_init(&swr->dev, &regmap_swr, &swr->dev, config,
+			   lock_key, lock_name);
+}
+EXPORT_SYMBOL(__regmap_init_swr);
+
+struct regmap *__devm_regmap_init_swr(struct swr_device *swr,
+				      const struct regmap_config *config,
+				      struct lock_class_key *lock_key,
+				      const char *lock_name)
+{
+	return __devm_regmap_init(&swr->dev, &regmap_swr, &swr->dev, config,
+				lock_key, lock_name);
+}
+EXPORT_SYMBOL(__devm_regmap_init_swr);
+
+MODULE_LICENSE("GPL v2");

+ 8 - 0
drivers/mfd/Makefile

@@ -0,0 +1,8 @@
+wcd-core-objs                  := wcd9xxx-rst.o wcd9xxx-core-init.o \
+				wcd9xxx-core.o wcd9xxx-irq.o \
+				wcd9xxx-slimslave.o wcd9xxx-utils.o \
+				wcd934x-regmap.o wcd934x-tables.o \
+				wcd9335-regmap.o wcd9335-tables.o \
+				msm-cdc-pinctrl.o msm-cdc-supply.o
+obj-$(CONFIG_WCD9XXX_CODEC_CORE) += wcd-core.o
+

+ 253 - 0
drivers/mfd/msm-cdc-pinctrl.c

@@ -0,0 +1,253 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/mfd/msm-cdc-pinctrl.h>
+
+struct msm_cdc_pinctrl_info {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pinctrl_active;
+	struct pinctrl_state *pinctrl_sleep;
+	int gpio;
+	bool state;
+};
+
+static struct msm_cdc_pinctrl_info *msm_cdc_pinctrl_get_gpiodata(
+						struct device_node *np)
+{
+	struct platform_device *pdev;
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	if (!np) {
+		pr_err("%s: device node is null\n", __func__);
+		return NULL;
+	}
+
+	pdev = of_find_device_by_node(np);
+	if (!pdev) {
+		pr_err("%s: platform device not found!\n", __func__);
+		return NULL;
+	}
+
+	gpio_data = dev_get_drvdata(&pdev->dev);
+	if (!gpio_data)
+		dev_err(&pdev->dev, "%s: cannot find cdc gpio info\n",
+			__func__);
+
+	return gpio_data;
+}
+
+/*
+ * msm_cdc_get_gpio_state: select pinctrl sleep state
+ * @np: pointer to struct device_node
+ *
+ * Returns error code for failure and GPIO value on success
+ */
+int msm_cdc_get_gpio_state(struct device_node *np)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+	int value = -EINVAL;
+
+	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
+	if (!gpio_data)
+		return value;
+
+	if (gpio_is_valid(gpio_data->gpio))
+		value = gpio_get_value_cansleep(gpio_data->gpio);
+
+	return value;
+}
+EXPORT_SYMBOL(msm_cdc_get_gpio_state);
+
+/*
+ * msm_cdc_pinctrl_select_sleep_state: select pinctrl sleep state
+ * @np: pointer to struct device_node
+ *
+ * Returns error code for failure
+ */
+int msm_cdc_pinctrl_select_sleep_state(struct device_node *np)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
+	if (!gpio_data)
+		return -EINVAL;
+
+	if (!gpio_data->pinctrl_sleep) {
+		pr_err("%s: pinctrl sleep state is null\n", __func__);
+		return -EINVAL;
+	}
+	gpio_data->state = false;
+
+	return pinctrl_select_state(gpio_data->pinctrl,
+				    gpio_data->pinctrl_sleep);
+}
+EXPORT_SYMBOL(msm_cdc_pinctrl_select_sleep_state);
+
+/*
+ * msm_cdc_pinctrl_select_active_state: select pinctrl active state
+ * @np: pointer to struct device_node
+ *
+ * Returns error code for failure
+ */
+int msm_cdc_pinctrl_select_active_state(struct device_node *np)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
+	if (!gpio_data)
+		return -EINVAL;
+
+	if (!gpio_data->pinctrl_active) {
+		pr_err("%s: pinctrl active state is null\n", __func__);
+		return -EINVAL;
+	}
+	gpio_data->state = true;
+
+	return pinctrl_select_state(gpio_data->pinctrl,
+				    gpio_data->pinctrl_active);
+}
+EXPORT_SYMBOL(msm_cdc_pinctrl_select_active_state);
+
+/*
+ * msm_cdc_pinctrl_get_state: get curren pinctrl state
+ * @np: pointer to struct device_node
+ *
+ * Returns 0 for sleep state, 1 for active state
+ */
+bool msm_cdc_pinctrl_get_state(struct device_node *np)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
+	if (!gpio_data)
+		return -EINVAL;
+
+	return gpio_data->state;
+}
+EXPORT_SYMBOL(msm_cdc_pinctrl_get_state);
+
+static int msm_cdc_pinctrl_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	gpio_data = devm_kzalloc(&pdev->dev,
+				 sizeof(struct msm_cdc_pinctrl_info),
+				 GFP_KERNEL);
+	if (!gpio_data)
+		return -ENOMEM;
+
+	gpio_data->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR_OR_NULL(gpio_data->pinctrl)) {
+		dev_err(&pdev->dev, "%s: Cannot get cdc gpio pinctrl:%ld\n",
+			__func__, PTR_ERR(gpio_data->pinctrl));
+		ret = PTR_ERR(gpio_data->pinctrl);
+		goto err_pctrl_get;
+	}
+
+	gpio_data->pinctrl_active = pinctrl_lookup_state(
+					gpio_data->pinctrl, "aud_active");
+	if (IS_ERR_OR_NULL(gpio_data->pinctrl_active)) {
+		dev_err(&pdev->dev, "%s: Cannot get aud_active pinctrl state:%ld\n",
+			__func__, PTR_ERR(gpio_data->pinctrl_active));
+		ret = PTR_ERR(gpio_data->pinctrl_active);
+		goto err_lookup_state;
+	}
+
+	gpio_data->pinctrl_sleep = pinctrl_lookup_state(
+					gpio_data->pinctrl, "aud_sleep");
+	if (IS_ERR_OR_NULL(gpio_data->pinctrl_sleep)) {
+		dev_err(&pdev->dev, "%s: Cannot get aud_sleep pinctrl state:%ld\n",
+			__func__, PTR_ERR(gpio_data->pinctrl_sleep));
+		ret = PTR_ERR(gpio_data->pinctrl_sleep);
+		goto err_lookup_state;
+	}
+	/* skip setting to sleep state for LPI_TLMM GPIOs */
+	if (!of_property_read_bool(pdev->dev.of_node, "qcom,lpi-gpios")) {
+		/* Set pinctrl state to aud_sleep by default */
+		ret = pinctrl_select_state(gpio_data->pinctrl,
+					   gpio_data->pinctrl_sleep);
+		if (ret)
+			dev_err(&pdev->dev, "%s: set cdc gpio sleep state fail: %d\n",
+				__func__, ret);
+	}
+
+	gpio_data->gpio = of_get_named_gpio(pdev->dev.of_node,
+					    "qcom,cdc-rst-n-gpio", 0);
+	if (gpio_is_valid(gpio_data->gpio)) {
+		ret = gpio_request(gpio_data->gpio, "MSM_CDC_RESET");
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to request gpio %d\n",
+				__func__, gpio_data->gpio);
+			goto err_lookup_state;
+		}
+	}
+
+	dev_set_drvdata(&pdev->dev, gpio_data);
+	return 0;
+
+err_lookup_state:
+	devm_pinctrl_put(gpio_data->pinctrl);
+err_pctrl_get:
+	devm_kfree(&pdev->dev, gpio_data);
+	return ret;
+}
+
+static int msm_cdc_pinctrl_remove(struct platform_device *pdev)
+{
+	struct msm_cdc_pinctrl_info *gpio_data;
+
+	gpio_data = dev_get_drvdata(&pdev->dev);
+
+	if (gpio_data && gpio_data->pinctrl)
+		devm_pinctrl_put(gpio_data->pinctrl);
+
+	devm_kfree(&pdev->dev, gpio_data);
+
+	return 0;
+}
+
+static const struct of_device_id msm_cdc_pinctrl_match[] = {
+	{.compatible = "qcom,msm-cdc-pinctrl"},
+	{}
+};
+
+static struct platform_driver msm_cdc_pinctrl_driver = {
+	.driver = {
+		.name = "msm-cdc-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_cdc_pinctrl_match,
+	},
+	.probe = msm_cdc_pinctrl_probe,
+	.remove = msm_cdc_pinctrl_remove,
+};
+
+int msm_cdc_pinctrl_drv_init(void)
+{
+	return platform_driver_register(&msm_cdc_pinctrl_driver);
+}
+
+void msm_cdc_pinctrl_drv_exit(void)
+{
+	platform_driver_unregister(&msm_cdc_pinctrl_driver);
+}
+MODULE_DESCRIPTION("MSM CODEC pin control platform driver");
+MODULE_LICENSE("GPL v2");

+ 456 - 0
drivers/mfd/msm-cdc-supply.c

@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/mfd/msm-cdc-supply.h>
+#include <linux/regulator/consumer.h>
+
+#define CODEC_DT_MAX_PROP_SIZE 40
+
+static int msm_cdc_dt_parse_vreg_info(struct device *dev,
+				      struct cdc_regulator *cdc_vreg,
+				      const char *name, bool is_ond)
+{
+	char prop_name[CODEC_DT_MAX_PROP_SIZE];
+	struct device_node *regulator_node = NULL;
+	const __be32 *prop;
+	int len, rc;
+	u32 prop_val;
+
+	/* Parse supply name */
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply", name);
+
+	regulator_node = of_parse_phandle(dev->of_node, prop_name, 0);
+	if (!regulator_node) {
+		dev_err(dev, "%s: Looking up %s property in node %s failed",
+			__func__, prop_name, dev->of_node->full_name);
+		rc = -EINVAL;
+		goto done;
+	}
+	cdc_vreg->name = name;
+	cdc_vreg->ondemand = is_ond;
+
+	/* Parse supply - voltage */
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-voltage", name);
+	prop = of_get_property(dev->of_node, prop_name, &len);
+	if (!prop || (len != (2 * sizeof(__be32)))) {
+		dev_err(dev, "%s: %s %s property\n", __func__,
+			prop ? "invalid format" : "no", prop_name);
+		rc = -EINVAL;
+		goto done;
+	} else {
+		cdc_vreg->min_uV = be32_to_cpup(&prop[0]);
+		cdc_vreg->max_uV = be32_to_cpup(&prop[1]);
+	}
+
+	/* Parse supply - current */
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-current", name);
+	rc = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+	if (rc) {
+		dev_err(dev, "%s: Looking up %s property in node %s failed",
+			__func__, prop_name, dev->of_node->full_name);
+		goto done;
+	}
+	cdc_vreg->optimum_uA = prop_val;
+
+	dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n",
+		 __func__, cdc_vreg->name, cdc_vreg->min_uV, cdc_vreg->max_uV,
+		 cdc_vreg->optimum_uA, cdc_vreg->ondemand);
+
+done:
+	return rc;
+}
+
+static int msm_cdc_parse_supplies(struct device *dev,
+				  struct cdc_regulator *cdc_reg,
+				  const char *sup_list, int sup_cnt,
+				  bool is_ond)
+{
+	int idx, rc = 0;
+	const char *name = NULL;
+
+	for (idx = 0; idx < sup_cnt; idx++) {
+		rc = of_property_read_string_index(dev->of_node, sup_list, idx,
+						   &name);
+		if (rc) {
+			dev_err(dev, "%s: read string %s[%d] error (%d)\n",
+				__func__, sup_list, idx, rc);
+			goto done;
+		}
+
+		dev_dbg(dev, "%s: Found cdc supply %s as part of %s\n",
+			__func__, name, sup_list);
+
+		rc = msm_cdc_dt_parse_vreg_info(dev, &cdc_reg[idx], name,
+						is_ond);
+		if (rc) {
+			dev_err(dev, "%s: parse %s vreg info failed (%d)\n",
+				__func__, name, rc);
+			goto done;
+		}
+	}
+
+done:
+	return rc;
+}
+
+static int msm_cdc_check_supply_param(struct device *dev,
+				      struct cdc_regulator *cdc_vreg,
+				      int num_supplies)
+{
+	if (!dev) {
+		pr_err("%s: device is NULL\n", __func__);
+		return -ENODEV;
+	}
+
+	if (!cdc_vreg || (num_supplies <= 0)) {
+		dev_err(dev, "%s: supply check failed: vreg: %pK, num_supplies: %d\n",
+			__func__, cdc_vreg, num_supplies);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * msm_cdc_disable_static_supplies:
+ *	Disable codec static supplies
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ *
+ * Return error code if supply disable is failed
+ */
+int msm_cdc_disable_static_supplies(struct device *dev,
+				    struct regulator_bulk_data *supplies,
+				    struct cdc_regulator *cdc_vreg,
+				    int num_supplies)
+{
+	int rc, i;
+
+	if ((!dev) || (!supplies) || (!cdc_vreg)) {
+		pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (cdc_vreg[i].ondemand)
+			continue;
+
+		rc = regulator_disable(supplies[i].consumer);
+		if (rc)
+			dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
+				__func__, supplies[i].supply, rc);
+		else
+			dev_dbg(dev, "%s: disabled regulator %s\n",
+				__func__, supplies[i].supply);
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_disable_static_supplies);
+
+/*
+ * msm_cdc_release_supplies:
+ *	Release codec power supplies
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ *
+ * Return error code if supply disable is failed
+ */
+int msm_cdc_release_supplies(struct device *dev,
+			     struct regulator_bulk_data *supplies,
+			     struct cdc_regulator *cdc_vreg,
+			     int num_supplies)
+{
+	int rc = 0;
+	int i;
+
+	if ((!dev) || (!supplies) || (!cdc_vreg)) {
+		pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	msm_cdc_disable_static_supplies(dev, supplies, cdc_vreg,
+					num_supplies);
+	for (i = 0; i < num_supplies; i++) {
+		if (regulator_count_voltages(supplies[i].consumer) < 0)
+			continue;
+
+		regulator_set_voltage(supplies[i].consumer, 0,
+				      cdc_vreg[i].max_uV);
+		regulator_set_load(supplies[i].consumer, 0);
+		devm_regulator_put(supplies[i].consumer);
+		supplies[i].consumer = NULL;
+	}
+	devm_kfree(dev, supplies);
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_release_supplies);
+
+/*
+ * msm_cdc_enable_static_supplies:
+ *	Enable codec static supplies
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ *
+ * Return error code if supply enable is failed
+ */
+int msm_cdc_enable_static_supplies(struct device *dev,
+				   struct regulator_bulk_data *supplies,
+				   struct cdc_regulator *cdc_vreg,
+				   int num_supplies)
+{
+	int rc, i;
+
+	if ((!dev) || (!supplies) || (!cdc_vreg)) {
+		pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (cdc_vreg[i].ondemand)
+			continue;
+
+		rc = regulator_enable(supplies[i].consumer);
+		if (rc) {
+			dev_err(dev, "%s: failed to enable supply %s, rc: %d\n",
+				__func__, supplies[i].supply, rc);
+			break;
+		}
+	}
+
+	while (rc && i--)
+		if (!cdc_vreg[i].ondemand)
+			regulator_disable(supplies[i].consumer);
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_enable_static_supplies);
+
+/*
+ * msm_cdc_init_supplies:
+ *	Initialize codec static supplies with regulator get
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ *
+ * Return error code if supply init is failed
+ */
+int msm_cdc_init_supplies(struct device *dev,
+			  struct regulator_bulk_data **supplies,
+			  struct cdc_regulator *cdc_vreg,
+			  int num_supplies)
+{
+	struct regulator_bulk_data *vsup;
+	int rc;
+	int i;
+
+	if (!dev || !cdc_vreg) {
+		pr_err("%s: device pointer or dce_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+
+	vsup = devm_kcalloc(dev, num_supplies,
+			    sizeof(struct regulator_bulk_data),
+			    GFP_KERNEL);
+	if (!vsup)
+		return -ENOMEM;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (!cdc_vreg[i].name) {
+			dev_err(dev, "%s: supply name not defined\n",
+				__func__);
+			rc = -EINVAL;
+			goto err_supply;
+		}
+		vsup[i].supply = cdc_vreg[i].name;
+	}
+
+	rc = devm_regulator_bulk_get(dev, num_supplies, vsup);
+	if (rc) {
+		dev_err(dev, "%s: failed to get supplies (%d)\n",
+			__func__, rc);
+		goto err_supply;
+	}
+
+	/* Set voltage and current on regulators */
+	for (i = 0; i < num_supplies; i++) {
+		if (regulator_count_voltages(vsup[i].consumer) < 0)
+			continue;
+
+		rc = regulator_set_voltage(vsup[i].consumer,
+					   cdc_vreg[i].min_uV,
+					   cdc_vreg[i].max_uV);
+		if (rc) {
+			dev_err(dev, "%s: set regulator voltage failed for %s, err:%d\n",
+				__func__, vsup[i].supply, rc);
+			goto err_set_supply;
+		}
+		rc = regulator_set_load(vsup[i].consumer,
+					cdc_vreg[i].optimum_uA);
+		if (rc < 0) {
+			dev_err(dev, "%s: set regulator optimum mode failed for %s, err:%d\n",
+				__func__, vsup[i].supply, rc);
+			goto err_set_supply;
+		}
+	}
+
+	*supplies = vsup;
+
+	return 0;
+
+err_set_supply:
+	for (i = 0; i < num_supplies; i++)
+		devm_regulator_put(vsup[i].consumer);
+err_supply:
+	devm_kfree(dev, vsup);
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_init_supplies);
+
+/*
+ * msm_cdc_get_power_supplies:
+ *	Get codec power supplies from device tree.
+ *	Allocate memory to hold regulator data for
+ *	all power supplies.
+ *
+ * @dev: pointer to codec device
+ * @cdc_vreg: pointer to codec regulator
+ * @total_num_supplies: total number of supplies read from DT
+ *
+ * Return error code if supply disable is failed
+ */
+int msm_cdc_get_power_supplies(struct device *dev,
+			       struct cdc_regulator **cdc_vreg,
+			       int *total_num_supplies)
+{
+	const char *static_prop_name = "qcom,cdc-static-supplies";
+	const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
+	const char *cp_prop_name = "qcom,cdc-cp-supplies";
+	int static_sup_cnt = 0;
+	int ond_sup_cnt = 0;
+	int cp_sup_cnt = 0;
+	int num_supplies = 0;
+	struct cdc_regulator *cdc_reg;
+	int rc;
+
+	if (!dev) {
+		pr_err("%s: device pointer is NULL\n", __func__);
+		return -EINVAL;
+	}
+	static_sup_cnt = of_property_count_strings(dev->of_node,
+						   static_prop_name);
+	if (static_sup_cnt < 0) {
+		dev_err(dev, "%s: Failed to get static supplies(%d)\n",
+			__func__, static_sup_cnt);
+		rc = static_sup_cnt;
+		goto err_supply_cnt;
+	}
+	ond_sup_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
+	if (ond_sup_cnt < 0)
+		ond_sup_cnt = 0;
+
+	cp_sup_cnt = of_property_count_strings(dev->of_node,
+					       cp_prop_name);
+	if (cp_sup_cnt < 0)
+		cp_sup_cnt = 0;
+
+	num_supplies = static_sup_cnt + ond_sup_cnt + cp_sup_cnt;
+	if (num_supplies <= 0) {
+		dev_err(dev, "%s: supply count is 0 or negative\n", __func__);
+		rc = -EINVAL;
+		goto err_supply_cnt;
+	}
+
+	cdc_reg = devm_kcalloc(dev, num_supplies,
+			       sizeof(struct cdc_regulator),
+			       GFP_KERNEL);
+	if (!cdc_reg) {
+		rc = -ENOMEM;
+		goto err_mem_alloc;
+	}
+
+	rc = msm_cdc_parse_supplies(dev, cdc_reg, static_prop_name,
+				    static_sup_cnt, false);
+	if (rc) {
+		dev_err(dev, "%s: failed to parse static supplies(%d)\n",
+				__func__, rc);
+		goto err_sup;
+	}
+
+	rc = msm_cdc_parse_supplies(dev, &cdc_reg[static_sup_cnt],
+				    ond_prop_name, ond_sup_cnt,
+				    true);
+	if (rc) {
+		dev_err(dev, "%s: failed to parse demand supplies(%d)\n",
+				__func__, rc);
+		goto err_sup;
+	}
+
+	rc = msm_cdc_parse_supplies(dev,
+				    &cdc_reg[static_sup_cnt + ond_sup_cnt],
+				    cp_prop_name, cp_sup_cnt, true);
+	if (rc) {
+		dev_err(dev, "%s: failed to parse cp supplies(%d)\n",
+				__func__, rc);
+		goto err_sup;
+	}
+
+	*cdc_vreg = cdc_reg;
+	*total_num_supplies = num_supplies;
+
+	return 0;
+
+err_sup:
+	devm_kfree(dev, cdc_reg);
+err_supply_cnt:
+err_mem_alloc:
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_get_power_supplies);

+ 1611 - 0
drivers/mfd/wcd9335-regmap.c

@@ -0,0 +1,1611 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9335/registers.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "wcd9xxx-regmap.h"
+
+static const struct reg_sequence wcd9335_1_x_defaults[] = {
+	{ WCD9335_CODEC_RPM_CLK_GATE,                     0x03,  0x00 },
+	{ WCD9335_CODEC_RPM_PWR_CPE_DRAM1_SHUTDOWN,       0x1f,  0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0,           0x00,  0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_CTL,               0x00,  0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX0_INP_CFG,          0x00,  0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX1_INP_CFG,          0x00,  0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX2_INP_CFG,          0x00,  0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX3_INP_CFG,          0x00,  0x00 },
+	{ WCD9335_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD,       0x14,  0x00 },
+	{ WCD9335_CPE_SS_SS_ERROR_INT_MASK,               0x3f,  0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_IIR_CTL_VAL,              0x00,  0x00 },
+	{ WCD9335_BIAS_VBG_FINE_ADJ,                      0x55,  0x00 },
+	{ WCD9335_SIDO_SIDO_CCL_2,                        0x6c,  0x00 },
+	{ WCD9335_SIDO_SIDO_CCL_3,                        0x2d,  0x00 },
+	{ WCD9335_SIDO_SIDO_CCL_8,                        0x6c,  0x00 },
+	{ WCD9335_SIDO_SIDO_CCL_10,                       0x6c,  0x00 },
+	{ WCD9335_SIDO_SIDO_DRIVER_2,                     0x77,  0x00 },
+	{ WCD9335_SIDO_SIDO_DRIVER_3,                     0x77,  0x00 },
+	{ WCD9335_SIDO_SIDO_TEST_2,                       0x00,  0x00 },
+	{ WCD9335_MBHC_ZDET_ANA_CTL,                      0x00,  0x00 },
+	{ WCD9335_MBHC_FSM_DEBUG,                         0xc0,  0x00 },
+	{ WCD9335_TX_1_2_ATEST_REFCTL,                    0x08,  0x00 },
+	{ WCD9335_TX_3_4_ATEST_REFCTL,                    0x08,  0x00 },
+	{ WCD9335_TX_5_6_ATEST_REFCTL,                    0x08,  0x00 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_1,                    0x67,  0x00 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_4,                    0x5f,  0x00 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_9,                    0x50,  0x00 },
+	{ WCD9335_FLYBACK_VNEG_DAC_CTRL_1,                0x65,  0x00 },
+	{ WCD9335_FLYBACK_VNEG_DAC_CTRL_4,                0x40,  0x00 },
+	{ WCD9335_RX_BIAS_HPH_PA,                         0xaa,  0x00 },
+	{ WCD9335_RX_BIAS_HPH_LOWPOWER,                   0x62,  0x00 },
+	{ WCD9335_HPH_PA_CTL2,                            0x40,  0x00 },
+	{ WCD9335_HPH_L_EN,                               0x00,  0x00 },
+	{ WCD9335_HPH_R_EN,                               0x00,  0x00 },
+	{ WCD9335_HPH_R_ATEST,                            0x50,  0x00 },
+	{ WCD9335_HPH_RDAC_LDO_CTL,                       0x00,  0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_CFG0,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_CFG1,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_SEC2,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_SEC3,                   0x0c,  0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_CFG0,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_CFG1,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_SEC2,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_SEC3,                   0x0c,  0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_CFG0,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_CFG0,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_CFG0,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_CFG0,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_CFG0,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_CFG0,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_CFG0,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_CFG1,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_CFG1,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_CFG1,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_CFG1,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_CFG1,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_CFG1,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_CFG1,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_SEC2,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_SEC2,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_SEC2,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_SEC2,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_SEC2,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_SEC2,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_SEC2,                   0x00,  0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_SEC3,                   0x0c,  0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_SEC3,                   0x0c,  0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_SEC3,                   0x0c,  0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_SEC3,                   0x0c,  0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_SEC3,                   0x0c,  0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_SEC3,                   0x0c,  0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_SEC3,                   0x0c,  0x00 },
+	{ WCD9335_CDC_COMPANDER1_CTL7,                    0x0c,  0x00 },
+	{ WCD9335_CDC_COMPANDER2_CTL7,                    0x0c,  0x00 },
+	{ WCD9335_CDC_COMPANDER3_CTL7,                    0x0c,  0x00 },
+	{ WCD9335_CDC_COMPANDER4_CTL7,                    0x0c,  0x00 },
+	{ WCD9335_CDC_COMPANDER5_CTL7,                    0x0c,  0x00 },
+	{ WCD9335_CDC_COMPANDER6_CTL7,                    0x0c,  0x00 },
+	{ WCD9335_CDC_COMPANDER7_CTL7,                    0x0c,  0x00 },
+	{ WCD9335_CDC_COMPANDER8_CTL7,                    0x0c,  0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_CFG1,                   0x04,  0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_MIX_CFG,                0x0e,  0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_SEC0,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_SEC1,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_MIX_SEC0,               0x00,  0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_CFG1,                   0x04,  0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_MIX_CFG,                0x0e,  0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_SEC0,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_SEC1,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_MIX_SEC0,               0x00,  0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_CFG1,                   0x04,  0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_MIX_CFG,                0x0e,  0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_SEC0,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_SEC1,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_MIX_SEC0,               0x00,  0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_CFG1,                   0x04,  0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_MIX_CFG,                0x0e,  0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_SEC0,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_SEC1,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_MIX_SEC0,               0x00,  0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_CFG1,                   0x04,  0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_MIX_CFG,                0x0e,  0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_SEC0,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_SEC1,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_MIX_SEC0,               0x00,  0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_CFG1,                   0x04,  0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_MIX_CFG,                0x0e,  0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_SEC0,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_SEC1,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_MIX_SEC0,               0x00,  0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_CFG1,                   0x04,  0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_MIX_CFG,                0x0e,  0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_SEC0,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_SEC1,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_MIX_SEC0,               0x00,  0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_CFG1,                   0x04,  0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_MIX_CFG,                0x0e,  0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_SEC0,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_SEC1,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_MIX_SEC0,               0x00,  0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_CFG1,                   0x04,  0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_MIX_CFG,                0x0e,  0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_SEC0,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_SEC1,                   0x00,  0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_MIX_SEC0,               0x00,  0x00 },
+	{ WCD9335_SPLINE_SRC0_CLK_RST_CTL_0,              0x00,  0x00 },
+	{ WCD9335_SPLINE_SRC1_CLK_RST_CTL_0,              0x00,  0x00 },
+	{ WCD9335_SPLINE_SRC2_CLK_RST_CTL_0,              0x00,  0x00 },
+	{ WCD9335_SPLINE_SRC3_CLK_RST_CTL_0,              0x00,  0x00 },
+	{ WCD9335_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,        0x00,  0x00 },
+	{ WCD9335_TEST_DEBUG_NPL_DLY_TEST_1,              0x00,  0x00 },
+	{ WCD9335_TEST_DEBUG_NPL_DLY_TEST_2,              0x00,  0x00 },
+};
+
+static const struct reg_sequence wcd9335_2_0_defaults[] = {
+	{ WCD9335_CODEC_RPM_CLK_GATE,                     0x07,  0x00 },
+	{ WCD9335_CODEC_RPM_PWR_CPE_DRAM1_SHUTDOWN,       0x3f,  0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0,           0x01,  0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_CTL,               0x10,  0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX0_INP_CFG,          0x08,  0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX1_INP_CFG,          0x08,  0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX2_INP_CFG,          0x08,  0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX3_INP_CFG,          0x08,  0x00 },
+	{ WCD9335_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD,       0x13,  0x00 },
+	{ WCD9335_CPE_SS_SS_ERROR_INT_MASK,               0xff,  0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_IIR_CTL_VAL,              0x40,  0x00 },
+	{ WCD9335_BIAS_VBG_FINE_ADJ,                      0xc5,  0x00 },
+	{ WCD9335_SIDO_SIDO_CCL_2,                        0x92,  0x00 },
+	{ WCD9335_SIDO_SIDO_CCL_3,                        0x35,  0x00 },
+	{ WCD9335_SIDO_SIDO_CCL_8,                        0x6e,  0x00 },
+	{ WCD9335_SIDO_SIDO_CCL_10,                       0x6e,  0x00 },
+	{ WCD9335_SIDO_SIDO_DRIVER_2,                     0x55,  0x00 },
+	{ WCD9335_SIDO_SIDO_DRIVER_3,                     0x55,  0x00 },
+	{ WCD9335_SIDO_SIDO_TEST_2,                       0x0f,  0x00 },
+	{ WCD9335_MBHC_ZDET_ANA_CTL,                      0x0f,  0x00 },
+	{ WCD9335_TX_1_2_ATEST_REFCTL,                    0x0a,  0x00 },
+	{ WCD9335_TX_3_4_ATEST_REFCTL,                    0x0a,  0x00 },
+	{ WCD9335_TX_5_6_ATEST_REFCTL,                    0x0a,  0x00 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_1,                    0xeb,  0x00 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_4,                    0x7f,  0x00 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_9,                    0x64,  0x00 },
+	{ WCD9335_FLYBACK_VNEG_DAC_CTRL_1,                0xed,  0x00 },
+	{ WCD9335_RX_BIAS_HPH_PA,                         0x9a,  0x00 },
+	{ WCD9335_RX_BIAS_HPH_LOWPOWER,                   0x82,  0x00 },
+	{ WCD9335_HPH_PA_CTL2,                            0x50,  0x00 },
+	{ WCD9335_HPH_L_EN,                               0x80,  0x00 },
+	{ WCD9335_HPH_R_EN,                               0x80,  0x00 },
+	{ WCD9335_HPH_R_ATEST,                            0x54,  0x00 },
+	{ WCD9335_HPH_RDAC_LDO_CTL,                       0x33,  0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_CFG0,                   0x10,  0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_CFG1,                   0x02,  0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_SEC2,                   0x01,  0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_SEC3,                   0x3c,  0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_CFG0,                   0x10,  0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_CFG1,                   0x02,  0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_SEC2,                   0x01,  0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_SEC3,                   0x3c,  0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_CFG0,                   0x10,  0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_CFG0,                   0x10,  0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_CFG0,                   0x10,  0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_CFG0,                   0x10,  0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_CFG0,                   0x10,  0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_CFG0,                   0x10,  0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_CFG0,                   0x10,  0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_CFG1,                   0x02,  0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_CFG1,                   0x02,  0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_CFG1,                   0x02,  0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_CFG1,                   0x02,  0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_CFG1,                   0x02,  0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_CFG1,                   0x02,  0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_CFG1,                   0x02,  0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_SEC2,                   0x01,  0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_SEC2,                   0x01,  0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_SEC2,                   0x01,  0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_SEC2,                   0x01,  0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_SEC2,                   0x01,  0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_SEC2,                   0x01,  0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_SEC2,                   0x01,  0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_SEC3,                   0x3c,  0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_SEC3,                   0x3c,  0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_SEC3,                   0x3c,  0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_SEC3,                   0x3c,  0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_SEC3,                   0x3c,  0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_SEC3,                   0x3c,  0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_SEC3,                   0x3c,  0x00 },
+	{ WCD9335_CDC_COMPANDER1_CTL7,                    0x08,  0x00 },
+	{ WCD9335_CDC_COMPANDER2_CTL7,                    0x08,  0x00 },
+	{ WCD9335_CDC_COMPANDER3_CTL7,                    0x08,  0x00 },
+	{ WCD9335_CDC_COMPANDER4_CTL7,                    0x08,  0x00 },
+	{ WCD9335_CDC_COMPANDER5_CTL7,                    0x08,  0x00 },
+	{ WCD9335_CDC_COMPANDER6_CTL7,                    0x08,  0x00 },
+	{ WCD9335_CDC_COMPANDER7_CTL7,                    0x08,  0x00 },
+	{ WCD9335_CDC_COMPANDER8_CTL7,                    0x08,  0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_CFG1,                   0x44,  0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_MIX_CFG,                0x1e,  0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_SEC0,                   0xfc,  0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_SEC1,                   0x08,  0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_MIX_SEC0,               0x08,  0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_CFG1,                   0x44,  0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_MIX_CFG,                0x1e,  0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_SEC0,                   0xfc,  0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_SEC1,                   0x08,  0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_MIX_SEC0,               0x08,  0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_CFG1,                   0x44,  0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_MIX_CFG,                0x1e,  0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_SEC0,                   0xfc,  0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_SEC1,                   0x08,  0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_MIX_SEC0,               0x08,  0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_CFG1,                   0x44,  0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_MIX_CFG,                0x1e,  0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_SEC0,                   0xfc,  0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_SEC1,                   0x08,  0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_MIX_SEC0,               0x08,  0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_CFG1,                   0x44,  0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_MIX_CFG,                0x1e,  0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_SEC0,                   0xfc,  0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_SEC1,                   0x08,  0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_MIX_SEC0,               0x08,  0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_CFG1,                   0x44,  0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_MIX_CFG,                0x1e,  0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_SEC0,                   0xfc,  0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_SEC1,                   0x08,  0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_MIX_SEC0,               0x08,  0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_CFG1,                   0x44,  0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_MIX_CFG,                0x1e,  0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_SEC0,                   0xfc,  0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_SEC1,                   0x08,  0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_MIX_SEC0,               0x08,  0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_CFG1,                   0x44,  0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_MIX_CFG,                0x1e,  0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_SEC0,                   0xfc,  0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_SEC1,                   0x08,  0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_MIX_SEC0,               0x08,  0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_CFG1,                   0x44,  0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_MIX_CFG,                0x1e,  0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_SEC0,                   0xfc,  0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_SEC1,                   0x08,  0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_MIX_SEC0,               0x08,  0x00 },
+	{ WCD9335_SPLINE_SRC0_CLK_RST_CTL_0,              0x20,  0x00 },
+	{ WCD9335_SPLINE_SRC1_CLK_RST_CTL_0,              0x20,  0x00 },
+	{ WCD9335_SPLINE_SRC2_CLK_RST_CTL_0,              0x20,  0x00 },
+	{ WCD9335_SPLINE_SRC3_CLK_RST_CTL_0,              0x20,  0x00 },
+	{ WCD9335_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,        0x0c,  0x00 },
+	{ WCD9335_TEST_DEBUG_NPL_DLY_TEST_1,              0x10,  0x00 },
+	{ WCD9335_TEST_DEBUG_NPL_DLY_TEST_2,              0x60,  0x00 },
+	{ WCD9335_DATA_HUB_NATIVE_FIFO_SYNC,              0x00,  0x00 },
+	{ WCD9335_DATA_HUB_NATIVE_FIFO_STATUS,            0x00,  0x00 },
+	{ WCD9335_CPE_SS_TX_PP_BUF_INT_PERIOD,            0x60,  0x00 },
+	{ WCD9335_CPE_SS_TX_PP_CFG,                       0x3C,  0x00 },
+	{ WCD9335_CPE_SS_SVA_CFG,                         0x00,  0x00 },
+	{ WCD9335_MBHC_FSM_STATUS,                        0x00,  0x00 },
+	{ WCD9335_FLYBACK_CTRL_1,                         0x45,  0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_SEC7,                   0x25,  0x00 },
+	{ WCD9335_SPLINE_SRC0_STATUS,                     0x00,  0x00 },
+	{ WCD9335_SPLINE_SRC1_STATUS,                     0x00,  0x00 },
+	{ WCD9335_SPLINE_SRC2_STATUS,                     0x00,  0x00 },
+	{ WCD9335_SPLINE_SRC3_STATUS,                     0x00,  0x00 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_CTL_REPEAT_PAT,    0x00,  0x00 },
+};
+
+static const struct reg_default wcd9335_defaults[] = {
+	/* Page #0 registers */
+	{ WCD9335_PAGE0_PAGE_REGISTER,                    0x00 },
+	{ WCD9335_CODEC_RPM_CLK_BYPASS,                   0x00 },
+	{ WCD9335_CODEC_RPM_CLK_MCLK_CFG,                 0x00 },
+	{ WCD9335_CODEC_RPM_RST_CTL,                      0x00 },
+	{ WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,           0x07 },
+	{ WCD9335_CODEC_RPM_PWR_CPE_DEEPSLP_1,            0x00 },
+	{ WCD9335_CODEC_RPM_PWR_CPE_DEEPSLP_2,            0x00 },
+	{ WCD9335_CODEC_RPM_PWR_CPE_DEEPSLP_3,            0x00 },
+	{ WCD9335_CODEC_RPM_PWR_CPE_IRAM_SHUTDOWN,        0x01 },
+	{ WCD9335_CODEC_RPM_PWR_CPE_DRAM0_SHUTDOWN_1,     0xff },
+	{ WCD9335_CODEC_RPM_PWR_CPE_DRAM0_SHUTDOWN_2,     0xff },
+	{ WCD9335_CODEC_RPM_INT_MASK,                     0x3f },
+	{ WCD9335_CODEC_RPM_INT_STATUS,                   0x00 },
+	{ WCD9335_CODEC_RPM_INT_CLEAR,                    0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE1,           0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE2,           0x07 },
+	{ WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE3,           0x01 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_TEST0,             0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_TEST1,             0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT0,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT1,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT2,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT3,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT4,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT5,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT6,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT7,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT8,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT9,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT10,         0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT11,         0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT12,         0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT13,         0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT14,         0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT15,         0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_EFUSE_STATUS,            0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_NONNEGO,    0x0d },
+	{ WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_1,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_2,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_3,          0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_ANA_WAIT_STATE_CTL,      0xCC },
+	{ WCD9335_CHIP_TIER_CTRL_I2C_ACTIVE,              0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC1_MON_CTL,           0x06 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC1_MON_STATUS,        0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC1_MON_CNT_MSB,       0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC1_MON_CNT_LSB,       0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC2_MON_CTL,           0x06 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC2_MON_STATUS,        0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC2_MON_CNT_MSB,       0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC2_MON_CNT_LSB,       0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC3_MON_CTL,           0x06 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC3_MON_STATUS,        0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC3_MON_CNT_MSB,       0x00 },
+	{ WCD9335_CHIP_TIER_CTRL_PROC3_MON_CNT_LSB,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX_I2S_CTL,           0x0c },
+	{ WCD9335_DATA_HUB_DATA_HUB_TX_I2S_CTL,           0x0c },
+	{ WCD9335_DATA_HUB_DATA_HUB_I2S_CLK,              0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX4_INP_CFG,          0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX5_INP_CFG,          0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX6_INP_CFG,          0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_RX7_INP_CFG,          0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX0_INP_CFG,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX1_INP_CFG,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX2_INP_CFG,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX3_INP_CFG,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX4_INP_CFG,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX5_INP_CFG,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX6_INP_CFG,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX7_INP_CFG,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX8_INP_CFG,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX9_INP_CFG,       0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX10_INP_CFG,      0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX11_INP_CFG,      0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX13_INP_CFG,      0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX14_INP_CFG,      0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_SB_TX15_INP_CFG,      0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD0_L_CFG,     0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD0_R_CFG,     0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD1_L_CFG,     0x00 },
+	{ WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD1_R_CFG,     0x00 },
+	{ WCD9335_INTR_CFG,                               0x00 },
+	{ WCD9335_INTR_CLR_COMMIT,                        0x00 },
+	{ WCD9335_INTR_PIN1_MASK0,                        0xff },
+	{ WCD9335_INTR_PIN1_MASK1,                        0xff },
+	{ WCD9335_INTR_PIN1_MASK2,                        0xff },
+	{ WCD9335_INTR_PIN1_MASK3,                        0xff },
+	{ WCD9335_INTR_PIN1_STATUS0,                      0x00 },
+	{ WCD9335_INTR_PIN1_STATUS1,                      0x00 },
+	{ WCD9335_INTR_PIN1_STATUS2,                      0x00 },
+	{ WCD9335_INTR_PIN1_STATUS3,                      0x00 },
+	{ WCD9335_INTR_PIN1_CLEAR0,                       0x00 },
+	{ WCD9335_INTR_PIN1_CLEAR1,                       0x00 },
+	{ WCD9335_INTR_PIN1_CLEAR2,                       0x00 },
+	{ WCD9335_INTR_PIN1_CLEAR3,                       0x00 },
+	{ WCD9335_INTR_PIN2_MASK0,                        0xff },
+	{ WCD9335_INTR_PIN2_MASK1,                        0xff },
+	{ WCD9335_INTR_PIN2_MASK2,                        0xff },
+	{ WCD9335_INTR_PIN2_MASK3,                        0xff },
+	{ WCD9335_INTR_PIN2_STATUS0,                      0x00 },
+	{ WCD9335_INTR_PIN2_STATUS1,                      0x00 },
+	{ WCD9335_INTR_PIN2_STATUS2,                      0x00 },
+	{ WCD9335_INTR_PIN2_STATUS3,                      0x00 },
+	{ WCD9335_INTR_PIN2_CLEAR0,                       0x00 },
+	{ WCD9335_INTR_PIN2_CLEAR1,                       0x00 },
+	{ WCD9335_INTR_PIN2_CLEAR2,                       0x00 },
+	{ WCD9335_INTR_PIN2_CLEAR3,                       0x00 },
+	{ WCD9335_INTR_LEVEL0,                            0x03 },
+	{ WCD9335_INTR_LEVEL1,                            0xe0 },
+	{ WCD9335_INTR_LEVEL2,                            0x10 },
+	{ WCD9335_INTR_LEVEL3,                            0x80 },
+	{ WCD9335_INTR_BYPASS0,                           0x00 },
+	{ WCD9335_INTR_BYPASS1,                           0x00 },
+	{ WCD9335_INTR_BYPASS2,                           0x00 },
+	{ WCD9335_INTR_BYPASS3,                           0x00 },
+	{ WCD9335_INTR_SET0,                              0x00 },
+	{ WCD9335_INTR_SET1,                              0x00 },
+	{ WCD9335_INTR_SET2,                              0x00 },
+	{ WCD9335_INTR_SET3,                              0x00 },
+	/* Page #1 registers */
+	{ WCD9335_PAGE1_PAGE_REGISTER,                    0x00 },
+	{ WCD9335_CPE_FLL_USER_CTL_0,                     0x71 },
+	{ WCD9335_CPE_FLL_USER_CTL_1,                     0x34 },
+	{ WCD9335_CPE_FLL_USER_CTL_2,                     0x0b },
+	{ WCD9335_CPE_FLL_USER_CTL_3,                     0x02 },
+	{ WCD9335_CPE_FLL_USER_CTL_4,                     0x04 },
+	{ WCD9335_CPE_FLL_USER_CTL_5,                     0x02 },
+	{ WCD9335_CPE_FLL_USER_CTL_6,                     0x64 },
+	{ WCD9335_CPE_FLL_USER_CTL_7,                     0x00 },
+	{ WCD9335_CPE_FLL_USER_CTL_8,                     0x94 },
+	{ WCD9335_CPE_FLL_USER_CTL_9,                     0x70 },
+	{ WCD9335_CPE_FLL_L_VAL_CTL_0,                    0x40 },
+	{ WCD9335_CPE_FLL_L_VAL_CTL_1,                    0x00 },
+	{ WCD9335_CPE_FLL_DSM_FRAC_CTL_0,                 0x00 },
+	{ WCD9335_CPE_FLL_DSM_FRAC_CTL_1,                 0xff },
+	{ WCD9335_CPE_FLL_CONFIG_CTL_0,                   0x6b },
+	{ WCD9335_CPE_FLL_CONFIG_CTL_1,                   0x05 },
+	{ WCD9335_CPE_FLL_CONFIG_CTL_2,                   0x08 },
+	{ WCD9335_CPE_FLL_CONFIG_CTL_3,                   0x00 },
+	{ WCD9335_CPE_FLL_CONFIG_CTL_4,                   0x10 },
+	{ WCD9335_CPE_FLL_TEST_CTL_0,                     0x00 },
+	{ WCD9335_CPE_FLL_TEST_CTL_1,                     0x00 },
+	{ WCD9335_CPE_FLL_TEST_CTL_2,                     0x00 },
+	{ WCD9335_CPE_FLL_TEST_CTL_3,                     0x00 },
+	{ WCD9335_CPE_FLL_TEST_CTL_4,                     0x00 },
+	{ WCD9335_CPE_FLL_TEST_CTL_5,                     0x00 },
+	{ WCD9335_CPE_FLL_TEST_CTL_6,                     0x00 },
+	{ WCD9335_CPE_FLL_TEST_CTL_7,                     0x33 },
+	{ WCD9335_CPE_FLL_FREQ_CTL_0,                     0x00 },
+	{ WCD9335_CPE_FLL_FREQ_CTL_1,                     0x00 },
+	{ WCD9335_CPE_FLL_FREQ_CTL_2,                     0x00 },
+	{ WCD9335_CPE_FLL_FREQ_CTL_3,                     0x00 },
+	{ WCD9335_CPE_FLL_SSC_CTL_0,                      0x00 },
+	{ WCD9335_CPE_FLL_SSC_CTL_1,                      0x00 },
+	{ WCD9335_CPE_FLL_SSC_CTL_2,                      0x00 },
+	{ WCD9335_CPE_FLL_SSC_CTL_3,                      0x00 },
+	{ WCD9335_CPE_FLL_FLL_MODE,                       0x20 },
+	{ WCD9335_CPE_FLL_STATUS_0,                       0x00 },
+	{ WCD9335_CPE_FLL_STATUS_1,                       0x00 },
+	{ WCD9335_CPE_FLL_STATUS_2,                       0x00 },
+	{ WCD9335_CPE_FLL_STATUS_3,                       0x00 },
+	{ WCD9335_I2S_FLL_USER_CTL_0,                     0x41 },
+	{ WCD9335_I2S_FLL_USER_CTL_1,                     0x94 },
+	{ WCD9335_I2S_FLL_USER_CTL_2,                     0x08 },
+	{ WCD9335_I2S_FLL_USER_CTL_3,                     0x02 },
+	{ WCD9335_I2S_FLL_USER_CTL_4,                     0x04 },
+	{ WCD9335_I2S_FLL_USER_CTL_5,                     0x02 },
+	{ WCD9335_I2S_FLL_USER_CTL_6,                     0x40 },
+	{ WCD9335_I2S_FLL_USER_CTL_7,                     0x00 },
+	{ WCD9335_I2S_FLL_USER_CTL_8,                     0x5f },
+	{ WCD9335_I2S_FLL_USER_CTL_9,                     0x02 },
+	{ WCD9335_I2S_FLL_L_VAL_CTL_0,                    0x40 },
+	{ WCD9335_I2S_FLL_L_VAL_CTL_1,                    0x00 },
+	{ WCD9335_I2S_FLL_DSM_FRAC_CTL_0,                 0x00 },
+	{ WCD9335_I2S_FLL_DSM_FRAC_CTL_1,                 0xff },
+	{ WCD9335_I2S_FLL_CONFIG_CTL_0,                   0x6b },
+	{ WCD9335_I2S_FLL_CONFIG_CTL_1,                   0x05 },
+	{ WCD9335_I2S_FLL_CONFIG_CTL_2,                   0x08 },
+	{ WCD9335_I2S_FLL_CONFIG_CTL_3,                   0x00 },
+	{ WCD9335_I2S_FLL_CONFIG_CTL_4,                   0x30 },
+	{ WCD9335_I2S_FLL_TEST_CTL_0,                     0x80 },
+	{ WCD9335_I2S_FLL_TEST_CTL_1,                     0x00 },
+	{ WCD9335_I2S_FLL_TEST_CTL_2,                     0x00 },
+	{ WCD9335_I2S_FLL_TEST_CTL_3,                     0x00 },
+	{ WCD9335_I2S_FLL_TEST_CTL_4,                     0x00 },
+	{ WCD9335_I2S_FLL_TEST_CTL_5,                     0x00 },
+	{ WCD9335_I2S_FLL_TEST_CTL_6,                     0x00 },
+	{ WCD9335_I2S_FLL_TEST_CTL_7,                     0xff },
+	{ WCD9335_I2S_FLL_FREQ_CTL_0,                     0x00 },
+	{ WCD9335_I2S_FLL_FREQ_CTL_1,                     0x00 },
+	{ WCD9335_I2S_FLL_FREQ_CTL_2,                     0x00 },
+	{ WCD9335_I2S_FLL_FREQ_CTL_3,                     0x00 },
+	{ WCD9335_I2S_FLL_SSC_CTL_0,                      0x00 },
+	{ WCD9335_I2S_FLL_SSC_CTL_1,                      0x00 },
+	{ WCD9335_I2S_FLL_SSC_CTL_2,                      0x00 },
+	{ WCD9335_I2S_FLL_SSC_CTL_3,                      0x00 },
+	{ WCD9335_I2S_FLL_FLL_MODE,                       0x00 },
+	{ WCD9335_I2S_FLL_STATUS_0,                       0x00 },
+	{ WCD9335_I2S_FLL_STATUS_1,                       0x00 },
+	{ WCD9335_I2S_FLL_STATUS_2,                       0x00 },
+	{ WCD9335_I2S_FLL_STATUS_3,                       0x00 },
+	{ WCD9335_SB_FLL_USER_CTL_0,                      0x41 },
+	{ WCD9335_SB_FLL_USER_CTL_1,                      0x94 },
+	{ WCD9335_SB_FLL_USER_CTL_2,                      0x08 },
+	{ WCD9335_SB_FLL_USER_CTL_3,                      0x02 },
+	{ WCD9335_SB_FLL_USER_CTL_4,                      0x04 },
+	{ WCD9335_SB_FLL_USER_CTL_5,                      0x02 },
+	{ WCD9335_SB_FLL_USER_CTL_6,                      0x40 },
+	{ WCD9335_SB_FLL_USER_CTL_7,                      0x00 },
+	{ WCD9335_SB_FLL_USER_CTL_8,                      0x5e },
+	{ WCD9335_SB_FLL_USER_CTL_9,                      0x01 },
+	{ WCD9335_SB_FLL_L_VAL_CTL_0,                     0x40 },
+	{ WCD9335_SB_FLL_L_VAL_CTL_1,                     0x00 },
+	{ WCD9335_SB_FLL_DSM_FRAC_CTL_0,                  0x00 },
+	{ WCD9335_SB_FLL_DSM_FRAC_CTL_1,                  0xff },
+	{ WCD9335_SB_FLL_CONFIG_CTL_0,                    0x6b },
+	{ WCD9335_SB_FLL_CONFIG_CTL_1,                    0x05 },
+	{ WCD9335_SB_FLL_CONFIG_CTL_2,                    0x08 },
+	{ WCD9335_SB_FLL_CONFIG_CTL_3,                    0x00 },
+	{ WCD9335_SB_FLL_CONFIG_CTL_4,                    0x10 },
+	{ WCD9335_SB_FLL_TEST_CTL_0,                      0x00 },
+	{ WCD9335_SB_FLL_TEST_CTL_1,                      0x00 },
+	{ WCD9335_SB_FLL_TEST_CTL_2,                      0x00 },
+	{ WCD9335_SB_FLL_TEST_CTL_3,                      0x00 },
+	{ WCD9335_SB_FLL_TEST_CTL_4,                      0x00 },
+	{ WCD9335_SB_FLL_TEST_CTL_5,                      0x00 },
+	{ WCD9335_SB_FLL_TEST_CTL_6,                      0x00 },
+	{ WCD9335_SB_FLL_TEST_CTL_7,                      0xff },
+	{ WCD9335_SB_FLL_FREQ_CTL_0,                      0x00 },
+	{ WCD9335_SB_FLL_FREQ_CTL_1,                      0x00 },
+	{ WCD9335_SB_FLL_FREQ_CTL_2,                      0x00 },
+	{ WCD9335_SB_FLL_FREQ_CTL_3,                      0x00 },
+	{ WCD9335_SB_FLL_SSC_CTL_0,                       0x00 },
+	{ WCD9335_SB_FLL_SSC_CTL_1,                       0x00 },
+	{ WCD9335_SB_FLL_SSC_CTL_2,                       0x00 },
+	{ WCD9335_SB_FLL_SSC_CTL_3,                       0x00 },
+	{ WCD9335_SB_FLL_FLL_MODE,                        0x00 },
+	{ WCD9335_SB_FLL_STATUS_0,                        0x00 },
+	{ WCD9335_SB_FLL_STATUS_1,                        0x00 },
+	{ WCD9335_SB_FLL_STATUS_2,                        0x00 },
+	{ WCD9335_SB_FLL_STATUS_3,                        0x00 },
+	/* Page #2 registers */
+	{ WCD9335_PAGE2_PAGE_REGISTER,                    0x00 },
+	{ WCD9335_CPE_SS_MEM_PTR_0,                       0x00 },
+	{ WCD9335_CPE_SS_MEM_PTR_1,                       0x00 },
+	{ WCD9335_CPE_SS_MEM_PTR_2,                       0x00 },
+	{ WCD9335_CPE_SS_MEM_CTRL,                        0x08 },
+	{ WCD9335_CPE_SS_MEM_BANK_0,                      0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_1,                      0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_2,                      0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_3,                      0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_4,                      0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_5,                      0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_6,                      0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_7,                      0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_8,                      0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_9,                      0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_10,                     0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_11,                     0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_12,                     0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_13,                     0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_14,                     0x00 },
+	{ WCD9335_CPE_SS_MEM_BANK_15,                     0x00 },
+	{ WCD9335_CPE_SS_INBOX1_TRG,                      0x00 },
+	{ WCD9335_CPE_SS_INBOX2_TRG,                      0x00 },
+	{ WCD9335_CPE_SS_INBOX1_0,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX1_1,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX1_2,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX1_3,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX1_4,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX1_5,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX1_6,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX1_7,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX1_8,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX1_9,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX1_10,                       0x00 },
+	{ WCD9335_CPE_SS_INBOX1_11,                       0x00 },
+	{ WCD9335_CPE_SS_INBOX1_12,                       0x00 },
+	{ WCD9335_CPE_SS_INBOX1_13,                       0x00 },
+	{ WCD9335_CPE_SS_INBOX1_14,                       0x00 },
+	{ WCD9335_CPE_SS_INBOX1_15,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_0,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_1,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_2,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_3,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_4,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_5,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_6,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_7,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_8,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_9,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_10,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_11,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_12,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_13,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_14,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_15,                      0x00 },
+	{ WCD9335_CPE_SS_INBOX2_0,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX2_1,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX2_2,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX2_3,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX2_4,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX2_5,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX2_6,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX2_7,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX2_8,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX2_9,                        0x00 },
+	{ WCD9335_CPE_SS_INBOX2_10,                       0x00 },
+	{ WCD9335_CPE_SS_INBOX2_11,                       0x00 },
+	{ WCD9335_CPE_SS_INBOX2_12,                       0x00 },
+	{ WCD9335_CPE_SS_INBOX2_13,                       0x00 },
+	{ WCD9335_CPE_SS_INBOX2_14,                       0x00 },
+	{ WCD9335_CPE_SS_INBOX2_15,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_0,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_1,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_2,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_3,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_4,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_5,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_6,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_7,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_8,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_9,                       0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_10,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_11,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_12,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_13,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_14,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_15,                      0x00 },
+	{ WCD9335_CPE_SS_OUTBOX1_ACK,                     0x00 },
+	{ WCD9335_CPE_SS_OUTBOX2_ACK,                     0x00 },
+	{ WCD9335_CPE_SS_EC_BUF_INT_PERIOD,               0x3c },
+	{ WCD9335_CPE_SS_US_BUF_INT_PERIOD,               0x60 },
+	{ WCD9335_CPE_SS_CFG,                             0x41 },
+	{ WCD9335_CPE_SS_US_EC_MUX_CFG,                   0x00 },
+	{ WCD9335_CPE_SS_MAD_CTL,                         0x00 },
+	{ WCD9335_CPE_SS_CPAR_CTL,                        0x00 },
+	{ WCD9335_CPE_SS_DMIC0_CTL,                       0x00 },
+	{ WCD9335_CPE_SS_DMIC1_CTL,                       0x00 },
+	{ WCD9335_CPE_SS_DMIC2_CTL,                       0x00 },
+	{ WCD9335_CPE_SS_DMIC_CFG,                        0x80 },
+	{ WCD9335_CPE_SS_CPAR_CFG,                        0x00 },
+	{ WCD9335_CPE_SS_WDOG_CFG,                        0x01 },
+	{ WCD9335_CPE_SS_BACKUP_INT,                      0x00 },
+	{ WCD9335_CPE_SS_STATUS,                          0x00 },
+	{ WCD9335_CPE_SS_CPE_OCD_CFG,                     0x00 },
+	{ WCD9335_CPE_SS_SS_ERROR_INT_STATUS,             0x00 },
+	{ WCD9335_CPE_SS_SS_ERROR_INT_CLEAR,              0x00 },
+	{ WCD9335_SOC_MAD_MAIN_CTL_1,                     0x00 },
+	{ WCD9335_SOC_MAD_MAIN_CTL_2,                     0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_CTL_1,                    0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_CTL_2,                    0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_CTL_3,                    0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_CTL_4,                    0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_CTL_5,                    0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_CTL_6,                    0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_CTL_7,                    0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_CTL_8,                    0x00 },
+	{ WCD9335_SOC_MAD_AUDIO_IIR_CTL_PTR,              0x00 },
+	{ WCD9335_SOC_MAD_ULTR_CTL_1,                     0x00 },
+	{ WCD9335_SOC_MAD_ULTR_CTL_2,                     0x00 },
+	{ WCD9335_SOC_MAD_ULTR_CTL_3,                     0x00 },
+	{ WCD9335_SOC_MAD_ULTR_CTL_4,                     0x00 },
+	{ WCD9335_SOC_MAD_ULTR_CTL_5,                     0x00 },
+	{ WCD9335_SOC_MAD_ULTR_CTL_6,                     0x00 },
+	{ WCD9335_SOC_MAD_ULTR_CTL_7,                     0x00 },
+	{ WCD9335_SOC_MAD_BEACON_CTL_1,                   0x00 },
+	{ WCD9335_SOC_MAD_BEACON_CTL_2,                   0x00 },
+	{ WCD9335_SOC_MAD_BEACON_CTL_3,                   0x00 },
+	{ WCD9335_SOC_MAD_BEACON_CTL_4,                   0x00 },
+	{ WCD9335_SOC_MAD_BEACON_CTL_5,                   0x00 },
+	{ WCD9335_SOC_MAD_BEACON_CTL_6,                   0x00 },
+	{ WCD9335_SOC_MAD_BEACON_CTL_7,                   0x00 },
+	{ WCD9335_SOC_MAD_BEACON_CTL_8,                   0x00 },
+	{ WCD9335_SOC_MAD_BEACON_IIR_CTL_PTR,             0x00 },
+	{ WCD9335_SOC_MAD_BEACON_IIR_CTL_VAL,             0x00 },
+	{ WCD9335_SOC_MAD_INP_SEL,                        0x00 },
+	/* Page #6 registers */
+	{ WCD9335_PAGE6_PAGE_REGISTER,                    0x00 },
+	{ WCD9335_ANA_BIAS,                               0x00 },
+	{ WCD9335_ANA_CLK_TOP,                            0x00 },
+	{ WCD9335_ANA_RCO,                                0x30 },
+	{ WCD9335_ANA_BUCK_VOUT_A,                        0xb4 },
+	{ WCD9335_ANA_BUCK_VOUT_D,                        0xb4 },
+	{ WCD9335_ANA_BUCK_CTL,                           0x00 },
+	{ WCD9335_ANA_BUCK_STATUS,                        0xe0 },
+	{ WCD9335_ANA_RX_SUPPLIES,                        0x00 },
+	{ WCD9335_ANA_HPH,                                0x00 },
+	{ WCD9335_ANA_EAR,                                0x00 },
+	{ WCD9335_ANA_LO_1_2,                             0x00 },
+	{ WCD9335_ANA_LO_3_4,                             0x00 },
+	{ WCD9335_ANA_MAD_SETUP,                          0x81 },
+	{ WCD9335_ANA_AMIC1,                              0x20 },
+	{ WCD9335_ANA_AMIC2,                              0x00 },
+	{ WCD9335_ANA_AMIC3,                              0x20 },
+	{ WCD9335_ANA_AMIC4,                              0x00 },
+	{ WCD9335_ANA_AMIC5,                              0x20 },
+	{ WCD9335_ANA_AMIC6,                              0x00 },
+	{ WCD9335_ANA_MBHC_MECH,                          0x39 },
+	{ WCD9335_ANA_MBHC_ELECT,                         0x08 },
+	{ WCD9335_ANA_MBHC_ZDET,                          0x00 },
+	{ WCD9335_ANA_MBHC_RESULT_1,                      0x00 },
+	{ WCD9335_ANA_MBHC_RESULT_2,                      0x00 },
+	{ WCD9335_ANA_MBHC_RESULT_3,                      0x00 },
+	{ WCD9335_ANA_MBHC_BTN0,                          0x00 },
+	{ WCD9335_ANA_MBHC_BTN1,                          0x10 },
+	{ WCD9335_ANA_MBHC_BTN2,                          0x20 },
+	{ WCD9335_ANA_MBHC_BTN3,                          0x30 },
+	{ WCD9335_ANA_MBHC_BTN4,                          0x40 },
+	{ WCD9335_ANA_MBHC_BTN5,                          0x50 },
+	{ WCD9335_ANA_MBHC_BTN6,                          0x60 },
+	{ WCD9335_ANA_MBHC_BTN7,                          0x70 },
+	{ WCD9335_ANA_MICB1,                              0x10 },
+	{ WCD9335_ANA_MICB2,                              0x10 },
+	{ WCD9335_ANA_MICB2_RAMP,                         0x00 },
+	{ WCD9335_ANA_MICB3,                              0x10 },
+	{ WCD9335_ANA_MICB4,                              0x10 },
+	{ WCD9335_ANA_VBADC,                              0x00 },
+	{ WCD9335_BIAS_CTL,                               0x28 },
+	{ WCD9335_CLOCK_TEST_CTL,                         0x00 },
+	{ WCD9335_RCO_CTRL_1,                             0x44 },
+	{ WCD9335_RCO_CTRL_2,                             0x44 },
+	{ WCD9335_RCO_CAL,                                0x00 },
+	{ WCD9335_RCO_CAL_1,                              0x00 },
+	{ WCD9335_RCO_CAL_2,                              0x00 },
+	{ WCD9335_RCO_TEST_CTRL,                          0x00 },
+	{ WCD9335_RCO_CAL_OUT_1,                          0x00 },
+	{ WCD9335_RCO_CAL_OUT_2,                          0x00 },
+	{ WCD9335_RCO_CAL_OUT_3,                          0x00 },
+	{ WCD9335_RCO_CAL_OUT_4,                          0x00 },
+	{ WCD9335_RCO_CAL_OUT_5,                          0x00 },
+	{ WCD9335_SIDO_SIDO_MODE_1,                       0x84 },
+	{ WCD9335_SIDO_SIDO_MODE_2,                       0xfe },
+	{ WCD9335_SIDO_SIDO_MODE_3,                       0xf6 },
+	{ WCD9335_SIDO_SIDO_MODE_4,                       0x56 },
+	{ WCD9335_SIDO_SIDO_VCL_1,                        0x00 },
+	{ WCD9335_SIDO_SIDO_VCL_2,                        0x6c },
+	{ WCD9335_SIDO_SIDO_VCL_3,                        0x44 },
+	{ WCD9335_SIDO_SIDO_CCL_1,                        0x57 },
+	{ WCD9335_SIDO_SIDO_CCL_4,                        0x61 },
+	{ WCD9335_SIDO_SIDO_CCL_5,                        0x6d },
+	{ WCD9335_SIDO_SIDO_CCL_6,                        0x60 },
+	{ WCD9335_SIDO_SIDO_CCL_7,                        0x6f },
+	{ WCD9335_SIDO_SIDO_CCL_9,                        0x6e },
+	{ WCD9335_SIDO_SIDO_FILTER_1,                     0x92 },
+	{ WCD9335_SIDO_SIDO_FILTER_2,                     0x54 },
+	{ WCD9335_SIDO_SIDO_DRIVER_1,                     0x77 },
+	{ WCD9335_SIDO_SIDO_CAL_CODE_EXT_1,               0x9c },
+	{ WCD9335_SIDO_SIDO_CAL_CODE_EXT_2,               0x82 },
+	{ WCD9335_SIDO_SIDO_CAL_CODE_OUT_1,               0x00 },
+	{ WCD9335_SIDO_SIDO_CAL_CODE_OUT_2,               0x00 },
+	{ WCD9335_SIDO_SIDO_TEST_1,                       0x00 },
+	{ WCD9335_MBHC_CTL_1,                             0x32 },
+	{ WCD9335_MBHC_CTL_2,                             0x01 },
+	{ WCD9335_MBHC_PLUG_DETECT_CTL,                   0x69 },
+	{ WCD9335_MBHC_ZDET_RAMP_CTL,                     0x00 },
+	{ WCD9335_MBHC_TEST_CTL,                          0x00 },
+	{ WCD9335_VBADC_SUBBLOCK_EN,                      0xfe },
+	{ WCD9335_VBADC_IBIAS_FE,                         0x54 },
+	{ WCD9335_VBADC_BIAS_ADC,                         0x51 },
+	{ WCD9335_VBADC_FE_CTRL,                          0x1c },
+	{ WCD9335_VBADC_ADC_REF,                          0x20 },
+	{ WCD9335_VBADC_ADC_IO,                           0x80 },
+	{ WCD9335_VBADC_ADC_SAR,                          0xff },
+	{ WCD9335_VBADC_DEBUG,                            0x00 },
+	{ WCD9335_VBADC_ADC_DOUTMSB,                      0x00 },
+	{ WCD9335_VBADC_ADC_DOUTLSB,                      0x00 },
+	{ WCD9335_LDOH_MODE,                              0x2b },
+	{ WCD9335_LDOH_BIAS,                              0x68 },
+	{ WCD9335_LDOH_STB_LOADS,                         0x00 },
+	{ WCD9335_LDOH_SLOWRAMP,                          0x50 },
+	{ WCD9335_MICB1_TEST_CTL_1,                       0x1a },
+	{ WCD9335_MICB1_TEST_CTL_2,                       0x18 },
+	{ WCD9335_MICB1_TEST_CTL_3,                       0xa4 },
+	{ WCD9335_MICB2_TEST_CTL_1,                       0x1a },
+	{ WCD9335_MICB2_TEST_CTL_2,                       0x18 },
+	{ WCD9335_MICB2_TEST_CTL_3,                       0x24 },
+	{ WCD9335_MICB3_TEST_CTL_1,                       0x1a },
+	{ WCD9335_MICB3_TEST_CTL_2,                       0x18 },
+	{ WCD9335_MICB3_TEST_CTL_3,                       0xa4 },
+	{ WCD9335_MICB4_TEST_CTL_1,                       0x1a },
+	{ WCD9335_MICB4_TEST_CTL_2,                       0x18 },
+	{ WCD9335_MICB4_TEST_CTL_3,                       0xa4 },
+	{ WCD9335_TX_COM_ADC_VCM,                         0x39 },
+	{ WCD9335_TX_COM_BIAS_ATEST,                      0xc0 },
+	{ WCD9335_TX_COM_ADC_INT1_IB,                     0x6f },
+	{ WCD9335_TX_COM_ADC_INT2_IB,                     0x4f },
+	{ WCD9335_TX_COM_TXFE_DIV_CTL,                    0x2e },
+	{ WCD9335_TX_COM_TXFE_DIV_START,                  0x00 },
+	{ WCD9335_TX_COM_TXFE_DIV_STOP_9P6M,              0xc7 },
+	{ WCD9335_TX_COM_TXFE_DIV_STOP_12P288M,           0xff },
+	{ WCD9335_TX_1_2_TEST_EN,                         0xcc },
+	{ WCD9335_TX_1_2_ADC_IB,                          0x09 },
+	{ WCD9335_TX_1_2_TEST_CTL,                        0x38 },
+	{ WCD9335_TX_1_2_TEST_BLK_EN,                     0xff },
+	{ WCD9335_TX_1_2_TXFE_CLKDIV,                     0x00 },
+	{ WCD9335_TX_1_2_SAR1_ERR,                        0x00 },
+	{ WCD9335_TX_1_2_SAR2_ERR,                        0x00 },
+	{ WCD9335_TX_3_4_TEST_EN,                         0xcc },
+	{ WCD9335_TX_3_4_ADC_IB,                          0x09 },
+	{ WCD9335_TX_3_4_TEST_CTL,                        0x38 },
+	{ WCD9335_TX_3_4_TEST_BLK_EN,                     0xff },
+	{ WCD9335_TX_3_4_TXFE_CLKDIV,                     0x00 },
+	{ WCD9335_TX_3_4_SAR1_ERR,                        0x00 },
+	{ WCD9335_TX_3_4_SAR2_ERR,                        0x00 },
+	{ WCD9335_TX_5_6_TEST_EN,                         0xcc },
+	{ WCD9335_TX_5_6_ADC_IB,                          0x09 },
+	{ WCD9335_TX_5_6_TEST_CTL,                        0x38 },
+	{ WCD9335_TX_5_6_TEST_BLK_EN,                     0xff },
+	{ WCD9335_TX_5_6_TXFE_CLKDIV,                     0x00 },
+	{ WCD9335_TX_5_6_SAR1_ERR,                        0x00 },
+	{ WCD9335_TX_5_6_SAR2_ERR,                        0x00 },
+	{ WCD9335_CLASSH_MODE_1,                          0x40 },
+	{ WCD9335_CLASSH_MODE_2,                          0x3a },
+	{ WCD9335_CLASSH_MODE_3,                          0x00 },
+	{ WCD9335_CLASSH_CTRL_VCL_1,                      0x70 },
+	{ WCD9335_CLASSH_CTRL_VCL_2,                      0xa2 },
+	{ WCD9335_CLASSH_CTRL_CCL_1,                      0x51 },
+	{ WCD9335_CLASSH_CTRL_CCL_2,                      0x80 },
+	{ WCD9335_CLASSH_CTRL_CCL_3,                      0x80 },
+	{ WCD9335_CLASSH_CTRL_CCL_4,                      0x51 },
+	{ WCD9335_CLASSH_CTRL_CCL_5,                      0x00 },
+	{ WCD9335_CLASSH_BUCK_TMUX_A_D,                   0x00 },
+	{ WCD9335_CLASSH_BUCK_SW_DRV_CNTL,                0x77 },
+	{ WCD9335_CLASSH_SPARE,                           0x00 },
+	{ WCD9335_FLYBACK_EN,                             0x4e },
+	{ WCD9335_FLYBACK_VNEG_CTRL_2,                    0x45 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_3,                    0x74 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_5,                    0x83 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_6,                    0x98 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_7,                    0xa9 },
+	{ WCD9335_FLYBACK_VNEG_CTRL_8,                    0x68 },
+	{ WCD9335_FLYBACK_VNEG_DAC_CTRL_2,                0x50 },
+	{ WCD9335_FLYBACK_VNEG_DAC_CTRL_3,                0xa6 },
+	{ WCD9335_FLYBACK_TEST_CTL,                       0x00 },
+	{ WCD9335_RX_AUX_SW_CTL,                          0x00 },
+	{ WCD9335_RX_PA_AUX_IN_CONN,                      0x00 },
+	{ WCD9335_RX_TIMER_DIV,                           0x74 },
+	{ WCD9335_RX_OCP_CTL,                             0x1f },
+	{ WCD9335_RX_OCP_COUNT,                           0x77 },
+	{ WCD9335_RX_BIAS_EAR_DAC,                        0xa0 },
+	{ WCD9335_RX_BIAS_EAR_AMP,                        0xaa },
+	{ WCD9335_RX_BIAS_HPH_LDO,                        0xa9 },
+	{ WCD9335_RX_BIAS_HPH_RDACBUFF_CNP2,              0x8a },
+	{ WCD9335_RX_BIAS_HPH_RDAC_LDO,                   0x88 },
+	{ WCD9335_RX_BIAS_HPH_CNP1,                       0x86 },
+	{ WCD9335_RX_BIAS_DIFFLO_PA,                      0x80 },
+	{ WCD9335_RX_BIAS_DIFFLO_REF,                     0x88 },
+	{ WCD9335_RX_BIAS_DIFFLO_LDO,                     0x88 },
+	{ WCD9335_RX_BIAS_SELO_DAC_PA,                    0xa8 },
+	{ WCD9335_RX_BIAS_BUCK_RST,                       0x08 },
+	{ WCD9335_RX_BIAS_BUCK_VREF_ERRAMP,               0x44 },
+	{ WCD9335_RX_BIAS_FLYB_ERRAMP,                    0x40 },
+	{ WCD9335_RX_BIAS_FLYB_BUFF,                      0xaa },
+	{ WCD9335_RX_BIAS_FLYB_MID_RST,                   0x44 },
+	{ WCD9335_HPH_L_STATUS,                           0x04 },
+	{ WCD9335_HPH_R_STATUS,                           0x04 },
+	{ WCD9335_HPH_CNP_EN,                             0x80 },
+	{ WCD9335_HPH_CNP_WG_CTL,                         0xda },
+	{ WCD9335_HPH_CNP_WG_TIME,                        0x15 },
+	{ WCD9335_HPH_OCP_CTL,                            0x28 },
+	{ WCD9335_HPH_AUTO_CHOP,                          0x12 },
+	{ WCD9335_HPH_CHOP_CTL,                           0x83 },
+	{ WCD9335_HPH_PA_CTL1,                            0x46 },
+	{ WCD9335_HPH_L_TEST,                             0x00 },
+	{ WCD9335_HPH_L_ATEST,                            0x50 },
+	{ WCD9335_HPH_R_TEST,                             0x00 },
+	{ WCD9335_HPH_RDAC_CLK_CTL1,                      0x99 },
+	{ WCD9335_HPH_RDAC_CLK_CTL2,                      0x9b },
+	{ WCD9335_HPH_RDAC_CHOP_CLK_LP_CTL,               0x00 },
+	{ WCD9335_HPH_REFBUFF_UHQA_CTL,                   0xa8 },
+	{ WCD9335_HPH_REFBUFF_LP_CTL,                     0x00 },
+	{ WCD9335_HPH_L_DAC_CTL,                          0x00 },
+	{ WCD9335_HPH_R_DAC_CTL,                          0x00 },
+	{ WCD9335_EAR_EN_REG,                             0x60 },
+	{ WCD9335_EAR_CMBUFF,                             0x0d },
+	{ WCD9335_EAR_ICTL,                               0x40 },
+	{ WCD9335_EAR_EN_DBG_CTL,                         0x00 },
+	{ WCD9335_EAR_CNP,                                0xe0 },
+	{ WCD9335_EAR_DAC_CTL_ATEST,                      0x00 },
+	{ WCD9335_EAR_STATUS_REG,                         0x04 },
+	{ WCD9335_EAR_OUT_SHORT,                          0x00 },
+	{ WCD9335_DIFF_LO_MISC,                           0x03 },
+	{ WCD9335_DIFF_LO_LO2_COMPANDER,                  0x00 },
+	{ WCD9335_DIFF_LO_LO1_COMPANDER,                  0x00 },
+	{ WCD9335_DIFF_LO_COMMON,                         0x40 },
+	{ WCD9335_DIFF_LO_BYPASS_EN,                      0x00 },
+	{ WCD9335_DIFF_LO_CNP,                            0x20 },
+	{ WCD9335_DIFF_LO_CORE_OUT_PROG,                  0x00 },
+	{ WCD9335_DIFF_LO_LDO_OUT_PROG,                   0x00 },
+	{ WCD9335_DIFF_LO_COM_SWCAP_REFBUF_FREQ,          0x9b },
+	{ WCD9335_DIFF_LO_COM_PA_FREQ,                    0xb0 },
+	{ WCD9335_DIFF_LO_RESERVED_REG,                   0x60 },
+	{ WCD9335_DIFF_LO_LO1_STATUS_1,                   0x00 },
+	{ WCD9335_DIFF_LO_LO1_STATUS_2,                   0x00 },
+	{ WCD9335_SE_LO_COM1,                             0x80 },
+	{ WCD9335_SE_LO_COM2,                             0x04 },
+	{ WCD9335_SE_LO_LO3_GAIN,                         0x20 },
+	{ WCD9335_SE_LO_LO3_CTRL,                         0x04 },
+	{ WCD9335_SE_LO_LO4_GAIN,                         0x20 },
+	{ WCD9335_SE_LO_LO4_CTRL,                         0x04 },
+	{ WCD9335_SE_LO_LO3_STATUS,                       0x00 },
+	{ WCD9335_SE_LO_LO4_STATUS,                       0x00 },
+	/* Page #10 registers */
+	{ WCD9335_PAGE10_PAGE_REGISTER,                   0x00 },
+	{ WCD9335_CDC_ANC0_CLK_RESET_CTL,                 0x00 },
+	{ WCD9335_CDC_ANC0_MODE_1_CTL,                    0x00 },
+	{ WCD9335_CDC_ANC0_MODE_2_CTL,                    0x00 },
+	{ WCD9335_CDC_ANC0_FF_SHIFT,                      0x00 },
+	{ WCD9335_CDC_ANC0_FB_SHIFT,                      0x00 },
+	{ WCD9335_CDC_ANC0_LPF_FF_A_CTL,                  0x00 },
+	{ WCD9335_CDC_ANC0_LPF_FF_B_CTL,                  0x00 },
+	{ WCD9335_CDC_ANC0_LPF_FB_CTL,                    0x00 },
+	{ WCD9335_CDC_ANC0_SMLPF_CTL,                     0x00 },
+	{ WCD9335_CDC_ANC0_DCFLT_SHIFT_CTL,               0x00 },
+	{ WCD9335_CDC_ANC0_IIR_ADAPT_CTL,                 0x00 },
+	{ WCD9335_CDC_ANC0_IIR_COEFF_1_CTL,               0x00 },
+	{ WCD9335_CDC_ANC0_IIR_COEFF_2_CTL,               0x00 },
+	{ WCD9335_CDC_ANC0_FF_A_GAIN_CTL,                 0x00 },
+	{ WCD9335_CDC_ANC0_FF_B_GAIN_CTL,                 0x00 },
+	{ WCD9335_CDC_ANC0_FB_GAIN_CTL,                   0x00 },
+	{ WCD9335_CDC_ANC1_CLK_RESET_CTL,                 0x00 },
+	{ WCD9335_CDC_ANC1_MODE_1_CTL,                    0x00 },
+	{ WCD9335_CDC_ANC1_MODE_2_CTL,                    0x00 },
+	{ WCD9335_CDC_ANC1_FF_SHIFT,                      0x00 },
+	{ WCD9335_CDC_ANC1_FB_SHIFT,                      0x00 },
+	{ WCD9335_CDC_ANC1_LPF_FF_A_CTL,                  0x00 },
+	{ WCD9335_CDC_ANC1_LPF_FF_B_CTL,                  0x00 },
+	{ WCD9335_CDC_ANC1_LPF_FB_CTL,                    0x00 },
+	{ WCD9335_CDC_ANC1_SMLPF_CTL,                     0x00 },
+	{ WCD9335_CDC_ANC1_DCFLT_SHIFT_CTL,               0x00 },
+	{ WCD9335_CDC_ANC1_IIR_ADAPT_CTL,                 0x00 },
+	{ WCD9335_CDC_ANC1_IIR_COEFF_1_CTL,               0x00 },
+	{ WCD9335_CDC_ANC1_IIR_COEFF_2_CTL,               0x00 },
+	{ WCD9335_CDC_ANC1_FF_A_GAIN_CTL,                 0x00 },
+	{ WCD9335_CDC_ANC1_FF_B_GAIN_CTL,                 0x00 },
+	{ WCD9335_CDC_ANC1_FB_GAIN_CTL,                   0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_TX0_TX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_192_CTL,                0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_192_CFG,                0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_SEC0,                   0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_SEC1,                   0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_SEC4,                   0x20 },
+	{ WCD9335_CDC_TX0_TX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_TX0_TX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_TX1_TX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_192_CTL,                0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_192_CFG,                0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_SEC0,                   0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_SEC1,                   0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_SEC4,                   0x20 },
+	{ WCD9335_CDC_TX1_TX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_TX1_TX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_TX2_TX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_192_CTL,                0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_192_CFG,                0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_SEC0,                   0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_SEC1,                   0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_SEC4,                   0x20 },
+	{ WCD9335_CDC_TX2_TX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_TX2_TX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_TX3_TX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_192_CTL,                0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_192_CFG,                0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_SEC0,                   0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_SEC1,                   0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_SEC4,                   0x20 },
+	{ WCD9335_CDC_TX3_TX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_TX3_TX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_TX4_TX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_192_CTL,                0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_192_CFG,                0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_SEC0,                   0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_SEC1,                   0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_SEC4,                   0x20 },
+	{ WCD9335_CDC_TX4_TX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_TX4_TX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_TX5_TX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_192_CTL,                0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_192_CFG,                0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_SEC0,                   0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_SEC1,                   0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_SEC4,                   0x20 },
+	{ WCD9335_CDC_TX5_TX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_TX5_TX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_TX6_TX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_192_CTL,                0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_192_CFG,                0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_SEC0,                   0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_SEC1,                   0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_SEC4,                   0x20 },
+	{ WCD9335_CDC_TX6_TX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_TX6_TX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_TX7_TX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_192_CTL,                0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_192_CFG,                0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_SEC0,                   0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_SEC1,                   0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_SEC4,                   0x20 },
+	{ WCD9335_CDC_TX7_TX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_TX7_TX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_TX8_TX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_192_CTL,                0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_192_CFG,                0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_SEC0,                   0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_SEC1,                   0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_SEC4,                   0x20 },
+	{ WCD9335_CDC_TX8_TX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_TX8_TX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_TX9_SPKR_PROT_PATH_CTL,             0x02 },
+	{ WCD9335_CDC_TX9_SPKR_PROT_PATH_CFG0,            0x00 },
+	{ WCD9335_CDC_TX10_SPKR_PROT_PATH_CTL,            0x02 },
+	{ WCD9335_CDC_TX10_SPKR_PROT_PATH_CFG0,           0x00 },
+	{ WCD9335_CDC_TX11_SPKR_PROT_PATH_CTL,            0x02 },
+	{ WCD9335_CDC_TX11_SPKR_PROT_PATH_CFG0,           0x00 },
+	{ WCD9335_CDC_TX12_SPKR_PROT_PATH_CTL,            0x02 },
+	{ WCD9335_CDC_TX12_SPKR_PROT_PATH_CFG0,           0x00 },
+	/* Page #11 registers */
+	{ WCD9335_PAGE11_PAGE_REGISTER,                   0x00 },
+	{ WCD9335_CDC_COMPANDER1_CTL0,                    0x60 },
+	{ WCD9335_CDC_COMPANDER1_CTL1,                    0xdb },
+	{ WCD9335_CDC_COMPANDER1_CTL2,                    0xff },
+	{ WCD9335_CDC_COMPANDER1_CTL3,                    0x35 },
+	{ WCD9335_CDC_COMPANDER1_CTL4,                    0xff },
+	{ WCD9335_CDC_COMPANDER1_CTL5,                    0x00 },
+	{ WCD9335_CDC_COMPANDER1_CTL6,                    0x01 },
+	{ WCD9335_CDC_COMPANDER2_CTL0,                    0x60 },
+	{ WCD9335_CDC_COMPANDER2_CTL1,                    0xdb },
+	{ WCD9335_CDC_COMPANDER2_CTL2,                    0xff },
+	{ WCD9335_CDC_COMPANDER2_CTL3,                    0x35 },
+	{ WCD9335_CDC_COMPANDER2_CTL4,                    0xff },
+	{ WCD9335_CDC_COMPANDER2_CTL5,                    0x00 },
+	{ WCD9335_CDC_COMPANDER2_CTL6,                    0x01 },
+	{ WCD9335_CDC_COMPANDER3_CTL0,                    0x60 },
+	{ WCD9335_CDC_COMPANDER3_CTL1,                    0xdb },
+	{ WCD9335_CDC_COMPANDER3_CTL2,                    0xff },
+	{ WCD9335_CDC_COMPANDER3_CTL3,                    0x35 },
+	{ WCD9335_CDC_COMPANDER3_CTL4,                    0xff },
+	{ WCD9335_CDC_COMPANDER3_CTL5,                    0x00 },
+	{ WCD9335_CDC_COMPANDER3_CTL6,                    0x01 },
+	{ WCD9335_CDC_COMPANDER4_CTL0,                    0x60 },
+	{ WCD9335_CDC_COMPANDER4_CTL1,                    0xdb },
+	{ WCD9335_CDC_COMPANDER4_CTL2,                    0xff },
+	{ WCD9335_CDC_COMPANDER4_CTL3,                    0x35 },
+	{ WCD9335_CDC_COMPANDER4_CTL4,                    0xff },
+	{ WCD9335_CDC_COMPANDER4_CTL5,                    0x00 },
+	{ WCD9335_CDC_COMPANDER4_CTL6,                    0x01 },
+	{ WCD9335_CDC_COMPANDER5_CTL0,                    0x60 },
+	{ WCD9335_CDC_COMPANDER5_CTL1,                    0xdb },
+	{ WCD9335_CDC_COMPANDER5_CTL2,                    0xff },
+	{ WCD9335_CDC_COMPANDER5_CTL3,                    0x35 },
+	{ WCD9335_CDC_COMPANDER5_CTL4,                    0xff },
+	{ WCD9335_CDC_COMPANDER5_CTL5,                    0x00 },
+	{ WCD9335_CDC_COMPANDER5_CTL6,                    0x01 },
+	{ WCD9335_CDC_COMPANDER6_CTL0,                    0x60 },
+	{ WCD9335_CDC_COMPANDER6_CTL1,                    0xdb },
+	{ WCD9335_CDC_COMPANDER6_CTL2,                    0xff },
+	{ WCD9335_CDC_COMPANDER6_CTL3,                    0x35 },
+	{ WCD9335_CDC_COMPANDER6_CTL4,                    0xff },
+	{ WCD9335_CDC_COMPANDER6_CTL5,                    0x00 },
+	{ WCD9335_CDC_COMPANDER6_CTL6,                    0x01 },
+	{ WCD9335_CDC_COMPANDER7_CTL0,                    0x60 },
+	{ WCD9335_CDC_COMPANDER7_CTL1,                    0xdb },
+	{ WCD9335_CDC_COMPANDER7_CTL2,                    0xff },
+	{ WCD9335_CDC_COMPANDER7_CTL3,                    0x35 },
+	{ WCD9335_CDC_COMPANDER7_CTL4,                    0xff },
+	{ WCD9335_CDC_COMPANDER7_CTL5,                    0x00 },
+	{ WCD9335_CDC_COMPANDER7_CTL6,                    0x01 },
+	{ WCD9335_CDC_COMPANDER8_CTL0,                    0x60 },
+	{ WCD9335_CDC_COMPANDER8_CTL1,                    0xdb },
+	{ WCD9335_CDC_COMPANDER8_CTL2,                    0xff },
+	{ WCD9335_CDC_COMPANDER8_CTL3,                    0x35 },
+	{ WCD9335_CDC_COMPANDER8_CTL4,                    0xff },
+	{ WCD9335_CDC_COMPANDER8_CTL5,                    0x00 },
+	{ WCD9335_CDC_COMPANDER8_CTL6,                    0x01 },
+	{ WCD9335_CDC_RX0_RX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_RX0_RX_PATH_CFG0,                   0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_CFG2,                   0x8f },
+	{ WCD9335_CDC_RX0_RX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_MIX_CTL,                0x04 },
+	{ WCD9335_CDC_RX0_RX_VOL_MIX_CTL,                 0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_SEC2,                   0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_SEC3,                   0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_SEC7,                   0x00 },
+	{ WCD9335_CDC_RX0_RX_PATH_MIX_SEC1,               0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_RX1_RX_PATH_CFG0,                   0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_CFG2,                   0x8f },
+	{ WCD9335_CDC_RX1_RX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_MIX_CTL,                0x04 },
+	{ WCD9335_CDC_RX1_RX_VOL_MIX_CTL,                 0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_SEC2,                   0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_SEC3,                   0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_SEC4,                   0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_SEC7,                   0x00 },
+	{ WCD9335_CDC_RX1_RX_PATH_MIX_SEC1,               0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_RX2_RX_PATH_CFG0,                   0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_CFG2,                   0x8f },
+	{ WCD9335_CDC_RX2_RX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_MIX_CTL,                0x04 },
+	{ WCD9335_CDC_RX2_RX_VOL_MIX_CTL,                 0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_SEC2,                   0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_SEC3,                   0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_SEC4,                   0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_SEC7,                   0x00 },
+	{ WCD9335_CDC_RX2_RX_PATH_MIX_SEC1,               0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_RX3_RX_PATH_CFG0,                   0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_CFG2,                   0x8f },
+	{ WCD9335_CDC_RX3_RX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_MIX_CTL,                0x04 },
+	{ WCD9335_CDC_RX3_RX_VOL_MIX_CTL,                 0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_SEC2,                   0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_SEC3,                   0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_SEC7,                   0x00 },
+	{ WCD9335_CDC_RX3_RX_PATH_MIX_SEC1,               0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_RX4_RX_PATH_CFG0,                   0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_CFG2,                   0x8f },
+	{ WCD9335_CDC_RX4_RX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_MIX_CTL,                0x04 },
+	{ WCD9335_CDC_RX4_RX_VOL_MIX_CTL,                 0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_SEC2,                   0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_SEC3,                   0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_SEC7,                   0x00 },
+	{ WCD9335_CDC_RX4_RX_PATH_MIX_SEC1,               0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_RX5_RX_PATH_CFG0,                   0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_CFG2,                   0x8f },
+	{ WCD9335_CDC_RX5_RX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_MIX_CTL,                0x04 },
+	{ WCD9335_CDC_RX5_RX_VOL_MIX_CTL,                 0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_SEC2,                   0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_SEC3,                   0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_SEC7,                   0x00 },
+	{ WCD9335_CDC_RX5_RX_PATH_MIX_SEC1,               0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_RX6_RX_PATH_CFG0,                   0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_CFG2,                   0x8f },
+	{ WCD9335_CDC_RX6_RX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_MIX_CTL,                0x04 },
+	{ WCD9335_CDC_RX6_RX_VOL_MIX_CTL,                 0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_SEC2,                   0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_SEC3,                   0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_SEC7,                   0x00 },
+	{ WCD9335_CDC_RX6_RX_PATH_MIX_SEC1,               0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_RX7_RX_PATH_CFG0,                   0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_CFG2,                   0x8f },
+	{ WCD9335_CDC_RX7_RX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_MIX_CTL,                0x04 },
+	{ WCD9335_CDC_RX7_RX_VOL_MIX_CTL,                 0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_SEC2,                   0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_SEC3,                   0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_SEC7,                   0x00 },
+	{ WCD9335_CDC_RX7_RX_PATH_MIX_SEC1,               0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_CTL,                    0x04 },
+	{ WCD9335_CDC_RX8_RX_PATH_CFG0,                   0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_CFG2,                   0x8f },
+	{ WCD9335_CDC_RX8_RX_VOL_CTL,                     0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_MIX_CTL,                0x04 },
+	{ WCD9335_CDC_RX8_RX_VOL_MIX_CTL,                 0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_SEC2,                   0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_SEC3,                   0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_SEC5,                   0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_SEC6,                   0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_SEC7,                   0x00 },
+	{ WCD9335_CDC_RX8_RX_PATH_MIX_SEC1,               0x00 },
+	/* Page #12 registers */
+	{ WCD9335_PAGE12_PAGE_REGISTER,                   0x00 },
+	{ WCD9335_CDC_CLSH_CRC,                           0x00 },
+	{ WCD9335_CDC_CLSH_DLY_CTRL,                      0x03 },
+	{ WCD9335_CDC_CLSH_DECAY_CTRL,                    0x02 },
+	{ WCD9335_CDC_CLSH_HPH_V_PA,                      0x1c },
+	{ WCD9335_CDC_CLSH_EAR_V_PA,                      0x39 },
+	{ WCD9335_CDC_CLSH_HPH_V_HD,                      0x0c },
+	{ WCD9335_CDC_CLSH_EAR_V_HD,                      0x0c },
+	{ WCD9335_CDC_CLSH_K1_MSB,                        0x01 },
+	{ WCD9335_CDC_CLSH_K1_LSB,                        0x00 },
+	{ WCD9335_CDC_CLSH_K2_MSB,                        0x00 },
+	{ WCD9335_CDC_CLSH_K2_LSB,                        0x80 },
+	{ WCD9335_CDC_CLSH_IDLE_CTRL,                     0x00 },
+	{ WCD9335_CDC_CLSH_IDLE_HPH,                      0x00 },
+	{ WCD9335_CDC_CLSH_IDLE_EAR,                      0x00 },
+	{ WCD9335_CDC_CLSH_TEST0,                         0x07 },
+	{ WCD9335_CDC_CLSH_TEST1,                         0x00 },
+	{ WCD9335_CDC_CLSH_OVR_VREF,                      0x00 },
+	{ WCD9335_CDC_BOOST0_BOOST_PATH_CTL,              0x00 },
+	{ WCD9335_CDC_BOOST0_BOOST_CTL,                   0xb2 },
+	{ WCD9335_CDC_BOOST0_BOOST_CFG1,                  0x00 },
+	{ WCD9335_CDC_BOOST0_BOOST_CFG2,                  0x00 },
+	{ WCD9335_CDC_BOOST1_BOOST_PATH_CTL,              0x00 },
+	{ WCD9335_CDC_BOOST1_BOOST_CTL,                   0xb2 },
+	{ WCD9335_CDC_BOOST1_BOOST_CFG1,                  0x00 },
+	{ WCD9335_CDC_BOOST1_BOOST_CFG2,                  0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_WR_DATA_0,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_WR_DATA_1,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_WR_DATA_2,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_WR_DATA_3,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_WR_ADDR_0,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_WR_ADDR_1,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_WR_ADDR_2,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_WR_ADDR_3,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_RD_ADDR_0,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_RD_ADDR_1,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_RD_ADDR_2,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_RD_ADDR_3,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_RD_DATA_0,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_RD_DATA_1,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_RD_DATA_2,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_RD_DATA_3,               0x00 },
+	{ WCD9335_SWR_AHB_BRIDGE_ACCESS_CFG,              0x0f },
+	{ WCD9335_SWR_AHB_BRIDGE_ACCESS_STATUS,           0x03 },
+	{ WCD9335_CDC_VBAT_VBAT_PATH_CTL,                 0x00 },
+	{ WCD9335_CDC_VBAT_VBAT_CFG,                      0x0a },
+	{ WCD9335_CDC_VBAT_VBAT_ADC_CAL1,                 0x00 },
+	{ WCD9335_CDC_VBAT_VBAT_ADC_CAL2,                 0x00 },
+	{ WCD9335_CDC_VBAT_VBAT_ADC_CAL3,                 0x04 },
+	{ WCD9335_CDC_VBAT_VBAT_PK_EST1,                  0xe0 },
+	{ WCD9335_CDC_VBAT_VBAT_PK_EST2,                  0x01 },
+	{ WCD9335_CDC_VBAT_VBAT_PK_EST3,                  0x40 },
+	{ WCD9335_CDC_VBAT_VBAT_RF_PROC1,                 0x2a },
+	{ WCD9335_CDC_VBAT_VBAT_RF_PROC2,                 0x86 },
+	{ WCD9335_CDC_VBAT_VBAT_TAC1,                     0x70 },
+	{ WCD9335_CDC_VBAT_VBAT_TAC2,                     0x18 },
+	{ WCD9335_CDC_VBAT_VBAT_TAC3,                     0x18 },
+	{ WCD9335_CDC_VBAT_VBAT_TAC4,                     0x03 },
+	{ WCD9335_CDC_VBAT_VBAT_GAIN_UPD1,                0x01 },
+	{ WCD9335_CDC_VBAT_VBAT_GAIN_UPD2,                0x00 },
+	{ WCD9335_CDC_VBAT_VBAT_GAIN_UPD3,                0x64 },
+	{ WCD9335_CDC_VBAT_VBAT_GAIN_UPD4,                0x01 },
+	{ WCD9335_CDC_VBAT_VBAT_DEBUG1,                   0x00 },
+	{ WCD9335_CDC_VBAT_VBAT_GAIN_UPD_MON,             0x00 },
+	{ WCD9335_CDC_VBAT_VBAT_GAIN_MON_VAL,             0x00 },
+	{ WCD9335_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL,      0x04 },
+	{ WCD9335_CDC_SIDETONE_SRC0_ST_SRC_PATH_CFG1,     0x00 },
+	{ WCD9335_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL,      0x04 },
+	{ WCD9335_CDC_SIDETONE_SRC1_ST_SRC_PATH_CFG1,     0x00 },
+	/* Page #13 registers */
+	{ WCD9335_PAGE13_PAGE_REGISTER,                   0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG0,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG1,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG0,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG1,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG0,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG1,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG0,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG1,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG0,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG1,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG0,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG1,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG0,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG1,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG0,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG1,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG0,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG1,            0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG0,             0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG1,             0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG2,             0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG3,             0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG4,             0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0,       0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1,       0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_ANC_CFG0,                0x00 },
+	{ WCD9335_CDC_RX_INP_MUX_SPLINE_SRC_CFG0,         0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG0,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG1,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG0,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG1,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG0,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG1,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG0,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG1,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX4_CFG0,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX5_CFG0,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX6_CFG0,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX7_CFG0,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX8_CFG0,           0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX10_CFG0,          0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX11_CFG0,          0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX12_CFG0,          0x00 },
+	{ WCD9335_CDC_TX_INP_MUX_ADC_MUX13_CFG0,          0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0, 0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1, 0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2, 0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3, 0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0, 0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1, 0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2, 0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3, 0x00 },
+	{ WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0,              0x00 },
+	{ WCD9335_CDC_IF_ROUTER_TX_MUX_CFG1,              0x00 },
+	{ WCD9335_CDC_IF_ROUTER_TX_MUX_CFG2,              0x00 },
+	{ WCD9335_CDC_IF_ROUTER_TX_MUX_CFG3,              0x00 },
+	{ WCD9335_CDC_CLK_RST_CTRL_MCLK_CONTROL,          0x00 },
+	{ WCD9335_CDC_CLK_RST_CTRL_SWR_CONTROL,           0x00 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_CTL,               0x08 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_POLL_PERIOD0,      0x00 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_POLL_PERIOD1,      0x4b },
+	{ WCD9335_CDC_PROX_DETECT_PROX_SIG_PATTERN_LSB,   0x00 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_SIG_PATTERN_MSB,   0x00 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_STATUS,            0x00 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_TEST_CTRL,         0x00 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB,     0x00 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB,     0x00 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB_RD,  0x00 },
+	{ WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB_RD,  0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_PATH_CTL,         0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B5_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B6_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B7_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B8_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_CTL,              0x40 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL,   0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_PATH_CTL,         0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B5_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B6_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B7_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B8_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_CTL,              0x40 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL,   0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_COEF_B1_CTL,      0x00 },
+	{ WCD9335_CDC_SIDETONE_IIR1_IIR_COEF_B2_CTL,      0x00 },
+	{ WCD9335_CDC_TOP_TOP_CFG0,                       0x00 },
+	{ WCD9335_CDC_TOP_TOP_CFG1,                       0x00 },
+	{ WCD9335_CDC_TOP_TOP_CFG2,                       0x00 },
+	{ WCD9335_CDC_TOP_TOP_CFG3,                       0x18 },
+	{ WCD9335_CDC_TOP_TOP_CFG4,                       0x00 },
+	{ WCD9335_CDC_TOP_TOP_CFG5,                       0x00 },
+	{ WCD9335_CDC_TOP_TOP_CFG6,                       0x00 },
+	{ WCD9335_CDC_TOP_TOP_CFG7,                       0x00 },
+	{ WCD9335_CDC_TOP_HPHL_COMP_WR_LSB,               0x00 },
+	{ WCD9335_CDC_TOP_HPHL_COMP_WR_MSB,               0x00 },
+	{ WCD9335_CDC_TOP_HPHL_COMP_LUT,                  0x00 },
+	{ WCD9335_CDC_TOP_HPHL_COMP_RD_LSB,               0x00 },
+	{ WCD9335_CDC_TOP_HPHL_COMP_RD_MSB,               0x00 },
+	{ WCD9335_CDC_TOP_HPHR_COMP_WR_LSB,               0x00 },
+	{ WCD9335_CDC_TOP_HPHR_COMP_WR_MSB,               0x00 },
+	{ WCD9335_CDC_TOP_HPHR_COMP_LUT,                  0x00 },
+	{ WCD9335_CDC_TOP_HPHR_COMP_RD_LSB,               0x00 },
+	{ WCD9335_CDC_TOP_HPHR_COMP_RD_MSB,               0x00 },
+	{ WCD9335_CDC_TOP_DIFFL_COMP_WR_LSB,              0x00 },
+	{ WCD9335_CDC_TOP_DIFFL_COMP_WR_MSB,              0x00 },
+	{ WCD9335_CDC_TOP_DIFFL_COMP_LUT,                 0x00 },
+	{ WCD9335_CDC_TOP_DIFFL_COMP_RD_LSB,              0x00 },
+	{ WCD9335_CDC_TOP_DIFFL_COMP_RD_MSB,              0x00 },
+	{ WCD9335_CDC_TOP_DIFFR_COMP_WR_LSB,              0x00 },
+	{ WCD9335_CDC_TOP_DIFFR_COMP_WR_MSB,              0x00 },
+	{ WCD9335_CDC_TOP_DIFFR_COMP_LUT,                 0x00 },
+	{ WCD9335_CDC_TOP_DIFFR_COMP_RD_LSB,              0x00 },
+	{ WCD9335_CDC_TOP_DIFFR_COMP_RD_MSB,              0x00 },
+	/* Page #0x80 registers */
+	{ WCD9335_PAGE80_PAGE_REGISTER,                   0x00 },
+	{ WCD9335_TLMM_BIST_MODE_PINCFG,                  0x00 },
+	{ WCD9335_TLMM_RF_PA_ON_PINCFG,                   0x00 },
+	{ WCD9335_TLMM_INTR1_PINCFG,                      0x00 },
+	{ WCD9335_TLMM_INTR2_PINCFG,                      0x00 },
+	{ WCD9335_TLMM_SWR_DATA_PINCFG,                   0x00 },
+	{ WCD9335_TLMM_SWR_CLK_PINCFG,                    0x00 },
+	{ WCD9335_TLMM_SLIMBUS_DATA2_PINCFG,              0x00 },
+	{ WCD9335_TLMM_I2C_CLK_PINCFG,                    0x00 },
+	{ WCD9335_TLMM_I2C_DATA_PINCFG,                   0x00 },
+	{ WCD9335_TLMM_I2S_RX_SD0_PINCFG,                 0x00 },
+	{ WCD9335_TLMM_I2S_RX_SD1_PINCFG,                 0x00 },
+	{ WCD9335_TLMM_I2S_RX_SCK_PINCFG,                 0x00 },
+	{ WCD9335_TLMM_I2S_RX_WS_PINCFG,                  0x00 },
+	{ WCD9335_TLMM_I2S_TX_SD0_PINCFG,                 0x00 },
+	{ WCD9335_TLMM_I2S_TX_SD1_PINCFG,                 0x00 },
+	{ WCD9335_TLMM_I2S_TX_SCK_PINCFG,                 0x00 },
+	{ WCD9335_TLMM_I2S_TX_WS_PINCFG,                  0x00 },
+	{ WCD9335_TLMM_DMIC1_CLK_PINCFG,                  0x00 },
+	{ WCD9335_TLMM_DMIC1_DATA_PINCFG,                 0x00 },
+	{ WCD9335_TLMM_DMIC2_CLK_PINCFG,                  0x00 },
+	{ WCD9335_TLMM_DMIC2_DATA_PINCFG,                 0x00 },
+	{ WCD9335_TLMM_DMIC3_CLK_PINCFG,                  0x00 },
+	{ WCD9335_TLMM_DMIC3_DATA_PINCFG,                 0x00 },
+	{ WCD9335_TLMM_JTDI_PINCFG,                       0x00 },
+	{ WCD9335_TLMM_JTDO_PINCFG,                       0x00 },
+	{ WCD9335_TLMM_JTMS_PINCFG,                       0x00 },
+	{ WCD9335_TLMM_JTCK_PINCFG,                       0x00 },
+	{ WCD9335_TLMM_JTRST_PINCFG,                      0x00 },
+	{ WCD9335_TEST_DEBUG_PIN_CTL_OE_0,                0x00 },
+	{ WCD9335_TEST_DEBUG_PIN_CTL_OE_1,                0x00 },
+	{ WCD9335_TEST_DEBUG_PIN_CTL_OE_2,                0x00 },
+	{ WCD9335_TEST_DEBUG_PIN_CTL_OE_3,                0x00 },
+	{ WCD9335_TEST_DEBUG_PIN_CTL_DATA_0,              0x00 },
+	{ WCD9335_TEST_DEBUG_PIN_CTL_DATA_1,              0x00 },
+	{ WCD9335_TEST_DEBUG_PIN_CTL_DATA_2,              0x00 },
+	{ WCD9335_TEST_DEBUG_PIN_CTL_DATA_3,              0x00 },
+	{ WCD9335_TEST_DEBUG_PAD_DRVCTL,                  0x00 },
+	{ WCD9335_TEST_DEBUG_PIN_STATUS,                  0x00 },
+	{ WCD9335_TEST_DEBUG_MEM_CTRL,                    0x00 },
+	{ WCD9335_TEST_DEBUG_DEBUG_BUS_SEL,               0x00 },
+	{ WCD9335_TEST_DEBUG_DEBUG_JTAG,                  0x00 },
+	{ WCD9335_TEST_DEBUG_DEBUG_EN_1,                  0x00 },
+	{ WCD9335_TEST_DEBUG_DEBUG_EN_2,                  0x00 },
+	{ WCD9335_TEST_DEBUG_DEBUG_EN_3,                  0x00 },
+};
+
+/*
+ * wcd9335_regmap_register_patch: Update register defaults based on version
+ * @regmap: handle to wcd9xxx regmap
+ * @version: wcd9335 version
+ *
+ * Returns error code in case of failure or 0 for success
+ */
+int wcd9335_regmap_register_patch(struct regmap *regmap, int version)
+{
+	int rc;
+
+	if (!regmap) {
+		pr_err("%s: regmap struct is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (version) {
+	case TASHA_VERSION_1_0:
+	case TASHA_VERSION_1_1:
+		regcache_cache_only(regmap, true);
+		rc = regmap_multi_reg_write(regmap, wcd9335_1_x_defaults,
+					    ARRAY_SIZE(wcd9335_1_x_defaults));
+		regcache_cache_only(regmap, false);
+		break;
+	case TASHA_VERSION_2_0:
+		regcache_cache_only(regmap, true);
+		rc = regmap_multi_reg_write(regmap, wcd9335_2_0_defaults,
+					    ARRAY_SIZE(wcd9335_2_0_defaults));
+		regcache_cache_only(regmap, false);
+		break;
+	default:
+		pr_err("%s: unknown version: %d\n", __func__, version);
+		rc = -EINVAL;
+		break;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(wcd9335_regmap_register_patch);
+
+static bool wcd9335_is_readable_register(struct device *dev, unsigned int reg)
+{
+	u8 pg_num, reg_offset;
+	const u8 *reg_tbl = NULL;
+
+	/*
+	 * Get the page number from MSB of codec register. If its 0x80, assign
+	 * the corresponding page index PAGE_0x80.
+	 */
+	pg_num = reg >> 0x8;
+	if (pg_num == 0x80)
+		pg_num = PAGE_0X80;
+	else if (pg_num >= 0xE)
+		return false;
+
+	reg_tbl = wcd9335_reg[pg_num];
+	reg_offset = reg & 0xFF;
+
+	if (reg_tbl)
+		return reg_tbl[reg_offset];
+	else
+		return false;
+}
+
+static bool wcd9335_is_volatile_register(struct device *dev, unsigned int reg)
+{
+	/*
+	 * registers from 0x000 to 0x0FF are volatile because
+	 * this space contains registers related to interrupt
+	 * status, mask etc
+	 */
+	if (reg < 0x100)
+		return true;
+
+	/* IIR Coeff registers are not cacheable */
+	if ((reg >= WCD9335_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL) &&
+	    (reg <= WCD9335_CDC_SIDETONE_IIR1_IIR_COEF_B2_CTL))
+		return true;
+
+	if ((reg >= WCD9335_CDC_ANC0_IIR_COEFF_1_CTL) &&
+	    (reg <= WCD9335_CDC_ANC0_FB_GAIN_CTL))
+		return true;
+
+	if ((reg >= WCD9335_CDC_ANC1_IIR_COEFF_1_CTL) &&
+	    (reg <= WCD9335_CDC_ANC1_FB_GAIN_CTL))
+		return true;
+	/*
+	 * CPE inbox and outbox registers are volatile
+	 * since they can be updated in the codec hardware
+	 * to indicate CPE status
+	 */
+	if (reg >= WCD9335_CPE_SS_MEM_PTR_0 &&
+	    reg <= WCD9335_CPE_SS_OUTBOX2_ACK)
+		return true;
+
+	if (reg >= WCD9335_RCO_CAL_OUT_1 &&
+	    reg <= WCD9335_RCO_CAL_OUT_5)
+		return true;
+
+	switch (reg) {
+	case WCD9335_CPE_SS_INBOX1_TRG:
+	case WCD9335_CPE_SS_INBOX2_TRG:
+	case WCD9335_SWR_AHB_BRIDGE_WR_DATA_0:
+	case WCD9335_SWR_AHB_BRIDGE_WR_DATA_1:
+	case WCD9335_SWR_AHB_BRIDGE_WR_DATA_2:
+	case WCD9335_SWR_AHB_BRIDGE_WR_DATA_3:
+	case WCD9335_SWR_AHB_BRIDGE_WR_ADDR_0:
+	case WCD9335_SWR_AHB_BRIDGE_WR_ADDR_1:
+	case WCD9335_SWR_AHB_BRIDGE_WR_ADDR_2:
+	case WCD9335_SWR_AHB_BRIDGE_WR_ADDR_3:
+	case WCD9335_SWR_AHB_BRIDGE_RD_DATA_0:
+	case WCD9335_SWR_AHB_BRIDGE_RD_DATA_1:
+	case WCD9335_SWR_AHB_BRIDGE_RD_DATA_2:
+	case WCD9335_SWR_AHB_BRIDGE_RD_DATA_3:
+	case WCD9335_SWR_AHB_BRIDGE_RD_ADDR_0:
+	case WCD9335_SWR_AHB_BRIDGE_RD_ADDR_1:
+	case WCD9335_SWR_AHB_BRIDGE_RD_ADDR_2:
+	case WCD9335_SWR_AHB_BRIDGE_RD_ADDR_3:
+	case WCD9335_ANA_BIAS:
+	case WCD9335_ANA_CLK_TOP:
+	case WCD9335_ANA_RCO:
+	case WCD9335_CDC_CLK_RST_CTRL_MCLK_CONTROL:
+	case WCD9335_ANA_MBHC_RESULT_3:
+	case WCD9335_ANA_MBHC_RESULT_2:
+	case WCD9335_ANA_MBHC_RESULT_1:
+	case WCD9335_ANA_MBHC_MECH:
+	case WCD9335_ANA_MBHC_ELECT:
+	case WCD9335_ANA_MBHC_ZDET:
+	case WCD9335_ANA_MICB2:
+	case WCD9335_CPE_SS_SS_ERROR_INT_STATUS:
+	case WCD9335_CPE_SS_SS_ERROR_INT_MASK:
+	case WCD9335_CPE_SS_SS_ERROR_INT_CLEAR:
+	case WCD9335_CPE_SS_STATUS:
+	case WCD9335_CPE_SS_BACKUP_INT:
+	case WCD9335_CPE_SS_CFG:
+	case WCD9335_SOC_MAD_MAIN_CTL_1:
+	case WCD9335_SOC_MAD_AUDIO_CTL_3:
+	case WCD9335_SOC_MAD_AUDIO_CTL_4:
+	case WCD9335_FLYBACK_EN:
+	case WCD9335_ANA_RX_SUPPLIES:
+	case WCD9335_CDC_CLK_RST_CTRL_FS_CNT_CONTROL:
+	case WCD9335_SIDO_SIDO_CCL_2:
+	case WCD9335_SIDO_SIDO_CCL_4:
+	case WCD9335_DATA_HUB_NATIVE_FIFO_STATUS:
+	case WCD9335_MBHC_FSM_STATUS:
+	case WCD9335_SPLINE_SRC0_STATUS:
+	case WCD9335_SPLINE_SRC1_STATUS:
+	case WCD9335_SPLINE_SRC2_STATUS:
+	case WCD9335_SPLINE_SRC3_STATUS:
+	case WCD9335_SIDO_SIDO_TEST_2:
+	case WCD9335_SIDO_SIDO_CCL_8:
+	case WCD9335_BIAS_VBG_FINE_ADJ:
+	case WCD9335_VBADC_ADC_DOUTMSB:
+	case WCD9335_VBADC_ADC_DOUTLSB:
+	case WCD9335_CDC_VBAT_VBAT_GAIN_MON_VAL:
+	case WCD9335_ANA_BUCK_CTL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+struct regmap_config wcd9335_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wcd9335_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wcd9335_defaults),
+	.max_register = WCD9335_MAX_REGISTER,
+	.volatile_reg = wcd9335_is_volatile_register,
+	.readable_reg = wcd9335_is_readable_register,
+	.can_multi_write = true,
+};

+ 1325 - 0
drivers/mfd/wcd9335-tables.c

@@ -0,0 +1,1325 @@
+/*
+ * Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/types.h>
+#include <linux/mfd/wcd9335/registers.h>
+
+#define WCD9335_REG(reg)  ((reg) & 0xFF)
+
+const u8 wcd9335_page0_reg_readable[WCD9335_PAGE_SIZE] = {
+	[WCD9335_REG(WCD9335_PAGE0_PAGE_REGISTER)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_CLK_BYPASS)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_CLK_GATE)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_CLK_MCLK_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_RST_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_PWR_CPE_DEEPSLP_1)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_PWR_CPE_DEEPSLP_2)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_PWR_CPE_DEEPSLP_3)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_PWR_CPE_IRAM_SHUTDOWN)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_PWR_CPE_DRAM1_SHUTDOWN)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_PWR_CPE_DRAM0_SHUTDOWN_1)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_PWR_CPE_DRAM0_SHUTDOWN_2)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_INT_MASK)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_INT_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_CODEC_RPM_INT_CLEAR)] = 0,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE1)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE2)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE3)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_TEST0)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_TEST1)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT0)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT1)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT2)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT3)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT4)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT5)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT6)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT7)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT8)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT9)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT10)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT11)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT12)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT13)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT14)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT15)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_EFUSE_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_NONNEGO)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_1)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_2)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_3)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_ANA_WAIT_STATE_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_I2C_ACTIVE)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC1_MON_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC1_MON_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC1_MON_CNT_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC1_MON_CNT_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC2_MON_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC2_MON_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC2_MON_CNT_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC2_MON_CNT_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC3_MON_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC3_MON_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC3_MON_CNT_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CHIP_TIER_CTRL_PROC3_MON_CNT_LSB)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_RX_I2S_CTL)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_TX_I2S_CTL)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_I2S_CLK)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_RX0_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_RX1_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_RX2_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_RX3_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_RX4_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_RX5_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_RX6_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_RX7_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX0_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX1_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX2_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX3_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX4_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX5_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX6_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX7_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX8_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX9_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX10_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX11_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX13_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX14_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_SB_TX15_INP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD0_L_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD0_R_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD1_L_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD1_R_CFG)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_NATIVE_FIFO_SYNC)] = 1,
+	[WCD9335_REG(WCD9335_DATA_HUB_NATIVE_FIFO_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_INTR_CFG)] = 1,
+	[WCD9335_REG(WCD9335_INTR_CLR_COMMIT)] = 0,
+	[WCD9335_REG(WCD9335_INTR_PIN1_MASK0)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN1_MASK1)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN1_MASK2)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN1_MASK3)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN1_STATUS0)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN1_STATUS1)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN1_STATUS2)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN1_STATUS3)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN1_CLEAR0)] = 0,
+	[WCD9335_REG(WCD9335_INTR_PIN1_CLEAR1)] = 0,
+	[WCD9335_REG(WCD9335_INTR_PIN1_CLEAR2)] = 0,
+	[WCD9335_REG(WCD9335_INTR_PIN1_CLEAR3)] = 0,
+	[WCD9335_REG(WCD9335_INTR_PIN2_MASK0)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN2_MASK1)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN2_MASK2)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN2_MASK3)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN2_STATUS0)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN2_STATUS1)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN2_STATUS2)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN2_STATUS3)] = 1,
+	[WCD9335_REG(WCD9335_INTR_PIN2_CLEAR0)] = 0,
+	[WCD9335_REG(WCD9335_INTR_PIN2_CLEAR1)] = 0,
+	[WCD9335_REG(WCD9335_INTR_PIN2_CLEAR2)] = 0,
+	[WCD9335_REG(WCD9335_INTR_PIN2_CLEAR3)] = 0,
+	[WCD9335_REG(WCD9335_INTR_LEVEL0)] = 1,
+	[WCD9335_REG(WCD9335_INTR_LEVEL1)] = 1,
+	[WCD9335_REG(WCD9335_INTR_LEVEL2)] = 1,
+	[WCD9335_REG(WCD9335_INTR_LEVEL3)] = 1,
+	[WCD9335_REG(WCD9335_INTR_BYPASS0)] = 1,
+	[WCD9335_REG(WCD9335_INTR_BYPASS1)] = 1,
+	[WCD9335_REG(WCD9335_INTR_BYPASS2)] = 1,
+	[WCD9335_REG(WCD9335_INTR_BYPASS3)] = 1,
+	[WCD9335_REG(WCD9335_INTR_SET0)] = 1,
+	[WCD9335_REG(WCD9335_INTR_SET1)] = 1,
+	[WCD9335_REG(WCD9335_INTR_SET2)] = 1,
+	[WCD9335_REG(WCD9335_INTR_SET3)] = 1,
+};
+
+const u8 wcd9335_page1_reg_readable[WCD9335_PAGE_SIZE] = {
+	[WCD9335_REG(WCD9335_PAGE1_PAGE_REGISTER)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_USER_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_USER_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_USER_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_USER_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_USER_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_USER_CTL_5)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_USER_CTL_6)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_USER_CTL_7)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_USER_CTL_8)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_USER_CTL_9)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_L_VAL_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_L_VAL_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_DSM_FRAC_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_DSM_FRAC_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_CONFIG_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_CONFIG_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_CONFIG_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_CONFIG_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_CONFIG_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_TEST_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_TEST_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_TEST_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_TEST_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_TEST_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_TEST_CTL_5)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_TEST_CTL_6)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_TEST_CTL_7)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_FREQ_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_FREQ_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_FREQ_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_FREQ_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_SSC_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_SSC_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_SSC_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_SSC_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_FLL_MODE)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_STATUS_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_STATUS_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_STATUS_2)] = 1,
+	[WCD9335_REG(WCD9335_CPE_FLL_STATUS_3)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_USER_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_USER_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_USER_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_USER_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_USER_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_USER_CTL_5)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_USER_CTL_6)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_USER_CTL_7)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_USER_CTL_8)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_USER_CTL_9)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_L_VAL_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_L_VAL_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_DSM_FRAC_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_DSM_FRAC_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_CONFIG_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_CONFIG_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_CONFIG_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_CONFIG_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_CONFIG_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_TEST_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_TEST_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_TEST_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_TEST_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_TEST_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_TEST_CTL_5)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_TEST_CTL_6)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_TEST_CTL_7)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_FREQ_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_FREQ_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_FREQ_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_FREQ_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_SSC_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_SSC_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_SSC_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_SSC_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_FLL_MODE)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_STATUS_0)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_STATUS_1)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_STATUS_2)] = 1,
+	[WCD9335_REG(WCD9335_I2S_FLL_STATUS_3)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_USER_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_USER_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_USER_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_USER_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_USER_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_USER_CTL_5)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_USER_CTL_6)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_USER_CTL_7)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_USER_CTL_8)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_USER_CTL_9)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_L_VAL_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_L_VAL_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_DSM_FRAC_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_DSM_FRAC_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_CONFIG_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_CONFIG_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_CONFIG_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_CONFIG_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_CONFIG_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_TEST_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_TEST_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_TEST_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_TEST_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_TEST_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_TEST_CTL_5)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_TEST_CTL_6)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_TEST_CTL_7)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_FREQ_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_FREQ_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_FREQ_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_FREQ_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_SSC_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_SSC_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_SSC_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_SSC_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_FLL_MODE)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_STATUS_0)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_STATUS_1)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_STATUS_2)] = 1,
+	[WCD9335_REG(WCD9335_SB_FLL_STATUS_3)] = 1,
+};
+
+const u8 wcd9335_page2_reg_readable[WCD9335_PAGE_SIZE] = {
+	[WCD9335_REG(WCD9335_PAGE2_PAGE_REGISTER)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_PTR_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_PTR_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_PTR_2)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_CTRL)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_2)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_3)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_4)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_5)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_6)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_7)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_8)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_9)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_10)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_11)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_12)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_13)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_14)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MEM_BANK_15)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_TRG)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_TRG)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_0)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_1)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_2)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_3)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_4)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_5)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_6)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_7)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_8)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_9)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_10)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_11)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_12)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_13)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_14)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX1_15)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_2)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_3)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_4)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_5)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_6)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_7)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_8)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_9)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_10)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_11)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_12)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_13)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_14)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_15)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_0)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_1)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_2)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_3)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_4)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_5)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_6)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_7)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_8)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_9)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_10)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_11)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_12)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_13)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_14)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_INBOX2_15)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_0)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_1)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_2)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_3)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_4)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_5)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_6)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_7)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_8)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_9)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_10)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_11)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_12)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_13)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_14)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_15)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX1_ACK)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_OUTBOX2_ACK)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_EC_BUF_INT_PERIOD)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_US_BUF_INT_PERIOD)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_US_EC_MUX_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_MAD_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_CPAR_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_TX_PP_BUF_INT_PERIOD)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_TX_PP_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_DMIC0_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_DMIC1_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_DMIC2_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_DMIC_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_SVA_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_CPAR_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_WDOG_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_BACKUP_INT)] = 0,
+	[WCD9335_REG(WCD9335_CPE_SS_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_CPE_OCD_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_SS_ERROR_INT_MASK)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_SS_ERROR_INT_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_CPE_SS_SS_ERROR_INT_CLEAR)] = 0,
+	[WCD9335_REG(WCD9335_SOC_MAD_MAIN_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_MAIN_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_AUDIO_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_AUDIO_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_AUDIO_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_AUDIO_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_AUDIO_CTL_5)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_AUDIO_CTL_6)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_AUDIO_CTL_7)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_AUDIO_CTL_8)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_AUDIO_IIR_CTL_PTR)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_AUDIO_IIR_CTL_VAL)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_ULTR_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_ULTR_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_ULTR_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_ULTR_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_ULTR_CTL_5)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_ULTR_CTL_6)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_ULTR_CTL_7)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_BEACON_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_BEACON_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_BEACON_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_BEACON_CTL_4)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_BEACON_CTL_5)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_BEACON_CTL_6)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_BEACON_CTL_7)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_BEACON_CTL_8)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_BEACON_IIR_CTL_PTR)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_BEACON_IIR_CTL_VAL)] = 1,
+	[WCD9335_REG(WCD9335_SOC_MAD_INP_SEL)] = 1,
+};
+
+const u8 wcd9335_page6_reg_readable[WCD9335_PAGE_SIZE] = {
+	[WCD9335_REG(WCD9335_PAGE6_PAGE_REGISTER)] = 1,
+	[WCD9335_REG(WCD9335_ANA_BIAS)] = 1,
+	[WCD9335_REG(WCD9335_ANA_CLK_TOP)] = 1,
+	[WCD9335_REG(WCD9335_ANA_RCO)] = 1,
+	[WCD9335_REG(WCD9335_ANA_BUCK_VOUT_A)] = 1,
+	[WCD9335_REG(WCD9335_ANA_BUCK_VOUT_D)] = 1,
+	[WCD9335_REG(WCD9335_ANA_BUCK_CTL)] = 1,
+	[WCD9335_REG(WCD9335_ANA_BUCK_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_ANA_RX_SUPPLIES)] = 1,
+	[WCD9335_REG(WCD9335_ANA_HPH)] = 1,
+	[WCD9335_REG(WCD9335_ANA_EAR)] = 1,
+	[WCD9335_REG(WCD9335_ANA_LO_1_2)] = 1,
+	[WCD9335_REG(WCD9335_ANA_LO_3_4)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MAD_SETUP)] = 1,
+	[WCD9335_REG(WCD9335_ANA_AMIC1)] = 1,
+	[WCD9335_REG(WCD9335_ANA_AMIC2)] = 1,
+	[WCD9335_REG(WCD9335_ANA_AMIC3)] = 1,
+	[WCD9335_REG(WCD9335_ANA_AMIC4)] = 1,
+	[WCD9335_REG(WCD9335_ANA_AMIC5)] = 1,
+	[WCD9335_REG(WCD9335_ANA_AMIC6)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_MECH)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_ELECT)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_ZDET)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_RESULT_1)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_RESULT_2)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_RESULT_3)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_BTN0)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_BTN1)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_BTN2)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_BTN3)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_BTN4)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_BTN5)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_BTN6)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MBHC_BTN7)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MICB1)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MICB2)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MICB2_RAMP)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MICB3)] = 1,
+	[WCD9335_REG(WCD9335_ANA_MICB4)] = 1,
+	[WCD9335_REG(WCD9335_ANA_VBADC)] = 1,
+	[WCD9335_REG(WCD9335_BIAS_CTL)] = 1,
+	[WCD9335_REG(WCD9335_BIAS_VBG_FINE_ADJ)] = 1,
+	[WCD9335_REG(WCD9335_CLOCK_TEST_CTL)] = 1,
+	[WCD9335_REG(WCD9335_RCO_CTRL_1)] = 1,
+	[WCD9335_REG(WCD9335_RCO_CTRL_2)] = 1,
+	[WCD9335_REG(WCD9335_RCO_CAL)] = 1,
+	[WCD9335_REG(WCD9335_RCO_CAL_1)] = 1,
+	[WCD9335_REG(WCD9335_RCO_CAL_2)] = 1,
+	[WCD9335_REG(WCD9335_RCO_TEST_CTRL)] = 1,
+	[WCD9335_REG(WCD9335_RCO_CAL_OUT_1)] = 1,
+	[WCD9335_REG(WCD9335_RCO_CAL_OUT_2)] = 1,
+	[WCD9335_REG(WCD9335_RCO_CAL_OUT_3)] = 1,
+	[WCD9335_REG(WCD9335_RCO_CAL_OUT_4)] = 1,
+	[WCD9335_REG(WCD9335_RCO_CAL_OUT_5)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_MODE_1)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_MODE_2)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_MODE_3)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_MODE_4)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_VCL_1)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_VCL_2)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_VCL_3)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CCL_1)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CCL_2)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CCL_3)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CCL_4)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CCL_5)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CCL_6)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CCL_7)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CCL_8)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CCL_9)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CCL_10)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_FILTER_1)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_FILTER_2)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_DRIVER_1)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_DRIVER_2)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_DRIVER_3)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CAL_CODE_EXT_1)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CAL_CODE_EXT_2)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CAL_CODE_OUT_1)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_CAL_CODE_OUT_2)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_TEST_1)] = 1,
+	[WCD9335_REG(WCD9335_SIDO_SIDO_TEST_2)] = 1,
+	[WCD9335_REG(WCD9335_MBHC_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_MBHC_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_MBHC_PLUG_DETECT_CTL)] = 1,
+	[WCD9335_REG(WCD9335_MBHC_ZDET_ANA_CTL)] = 1,
+	[WCD9335_REG(WCD9335_MBHC_ZDET_RAMP_CTL)] = 1,
+	[WCD9335_REG(WCD9335_MBHC_FSM_DEBUG)] = 1,
+	[WCD9335_REG(WCD9335_MBHC_TEST_CTL)] = 1,
+	[WCD9335_REG(WCD9335_VBADC_SUBBLOCK_EN)] = 1,
+	[WCD9335_REG(WCD9335_VBADC_IBIAS_FE)] = 1,
+	[WCD9335_REG(WCD9335_VBADC_BIAS_ADC)] = 1,
+	[WCD9335_REG(WCD9335_VBADC_FE_CTRL)] = 1,
+	[WCD9335_REG(WCD9335_VBADC_ADC_REF)] = 1,
+	[WCD9335_REG(WCD9335_VBADC_ADC_IO)] = 1,
+	[WCD9335_REG(WCD9335_VBADC_ADC_SAR)] = 1,
+	[WCD9335_REG(WCD9335_VBADC_DEBUG)] = 1,
+	[WCD9335_REG(WCD9335_VBADC_ADC_DOUTMSB)] = 1,
+	[WCD9335_REG(WCD9335_VBADC_ADC_DOUTLSB)] = 1,
+	[WCD9335_REG(WCD9335_LDOH_MODE)] = 1,
+	[WCD9335_REG(WCD9335_LDOH_BIAS)] = 1,
+	[WCD9335_REG(WCD9335_LDOH_STB_LOADS)] = 1,
+	[WCD9335_REG(WCD9335_LDOH_SLOWRAMP)] = 1,
+	[WCD9335_REG(WCD9335_MICB1_TEST_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_MICB1_TEST_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_MICB1_TEST_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_MICB2_TEST_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_MICB2_TEST_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_MICB2_TEST_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_MICB3_TEST_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_MICB3_TEST_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_MICB3_TEST_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_MICB4_TEST_CTL_1)] = 1,
+	[WCD9335_REG(WCD9335_MICB4_TEST_CTL_2)] = 1,
+	[WCD9335_REG(WCD9335_MICB4_TEST_CTL_3)] = 1,
+	[WCD9335_REG(WCD9335_TX_COM_ADC_VCM)] = 1,
+	[WCD9335_REG(WCD9335_TX_COM_BIAS_ATEST)] = 1,
+	[WCD9335_REG(WCD9335_TX_COM_ADC_INT1_IB)] = 1,
+	[WCD9335_REG(WCD9335_TX_COM_ADC_INT2_IB)] = 1,
+	[WCD9335_REG(WCD9335_TX_COM_TXFE_DIV_CTL)] = 1,
+	[WCD9335_REG(WCD9335_TX_COM_TXFE_DIV_START)] = 1,
+	[WCD9335_REG(WCD9335_TX_COM_TXFE_DIV_STOP_9P6M)] = 1,
+	[WCD9335_REG(WCD9335_TX_COM_TXFE_DIV_STOP_12P288M)] = 1,
+	[WCD9335_REG(WCD9335_TX_1_2_TEST_EN)] = 1,
+	[WCD9335_REG(WCD9335_TX_1_2_ADC_IB)] = 1,
+	[WCD9335_REG(WCD9335_TX_1_2_ATEST_REFCTL)] = 1,
+	[WCD9335_REG(WCD9335_TX_1_2_TEST_CTL)] = 1,
+	[WCD9335_REG(WCD9335_TX_1_2_TEST_BLK_EN)] = 1,
+	[WCD9335_REG(WCD9335_TX_1_2_TXFE_CLKDIV)] = 1,
+	[WCD9335_REG(WCD9335_TX_1_2_SAR1_ERR)] = 1,
+	[WCD9335_REG(WCD9335_TX_1_2_SAR2_ERR)] = 1,
+	[WCD9335_REG(WCD9335_TX_3_4_TEST_EN)] = 1,
+	[WCD9335_REG(WCD9335_TX_3_4_ADC_IB)] = 1,
+	[WCD9335_REG(WCD9335_TX_3_4_ATEST_REFCTL)] = 1,
+	[WCD9335_REG(WCD9335_TX_3_4_TEST_CTL)] = 1,
+	[WCD9335_REG(WCD9335_TX_3_4_TEST_BLK_EN)] = 1,
+	[WCD9335_REG(WCD9335_TX_3_4_TXFE_CLKDIV)] = 1,
+	[WCD9335_REG(WCD9335_TX_3_4_SAR1_ERR)] = 1,
+	[WCD9335_REG(WCD9335_TX_3_4_SAR2_ERR)] = 1,
+	[WCD9335_REG(WCD9335_TX_5_6_TEST_EN)] = 1,
+	[WCD9335_REG(WCD9335_TX_5_6_ADC_IB)] = 1,
+	[WCD9335_REG(WCD9335_TX_5_6_ATEST_REFCTL)] = 1,
+	[WCD9335_REG(WCD9335_TX_5_6_TEST_CTL)] = 1,
+	[WCD9335_REG(WCD9335_TX_5_6_TEST_BLK_EN)] = 1,
+	[WCD9335_REG(WCD9335_TX_5_6_TXFE_CLKDIV)] = 1,
+	[WCD9335_REG(WCD9335_TX_5_6_SAR1_ERR)] = 1,
+	[WCD9335_REG(WCD9335_TX_5_6_SAR2_ERR)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_MODE_1)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_MODE_2)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_MODE_3)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_CTRL_VCL_1)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_CTRL_VCL_2)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_CTRL_CCL_1)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_CTRL_CCL_2)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_CTRL_CCL_3)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_CTRL_CCL_4)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_CTRL_CCL_5)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_BUCK_TMUX_A_D)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_BUCK_SW_DRV_CNTL)] = 1,
+	[WCD9335_REG(WCD9335_CLASSH_SPARE)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_EN)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_CTRL_1)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_CTRL_2)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_CTRL_3)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_CTRL_4)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_CTRL_5)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_CTRL_6)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_CTRL_7)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_CTRL_8)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_CTRL_9)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_DAC_CTRL_1)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_DAC_CTRL_2)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_DAC_CTRL_3)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_VNEG_DAC_CTRL_4)] = 1,
+	[WCD9335_REG(WCD9335_FLYBACK_TEST_CTL)] = 1,
+	[WCD9335_REG(WCD9335_RX_AUX_SW_CTL)] = 1,
+	[WCD9335_REG(WCD9335_RX_PA_AUX_IN_CONN)] = 1,
+	[WCD9335_REG(WCD9335_RX_TIMER_DIV)] = 1,
+	[WCD9335_REG(WCD9335_RX_OCP_CTL)] = 1,
+	[WCD9335_REG(WCD9335_RX_OCP_COUNT)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_EAR_DAC)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_EAR_AMP)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_HPH_LDO)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_HPH_PA)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_HPH_RDACBUFF_CNP2)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_HPH_RDAC_LDO)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_HPH_CNP1)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_HPH_LOWPOWER)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_DIFFLO_PA)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_DIFFLO_REF)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_DIFFLO_LDO)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_SELO_DAC_PA)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_BUCK_RST)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_BUCK_VREF_ERRAMP)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_FLYB_ERRAMP)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_FLYB_BUFF)] = 1,
+	[WCD9335_REG(WCD9335_RX_BIAS_FLYB_MID_RST)] = 1,
+	[WCD9335_REG(WCD9335_HPH_L_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_HPH_R_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_HPH_CNP_EN)] = 1,
+	[WCD9335_REG(WCD9335_HPH_CNP_WG_CTL)] = 1,
+	[WCD9335_REG(WCD9335_HPH_CNP_WG_TIME)] = 1,
+	[WCD9335_REG(WCD9335_HPH_OCP_CTL)] = 1,
+	[WCD9335_REG(WCD9335_HPH_AUTO_CHOP)] = 1,
+	[WCD9335_REG(WCD9335_HPH_CHOP_CTL)] = 1,
+	[WCD9335_REG(WCD9335_HPH_PA_CTL1)] = 1,
+	[WCD9335_REG(WCD9335_HPH_PA_CTL2)] = 1,
+	[WCD9335_REG(WCD9335_HPH_L_EN)] = 1,
+	[WCD9335_REG(WCD9335_HPH_L_TEST)] = 1,
+	[WCD9335_REG(WCD9335_HPH_L_ATEST)] = 1,
+	[WCD9335_REG(WCD9335_HPH_R_EN)] = 1,
+	[WCD9335_REG(WCD9335_HPH_R_TEST)] = 1,
+	[WCD9335_REG(WCD9335_HPH_R_ATEST)] = 1,
+	[WCD9335_REG(WCD9335_HPH_RDAC_CLK_CTL1)] = 1,
+	[WCD9335_REG(WCD9335_HPH_RDAC_CLK_CTL2)] = 1,
+	[WCD9335_REG(WCD9335_HPH_RDAC_LDO_CTL)] = 1,
+	[WCD9335_REG(WCD9335_HPH_RDAC_CHOP_CLK_LP_CTL)] = 1,
+	[WCD9335_REG(WCD9335_HPH_REFBUFF_UHQA_CTL)] = 1,
+	[WCD9335_REG(WCD9335_HPH_REFBUFF_LP_CTL)] = 1,
+	[WCD9335_REG(WCD9335_HPH_L_DAC_CTL)] = 1,
+	[WCD9335_REG(WCD9335_HPH_R_DAC_CTL)] = 1,
+	[WCD9335_REG(WCD9335_EAR_EN_REG)] = 1,
+	[WCD9335_REG(WCD9335_EAR_CMBUFF)] = 1,
+	[WCD9335_REG(WCD9335_EAR_ICTL)] = 1,
+	[WCD9335_REG(WCD9335_EAR_EN_DBG_CTL)] = 1,
+	[WCD9335_REG(WCD9335_EAR_CNP)] = 1,
+	[WCD9335_REG(WCD9335_EAR_DAC_CTL_ATEST)] = 1,
+	[WCD9335_REG(WCD9335_EAR_STATUS_REG)] = 1,
+	[WCD9335_REG(WCD9335_EAR_OUT_SHORT)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_MISC)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_LO2_COMPANDER)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_LO1_COMPANDER)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_COMMON)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_BYPASS_EN)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_CNP)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_CORE_OUT_PROG)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_LDO_OUT_PROG)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_COM_SWCAP_REFBUF_FREQ)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_COM_PA_FREQ)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_RESERVED_REG)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_LO1_STATUS_1)] = 1,
+	[WCD9335_REG(WCD9335_DIFF_LO_LO1_STATUS_2)] = 1,
+	[WCD9335_REG(WCD9335_SE_LO_COM1)] = 1,
+	[WCD9335_REG(WCD9335_SE_LO_COM2)] = 1,
+	[WCD9335_REG(WCD9335_SE_LO_LO3_GAIN)] = 1,
+	[WCD9335_REG(WCD9335_SE_LO_LO3_CTRL)] = 1,
+	[WCD9335_REG(WCD9335_SE_LO_LO4_GAIN)] = 1,
+	[WCD9335_REG(WCD9335_SE_LO_LO4_CTRL)] = 1,
+	[WCD9335_REG(WCD9335_SE_LO_LO3_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_SE_LO_LO4_STATUS)] = 1,
+};
+
+const u8 wcd9335_page10_reg_readable[WCD9335_PAGE_SIZE] = {
+	[WCD9335_REG(WCD9335_PAGE10_PAGE_REGISTER)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_CLK_RESET_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_MODE_1_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_MODE_2_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_FF_SHIFT)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_FB_SHIFT)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_LPF_FF_A_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_LPF_FF_B_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_LPF_FB_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_SMLPF_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_DCFLT_SHIFT_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_IIR_ADAPT_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_IIR_COEFF_1_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_IIR_COEFF_2_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_FF_A_GAIN_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_FF_B_GAIN_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC0_FB_GAIN_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_CLK_RESET_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_MODE_1_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_MODE_2_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_FF_SHIFT)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_FB_SHIFT)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_LPF_FF_A_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_LPF_FF_B_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_LPF_FB_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_SMLPF_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_DCFLT_SHIFT_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_IIR_ADAPT_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_IIR_COEFF_1_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_IIR_COEFF_2_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_FF_A_GAIN_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_FF_B_GAIN_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_ANC1_FB_GAIN_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_192_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_192_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX0_TX_PATH_SEC7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_192_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_192_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX1_TX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_192_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_192_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX2_TX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_192_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_192_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX3_TX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_192_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_192_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX4_TX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_192_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_192_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX5_TX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_192_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_192_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX6_TX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_192_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_192_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX7_TX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_192_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_192_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX8_TX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX9_SPKR_PROT_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX9_SPKR_PROT_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX10_SPKR_PROT_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX10_SPKR_PROT_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX11_SPKR_PROT_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX11_SPKR_PROT_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX12_SPKR_PROT_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX12_SPKR_PROT_PATH_CFG0)] = 1,
+};
+
+const u8 wcd9335_page11_reg_readable[WCD9335_PAGE_SIZE] = {
+	[WCD9335_REG(WCD9335_PAGE11_PAGE_REGISTER)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER1_CTL0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER1_CTL1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER1_CTL2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER1_CTL3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER1_CTL4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER1_CTL5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER1_CTL6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER1_CTL7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER2_CTL0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER2_CTL1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER2_CTL2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER2_CTL3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER2_CTL4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER2_CTL5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER2_CTL6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER2_CTL7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER3_CTL0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER3_CTL1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER3_CTL2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER3_CTL3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER3_CTL4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER3_CTL5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER3_CTL6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER3_CTL7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER4_CTL0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER4_CTL1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER4_CTL2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER4_CTL3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER4_CTL4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER4_CTL5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER4_CTL6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER4_CTL7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER5_CTL0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER5_CTL1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER5_CTL2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER5_CTL3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER5_CTL4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER5_CTL5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER5_CTL6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER5_CTL7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER6_CTL0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER6_CTL1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER6_CTL2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER6_CTL3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER6_CTL4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER6_CTL5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER6_CTL6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER6_CTL7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER7_CTL0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER7_CTL1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER7_CTL2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER7_CTL3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER7_CTL4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER7_CTL5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER7_CTL6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER7_CTL7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER8_CTL0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER8_CTL1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER8_CTL2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER8_CTL3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER8_CTL4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER8_CTL5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER8_CTL6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_COMPANDER8_CTL7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_MIX_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_VOL_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_SEC7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_MIX_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX0_RX_PATH_MIX_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_MIX_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_VOL_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_SEC7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_MIX_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX1_RX_PATH_MIX_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_MIX_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_VOL_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_SEC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_SEC7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_MIX_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX2_RX_PATH_MIX_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_MIX_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_VOL_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_SEC7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_MIX_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX3_RX_PATH_MIX_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_MIX_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_VOL_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_SEC7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_MIX_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX4_RX_PATH_MIX_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_MIX_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_VOL_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_SEC7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_MIX_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX5_RX_PATH_MIX_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_MIX_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_VOL_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_SEC7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_MIX_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX6_RX_PATH_MIX_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_MIX_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_VOL_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_SEC7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_MIX_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX7_RX_PATH_MIX_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_VOL_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_MIX_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_VOL_MIX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_SEC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_SEC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_SEC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_SEC5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_SEC6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_SEC7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_MIX_SEC0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX8_RX_PATH_MIX_SEC1)] = 1,
+};
+
+const u8 wcd9335_page12_reg_readable[WCD9335_PAGE_SIZE] = {
+	[WCD9335_REG(WCD9335_PAGE12_PAGE_REGISTER)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_CRC)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_DLY_CTRL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_DECAY_CTRL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_HPH_V_PA)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_EAR_V_PA)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_HPH_V_HD)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_EAR_V_HD)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_K1_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_K1_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_K2_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_K2_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_IDLE_CTRL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_IDLE_HPH)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_IDLE_EAR)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_TEST0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_TEST1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLSH_OVR_VREF)] = 1,
+	[WCD9335_REG(WCD9335_CDC_BOOST0_BOOST_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_BOOST0_BOOST_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_BOOST0_BOOST_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_BOOST0_BOOST_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_BOOST1_BOOST_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_BOOST1_BOOST_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_BOOST1_BOOST_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_BOOST1_BOOST_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_WR_DATA_0)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_WR_DATA_1)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_WR_DATA_2)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_WR_DATA_3)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_WR_ADDR_0)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_WR_ADDR_1)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_WR_ADDR_2)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_WR_ADDR_3)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_RD_ADDR_0)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_RD_ADDR_1)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_RD_ADDR_2)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_RD_ADDR_3)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_RD_DATA_0)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_RD_DATA_1)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_RD_DATA_2)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_RD_DATA_3)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_ACCESS_CFG)] = 1,
+	[WCD9335_REG(WCD9335_SWR_AHB_BRIDGE_ACCESS_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_CFG)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_ADC_CAL1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_ADC_CAL2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_ADC_CAL3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_PK_EST1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_PK_EST2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_PK_EST3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_RF_PROC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_RF_PROC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_TAC1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_TAC2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_TAC3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_TAC4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_GAIN_UPD1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_GAIN_UPD2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_GAIN_UPD3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_GAIN_UPD4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_DEBUG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_GAIN_UPD_MON)] = 0,
+	[WCD9335_REG(WCD9335_CDC_VBAT_VBAT_GAIN_MON_VAL)] = 1,
+	[WCD9335_REG(WCD9335_SPLINE_SRC0_CLK_RST_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SPLINE_SRC0_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_SPLINE_SRC1_CLK_RST_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SPLINE_SRC1_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_SPLINE_SRC2_CLK_RST_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SPLINE_SRC2_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_SPLINE_SRC3_CLK_RST_CTL_0)] = 1,
+	[WCD9335_REG(WCD9335_SPLINE_SRC3_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_SRC0_ST_SRC_PATH_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_SRC1_ST_SRC_PATH_CFG1)] = 1,
+};
+
+const u8 wcd9335_page13_reg_readable[WCD9335_PAGE_SIZE] = {
+	[WCD9335_REG(WCD9335_PAGE13_PAGE_REGISTER)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_ANC_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_RX_INP_MUX_SPLINE_SRC_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX4_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX5_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX6_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX7_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX8_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX10_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX11_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX12_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TX_INP_MUX_ADC_MUX13_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLK_RST_CTRL_MCLK_CONTROL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLK_RST_CTRL_FS_CNT_CONTROL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_CLK_RST_CTRL_SWR_CONTROL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_POLL_PERIOD0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_POLL_PERIOD1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_SIG_PATTERN_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_SIG_PATTERN_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_TEST_CTRL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB_RD)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB_RD)] = 1,
+	[WCD9335_REG(WCD9335_CDC_PROX_DETECT_PROX_CTL_REPEAT_PAT)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B5_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B6_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B7_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B8_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_PATH_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B5_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B6_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B7_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B8_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_COEF_B1_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_SIDETONE_IIR1_IIR_COEF_B2_CTL)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_TOP_CFG0)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_TOP_CFG1)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_TOP_CFG2)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_TOP_CFG3)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_TOP_CFG4)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_TOP_CFG5)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_TOP_CFG6)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_TOP_CFG7)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_HPHL_COMP_WR_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_HPHL_COMP_WR_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_HPHL_COMP_LUT)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_HPHL_COMP_RD_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_HPHL_COMP_RD_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_HPHR_COMP_WR_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_HPHR_COMP_WR_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_HPHR_COMP_LUT)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_HPHR_COMP_RD_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_HPHR_COMP_RD_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_DIFFL_COMP_WR_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_DIFFL_COMP_WR_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_DIFFL_COMP_LUT)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_DIFFL_COMP_RD_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_DIFFL_COMP_RD_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_DIFFR_COMP_WR_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_DIFFR_COMP_WR_MSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_DIFFR_COMP_LUT)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_DIFFR_COMP_RD_LSB)] = 1,
+	[WCD9335_REG(WCD9335_CDC_TOP_DIFFR_COMP_RD_MSB)] = 1,
+};
+
+const u8 wcd9335_page_0x80_reg_readable[WCD9335_PAGE_SIZE] = {
+	[WCD9335_REG(WCD9335_PAGE80_PAGE_REGISTER)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_BIST_MODE_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_RF_PA_ON_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_INTR1_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_INTR2_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_SWR_DATA_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_SWR_CLK_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_SLIMBUS_DATA2_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_I2C_CLK_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_I2C_DATA_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_I2S_RX_SD0_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_I2S_RX_SD1_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_I2S_RX_SCK_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_I2S_RX_WS_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_I2S_TX_SD0_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_I2S_TX_SD1_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_I2S_TX_SCK_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_I2S_TX_WS_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_DMIC1_CLK_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_DMIC1_DATA_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_DMIC2_CLK_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_DMIC2_DATA_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_DMIC3_CLK_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_DMIC3_DATA_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_JTDI_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_JTDO_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_JTMS_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_JTCK_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TLMM_JTRST_PINCFG)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_PIN_CTL_OE_0)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_PIN_CTL_OE_1)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_PIN_CTL_OE_2)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_PIN_CTL_OE_3)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_PIN_CTL_DATA_0)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_PIN_CTL_DATA_1)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_PIN_CTL_DATA_2)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_PIN_CTL_DATA_3)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_PAD_DRVCTL)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_PIN_STATUS)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_NPL_DLY_TEST_1)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_NPL_DLY_TEST_2)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_MEM_CTRL)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_DEBUG_BUS_SEL)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_DEBUG_JTAG)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_DEBUG_EN_1)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_DEBUG_EN_2)] = 1,
+	[WCD9335_REG(WCD9335_TEST_DEBUG_DEBUG_EN_3)] = 1,
+};
+
+const u8 *wcd9335_reg[WCD9335_NUM_PAGES] = {
+	[PAGE_0] = wcd9335_page0_reg_readable,
+	[PAGE_1] = wcd9335_page1_reg_readable,
+	[PAGE_2] = wcd9335_page2_reg_readable,
+	[PAGE_6] = wcd9335_page6_reg_readable,
+	[PAGE_10] = wcd9335_page10_reg_readable,
+	[PAGE_11] = wcd9335_page11_reg_readable,
+	[PAGE_12] = wcd9335_page12_reg_readable,
+	[PAGE_13] = wcd9335_page13_reg_readable,
+	[PAGE_0X80] = wcd9335_page_0x80_reg_readable,
+};

+ 1957 - 0
drivers/mfd/wcd934x-regmap.c

@@ -0,0 +1,1957 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd934x/registers.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "wcd9xxx-regmap.h"
+
+
+static const struct reg_sequence wcd934x_1_1_defaults[] = {
+	{ WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0,             0x01 },
+	{ WCD934X_BIAS_VBG_FINE_ADJ,                        0x75 },
+	{ WCD934X_HPH_REFBUFF_LP_CTL,                       0x0E },
+	{ WCD934X_EAR_DAC_CTL_ATEST,                        0x08 },
+	{ WCD934X_SIDO_NEW_VOUT_A_STARTUP,                  0x17 },
+	{ WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,                0x40 },
+	{ WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L,               0x81 },
+	{ WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R,               0x81 },
+};
+
+static const struct reg_default wcd934x_defaults[] = {
+	{ WCD934X_PAGE0_PAGE_REGISTER,                      0x00 },
+	{ WCD934X_CODEC_RPM_CLK_BYPASS,                     0x00 },
+	{ WCD934X_CODEC_RPM_CLK_GATE,                       0x1f },
+	{ WCD934X_CODEC_RPM_CLK_MCLK_CFG,                   0x00 },
+	{ WCD934X_CODEC_RPM_CLK_MCLK2_CFG,                  0x02 },
+	{ WCD934X_CODEC_RPM_I2S_DSD_CLK_SEL,                0x00 },
+	{ WCD934X_CODEC_RPM_RST_CTL,                        0x00 },
+	{ WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,             0x04 },
+	{ WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0,             0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE1,             0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2,             0x08 },
+	{ WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE3,             0x01 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_CTL,                 0x10 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_TEST0,               0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_TEST1,               0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT0,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT1,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT2,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT3,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT4,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT5,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT6,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT7,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT8,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT9,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT10,           0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT11,           0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT12,           0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT13,           0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14,           0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15,           0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS,              0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_NONNEGO,      0x0d },
+	{ WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_1,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_2,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_3,            0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_ANA_WAIT_STATE_CTL,        0xcc },
+	{ WCD934X_CHIP_TIER_CTRL_SLNQ_WAIT_STATE_CTL,       0xcc },
+	{ WCD934X_CHIP_TIER_CTRL_I2C_ACTIVE,                0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_ALT_FUNC_EN,               0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_GPIO_CTL_OE,               0x00 },
+	{ WCD934X_CHIP_TIER_CTRL_GPIO_CTL_DATA,             0x00 },
+	{ WCD934X_DATA_HUB_RX0_CFG,                         0x00 },
+	{ WCD934X_DATA_HUB_RX1_CFG,                         0x00 },
+	{ WCD934X_DATA_HUB_RX2_CFG,                         0x00 },
+	{ WCD934X_DATA_HUB_RX3_CFG,                         0x00 },
+	{ WCD934X_DATA_HUB_RX4_CFG,                         0x00 },
+	{ WCD934X_DATA_HUB_RX5_CFG,                         0x00 },
+	{ WCD934X_DATA_HUB_RX6_CFG,                         0x00 },
+	{ WCD934X_DATA_HUB_RX7_CFG,                         0x00 },
+	{ WCD934X_DATA_HUB_SB_TX0_INP_CFG,                  0x00 },
+	{ WCD934X_DATA_HUB_SB_TX1_INP_CFG,                  0x00 },
+	{ WCD934X_DATA_HUB_SB_TX2_INP_CFG,                  0x00 },
+	{ WCD934X_DATA_HUB_SB_TX3_INP_CFG,                  0x00 },
+	{ WCD934X_DATA_HUB_SB_TX4_INP_CFG,                  0x00 },
+	{ WCD934X_DATA_HUB_SB_TX5_INP_CFG,                  0x00 },
+	{ WCD934X_DATA_HUB_SB_TX6_INP_CFG,                  0x00 },
+	{ WCD934X_DATA_HUB_SB_TX7_INP_CFG,                  0x00 },
+	{ WCD934X_DATA_HUB_SB_TX8_INP_CFG,                  0x00 },
+	{ WCD934X_DATA_HUB_SB_TX9_INP_CFG,                  0x00 },
+	{ WCD934X_DATA_HUB_SB_TX10_INP_CFG,                 0x00 },
+	{ WCD934X_DATA_HUB_SB_TX11_INP_CFG,                 0x00 },
+	{ WCD934X_DATA_HUB_SB_TX13_INP_CFG,                 0x00 },
+	{ WCD934X_DATA_HUB_SB_TX14_INP_CFG,                 0x00 },
+	{ WCD934X_DATA_HUB_SB_TX15_INP_CFG,                 0x00 },
+	{ WCD934X_DATA_HUB_I2S_TX0_CFG,                     0x00 },
+	{ WCD934X_DATA_HUB_I2S_TX1_0_CFG,                   0x00 },
+	{ WCD934X_DATA_HUB_I2S_TX1_1_CFG,                   0x00 },
+	{ WCD934X_DATA_HUB_I2S_0_CTL,                       0x0c },
+	{ WCD934X_DATA_HUB_I2S_1_CTL,                       0x0c },
+	{ WCD934X_DATA_HUB_I2S_2_CTL,                       0x0c },
+	{ WCD934X_DATA_HUB_I2S_3_CTL,                       0x0c },
+	{ WCD934X_DATA_HUB_I2S_CLKSRC_CTL,                  0x00 },
+	{ WCD934X_DATA_HUB_I2S_COMMON_CTL,                  0x00 },
+	{ WCD934X_DATA_HUB_I2S_0_TDM_CTL,                   0x00 },
+	{ WCD934X_DATA_HUB_I2S_STATUS,                      0x00 },
+	{ WCD934X_DMA_RDMA_CTL_0,                           0x00 },
+	{ WCD934X_DMA_CH_2_3_CFG_RDMA_0,                    0xff },
+	{ WCD934X_DMA_CH_0_1_CFG_RDMA_0,                    0xff },
+	{ WCD934X_DMA_RDMA_CTL_1,                           0x00 },
+	{ WCD934X_DMA_CH_2_3_CFG_RDMA_1,                    0xff },
+	{ WCD934X_DMA_CH_0_1_CFG_RDMA_1,                    0xff },
+	{ WCD934X_DMA_RDMA_CTL_2,                           0x00 },
+	{ WCD934X_DMA_CH_2_3_CFG_RDMA_2,                    0xff },
+	{ WCD934X_DMA_CH_0_1_CFG_RDMA_2,                    0xff },
+	{ WCD934X_DMA_RDMA_CTL_3,                           0x00 },
+	{ WCD934X_DMA_CH_2_3_CFG_RDMA_3,                    0xff },
+	{ WCD934X_DMA_CH_0_1_CFG_RDMA_3,                    0xff },
+	{ WCD934X_DMA_RDMA_CTL_4,                           0x00 },
+	{ WCD934X_DMA_CH_2_3_CFG_RDMA_4,                    0xff },
+	{ WCD934X_DMA_CH_0_1_CFG_RDMA_4,                    0xff },
+	{ WCD934X_DMA_RDMA4_PRT_CFG,                       0x00 },
+	{ WCD934X_DMA_RDMA_SBTX0_7_CFG,                    0x00 },
+	{ WCD934X_DMA_RDMA_SBTX8_11_CFG,                   0x00 },
+	{ WCD934X_DMA_WDMA_CTL_0,                          0x00 },
+	{ WCD934X_DMA_CH_4_5_CFG_WDMA_0,                   0x00 },
+	{ WCD934X_DMA_CH_2_3_CFG_WDMA_0,                   0x00 },
+	{ WCD934X_DMA_CH_0_1_CFG_WDMA_0,                   0x00 },
+	{ WCD934X_DMA_WDMA_CTL_1,                          0x00 },
+	{ WCD934X_DMA_CH_4_5_CFG_WDMA_1,                   0x00 },
+	{ WCD934X_DMA_CH_2_3_CFG_WDMA_1,                   0x00 },
+	{ WCD934X_DMA_CH_0_1_CFG_WDMA_1,                   0x00 },
+	{ WCD934X_DMA_WDMA_CTL_2,                          0x00 },
+	{ WCD934X_DMA_CH_4_5_CFG_WDMA_2,                   0x00 },
+	{ WCD934X_DMA_CH_2_3_CFG_WDMA_2,                   0x00 },
+	{ WCD934X_DMA_CH_0_1_CFG_WDMA_2,                   0x00 },
+	{ WCD934X_DMA_WDMA_CTL_3,                          0x00 },
+	{ WCD934X_DMA_CH_4_5_CFG_WDMA_3,                   0x00 },
+	{ WCD934X_DMA_CH_2_3_CFG_WDMA_3,                   0x00 },
+	{ WCD934X_DMA_CH_0_1_CFG_WDMA_3,                   0x00 },
+	{ WCD934X_DMA_WDMA_CTL_4,                          0x00 },
+	{ WCD934X_DMA_CH_4_5_CFG_WDMA_4,                   0x00 },
+	{ WCD934X_DMA_CH_2_3_CFG_WDMA_4,                   0x00 },
+	{ WCD934X_DMA_CH_0_1_CFG_WDMA_4,                   0x00 },
+	{ WCD934X_DMA_WDMA0_PRT_CFG,                       0x00 },
+	{ WCD934X_DMA_WDMA3_PRT_CFG,                       0x00 },
+	{ WCD934X_DMA_WDMA4_PRT0_3_CFG,                    0x00 },
+	{ WCD934X_DMA_WDMA4_PRT4_7_CFG,                    0x00 },
+	{ WCD934X_PAGE1_PAGE_REGISTER,                     0x00 },
+	{ WCD934X_CPE_FLL_USER_CTL_0,                      0x71 },
+	{ WCD934X_CPE_FLL_USER_CTL_1,                      0x34 },
+	{ WCD934X_CPE_FLL_USER_CTL_2,                      0x0b },
+	{ WCD934X_CPE_FLL_USER_CTL_3,                      0x02 },
+	{ WCD934X_CPE_FLL_USER_CTL_4,                      0x04 },
+	{ WCD934X_CPE_FLL_USER_CTL_5,                      0x02 },
+	{ WCD934X_CPE_FLL_USER_CTL_6,                      0x6e },
+	{ WCD934X_CPE_FLL_USER_CTL_7,                      0x00 },
+	{ WCD934X_CPE_FLL_USER_CTL_8,                      0x94 },
+	{ WCD934X_CPE_FLL_USER_CTL_9,                      0x50 },
+	{ WCD934X_CPE_FLL_L_VAL_CTL_0,                     0x53 },
+	{ WCD934X_CPE_FLL_L_VAL_CTL_1,                     0x00 },
+	{ WCD934X_CPE_FLL_DSM_FRAC_CTL_0,                  0x00 },
+	{ WCD934X_CPE_FLL_DSM_FRAC_CTL_1,                  0xff },
+	{ WCD934X_CPE_FLL_CONFIG_CTL_0,                    0x6b },
+	{ WCD934X_CPE_FLL_CONFIG_CTL_1,                    0x05 },
+	{ WCD934X_CPE_FLL_CONFIG_CTL_2,                    0x08 },
+	{ WCD934X_CPE_FLL_CONFIG_CTL_3,                    0x00 },
+	{ WCD934X_CPE_FLL_CONFIG_CTL_4,                    0x10 },
+	{ WCD934X_CPE_FLL_TEST_CTL_0,                      0x80 },
+	{ WCD934X_CPE_FLL_TEST_CTL_1,                      0x00 },
+	{ WCD934X_CPE_FLL_TEST_CTL_2,                      0x00 },
+	{ WCD934X_CPE_FLL_TEST_CTL_3,                      0x00 },
+	{ WCD934X_CPE_FLL_TEST_CTL_4,                      0x00 },
+	{ WCD934X_CPE_FLL_TEST_CTL_5,                      0x00 },
+	{ WCD934X_CPE_FLL_TEST_CTL_6,                      0x00 },
+	{ WCD934X_CPE_FLL_TEST_CTL_7,                      0x33 },
+	{ WCD934X_CPE_FLL_FREQ_CTL_0,                      0x00 },
+	{ WCD934X_CPE_FLL_FREQ_CTL_1,                      0x00 },
+	{ WCD934X_CPE_FLL_FREQ_CTL_2,                      0x00 },
+	{ WCD934X_CPE_FLL_FREQ_CTL_3,                      0x00 },
+	{ WCD934X_CPE_FLL_SSC_CTL_0,                       0x00 },
+	{ WCD934X_CPE_FLL_SSC_CTL_1,                       0x00 },
+	{ WCD934X_CPE_FLL_SSC_CTL_2,                       0x00 },
+	{ WCD934X_CPE_FLL_SSC_CTL_3,                       0x00 },
+	{ WCD934X_CPE_FLL_FLL_MODE,                        0x20 },
+	{ WCD934X_CPE_FLL_STATUS_0,                        0x00 },
+	{ WCD934X_CPE_FLL_STATUS_1,                        0x00 },
+	{ WCD934X_CPE_FLL_STATUS_2,                        0x00 },
+	{ WCD934X_CPE_FLL_STATUS_3,                        0x00 },
+	{ WCD934X_I2S_FLL_USER_CTL_0,                      0x41 },
+	{ WCD934X_I2S_FLL_USER_CTL_1,                      0x94 },
+	{ WCD934X_I2S_FLL_USER_CTL_2,                      0x08 },
+	{ WCD934X_I2S_FLL_USER_CTL_3,                      0x02 },
+	{ WCD934X_I2S_FLL_USER_CTL_4,                      0x04 },
+	{ WCD934X_I2S_FLL_USER_CTL_5,                      0x02 },
+	{ WCD934X_I2S_FLL_USER_CTL_6,                      0x40 },
+	{ WCD934X_I2S_FLL_USER_CTL_7,                      0x00 },
+	{ WCD934X_I2S_FLL_USER_CTL_8,                      0x5f },
+	{ WCD934X_I2S_FLL_USER_CTL_9,                      0x02 },
+	{ WCD934X_I2S_FLL_L_VAL_CTL_0,                     0x40 },
+	{ WCD934X_I2S_FLL_L_VAL_CTL_1,                     0x00 },
+	{ WCD934X_I2S_FLL_DSM_FRAC_CTL_0,                  0x00 },
+	{ WCD934X_I2S_FLL_DSM_FRAC_CTL_1,                  0xff },
+	{ WCD934X_I2S_FLL_CONFIG_CTL_0,                    0x6b },
+	{ WCD934X_I2S_FLL_CONFIG_CTL_1,                    0x05 },
+	{ WCD934X_I2S_FLL_CONFIG_CTL_2,                    0x08 },
+	{ WCD934X_I2S_FLL_CONFIG_CTL_3,                    0x00 },
+	{ WCD934X_I2S_FLL_CONFIG_CTL_4,                    0x30 },
+	{ WCD934X_I2S_FLL_TEST_CTL_0,                      0x80 },
+	{ WCD934X_I2S_FLL_TEST_CTL_1,                      0x00 },
+	{ WCD934X_I2S_FLL_TEST_CTL_2,                      0x00 },
+	{ WCD934X_I2S_FLL_TEST_CTL_3,                      0x00 },
+	{ WCD934X_I2S_FLL_TEST_CTL_4,                      0x00 },
+	{ WCD934X_I2S_FLL_TEST_CTL_5,                      0x00 },
+	{ WCD934X_I2S_FLL_TEST_CTL_6,                      0x00 },
+	{ WCD934X_I2S_FLL_TEST_CTL_7,                      0xff },
+	{ WCD934X_I2S_FLL_FREQ_CTL_0,                      0x00 },
+	{ WCD934X_I2S_FLL_FREQ_CTL_1,                      0x00 },
+	{ WCD934X_I2S_FLL_FREQ_CTL_2,                      0x00 },
+	{ WCD934X_I2S_FLL_FREQ_CTL_3,                      0x00 },
+	{ WCD934X_I2S_FLL_SSC_CTL_0,                       0x00 },
+	{ WCD934X_I2S_FLL_SSC_CTL_1,                       0x00 },
+	{ WCD934X_I2S_FLL_SSC_CTL_2,                       0x00 },
+	{ WCD934X_I2S_FLL_SSC_CTL_3,                       0x00 },
+	{ WCD934X_I2S_FLL_FLL_MODE,                        0x00 },
+	{ WCD934X_I2S_FLL_STATUS_0,                        0x00 },
+	{ WCD934X_I2S_FLL_STATUS_1,                        0x00 },
+	{ WCD934X_I2S_FLL_STATUS_2,                        0x00 },
+	{ WCD934X_I2S_FLL_STATUS_3,                        0x00 },
+	{ WCD934X_SB_FLL_USER_CTL_0,                       0x41 },
+	{ WCD934X_SB_FLL_USER_CTL_1,                       0x94 },
+	{ WCD934X_SB_FLL_USER_CTL_2,                       0x08 },
+	{ WCD934X_SB_FLL_USER_CTL_3,                       0x02 },
+	{ WCD934X_SB_FLL_USER_CTL_4,                       0x04 },
+	{ WCD934X_SB_FLL_USER_CTL_5,                       0x02 },
+	{ WCD934X_SB_FLL_USER_CTL_6,                       0x40 },
+	{ WCD934X_SB_FLL_USER_CTL_7,                       0x00 },
+	{ WCD934X_SB_FLL_USER_CTL_8,                       0x5e },
+	{ WCD934X_SB_FLL_USER_CTL_9,                       0x01 },
+	{ WCD934X_SB_FLL_L_VAL_CTL_0,                      0x40 },
+	{ WCD934X_SB_FLL_L_VAL_CTL_1,                      0x00 },
+	{ WCD934X_SB_FLL_DSM_FRAC_CTL_0,                   0x00 },
+	{ WCD934X_SB_FLL_DSM_FRAC_CTL_1,                   0xff },
+	{ WCD934X_SB_FLL_CONFIG_CTL_0,                     0x6b },
+	{ WCD934X_SB_FLL_CONFIG_CTL_1,                     0x05 },
+	{ WCD934X_SB_FLL_CONFIG_CTL_2,                     0x08 },
+	{ WCD934X_SB_FLL_CONFIG_CTL_3,                     0x00 },
+	{ WCD934X_SB_FLL_CONFIG_CTL_4,                     0x10 },
+	{ WCD934X_SB_FLL_TEST_CTL_0,                       0x00 },
+	{ WCD934X_SB_FLL_TEST_CTL_1,                       0x00 },
+	{ WCD934X_SB_FLL_TEST_CTL_2,                       0x00 },
+	{ WCD934X_SB_FLL_TEST_CTL_3,                       0x00 },
+	{ WCD934X_SB_FLL_TEST_CTL_4,                       0x00 },
+	{ WCD934X_SB_FLL_TEST_CTL_5,                       0x00 },
+	{ WCD934X_SB_FLL_TEST_CTL_6,                       0x00 },
+	{ WCD934X_SB_FLL_TEST_CTL_7,                       0xff },
+	{ WCD934X_SB_FLL_FREQ_CTL_0,                       0x00 },
+	{ WCD934X_SB_FLL_FREQ_CTL_1,                       0x00 },
+	{ WCD934X_SB_FLL_FREQ_CTL_2,                       0x00 },
+	{ WCD934X_SB_FLL_FREQ_CTL_3,                       0x00 },
+	{ WCD934X_SB_FLL_SSC_CTL_0,                        0x00 },
+	{ WCD934X_SB_FLL_SSC_CTL_1,                        0x00 },
+	{ WCD934X_SB_FLL_SSC_CTL_2,                        0x00 },
+	{ WCD934X_SB_FLL_SSC_CTL_3,                        0x00 },
+	{ WCD934X_SB_FLL_FLL_MODE,                         0x00 },
+	{ WCD934X_SB_FLL_STATUS_0,                         0x00 },
+	{ WCD934X_SB_FLL_STATUS_1,                         0x00 },
+	{ WCD934X_SB_FLL_STATUS_2,                         0x00 },
+	{ WCD934X_SB_FLL_STATUS_3,                         0x00 },
+	{ WCD934X_PAGE2_PAGE_REGISTER,                     0x00 },
+	{ WCD934X_CPE_SS_CPE_CTL,                          0x05 },
+	{ WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0,             0x01 },
+	{ WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_1,             0x00 },
+	{ WCD934X_CPE_SS_PWR_CPEFLL_CTL,                   0x02 },
+	{ WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0,         0xff },
+	{ WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1,         0x0f },
+	{ WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_OVERRIDE,  0x00 },
+	{ WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0,        0xff },
+	{ WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1,        0xff },
+	{ WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2,        0xff },
+	{ WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3,        0xff },
+	{ WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_4,        0xff },
+	{ WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_5,        0xff },
+	{ WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN,           0x07 },
+	{ WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,              0x00 },
+	{ WCD934X_CPE_SS_SOC_SW_COLLAPSE_OVERRIDE_CTL,     0x20 },
+	{ WCD934X_CPE_SS_SOC_SW_COLLAPSE_OVERRIDE_CTL1,    0x00 },
+	{ WCD934X_CPE_SS_US_BUF_INT_PERIOD,                0x60 },
+	{ WCD934X_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD,        0x13 },
+	{ WCD934X_CPE_SS_SVA_CFG,                          0x41 },
+	{ WCD934X_CPE_SS_US_CFG,                           0x00 },
+	{ WCD934X_CPE_SS_MAD_CTL,                          0x00 },
+	{ WCD934X_CPE_SS_CPAR_CTL,                         0x00 },
+	{ WCD934X_CPE_SS_DMIC0_CTL,                        0x00 },
+	{ WCD934X_CPE_SS_DMIC1_CTL,                        0x00 },
+	{ WCD934X_CPE_SS_DMIC2_CTL,                        0x00 },
+	{ WCD934X_CPE_SS_DMIC_CFG,                         0x80 },
+	{ WCD934X_CPE_SS_CPAR_CFG,                         0x00 },
+	{ WCD934X_CPE_SS_WDOG_CFG,                         0x01 },
+	{ WCD934X_CPE_SS_BACKUP_INT,                       0x00 },
+	{ WCD934X_CPE_SS_STATUS,                           0x00 },
+	{ WCD934X_CPE_SS_CPE_OCD_CFG,                      0x00 },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A,             0xff },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B,             0x3f },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_MASK_1A,             0xff },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_MASK_1B,             0x3f },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0A,           0x00 },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0B,           0x00 },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_STATUS_1A,           0x00 },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_STATUS_1B,           0x00 },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_0A,            0x00 },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_0B,            0x00 },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_1A,            0x00 },
+	{ WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_1B,            0x00 },
+	{ WCD934X_SOC_MAD_MAIN_CTL_1,                      0x00 },
+	{ WCD934X_SOC_MAD_MAIN_CTL_2,                      0x00 },
+	{ WCD934X_SOC_MAD_AUDIO_CTL_1,                     0x00 },
+	{ WCD934X_SOC_MAD_AUDIO_CTL_2,                     0x00 },
+	{ WCD934X_SOC_MAD_AUDIO_CTL_3,                     0x00 },
+	{ WCD934X_SOC_MAD_AUDIO_CTL_4,                     0x00 },
+	{ WCD934X_SOC_MAD_AUDIO_CTL_5,                     0x00 },
+	{ WCD934X_SOC_MAD_AUDIO_CTL_6,                     0x00 },
+	{ WCD934X_SOC_MAD_AUDIO_CTL_7,                     0x00 },
+	{ WCD934X_SOC_MAD_AUDIO_CTL_8,                     0x00 },
+	{ WCD934X_SOC_MAD_AUDIO_IIR_CTL_PTR,               0x00 },
+	{ WCD934X_SOC_MAD_AUDIO_IIR_CTL_VAL,               0x40 },
+	{ WCD934X_SOC_MAD_ULTR_CTL_1,                      0x00 },
+	{ WCD934X_SOC_MAD_ULTR_CTL_2,                      0x00 },
+	{ WCD934X_SOC_MAD_ULTR_CTL_3,                      0x00 },
+	{ WCD934X_SOC_MAD_ULTR_CTL_4,                      0x00 },
+	{ WCD934X_SOC_MAD_ULTR_CTL_5,                      0x00 },
+	{ WCD934X_SOC_MAD_ULTR_CTL_6,                      0x00 },
+	{ WCD934X_SOC_MAD_ULTR_CTL_7,                      0x00 },
+	{ WCD934X_SOC_MAD_BEACON_CTL_1,                    0x00 },
+	{ WCD934X_SOC_MAD_BEACON_CTL_2,                    0x00 },
+	{ WCD934X_SOC_MAD_BEACON_CTL_3,                    0x00 },
+	{ WCD934X_SOC_MAD_BEACON_CTL_4,                    0x00 },
+	{ WCD934X_SOC_MAD_BEACON_CTL_5,                    0x00 },
+	{ WCD934X_SOC_MAD_BEACON_CTL_6,                    0x00 },
+	{ WCD934X_SOC_MAD_BEACON_CTL_7,                    0x00 },
+	{ WCD934X_SOC_MAD_BEACON_CTL_8,                    0x00 },
+	{ WCD934X_SOC_MAD_BEACON_IIR_CTL_PTR,              0x00 },
+	{ WCD934X_SOC_MAD_BEACON_IIR_CTL_VAL,              0x00 },
+	{ WCD934X_SOC_MAD_INP_SEL,                         0x00 },
+	{ WCD934X_PAGE4_PAGE_REGISTER,                     0x00 },
+	{ WCD934X_INTR_CFG,                                0x00 },
+	{ WCD934X_INTR_CLR_COMMIT,                         0x00 },
+	{ WCD934X_INTR_PIN1_MASK0,                         0xff },
+	{ WCD934X_INTR_PIN1_MASK1,                         0xff },
+	{ WCD934X_INTR_PIN1_MASK2,                         0xff },
+	{ WCD934X_INTR_PIN1_MASK3,                         0xff },
+	{ WCD934X_INTR_PIN1_STATUS0,                       0x00 },
+	{ WCD934X_INTR_PIN1_STATUS1,                       0x00 },
+	{ WCD934X_INTR_PIN1_STATUS2,                       0x00 },
+	{ WCD934X_INTR_PIN1_STATUS3,                       0x00 },
+	{ WCD934X_INTR_PIN1_CLEAR0,                        0x00 },
+	{ WCD934X_INTR_PIN1_CLEAR1,                        0x00 },
+	{ WCD934X_INTR_PIN1_CLEAR2,                        0x00 },
+	{ WCD934X_INTR_PIN1_CLEAR3,                        0x00 },
+	{ WCD934X_INTR_PIN2_MASK3,                         0xff },
+	{ WCD934X_INTR_PIN2_STATUS3,                       0x00 },
+	{ WCD934X_INTR_PIN2_CLEAR3,                        0x00 },
+	{ WCD934X_INTR_CPESS_SUMRY_MASK2,                  0xff },
+	{ WCD934X_INTR_CPESS_SUMRY_MASK3,                  0xff },
+	{ WCD934X_INTR_CPESS_SUMRY_STATUS2,                0x00 },
+	{ WCD934X_INTR_CPESS_SUMRY_STATUS3,                0x00 },
+	{ WCD934X_INTR_CPESS_SUMRY_CLEAR2,                 0x00 },
+	{ WCD934X_INTR_CPESS_SUMRY_CLEAR3,                 0x00 },
+	{ WCD934X_INTR_LEVEL0,                             0x03 },
+	{ WCD934X_INTR_LEVEL1,                             0xe0 },
+	{ WCD934X_INTR_LEVEL2,                             0x94 },
+	{ WCD934X_INTR_LEVEL3,                             0x80 },
+	{ WCD934X_INTR_BYPASS0,                            0x00 },
+	{ WCD934X_INTR_BYPASS1,                            0x00 },
+	{ WCD934X_INTR_BYPASS2,                            0x00 },
+	{ WCD934X_INTR_BYPASS3,                            0x00 },
+	{ WCD934X_INTR_SET0,                               0x00 },
+	{ WCD934X_INTR_SET1,                               0x00 },
+	{ WCD934X_INTR_SET2,                               0x00 },
+	{ WCD934X_INTR_SET3,                               0x00 },
+	{ WCD934X_INTR_CODEC_MISC_MASK,                    0x7f },
+	{ WCD934X_INTR_CODEC_MISC_STATUS,                  0x00 },
+	{ WCD934X_INTR_CODEC_MISC_CLEAR,                   0x00 },
+	{ WCD934X_PAGE5_PAGE_REGISTER,                     0x00 },
+	{ WCD934X_SLNQ_DIG_DEVICE,                         0x49 },
+	{ WCD934X_SLNQ_DIG_REVISION,                       0x01 },
+	{ WCD934X_SLNQ_DIG_H_COMMAND,                      0x00 },
+	{ WCD934X_SLNQ_DIG_NUMBER_OF_BYTE_MSB,             0x00 },
+	{ WCD934X_SLNQ_DIG_NUMBER_OF_BYTE_LSB,             0x00 },
+	{ WCD934X_SLNQ_DIG_MASTER_ADDRESS_MSB,             0x00 },
+	{ WCD934X_SLNQ_DIG_MASTER_ADDRESS_LSB,             0x00 },
+	{ WCD934X_SLNQ_DIG_SLAVE_ADDRESS_MSB,              0x00 },
+	{ WCD934X_SLNQ_DIG_SLAVE_ADDRESS_LSB,              0x00 },
+	{ WCD934X_SLNQ_DIG_TIMER0_INTERRUPT_MSB,           0x40 },
+	{ WCD934X_SLNQ_DIG_TIMER0_INTERRUPT_LSB,           0x00 },
+	{ WCD934X_SLNQ_DIG_TIMER1_INTERRUPT_MSB,           0x40 },
+	{ WCD934X_SLNQ_DIG_TIMER1_INTERRUPT_LSB,           0x00 },
+	{ WCD934X_SLNQ_DIG_TIMER2_INTERRUPT_MSB,           0x40 },
+	{ WCD934X_SLNQ_DIG_TIMER2_INTERRUPT_LSB,           0x00 },
+	{ WCD934X_SLNQ_DIG_COMM_CTL,                       0x00 },
+	{ WCD934X_SLNQ_DIG_FRAME_CTRL,                     0x01 },
+	{ WCD934X_SLNQ_DIG_PDM_2ND_DATA_CH1_2,             0x77 },
+	{ WCD934X_SLNQ_DIG_PDM_2ND_DATA_CH3_4,             0x77 },
+	{ WCD934X_SLNQ_DIG_PDM_2ND_DATA_CH5,               0x70 },
+	{ WCD934X_SLNQ_DIG_SW_EVENT_RD,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SW_EVENT_CTRL,                  0x00 },
+	{ WCD934X_SLNQ_DIG_PDM_SELECT_1,                   0x12 },
+	{ WCD934X_SLNQ_DIG_PDM_SELECT_2,                   0x34 },
+	{ WCD934X_SLNQ_DIG_PDM_SELECT_3,                   0x55 },
+	{ WCD934X_SLNQ_DIG_PDM_SAMPLING_FREQ,              0x01 },
+	{ WCD934X_SLNQ_DIG_PDM_DC_CONVERSION_CTL,          0x00 },
+	{ WCD934X_SLNQ_DIG_PDM_DC_CONVERSION_SEL,          0x11 },
+	{ WCD934X_SLNQ_DIG_PDM_DC_CONV_CHA_MSB,            0x00 },
+	{ WCD934X_SLNQ_DIG_PDM_DC_CONV_CHA_LSB,            0x00 },
+	{ WCD934X_SLNQ_DIG_PDM_DC_CONV_CHB_MSB,            0x00 },
+	{ WCD934X_SLNQ_DIG_PDM_DC_CONV_CHB_LSB,            0x00 },
+	{ WCD934X_SLNQ_DIG_RAM_CNTRL,                      0x01 },
+	{ WCD934X_SLNQ_DIG_SRAM_BANK,                      0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_0,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_1,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_2,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_3,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_4,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_5,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_6,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_7,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_8,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_9,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_A,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_B,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_C,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_D,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_E,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_F,                    0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_10,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_11,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_12,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_13,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_14,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_15,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_16,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_17,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_18,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_19,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_1A,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_1B,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_1C,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_1D,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_1E,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_1F,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_20,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_21,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_22,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_23,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_24,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_25,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_26,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_27,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_28,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_29,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_2A,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_2B,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_2C,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_2D,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_2E,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_2F,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_30,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_31,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_32,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_33,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_34,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_35,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_36,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_37,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_38,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_39,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_3A,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_3B,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_3C,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_3D,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_3E,                   0x00 },
+	{ WCD934X_SLNQ_DIG_SRAM_BYTE_3F,                   0x00 },
+	{ WCD934X_SLNQ_DIG_TOP_CTRL1,                      0x00 },
+	{ WCD934X_SLNQ_DIG_TOP_CTRL2,                      0x00 },
+	{ WCD934X_SLNQ_DIG_PDM_CTRL,                       0x00 },
+	{ WCD934X_SLNQ_DIG_PDM_MUTE_CTRL,                  0x20 },
+	{ WCD934X_SLNQ_DIG_DEC_BYPASS_CTRL,                0x00 },
+	{ WCD934X_SLNQ_DIG_DEC_BYPASS_STATUS,              0x00 },
+	{ WCD934X_SLNQ_DIG_DEC_BYPASS_FS,                  0x00 },
+	{ WCD934X_SLNQ_DIG_DEC_BYPASS_IN_SEL,              0x00 },
+	{ WCD934X_SLNQ_DIG_GPOUT_ENABLE,                   0x00 },
+	{ WCD934X_SLNQ_DIG_GPOUT_VAL,                      0x00 },
+	{ WCD934X_SLNQ_DIG_ANA_INTERRUPT_MASK,             0x00 },
+	{ WCD934X_SLNQ_DIG_ANA_INTERRUPT_STATUS,           0x00 },
+	{ WCD934X_SLNQ_DIG_ANA_INTERRUPT_CLR,              0x00 },
+	{ WCD934X_SLNQ_DIG_IP_TESTING,                     0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_CNTRL,                0x0f },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_CNT,                  0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_CNT_MSB,              0xff },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_CNT_LSB,              0xff },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_MASK0,                0xff },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_MASK1,                0xff },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_MASK2,                0xff },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_MASK3,                0xff },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_MASK4,                0x1f },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_STATUS0,              0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_STATUS1,              0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_STATUS2,              0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_STATUS3,              0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_STATUS4,              0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_CLR0,                 0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_CLR1,                 0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_CLR2,                 0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_CLR3,                 0x00 },
+	{ WCD934X_SLNQ_DIG_INTERRUPT_CLR4,                 0x00 },
+	{ WCD934X_ANA_PAGE_REGISTER,                       0x00 },
+	{ WCD934X_ANA_BIAS,                                0x00 },
+	{ WCD934X_ANA_RCO,                                 0x00 },
+	{ WCD934X_ANA_PAGE6_SPARE2,                        0x00 },
+	{ WCD934X_ANA_PAGE6_SPARE3,                        0x00 },
+	{ WCD934X_ANA_BUCK_CTL,                            0x00 },
+	{ WCD934X_ANA_BUCK_STATUS,                         0x00 },
+	{ WCD934X_ANA_RX_SUPPLIES,                         0x00 },
+	{ WCD934X_ANA_HPH,                                 0x0c },
+	{ WCD934X_ANA_EAR,                                 0x00 },
+	{ WCD934X_ANA_LO_1_2,                              0x3c },
+	{ WCD934X_ANA_MAD_SETUP,                           0x01 },
+	{ WCD934X_ANA_AMIC1,                               0x20 },
+	{ WCD934X_ANA_AMIC2,                               0x00 },
+	{ WCD934X_ANA_AMIC3,                               0x20 },
+	{ WCD934X_ANA_AMIC4,                               0x00 },
+	{ WCD934X_ANA_MBHC_MECH,                           0x39 },
+	{ WCD934X_ANA_MBHC_ELECT,                          0x08 },
+	{ WCD934X_ANA_MBHC_ZDET,                           0x00 },
+	{ WCD934X_ANA_MBHC_RESULT_1,                       0x00 },
+	{ WCD934X_ANA_MBHC_RESULT_2,                       0x00 },
+	{ WCD934X_ANA_MBHC_RESULT_3,                       0x00 },
+	{ WCD934X_ANA_MBHC_BTN0,                           0x00 },
+	{ WCD934X_ANA_MBHC_BTN1,                           0x10 },
+	{ WCD934X_ANA_MBHC_BTN2,                           0x20 },
+	{ WCD934X_ANA_MBHC_BTN3,                           0x30 },
+	{ WCD934X_ANA_MBHC_BTN4,                           0x40 },
+	{ WCD934X_ANA_MBHC_BTN5,                           0x50 },
+	{ WCD934X_ANA_MBHC_BTN6,                           0x60 },
+	{ WCD934X_ANA_MBHC_BTN7,                           0x70 },
+	{ WCD934X_ANA_MICB1,                               0x10 },
+	{ WCD934X_ANA_MICB2,                               0x10 },
+	{ WCD934X_ANA_MICB2_RAMP,                          0x00 },
+	{ WCD934X_ANA_MICB3,                               0x10 },
+	{ WCD934X_ANA_MICB4,                               0x10 },
+	{ WCD934X_ANA_VBADC,                               0x00 },
+	{ WCD934X_BIAS_CTL,                                0x28 },
+	{ WCD934X_BIAS_VBG_FINE_ADJ,                       0x65 },
+	{ WCD934X_RCO_CTRL_1,                              0x44 },
+	{ WCD934X_RCO_CTRL_2,                              0x48 },
+	{ WCD934X_RCO_CAL,                                 0x00 },
+	{ WCD934X_RCO_CAL_1,                               0x00 },
+	{ WCD934X_RCO_CAL_2,                               0x00 },
+	{ WCD934X_RCO_TEST_CTRL,                           0x00 },
+	{ WCD934X_RCO_CAL_OUT_1,                           0x00 },
+	{ WCD934X_RCO_CAL_OUT_2,                           0x00 },
+	{ WCD934X_RCO_CAL_OUT_3,                           0x00 },
+	{ WCD934X_RCO_CAL_OUT_4,                           0x00 },
+	{ WCD934X_RCO_CAL_OUT_5,                           0x00 },
+	{ WCD934X_SIDO_MODE_1,                             0x84 },
+	{ WCD934X_SIDO_MODE_2,                             0xfe },
+	{ WCD934X_SIDO_MODE_3,                             0xf6 },
+	{ WCD934X_SIDO_MODE_4,                             0x56 },
+	{ WCD934X_SIDO_VCL_1,                              0x00 },
+	{ WCD934X_SIDO_VCL_2,                              0x6c },
+	{ WCD934X_SIDO_VCL_3,                              0x44 },
+	{ WCD934X_SIDO_CCL_1,                              0x57 },
+	{ WCD934X_SIDO_CCL_2,                              0x92 },
+	{ WCD934X_SIDO_CCL_3,                              0x35 },
+	{ WCD934X_SIDO_CCL_4,                              0x61 },
+	{ WCD934X_SIDO_CCL_5,                              0x6d },
+	{ WCD934X_SIDO_CCL_6,                              0x60 },
+	{ WCD934X_SIDO_CCL_7,                              0x6f },
+	{ WCD934X_SIDO_CCL_8,                              0x6f },
+	{ WCD934X_SIDO_CCL_9,                              0x6e },
+	{ WCD934X_SIDO_CCL_10,                             0x26 },
+	{ WCD934X_SIDO_FILTER_1,                           0x92 },
+	{ WCD934X_SIDO_FILTER_2,                           0x54 },
+	{ WCD934X_SIDO_DRIVER_1,                           0x77 },
+	{ WCD934X_SIDO_DRIVER_2,                           0x55 },
+	{ WCD934X_SIDO_DRIVER_3,                           0x55 },
+	{ WCD934X_SIDO_CAL_CODE_EXT_1,                     0x9c },
+	{ WCD934X_SIDO_CAL_CODE_EXT_2,                     0x82 },
+	{ WCD934X_SIDO_CAL_CODE_OUT_1,                     0x00 },
+	{ WCD934X_SIDO_CAL_CODE_OUT_2,                     0x00 },
+	{ WCD934X_SIDO_TEST_1,                             0x00 },
+	{ WCD934X_SIDO_TEST_2,                             0x00 },
+	{ WCD934X_MBHC_CTL_CLK,                            0x30 },
+	{ WCD934X_MBHC_CTL_ANA,                            0x00 },
+	{ WCD934X_MBHC_CTL_SPARE_1,                        0x00 },
+	{ WCD934X_MBHC_CTL_SPARE_2,                        0x00 },
+	{ WCD934X_MBHC_CTL_BCS,                            0x00 },
+	{ WCD934X_MBHC_STATUS_SPARE_1,                     0x00 },
+	{ WCD934X_MBHC_TEST_CTL,                           0x00 },
+	{ WCD934X_VBADC_SUBBLOCK_EN,                       0xde },
+	{ WCD934X_VBADC_IBIAS_FE,                          0x58 },
+	{ WCD934X_VBADC_BIAS_ADC,                          0x51 },
+	{ WCD934X_VBADC_FE_CTRL,                           0x1c },
+	{ WCD934X_VBADC_ADC_REF,                           0x20 },
+	{ WCD934X_VBADC_ADC_IO,                            0x80 },
+	{ WCD934X_VBADC_ADC_SAR,                           0xff },
+	{ WCD934X_VBADC_DEBUG,                             0x00 },
+	{ WCD934X_LDOH_MODE,                               0x2b },
+	{ WCD934X_LDOH_BIAS,                               0x68 },
+	{ WCD934X_LDOH_STB_LOADS,                          0x00 },
+	{ WCD934X_LDOH_SLOWRAMP,                           0x50 },
+	{ WCD934X_MICB1_TEST_CTL_1,                        0x1a },
+	{ WCD934X_MICB1_TEST_CTL_2,                        0x18 },
+	{ WCD934X_MICB1_TEST_CTL_3,                        0xa4 },
+	{ WCD934X_MICB2_TEST_CTL_1,                        0x1a },
+	{ WCD934X_MICB2_TEST_CTL_2,                        0x18 },
+	{ WCD934X_MICB2_TEST_CTL_3,                        0xa4 },
+	{ WCD934X_MICB3_TEST_CTL_1,                        0x1a },
+	{ WCD934X_MICB3_TEST_CTL_2,                        0x18 },
+	{ WCD934X_MICB3_TEST_CTL_3,                        0xa4 },
+	{ WCD934X_MICB4_TEST_CTL_1,                        0x1a },
+	{ WCD934X_MICB4_TEST_CTL_2,                        0x18 },
+	{ WCD934X_MICB4_TEST_CTL_3,                        0xa4 },
+	{ WCD934X_TX_COM_ADC_VCM,                          0x39 },
+	{ WCD934X_TX_COM_BIAS_ATEST,                       0xc0 },
+	{ WCD934X_TX_COM_ADC_INT1_IB,                      0x6f },
+	{ WCD934X_TX_COM_ADC_INT2_IB,                      0x4f },
+	{ WCD934X_TX_COM_TXFE_DIV_CTL,                     0x2e },
+	{ WCD934X_TX_COM_TXFE_DIV_START,                   0x00 },
+	{ WCD934X_TX_COM_TXFE_DIV_STOP_9P6M,               0xc7 },
+	{ WCD934X_TX_COM_TXFE_DIV_STOP_12P288M,            0xff },
+	{ WCD934X_TX_1_2_TEST_EN,                          0xcc },
+	{ WCD934X_TX_1_2_ADC_IB,                           0x09 },
+	{ WCD934X_TX_1_2_ATEST_REFCTL,                     0x0a },
+	{ WCD934X_TX_1_2_TEST_CTL,                         0x38 },
+	{ WCD934X_TX_1_2_TEST_BLK_EN,                      0xff },
+	{ WCD934X_TX_1_2_TXFE_CLKDIV,                      0x00 },
+	{ WCD934X_TX_1_2_SAR1_ERR,                         0x00 },
+	{ WCD934X_TX_1_2_SAR2_ERR,                         0x00 },
+	{ WCD934X_TX_3_4_TEST_EN,                          0xcc },
+	{ WCD934X_TX_3_4_ADC_IB,                           0x09 },
+	{ WCD934X_TX_3_4_ATEST_REFCTL,                     0x0a },
+	{ WCD934X_TX_3_4_TEST_CTL,                         0x38 },
+	{ WCD934X_TX_3_4_TEST_BLK_EN,                      0xff },
+	{ WCD934X_TX_3_4_TXFE_CLKDIV,                      0x00 },
+	{ WCD934X_TX_3_4_SAR1_ERR,                         0x00 },
+	{ WCD934X_TX_3_4_SAR2_ERR,                         0x00 },
+	{ WCD934X_CLASSH_MODE_1,                           0x40 },
+	{ WCD934X_CLASSH_MODE_2,                           0x3a },
+	{ WCD934X_CLASSH_MODE_3,                           0x00 },
+	{ WCD934X_CLASSH_CTRL_VCL_1,                       0x70 },
+	{ WCD934X_CLASSH_CTRL_VCL_2,                       0x82 },
+	{ WCD934X_CLASSH_CTRL_CCL_1,                       0x31 },
+	{ WCD934X_CLASSH_CTRL_CCL_2,                       0x80 },
+	{ WCD934X_CLASSH_CTRL_CCL_3,                       0x80 },
+	{ WCD934X_CLASSH_CTRL_CCL_4,                       0x51 },
+	{ WCD934X_CLASSH_CTRL_CCL_5,                       0x00 },
+	{ WCD934X_CLASSH_BUCK_TMUX_A_D,                    0x00 },
+	{ WCD934X_CLASSH_BUCK_SW_DRV_CNTL,                 0x77 },
+	{ WCD934X_CLASSH_SPARE,                            0x00 },
+	{ WCD934X_FLYBACK_EN,                              0x4e },
+	{ WCD934X_FLYBACK_VNEG_CTRL_1,                     0x0b },
+	{ WCD934X_FLYBACK_VNEG_CTRL_2,                     0x45 },
+	{ WCD934X_FLYBACK_VNEG_CTRL_3,                     0x74 },
+	{ WCD934X_FLYBACK_VNEG_CTRL_4,                     0x7f },
+	{ WCD934X_FLYBACK_VNEG_CTRL_5,                     0x83 },
+	{ WCD934X_FLYBACK_VNEG_CTRL_6,                     0x98 },
+	{ WCD934X_FLYBACK_VNEG_CTRL_7,                     0xa9 },
+	{ WCD934X_FLYBACK_VNEG_CTRL_8,                     0x68 },
+	{ WCD934X_FLYBACK_VNEG_CTRL_9,                     0x64 },
+	{ WCD934X_FLYBACK_VNEGDAC_CTRL_1,                  0xed },
+	{ WCD934X_FLYBACK_VNEGDAC_CTRL_2,                  0xf0 },
+	{ WCD934X_FLYBACK_VNEGDAC_CTRL_3,                  0xa6 },
+	{ WCD934X_FLYBACK_CTRL_1,                          0x65 },
+	{ WCD934X_FLYBACK_TEST_CTL,                        0x00 },
+	{ WCD934X_RX_AUX_SW_CTL,                           0x00 },
+	{ WCD934X_RX_PA_AUX_IN_CONN,                       0x00 },
+	{ WCD934X_RX_TIMER_DIV,                            0x32 },
+	{ WCD934X_RX_OCP_CTL,                              0x1f },
+	{ WCD934X_RX_OCP_COUNT,                            0x77 },
+	{ WCD934X_RX_BIAS_EAR_DAC,                         0xa0 },
+	{ WCD934X_RX_BIAS_EAR_AMP,                         0xaa },
+	{ WCD934X_RX_BIAS_HPH_LDO,                         0xa9 },
+	{ WCD934X_RX_BIAS_HPH_PA,                          0xaa },
+	{ WCD934X_RX_BIAS_HPH_RDACBUFF_CNP2,               0x8a },
+	{ WCD934X_RX_BIAS_HPH_RDAC_LDO,                    0x88 },
+	{ WCD934X_RX_BIAS_HPH_CNP1,                        0x82 },
+	{ WCD934X_RX_BIAS_HPH_LOWPOWER,                    0x82 },
+	{ WCD934X_RX_BIAS_DIFFLO_PA,                       0x80 },
+	{ WCD934X_RX_BIAS_DIFFLO_REF,                      0x88 },
+	{ WCD934X_RX_BIAS_DIFFLO_LDO,                      0x88 },
+	{ WCD934X_RX_BIAS_SELO_DAC_PA,                     0xa8 },
+	{ WCD934X_RX_BIAS_BUCK_RST,                        0x08 },
+	{ WCD934X_RX_BIAS_BUCK_VREF_ERRAMP,                0x44 },
+	{ WCD934X_RX_BIAS_FLYB_ERRAMP,                     0x40 },
+	{ WCD934X_RX_BIAS_FLYB_BUFF,                       0xaa },
+	{ WCD934X_RX_BIAS_FLYB_MID_RST,                    0x14 },
+	{ WCD934X_HPH_L_STATUS,                            0x04 },
+	{ WCD934X_HPH_R_STATUS,                            0x04 },
+	{ WCD934X_HPH_CNP_EN,                              0x80 },
+	{ WCD934X_HPH_CNP_WG_CTL,                          0x9a },
+	{ WCD934X_HPH_CNP_WG_TIME,                         0x14 },
+	{ WCD934X_HPH_OCP_CTL,                             0x28 },
+	{ WCD934X_HPH_AUTO_CHOP,                           0x16 },
+	{ WCD934X_HPH_CHOP_CTL,                            0x83 },
+	{ WCD934X_HPH_PA_CTL1,                             0x46 },
+	{ WCD934X_HPH_PA_CTL2,                             0x50 },
+	{ WCD934X_HPH_L_EN,                                0x80 },
+	{ WCD934X_HPH_L_TEST,                              0xe0 },
+	{ WCD934X_HPH_L_ATEST,                             0x50 },
+	{ WCD934X_HPH_R_EN,                                0x80 },
+	{ WCD934X_HPH_R_TEST,                              0xe0 },
+	{ WCD934X_HPH_R_ATEST,                             0x54 },
+	{ WCD934X_HPH_RDAC_CLK_CTL1,                       0x99 },
+	{ WCD934X_HPH_RDAC_CLK_CTL2,                       0x9b },
+	{ WCD934X_HPH_RDAC_LDO_CTL,                        0x33 },
+	{ WCD934X_HPH_RDAC_CHOP_CLK_LP_CTL,                0x00 },
+	{ WCD934X_HPH_REFBUFF_UHQA_CTL,                    0xa8 },
+	{ WCD934X_HPH_REFBUFF_LP_CTL,                      0x0a },
+	{ WCD934X_HPH_L_DAC_CTL,                           0x00 },
+	{ WCD934X_HPH_R_DAC_CTL,                           0x00 },
+	{ WCD934X_EAR_EN_REG,                              0x60 },
+	{ WCD934X_EAR_CMBUFF,                              0x05 },
+	{ WCD934X_EAR_ICTL,                                0x40 },
+	{ WCD934X_EAR_EN_DBG_CTL,                          0x00 },
+	{ WCD934X_EAR_CNP,                                 0xe0 },
+	{ WCD934X_EAR_DAC_CTL_ATEST,                       0x00 },
+	{ WCD934X_EAR_STATUS_REG,                          0x04 },
+	{ WCD934X_EAR_EAR_MISC,                            0x28 },
+	{ WCD934X_DIFF_LO_MISC,                            0x03 },
+	{ WCD934X_DIFF_LO_LO2_COMPANDER,                   0x00 },
+	{ WCD934X_DIFF_LO_LO1_COMPANDER,                   0x00 },
+	{ WCD934X_DIFF_LO_COMMON,                          0x40 },
+	{ WCD934X_DIFF_LO_BYPASS_EN,                       0x00 },
+	{ WCD934X_DIFF_LO_CNP,                             0x20 },
+	{ WCD934X_DIFF_LO_CORE_OUT_PROG,                   0xa0 },
+	{ WCD934X_DIFF_LO_LDO_OUT_PROG,                    0x00 },
+	{ WCD934X_DIFF_LO_COM_SWCAP_REFBUF_FREQ,           0x8b },
+	{ WCD934X_DIFF_LO_COM_PA_FREQ,                     0xb0 },
+	{ WCD934X_DIFF_LO_RESERVED_REG,                    0x60 },
+	{ WCD934X_DIFF_LO_LO1_STATUS_1,                    0x00 },
+	{ WCD934X_DIFF_LO_LO1_STATUS_2,                    0x00 },
+	{ WCD934X_ANA_NEW_PAGE_REGISTER,                   0x00 },
+	{ WCD934X_HPH_NEW_ANA_HPH2,                        0x00 },
+	{ WCD934X_HPH_NEW_ANA_HPH3,                        0x00 },
+	{ WCD934X_SLNQ_ANA_EN,                             0x02 },
+	{ WCD934X_SLNQ_ANA_STATUS,                         0x00 },
+	{ WCD934X_SLNQ_ANA_LDO_CONFIG,                     0xea },
+	{ WCD934X_SLNQ_ANA_LDO_OCP_CONFIG,                 0x95 },
+	{ WCD934X_SLNQ_ANA_TX_LDO_CONFIG,                  0xb6 },
+	{ WCD934X_SLNQ_ANA_TX_DRV_CONFIG,                  0x26 },
+	{ WCD934X_SLNQ_ANA_RX_CONFIG_1,                    0x64 },
+	{ WCD934X_SLNQ_ANA_RX_CONFIG_2,                    0x40 },
+	{ WCD934X_SLNQ_ANA_PLL_ENABLES,                    0x00 },
+	{ WCD934X_SLNQ_ANA_PLL_PRESET,                     0x08 },
+	{ WCD934X_SLNQ_ANA_PLL_STATUS,                     0x00 },
+	{ WCD934X_CLK_SYS_PLL_ENABLES,                     0x00 },
+	{ WCD934X_CLK_SYS_PLL_PRESET,                      0x00 },
+	{ WCD934X_CLK_SYS_PLL_STATUS,                      0x00 },
+	{ WCD934X_CLK_SYS_MCLK_PRG,                        0x00 },
+	{ WCD934X_CLK_SYS_MCLK2_PRG1,                      0x00 },
+	{ WCD934X_CLK_SYS_MCLK2_PRG2,                      0x00 },
+	{ WCD934X_CLK_SYS_XO_PRG,                          0x00 },
+	{ WCD934X_CLK_SYS_XO_CAP_XTP,                      0x00 },
+	{ WCD934X_CLK_SYS_XO_CAP_XTM,                      0x00 },
+	{ WCD934X_BOOST_BST_EN_DLY,                        0x40 },
+	{ WCD934X_BOOST_CTRL_ILIM,                         0x9c },
+	{ WCD934X_BOOST_VOUT_SETTING,                      0xca },
+	{ WCD934X_SIDO_NEW_VOUT_A_STARTUP,                 0x05 },
+	{ WCD934X_SIDO_NEW_VOUT_D_STARTUP,                 0x0d },
+	{ WCD934X_SIDO_NEW_VOUT_D_FREQ1,                   0x07 },
+	{ WCD934X_SIDO_NEW_VOUT_D_FREQ2,                   0x00 },
+	{ WCD934X_MBHC_NEW_ELECT_REM_CLAMP_CTL,            0x00 },
+	{ WCD934X_MBHC_NEW_CTL_1,                          0x02 },
+	{ WCD934X_MBHC_NEW_CTL_2,                          0x05 },
+	{ WCD934X_MBHC_NEW_PLUG_DETECT_CTL,                0xe9 },
+	{ WCD934X_MBHC_NEW_ZDET_ANA_CTL,                   0x0f },
+	{ WCD934X_MBHC_NEW_ZDET_RAMP_CTL,                  0x00 },
+	{ WCD934X_MBHC_NEW_FSM_STATUS,                     0x00 },
+	{ WCD934X_MBHC_NEW_ADC_RESULT,                     0x00 },
+	{ WCD934X_TX_NEW_AMIC_4_5_SEL,                     0x00 },
+	{ WCD934X_VBADC_NEW_ADC_MODE,                      0x10 },
+	{ WCD934X_VBADC_NEW_ADC_DOUTMSB,                   0x00 },
+	{ WCD934X_VBADC_NEW_ADC_DOUTLSB,                   0x00 },
+	{ WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,               0x00 },
+	{ WCD934X_HPH_NEW_INT_RDAC_HD2_CTL,                0xa0 },
+	{ WCD934X_HPH_NEW_INT_RDAC_VREF_CTL,               0x10 },
+	{ WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL,           0x00 },
+	{ WCD934X_HPH_NEW_INT_RDAC_MISC1,                  0x00 },
+	{ WCD934X_HPH_NEW_INT_PA_MISC1,                    0x22 },
+	{ WCD934X_HPH_NEW_INT_PA_MISC2,                    0x00 },
+	{ WCD934X_HPH_NEW_INT_PA_RDAC_MISC,                0x00 },
+	{ WCD934X_HPH_NEW_INT_HPH_TIMER1,                  0xfe },
+	{ WCD934X_HPH_NEW_INT_HPH_TIMER2,                  0x02 },
+	{ WCD934X_HPH_NEW_INT_HPH_TIMER3,                  0x4e },
+	{ WCD934X_HPH_NEW_INT_HPH_TIMER4,                  0x54 },
+	{ WCD934X_HPH_NEW_INT_PA_RDAC_MISC2,               0x00 },
+	{ WCD934X_HPH_NEW_INT_PA_RDAC_MISC3,               0x00 },
+	{ WCD934X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI,         0x62 },
+	{ WCD934X_RX_NEW_INT_HPH_RDAC_BIAS_ULP,            0x01 },
+	{ WCD934X_RX_NEW_INT_HPH_RDAC_LDO_LP,              0x11 },
+	{ WCD934X_SLNQ_INT_ANA_INT_LDO_TEST,               0x0d },
+	{ WCD934X_SLNQ_INT_ANA_INT_LDO_DEBUG_1,            0x85 },
+	{ WCD934X_SLNQ_INT_ANA_INT_LDO_DEBUG_2,            0xb4 },
+	{ WCD934X_SLNQ_INT_ANA_INT_TX_LDO_TEST,            0x16 },
+	{ WCD934X_SLNQ_INT_ANA_INT_TX_DRV_TEST,            0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_RX_TEST,                0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_RX_TEST_STATUS,         0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_RX_DEBUG_1,             0x50 },
+	{ WCD934X_SLNQ_INT_ANA_INT_RX_DEBUG_2,             0x04 },
+	{ WCD934X_SLNQ_INT_ANA_INT_CLK_CTRL,               0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_RESERVED_1,             0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_RESERVED_2,             0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_POST_DIV_REG0,      0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_POST_DIV_REG1,      0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_REF_DIV_REG0,       0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_REF_DIV_REG1,       0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_FILTER_REG0,        0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_FILTER_REG1,        0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_L_VAL,              0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_M_VAL,              0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_N_VAL,              0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_TEST_REG0,          0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_PFD_CP_DSM_PROG,    0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_VCO_PROG,           0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_TEST_REG1,          0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_LDO_LOCK_CFG,       0x00 },
+	{ WCD934X_SLNQ_INT_ANA_INT_PLL_DIG_LOCK_DET_CFG,   0x00 },
+	{ WCD934X_CLK_SYS_INT_POST_DIV_REG0,               0x00 },
+	{ WCD934X_CLK_SYS_INT_POST_DIV_REG1,               0x00 },
+	{ WCD934X_CLK_SYS_INT_REF_DIV_REG0,                0x00 },
+	{ WCD934X_CLK_SYS_INT_REF_DIV_REG1,                0x00 },
+	{ WCD934X_CLK_SYS_INT_FILTER_REG0,                 0x00 },
+	{ WCD934X_CLK_SYS_INT_FILTER_REG1,                 0x00 },
+	{ WCD934X_CLK_SYS_INT_PLL_L_VAL,                   0x00 },
+	{ WCD934X_CLK_SYS_INT_PLL_M_VAL,                   0x00 },
+	{ WCD934X_CLK_SYS_INT_PLL_N_VAL,                   0x00 },
+	{ WCD934X_CLK_SYS_INT_TEST_REG0,                   0x00 },
+	{ WCD934X_CLK_SYS_INT_PFD_CP_DSM_PROG,             0x00 },
+	{ WCD934X_CLK_SYS_INT_VCO_PROG,                    0x00 },
+	{ WCD934X_CLK_SYS_INT_TEST_REG1,                   0x00 },
+	{ WCD934X_CLK_SYS_INT_LDO_LOCK_CFG,                0x00 },
+	{ WCD934X_CLK_SYS_INT_DIG_LOCK_DET_CFG,            0x00 },
+	{ WCD934X_CLK_SYS_INT_CLK_TEST1,                   0x00 },
+	{ WCD934X_CLK_SYS_INT_CLK_TEST2,                   0x00 },
+	{ WCD934X_CLK_SYS_INT_CLK_TEST3,                   0x00 },
+	{ WCD934X_CLK_SYS_INT_XO_TEST1,                    0x98 },
+	{ WCD934X_CLK_SYS_INT_XO_TEST2,                    0x00 },
+	{ WCD934X_BOOST_INT_VCOMP_HYST,                    0x02 },
+	{ WCD934X_BOOST_INT_VLOOP_FILTER,                  0xef },
+	{ WCD934X_BOOST_INT_CTRL_IDELTA,                   0xa8 },
+	{ WCD934X_BOOST_INT_CTRL_ILIM_STARTUP,             0x17 },
+	{ WCD934X_BOOST_INT_CTRL_MIN_ONTIME,               0x5f },
+	{ WCD934X_BOOST_INT_CTRL_MAX_ONTIME,               0x88 },
+	{ WCD934X_BOOST_INT_CTRL_TIMING,                   0x0a },
+	{ WCD934X_BOOST_INT_TMUX_A_D,                      0x00 },
+	{ WCD934X_BOOST_INT_SW_DRV_CNTL,                   0xf8 },
+	{ WCD934X_BOOST_INT_SPARE1,                        0x00 },
+	{ WCD934X_BOOST_INT_SPARE2,                        0x00 },
+	{ WCD934X_SIDO_NEW_INT_RAMP_STATUS,                0x00 },
+	{ WCD934X_SIDO_NEW_INT_SPARE_1,                    0x00 },
+	{ WCD934X_SIDO_NEW_INT_DEBUG_VOUT_SETTING_A,       0x64 },
+	{ WCD934X_SIDO_NEW_INT_DEBUG_VOUT_SETTING_D,       0x40 },
+	{ WCD934X_SIDO_NEW_INT_RAMP_INC_WAIT,              0x24 },
+	{ WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_CTL,          0x09 },
+	{ WCD934X_SIDO_NEW_INT_RAMP_IBLEED_CTL,            0x7d },
+	{ WCD934X_SIDO_NEW_INT_DEBUG_CPROVR_TEST,          0x00 },
+	{ WCD934X_SIDO_NEW_INT_RAMP_CTL_A,                 0x14 },
+	{ WCD934X_SIDO_NEW_INT_RAMP_CTL_D,                 0x14 },
+	{ WCD934X_SIDO_NEW_INT_RAMP_TIMEOUT_PERIOD,        0x33 },
+	{ WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_SETTING1,     0x3f },
+	{ WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_SETTING2,     0x74 },
+	{ WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_SETTING3,     0x33 },
+	{ WCD934X_SIDO_NEW_INT_HIGH_ACCU_MODE_SEL1,        0x1d },
+	{ WCD934X_SIDO_NEW_INT_HIGH_ACCU_MODE_SEL2,        0x0a },
+	{ WCD934X_MBHC_NEW_INT_SLNQ_HPF,                   0x50 },
+	{ WCD934X_MBHC_NEW_INT_SLNQ_REF,                   0x24 },
+	{ WCD934X_MBHC_NEW_INT_SLNQ_COMP,                  0x50 },
+	{ WCD934X_MBHC_NEW_INT_SPARE_2,                    0x00 },
+	{ WCD934X_PAGE10_PAGE_REGISTER,                    0x00 },
+	{ WCD934X_CDC_ANC0_CLK_RESET_CTL,                  0x00 },
+	{ WCD934X_CDC_ANC0_MODE_1_CTL,                     0x00 },
+	{ WCD934X_CDC_ANC0_MODE_2_CTL,                     0x00 },
+	{ WCD934X_CDC_ANC0_FF_SHIFT,                       0x00 },
+	{ WCD934X_CDC_ANC0_FB_SHIFT,                       0x00 },
+	{ WCD934X_CDC_ANC0_LPF_FF_A_CTL,                   0x00 },
+	{ WCD934X_CDC_ANC0_LPF_FF_B_CTL,                   0x00 },
+	{ WCD934X_CDC_ANC0_LPF_FB_CTL,                     0x00 },
+	{ WCD934X_CDC_ANC0_SMLPF_CTL,                      0x00 },
+	{ WCD934X_CDC_ANC0_DCFLT_SHIFT_CTL,                0x00 },
+	{ WCD934X_CDC_ANC0_IIR_ADAPT_CTL,                  0x00 },
+	{ WCD934X_CDC_ANC0_IIR_COEFF_1_CTL,                0x00 },
+	{ WCD934X_CDC_ANC0_IIR_COEFF_2_CTL,                0x00 },
+	{ WCD934X_CDC_ANC0_FF_A_GAIN_CTL,                  0x00 },
+	{ WCD934X_CDC_ANC0_FF_B_GAIN_CTL,                  0x00 },
+	{ WCD934X_CDC_ANC0_FB_GAIN_CTL,                    0x00 },
+	{ WCD934X_CDC_ANC0_RC_COMMON_CTL,                  0x00 },
+	{ WCD934X_CDC_ANC0_FIFO_COMMON_CTL,                0x88 },
+	{ WCD934X_CDC_ANC0_RC0_STATUS_FMIN_CNTR,           0x00 },
+	{ WCD934X_CDC_ANC0_RC1_STATUS_FMIN_CNTR,           0x00 },
+	{ WCD934X_CDC_ANC0_RC0_STATUS_FMAX_CNTR,           0x00 },
+	{ WCD934X_CDC_ANC0_RC1_STATUS_FMAX_CNTR,           0x00 },
+	{ WCD934X_CDC_ANC0_STATUS_FIFO,                    0x00 },
+	{ WCD934X_CDC_ANC1_CLK_RESET_CTL,                  0x00 },
+	{ WCD934X_CDC_ANC1_MODE_1_CTL,                     0x00 },
+	{ WCD934X_CDC_ANC1_MODE_2_CTL,                     0x00 },
+	{ WCD934X_CDC_ANC1_FF_SHIFT,                       0x00 },
+	{ WCD934X_CDC_ANC1_FB_SHIFT,                       0x00 },
+	{ WCD934X_CDC_ANC1_LPF_FF_A_CTL,                   0x00 },
+	{ WCD934X_CDC_ANC1_LPF_FF_B_CTL,                   0x00 },
+	{ WCD934X_CDC_ANC1_LPF_FB_CTL,                     0x00 },
+	{ WCD934X_CDC_ANC1_SMLPF_CTL,                      0x00 },
+	{ WCD934X_CDC_ANC1_DCFLT_SHIFT_CTL,                0x00 },
+	{ WCD934X_CDC_ANC1_IIR_ADAPT_CTL,                  0x00 },
+	{ WCD934X_CDC_ANC1_IIR_COEFF_1_CTL,                0x00 },
+	{ WCD934X_CDC_ANC1_IIR_COEFF_2_CTL,                0x00 },
+	{ WCD934X_CDC_ANC1_FF_A_GAIN_CTL,                  0x00 },
+	{ WCD934X_CDC_ANC1_FF_B_GAIN_CTL,                  0x00 },
+	{ WCD934X_CDC_ANC1_FB_GAIN_CTL,                    0x00 },
+	{ WCD934X_CDC_ANC1_RC_COMMON_CTL,                  0x00 },
+	{ WCD934X_CDC_ANC1_FIFO_COMMON_CTL,                0x88 },
+	{ WCD934X_CDC_ANC1_RC0_STATUS_FMIN_CNTR,           0x00 },
+	{ WCD934X_CDC_ANC1_RC1_STATUS_FMIN_CNTR,           0x00 },
+	{ WCD934X_CDC_ANC1_RC0_STATUS_FMAX_CNTR,           0x00 },
+	{ WCD934X_CDC_ANC1_RC1_STATUS_FMAX_CNTR,           0x00 },
+	{ WCD934X_CDC_ANC1_STATUS_FIFO,                    0x00 },
+	{ WCD934X_CDC_TX0_TX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_TX0_TX_PATH_CFG0,                    0x10 },
+	{ WCD934X_CDC_TX0_TX_PATH_CFG1,                    0x03 },
+	{ WCD934X_CDC_TX0_TX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_TX0_TX_PATH_192_CTL,                 0x00 },
+	{ WCD934X_CDC_TX0_TX_PATH_192_CFG,                 0x00 },
+	{ WCD934X_CDC_TX0_TX_PATH_SEC0,                    0x00 },
+	{ WCD934X_CDC_TX0_TX_PATH_SEC1,                    0x00 },
+	{ WCD934X_CDC_TX0_TX_PATH_SEC2,                    0x01 },
+	{ WCD934X_CDC_TX0_TX_PATH_SEC3,                    0x3c },
+	{ WCD934X_CDC_TX0_TX_PATH_SEC4,                    0x20 },
+	{ WCD934X_CDC_TX0_TX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_TX0_TX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_TX0_TX_PATH_SEC7,                    0x25 },
+	{ WCD934X_CDC_TX1_TX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_TX1_TX_PATH_CFG0,                    0x10 },
+	{ WCD934X_CDC_TX1_TX_PATH_CFG1,                    0x03 },
+	{ WCD934X_CDC_TX1_TX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_TX1_TX_PATH_192_CTL,                 0x00 },
+	{ WCD934X_CDC_TX1_TX_PATH_192_CFG,                 0x00 },
+	{ WCD934X_CDC_TX1_TX_PATH_SEC0,                    0x00 },
+	{ WCD934X_CDC_TX1_TX_PATH_SEC1,                    0x00 },
+	{ WCD934X_CDC_TX1_TX_PATH_SEC2,                    0x01 },
+	{ WCD934X_CDC_TX1_TX_PATH_SEC3,                    0x3c },
+	{ WCD934X_CDC_TX1_TX_PATH_SEC4,                    0x20 },
+	{ WCD934X_CDC_TX1_TX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_TX1_TX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_TX2_TX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_TX2_TX_PATH_CFG0,                    0x10 },
+	{ WCD934X_CDC_TX2_TX_PATH_CFG1,                    0x03 },
+	{ WCD934X_CDC_TX2_TX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_TX2_TX_PATH_192_CTL,                 0x00 },
+	{ WCD934X_CDC_TX2_TX_PATH_192_CFG,                 0x00 },
+	{ WCD934X_CDC_TX2_TX_PATH_SEC0,                    0x00 },
+	{ WCD934X_CDC_TX2_TX_PATH_SEC1,                    0x00 },
+	{ WCD934X_CDC_TX2_TX_PATH_SEC2,                    0x01 },
+	{ WCD934X_CDC_TX2_TX_PATH_SEC3,                    0x3c },
+	{ WCD934X_CDC_TX2_TX_PATH_SEC4,                    0x20 },
+	{ WCD934X_CDC_TX2_TX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_TX2_TX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_TX3_TX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_TX3_TX_PATH_CFG0,                    0x10 },
+	{ WCD934X_CDC_TX3_TX_PATH_CFG1,                    0x03 },
+	{ WCD934X_CDC_TX3_TX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_TX3_TX_PATH_192_CTL,                 0x00 },
+	{ WCD934X_CDC_TX3_TX_PATH_192_CFG,                 0x00 },
+	{ WCD934X_CDC_TX3_TX_PATH_SEC0,                    0x00 },
+	{ WCD934X_CDC_TX3_TX_PATH_SEC1,                    0x00 },
+	{ WCD934X_CDC_TX3_TX_PATH_SEC2,                    0x01 },
+	{ WCD934X_CDC_TX3_TX_PATH_SEC3,                    0x3c },
+	{ WCD934X_CDC_TX3_TX_PATH_SEC4,                    0x20 },
+	{ WCD934X_CDC_TX3_TX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_TX3_TX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_TX4_TX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_TX4_TX_PATH_CFG0,                    0x10 },
+	{ WCD934X_CDC_TX4_TX_PATH_CFG1,                    0x03 },
+	{ WCD934X_CDC_TX4_TX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_TX4_TX_PATH_192_CTL,                 0x00 },
+	{ WCD934X_CDC_TX4_TX_PATH_192_CFG,                 0x00 },
+	{ WCD934X_CDC_TX4_TX_PATH_SEC0,                    0x00 },
+	{ WCD934X_CDC_TX4_TX_PATH_SEC1,                    0x00 },
+	{ WCD934X_CDC_TX4_TX_PATH_SEC2,                    0x01 },
+	{ WCD934X_CDC_TX4_TX_PATH_SEC3,                    0x3c },
+	{ WCD934X_CDC_TX4_TX_PATH_SEC4,                    0x20 },
+	{ WCD934X_CDC_TX4_TX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_TX4_TX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_TX5_TX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_TX5_TX_PATH_CFG0,                    0x10 },
+	{ WCD934X_CDC_TX5_TX_PATH_CFG1,                    0x03 },
+	{ WCD934X_CDC_TX5_TX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_TX5_TX_PATH_192_CTL,                 0x00 },
+	{ WCD934X_CDC_TX5_TX_PATH_192_CFG,                 0x00 },
+	{ WCD934X_CDC_TX5_TX_PATH_SEC0,                    0x00 },
+	{ WCD934X_CDC_TX5_TX_PATH_SEC1,                    0x00 },
+	{ WCD934X_CDC_TX5_TX_PATH_SEC2,                    0x01 },
+	{ WCD934X_CDC_TX5_TX_PATH_SEC3,                    0x3c },
+	{ WCD934X_CDC_TX5_TX_PATH_SEC4,                    0x20 },
+	{ WCD934X_CDC_TX5_TX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_TX5_TX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_TX6_TX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_TX6_TX_PATH_CFG0,                    0x10 },
+	{ WCD934X_CDC_TX6_TX_PATH_CFG1,                    0x03 },
+	{ WCD934X_CDC_TX6_TX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_TX6_TX_PATH_192_CTL,                 0x00 },
+	{ WCD934X_CDC_TX6_TX_PATH_192_CFG,                 0x00 },
+	{ WCD934X_CDC_TX6_TX_PATH_SEC0,                    0x00 },
+	{ WCD934X_CDC_TX6_TX_PATH_SEC1,                    0x00 },
+	{ WCD934X_CDC_TX6_TX_PATH_SEC2,                    0x01 },
+	{ WCD934X_CDC_TX6_TX_PATH_SEC3,                    0x3c },
+	{ WCD934X_CDC_TX6_TX_PATH_SEC4,                    0x20 },
+	{ WCD934X_CDC_TX6_TX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_TX6_TX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_TX7_TX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_TX7_TX_PATH_CFG0,                    0x10 },
+	{ WCD934X_CDC_TX7_TX_PATH_CFG1,                    0x03 },
+	{ WCD934X_CDC_TX7_TX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_TX7_TX_PATH_192_CTL,                 0x00 },
+	{ WCD934X_CDC_TX7_TX_PATH_192_CFG,                 0x00 },
+	{ WCD934X_CDC_TX7_TX_PATH_SEC0,                    0x00 },
+	{ WCD934X_CDC_TX7_TX_PATH_SEC1,                    0x00 },
+	{ WCD934X_CDC_TX7_TX_PATH_SEC2,                    0x01 },
+	{ WCD934X_CDC_TX7_TX_PATH_SEC3,                    0x3c },
+	{ WCD934X_CDC_TX7_TX_PATH_SEC4,                    0x20 },
+	{ WCD934X_CDC_TX7_TX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_TX7_TX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_TX8_TX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_TX8_TX_PATH_CFG0,                    0x10 },
+	{ WCD934X_CDC_TX8_TX_PATH_CFG1,                    0x03 },
+	{ WCD934X_CDC_TX8_TX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_TX8_TX_PATH_192_CTL,                 0x00 },
+	{ WCD934X_CDC_TX8_TX_PATH_192_CFG,                 0x00 },
+	{ WCD934X_CDC_TX8_TX_PATH_SEC0,                    0x00 },
+	{ WCD934X_CDC_TX8_TX_PATH_SEC1,                    0x00 },
+	{ WCD934X_CDC_TX8_TX_PATH_SEC2,                    0x01 },
+	{ WCD934X_CDC_TX8_TX_PATH_SEC3,                    0x3c },
+	{ WCD934X_CDC_TX8_TX_PATH_SEC4,                    0x20 },
+	{ WCD934X_CDC_TX8_TX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_TX8_TX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL,              0x02 },
+	{ WCD934X_CDC_TX9_SPKR_PROT_PATH_CFG0,             0x00 },
+	{ WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL,             0x02 },
+	{ WCD934X_CDC_TX10_SPKR_PROT_PATH_CFG0,            0x00 },
+	{ WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL,             0x02 },
+	{ WCD934X_CDC_TX11_SPKR_PROT_PATH_CFG0,            0x00 },
+	{ WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL,             0x02 },
+	{ WCD934X_CDC_TX12_SPKR_PROT_PATH_CFG0,            0x00 },
+	{ WCD934X_PAGE11_PAGE_REGISTER,                    0x00 },
+	{ WCD934X_CDC_COMPANDER1_CTL0,                     0x60 },
+	{ WCD934X_CDC_COMPANDER1_CTL1,                     0xdb },
+	{ WCD934X_CDC_COMPANDER1_CTL2,                     0xff },
+	{ WCD934X_CDC_COMPANDER1_CTL3,                     0x35 },
+	{ WCD934X_CDC_COMPANDER1_CTL4,                     0xff },
+	{ WCD934X_CDC_COMPANDER1_CTL5,                     0x00 },
+	{ WCD934X_CDC_COMPANDER1_CTL6,                     0x01 },
+	{ WCD934X_CDC_COMPANDER1_CTL7,                     0x08 },
+	{ WCD934X_CDC_COMPANDER2_CTL0,                     0x60 },
+	{ WCD934X_CDC_COMPANDER2_CTL1,                     0xdb },
+	{ WCD934X_CDC_COMPANDER2_CTL2,                     0xff },
+	{ WCD934X_CDC_COMPANDER2_CTL3,                     0x35 },
+	{ WCD934X_CDC_COMPANDER2_CTL4,                     0xff },
+	{ WCD934X_CDC_COMPANDER2_CTL5,                     0x00 },
+	{ WCD934X_CDC_COMPANDER2_CTL6,                     0x01 },
+	{ WCD934X_CDC_COMPANDER2_CTL7,                     0x08 },
+	{ WCD934X_CDC_COMPANDER3_CTL0,                     0x60 },
+	{ WCD934X_CDC_COMPANDER3_CTL1,                     0xdb },
+	{ WCD934X_CDC_COMPANDER3_CTL2,                     0xff },
+	{ WCD934X_CDC_COMPANDER3_CTL3,                     0x35 },
+	{ WCD934X_CDC_COMPANDER3_CTL4,                     0xff },
+	{ WCD934X_CDC_COMPANDER3_CTL5,                     0x00 },
+	{ WCD934X_CDC_COMPANDER3_CTL6,                     0x01 },
+	{ WCD934X_CDC_COMPANDER3_CTL7,                     0x08 },
+	{ WCD934X_CDC_COMPANDER4_CTL0,                     0x60 },
+	{ WCD934X_CDC_COMPANDER4_CTL1,                     0xdb },
+	{ WCD934X_CDC_COMPANDER4_CTL2,                     0xff },
+	{ WCD934X_CDC_COMPANDER4_CTL3,                     0x35 },
+	{ WCD934X_CDC_COMPANDER4_CTL4,                     0xff },
+	{ WCD934X_CDC_COMPANDER4_CTL5,                     0x00 },
+	{ WCD934X_CDC_COMPANDER4_CTL6,                     0x01 },
+	{ WCD934X_CDC_COMPANDER4_CTL7,                     0x08 },
+	{ WCD934X_CDC_COMPANDER7_CTL0,                     0x60 },
+	{ WCD934X_CDC_COMPANDER7_CTL1,                     0xdb },
+	{ WCD934X_CDC_COMPANDER7_CTL2,                     0xff },
+	{ WCD934X_CDC_COMPANDER7_CTL3,                     0x35 },
+	{ WCD934X_CDC_COMPANDER7_CTL4,                     0xff },
+	{ WCD934X_CDC_COMPANDER7_CTL5,                     0x00 },
+	{ WCD934X_CDC_COMPANDER7_CTL6,                     0x01 },
+	{ WCD934X_CDC_COMPANDER7_CTL7,                     0x08 },
+	{ WCD934X_CDC_COMPANDER8_CTL0,                     0x60 },
+	{ WCD934X_CDC_COMPANDER8_CTL1,                     0xdb },
+	{ WCD934X_CDC_COMPANDER8_CTL2,                     0xff },
+	{ WCD934X_CDC_COMPANDER8_CTL3,                     0x35 },
+	{ WCD934X_CDC_COMPANDER8_CTL4,                     0xff },
+	{ WCD934X_CDC_COMPANDER8_CTL5,                     0x00 },
+	{ WCD934X_CDC_COMPANDER8_CTL6,                     0x01 },
+	{ WCD934X_CDC_COMPANDER8_CTL7,                     0x08 },
+	{ WCD934X_CDC_RX0_RX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_RX0_RX_PATH_CFG0,                    0x00 },
+	{ WCD934X_CDC_RX0_RX_PATH_CFG1,                    0x64 },
+	{ WCD934X_CDC_RX0_RX_PATH_CFG2,                    0x8f },
+	{ WCD934X_CDC_RX0_RX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_RX0_RX_PATH_MIX_CTL,                 0x04 },
+	{ WCD934X_CDC_RX0_RX_PATH_MIX_CFG,                 0x7e },
+	{ WCD934X_CDC_RX0_RX_VOL_MIX_CTL,                  0x00 },
+	{ WCD934X_CDC_RX0_RX_PATH_SEC0,                    0xfc },
+	{ WCD934X_CDC_RX0_RX_PATH_SEC1,                    0x08 },
+	{ WCD934X_CDC_RX0_RX_PATH_SEC2,                    0x00 },
+	{ WCD934X_CDC_RX0_RX_PATH_SEC3,                    0x00 },
+	{ WCD934X_CDC_RX0_RX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_RX0_RX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_RX0_RX_PATH_SEC7,                    0x00 },
+	{ WCD934X_CDC_RX0_RX_PATH_MIX_SEC0,                0x08 },
+	{ WCD934X_CDC_RX0_RX_PATH_MIX_SEC1,                0x00 },
+	{ WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL,              0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_RX1_RX_PATH_CFG0,                    0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_CFG1,                    0x64 },
+	{ WCD934X_CDC_RX1_RX_PATH_CFG2,                    0x8f },
+	{ WCD934X_CDC_RX1_RX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_MIX_CTL,                 0x04 },
+	{ WCD934X_CDC_RX1_RX_PATH_MIX_CFG,                 0x7e },
+	{ WCD934X_CDC_RX1_RX_VOL_MIX_CTL,                  0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_SEC0,                    0xfc },
+	{ WCD934X_CDC_RX1_RX_PATH_SEC1,                    0x08 },
+	{ WCD934X_CDC_RX1_RX_PATH_SEC2,                    0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_SEC3,                    0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_SEC4,                    0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_SEC7,                    0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_MIX_SEC0,                0x08 },
+	{ WCD934X_CDC_RX1_RX_PATH_MIX_SEC1,                0x00 },
+	{ WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL,              0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_RX2_RX_PATH_CFG0,                    0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_CFG1,                    0x64 },
+	{ WCD934X_CDC_RX2_RX_PATH_CFG2,                    0x8f },
+	{ WCD934X_CDC_RX2_RX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_MIX_CTL,                 0x04 },
+	{ WCD934X_CDC_RX2_RX_PATH_MIX_CFG,                 0x7e },
+	{ WCD934X_CDC_RX2_RX_VOL_MIX_CTL,                  0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_SEC0,                    0xfc },
+	{ WCD934X_CDC_RX2_RX_PATH_SEC1,                    0x08 },
+	{ WCD934X_CDC_RX2_RX_PATH_SEC2,                    0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_SEC3,                    0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_SEC4,                    0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_SEC7,                    0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_MIX_SEC0,                0x08 },
+	{ WCD934X_CDC_RX2_RX_PATH_MIX_SEC1,                0x00 },
+	{ WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL,              0x00 },
+	{ WCD934X_CDC_RX3_RX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_RX3_RX_PATH_CFG0,                    0x00 },
+	{ WCD934X_CDC_RX3_RX_PATH_CFG1,                    0x64 },
+	{ WCD934X_CDC_RX3_RX_PATH_CFG2,                    0x8f },
+	{ WCD934X_CDC_RX3_RX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_RX3_RX_PATH_MIX_CTL,                 0x04 },
+	{ WCD934X_CDC_RX3_RX_PATH_MIX_CFG,                 0x7e },
+	{ WCD934X_CDC_RX3_RX_VOL_MIX_CTL,                  0x00 },
+	{ WCD934X_CDC_RX3_RX_PATH_SEC0,                    0xfc },
+	{ WCD934X_CDC_RX3_RX_PATH_SEC1,                    0x08 },
+	{ WCD934X_CDC_RX3_RX_PATH_SEC2,                    0x00 },
+	{ WCD934X_CDC_RX3_RX_PATH_SEC3,                    0x00 },
+	{ WCD934X_CDC_RX3_RX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_RX3_RX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_RX3_RX_PATH_SEC7,                    0x00 },
+	{ WCD934X_CDC_RX3_RX_PATH_MIX_SEC0,                0x08 },
+	{ WCD934X_CDC_RX3_RX_PATH_MIX_SEC1,                0x00 },
+	{ WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL,              0x00 },
+	{ WCD934X_CDC_RX4_RX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_RX4_RX_PATH_CFG0,                    0x00 },
+	{ WCD934X_CDC_RX4_RX_PATH_CFG1,                    0x64 },
+	{ WCD934X_CDC_RX4_RX_PATH_CFG2,                    0x8f },
+	{ WCD934X_CDC_RX4_RX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_RX4_RX_PATH_MIX_CTL,                 0x04 },
+	{ WCD934X_CDC_RX4_RX_PATH_MIX_CFG,                 0x7e },
+	{ WCD934X_CDC_RX4_RX_VOL_MIX_CTL,                  0x00 },
+	{ WCD934X_CDC_RX4_RX_PATH_SEC0,                    0xfc },
+	{ WCD934X_CDC_RX4_RX_PATH_SEC1,                    0x08 },
+	{ WCD934X_CDC_RX4_RX_PATH_SEC2,                    0x00 },
+	{ WCD934X_CDC_RX4_RX_PATH_SEC3,                    0x00 },
+	{ WCD934X_CDC_RX4_RX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_RX4_RX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_RX4_RX_PATH_SEC7,                    0x00 },
+	{ WCD934X_CDC_RX4_RX_PATH_MIX_SEC0,                0x08 },
+	{ WCD934X_CDC_RX4_RX_PATH_MIX_SEC1,                0x00 },
+	{ WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL,              0x00 },
+	{ WCD934X_CDC_RX7_RX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_RX7_RX_PATH_CFG0,                    0x00 },
+	{ WCD934X_CDC_RX7_RX_PATH_CFG1,                    0x64 },
+	{ WCD934X_CDC_RX7_RX_PATH_CFG2,                    0x8f },
+	{ WCD934X_CDC_RX7_RX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_RX7_RX_PATH_MIX_CTL,                 0x04 },
+	{ WCD934X_CDC_RX7_RX_PATH_MIX_CFG,                 0x7e },
+	{ WCD934X_CDC_RX7_RX_VOL_MIX_CTL,                  0x00 },
+	{ WCD934X_CDC_RX7_RX_PATH_SEC0,                    0x04 },
+	{ WCD934X_CDC_RX7_RX_PATH_SEC1,                    0x08 },
+	{ WCD934X_CDC_RX7_RX_PATH_SEC2,                    0x00 },
+	{ WCD934X_CDC_RX7_RX_PATH_SEC3,                    0x00 },
+	{ WCD934X_CDC_RX7_RX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_RX7_RX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_RX7_RX_PATH_SEC7,                    0x00 },
+	{ WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,                0x08 },
+	{ WCD934X_CDC_RX7_RX_PATH_MIX_SEC1,                0x00 },
+	{ WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL,              0x00 },
+	{ WCD934X_CDC_RX8_RX_PATH_CTL,                     0x04 },
+	{ WCD934X_CDC_RX8_RX_PATH_CFG0,                    0x00 },
+	{ WCD934X_CDC_RX8_RX_PATH_CFG1,                    0x64 },
+	{ WCD934X_CDC_RX8_RX_PATH_CFG2,                    0x8f },
+	{ WCD934X_CDC_RX8_RX_VOL_CTL,                      0x00 },
+	{ WCD934X_CDC_RX8_RX_PATH_MIX_CTL,                 0x04 },
+	{ WCD934X_CDC_RX8_RX_PATH_MIX_CFG,                 0x7e },
+	{ WCD934X_CDC_RX8_RX_VOL_MIX_CTL,                  0x00 },
+	{ WCD934X_CDC_RX8_RX_PATH_SEC0,                    0x04 },
+	{ WCD934X_CDC_RX8_RX_PATH_SEC1,                    0x08 },
+	{ WCD934X_CDC_RX8_RX_PATH_SEC2,                    0x00 },
+	{ WCD934X_CDC_RX8_RX_PATH_SEC3,                    0x00 },
+	{ WCD934X_CDC_RX8_RX_PATH_SEC5,                    0x00 },
+	{ WCD934X_CDC_RX8_RX_PATH_SEC6,                    0x00 },
+	{ WCD934X_CDC_RX8_RX_PATH_SEC7,                    0x00 },
+	{ WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,                0x08 },
+	{ WCD934X_CDC_RX8_RX_PATH_MIX_SEC1,                0x00 },
+	{ WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL,              0x00 },
+	{ WCD934X_PAGE12_PAGE_REGISTER,                    0x00 },
+	{ WCD934X_CDC_CLSH_CRC,                            0x00 },
+	{ WCD934X_CDC_CLSH_DLY_CTRL,                       0x03 },
+	{ WCD934X_CDC_CLSH_DECAY_CTRL,                     0x02 },
+	{ WCD934X_CDC_CLSH_HPH_V_PA,                       0x1c },
+	{ WCD934X_CDC_CLSH_EAR_V_PA,                       0x39 },
+	{ WCD934X_CDC_CLSH_HPH_V_HD,                       0x0c },
+	{ WCD934X_CDC_CLSH_EAR_V_HD,                       0x0c },
+	{ WCD934X_CDC_CLSH_K1_MSB,                         0x01 },
+	{ WCD934X_CDC_CLSH_K1_LSB,                         0x00 },
+	{ WCD934X_CDC_CLSH_K2_MSB,                         0x00 },
+	{ WCD934X_CDC_CLSH_K2_LSB,                         0x80 },
+	{ WCD934X_CDC_CLSH_IDLE_CTRL,                      0x00 },
+	{ WCD934X_CDC_CLSH_IDLE_HPH,                       0x00 },
+	{ WCD934X_CDC_CLSH_IDLE_EAR,                       0x00 },
+	{ WCD934X_CDC_CLSH_TEST0,                          0x07 },
+	{ WCD934X_CDC_CLSH_TEST1,                          0x00 },
+	{ WCD934X_CDC_CLSH_OVR_VREF,                       0x00 },
+	{ WCD934X_CDC_BOOST0_BOOST_PATH_CTL,               0x00 },
+	{ WCD934X_CDC_BOOST0_BOOST_CTL,                    0xb2 },
+	{ WCD934X_CDC_BOOST0_BOOST_CFG1,                   0x00 },
+	{ WCD934X_CDC_BOOST0_BOOST_CFG2,                   0x00 },
+	{ WCD934X_CDC_BOOST1_BOOST_PATH_CTL,               0x00 },
+	{ WCD934X_CDC_BOOST1_BOOST_CTL,                    0xb2 },
+	{ WCD934X_CDC_BOOST1_BOOST_CFG1,                   0x00 },
+	{ WCD934X_CDC_BOOST1_BOOST_CFG2,                   0x00 },
+	{ WCD934X_CDC_VBAT_VBAT_PATH_CTL,                  0x00 },
+	{ WCD934X_CDC_VBAT_VBAT_CFG,                       0x1a },
+	{ WCD934X_CDC_VBAT_VBAT_ADC_CAL1,                  0x00 },
+	{ WCD934X_CDC_VBAT_VBAT_ADC_CAL2,                  0x00 },
+	{ WCD934X_CDC_VBAT_VBAT_ADC_CAL3,                  0x04 },
+	{ WCD934X_CDC_VBAT_VBAT_PK_EST1,                   0xe0 },
+	{ WCD934X_CDC_VBAT_VBAT_PK_EST2,                   0x01 },
+	{ WCD934X_CDC_VBAT_VBAT_PK_EST3,                   0x40 },
+	{ WCD934X_CDC_VBAT_VBAT_RF_PROC1,                  0x2a },
+	{ WCD934X_CDC_VBAT_VBAT_RF_PROC2,                  0x86 },
+	{ WCD934X_CDC_VBAT_VBAT_TAC1,                      0x70 },
+	{ WCD934X_CDC_VBAT_VBAT_TAC2,                      0x18 },
+	{ WCD934X_CDC_VBAT_VBAT_TAC3,                      0x18 },
+	{ WCD934X_CDC_VBAT_VBAT_TAC4,                      0x03 },
+	{ WCD934X_CDC_VBAT_VBAT_GAIN_UPD1,                 0x01 },
+	{ WCD934X_CDC_VBAT_VBAT_GAIN_UPD2,                 0x00 },
+	{ WCD934X_CDC_VBAT_VBAT_GAIN_UPD3,                 0x64 },
+	{ WCD934X_CDC_VBAT_VBAT_GAIN_UPD4,                 0x01 },
+	{ WCD934X_CDC_VBAT_VBAT_DEBUG1,                    0x00 },
+	{ WCD934X_CDC_VBAT_VBAT_GAIN_UPD_MON,              0x00 },
+	{ WCD934X_CDC_VBAT_VBAT_GAIN_MON_VAL,              0x00 },
+	{ WCD934X_CDC_VBAT_VBAT_BAN,                       0x0c },
+	{ WCD934X_MIXING_ASRC0_CLK_RST_CTL,                0x00 },
+	{ WCD934X_MIXING_ASRC0_CTL0,                       0x00 },
+	{ WCD934X_MIXING_ASRC0_CTL1,                       0x00 },
+	{ WCD934X_MIXING_ASRC0_FIFO_CTL,                   0xa8 },
+	{ WCD934X_MIXING_ASRC0_STATUS_FMIN_CNTR_LSB,       0x00 },
+	{ WCD934X_MIXING_ASRC0_STATUS_FMIN_CNTR_MSB,       0x00 },
+	{ WCD934X_MIXING_ASRC0_STATUS_FMAX_CNTR_LSB,       0x00 },
+	{ WCD934X_MIXING_ASRC0_STATUS_FMAX_CNTR_MSB,       0x00 },
+	{ WCD934X_MIXING_ASRC0_STATUS_FIFO,                0x00 },
+	{ WCD934X_MIXING_ASRC1_CLK_RST_CTL,                0x00 },
+	{ WCD934X_MIXING_ASRC1_CTL0,                       0x00 },
+	{ WCD934X_MIXING_ASRC1_CTL1,                       0x00 },
+	{ WCD934X_MIXING_ASRC1_FIFO_CTL,                   0xa8 },
+	{ WCD934X_MIXING_ASRC1_STATUS_FMIN_CNTR_LSB,       0x00 },
+	{ WCD934X_MIXING_ASRC1_STATUS_FMIN_CNTR_MSB,       0x00 },
+	{ WCD934X_MIXING_ASRC1_STATUS_FMAX_CNTR_LSB,       0x00 },
+	{ WCD934X_MIXING_ASRC1_STATUS_FMAX_CNTR_MSB,       0x00 },
+	{ WCD934X_MIXING_ASRC1_STATUS_FIFO,                0x00 },
+	{ WCD934X_MIXING_ASRC2_CLK_RST_CTL,                0x00 },
+	{ WCD934X_MIXING_ASRC2_CTL0,                       0x00 },
+	{ WCD934X_MIXING_ASRC2_CTL1,                       0x00 },
+	{ WCD934X_MIXING_ASRC2_FIFO_CTL,                   0xa8 },
+	{ WCD934X_MIXING_ASRC2_STATUS_FMIN_CNTR_LSB,       0x00 },
+	{ WCD934X_MIXING_ASRC2_STATUS_FMIN_CNTR_MSB,       0x00 },
+	{ WCD934X_MIXING_ASRC2_STATUS_FMAX_CNTR_LSB,       0x00 },
+	{ WCD934X_MIXING_ASRC2_STATUS_FMAX_CNTR_MSB,       0x00 },
+	{ WCD934X_MIXING_ASRC2_STATUS_FIFO,                0x00 },
+	{ WCD934X_MIXING_ASRC3_CLK_RST_CTL,                0x00 },
+	{ WCD934X_MIXING_ASRC3_CTL0,                       0x00 },
+	{ WCD934X_MIXING_ASRC3_CTL1,                       0x00 },
+	{ WCD934X_MIXING_ASRC3_FIFO_CTL,                   0xa8 },
+	{ WCD934X_MIXING_ASRC3_STATUS_FMIN_CNTR_LSB,       0x00 },
+	{ WCD934X_MIXING_ASRC3_STATUS_FMIN_CNTR_MSB,       0x00 },
+	{ WCD934X_MIXING_ASRC3_STATUS_FMAX_CNTR_LSB,       0x00 },
+	{ WCD934X_MIXING_ASRC3_STATUS_FMAX_CNTR_MSB,       0x00 },
+	{ WCD934X_MIXING_ASRC3_STATUS_FIFO,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_WR_DATA_0,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_WR_DATA_1,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_WR_DATA_2,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_WR_DATA_3,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_WR_ADDR_1,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_WR_ADDR_2,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_WR_ADDR_3,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_RD_ADDR_0,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_RD_ADDR_1,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_RD_ADDR_2,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_RD_ADDR_3,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_RD_DATA_0,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_RD_DATA_1,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_RD_DATA_2,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_RD_DATA_3,                0x00 },
+	{ WCD934X_SWR_AHB_BRIDGE_ACCESS_CFG,               0x0f },
+	{ WCD934X_SWR_AHB_BRIDGE_ACCESS_STATUS,            0x03 },
+	{ WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL,       0x04 },
+	{ WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CFG1,      0x00 },
+	{ WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL,       0x04 },
+	{ WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CFG1,      0x00 },
+	{ WCD934X_SIDETONE_ASRC0_CLK_RST_CTL,              0x00 },
+	{ WCD934X_SIDETONE_ASRC0_CTL0,                     0x00 },
+	{ WCD934X_SIDETONE_ASRC0_CTL1,                     0x00 },
+	{ WCD934X_SIDETONE_ASRC0_FIFO_CTL,                 0xa8 },
+	{ WCD934X_SIDETONE_ASRC0_STATUS_FMIN_CNTR_LSB,     0x00 },
+	{ WCD934X_SIDETONE_ASRC0_STATUS_FMIN_CNTR_MSB,     0x00 },
+	{ WCD934X_SIDETONE_ASRC0_STATUS_FMAX_CNTR_LSB,     0x00 },
+	{ WCD934X_SIDETONE_ASRC0_STATUS_FMAX_CNTR_MSB,     0x00 },
+	{ WCD934X_SIDETONE_ASRC0_STATUS_FIFO,              0x00 },
+	{ WCD934X_SIDETONE_ASRC1_CLK_RST_CTL,              0x00 },
+	{ WCD934X_SIDETONE_ASRC1_CTL0,                     0x00 },
+	{ WCD934X_SIDETONE_ASRC1_CTL1,                     0x00 },
+	{ WCD934X_SIDETONE_ASRC1_FIFO_CTL,                 0xa8 },
+	{ WCD934X_SIDETONE_ASRC1_STATUS_FMIN_CNTR_LSB,     0x00 },
+	{ WCD934X_SIDETONE_ASRC1_STATUS_FMIN_CNTR_MSB,     0x00 },
+	{ WCD934X_SIDETONE_ASRC1_STATUS_FMAX_CNTR_LSB,     0x00 },
+	{ WCD934X_SIDETONE_ASRC1_STATUS_FMAX_CNTR_MSB,     0x00 },
+	{ WCD934X_SIDETONE_ASRC1_STATUS_FIFO,              0x00 },
+	{ WCD934X_EC_REF_HQ0_EC_REF_HQ_PATH_CTL,           0x00 },
+	{ WCD934X_EC_REF_HQ0_EC_REF_HQ_CFG0,               0x01 },
+	{ WCD934X_EC_REF_HQ1_EC_REF_HQ_PATH_CTL,           0x00 },
+	{ WCD934X_EC_REF_HQ1_EC_REF_HQ_CFG0,               0x01 },
+	{ WCD934X_EC_ASRC0_CLK_RST_CTL,                    0x00 },
+	{ WCD934X_EC_ASRC0_CTL0,                           0x00 },
+	{ WCD934X_EC_ASRC0_CTL1,                           0x00 },
+	{ WCD934X_EC_ASRC0_FIFO_CTL,                       0xa8 },
+	{ WCD934X_EC_ASRC0_STATUS_FMIN_CNTR_LSB,           0x00 },
+	{ WCD934X_EC_ASRC0_STATUS_FMIN_CNTR_MSB,           0x00 },
+	{ WCD934X_EC_ASRC0_STATUS_FMAX_CNTR_LSB,           0x00 },
+	{ WCD934X_EC_ASRC0_STATUS_FMAX_CNTR_MSB,           0x00 },
+	{ WCD934X_EC_ASRC0_STATUS_FIFO,                    0x00 },
+	{ WCD934X_EC_ASRC1_CLK_RST_CTL,                    0x00 },
+	{ WCD934X_EC_ASRC1_CTL0,                           0x00 },
+	{ WCD934X_EC_ASRC1_CTL1,                           0x00 },
+	{ WCD934X_EC_ASRC1_FIFO_CTL,                       0xa8 },
+	{ WCD934X_EC_ASRC1_STATUS_FMIN_CNTR_LSB,           0x00 },
+	{ WCD934X_EC_ASRC1_STATUS_FMIN_CNTR_MSB,           0x00 },
+	{ WCD934X_EC_ASRC1_STATUS_FMAX_CNTR_LSB,           0x00 },
+	{ WCD934X_EC_ASRC1_STATUS_FMAX_CNTR_MSB,           0x00 },
+	{ WCD934X_EC_ASRC1_STATUS_FIFO,                    0x00 },
+	{ WCD934X_PAGE13_PAGE_REGISTER,                    0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1,             0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG0,              0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG1,              0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG2,              0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG3,              0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG4,              0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0,        0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1,        0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_ANC_CFG0,                 0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0,         0x00 },
+	{ WCD934X_CDC_RX_INP_MUX_EC_REF_HQ_CFG0,           0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0,            0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX10_CFG0,           0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX11_CFG0,           0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX12_CFG0,           0x00 },
+	{ WCD934X_CDC_TX_INP_MUX_ADC_MUX13_CFG0,           0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0,  0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1,  0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2,  0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3,  0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0,  0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1,  0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2,  0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3,  0x00 },
+	{ WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0,               0x00 },
+	{ WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1,               0x00 },
+	{ WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2,               0x00 },
+	{ WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3,               0x00 },
+	{ WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL,           0x00 },
+	{ WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,         0x0c },
+	{ WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,            0x00 },
+	{ WCD934X_CDC_CLK_RST_CTRL_DSD_CONTROL,            0x00 },
+	{ WCD934X_CDC_CLK_RST_CTRL_ASRC_SHARE_CONTROL,     0x0f },
+	{ WCD934X_CDC_CLK_RST_CTRL_GFM_CONTROL,            0x00 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_CTL,                0x08 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_POLL_PERIOD0,       0x00 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_POLL_PERIOD1,       0x4b },
+	{ WCD934X_CDC_PROX_DETECT_PROX_SIG_PATTERN_LSB,    0x00 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_SIG_PATTERN_MSB,    0x00 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_STATUS,             0x00 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_TEST_CTRL,          0x00 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB,      0x00 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB,      0x00 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB_RD,   0x00 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB_RD,   0x00 },
+	{ WCD934X_CDC_PROX_DETECT_PROX_CTL_REPEAT_PAT,     0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_PATH_CTL,          0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B5_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B6_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B7_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B8_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_CTL,               0x40 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL,    0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_PATH_CTL,          0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B5_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B6_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B7_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B8_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_CTL,               0x40 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL,    0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_COEF_B1_CTL,       0x00 },
+	{ WCD934X_CDC_SIDETONE_IIR1_IIR_COEF_B2_CTL,       0x00 },
+	{ WCD934X_CDC_TOP_TOP_CFG0,                        0x00 },
+	{ WCD934X_CDC_TOP_TOP_CFG1,                        0x00 },
+	{ WCD934X_CDC_TOP_TOP_CFG7,                        0x00 },
+	{ WCD934X_CDC_TOP_HPHL_COMP_WR_LSB,                0x00 },
+	{ WCD934X_CDC_TOP_HPHL_COMP_WR_MSB,                0x00 },
+	{ WCD934X_CDC_TOP_HPHL_COMP_LUT,                   0x00 },
+	{ WCD934X_CDC_TOP_HPHL_COMP_RD_LSB,                0x00 },
+	{ WCD934X_CDC_TOP_HPHL_COMP_RD_MSB,                0x00 },
+	{ WCD934X_CDC_TOP_HPHR_COMP_WR_LSB,                0x00 },
+	{ WCD934X_CDC_TOP_HPHR_COMP_WR_MSB,                0x00 },
+	{ WCD934X_CDC_TOP_HPHR_COMP_LUT,                   0x00 },
+	{ WCD934X_CDC_TOP_HPHR_COMP_RD_LSB,                0x00 },
+	{ WCD934X_CDC_TOP_HPHR_COMP_RD_MSB,                0x00 },
+	{ WCD934X_CDC_TOP_DIFFL_COMP_WR_LSB,               0x00 },
+	{ WCD934X_CDC_TOP_DIFFL_COMP_WR_MSB,               0x00 },
+	{ WCD934X_CDC_TOP_DIFFL_COMP_LUT,                  0x00 },
+	{ WCD934X_CDC_TOP_DIFFL_COMP_RD_LSB,               0x00 },
+	{ WCD934X_CDC_TOP_DIFFL_COMP_RD_MSB,               0x00 },
+	{ WCD934X_CDC_TOP_DIFFR_COMP_WR_LSB,               0x00 },
+	{ WCD934X_CDC_TOP_DIFFR_COMP_WR_MSB,               0x00 },
+	{ WCD934X_CDC_TOP_DIFFR_COMP_LUT,                  0x00 },
+	{ WCD934X_CDC_TOP_DIFFR_COMP_RD_LSB,               0x00 },
+	{ WCD934X_CDC_TOP_DIFFR_COMP_RD_MSB,               0x00 },
+	{ WCD934X_CDC_DSD0_PATH_CTL,                       0x00 },
+	{ WCD934X_CDC_DSD0_CFG0,                           0x00 },
+	{ WCD934X_CDC_DSD0_CFG1,                           0x00 },
+	{ WCD934X_CDC_DSD0_CFG2,                           0x42 },
+	{ WCD934X_CDC_DSD0_CFG3,                           0x00 },
+	{ WCD934X_CDC_DSD0_CFG4,                           0x02 },
+	{ WCD934X_CDC_DSD0_CFG5,                           0x00 },
+	{ WCD934X_CDC_DSD1_PATH_CTL,                       0x00 },
+	{ WCD934X_CDC_DSD1_CFG0,                           0x00 },
+	{ WCD934X_CDC_DSD1_CFG1,                           0x00 },
+	{ WCD934X_CDC_DSD1_CFG2,                           0x42 },
+	{ WCD934X_CDC_DSD1_CFG3,                           0x00 },
+	{ WCD934X_CDC_DSD1_CFG4,                           0x02 },
+	{ WCD934X_CDC_DSD1_CFG5,                           0x00 },
+	{ WCD934X_CDC_RX_IDLE_DET_PATH_CTL,                0x00 },
+	{ WCD934X_CDC_RX_IDLE_DET_CFG0,                    0x07 },
+	{ WCD934X_CDC_RX_IDLE_DET_CFG1,                    0x3c },
+	{ WCD934X_CDC_RX_IDLE_DET_CFG2,                    0x00 },
+	{ WCD934X_CDC_RX_IDLE_DET_CFG3,                    0x00 },
+	{ WCD934X_PAGE14_PAGE_REGISTER,                    0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_CLK_RST_CTL,            0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_CTL,                    0x09 },
+	{ WCD934X_CDC_RATE_EST0_RE_PULSE_SUPR_CTL,         0x06 },
+	{ WCD934X_CDC_RATE_EST0_RE_TIMER,                  0x01 },
+	{ WCD934X_CDC_RATE_EST0_RE_BW_SW,                  0x20 },
+	{ WCD934X_CDC_RATE_EST0_RE_THRESH,                 0xa0 },
+	{ WCD934X_CDC_RATE_EST0_RE_STATUS,                 0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_CTRL,              0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_TIMER2,            0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW1,        0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW2,        0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW3,        0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW4,        0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW5,        0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW1,         0x08 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW2,         0x07 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW3,         0x05 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW4,         0x05 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW5,         0x05 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW1,       0x08 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW2,       0x07 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW3,       0x05 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW4,       0x05 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW5,       0x05 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW1,          0x03 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW2,          0x03 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW3,          0x03 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW4,          0x03 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW5,          0x03 },
+	{ WCD934X_CDC_RATE_EST0_RE_RMAX_DIAG,              0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_RMIN_DIAG,              0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_PH_DET,                 0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_DIAG_CLR,               0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_MB_SW_STATE,            0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_MAST_DIAG_STATE,        0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_RATE_OUT_7_0,           0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_RATE_OUT_15_8,          0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_RATE_OUT_23_16,         0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_RATE_OUT_31_24,         0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_RATE_OUT_39_32,         0x00 },
+	{ WCD934X_CDC_RATE_EST0_RE_RATE_OUT_40_43,         0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_CLK_RST_CTL,            0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_CTL,                    0x09 },
+	{ WCD934X_CDC_RATE_EST1_RE_PULSE_SUPR_CTL,         0x06 },
+	{ WCD934X_CDC_RATE_EST1_RE_TIMER,                  0x01 },
+	{ WCD934X_CDC_RATE_EST1_RE_BW_SW,                  0x20 },
+	{ WCD934X_CDC_RATE_EST1_RE_THRESH,                 0xa0 },
+	{ WCD934X_CDC_RATE_EST1_RE_STATUS,                 0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_CTRL,              0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_TIMER2,            0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW1,        0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW2,        0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW3,        0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW4,        0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW5,        0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW1,         0x08 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW2,         0x07 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW3,         0x05 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW4,         0x05 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW5,         0x05 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW1,       0x08 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW2,       0x07 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW3,       0x05 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW4,       0x05 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW5,       0x05 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW1,          0x03 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW2,          0x03 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW3,          0x03 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW4,          0x03 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW5,          0x03 },
+	{ WCD934X_CDC_RATE_EST1_RE_RMAX_DIAG,              0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_RMIN_DIAG,              0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_PH_DET,                 0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_DIAG_CLR,               0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_MB_SW_STATE,            0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_MAST_DIAG_STATE,        0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_RATE_OUT_7_0,           0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_RATE_OUT_15_8,          0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_RATE_OUT_23_16,         0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_RATE_OUT_31_24,         0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_RATE_OUT_39_32,         0x00 },
+	{ WCD934X_CDC_RATE_EST1_RE_RATE_OUT_40_43,         0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_CLK_RST_CTL,            0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_CTL,                    0x09 },
+	{ WCD934X_CDC_RATE_EST2_RE_PULSE_SUPR_CTL,         0x06 },
+	{ WCD934X_CDC_RATE_EST2_RE_TIMER,                  0x01 },
+	{ WCD934X_CDC_RATE_EST2_RE_BW_SW,                  0x20 },
+	{ WCD934X_CDC_RATE_EST2_RE_THRESH,                 0xa0 },
+	{ WCD934X_CDC_RATE_EST2_RE_STATUS,                 0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_CTRL,              0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_TIMER2,            0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW1,        0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW2,        0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW3,        0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW4,        0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW5,        0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW1,         0x08 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW2,         0x07 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW3,         0x05 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW4,         0x05 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW5,         0x05 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW1,       0x08 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW2,       0x07 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW3,       0x05 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW4,       0x05 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW5,       0x05 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW1,          0x03 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW2,          0x03 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW3,          0x03 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW4,          0x03 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW5,          0x03 },
+	{ WCD934X_CDC_RATE_EST2_RE_RMAX_DIAG,              0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_RMIN_DIAG,              0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_PH_DET,                 0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_DIAG_CLR,               0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_MB_SW_STATE,            0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_MAST_DIAG_STATE,        0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_RATE_OUT_7_0,           0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_RATE_OUT_15_8,          0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_RATE_OUT_23_16,         0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_RATE_OUT_31_24,         0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_RATE_OUT_39_32,         0x00 },
+	{ WCD934X_CDC_RATE_EST2_RE_RATE_OUT_40_43,         0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_CLK_RST_CTL,            0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_CTL,                    0x09 },
+	{ WCD934X_CDC_RATE_EST3_RE_PULSE_SUPR_CTL,         0x06 },
+	{ WCD934X_CDC_RATE_EST3_RE_TIMER,                  0x01 },
+	{ WCD934X_CDC_RATE_EST3_RE_BW_SW,                  0x20 },
+	{ WCD934X_CDC_RATE_EST3_RE_THRESH,                 0xa0 },
+	{ WCD934X_CDC_RATE_EST3_RE_STATUS,                 0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_CTRL,              0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_TIMER2,            0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW1,        0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW2,        0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW3,        0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW4,        0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW5,        0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW1,         0x08 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW2,         0x07 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW3,         0x05 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW4,         0x05 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW5,         0x05 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW1,       0x08 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW2,       0x07 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW3,       0x05 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW4,       0x05 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW5,       0x05 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW1,          0x03 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW2,          0x03 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW3,          0x03 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW4,          0x03 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW5,          0x03 },
+	{ WCD934X_CDC_RATE_EST3_RE_RMAX_DIAG,              0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_RMIN_DIAG,              0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_PH_DET,                 0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_DIAG_CLR,               0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_MB_SW_STATE,            0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_MAST_DIAG_STATE,        0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_RATE_OUT_7_0,           0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_RATE_OUT_15_8,          0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_RATE_OUT_23_16,         0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_RATE_OUT_31_24,         0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_RATE_OUT_39_32,         0x00 },
+	{ WCD934X_CDC_RATE_EST3_RE_RATE_OUT_40_43,         0x00 },
+	{ WCD934X_PAGE15_PAGE_REGISTER,                    0x00 },
+	{ WCD934X_SPLINE_SRC0_CLK_RST_CTL_0,               0x20 },
+	{ WCD934X_SPLINE_SRC0_STATUS,                      0x00 },
+	{ WCD934X_SPLINE_SRC1_CLK_RST_CTL_0,               0x20 },
+	{ WCD934X_SPLINE_SRC1_STATUS,                      0x00 },
+	{ WCD934X_SPLINE_SRC2_CLK_RST_CTL_0,               0x20 },
+	{ WCD934X_SPLINE_SRC2_STATUS,                      0x00 },
+	{ WCD934X_SPLINE_SRC3_CLK_RST_CTL_0,               0x20 },
+	{ WCD934X_SPLINE_SRC3_STATUS,                      0x00 },
+	{ WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG0,               0x11 },
+	{ WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG1,               0x20 },
+	{ WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG2,               0x00 },
+	{ WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG3,               0x08 },
+	{ WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG0,               0x11 },
+	{ WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG1,               0x20 },
+	{ WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG2,               0x00 },
+	{ WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG3,               0x08 },
+	{ WCD934X_CDC_DEBUG_SPLINE_SRC_DEBUG_CFG0,         0x00 },
+	{ WCD934X_CDC_DEBUG_SPLINE_SRC_DEBUG_CFG1,         0x00 },
+	{ WCD934X_CDC_DEBUG_RC_RE_ASRC_DEBUG_CFG0,         0x00 },
+	{ WCD934X_CDC_DEBUG_ANC0_RC0_FIFO_CTL,             0x4c },
+	{ WCD934X_CDC_DEBUG_ANC0_RC1_FIFO_CTL,             0x4c },
+	{ WCD934X_CDC_DEBUG_ANC1_RC0_FIFO_CTL,             0x4c },
+	{ WCD934X_CDC_DEBUG_ANC1_RC1_FIFO_CTL,             0x4c },
+	{ WCD934X_CDC_DEBUG_ANC_RC_RST_DBG_CNTR,           0x00 },
+	{ WCD934X_PAGE80_PAGE_REGISTER,                    0x00 },
+	{ WCD934X_CODEC_CPR_WR_DATA_0,                     0x00 },
+	{ WCD934X_CODEC_CPR_WR_DATA_1,                     0x00 },
+	{ WCD934X_CODEC_CPR_WR_DATA_2,                     0x00 },
+	{ WCD934X_CODEC_CPR_WR_DATA_3,                     0x00 },
+	{ WCD934X_CODEC_CPR_WR_ADDR_0,                     0x00 },
+	{ WCD934X_CODEC_CPR_WR_ADDR_1,                     0x00 },
+	{ WCD934X_CODEC_CPR_WR_ADDR_2,                     0x00 },
+	{ WCD934X_CODEC_CPR_WR_ADDR_3,                     0x00 },
+	{ WCD934X_CODEC_CPR_RD_ADDR_0,                     0x00 },
+	{ WCD934X_CODEC_CPR_RD_ADDR_1,                     0x00 },
+	{ WCD934X_CODEC_CPR_RD_ADDR_2,                     0x00 },
+	{ WCD934X_CODEC_CPR_RD_ADDR_3,                     0x00 },
+	{ WCD934X_CODEC_CPR_RD_DATA_0,                     0x00 },
+	{ WCD934X_CODEC_CPR_RD_DATA_1,                     0x00 },
+	{ WCD934X_CODEC_CPR_RD_DATA_2,                     0x00 },
+	{ WCD934X_CODEC_CPR_RD_DATA_3,                     0x00 },
+	{ WCD934X_CODEC_CPR_ACCESS_CFG,                    0x0f },
+	{ WCD934X_CODEC_CPR_ACCESS_STATUS,                 0x03 },
+	{ WCD934X_CODEC_CPR_NOM_CX_VDD,                    0xb4 },
+	{ WCD934X_CODEC_CPR_SVS_CX_VDD,                    0x5c },
+	{ WCD934X_CODEC_CPR_SVS2_CX_VDD,                   0x40 },
+	{ WCD934X_CODEC_CPR_NOM_MX_VDD,                    0xb4 },
+	{ WCD934X_CODEC_CPR_SVS_MX_VDD,                    0xb4 },
+	{ WCD934X_CODEC_CPR_SVS2_MX_VDD,                   0xa0 },
+	{ WCD934X_CODEC_CPR_SVS2_MIN_CX_VDD,               0x28 },
+	{ WCD934X_CODEC_CPR_MAX_SVS2_STEP,                 0x08 },
+	{ WCD934X_CODEC_CPR_CTL,                           0x00 },
+	{ WCD934X_CODEC_CPR_SW_MODECHNG_STATUS,            0x00 },
+	{ WCD934X_CODEC_CPR_SW_MODECHNG_START,             0x00 },
+	{ WCD934X_CODEC_CPR_CPR_STATUS,                    0x00 },
+	{ WCD934X_PAGE128_PAGE_REGISTER,                   0x00 },
+	{ WCD934X_TLMM_BIST_MODE_PINCFG,                   0x00 },
+	{ WCD934X_TLMM_RF_PA_ON_PINCFG,                    0x00 },
+	{ WCD934X_TLMM_INTR1_PINCFG,                       0x00 },
+	{ WCD934X_TLMM_INTR2_PINCFG,                       0x00 },
+	{ WCD934X_TLMM_SWR_DATA_PINCFG,                    0x00 },
+	{ WCD934X_TLMM_SWR_CLK_PINCFG,                     0x00 },
+	{ WCD934X_TLMM_I2S_2_SCK_PINCFG,                   0x00 },
+	{ WCD934X_TLMM_SLIMBUS_DATA1_PINCFG,               0x00 },
+	{ WCD934X_TLMM_SLIMBUS_DATA2_PINCFG,               0x00 },
+	{ WCD934X_TLMM_SLIMBUS_CLK_PINCFG,                 0x00 },
+	{ WCD934X_TLMM_I2C_CLK_PINCFG,                     0x00 },
+	{ WCD934X_TLMM_I2C_DATA_PINCFG,                    0x00 },
+	{ WCD934X_TLMM_I2S_0_RX_PINCFG,                    0x00 },
+	{ WCD934X_TLMM_I2S_0_TX_PINCFG,                    0x00 },
+	{ WCD934X_TLMM_I2S_0_SCK_PINCFG,                   0x00 },
+	{ WCD934X_TLMM_I2S_0_WS_PINCFG,                    0x00 },
+	{ WCD934X_TLMM_I2S_1_RX_PINCFG,                    0x00 },
+	{ WCD934X_TLMM_I2S_1_TX_PINCFG,                    0x00 },
+	{ WCD934X_TLMM_I2S_1_SCK_PINCFG,                   0x00 },
+	{ WCD934X_TLMM_I2S_1_WS_PINCFG,                    0x00 },
+	{ WCD934X_TLMM_DMIC1_CLK_PINCFG,                   0x00 },
+	{ WCD934X_TLMM_DMIC1_DATA_PINCFG,                  0x00 },
+	{ WCD934X_TLMM_DMIC2_CLK_PINCFG,                   0x00 },
+	{ WCD934X_TLMM_DMIC2_DATA_PINCFG,                  0x00 },
+	{ WCD934X_TLMM_DMIC3_CLK_PINCFG,                   0x00 },
+	{ WCD934X_TLMM_DMIC3_DATA_PINCFG,                  0x00 },
+	{ WCD934X_TLMM_JTCK_PINCFG,                        0x00 },
+	{ WCD934X_TLMM_GPIO1_PINCFG,                       0x00 },
+	{ WCD934X_TLMM_GPIO2_PINCFG,                       0x00 },
+	{ WCD934X_TLMM_GPIO3_PINCFG,                       0x00 },
+	{ WCD934X_TLMM_GPIO4_PINCFG,                       0x00 },
+	{ WCD934X_TLMM_SPI_S_CSN_PINCFG,                   0x00 },
+	{ WCD934X_TLMM_SPI_S_CLK_PINCFG,                   0x00 },
+	{ WCD934X_TLMM_SPI_S_DOUT_PINCFG,                  0x00 },
+	{ WCD934X_TLMM_SPI_S_DIN_PINCFG,                   0x00 },
+	{ WCD934X_TLMM_BA_N_PINCFG,                        0x00 },
+	{ WCD934X_TLMM_GPIO0_PINCFG,                       0x00 },
+	{ WCD934X_TLMM_I2S_2_RX_PINCFG,                    0x00 },
+	{ WCD934X_TLMM_I2S_2_WS_PINCFG,                    0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_CTL_OE_0,                 0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_CTL_OE_1,                 0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_CTL_OE_2,                 0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_CTL_OE_3,                 0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_CTL_OE_4,                 0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_CTL_DATA_0,               0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_CTL_DATA_1,               0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_CTL_DATA_2,               0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_CTL_DATA_3,               0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_CTL_DATA_4,               0x00 },
+	{ WCD934X_TEST_DEBUG_PAD_DRVCTL_0,                 0x00 },
+	{ WCD934X_TEST_DEBUG_PAD_DRVCTL_1,                 0x00 },
+	{ WCD934X_TEST_DEBUG_PIN_STATUS,                   0x00 },
+	{ WCD934X_TEST_DEBUG_NPL_DLY_TEST_1,               0x10 },
+	{ WCD934X_TEST_DEBUG_NPL_DLY_TEST_2,               0x60 },
+	{ WCD934X_TEST_DEBUG_MEM_CTRL,                     0x00 },
+	{ WCD934X_TEST_DEBUG_DEBUG_BUS_SEL,                0x00 },
+	{ WCD934X_TEST_DEBUG_DEBUG_JTAG,                   0x00 },
+	{ WCD934X_TEST_DEBUG_DEBUG_EN_1,                   0x00 },
+	{ WCD934X_TEST_DEBUG_DEBUG_EN_2,                   0x00 },
+	{ WCD934X_TEST_DEBUG_DEBUG_EN_3,                   0x00 },
+	{ WCD934X_TEST_DEBUG_DEBUG_EN_4,                   0x00 },
+	{ WCD934X_TEST_DEBUG_DEBUG_EN_5,                   0x00 },
+	{ WCD934X_TEST_DEBUG_ANA_DTEST_DIR,                0x00 },
+	{ WCD934X_TEST_DEBUG_PAD_INP_DISABLE_0,            0x00 },
+	{ WCD934X_TEST_DEBUG_PAD_INP_DISABLE_1,            0x00 },
+	{ WCD934X_TEST_DEBUG_PAD_INP_DISABLE_2,            0x00 },
+	{ WCD934X_TEST_DEBUG_PAD_INP_DISABLE_3,            0x00 },
+	{ WCD934X_TEST_DEBUG_PAD_INP_DISABLE_4,            0x00 },
+	{ WCD934X_TEST_DEBUG_SYSMEM_CTRL,                  0x00 },
+	{ WCD934X_TEST_DEBUG_SOC_SW_PWR_SEQ_DELAY,         0x00 },
+	{ WCD934X_TEST_DEBUG_LVAL_NOM_LOW,                 0x96 },
+	{ WCD934X_TEST_DEBUG_LVAL_NOM_HIGH,                0x00 },
+	{ WCD934X_TEST_DEBUG_LVAL_SVS_SVS2_LOW,            0x53 },
+	{ WCD934X_TEST_DEBUG_LVAL_SVS_SVS2_HIGH,           0x00 },
+	{ WCD934X_TEST_DEBUG_SPI_SLAVE_CHAR,               0x00 },
+	{ WCD934X_TEST_DEBUG_CODEC_DIAGS,                  0x00 },
+};
+
+/*
+ * wcd934x_regmap_register_patch: Update register defaults based on version
+ * @regmap: handle to wcd9xxx regmap
+ * @version: wcd934x version
+ *
+ * Returns error code in case of failure or 0 for success
+ */
+int wcd934x_regmap_register_patch(struct regmap *regmap, int revision)
+{
+	int rc = 0;
+
+	if (!regmap) {
+		pr_err("%s: regmap struct is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (revision) {
+	case TAVIL_VERSION_1_1:
+	case TAVIL_VERSION_WCD9340_1_1:
+	case TAVIL_VERSION_WCD9341_1_1:
+		regcache_cache_only(regmap, true);
+		rc = regmap_multi_reg_write(regmap, wcd934x_1_1_defaults,
+					    ARRAY_SIZE(wcd934x_1_1_defaults));
+		regcache_cache_only(regmap, false);
+		break;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(wcd934x_regmap_register_patch);
+
+static bool wcd934x_is_readable_register(struct device *dev, unsigned int reg)
+{
+	u8 pg_num, reg_offset;
+	const u8 *reg_tbl = NULL;
+
+	/*
+	 * Get the page number from MSB of codec register. If its 0x80, assign
+	 * the corresponding page index PAGE_0x80.
+	 */
+	pg_num = reg >> 0x8;
+	if (pg_num == 0x80)
+		pg_num = WCD934X_PAGE_0X80;
+	else if (pg_num == 0x50)
+		pg_num = WCD934X_PAGE_0x50;
+	else if (pg_num > 0xF)
+		return false;
+
+	reg_tbl = wcd934x_reg[pg_num];
+	reg_offset = reg & 0xFF;
+
+	if (reg_tbl && reg_tbl[reg_offset])
+		return true;
+	else
+		return false;
+}
+
+static bool wcd934x_is_volatile_register(struct device *dev, unsigned int reg)
+{
+	u8 pg_num, reg_offset;
+	const u8 *reg_tbl = NULL;
+
+	pg_num = reg >> 0x8;
+	if (pg_num == 0x80)
+		pg_num = WCD934X_PAGE_0X80;
+	else if (pg_num == 0x50)
+		pg_num = WCD934X_PAGE_0x50;
+	else if (pg_num > 0xF)
+		return false;
+
+	reg_tbl = wcd934x_reg[pg_num];
+	reg_offset = reg & 0xFF;
+
+	if (reg_tbl && reg_tbl[reg_offset] == WCD934X_READ)
+		return true;
+
+	/* IIR Coeff registers are not cacheable */
+	if ((reg >= WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL) &&
+	    (reg <= WCD934X_CDC_SIDETONE_IIR1_IIR_COEF_B2_CTL))
+		return true;
+
+	if ((reg >= WCD934X_CDC_ANC0_IIR_COEFF_1_CTL) &&
+	    (reg <= WCD934X_CDC_ANC0_FB_GAIN_CTL))
+		return true;
+
+	if ((reg >= WCD934X_CDC_ANC1_IIR_COEFF_1_CTL) &&
+	    (reg <= WCD934X_CDC_ANC1_FB_GAIN_CTL))
+		return true;
+
+	if ((reg >= WCD934X_CODEC_CPR_WR_DATA_0) &&
+	    (reg <= WCD934X_CODEC_CPR_RD_DATA_3))
+		return true;
+
+	/*
+	 * Need to mark volatile for registers that are writable but
+	 * only few bits are read-only
+	 */
+	switch (reg) {
+	case WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL:
+	case WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0:
+	case WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_1:
+	case WCD934X_CPE_SS_CPAR_CTL:
+	case WCD934X_CPE_SS_STATUS:
+	case WCD934X_CODEC_RPM_RST_CTL:
+	case WCD934X_SIDO_NEW_VOUT_A_STARTUP:
+	case WCD934X_SIDO_NEW_VOUT_D_STARTUP:
+	case WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL:
+	case WCD934X_ANA_MBHC_MECH:
+	case WCD934X_ANA_MBHC_ELECT:
+	case WCD934X_ANA_MBHC_ZDET:
+	case WCD934X_ANA_MICB2:
+	case WCD934X_CODEC_RPM_CLK_MCLK_CFG:
+	case WCD934X_CLK_SYS_MCLK_PRG:
+	case WCD934X_CHIP_TIER_CTRL_EFUSE_CTL:
+	case WCD934X_ANA_BIAS:
+	case WCD934X_ANA_BUCK_CTL:
+	case WCD934X_ANA_RCO:
+	case WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL:
+	case WCD934X_CODEC_RPM_CLK_GATE:
+	case WCD934X_BIAS_VBG_FINE_ADJ:
+	case WCD934X_CODEC_CPR_SVS_CX_VDD:
+	case WCD934X_CODEC_CPR_SVS2_CX_VDD:
+	case WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL:
+		return true;
+	}
+
+	return false;
+}
+
+struct regmap_config wcd934x_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wcd934x_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wcd934x_defaults),
+	.max_register = WCD934X_MAX_REGISTER,
+	.volatile_reg = wcd934x_is_volatile_register,
+	.readable_reg = wcd934x_is_readable_register,
+	.can_multi_write = true,
+};

+ 2155 - 0
drivers/mfd/wcd934x-tables.c

@@ -0,0 +1,2155 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/types.h>
+#include <linux/mfd/wcd934x/registers.h>
+
+#define WCD934X_REG(reg)  ((reg) & 0xFF)
+
+const u8 wcd934x_page0_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE0_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_RPM_CLK_BYPASS)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_RPM_CLK_GATE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_RPM_CLK_MCLK_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_RPM_CLK_MCLK2_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_RPM_I2S_DSD_CLK_SEL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_RPM_RST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_TEST0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_TEST1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT4)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT5)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT6)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT7)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT8)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT9)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT10)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT11)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT12)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT13)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_NONNEGO)] =
+								WCD934X_READ,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_ANA_WAIT_STATE_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_SLNQ_WAIT_STATE_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_I2C_ACTIVE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_ALT_FUNC_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_GPIO_CTL_OE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CHIP_TIER_CTRL_GPIO_CTL_DATA)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_RX0_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_RX1_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_RX2_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_RX3_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_RX4_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_RX5_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_RX6_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_RX7_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX0_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX1_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX2_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX3_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX4_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX5_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX6_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX7_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX8_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX9_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX10_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX11_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX13_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX14_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_SB_TX15_INP_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_TX0_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_TX1_0_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_TX1_1_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_0_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_1_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_2_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_3_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_CLKSRC_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_COMMON_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_0_TDM_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DATA_HUB_I2S_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_DMA_RDMA_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_2_3_CFG_RDMA_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_0_1_CFG_RDMA_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_RDMA_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_2_3_CFG_RDMA_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_0_1_CFG_RDMA_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_RDMA_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_2_3_CFG_RDMA_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_0_1_CFG_RDMA_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_RDMA_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_2_3_CFG_RDMA_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_0_1_CFG_RDMA_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_RDMA_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_2_3_CFG_RDMA_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_0_1_CFG_RDMA_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_RDMA4_PRT_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_RDMA_SBTX0_7_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_RDMA_SBTX8_11_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_WDMA_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_4_5_CFG_WDMA_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_2_3_CFG_WDMA_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_0_1_CFG_WDMA_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_WDMA_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_4_5_CFG_WDMA_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_2_3_CFG_WDMA_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_0_1_CFG_WDMA_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_WDMA_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_4_5_CFG_WDMA_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_2_3_CFG_WDMA_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_0_1_CFG_WDMA_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_WDMA_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_4_5_CFG_WDMA_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_2_3_CFG_WDMA_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_0_1_CFG_WDMA_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_WDMA_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_4_5_CFG_WDMA_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_2_3_CFG_WDMA_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_CH_0_1_CFG_WDMA_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_WDMA0_PRT_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_WDMA3_PRT_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_WDMA4_PRT0_3_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DMA_WDMA4_PRT4_7_CFG)] = WCD934X_READ_WRITE,
+};
+
+const u8 wcd934x_page1_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE1_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_USER_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_USER_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_USER_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_USER_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_USER_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_USER_CTL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_USER_CTL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_USER_CTL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_USER_CTL_8)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_USER_CTL_9)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_L_VAL_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_L_VAL_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_DSM_FRAC_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_DSM_FRAC_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_CONFIG_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_CONFIG_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_CONFIG_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_CONFIG_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_CONFIG_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_TEST_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_TEST_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_TEST_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_TEST_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_TEST_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_TEST_CTL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_TEST_CTL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_TEST_CTL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_FREQ_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_FREQ_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_FREQ_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_FREQ_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_SSC_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_SSC_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_SSC_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_SSC_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_FLL_MODE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_FLL_STATUS_0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CPE_FLL_STATUS_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CPE_FLL_STATUS_2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CPE_FLL_STATUS_3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_I2S_FLL_USER_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_USER_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_USER_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_USER_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_USER_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_USER_CTL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_USER_CTL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_USER_CTL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_USER_CTL_8)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_USER_CTL_9)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_L_VAL_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_L_VAL_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_DSM_FRAC_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_DSM_FRAC_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_CONFIG_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_CONFIG_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_CONFIG_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_CONFIG_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_CONFIG_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_TEST_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_TEST_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_TEST_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_TEST_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_TEST_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_TEST_CTL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_TEST_CTL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_TEST_CTL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_FREQ_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_FREQ_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_FREQ_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_FREQ_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_SSC_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_SSC_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_SSC_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_SSC_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_FLL_MODE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_I2S_FLL_STATUS_0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_I2S_FLL_STATUS_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_I2S_FLL_STATUS_2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_I2S_FLL_STATUS_3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SB_FLL_USER_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_USER_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_USER_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_USER_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_USER_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_USER_CTL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_USER_CTL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_USER_CTL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_USER_CTL_8)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_USER_CTL_9)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_L_VAL_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_L_VAL_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_DSM_FRAC_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_DSM_FRAC_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_CONFIG_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_CONFIG_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_CONFIG_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_CONFIG_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_CONFIG_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_TEST_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_TEST_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_TEST_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_TEST_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_TEST_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_TEST_CTL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_TEST_CTL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_TEST_CTL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_FREQ_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_FREQ_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_FREQ_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_FREQ_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_SSC_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_SSC_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_SSC_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_SSC_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_FLL_MODE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SB_FLL_STATUS_0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SB_FLL_STATUS_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SB_FLL_STATUS_2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SB_FLL_STATUS_3)] = WCD934X_READ,
+};
+
+const u8 wcd934x_page2_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE2_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_CPE_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPEFLL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_OVERRIDE)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SOC_SW_COLLAPSE_OVERRIDE_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SOC_SW_COLLAPSE_OVERRIDE_CTL1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_US_BUF_INT_PERIOD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SVA_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_US_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_MAD_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_CPAR_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_DMIC0_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_DMIC1_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_DMIC2_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_DMIC_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_CPAR_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_WDOG_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_BACKUP_INT)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_STATUS)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_CPE_OCD_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_MASK_1A)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_MASK_1B)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0A)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0B)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_STATUS_1A)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_STATUS_1B)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_0A)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_0B)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_1A)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_1B)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_MAIN_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_MAIN_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_AUDIO_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_AUDIO_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_AUDIO_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_AUDIO_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_AUDIO_CTL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_AUDIO_CTL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_AUDIO_CTL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_AUDIO_CTL_8)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_AUDIO_IIR_CTL_PTR)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_AUDIO_IIR_CTL_VAL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_ULTR_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_ULTR_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_ULTR_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_ULTR_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_ULTR_CTL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_ULTR_CTL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_ULTR_CTL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_BEACON_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_BEACON_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_BEACON_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_BEACON_CTL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_BEACON_CTL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_BEACON_CTL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_BEACON_CTL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_BEACON_CTL_8)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_BEACON_IIR_CTL_PTR)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_BEACON_IIR_CTL_VAL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SOC_MAD_INP_SEL)] = WCD934X_READ_WRITE,
+};
+
+const u8 wcd934x_page4_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE4_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_CLR_COMMIT)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_INTR_PIN1_MASK0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_PIN1_MASK1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_PIN1_MASK2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_PIN1_MASK3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_PIN1_STATUS0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_INTR_PIN1_STATUS1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_INTR_PIN1_STATUS2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_INTR_PIN1_STATUS3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_INTR_PIN1_CLEAR0)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_INTR_PIN1_CLEAR1)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_INTR_PIN1_CLEAR2)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_INTR_PIN1_CLEAR3)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_INTR_PIN2_MASK3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_PIN2_STATUS3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_INTR_PIN2_CLEAR3)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_INTR_CPESS_SUMRY_MASK2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_CPESS_SUMRY_MASK3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_CPESS_SUMRY_STATUS2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_INTR_CPESS_SUMRY_STATUS3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_INTR_CPESS_SUMRY_CLEAR2)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_INTR_CPESS_SUMRY_CLEAR3)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_INTR_LEVEL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_LEVEL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_LEVEL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_LEVEL3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_BYPASS0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_BYPASS1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_BYPASS2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_BYPASS3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_SET0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_SET1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_SET2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_SET3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_CODEC_MISC_MASK)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_INTR_CODEC_MISC_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_INTR_CODEC_MISC_CLEAR)] = WCD934X_WRITE,
+};
+
+const u8 wcd934x_page5_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE5_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_DEVICE)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_REVISION)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_H_COMMAND)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_NUMBER_OF_BYTE_MSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_NUMBER_OF_BYTE_LSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_MASTER_ADDRESS_MSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_MASTER_ADDRESS_LSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SLAVE_ADDRESS_MSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SLAVE_ADDRESS_LSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_TIMER0_INTERRUPT_MSB)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_TIMER0_INTERRUPT_LSB)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_TIMER1_INTERRUPT_MSB)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_TIMER1_INTERRUPT_LSB)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_TIMER2_INTERRUPT_MSB)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_TIMER2_INTERRUPT_LSB)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_COMM_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_FRAME_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_2ND_DATA_CH1_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_2ND_DATA_CH3_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_2ND_DATA_CH5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SW_EVENT_RD)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SW_EVENT_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_SELECT_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_SELECT_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_SELECT_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_SAMPLING_FREQ)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_DC_CONVERSION_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_DC_CONVERSION_SEL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_DC_CONV_CHA_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_DC_CONV_CHA_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_DC_CONV_CHB_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_DC_CONV_CHB_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_RAM_CNTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BANK)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_8)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_9)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_A)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_B)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_C)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_D)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_E)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_F)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_10)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_11)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_12)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_13)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_14)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_15)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_16)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_17)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_18)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_19)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_1A)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_1B)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_1C)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_1D)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_1E)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_1F)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_20)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_21)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_22)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_23)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_24)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_25)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_26)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_27)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_28)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_29)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_2A)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_2B)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_2C)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_2D)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_2E)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_2F)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_30)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_31)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_32)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_33)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_34)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_35)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_36)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_37)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_38)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_39)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_3A)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_3B)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_3C)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_3D)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_3E)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_SRAM_BYTE_3F)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_TOP_CTRL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_TOP_CTRL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_PDM_MUTE_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_DEC_BYPASS_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_DEC_BYPASS_STATUS)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_DEC_BYPASS_FS)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_DEC_BYPASS_IN_SEL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_GPOUT_ENABLE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_GPOUT_VAL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_ANA_INTERRUPT_MASK)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_ANA_INTERRUPT_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_ANA_INTERRUPT_CLR)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_IP_TESTING)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_CNTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_CNT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_CNT_MSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_CNT_LSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_MASK0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_MASK1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_MASK2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_MASK3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_MASK4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_STATUS0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_STATUS1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_STATUS2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_STATUS3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_STATUS4)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_CLR0)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_CLR1)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_CLR2)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_CLR3)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_DIG_INTERRUPT_CLR4)] = WCD934X_WRITE,
+};
+
+const u8 wcd934x_page6_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_ANA_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_BIAS)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_RCO)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_PAGE6_SPARE2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_PAGE6_SPARE3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_BUCK_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_BUCK_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_ANA_RX_SUPPLIES)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_HPH)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_EAR)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_LO_1_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MAD_SETUP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_AMIC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_AMIC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_AMIC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_AMIC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_MECH)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_ELECT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_ZDET)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_RESULT_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_ANA_MBHC_RESULT_2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_ANA_MBHC_RESULT_3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_ANA_MBHC_BTN0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_BTN1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_BTN2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_BTN3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_BTN4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_BTN5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_BTN6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MBHC_BTN7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MICB1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MICB2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MICB2_RAMP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MICB3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_MICB4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_ANA_VBADC)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BIAS_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BIAS_VBG_FINE_ADJ)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RCO_CTRL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RCO_CTRL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RCO_CAL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RCO_CAL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RCO_CAL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RCO_TEST_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RCO_CAL_OUT_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_RCO_CAL_OUT_2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_RCO_CAL_OUT_3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_RCO_CAL_OUT_4)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_RCO_CAL_OUT_5)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDO_MODE_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_MODE_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_MODE_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_MODE_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_VCL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_VCL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_VCL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CCL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CCL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CCL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CCL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CCL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CCL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CCL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CCL_8)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CCL_9)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CCL_10)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_FILTER_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_FILTER_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_DRIVER_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_DRIVER_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_DRIVER_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CAL_CODE_EXT_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CAL_CODE_EXT_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_CAL_CODE_OUT_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDO_CAL_CODE_OUT_2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDO_TEST_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_TEST_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_CTL_CLK)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_CTL_ANA)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_CTL_SPARE_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_CTL_SPARE_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_CTL_BCS)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_STATUS_SPARE_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MBHC_TEST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_VBADC_SUBBLOCK_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_VBADC_IBIAS_FE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_VBADC_BIAS_ADC)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_VBADC_FE_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_VBADC_ADC_REF)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_VBADC_ADC_IO)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_VBADC_ADC_SAR)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_VBADC_DEBUG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_LDOH_MODE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_LDOH_BIAS)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_LDOH_STB_LOADS)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_LDOH_SLOWRAMP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB1_TEST_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB1_TEST_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB1_TEST_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB2_TEST_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB2_TEST_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB2_TEST_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB3_TEST_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB3_TEST_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB3_TEST_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB4_TEST_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB4_TEST_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MICB4_TEST_CTL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_COM_ADC_VCM)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_COM_BIAS_ATEST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_COM_ADC_INT1_IB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_COM_ADC_INT2_IB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_COM_TXFE_DIV_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_COM_TXFE_DIV_START)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_COM_TXFE_DIV_STOP_9P6M)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_COM_TXFE_DIV_STOP_12P288M)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_1_2_TEST_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_1_2_ADC_IB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_1_2_ATEST_REFCTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_1_2_TEST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_1_2_TEST_BLK_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_1_2_TXFE_CLKDIV)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_1_2_SAR1_ERR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_TX_1_2_SAR2_ERR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_TX_3_4_TEST_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_3_4_ADC_IB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_3_4_ATEST_REFCTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_3_4_TEST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_3_4_TEST_BLK_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_3_4_TXFE_CLKDIV)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TX_3_4_SAR1_ERR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_TX_3_4_SAR2_ERR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CLASSH_MODE_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_MODE_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_MODE_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_CTRL_VCL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_CTRL_VCL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_CTRL_CCL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_CTRL_CCL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_CTRL_CCL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_CTRL_CCL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_CTRL_CCL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_BUCK_TMUX_A_D)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_BUCK_SW_DRV_CNTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLASSH_SPARE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEG_CTRL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEG_CTRL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEG_CTRL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEG_CTRL_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEG_CTRL_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEG_CTRL_6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEG_CTRL_7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEG_CTRL_8)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEG_CTRL_9)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEGDAC_CTRL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEGDAC_CTRL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_VNEGDAC_CTRL_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_CTRL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_FLYBACK_TEST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_AUX_SW_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_PA_AUX_IN_CONN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_TIMER_DIV)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_OCP_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_OCP_COUNT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_EAR_DAC)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_EAR_AMP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_HPH_LDO)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_HPH_PA)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_HPH_RDACBUFF_CNP2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_HPH_RDAC_LDO)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_HPH_CNP1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_HPH_LOWPOWER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_DIFFLO_PA)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_DIFFLO_REF)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_DIFFLO_LDO)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_SELO_DAC_PA)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_BUCK_RST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_BUCK_VREF_ERRAMP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_FLYB_ERRAMP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_FLYB_BUFF)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_BIAS_FLYB_MID_RST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_L_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_HPH_R_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_HPH_CNP_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_CNP_WG_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_CNP_WG_TIME)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_OCP_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_AUTO_CHOP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_CHOP_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_PA_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_PA_CTL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_L_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_L_TEST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_L_ATEST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_R_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_R_TEST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_R_ATEST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_RDAC_CLK_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_RDAC_CLK_CTL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_RDAC_LDO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_RDAC_CHOP_CLK_LP_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_REFBUFF_UHQA_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_REFBUFF_LP_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_L_DAC_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_R_DAC_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EAR_EN_REG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EAR_CMBUFF)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EAR_ICTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EAR_EN_DBG_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EAR_CNP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EAR_DAC_CTL_ATEST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EAR_STATUS_REG)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EAR_EAR_MISC)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_MISC)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_LO2_COMPANDER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_LO1_COMPANDER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_COMMON)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_BYPASS_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_CNP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_CORE_OUT_PROG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_LDO_OUT_PROG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_COM_SWCAP_REFBUF_FREQ)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_COM_PA_FREQ)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_RESERVED_REG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_DIFF_LO_LO1_STATUS_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_DIFF_LO_LO1_STATUS_2)] = WCD934X_READ,
+};
+
+const u8 wcd934x_page7_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_ANA_NEW_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_ANA_HPH2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_ANA_HPH3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_EN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_LDO_CONFIG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_LDO_OCP_CONFIG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_TX_LDO_CONFIG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_TX_DRV_CONFIG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_RX_CONFIG_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_RX_CONFIG_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_PLL_ENABLES)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_PLL_PRESET)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_ANA_PLL_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CLK_SYS_PLL_ENABLES)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_PLL_PRESET)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_PLL_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CLK_SYS_MCLK_PRG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_MCLK2_PRG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_MCLK2_PRG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_XO_PRG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_XO_CAP_XTP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_XO_CAP_XTM)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_BST_EN_DLY)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_CTRL_ILIM)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_VOUT_SETTING)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_VOUT_A_STARTUP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_VOUT_D_STARTUP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_VOUT_D_FREQ1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_VOUT_D_FREQ2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_ELECT_REM_CLAMP_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_CTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_CTL_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_PLUG_DETECT_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_ZDET_ANA_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_ZDET_RAMP_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_FSM_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MBHC_NEW_ADC_RESULT)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_TX_NEW_AMIC_4_5_SEL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_VBADC_NEW_ADC_MODE)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_VBADC_NEW_ADC_DOUTMSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_VBADC_NEW_ADC_DOUTLSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_RDAC_HD2_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_RDAC_VREF_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_RDAC_MISC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_PA_MISC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_PA_MISC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_PA_RDAC_MISC)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_HPH_TIMER1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_HPH_TIMER2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_HPH_TIMER3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_HPH_TIMER4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_PA_RDAC_MISC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_HPH_NEW_INT_PA_RDAC_MISC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_NEW_INT_HPH_RDAC_BIAS_ULP)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_RX_NEW_INT_HPH_RDAC_LDO_LP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_LDO_TEST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_LDO_DEBUG_1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_LDO_DEBUG_2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_TX_LDO_TEST)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_TX_DRV_TEST)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_RX_TEST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_RX_TEST_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_RX_DEBUG_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_RX_DEBUG_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_CLK_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_RESERVED_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_RESERVED_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_POST_DIV_REG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_POST_DIV_REG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_REF_DIV_REG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_REF_DIV_REG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_FILTER_REG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_FILTER_REG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_L_VAL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_M_VAL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_N_VAL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_TEST_REG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_PFD_CP_DSM_PROG)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_VCO_PROG)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_TEST_REG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_LDO_LOCK_CFG)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SLNQ_INT_ANA_INT_PLL_DIG_LOCK_DET_CFG)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_POST_DIV_REG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_POST_DIV_REG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_REF_DIV_REG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_REF_DIV_REG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_FILTER_REG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_FILTER_REG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_PLL_L_VAL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_PLL_M_VAL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_PLL_N_VAL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_TEST_REG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_PFD_CP_DSM_PROG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_VCO_PROG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_TEST_REG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_LDO_LOCK_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_DIG_LOCK_DET_CFG)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_CLK_TEST1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_CLK_TEST2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_CLK_TEST3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_XO_TEST1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CLK_SYS_INT_XO_TEST2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_VCOMP_HYST)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_VLOOP_FILTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_CTRL_IDELTA)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_CTRL_ILIM_STARTUP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_CTRL_MIN_ONTIME)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_CTRL_MAX_ONTIME)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_CTRL_TIMING)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_TMUX_A_D)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_SW_DRV_CNTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_SPARE1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_BOOST_INT_SPARE2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_RAMP_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_SPARE_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_DEBUG_VOUT_SETTING_A)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_DEBUG_VOUT_SETTING_D)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_RAMP_INC_WAIT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_RAMP_IBLEED_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_DEBUG_CPROVR_TEST)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_RAMP_CTL_A)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_RAMP_CTL_D)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_RAMP_TIMEOUT_PERIOD)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_SETTING1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_SETTING2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_SETTING3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_HIGH_ACCU_MODE_SEL1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDO_NEW_INT_HIGH_ACCU_MODE_SEL2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_INT_SLNQ_HPF)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_INT_SLNQ_REF)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_INT_SLNQ_COMP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MBHC_NEW_INT_SPARE_2)] = WCD934X_READ_WRITE,
+
+};
+
+const u8 wcd934x_page10_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE10_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_CLK_RESET_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_MODE_1_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_MODE_2_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_FF_SHIFT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_FB_SHIFT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_LPF_FF_A_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_LPF_FF_B_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_LPF_FB_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_SMLPF_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_DCFLT_SHIFT_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_IIR_ADAPT_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_IIR_COEFF_1_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_IIR_COEFF_2_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_FF_A_GAIN_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_FF_B_GAIN_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_FB_GAIN_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_RC_COMMON_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_FIFO_COMMON_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC0_RC0_STATUS_FMIN_CNTR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_ANC0_RC1_STATUS_FMIN_CNTR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_ANC0_RC0_STATUS_FMAX_CNTR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_ANC0_RC1_STATUS_FMAX_CNTR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_ANC0_STATUS_FIFO)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_ANC1_CLK_RESET_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_MODE_1_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_MODE_2_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_FF_SHIFT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_FB_SHIFT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_LPF_FF_A_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_LPF_FF_B_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_LPF_FB_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_SMLPF_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_DCFLT_SHIFT_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_IIR_ADAPT_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_IIR_COEFF_1_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_IIR_COEFF_2_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_FF_A_GAIN_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_FF_B_GAIN_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_FB_GAIN_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_RC_COMMON_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_FIFO_COMMON_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_ANC1_RC0_STATUS_FMIN_CNTR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_ANC1_RC1_STATUS_FMIN_CNTR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_ANC1_RC0_STATUS_FMAX_CNTR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_ANC1_RC1_STATUS_FMAX_CNTR)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_ANC1_STATUS_FIFO)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_192_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_192_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX0_TX_PATH_SEC7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_192_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_192_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX1_TX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_192_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_192_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX2_TX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_192_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_192_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX3_TX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_192_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_192_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX4_TX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_192_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_192_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX5_TX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_192_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_192_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX6_TX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_192_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_192_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX7_TX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_192_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_192_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX8_TX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX9_SPKR_PROT_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX10_SPKR_PROT_PATH_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX11_SPKR_PROT_PATH_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX12_SPKR_PROT_PATH_CFG0)] =
+							WCD934X_READ_WRITE,
+};
+
+const u8 wcd934x_page11_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE11_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER1_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER1_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER1_CTL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER1_CTL3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER1_CTL4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER1_CTL5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER1_CTL6)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER1_CTL7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER2_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER2_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER2_CTL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER2_CTL3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER2_CTL4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER2_CTL5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER2_CTL6)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER2_CTL7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER3_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER3_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER3_CTL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER3_CTL3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER3_CTL4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER3_CTL5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER3_CTL6)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER3_CTL7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER4_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER4_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER4_CTL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER4_CTL3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER4_CTL4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER4_CTL5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER4_CTL6)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER4_CTL7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER7_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER7_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER7_CTL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER7_CTL3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER7_CTL4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER7_CTL5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER7_CTL6)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER7_CTL7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER8_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER8_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER8_CTL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER8_CTL3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER8_CTL4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER8_CTL5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER8_CTL6)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_COMPANDER8_CTL7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_MIX_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_VOL_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_SEC7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_MIX_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_MIX_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_MIX_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_VOL_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_SEC7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_MIX_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_MIX_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_MIX_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_VOL_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_SEC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_SEC7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_MIX_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_MIX_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_MIX_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_VOL_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_SEC7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_MIX_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_MIX_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_MIX_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_VOL_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_SEC7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_MIX_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_MIX_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_MIX_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_VOL_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_SEC7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_MIX_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_MIX_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_VOL_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_MIX_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_VOL_MIX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_SEC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_SEC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_SEC5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_SEC6)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_SEC7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_MIX_SEC0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_MIX_SEC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL)] = WCD934X_READ_WRITE,
+};
+
+const u8 wcd934x_page12_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE12_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_CRC)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_DLY_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_DECAY_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_HPH_V_PA)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_EAR_V_PA)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_HPH_V_HD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_EAR_V_HD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_K1_MSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_K1_LSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_K2_MSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_K2_LSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_IDLE_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_IDLE_HPH)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_IDLE_EAR)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_TEST0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_TEST1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLSH_OVR_VREF)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_BOOST0_BOOST_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_BOOST0_BOOST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_BOOST0_BOOST_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_BOOST0_BOOST_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_BOOST1_BOOST_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_BOOST1_BOOST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_BOOST1_BOOST_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_BOOST1_BOOST_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_ADC_CAL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_ADC_CAL2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_ADC_CAL3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_PK_EST1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_PK_EST2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_PK_EST3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_RF_PROC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_RF_PROC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_TAC1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_TAC2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_TAC3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_TAC4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_GAIN_UPD1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_GAIN_UPD2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_GAIN_UPD3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_GAIN_UPD4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_DEBUG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_GAIN_UPD_MON)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_GAIN_MON_VAL)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_VBAT_VBAT_BAN)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC0_CLK_RST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC0_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC0_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC0_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC0_STATUS_FMIN_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC0_STATUS_FMIN_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC0_STATUS_FMAX_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC0_STATUS_FMAX_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC0_STATUS_FIFO)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC1_CLK_RST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC1_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC1_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC1_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC1_STATUS_FMIN_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC1_STATUS_FMIN_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC1_STATUS_FMAX_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC1_STATUS_FMAX_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC1_STATUS_FIFO)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC2_CLK_RST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC2_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC2_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC2_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC2_STATUS_FMIN_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC2_STATUS_FMIN_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC2_STATUS_FMAX_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC2_STATUS_FMAX_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC2_STATUS_FIFO)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC3_CLK_RST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC3_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC3_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC3_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_MIXING_ASRC3_STATUS_FMIN_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC3_STATUS_FMIN_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC3_STATUS_FMAX_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC3_STATUS_FMAX_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_MIXING_ASRC3_STATUS_FIFO)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_WR_DATA_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_WR_DATA_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_WR_DATA_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_WR_DATA_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_WR_ADDR_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_WR_ADDR_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_WR_ADDR_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_RD_ADDR_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_RD_ADDR_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_RD_ADDR_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_RD_ADDR_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_RD_DATA_0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_RD_DATA_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_RD_DATA_2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_RD_DATA_3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_ACCESS_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SWR_AHB_BRIDGE_ACCESS_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CFG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CFG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC0_CLK_RST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC0_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC0_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC0_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC0_STATUS_FMIN_CNTR_LSB)] =
+							WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC0_STATUS_FMIN_CNTR_MSB)] =
+							WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC0_STATUS_FMAX_CNTR_LSB)] =
+							WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC0_STATUS_FMAX_CNTR_MSB)] =
+							WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC0_STATUS_FIFO)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC1_CLK_RST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC1_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC1_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC1_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC1_STATUS_FMIN_CNTR_LSB)] =
+							WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC1_STATUS_FMIN_CNTR_MSB)] =
+							WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC1_STATUS_FMAX_CNTR_LSB)] =
+							WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC1_STATUS_FMAX_CNTR_MSB)] =
+							WCD934X_READ,
+	[WCD934X_REG(WCD934X_SIDETONE_ASRC1_STATUS_FIFO)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EC_REF_HQ0_EC_REF_HQ_PATH_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_REF_HQ0_EC_REF_HQ_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_REF_HQ1_EC_REF_HQ_PATH_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_REF_HQ1_EC_REF_HQ_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_ASRC0_CLK_RST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_ASRC0_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_ASRC0_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_ASRC0_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_ASRC0_STATUS_FMIN_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EC_ASRC0_STATUS_FMIN_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EC_ASRC0_STATUS_FMAX_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EC_ASRC0_STATUS_FMAX_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EC_ASRC0_STATUS_FIFO)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EC_ASRC1_CLK_RST_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_ASRC1_CTL0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_ASRC1_CTL1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_ASRC1_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_EC_ASRC1_STATUS_FMIN_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EC_ASRC1_STATUS_FMIN_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EC_ASRC1_STATUS_FMAX_CNTR_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EC_ASRC1_STATUS_FMAX_CNTR_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_EC_ASRC1_STATUS_FIFO)] = WCD934X_READ,
+};
+
+const u8 wcd934x_page13_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE13_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_ANC_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_INP_MUX_EC_REF_HQ_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX10_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX11_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX12_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TX_INP_MUX_ADC_MUX13_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLK_RST_CTRL_DSD_CONTROL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLK_RST_CTRL_ASRC_SHARE_CONTROL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_CLK_RST_CTRL_GFM_CONTROL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_POLL_PERIOD0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_POLL_PERIOD1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_SIG_PATTERN_LSB)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_SIG_PATTERN_MSB)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_TEST_CTRL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB_RD)] =
+							WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB_RD)] =
+							WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_PROX_DETECT_PROX_CTL_REPEAT_PAT)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_PATH_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B5_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B6_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B7_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B8_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_PATH_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B5_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B6_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B7_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B8_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_COEF_B1_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_SIDETONE_IIR1_IIR_COEF_B2_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_TOP_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_TOP_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_TOP_CFG7)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_HPHL_COMP_WR_LSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_HPHL_COMP_WR_MSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_HPHL_COMP_LUT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_HPHL_COMP_RD_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_TOP_HPHL_COMP_RD_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_TOP_HPHR_COMP_WR_LSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_HPHR_COMP_WR_MSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_HPHR_COMP_LUT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_HPHR_COMP_RD_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_TOP_HPHR_COMP_RD_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_TOP_DIFFL_COMP_WR_LSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_DIFFL_COMP_WR_MSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_DIFFL_COMP_LUT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_DIFFL_COMP_RD_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_TOP_DIFFL_COMP_RD_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_TOP_DIFFR_COMP_WR_LSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_DIFFR_COMP_WR_MSB)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_DIFFR_COMP_LUT)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_TOP_DIFFR_COMP_RD_LSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_TOP_DIFFR_COMP_RD_MSB)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_DSD0_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD0_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD0_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD0_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD0_CFG3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD0_CFG4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD0_CFG5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD1_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD1_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD1_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD1_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD1_CFG3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD1_CFG4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DSD1_CFG5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_IDLE_DET_PATH_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_IDLE_DET_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_IDLE_DET_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_IDLE_DET_CFG2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RX_IDLE_DET_CFG3)] = WCD934X_READ_WRITE,
+};
+
+const u8 wcd934x_page14_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE14_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_CLK_RST_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_PULSE_SUPR_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_TIMER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_BW_SW)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_THRESH)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_TIMER2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_RMAX_DIAG)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_RMIN_DIAG)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_PH_DET)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_DIAG_CLR)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_MB_SW_STATE)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_MAST_DIAG_STATE)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_RATE_OUT_7_0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_RATE_OUT_15_8)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_RATE_OUT_23_16)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_RATE_OUT_31_24)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_RATE_OUT_39_32)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST0_RE_RATE_OUT_40_43)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_CLK_RST_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_PULSE_SUPR_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_TIMER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_BW_SW)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_THRESH)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_TIMER2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_RMAX_DIAG)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_RMIN_DIAG)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_PH_DET)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_DIAG_CLR)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_MB_SW_STATE)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_MAST_DIAG_STATE)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_RATE_OUT_7_0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_RATE_OUT_15_8)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_RATE_OUT_23_16)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_RATE_OUT_31_24)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_RATE_OUT_39_32)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST1_RE_RATE_OUT_40_43)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_CLK_RST_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_PULSE_SUPR_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_TIMER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_BW_SW)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_THRESH)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_TIMER2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_RMAX_DIAG)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_RMIN_DIAG)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_PH_DET)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_DIAG_CLR)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_MB_SW_STATE)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_MAST_DIAG_STATE)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_RATE_OUT_7_0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_RATE_OUT_15_8)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_RATE_OUT_23_16)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_RATE_OUT_31_24)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_RATE_OUT_39_32)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST2_RE_RATE_OUT_40_43)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_CLK_RST_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_PULSE_SUPR_CTL)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_TIMER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_BW_SW)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_THRESH)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_TIMER2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW5)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_RMAX_DIAG)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_RMIN_DIAG)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_PH_DET)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_DIAG_CLR)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_MB_SW_STATE)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_MAST_DIAG_STATE)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_RATE_OUT_7_0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_RATE_OUT_15_8)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_RATE_OUT_23_16)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_RATE_OUT_31_24)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_RATE_OUT_39_32)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_RATE_EST3_RE_RATE_OUT_40_43)] = WCD934X_READ,
+};
+
+const u8 wcd934x_page15_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE15_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SPLINE_SRC0_CLK_RST_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SPLINE_SRC0_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SPLINE_SRC1_CLK_RST_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SPLINE_SRC1_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SPLINE_SRC2_CLK_RST_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SPLINE_SRC2_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_SPLINE_SRC3_CLK_RST_CTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_SPLINE_SRC3_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_SPLINE_SRC_DEBUG_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_SPLINE_SRC_DEBUG_CFG1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_RC_RE_ASRC_DEBUG_CFG0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_ANC0_RC0_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_ANC0_RC1_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_ANC1_RC0_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_ANC1_RC1_FIFO_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CDC_DEBUG_ANC_RC_RST_DBG_CNTR)] =
+							WCD934X_READ_WRITE,
+};
+
+const u8 wcd934x_page_0x50_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE80_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_DATA_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_DATA_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_DATA_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_DATA_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_ADDR_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_ADDR_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_ADDR_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_ADDR_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_ADDR_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_ADDR_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_ADDR_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_ADDR_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_DATA_0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_DATA_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_DATA_2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_DATA_3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_ACCESS_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_ACCESS_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_NOM_CX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SVS_CX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SVS2_CX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_NOM_MX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SVS_MX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SVS2_MX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SVS2_MIN_CX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_MAX_SVS2_STEP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SW_MODECHNG_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SW_MODECHNG_START)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_CPR_STATUS)] = WCD934X_READ_WRITE,
+};
+
+const u8 wcd934x_page_0x80_reg_access[WCD934X_PAGE_SIZE] = {
+	[WCD934X_REG(WCD934X_PAGE80_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_DATA_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_DATA_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_DATA_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_DATA_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_ADDR_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_ADDR_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_ADDR_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_WR_ADDR_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_ADDR_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_ADDR_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_ADDR_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_ADDR_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_DATA_0)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_DATA_1)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_DATA_2)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_RD_DATA_3)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_ACCESS_CFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_ACCESS_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_NOM_CX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SVS_CX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SVS2_CX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_NOM_MX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SVS_MX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SVS2_MX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SVS2_MIN_CX_VDD)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_MAX_SVS2_STEP)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_CTL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SW_MODECHNG_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_CODEC_CPR_SW_MODECHNG_START)] = WCD934X_WRITE,
+	[WCD934X_REG(WCD934X_CODEC_CPR_CPR_STATUS)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_PAGE128_PAGE_REGISTER)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_BIST_MODE_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_RF_PA_ON_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_INTR1_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_INTR2_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_SWR_DATA_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_SWR_CLK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_2_SCK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_SLIMBUS_DATA1_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_SLIMBUS_DATA2_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_SLIMBUS_CLK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2C_CLK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2C_DATA_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_0_RX_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_0_TX_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_0_SCK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_0_WS_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_1_RX_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_1_TX_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_1_SCK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_1_WS_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_DMIC1_CLK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_DMIC1_DATA_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_DMIC2_CLK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_DMIC2_DATA_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_DMIC3_CLK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_DMIC3_DATA_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_JTCK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_GPIO1_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_GPIO2_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_GPIO3_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_GPIO4_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_SPI_S_CSN_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_SPI_S_CLK_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_SPI_S_DOUT_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_SPI_S_DIN_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_BA_N_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_GPIO0_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_2_RX_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TLMM_I2S_2_WS_PINCFG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_CTL_OE_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_CTL_OE_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_CTL_OE_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_CTL_OE_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_CTL_OE_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_CTL_DATA_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_CTL_DATA_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_CTL_DATA_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_CTL_DATA_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_CTL_DATA_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PAD_DRVCTL_0)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PAD_DRVCTL_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PIN_STATUS)] = WCD934X_READ,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_NPL_DLY_TEST_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_NPL_DLY_TEST_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_MEM_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_DEBUG_BUS_SEL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_DEBUG_JTAG)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_DEBUG_EN_1)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_DEBUG_EN_2)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_DEBUG_EN_3)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_DEBUG_EN_4)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_DEBUG_EN_5)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_ANA_DTEST_DIR)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PAD_INP_DISABLE_0)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PAD_INP_DISABLE_1)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PAD_INP_DISABLE_2)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PAD_INP_DISABLE_3)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_PAD_INP_DISABLE_4)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_SYSMEM_CTRL)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_SOC_SW_PWR_SEQ_DELAY)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_LVAL_NOM_LOW)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_LVAL_NOM_HIGH)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_LVAL_SVS_SVS2_LOW)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_LVAL_SVS_SVS2_HIGH)] =
+							WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_SPI_SLAVE_CHAR)] = WCD934X_READ_WRITE,
+	[WCD934X_REG(WCD934X_TEST_DEBUG_CODEC_DIAGS)] = WCD934X_READ,
+};
+
+const u8 * const wcd934x_reg[WCD934X_NUM_PAGES] = {
+	[WCD934X_PAGE_0] = wcd934x_page0_reg_access,
+	[WCD934X_PAGE_1] = wcd934x_page1_reg_access,
+	[WCD934X_PAGE_2] = wcd934x_page2_reg_access,
+	[WCD934X_PAGE_4] = wcd934x_page4_reg_access,
+	[WCD934X_PAGE_5] = wcd934x_page5_reg_access,
+	[WCD934X_PAGE_6] = wcd934x_page6_reg_access,
+	[WCD934X_PAGE_7] = wcd934x_page7_reg_access,
+	[WCD934X_PAGE_10] = wcd934x_page10_reg_access,
+	[WCD934X_PAGE_11] = wcd934x_page11_reg_access,
+	[WCD934X_PAGE_12] = wcd934x_page12_reg_access,
+	[WCD934X_PAGE_13] = wcd934x_page13_reg_access,
+	[WCD934X_PAGE_14] = wcd934x_page14_reg_access,
+	[WCD934X_PAGE_15] = wcd934x_page15_reg_access,
+	[WCD934X_PAGE_0x50] = wcd934x_page_0x50_reg_access,
+	[WCD934X_PAGE_0X80] = wcd934x_page_0x80_reg_access,
+};

+ 55 - 0
drivers/mfd/wcd9xxx-core-init.c

@@ -0,0 +1,55 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/mfd/msm-cdc-pinctrl.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-irq.h>
+#include <linux/mfd/wcd9xxx/core.h>
+
+#define NUM_DRIVERS_REG_RET 3
+
+static int __init wcd9xxx_core_init(void)
+{
+	int ret[NUM_DRIVERS_REG_RET] = {0};
+	int i = 0;
+
+	ret[0] = msm_cdc_pinctrl_drv_init();
+	if (ret[0])
+		pr_err("%s: Failed init pinctrl drv: %d\n", __func__, ret[0]);
+
+	ret[1] = wcd9xxx_irq_drv_init();
+	if (ret[1])
+		pr_err("%s: Failed init irq drv: %d\n", __func__, ret[1]);
+
+	ret[2] = wcd9xxx_init();
+	if (ret[2])
+		pr_err("%s: Failed wcd core drv: %d\n", __func__, ret[2]);
+
+	for (i = 0; i < NUM_DRIVERS_REG_RET; i++) {
+		if (ret[i])
+			return ret[i];
+	}
+
+	return 0;
+}
+module_init(wcd9xxx_core_init);
+
+static void __exit wcd9xxx_core_exit(void)
+{
+	wcd9xxx_exit();
+	wcd9xxx_irq_drv_exit();
+	msm_cdc_pinctrl_drv_exit();
+}
+module_exit(wcd9xxx_core_exit);
+
+MODULE_DESCRIPTION("WCD9XXX CODEC core init driver");
+MODULE_LICENSE("GPL v2");

+ 1714 - 0
drivers/mfd/wcd9xxx-core.c

@@ -0,0 +1,1714 @@
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/ratelimit.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-irq.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/msm-cdc-pinctrl.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-utils.h>
+#include <linux/mfd/msm-cdc-supply.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/debugfs.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include "wcd9xxx-regmap.h"
+
+#define WCD9XXX_REGISTER_START_OFFSET 0x800
+#define WCD9XXX_SLIM_RW_MAX_TRIES 3
+#define SLIMBUS_PRESENT_TIMEOUT 100
+
+#define MAX_WCD9XXX_DEVICE	4
+#define WCD9XXX_I2C_GSBI_SLAVE_ID "3-000d"
+#define WCD9XXX_I2C_TOP_SLAVE_ADDR	0x0d
+#define WCD9XXX_ANALOG_I2C_SLAVE_ADDR	0x77
+#define WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR	0x66
+#define WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR	0x55
+#define WCD9XXX_I2C_TOP_LEVEL	0
+#define WCD9XXX_I2C_ANALOG	1
+#define WCD9XXX_I2C_DIGITAL_1	2
+#define WCD9XXX_I2C_DIGITAL_2	3
+
+/*
+ * Number of return values needs to be checked for each
+ * registration of Slimbus of I2C bus for each codec
+ */
+#define NUM_WCD9XXX_REG_RET	4
+
+#define SLIM_USR_MC_REPEAT_CHANGE_VALUE 0x0
+#define SLIM_REPEAT_WRITE_MAX_SLICE 16
+#define REG_BYTES 2
+#define VAL_BYTES 1
+#define WCD9XXX_PAGE_NUM(reg)    (((reg) >> 8) & 0xff)
+#define WCD9XXX_PAGE_SIZE 256
+
+struct wcd9xxx_i2c {
+	struct i2c_client *client;
+	struct i2c_msg xfer_msg[2];
+	struct mutex xfer_lock;
+	int mod_id;
+};
+
+static struct regmap_config wcd9xxx_base_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.can_multi_write = true,
+};
+
+static struct regmap_config wcd9xxx_i2c_base_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.can_multi_write = false,
+	.use_single_rw = true,
+};
+
+static u8 wcd9xxx_pgd_la;
+static u8 wcd9xxx_inf_la;
+
+static const int wcd9xxx_cdc_types[] = {
+	[WCD9XXX] = WCD9XXX,
+	[WCD9330] = WCD9330,
+	[WCD9335] = WCD9335,
+	[WCD934X] = WCD934X,
+};
+
+static const struct of_device_id wcd9xxx_of_match[] = {
+	{ .compatible = "qcom,tasha-i2c-pgd",
+	  .data = (void *)&wcd9xxx_cdc_types[WCD9335]},
+	{ .compatible = "qcom,wcd9xxx-i2c",
+	  .data = (void *)&wcd9xxx_cdc_types[WCD9330]},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wcd9xxx_of_match);
+
+static int wcd9xxx_slim_device_up(struct slim_device *sldev);
+static int wcd9xxx_slim_device_down(struct slim_device *sldev);
+
+struct wcd9xxx_i2c wcd9xxx_modules[MAX_WCD9XXX_DEVICE];
+
+static int wcd9xxx_slim_multi_reg_write(struct wcd9xxx *wcd9xxx,
+					const void *data, size_t count)
+{
+	unsigned int reg;
+	struct device *dev;
+	u8 val[WCD9XXX_PAGE_SIZE];
+	int ret = 0;
+	int i = 0;
+	int n = 0;
+	unsigned int page_num;
+	size_t num_regs = (count / (REG_BYTES + VAL_BYTES));
+	struct wcd9xxx_reg_val *bulk_reg;
+	u8 *buf;
+
+	dev = wcd9xxx->dev;
+	if (!data) {
+		dev_err(dev, "%s: data is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (num_regs == 0)
+		return -EINVAL;
+
+	bulk_reg = kzalloc(num_regs * (sizeof(struct wcd9xxx_reg_val)),
+			   GFP_KERNEL);
+	if (!bulk_reg)
+		return -ENOMEM;
+
+	buf = (u8 *)data;
+	reg = *(u16 *)buf;
+	page_num = WCD9XXX_PAGE_NUM(reg);
+	for (i = 0, n = 0; n < num_regs; i++, n++) {
+		reg = *(u16 *)buf;
+		if (page_num != WCD9XXX_PAGE_NUM(reg)) {
+			ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg,
+						      i, false);
+			page_num = WCD9XXX_PAGE_NUM(reg);
+			i = 0;
+		}
+		buf += REG_BYTES;
+		val[i] = *buf;
+		buf += VAL_BYTES;
+		bulk_reg[i].reg = reg;
+		bulk_reg[i].buf = &val[i];
+		bulk_reg[i].bytes = 1;
+	}
+	ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg,
+				      i, false);
+	if (ret)
+		dev_err(dev, "%s: error writing bulk regs\n",
+			__func__);
+
+	kfree(bulk_reg);
+	return ret;
+}
+
+/*
+ * wcd9xxx_interface_reg_read: Read slim interface registers
+ *
+ * @wcd9xxx: Pointer to wcd9xxx structure
+ * @reg: register adderss
+ *
+ * Returns register value in success and negative error code in case of failure
+ */
+int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
+{
+	u8 val;
+	int ret;
+
+	mutex_lock(&wcd9xxx->io_lock);
+	ret = wcd9xxx->read_dev(wcd9xxx, reg, 1, (void *)&val,
+				true);
+	if (ret < 0)
+		dev_err(wcd9xxx->dev, "%s: Codec read 0x%x failed\n",
+			__func__, reg);
+	else
+		dev_dbg(wcd9xxx->dev, "%s: Read 0x%02x from 0x%x\n",
+			__func__, val, reg);
+
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	if (ret < 0)
+		return ret;
+	else
+		return val;
+}
+EXPORT_SYMBOL(wcd9xxx_interface_reg_read);
+
+/*
+ * wcd9xxx_interface_reg_write: Write slim interface registers
+ *
+ * @wcd9xxx: Pointer to wcd9xxx structure
+ * @reg: register adderss
+ * @val: value of the register to be written
+ *
+ * Returns 0 for success and negative error code in case of failure
+ */
+int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+		     u8 val)
+{
+	int ret;
+
+	mutex_lock(&wcd9xxx->io_lock);
+	ret = wcd9xxx->write_dev(wcd9xxx, reg, 1, (void *)&val, true);
+	dev_dbg(wcd9xxx->dev, "%s: Write %02x to 0x%x ret(%d)\n",
+		__func__, val, reg, ret);
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_interface_reg_write);
+
+static int wcd9xxx_slim_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,
+				int bytes, void *dest, bool interface)
+{
+	int ret;
+	struct slim_ele_access msg;
+	int slim_read_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
+
+	msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
+	msg.num_bytes = bytes;
+	msg.comp = NULL;
+
+	if (!wcd9xxx->dev_up) {
+		dev_dbg_ratelimited(
+			wcd9xxx->dev, "%s: No read allowed. dev_up = %d\n",
+			__func__, wcd9xxx->dev_up);
+		return 0;
+	}
+
+	while (1) {
+		mutex_lock(&wcd9xxx->xfer_lock);
+		ret = slim_request_val_element(interface ?
+			       wcd9xxx->slim_slave : wcd9xxx->slim,
+			       &msg, dest, bytes);
+		mutex_unlock(&wcd9xxx->xfer_lock);
+		if (likely(ret == 0) || (--slim_read_tries == 0))
+			break;
+		usleep_range(5000, 5100);
+	}
+
+	if (ret)
+		dev_err(wcd9xxx->dev, "%s: Error, Codec read failed (%d)\n",
+			__func__, ret);
+
+	return ret;
+}
+
+/*
+ * Interface specifies whether the write is to the interface or general
+ * registers.
+ */
+static int wcd9xxx_slim_write_device(struct wcd9xxx *wcd9xxx,
+		unsigned short reg, int bytes, void *src, bool interface)
+{
+	int ret;
+	struct slim_ele_access msg;
+	int slim_write_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
+
+	msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
+	msg.num_bytes = bytes;
+	msg.comp = NULL;
+
+	if (!wcd9xxx->dev_up) {
+		dev_dbg_ratelimited(
+			wcd9xxx->dev, "%s: No write allowed. dev_up = %d\n",
+			__func__, wcd9xxx->dev_up);
+		return 0;
+	}
+
+	while (1) {
+		mutex_lock(&wcd9xxx->xfer_lock);
+		ret = slim_change_val_element(interface ?
+			      wcd9xxx->slim_slave : wcd9xxx->slim,
+			      &msg, src, bytes);
+		mutex_unlock(&wcd9xxx->xfer_lock);
+		if (likely(ret == 0) || (--slim_write_tries == 0))
+			break;
+		usleep_range(5000, 5100);
+	}
+
+	if (ret)
+		pr_err("%s: Error, Codec write failed (%d)\n", __func__, ret);
+
+	return ret;
+}
+
+static int wcd9xxx_slim_get_allowed_slice(struct wcd9xxx *wcd9xxx,
+					  int bytes)
+{
+	int allowed_sz = bytes;
+
+	if (likely(bytes == SLIM_REPEAT_WRITE_MAX_SLICE))
+		allowed_sz = 16;
+	else if (bytes >= 12)
+		allowed_sz = 12;
+	else if (bytes >= 8)
+		allowed_sz = 8;
+	else if (bytes >= 6)
+		allowed_sz = 6;
+	else if (bytes >= 4)
+		allowed_sz = 4;
+	else
+		allowed_sz = bytes;
+
+	return allowed_sz;
+}
+
+/*
+ * wcd9xxx_slim_write_repeat: Write the same register with multiple values
+ * @wcd9xxx: handle to wcd core
+ * @reg: register to be written
+ * @bytes: number of bytes to be written to reg
+ * @src: buffer with data content to be written to reg
+ * This API will write reg with bytes from src in a single slimbus
+ * transaction. All values from 1 to 16 are supported by this API.
+ */
+int wcd9xxx_slim_write_repeat(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			      int bytes, void *src)
+{
+	int ret = 0, bytes_to_write = bytes, bytes_allowed;
+	struct slim_ele_access slim_msg;
+
+	mutex_lock(&wcd9xxx->io_lock);
+	if (wcd9xxx->type == WCD9335 || wcd9xxx->type == WCD934X) {
+		ret = wcd9xxx_page_write(wcd9xxx, &reg);
+		if (ret)
+			goto done;
+	}
+
+	slim_msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
+	slim_msg.comp = NULL;
+
+	if (unlikely(bytes > SLIM_REPEAT_WRITE_MAX_SLICE)) {
+		dev_err(wcd9xxx->dev, "%s: size %d not supported\n",
+			__func__, bytes);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (!wcd9xxx->dev_up) {
+		dev_dbg_ratelimited(
+			wcd9xxx->dev, "%s: No write allowed. dev_up = %d\n",
+			__func__, wcd9xxx->dev_up);
+		ret = 0;
+		goto done;
+	}
+
+	while (bytes_to_write > 0) {
+		bytes_allowed = wcd9xxx_slim_get_allowed_slice(wcd9xxx,
+				       bytes_to_write);
+
+		slim_msg.num_bytes = bytes_allowed;
+		mutex_lock(&wcd9xxx->xfer_lock);
+		ret = slim_user_msg(wcd9xxx->slim, wcd9xxx->slim->laddr,
+				    SLIM_MSG_MT_DEST_REFERRED_USER,
+				    SLIM_USR_MC_REPEAT_CHANGE_VALUE,
+				    &slim_msg, src, bytes_allowed);
+		mutex_unlock(&wcd9xxx->xfer_lock);
+
+		if (ret) {
+			dev_err(wcd9xxx->dev, "%s: failed, ret = %d\n",
+				__func__, ret);
+			break;
+		}
+
+		bytes_to_write = bytes_to_write - bytes_allowed;
+		src = ((u8 *)src) + bytes_allowed;
+	}
+
+done:
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_slim_write_repeat);
+
+/*
+ * wcd9xxx_slim_reserve_bw: API to reserve the slimbus bandwidth
+ * @wcd9xxx: Handle to the wcd9xxx core
+ * @bw_ops: value of the bandwidth that is requested
+ * @commit: Flag to indicate if bandwidth change is to be committed
+ *	    right away
+ */
+int wcd9xxx_slim_reserve_bw(struct wcd9xxx *wcd9xxx,
+		u32 bw_ops, bool commit)
+{
+	if (!wcd9xxx || !wcd9xxx->slim) {
+		pr_err("%s: Invalid handle to %s\n",
+			__func__,
+			(!wcd9xxx) ? "wcd9xxx" : "slim_device");
+		return -EINVAL;
+	}
+
+	return slim_reservemsg_bw(wcd9xxx->slim, bw_ops, commit);
+}
+EXPORT_SYMBOL(wcd9xxx_slim_reserve_bw);
+
+/*
+ * wcd9xxx_slim_bulk_write: API to write multiple registers with one descriptor
+ * @wcd9xxx: Handle to the wcd9xxx core
+ * @wcd9xxx_reg_val: structure holding register and values to be written
+ * @size: Indicates number of messages to be written with one descriptor
+ * @is_interface: Indicates whether the register is for slim interface or for
+ *	       general registers.
+ * @return: returns 0 if success or error information to the caller in case
+ *	    of failure.
+ */
+int wcd9xxx_slim_bulk_write(struct wcd9xxx *wcd9xxx,
+			    struct wcd9xxx_reg_val *bulk_reg,
+			    unsigned int size, bool is_interface)
+{
+	int ret, i;
+	struct slim_val_inf *msgs;
+	unsigned short reg;
+
+	if (!bulk_reg || !size || !wcd9xxx) {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!wcd9xxx->dev_up) {
+		dev_dbg_ratelimited(
+			wcd9xxx->dev, "%s: No write allowed. dev_up = %d\n",
+			__func__, wcd9xxx->dev_up);
+		return 0;
+	}
+
+	msgs = kzalloc(size * (sizeof(struct slim_val_inf)), GFP_KERNEL);
+	if (!msgs) {
+		ret = -ENOMEM;
+		goto mem_fail;
+	}
+
+	mutex_lock(&wcd9xxx->io_lock);
+	reg = bulk_reg->reg;
+	for (i = 0; i < size; i++) {
+		msgs[i].start_offset = WCD9XXX_REGISTER_START_OFFSET +
+					(bulk_reg->reg & 0xFF);
+		msgs[i].num_bytes = bulk_reg->bytes;
+		msgs[i].wbuf = bulk_reg->buf;
+		bulk_reg++;
+	}
+	ret = wcd9xxx_page_write(wcd9xxx, &reg);
+	if (ret) {
+		pr_err("%s: Page write error for reg: 0x%x\n",
+			__func__, reg);
+		goto err;
+	}
+
+	ret = slim_bulk_msg_write(is_interface ?
+				  wcd9xxx->slim_slave : wcd9xxx->slim,
+				  SLIM_MSG_MT_CORE,
+				  SLIM_MSG_MC_CHANGE_VALUE, msgs, size,
+				  NULL, NULL);
+	if (ret)
+		pr_err("%s: Error, Codec bulk write failed (%d)\n",
+			__func__, ret);
+	/* 100 usec sleep is needed as per HW requirement */
+	usleep_range(100, 110);
+err:
+	mutex_unlock(&wcd9xxx->io_lock);
+	kfree(msgs);
+mem_fail:
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_slim_bulk_write);
+
+static int wcd9xxx_num_irq_regs(const struct wcd9xxx *wcd9xxx)
+{
+	return (wcd9xxx->codec_type->num_irqs / 8) +
+		((wcd9xxx->codec_type->num_irqs % 8) ? 1 : 0);
+}
+
+static int wcd9xxx_regmap_init_cache(struct wcd9xxx *wcd9xxx)
+{
+	struct regmap_config *regmap_config;
+	int rc;
+
+	regmap_config = wcd9xxx_get_regmap_config(wcd9xxx->type);
+	if (!regmap_config) {
+		dev_err(wcd9xxx->dev, "regmap config is not defined\n");
+		return -EINVAL;
+	}
+
+	rc = regmap_reinit_cache(wcd9xxx->regmap, regmap_config);
+	if (rc != 0) {
+		dev_err(wcd9xxx->dev, "%s:Failed to reinit register cache: %d\n",
+			__func__, rc);
+	}
+
+	return rc;
+}
+
+static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
+{
+	int ret = 0, i;
+	struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
+	regmap_patch_fptr regmap_apply_patch = NULL;
+
+	mutex_init(&wcd9xxx->io_lock);
+	mutex_init(&wcd9xxx->xfer_lock);
+	mutex_init(&wcd9xxx->reset_lock);
+
+	ret = wcd9xxx_bringup(wcd9xxx->dev);
+	if (ret) {
+		ret = -EPROBE_DEFER;
+		goto err_bring_up;
+	}
+
+	wcd9xxx->codec_type = devm_kzalloc(wcd9xxx->dev,
+			sizeof(struct wcd9xxx_codec_type), GFP_KERNEL);
+	if (!wcd9xxx->codec_type) {
+		ret = -ENOMEM;
+		goto err_bring_up;
+	}
+	ret = wcd9xxx_get_codec_info(wcd9xxx->dev);
+	if (ret) {
+		ret = -EPROBE_DEFER;
+		goto fail_cdc_fill;
+	}
+	wcd9xxx->version = wcd9xxx->codec_type->version;
+	if (!wcd9xxx->codec_type->dev || !wcd9xxx->codec_type->size)
+		goto fail_cdc_fill;
+
+	core_res->parent = wcd9xxx;
+	core_res->dev = wcd9xxx->dev;
+	core_res->intr_table = wcd9xxx->codec_type->intr_tbl;
+	core_res->intr_table_size = wcd9xxx->codec_type->intr_tbl_size;
+
+	for (i = 0; i < WCD9XXX_INTR_REG_MAX; i++)
+		wcd9xxx->core_res.intr_reg[i] =
+			wcd9xxx->codec_type->intr_reg[i];
+
+	wcd9xxx_core_res_init(&wcd9xxx->core_res,
+			      wcd9xxx->codec_type->num_irqs,
+			      wcd9xxx_num_irq_regs(wcd9xxx),
+			      wcd9xxx->regmap);
+
+	if (wcd9xxx_core_irq_init(&wcd9xxx->core_res))
+		goto err;
+
+	ret = wcd9xxx_regmap_init_cache(wcd9xxx);
+	if (ret)
+		goto err_irq;
+
+	regmap_apply_patch = wcd9xxx_get_regmap_reg_patch(
+			wcd9xxx->type);
+	if (regmap_apply_patch) {
+		ret = regmap_apply_patch(wcd9xxx->regmap,
+				wcd9xxx->version);
+		if (ret)
+			dev_err(wcd9xxx->dev,
+					"Failed to register patch: %d\n", ret);
+	}
+
+	ret = mfd_add_devices(wcd9xxx->dev, -1, wcd9xxx->codec_type->dev,
+			      wcd9xxx->codec_type->size, NULL, 0, NULL);
+	if (ret != 0) {
+		dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
+		goto err_irq;
+	}
+
+	ret = device_init_wakeup(wcd9xxx->dev, true);
+	if (ret) {
+		dev_err(wcd9xxx->dev, "Device wakeup init failed: %d\n", ret);
+		goto err_irq;
+	}
+
+	return ret;
+err_irq:
+	wcd9xxx_irq_exit(&wcd9xxx->core_res);
+fail_cdc_fill:
+	devm_kfree(wcd9xxx->dev, wcd9xxx->codec_type);
+	wcd9xxx->codec_type = NULL;
+err:
+	wcd9xxx_bringdown(wcd9xxx->dev);
+	wcd9xxx_core_res_deinit(&wcd9xxx->core_res);
+err_bring_up:
+	mutex_destroy(&wcd9xxx->io_lock);
+	mutex_destroy(&wcd9xxx->xfer_lock);
+	mutex_destroy(&wcd9xxx->reset_lock);
+	return ret;
+}
+
+static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
+{
+	device_init_wakeup(wcd9xxx->dev, false);
+	wcd9xxx_irq_exit(&wcd9xxx->core_res);
+	wcd9xxx_bringdown(wcd9xxx->dev);
+	wcd9xxx_reset_low(wcd9xxx->dev);
+	wcd9xxx_core_res_deinit(&wcd9xxx->core_res);
+	mutex_destroy(&wcd9xxx->io_lock);
+	mutex_destroy(&wcd9xxx->xfer_lock);
+	mutex_destroy(&wcd9xxx->reset_lock);
+	if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		slim_remove_device(wcd9xxx->slim_slave);
+}
+
+
+#ifdef CONFIG_DEBUG_FS
+struct wcd9xxx *debugCodec;
+
+static struct dentry *debugfs_wcd9xxx_dent;
+static struct dentry *debugfs_peek;
+static struct dentry *debugfs_poke;
+static struct dentry *debugfs_power_state;
+static struct dentry *debugfs_reg_dump;
+
+static unsigned char read_data;
+
+static int codec_debug_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static int get_parameters(char *buf, long int *param1, int num_of_par)
+{
+	char *token;
+	int base, cnt;
+
+	token = strsep(&buf, " ");
+
+	for (cnt = 0; cnt < num_of_par; cnt++) {
+		if (token != NULL) {
+			if ((token[1] == 'x') || (token[1] == 'X'))
+				base = 16;
+			else
+				base = 10;
+
+			if (kstrtoul(token, base, &param1[cnt]) != 0)
+				return -EINVAL;
+
+			token = strsep(&buf, " ");
+		} else
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static ssize_t wcd9xxx_slimslave_reg_show(char __user *ubuf, size_t count,
+					  loff_t *ppos)
+{
+	int i, reg_val, len;
+	ssize_t total = 0;
+	char tmp_buf[25]; /* each line is 12 bytes but 25 for margin of error */
+
+	for (i = (int) *ppos / 12; i <= SLIM_MAX_REG_ADDR; i++) {
+		reg_val = wcd9xxx_interface_reg_read(debugCodec, i);
+		len = snprintf(tmp_buf, sizeof(tmp_buf),
+			"0x%.3x: 0x%.2x\n", i, reg_val);
+
+		if ((total + len) >= count - 1)
+			break;
+		if (copy_to_user((ubuf + total), tmp_buf, len)) {
+			pr_err("%s: fail to copy reg dump\n", __func__);
+			total = -EFAULT;
+			goto copy_err;
+		}
+		*ppos += len;
+		total += len;
+	}
+
+copy_err:
+	return total;
+}
+
+static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	char lbuf[8];
+	char *access_str = file->private_data;
+	ssize_t ret_cnt;
+
+	if (*ppos < 0 || !count)
+		return -EINVAL;
+
+	if (!strcmp(access_str, "slimslave_peek")) {
+		snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
+		ret_cnt = simple_read_from_buffer(ubuf, count, ppos, lbuf,
+					       strnlen(lbuf, 7));
+	} else if (!strcmp(access_str, "slimslave_reg_dump")) {
+		ret_cnt = wcd9xxx_slimslave_reg_show(ubuf, count, ppos);
+	} else {
+		pr_err("%s: %s not permitted to read\n", __func__, access_str);
+		ret_cnt = -EPERM;
+	}
+
+	return ret_cnt;
+}
+
+static void wcd9xxx_set_reset_pin_state(struct wcd9xxx *wcd9xxx,
+					struct wcd9xxx_pdata *pdata,
+					bool active)
+{
+	if (wcd9xxx->wcd_rst_np) {
+		if (active)
+			msm_cdc_pinctrl_select_active_state(
+						wcd9xxx->wcd_rst_np);
+		else
+			msm_cdc_pinctrl_select_sleep_state(
+						wcd9xxx->wcd_rst_np);
+
+		return;
+	} else if (gpio_is_valid(wcd9xxx->reset_gpio)) {
+		gpio_direction_output(wcd9xxx->reset_gpio,
+				      (active == true ? 1 : 0));
+	}
+}
+
+static int codec_debug_process_cdc_power(char *lbuf)
+{
+	long int param;
+	int rc;
+	struct wcd9xxx_pdata *pdata;
+
+	if (wcd9xxx_get_intf_type() != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+		pr_err("%s: CODEC is not in SLIMBUS mode\n", __func__);
+		rc = -EPERM;
+		goto error_intf;
+	}
+
+	rc = get_parameters(lbuf, &param, 1);
+
+	if (likely(!rc)) {
+		pdata = debugCodec->slim->dev.platform_data;
+		if (param == 0) {
+			wcd9xxx_slim_device_down(debugCodec->slim);
+			msm_cdc_disable_static_supplies(debugCodec->dev,
+							debugCodec->supplies,
+							pdata->regulator,
+							pdata->num_supplies);
+			wcd9xxx_set_reset_pin_state(debugCodec, pdata, false);
+		} else if (param == 1) {
+			msm_cdc_enable_static_supplies(debugCodec->dev,
+						       debugCodec->supplies,
+						       pdata->regulator,
+						       pdata->num_supplies);
+			usleep_range(1000, 2000);
+			wcd9xxx_set_reset_pin_state(debugCodec, pdata, false);
+			usleep_range(1000, 2000);
+			wcd9xxx_set_reset_pin_state(debugCodec, pdata, true);
+			usleep_range(1000, 2000);
+			wcd9xxx_slim_device_up(debugCodec->slim);
+		} else {
+			pr_err("%s: invalid command %ld\n", __func__, param);
+		}
+	}
+
+error_intf:
+	return rc;
+}
+
+static ssize_t codec_debug_write(struct file *filp,
+	const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	char *access_str = filp->private_data;
+	char lbuf[32];
+	int rc;
+	long int param[5];
+
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+
+	lbuf[cnt] = '\0';
+
+	if (!strcmp(access_str, "slimslave_poke")) {
+		/* write */
+		rc = get_parameters(lbuf, param, 2);
+		if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
+			(rc == 0))
+			wcd9xxx_interface_reg_write(debugCodec, param[0],
+				param[1]);
+		else
+			rc = -EINVAL;
+	} else if (!strcmp(access_str, "slimslave_peek")) {
+		/* read */
+		rc = get_parameters(lbuf, param, 1);
+		if ((param[0] <= 0x3FF) && (rc == 0))
+			read_data = wcd9xxx_interface_reg_read(debugCodec,
+				param[0]);
+		else
+			rc = -EINVAL;
+	} else if (!strcmp(access_str, "power_state")) {
+		rc = codec_debug_process_cdc_power(lbuf);
+	}
+
+	if (rc == 0)
+		rc = cnt;
+	else
+		pr_err("%s: rc = %d\n", __func__, rc);
+
+	return rc;
+}
+
+static const struct file_operations codec_debug_ops = {
+	.open = codec_debug_open,
+	.write = codec_debug_write,
+	.read = codec_debug_read
+};
+#endif
+
+static struct wcd9xxx_i2c *wcd9xxx_i2c_get_device_info(struct wcd9xxx *wcd9xxx,
+						u16 reg)
+{
+	u16 mask = 0x0f00;
+	int value = 0;
+	struct wcd9xxx_i2c *wcd9xxx_i2c = NULL;
+
+	if (wcd9xxx->type == WCD9335) {
+		wcd9xxx_i2c = &wcd9xxx_modules[0];
+	} else {
+		value = ((reg & mask) >> 8) & 0x000f;
+		switch (value) {
+		case 0:
+			wcd9xxx_i2c = &wcd9xxx_modules[0];
+			break;
+		case 1:
+			wcd9xxx_i2c = &wcd9xxx_modules[1];
+			break;
+		case 2:
+			wcd9xxx_i2c = &wcd9xxx_modules[2];
+			break;
+		case 3:
+			wcd9xxx_i2c = &wcd9xxx_modules[3];
+			break;
+
+		default:
+			break;
+		}
+	}
+	return wcd9xxx_i2c;
+}
+
+static int wcd9xxx_i2c_write_device(struct wcd9xxx *wcd9xxx, u16 reg, u8 *value,
+				u32 bytes)
+{
+
+	struct i2c_msg *msg;
+	int ret = 0;
+	u8 reg_addr = 0;
+	u8 data[bytes + 1];
+	struct wcd9xxx_i2c *wcd9xxx_i2c;
+
+	wcd9xxx_i2c = wcd9xxx_i2c_get_device_info(wcd9xxx, reg);
+	if (wcd9xxx_i2c == NULL || wcd9xxx_i2c->client == NULL) {
+		pr_err("failed to get device info\n");
+		return -ENODEV;
+	}
+	reg_addr = (u8)reg;
+	msg = &wcd9xxx_i2c->xfer_msg[0];
+	msg->addr = wcd9xxx_i2c->client->addr;
+	msg->len = bytes + 1;
+	msg->flags = 0;
+	data[0] = reg;
+	data[1] = *value;
+	msg->buf = data;
+	ret = i2c_transfer(wcd9xxx_i2c->client->adapter,
+			   wcd9xxx_i2c->xfer_msg, 1);
+	/* Try again if the write fails */
+	if (ret != 1) {
+		ret = i2c_transfer(wcd9xxx_i2c->client->adapter,
+						wcd9xxx_i2c->xfer_msg, 1);
+		if (ret != 1) {
+			pr_err("failed to write the device\n");
+			return ret;
+		}
+	}
+	pr_debug("write success register = %x val = %x\n", reg, data[1]);
+	return 0;
+}
+
+
+static int wcd9xxx_i2c_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,
+				  int bytes, unsigned char *dest)
+{
+	struct i2c_msg *msg;
+	int ret = 0;
+	u8 reg_addr = 0;
+	struct wcd9xxx_i2c *wcd9xxx_i2c;
+	u8 i = 0;
+
+	wcd9xxx_i2c = wcd9xxx_i2c_get_device_info(wcd9xxx, reg);
+	if (wcd9xxx_i2c == NULL || wcd9xxx_i2c->client == NULL) {
+		pr_err("failed to get device info\n");
+		return -ENODEV;
+	}
+	for (i = 0; i < bytes; i++) {
+		reg_addr = (u8)reg++;
+		msg = &wcd9xxx_i2c->xfer_msg[0];
+		msg->addr = wcd9xxx_i2c->client->addr;
+		msg->len = 1;
+		msg->flags = 0;
+		msg->buf = &reg_addr;
+
+		msg = &wcd9xxx_i2c->xfer_msg[1];
+		msg->addr = wcd9xxx_i2c->client->addr;
+		msg->len = 1;
+		msg->flags = I2C_M_RD;
+		msg->buf = dest++;
+		ret = i2c_transfer(wcd9xxx_i2c->client->adapter,
+				wcd9xxx_i2c->xfer_msg, 2);
+
+		/* Try again if read fails first time */
+		if (ret != 2) {
+			ret = i2c_transfer(wcd9xxx_i2c->client->adapter,
+					   wcd9xxx_i2c->xfer_msg, 2);
+			if (ret != 2) {
+				pr_err("failed to read wcd9xxx register\n");
+				return ret;
+			}
+		}
+	}
+	return 0;
+}
+
+int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			int bytes, void *dest, bool interface_reg)
+{
+	return wcd9xxx_i2c_read_device(wcd9xxx, reg, bytes, dest);
+}
+
+int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			 int bytes, void *src, bool interface_reg)
+{
+	return wcd9xxx_i2c_write_device(wcd9xxx, reg, src, bytes);
+}
+
+static int wcd9xxx_i2c_get_client_index(struct i2c_client *client,
+					int *wcd9xx_index)
+{
+	int ret = 0;
+
+	switch (client->addr) {
+	case WCD9XXX_I2C_TOP_SLAVE_ADDR:
+		*wcd9xx_index = WCD9XXX_I2C_TOP_LEVEL;
+	break;
+	case WCD9XXX_ANALOG_I2C_SLAVE_ADDR:
+		*wcd9xx_index = WCD9XXX_I2C_ANALOG;
+	break;
+	case WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR:
+		*wcd9xx_index = WCD9XXX_I2C_DIGITAL_1;
+	break;
+	case WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR:
+		*wcd9xx_index = WCD9XXX_I2C_DIGITAL_2;
+	break;
+	default:
+		ret = -EINVAL;
+	break;
+	}
+	return ret;
+}
+
+static int wcd9xxx_i2c_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct wcd9xxx *wcd9xxx = NULL;
+	struct wcd9xxx_pdata *pdata = NULL;
+	int val = 0;
+	int ret = 0;
+	int wcd9xx_index = 0;
+	struct device *dev;
+	int intf_type;
+	const struct of_device_id *of_id;
+
+	intf_type = wcd9xxx_get_intf_type();
+
+	pr_debug("%s: interface status %d\n", __func__, intf_type);
+	if (intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+		dev_dbg(&client->dev, "%s:Codec is detected in slimbus mode\n",
+			__func__);
+		return -ENODEV;
+	} else if (intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+		ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
+		if (ret != 0)
+			dev_err(&client->dev, "%s: I2C set codec I2C\n"
+				"client failed\n", __func__);
+		else {
+			dev_err(&client->dev, "%s:probe for other slaves\n"
+				"devices of codec I2C slave Addr = %x\n",
+				__func__, client->addr);
+			wcd9xxx_modules[wcd9xx_index].client = client;
+		}
+		return ret;
+	} else if (intf_type == WCD9XXX_INTERFACE_TYPE_PROBING) {
+		dev = &client->dev;
+		if (client->dev.of_node) {
+			dev_dbg(&client->dev, "%s:Platform data\n"
+				"from device tree\n", __func__);
+			pdata = wcd9xxx_populate_dt_data(&client->dev);
+			if (!pdata) {
+				dev_err(&client->dev,
+					"%s: Fail to obtain pdata from device tree\n",
+					__func__);
+				ret = -EINVAL;
+				goto fail;
+			}
+			client->dev.platform_data = pdata;
+		} else {
+			dev_dbg(&client->dev, "%s:Platform data from\n"
+				"board file\n", __func__);
+			pdata = client->dev.platform_data;
+		}
+		wcd9xxx = devm_kzalloc(&client->dev, sizeof(struct wcd9xxx),
+				       GFP_KERNEL);
+		if (!wcd9xxx) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		if (!pdata) {
+			dev_dbg(&client->dev, "no platform data?\n");
+			ret = -EINVAL;
+			goto fail;
+		}
+		wcd9xxx->type = WCD9XXX;
+		if (client->dev.of_node) {
+			of_id = of_match_device(wcd9xxx_of_match, &client->dev);
+			if (of_id) {
+				wcd9xxx->type = *((int *)of_id->data);
+				dev_info(&client->dev, "%s: codec type is %d\n",
+					 __func__, wcd9xxx->type);
+			}
+		} else {
+			dev_info(&client->dev, "%s: dev.of_node is NULL, default to WCD9XXX\n",
+				 __func__);
+			wcd9xxx->type = WCD9XXX;
+		}
+		wcd9xxx->regmap = wcd9xxx_regmap_init(&client->dev,
+				&wcd9xxx_i2c_base_regmap_config);
+		if (IS_ERR(wcd9xxx->regmap)) {
+			ret = PTR_ERR(wcd9xxx->regmap);
+			dev_err(&client->dev, "%s: Failed to allocate register map: %d\n",
+					__func__, ret);
+			goto err_codec;
+		}
+		wcd9xxx->reset_gpio = pdata->reset_gpio;
+		wcd9xxx->wcd_rst_np = pdata->wcd_rst_np;
+
+		if (!wcd9xxx->wcd_rst_np) {
+			pdata->use_pinctrl = false;
+			dev_err(&client->dev, "%s: pinctrl not used for rst_n\n",
+				__func__);
+			goto err_codec;
+		}
+
+		if (i2c_check_functionality(client->adapter,
+					    I2C_FUNC_I2C) == 0) {
+			dev_dbg(&client->dev, "can't talk I2C?\n");
+			ret = -EIO;
+			goto fail;
+		}
+		dev_set_drvdata(&client->dev, wcd9xxx);
+		wcd9xxx->dev = &client->dev;
+		wcd9xxx->dev_up = true;
+		if (client->dev.of_node)
+			wcd9xxx->mclk_rate = pdata->mclk_rate;
+
+		wcd9xxx->num_of_supplies = pdata->num_supplies;
+		ret = msm_cdc_init_supplies(wcd9xxx->dev, &wcd9xxx->supplies,
+					    pdata->regulator,
+					    pdata->num_supplies);
+		if (!wcd9xxx->supplies) {
+			dev_err(wcd9xxx->dev, "%s: Cannot init wcd supplies\n",
+				__func__);
+			goto err_codec;
+		}
+		ret = msm_cdc_enable_static_supplies(wcd9xxx->dev,
+						     wcd9xxx->supplies,
+						     pdata->regulator,
+						     pdata->num_supplies);
+		if (ret) {
+			dev_err(wcd9xxx->dev, "%s: wcd static supply enable failed!\n",
+				__func__);
+			goto err_codec;
+		}
+		/* For WCD9335, it takes about 600us for the Vout_A and
+		 * Vout_D to be ready after BUCK_SIDO is powered up\
+		 * SYS_RST_N shouldn't be pulled high during this time
+		 */
+		if (wcd9xxx->type == WCD9335)
+			usleep_range(600, 650);
+		else
+			usleep_range(5, 10);
+
+		ret = wcd9xxx_reset(wcd9xxx->dev);
+		if (ret) {
+			pr_err("%s: Resetting Codec failed\n", __func__);
+			goto err_supplies;
+		}
+
+		ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
+		if (ret != 0) {
+			pr_err("%s:Set codec I2C client failed\n", __func__);
+			goto err_supplies;
+		}
+
+		wcd9xxx_modules[wcd9xx_index].client = client;
+		wcd9xxx->read_dev = wcd9xxx_i2c_read;
+		wcd9xxx->write_dev = wcd9xxx_i2c_write;
+		if (!wcd9xxx->dev->of_node)
+			wcd9xxx_assign_irq(&wcd9xxx->core_res,
+					pdata->irq, pdata->irq_base);
+
+		ret = wcd9xxx_device_init(wcd9xxx);
+		if (ret) {
+			pr_err("%s: error, initializing device failed (%d)\n",
+			       __func__, ret);
+			goto err_device_init;
+		}
+
+		ret = wcd9xxx_i2c_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1,
+				       &val, 0);
+		if (ret < 0)
+			pr_err("%s: failed to read the wcd9xxx status (%d)\n",
+			       __func__, ret);
+		if (val != wcd9xxx->codec_type->i2c_chip_status)
+			pr_err("%s: unknown chip status 0x%x\n", __func__, val);
+
+		wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_I2C);
+
+		return ret;
+	}
+
+	pr_err("%s: I2C probe in wrong state\n", __func__);
+
+
+err_device_init:
+	wcd9xxx_reset_low(wcd9xxx->dev);
+err_supplies:
+	msm_cdc_release_supplies(wcd9xxx->dev, wcd9xxx->supplies,
+				 pdata->regulator,
+				 pdata->num_supplies);
+	pdata->regulator = NULL;
+	pdata->num_supplies = 0;
+err_codec:
+	devm_kfree(&client->dev, wcd9xxx);
+	dev_set_drvdata(&client->dev, NULL);
+fail:
+	return ret;
+}
+
+static int wcd9xxx_i2c_remove(struct i2c_client *client)
+{
+	struct wcd9xxx *wcd9xxx;
+	struct wcd9xxx_pdata *pdata = client->dev.platform_data;
+
+	wcd9xxx = dev_get_drvdata(&client->dev);
+	msm_cdc_release_supplies(wcd9xxx->dev, wcd9xxx->supplies,
+				 pdata->regulator,
+				 pdata->num_supplies);
+	wcd9xxx_device_exit(wcd9xxx);
+	dev_set_drvdata(&client->dev, NULL);
+	return 0;
+}
+
+static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
+						struct slim_device *slim_ifd)
+{
+	int ret = 0;
+	struct property *prop;
+
+	ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
+				      &slim_ifd->name);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			"qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
+		return -ENODEV;
+	}
+	prop = of_find_property(dev->of_node,
+			"qcom,cdc-slim-ifd-elemental-addr", NULL);
+	if (!prop) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			"qcom,cdc-slim-ifd-elemental-addr",
+			dev->of_node->full_name);
+		return -ENODEV;
+	} else if (prop->length != 6) {
+		dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
+			      prop->length);
+		return -ENODEV;
+	}
+	memcpy(slim_ifd->e_addr, prop->value, 6);
+
+	return 0;
+}
+
+static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
+				  const u8 *e_addr, u8 e_len, u8 *laddr)
+{
+	int ret;
+	const unsigned long timeout = jiffies +
+				      msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
+
+	do {
+		ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
+		if (!ret)
+			break;
+		/* Give SLIMBUS time to report present and be ready. */
+		usleep_range(1000, 1100);
+		pr_debug_ratelimited("%s: retyring get logical addr\n",
+				     __func__);
+	} while time_before(jiffies, timeout);
+
+	return ret;
+}
+
+static int wcd9xxx_slim_probe(struct slim_device *slim)
+{
+	struct wcd9xxx *wcd9xxx;
+	struct wcd9xxx_pdata *pdata;
+	const struct slim_device_id *device_id;
+	int ret = 0;
+	int intf_type;
+
+	intf_type = wcd9xxx_get_intf_type();
+
+	wcd9xxx = devm_kzalloc(&slim->dev, sizeof(struct wcd9xxx),
+				GFP_KERNEL);
+	if (!wcd9xxx) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (!slim) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+		dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
+			__func__);
+		ret = -ENODEV;
+		goto err;
+	}
+	if (slim->dev.of_node) {
+		dev_info(&slim->dev, "Platform data from device tree\n");
+		pdata = wcd9xxx_populate_dt_data(&slim->dev);
+		if (!pdata) {
+			dev_err(&slim->dev,
+				"%s: Fail to obtain pdata from device tree\n",
+				__func__);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		ret = wcd9xxx_dt_parse_slim_interface_dev_info(&slim->dev,
+				&pdata->slimbus_slave_device);
+		if (ret) {
+			dev_err(&slim->dev, "Error, parsing slim interface\n");
+			devm_kfree(&slim->dev, pdata);
+			ret = -EINVAL;
+			goto err;
+		}
+		slim->dev.platform_data = pdata;
+
+	} else {
+		dev_info(&slim->dev, "Platform data from board file\n");
+		pdata = slim->dev.platform_data;
+	}
+
+	if (!pdata) {
+		dev_err(&slim->dev, "Error, no platform data\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (!slim->ctrl) {
+		dev_err(&slim->dev, "%s: Error, no SLIMBUS control data\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_codec;
+	}
+	device_id = slim_get_device_id(slim);
+	if (!device_id) {
+		dev_err(&slim->dev, "%s: Error, no device id\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	wcd9xxx->type = device_id->driver_data;
+	dev_info(&slim->dev, "%s: probing for wcd type: %d, name: %s\n",
+		 __func__, wcd9xxx->type, device_id->name);
+
+	/* wcd9xxx members init */
+	wcd9xxx->multi_reg_write = wcd9xxx_slim_multi_reg_write;
+	wcd9xxx->slim = slim;
+	slim_set_clientdata(slim, wcd9xxx);
+	wcd9xxx->reset_gpio = pdata->reset_gpio;
+	wcd9xxx->dev = &slim->dev;
+	wcd9xxx->mclk_rate = pdata->mclk_rate;
+	wcd9xxx->dev_up = true;
+	wcd9xxx->wcd_rst_np = pdata->wcd_rst_np;
+
+	wcd9xxx->regmap = wcd9xxx_regmap_init(&slim->dev,
+					      &wcd9xxx_base_regmap_config);
+	if (IS_ERR(wcd9xxx->regmap)) {
+		ret = PTR_ERR(wcd9xxx->regmap);
+		dev_err(&slim->dev, "%s: Failed to allocate register map: %d\n",
+			__func__, ret);
+		goto err_codec;
+	}
+
+	if (!wcd9xxx->wcd_rst_np) {
+		pdata->use_pinctrl = false;
+		dev_err(&slim->dev, "%s: pinctrl not used for rst_n\n",
+			__func__);
+		goto err_codec;
+	}
+
+	wcd9xxx->num_of_supplies = pdata->num_supplies;
+	ret = msm_cdc_init_supplies(&slim->dev, &wcd9xxx->supplies,
+				    pdata->regulator,
+				    pdata->num_supplies);
+	if (!wcd9xxx->supplies) {
+		dev_err(wcd9xxx->dev, "%s: Cannot init wcd supplies\n",
+			__func__);
+		goto err_codec;
+	}
+	ret = msm_cdc_enable_static_supplies(wcd9xxx->dev,
+					     wcd9xxx->supplies,
+					     pdata->regulator,
+					     pdata->num_supplies);
+	if (ret) {
+		dev_err(wcd9xxx->dev, "%s: wcd static supply enable failed!\n",
+			__func__);
+		goto err_codec;
+	}
+
+	/*
+	 * For WCD9335, it takes about 600us for the Vout_A and
+	 * Vout_D to be ready after BUCK_SIDO is powered up.
+	 * SYS_RST_N shouldn't be pulled high during this time
+	 */
+	if (wcd9xxx->type == WCD9335 || wcd9xxx->type == WCD934X)
+		usleep_range(600, 650);
+	else
+		usleep_range(5, 10);
+
+	ret = wcd9xxx_reset(&slim->dev);
+	if (ret) {
+		dev_err(&slim->dev, "%s: Resetting Codec failed\n", __func__);
+		goto err_supplies;
+	}
+
+	ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
+				     ARRAY_SIZE(wcd9xxx->slim->e_addr),
+				     &wcd9xxx->slim->laddr);
+	if (ret) {
+		dev_err(&slim->dev, "%s: failed to get slimbus %s logical address: %d\n",
+		       __func__, wcd9xxx->slim->name, ret);
+		goto err_reset;
+	}
+	wcd9xxx->read_dev = wcd9xxx_slim_read_device;
+	wcd9xxx->write_dev = wcd9xxx_slim_write_device;
+	wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
+	wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
+	if (!wcd9xxx->dev->of_node)
+		wcd9xxx_assign_irq(&wcd9xxx->core_res,
+					pdata->irq, pdata->irq_base);
+
+	ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
+	if (ret) {
+		dev_err(&slim->dev, "%s: error, adding SLIMBUS device failed\n",
+			__func__);
+		goto err_reset;
+	}
+
+	ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
+				     wcd9xxx->slim_slave->e_addr,
+				     ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
+				     &wcd9xxx->slim_slave->laddr);
+	if (ret) {
+		dev_err(&slim->dev, "%s: failed to get slimbus %s logical address: %d\n",
+		       __func__, wcd9xxx->slim->name, ret);
+		goto err_slim_add;
+	}
+	wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
+	wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_SLIMBUS);
+
+	ret = wcd9xxx_device_init(wcd9xxx);
+	if (ret) {
+		dev_err(&slim->dev, "%s: error, initializing device failed (%d)\n",
+			__func__, ret);
+		goto err_slim_add;
+	}
+#ifdef CONFIG_DEBUG_FS
+	debugCodec = wcd9xxx;
+
+	debugfs_wcd9xxx_dent = debugfs_create_dir
+		("wcd9xxx_core", 0);
+	if (!IS_ERR(debugfs_wcd9xxx_dent)) {
+		debugfs_peek = debugfs_create_file("slimslave_peek",
+		S_IFREG | 0444, debugfs_wcd9xxx_dent,
+		(void *) "slimslave_peek", &codec_debug_ops);
+
+		debugfs_poke = debugfs_create_file("slimslave_poke",
+		S_IFREG | 0444, debugfs_wcd9xxx_dent,
+		(void *) "slimslave_poke", &codec_debug_ops);
+
+		debugfs_power_state = debugfs_create_file("power_state",
+		S_IFREG | 0444, debugfs_wcd9xxx_dent,
+		(void *) "power_state", &codec_debug_ops);
+
+		debugfs_reg_dump = debugfs_create_file("slimslave_reg_dump",
+		S_IFREG | 0444, debugfs_wcd9xxx_dent,
+		(void *) "slimslave_reg_dump", &codec_debug_ops);
+	}
+#endif
+
+	return ret;
+
+err_slim_add:
+	slim_remove_device(wcd9xxx->slim_slave);
+err_reset:
+	wcd9xxx_reset_low(wcd9xxx->dev);
+err_supplies:
+	msm_cdc_release_supplies(wcd9xxx->dev, wcd9xxx->supplies,
+				 pdata->regulator,
+				 pdata->num_supplies);
+err_codec:
+	slim_set_clientdata(slim, NULL);
+err:
+	devm_kfree(&slim->dev, wcd9xxx);
+	return ret;
+}
+static int wcd9xxx_slim_remove(struct slim_device *pdev)
+{
+	struct wcd9xxx *wcd9xxx;
+	struct wcd9xxx_pdata *pdata = pdev->dev.platform_data;
+
+#ifdef CONFIG_DEBUG_FS
+	debugfs_remove_recursive(debugfs_wcd9xxx_dent);
+#endif
+	wcd9xxx = slim_get_devicedata(pdev);
+	wcd9xxx_deinit_slimslave(wcd9xxx);
+	slim_remove_device(wcd9xxx->slim_slave);
+	msm_cdc_release_supplies(wcd9xxx->dev, wcd9xxx->supplies,
+				 pdata->regulator,
+				 pdata->num_supplies);
+	wcd9xxx_device_exit(wcd9xxx);
+	slim_set_clientdata(pdev, NULL);
+	return 0;
+}
+
+static int wcd9xxx_device_up(struct wcd9xxx *wcd9xxx)
+{
+	int ret = 0;
+	struct wcd9xxx_core_resource *wcd9xxx_res = &wcd9xxx->core_res;
+
+	dev_info(wcd9xxx->dev, "%s: codec bring up\n", __func__);
+	wcd9xxx_bringup(wcd9xxx->dev);
+	ret = wcd9xxx_irq_init(wcd9xxx_res);
+	if (ret) {
+		pr_err("%s: wcd9xx_irq_init failed : %d\n", __func__, ret);
+	} else {
+		if (wcd9xxx->post_reset)
+			ret = wcd9xxx->post_reset(wcd9xxx);
+	}
+	return ret;
+}
+
+static int wcd9xxx_slim_device_reset(struct slim_device *sldev)
+{
+	int ret;
+	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+
+	if (!wcd9xxx) {
+		pr_err("%s: wcd9xxx is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_info(wcd9xxx->dev, "%s: device reset, dev_up = %d\n",
+		__func__, wcd9xxx->dev_up);
+	if (wcd9xxx->dev_up)
+		return 0;
+
+	mutex_lock(&wcd9xxx->reset_lock);
+	ret = wcd9xxx_reset(wcd9xxx->dev);
+	if (ret)
+		dev_err(wcd9xxx->dev, "%s: Resetting Codec failed\n", __func__);
+	mutex_unlock(&wcd9xxx->reset_lock);
+
+	return ret;
+}
+
+static int wcd9xxx_slim_device_up(struct slim_device *sldev)
+{
+	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+	int ret = 0;
+
+	if (!wcd9xxx) {
+		pr_err("%s: wcd9xxx is NULL\n", __func__);
+		return -EINVAL;
+	}
+	dev_info(wcd9xxx->dev, "%s: slim device up, dev_up = %d\n",
+		__func__, wcd9xxx->dev_up);
+	if (wcd9xxx->dev_up)
+		return 0;
+
+	wcd9xxx->dev_up = true;
+
+	mutex_lock(&wcd9xxx->reset_lock);
+	ret = wcd9xxx_device_up(wcd9xxx);
+	mutex_unlock(&wcd9xxx->reset_lock);
+
+	return ret;
+}
+
+static int wcd9xxx_slim_device_down(struct slim_device *sldev)
+{
+	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+
+	if (!wcd9xxx) {
+		pr_err("%s: wcd9xxx is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_info(wcd9xxx->dev, "%s: device down, dev_up = %d\n",
+		__func__, wcd9xxx->dev_up);
+	if (!wcd9xxx->dev_up)
+		return 0;
+
+	wcd9xxx->dev_up = false;
+
+	mutex_lock(&wcd9xxx->reset_lock);
+	if (wcd9xxx->dev_down)
+		wcd9xxx->dev_down(wcd9xxx);
+	wcd9xxx_irq_exit(&wcd9xxx->core_res);
+	wcd9xxx_reset_low(wcd9xxx->dev);
+	mutex_unlock(&wcd9xxx->reset_lock);
+
+	return 0;
+}
+
+static int wcd9xxx_slim_resume(struct slim_device *sldev)
+{
+	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+
+	return wcd9xxx_core_res_resume(&wcd9xxx->core_res);
+}
+
+static int wcd9xxx_i2c_resume(struct device *dev)
+{
+	struct wcd9xxx *wcd9xxx = dev_get_drvdata(dev);
+
+	if (wcd9xxx)
+		return wcd9xxx_core_res_resume(&wcd9xxx->core_res);
+	else
+		return 0;
+}
+
+static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
+{
+	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+
+	return wcd9xxx_core_res_suspend(&wcd9xxx->core_res, pmesg);
+}
+
+static int wcd9xxx_i2c_suspend(struct device *dev)
+{
+	struct wcd9xxx *wcd9xxx = dev_get_drvdata(dev);
+	pm_message_t pmesg = {0};
+
+	if (wcd9xxx)
+		return wcd9xxx_core_res_suspend(&wcd9xxx->core_res, pmesg);
+	else
+		return 0;
+}
+
+static const struct slim_device_id wcd_slim_device_id[] = {
+	{"sitar-slim", 0},
+	{"sitar1p1-slim", 0},
+	{"tabla-slim", 0},
+	{"tabla2x-slim", 0},
+	{"taiko-slim-pgd", 0},
+	{"tapan-slim-pgd", 0},
+	{"tomtom-slim-pgd", WCD9330},
+	{"tasha-slim-pgd", WCD9335},
+	{"tavil-slim-pgd", WCD934X},
+	{}
+};
+
+static struct slim_driver wcd_slim_driver = {
+	.driver = {
+		.name = "wcd-slim",
+		.owner = THIS_MODULE,
+	},
+	.probe = wcd9xxx_slim_probe,
+	.remove = wcd9xxx_slim_remove,
+	.id_table = wcd_slim_device_id,
+	.resume = wcd9xxx_slim_resume,
+	.suspend = wcd9xxx_slim_suspend,
+	.device_up = wcd9xxx_slim_device_up,
+	.reset_device = wcd9xxx_slim_device_reset,
+	.device_down = wcd9xxx_slim_device_down,
+};
+
+static struct i2c_device_id wcd9xxx_id_table[] = {
+	{"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
+	{"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
+	{"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_1},
+	{"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_2},
+	{}
+};
+
+static struct i2c_device_id tasha_id_table[] = {
+	{"tasha-i2c-pgd", WCD9XXX_I2C_TOP_LEVEL},
+	{}
+};
+
+static struct i2c_device_id tabla_id_table[] = {
+	{"tabla top level", WCD9XXX_I2C_TOP_LEVEL},
+	{"tabla analog", WCD9XXX_I2C_ANALOG},
+	{"tabla digital1", WCD9XXX_I2C_DIGITAL_1},
+	{"tabla digital2", WCD9XXX_I2C_DIGITAL_2},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, tabla_id_table);
+
+static const struct dev_pm_ops wcd9xxx_i2c_pm_ops = {
+	.suspend = wcd9xxx_i2c_suspend,
+	.resume	= wcd9xxx_i2c_resume,
+};
+
+static struct i2c_driver tabla_i2c_driver = {
+	.driver                 = {
+		.owner          =       THIS_MODULE,
+		.name           =       "tabla-i2c-core",
+		.pm		=	&wcd9xxx_i2c_pm_ops,
+	},
+	.id_table               =       tabla_id_table,
+	.probe                  =       wcd9xxx_i2c_probe,
+	.remove                 =       wcd9xxx_i2c_remove,
+};
+
+static struct i2c_driver wcd9xxx_i2c_driver = {
+	.driver                 = {
+		.owner          =       THIS_MODULE,
+		.name           =       "wcd9xxx-i2c-core",
+		.pm		=	&wcd9xxx_i2c_pm_ops,
+	},
+	.id_table               =       wcd9xxx_id_table,
+	.probe                  =       wcd9xxx_i2c_probe,
+	.remove                 =       wcd9xxx_i2c_remove,
+};
+
+static struct i2c_driver wcd9335_i2c_driver = {
+	.driver	                = {
+		.owner	        =       THIS_MODULE,
+		.name           =       "tasha-i2c-core",
+		.pm		=	&wcd9xxx_i2c_pm_ops,
+	},
+	.id_table               =       tasha_id_table,
+	.probe                  =       wcd9xxx_i2c_probe,
+	.remove                 =       wcd9xxx_i2c_remove,
+};
+
+int wcd9xxx_init(void)
+{
+	int ret[NUM_WCD9XXX_REG_RET] = {0};
+	int i = 0;
+
+	wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_PROBING);
+
+	ret[0] = i2c_add_driver(&tabla_i2c_driver);
+	if (ret[0])
+		pr_err("%s: Failed to add the tabla2x I2C driver: %d\n",
+			__func__, ret[0]);
+
+	ret[1] = i2c_add_driver(&wcd9xxx_i2c_driver);
+	if (ret[1])
+		pr_err("%s: Failed to add the wcd9xxx I2C driver: %d\n",
+			__func__, ret[1]);
+
+	ret[2] = i2c_add_driver(&wcd9335_i2c_driver);
+	if (ret[2])
+		pr_err("%s: Failed to add the wcd9335 I2C driver: %d\n",
+			__func__, ret[2]);
+
+	ret[3] = slim_driver_register(&wcd_slim_driver);
+	if (ret[3])
+		pr_err("%s: Failed to register wcd SB driver: %d\n",
+			__func__, ret[3]);
+
+	for (i = 0; i < NUM_WCD9XXX_REG_RET; i++) {
+		if (ret[i])
+			return ret[i];
+	}
+
+	return 0;
+}
+
+void wcd9xxx_exit(void)
+{
+	wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_PROBING);
+
+	i2c_del_driver(&tabla_i2c_driver);
+	i2c_del_driver(&wcd9xxx_i2c_driver);
+	i2c_del_driver(&wcd9335_i2c_driver);
+	slim_driver_unregister(&wcd_slim_driver);
+}
+
+MODULE_DESCRIPTION("Codec core driver");
+MODULE_LICENSE("GPL v2");

+ 853 - 0
drivers/mfd/wcd9xxx-irq.c

@@ -0,0 +1,853 @@
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/regmap.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-irq.h>
+#include <linux/delay.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/ratelimit.h>
+#include <soc/qcom/pm.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#define BYTE_BIT_MASK(nr)		(1UL << ((nr) % BITS_PER_BYTE))
+#define BIT_BYTE(nr)			((nr) / BITS_PER_BYTE)
+
+#define WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS 100
+
+#ifndef NO_IRQ
+#define NO_IRQ	(-1)
+#endif
+
+#ifdef CONFIG_OF
+struct wcd9xxx_irq_drv_data {
+	struct irq_domain *domain;
+	int irq;
+};
+#endif
+
+static int virq_to_phyirq(
+	struct wcd9xxx_core_resource *wcd9xxx_res, int virq);
+static int phyirq_to_virq(
+	struct wcd9xxx_core_resource *wcd9xxx_res, int irq);
+static unsigned int wcd9xxx_irq_get_upstream_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_res);
+static void wcd9xxx_irq_put_upstream_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_res);
+static int wcd9xxx_map_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_res, int irq);
+
+static void wcd9xxx_irq_lock(struct irq_data *data)
+{
+	struct wcd9xxx_core_resource *wcd9xxx_res =
+			irq_data_get_irq_chip_data(data);
+	mutex_lock(&wcd9xxx_res->irq_lock);
+}
+
+static void wcd9xxx_irq_sync_unlock(struct irq_data *data)
+{
+	struct wcd9xxx_core_resource *wcd9xxx_res =
+			irq_data_get_irq_chip_data(data);
+	int i;
+
+	if ((ARRAY_SIZE(wcd9xxx_res->irq_masks_cur) >
+	     WCD9XXX_MAX_IRQ_REGS) ||
+	     (ARRAY_SIZE(wcd9xxx_res->irq_masks_cache) >
+	      WCD9XXX_MAX_IRQ_REGS)) {
+		pr_err("%s: Array Size out of bound\n", __func__);
+		return;
+	}
+	if (!wcd9xxx_res->wcd_core_regmap) {
+		pr_err("%s: Codec core regmap not defined\n",
+			__func__);
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wcd9xxx_res->irq_masks_cur); i++) {
+		/* If there's been a change in the mask write it back
+		 * to the hardware.
+		 */
+		if (wcd9xxx_res->irq_masks_cur[i] !=
+					wcd9xxx_res->irq_masks_cache[i]) {
+
+			wcd9xxx_res->irq_masks_cache[i] =
+					wcd9xxx_res->irq_masks_cur[i];
+			regmap_write(wcd9xxx_res->wcd_core_regmap,
+			wcd9xxx_res->intr_reg[WCD9XXX_INTR_MASK_BASE] + i,
+			wcd9xxx_res->irq_masks_cur[i]);
+		}
+	}
+
+	mutex_unlock(&wcd9xxx_res->irq_lock);
+}
+
+static void wcd9xxx_irq_enable(struct irq_data *data)
+{
+	struct wcd9xxx_core_resource *wcd9xxx_res =
+			irq_data_get_irq_chip_data(data);
+	int wcd9xxx_irq = virq_to_phyirq(wcd9xxx_res, data->irq);
+	int byte = BIT_BYTE(wcd9xxx_irq);
+	int size = ARRAY_SIZE(wcd9xxx_res->irq_masks_cur);
+
+	if ((byte < size) && (byte >= 0)) {
+		wcd9xxx_res->irq_masks_cur[byte] &=
+			~(BYTE_BIT_MASK(wcd9xxx_irq));
+	} else {
+		pr_err("%s: Array size is %d but index is %d: Out of range\n",
+			__func__, size, byte);
+	}
+}
+
+static void wcd9xxx_irq_disable(struct irq_data *data)
+{
+	struct wcd9xxx_core_resource *wcd9xxx_res =
+			irq_data_get_irq_chip_data(data);
+	int wcd9xxx_irq = virq_to_phyirq(wcd9xxx_res, data->irq);
+	int byte = BIT_BYTE(wcd9xxx_irq);
+	int size = ARRAY_SIZE(wcd9xxx_res->irq_masks_cur);
+
+	if ((byte < size) && (byte >= 0)) {
+		wcd9xxx_res->irq_masks_cur[byte]
+			|= BYTE_BIT_MASK(wcd9xxx_irq);
+	} else {
+		pr_err("%s: Array size is %d but index is %d: Out of range\n",
+			__func__, size, byte);
+	}
+}
+
+static void wcd9xxx_irq_ack(struct irq_data *data)
+{
+	int wcd9xxx_irq = 0;
+	struct wcd9xxx_core_resource *wcd9xxx_res =
+			irq_data_get_irq_chip_data(data);
+
+	if (wcd9xxx_res == NULL) {
+		pr_err("%s: wcd9xxx_res is NULL\n", __func__);
+		return;
+	}
+	wcd9xxx_irq = virq_to_phyirq(wcd9xxx_res, data->irq);
+	pr_debug("%s: IRQ_ACK called for WCD9XXX IRQ: %d\n",
+				__func__, wcd9xxx_irq);
+}
+
+static void wcd9xxx_irq_mask(struct irq_data *d)
+{
+	/* do nothing but required as linux calls irq_mask without NULL check */
+}
+
+static struct irq_chip wcd9xxx_irq_chip = {
+	.name = "wcd9xxx",
+	.irq_bus_lock = wcd9xxx_irq_lock,
+	.irq_bus_sync_unlock = wcd9xxx_irq_sync_unlock,
+	.irq_disable = wcd9xxx_irq_disable,
+	.irq_enable = wcd9xxx_irq_enable,
+	.irq_mask = wcd9xxx_irq_mask,
+	.irq_ack = wcd9xxx_irq_ack,
+};
+
+bool wcd9xxx_lock_sleep(
+	struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	enum wcd9xxx_pm_state os;
+
+	/*
+	 * wcd9xxx_{lock/unlock}_sleep will be called by wcd9xxx_irq_thread
+	 * and its subroutines only motly.
+	 * but btn0_lpress_fn is not wcd9xxx_irq_thread's subroutine and
+	 * It can race with wcd9xxx_irq_thread.
+	 * So need to embrace wlock_holders with mutex.
+	 *
+	 * If system didn't resume, we can simply return false so codec driver's
+	 * IRQ handler can return without handling IRQ.
+	 * As interrupt line is still active, codec will have another IRQ to
+	 * retry shortly.
+	 */
+	mutex_lock(&wcd9xxx_res->pm_lock);
+	if (wcd9xxx_res->wlock_holders++ == 0) {
+		pr_debug("%s: holding wake lock\n", __func__);
+		pm_qos_update_request(&wcd9xxx_res->pm_qos_req,
+				      msm_cpuidle_get_deep_idle_latency());
+		pm_stay_awake(wcd9xxx_res->dev);
+	}
+	mutex_unlock(&wcd9xxx_res->pm_lock);
+
+	if (!wait_event_timeout(wcd9xxx_res->pm_wq,
+				((os =  wcd9xxx_pm_cmpxchg(wcd9xxx_res,
+						  WCD9XXX_PM_SLEEPABLE,
+						  WCD9XXX_PM_AWAKE)) ==
+							WCD9XXX_PM_SLEEPABLE ||
+					(os == WCD9XXX_PM_AWAKE)),
+				msecs_to_jiffies(
+					WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
+		pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
+			__func__,
+			WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, wcd9xxx_res->pm_state,
+			wcd9xxx_res->wlock_holders);
+		wcd9xxx_unlock_sleep(wcd9xxx_res);
+		return false;
+	}
+	wake_up_all(&wcd9xxx_res->pm_wq);
+	return true;
+}
+EXPORT_SYMBOL(wcd9xxx_lock_sleep);
+
+void wcd9xxx_unlock_sleep(
+	struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	mutex_lock(&wcd9xxx_res->pm_lock);
+	if (--wcd9xxx_res->wlock_holders == 0) {
+		pr_debug("%s: releasing wake lock pm_state %d -> %d\n",
+			 __func__, wcd9xxx_res->pm_state, WCD9XXX_PM_SLEEPABLE);
+		/*
+		 * if wcd9xxx_lock_sleep failed, pm_state would be still
+		 * WCD9XXX_PM_ASLEEP, don't overwrite
+		 */
+		if (likely(wcd9xxx_res->pm_state == WCD9XXX_PM_AWAKE))
+			wcd9xxx_res->pm_state = WCD9XXX_PM_SLEEPABLE;
+		pm_qos_update_request(&wcd9xxx_res->pm_qos_req,
+				PM_QOS_DEFAULT_VALUE);
+		pm_relax(wcd9xxx_res->dev);
+	}
+	mutex_unlock(&wcd9xxx_res->pm_lock);
+	wake_up_all(&wcd9xxx_res->pm_wq);
+}
+EXPORT_SYMBOL(wcd9xxx_unlock_sleep);
+
+void wcd9xxx_nested_irq_lock(struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	mutex_lock(&wcd9xxx_res->nested_irq_lock);
+}
+
+void wcd9xxx_nested_irq_unlock(struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	mutex_unlock(&wcd9xxx_res->nested_irq_lock);
+}
+
+
+static void wcd9xxx_irq_dispatch(struct wcd9xxx_core_resource *wcd9xxx_res,
+			struct intr_data *irqdata)
+{
+	int irqbit = irqdata->intr_num;
+
+	if (!wcd9xxx_res->wcd_core_regmap) {
+		pr_err("%s: codec core regmap not defined\n",
+			__func__);
+		return;
+	}
+
+	if (irqdata->clear_first) {
+		wcd9xxx_nested_irq_lock(wcd9xxx_res);
+		regmap_write(wcd9xxx_res->wcd_core_regmap,
+			wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLEAR_BASE] +
+					      BIT_BYTE(irqbit),
+			BYTE_BIT_MASK(irqbit));
+
+		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+			regmap_write(wcd9xxx_res->wcd_core_regmap,
+				wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLR_COMMIT],
+				0x02);
+		handle_nested_irq(phyirq_to_virq(wcd9xxx_res, irqbit));
+		wcd9xxx_nested_irq_unlock(wcd9xxx_res);
+	} else {
+		wcd9xxx_nested_irq_lock(wcd9xxx_res);
+		handle_nested_irq(phyirq_to_virq(wcd9xxx_res, irqbit));
+		regmap_write(wcd9xxx_res->wcd_core_regmap,
+			wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLEAR_BASE] +
+					      BIT_BYTE(irqbit),
+			BYTE_BIT_MASK(irqbit));
+		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+			regmap_write(wcd9xxx_res->wcd_core_regmap,
+				wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLR_COMMIT],
+				0x02);
+
+		wcd9xxx_nested_irq_unlock(wcd9xxx_res);
+	}
+}
+
+static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
+{
+	int ret;
+	int i;
+	struct intr_data irqdata;
+	char linebuf[128];
+	static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 1);
+	struct wcd9xxx_core_resource *wcd9xxx_res = data;
+	int num_irq_regs = wcd9xxx_res->num_irq_regs;
+	u8 status[4], status1[4] = {0}, unmask_status[4] = {0};
+
+	if (unlikely(wcd9xxx_lock_sleep(wcd9xxx_res) == false)) {
+		dev_err(wcd9xxx_res->dev, "Failed to hold suspend\n");
+		return IRQ_NONE;
+	}
+
+	if (!wcd9xxx_res->wcd_core_regmap) {
+		dev_err(wcd9xxx_res->dev,
+			"%s: Codec core regmap not supplied\n",
+			   __func__);
+		goto err_disable_irq;
+	}
+
+	memset(status, 0, sizeof(status));
+	ret = regmap_bulk_read(wcd9xxx_res->wcd_core_regmap,
+		wcd9xxx_res->intr_reg[WCD9XXX_INTR_STATUS_BASE],
+		status, num_irq_regs);
+
+	if (ret < 0) {
+		dev_err(wcd9xxx_res->dev,
+				"Failed to read interrupt status: %d\n", ret);
+		goto err_disable_irq;
+	}
+	/*
+	 * If status is 0 return without clearing.
+	 * status contains: HW status - masked interrupts
+	 * status1 contains: unhandled interrupts - masked interrupts
+	 * unmasked_status contains: unhandled interrupts
+	 */
+	if (unlikely(!memcmp(status, status1, sizeof(status)))) {
+		pr_debug("%s: status is 0\n", __func__);
+		wcd9xxx_unlock_sleep(wcd9xxx_res);
+		return IRQ_HANDLED;
+	}
+
+	/*
+	 * Copy status to unmask_status before masking, otherwise SW may miss
+	 * to clear masked interrupt in corner case.
+	 */
+	memcpy(unmask_status, status, sizeof(unmask_status));
+
+	/* Apply masking */
+	for (i = 0; i < num_irq_regs; i++)
+		status[i] &= ~wcd9xxx_res->irq_masks_cur[i];
+
+	memcpy(status1, status, sizeof(status1));
+
+	/* Find out which interrupt was triggered and call that interrupt's
+	 * handler function
+	 *
+	 * Since codec has only one hardware irq line which is shared by
+	 * codec's different internal interrupts, so it's possible master irq
+	 * handler dispatches multiple nested irq handlers after breaking
+	 * order.  Dispatch interrupts in the order that is maintained by
+	 * the interrupt table.
+	 */
+	for (i = 0; i < wcd9xxx_res->intr_table_size; i++) {
+		irqdata = wcd9xxx_res->intr_table[i];
+		if (status[BIT_BYTE(irqdata.intr_num)] &
+			BYTE_BIT_MASK(irqdata.intr_num)) {
+			wcd9xxx_irq_dispatch(wcd9xxx_res, &irqdata);
+			status1[BIT_BYTE(irqdata.intr_num)] &=
+					~BYTE_BIT_MASK(irqdata.intr_num);
+			unmask_status[BIT_BYTE(irqdata.intr_num)] &=
+					~BYTE_BIT_MASK(irqdata.intr_num);
+		}
+	}
+
+	/*
+	 * As a failsafe if unhandled irq is found, clear it to prevent
+	 * interrupt storm.
+	 * Note that we can say there was an unhandled irq only when no irq
+	 * handled by nested irq handler since Taiko supports qdsp as irqs'
+	 * destination for few irqs.  Therefore driver shouldn't clear pending
+	 * irqs when few handled while few others not.
+	 */
+	if (unlikely(!memcmp(status, status1, sizeof(status)))) {
+		if (__ratelimit(&ratelimit)) {
+			pr_warn("%s: Unhandled irq found\n", __func__);
+			hex_dump_to_buffer(status, sizeof(status), 16, 1,
+					   linebuf, sizeof(linebuf), false);
+			pr_warn("%s: status0 : %s\n", __func__, linebuf);
+			hex_dump_to_buffer(status1, sizeof(status1), 16, 1,
+					   linebuf, sizeof(linebuf), false);
+			pr_warn("%s: status1 : %s\n", __func__, linebuf);
+		}
+		/*
+		 * unmask_status contains unhandled interrupts, hence clear all
+		 * unhandled interrupts.
+		 */
+		ret = regmap_bulk_write(wcd9xxx_res->wcd_core_regmap,
+			wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLEAR_BASE],
+			unmask_status, num_irq_regs);
+		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+			regmap_write(wcd9xxx_res->wcd_core_regmap,
+				wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLR_COMMIT],
+				0x02);
+	}
+	wcd9xxx_unlock_sleep(wcd9xxx_res);
+
+	return IRQ_HANDLED;
+
+err_disable_irq:
+		dev_err(wcd9xxx_res->dev,
+				"Disable irq %d\n", wcd9xxx_res->irq);
+
+		disable_irq_wake(wcd9xxx_res->irq);
+		disable_irq_nosync(wcd9xxx_res->irq);
+		wcd9xxx_unlock_sleep(wcd9xxx_res);
+		return IRQ_NONE;
+}
+
+/**
+ * wcd9xxx_free_irq
+ *
+ * @wcd9xxx_res: pointer to core resource
+ * irq: irq number
+ * @data: data pointer
+ *
+ */
+void wcd9xxx_free_irq(struct wcd9xxx_core_resource *wcd9xxx_res,
+			int irq, void *data)
+{
+	free_irq(phyirq_to_virq(wcd9xxx_res, irq), data);
+}
+EXPORT_SYMBOL(wcd9xxx_free_irq);
+
+/**
+ * wcd9xxx_enable_irq
+ *
+ * @wcd9xxx_res: pointer to core resource
+ * irq: irq number
+ *
+ */
+void wcd9xxx_enable_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq)
+{
+	if (wcd9xxx_res->irq)
+		enable_irq(phyirq_to_virq(wcd9xxx_res, irq));
+}
+EXPORT_SYMBOL(wcd9xxx_enable_irq);
+
+/**
+ * wcd9xxx_disable_irq
+ *
+ * @wcd9xxx_res: pointer to core resource
+ * irq: irq number
+ *
+ */
+void wcd9xxx_disable_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq)
+{
+	if (wcd9xxx_res->irq)
+		disable_irq_nosync(phyirq_to_virq(wcd9xxx_res, irq));
+}
+EXPORT_SYMBOL(wcd9xxx_disable_irq);
+
+/**
+ * wcd9xxx_disable_irq_sync
+ *
+ * @wcd9xxx_res: pointer to core resource
+ * irq: irq number
+ *
+ */
+void wcd9xxx_disable_irq_sync(
+			struct wcd9xxx_core_resource *wcd9xxx_res, int irq)
+{
+	if (wcd9xxx_res->irq)
+		disable_irq(phyirq_to_virq(wcd9xxx_res, irq));
+}
+EXPORT_SYMBOL(wcd9xxx_disable_irq_sync);
+
+static int wcd9xxx_irq_setup_downstream_irq(
+			struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	int irq, virq, ret;
+
+	pr_debug("%s: enter\n", __func__);
+
+	for (irq = 0; irq < wcd9xxx_res->num_irqs; irq++) {
+		/* Map OF irq */
+		virq = wcd9xxx_map_irq(wcd9xxx_res, irq);
+		pr_debug("%s: irq %d -> %d\n", __func__, irq, virq);
+		if (virq == NO_IRQ) {
+			pr_err("%s, No interrupt specifier for irq %d\n",
+			       __func__, irq);
+			return NO_IRQ;
+		}
+
+		ret = irq_set_chip_data(virq, wcd9xxx_res);
+		if (ret) {
+			pr_err("%s: Failed to configure irq %d (%d)\n",
+			       __func__, irq, ret);
+			return ret;
+		}
+
+		if (wcd9xxx_res->irq_level_high[irq])
+			irq_set_chip_and_handler(virq, &wcd9xxx_irq_chip,
+						 handle_level_irq);
+		else
+			irq_set_chip_and_handler(virq, &wcd9xxx_irq_chip,
+						 handle_edge_irq);
+
+		irq_set_nested_thread(virq, 1);
+	}
+
+	pr_debug("%s: leave\n", __func__);
+
+	return 0;
+}
+
+/**
+ * wcd9xxx_irq_init
+ *
+ * @wcd9xxx_res: pointer to core resource
+ *
+ * Returns 0 on success, appropriate error code otherwise
+ */
+int wcd9xxx_irq_init(struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	int i, ret;
+	u8 irq_level[wcd9xxx_res->num_irq_regs];
+	struct irq_domain *domain;
+	struct device_node *pnode;
+
+	mutex_init(&wcd9xxx_res->irq_lock);
+	mutex_init(&wcd9xxx_res->nested_irq_lock);
+
+	pnode = of_irq_find_parent(wcd9xxx_res->dev->of_node);
+	if (unlikely(!pnode))
+		return -EINVAL;
+
+	domain = irq_find_host(pnode);
+	if (unlikely(!domain))
+		return -EINVAL;
+
+	wcd9xxx_res->domain = domain;
+
+	wcd9xxx_res->irq = wcd9xxx_irq_get_upstream_irq(wcd9xxx_res);
+	if (!wcd9xxx_res->irq) {
+		pr_warn("%s: irq driver is not yet initialized\n", __func__);
+		mutex_destroy(&wcd9xxx_res->irq_lock);
+		mutex_destroy(&wcd9xxx_res->nested_irq_lock);
+		return -EPROBE_DEFER;
+	}
+	pr_debug("%s: probed irq %d\n", __func__, wcd9xxx_res->irq);
+
+	/* Setup downstream IRQs */
+	ret = wcd9xxx_irq_setup_downstream_irq(wcd9xxx_res);
+	if (ret) {
+		pr_err("%s: Failed to setup downstream IRQ\n", __func__);
+		wcd9xxx_irq_put_upstream_irq(wcd9xxx_res);
+		mutex_destroy(&wcd9xxx_res->irq_lock);
+		mutex_destroy(&wcd9xxx_res->nested_irq_lock);
+		return ret;
+	}
+
+	/* All other wcd9xxx interrupts are edge triggered */
+	wcd9xxx_res->irq_level_high[0] = true;
+
+	/* mask all the interrupts */
+	memset(irq_level, 0, wcd9xxx_res->num_irq_regs);
+	for (i = 0; i < wcd9xxx_res->num_irqs; i++) {
+		wcd9xxx_res->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
+		wcd9xxx_res->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
+		irq_level[BIT_BYTE(i)] |=
+		    wcd9xxx_res->irq_level_high[i] << (i % BITS_PER_BYTE);
+	}
+
+	if (!wcd9xxx_res->wcd_core_regmap) {
+		dev_err(wcd9xxx_res->dev,
+			"%s: Codec core regmap not defined\n",
+			   __func__);
+		ret = -EINVAL;
+		goto fail_irq_init;
+	}
+
+	for (i = 0; i < wcd9xxx_res->num_irq_regs; i++) {
+		/* Initialize interrupt mask and level registers */
+		regmap_write(wcd9xxx_res->wcd_core_regmap,
+			wcd9xxx_res->intr_reg[WCD9XXX_INTR_LEVEL_BASE] + i,
+					irq_level[i]);
+		regmap_write(wcd9xxx_res->wcd_core_regmap,
+			wcd9xxx_res->intr_reg[WCD9XXX_INTR_MASK_BASE] + i,
+			wcd9xxx_res->irq_masks_cur[i]);
+	}
+
+	ret = request_threaded_irq(wcd9xxx_res->irq, NULL, wcd9xxx_irq_thread,
+				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   "wcd9xxx", wcd9xxx_res);
+	if (ret != 0)
+		dev_err(wcd9xxx_res->dev, "Failed to request IRQ %d: %d\n",
+			wcd9xxx_res->irq, ret);
+	else {
+		ret = enable_irq_wake(wcd9xxx_res->irq);
+		if (ret)
+			dev_err(wcd9xxx_res->dev,
+				"Failed to set wake interrupt on IRQ %d: %d\n",
+				wcd9xxx_res->irq, ret);
+		if (ret)
+			free_irq(wcd9xxx_res->irq, wcd9xxx_res);
+	}
+
+	if (ret)
+		goto fail_irq_init;
+
+	return ret;
+
+fail_irq_init:
+	dev_err(wcd9xxx_res->dev,
+			"%s: Failed to init wcd9xxx irq\n", __func__);
+	wcd9xxx_irq_put_upstream_irq(wcd9xxx_res);
+	mutex_destroy(&wcd9xxx_res->irq_lock);
+	mutex_destroy(&wcd9xxx_res->nested_irq_lock);
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_irq_init);
+
+int wcd9xxx_request_irq(struct wcd9xxx_core_resource *wcd9xxx_res,
+			int irq, irq_handler_t handler,
+			const char *name, void *data)
+{
+	int virq;
+
+	virq = phyirq_to_virq(wcd9xxx_res, irq);
+
+	return request_threaded_irq(virq, NULL, handler, IRQF_TRIGGER_RISING,
+				    name, data);
+}
+EXPORT_SYMBOL(wcd9xxx_request_irq);
+
+void wcd9xxx_irq_exit(struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	dev_dbg(wcd9xxx_res->dev, "%s: Cleaning up irq %d\n", __func__,
+		wcd9xxx_res->irq);
+
+	if (wcd9xxx_res->irq) {
+		disable_irq_wake(wcd9xxx_res->irq);
+		free_irq(wcd9xxx_res->irq, wcd9xxx_res);
+		wcd9xxx_res->irq = 0;
+		wcd9xxx_irq_put_upstream_irq(wcd9xxx_res);
+	}
+	mutex_destroy(&wcd9xxx_res->irq_lock);
+	mutex_destroy(&wcd9xxx_res->nested_irq_lock);
+}
+
+#ifndef CONFIG_OF
+static int phyirq_to_virq(
+	struct wcd9xxx_core_resource *wcd9xxx_res,
+	int offset)
+{
+	return wcd9xxx_res->irq_base + offset;
+}
+
+static int virq_to_phyirq(
+	struct wcd9xxx_core_resource *wcd9xxx_res,
+	int virq)
+{
+	return virq - wcd9xxx_res->irq_base;
+}
+
+static unsigned int wcd9xxx_irq_get_upstream_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	return wcd9xxx_res->irq;
+}
+
+static void wcd9xxx_irq_put_upstream_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	/* Do nothing */
+}
+
+static int wcd9xxx_map_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res, int irq)
+{
+	return phyirq_to_virq(wcd9xxx_core_res, irq);
+}
+#else
+static struct wcd9xxx_irq_drv_data *
+wcd9xxx_irq_add_domain(struct device_node *node,
+			       struct device_node *parent)
+{
+	struct wcd9xxx_irq_drv_data *data = NULL;
+
+	pr_debug("%s: node %s, node parent %s\n", __func__,
+		 node->name, node->parent->name);
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return NULL;
+
+	/*
+	 * wcd9xxx_intc interrupt controller supports N to N irq mapping with
+	 * single cell binding with irq numbers(offsets) only.
+	 * Use irq_domain_simple_ops that has irq_domain_simple_map and
+	 * irq_domain_xlate_onetwocell.
+	 */
+	data->domain = irq_domain_add_linear(node, WCD9XXX_MAX_NUM_IRQS,
+					     &irq_domain_simple_ops, data);
+	if (!data->domain) {
+		kfree(data);
+		return NULL;
+	}
+
+	return data;
+}
+
+static struct wcd9xxx_irq_drv_data *
+wcd9xxx_get_irq_drv_d(const struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	struct irq_domain *domain;
+
+	domain = wcd9xxx_res->domain;
+
+	if (domain)
+		return domain->host_data;
+	else
+		return NULL;
+}
+
+static int phyirq_to_virq(struct wcd9xxx_core_resource *wcd9xxx_res, int offset)
+{
+	struct wcd9xxx_irq_drv_data *data;
+
+	data = wcd9xxx_get_irq_drv_d(wcd9xxx_res);
+	if (!data) {
+		pr_warn("%s: not registered to interrupt controller\n",
+			__func__);
+		return -EINVAL;
+	}
+	return irq_linear_revmap(data->domain, offset);
+}
+
+static int virq_to_phyirq(struct wcd9xxx_core_resource *wcd9xxx_res, int virq)
+{
+	struct irq_data *irq_data = irq_get_irq_data(virq);
+
+	if (unlikely(!irq_data)) {
+		pr_err("%s: irq_data is NULL", __func__);
+		return -EINVAL;
+	}
+	return irq_data->hwirq;
+}
+
+static unsigned int wcd9xxx_irq_get_upstream_irq(
+				struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	struct wcd9xxx_irq_drv_data *data;
+
+	data = wcd9xxx_get_irq_drv_d(wcd9xxx_res);
+	if (!data) {
+		pr_err("%s: interrupt controller is not registered\n",
+			__func__);
+		return 0;
+	}
+
+	/* Make sure data is updated before return. */
+	rmb();
+	return data->irq;
+}
+
+static void wcd9xxx_irq_put_upstream_irq(
+			struct wcd9xxx_core_resource *wcd9xxx_res)
+{
+	wcd9xxx_res->domain = NULL;
+}
+
+static int wcd9xxx_map_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq)
+{
+	return of_irq_to_resource(wcd9xxx_res->dev->of_node, irq, NULL);
+}
+
+static int wcd9xxx_irq_probe(struct platform_device *pdev)
+{
+	int irq, dir_apps_irq = -EINVAL;
+	struct wcd9xxx_irq_drv_data *data;
+	struct device_node *node = pdev->dev.of_node;
+	int ret = -EINVAL;
+
+	irq = of_get_named_gpio(node, "qcom,gpio-connect", 0);
+	if (!gpio_is_valid(irq))
+		dir_apps_irq = platform_get_irq_byname(pdev, "wcd_irq");
+
+	if (!gpio_is_valid(irq) && dir_apps_irq < 0) {
+		dev_err(&pdev->dev, "TLMM connect gpio not found\n");
+		return -EPROBE_DEFER;
+	}
+	if (dir_apps_irq > 0) {
+		irq = dir_apps_irq;
+	} else {
+		irq = gpio_to_irq(irq);
+		if (irq < 0) {
+			dev_err(&pdev->dev, "Unable to configure irq\n");
+			return irq;
+		}
+	}
+	dev_dbg(&pdev->dev, "%s: virq = %d\n", __func__, irq);
+	data = wcd9xxx_irq_add_domain(node, node->parent);
+	if (!data) {
+		pr_err("%s: irq_add_domain failed\n", __func__);
+		return -EINVAL;
+	}
+	data->irq = irq;
+
+	/* Make sure irq is saved before return. */
+	wmb();
+	ret = 0;
+
+	return ret;
+}
+
+static int wcd9xxx_irq_remove(struct platform_device *pdev)
+{
+	struct irq_domain *domain;
+	struct wcd9xxx_irq_drv_data *data;
+
+	domain = irq_find_host(pdev->dev.of_node);
+	if (unlikely(!domain)) {
+		pr_err("%s: domain is NULL", __func__);
+		return -EINVAL;
+	}
+	data = (struct wcd9xxx_irq_drv_data *)domain->host_data;
+	data->irq = 0;
+
+	/* Make sure irq variable is updated in data, before irq removal. */
+	wmb();
+	irq_domain_remove(data->domain);
+	kfree(data);
+	domain->host_data = NULL;
+
+	return 0;
+}
+
+static const struct of_device_id of_match[] = {
+	{ .compatible = "qcom,wcd9xxx-irq" },
+	{ }
+};
+
+static struct platform_driver wcd9xxx_irq_driver = {
+	.probe = wcd9xxx_irq_probe,
+	.remove = wcd9xxx_irq_remove,
+	.driver = {
+		.name = "wcd9xxx_intc",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(of_match),
+	},
+};
+
+int wcd9xxx_irq_drv_init(void)
+{
+	return platform_driver_register(&wcd9xxx_irq_driver);
+}
+
+void wcd9xxx_irq_drv_exit(void)
+{
+	platform_driver_unregister(&wcd9xxx_irq_driver);
+}
+#endif /* CONFIG_OF */

+ 68 - 0
drivers/mfd/wcd9xxx-regmap.h

@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _WCD9XXX_REGMAP_
+#define _WCD9XXX_REGMAP_
+
+#include <linux/regmap.h>
+#include <linux/mfd/wcd9xxx/core.h>
+
+typedef int (*regmap_patch_fptr)(struct regmap *, int);
+
+extern struct regmap_config wcd934x_regmap_config;
+extern int wcd934x_regmap_register_patch(struct regmap *regmap,
+					 int version);
+
+extern struct regmap_config wcd9335_regmap_config;
+extern int wcd9335_regmap_register_patch(struct regmap *regmap,
+					 int version);
+
+static inline struct regmap_config *wcd9xxx_get_regmap_config(int type)
+{
+	struct regmap_config *regmap_config;
+
+	switch (type) {
+	case WCD934X:
+		regmap_config = &wcd934x_regmap_config;
+		break;
+	case WCD9335:
+		regmap_config = &wcd9335_regmap_config;
+		break;
+	default:
+		regmap_config = NULL;
+		break;
+	};
+
+	return regmap_config;
+}
+
+static inline regmap_patch_fptr wcd9xxx_get_regmap_reg_patch(int type)
+{
+	regmap_patch_fptr apply_patch;
+
+	switch (type) {
+	case WCD9335:
+		apply_patch = wcd9335_regmap_register_patch;
+		break;
+	case WCD934X:
+		apply_patch = wcd934x_regmap_register_patch;
+		break;
+	default:
+		apply_patch = NULL;
+		break;
+	}
+
+	return apply_patch;
+}
+
+#endif

+ 443 - 0
drivers/mfd/wcd9xxx-rst.c

@@ -0,0 +1,443 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/kernel.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-utils.h>
+#include <linux/mfd/wcd9335/registers.h>
+#include <linux/mfd/wcd934x/registers.h>
+#include <linux/mfd/wcd9335/irq.h>
+#include <linux/mfd/wcd934x/irq.h>
+
+/* wcd9335 interrupt table  */
+static const struct intr_data wcd9335_intr_table[] = {
+	{WCD9XXX_IRQ_SLIMBUS, false},
+	{WCD9335_IRQ_MBHC_SW_DET, true},
+	{WCD9335_IRQ_MBHC_BUTTON_PRESS_DET, true},
+	{WCD9335_IRQ_MBHC_BUTTON_RELEASE_DET, true},
+	{WCD9335_IRQ_MBHC_ELECT_INS_REM_DET, true},
+	{WCD9335_IRQ_MBHC_ELECT_INS_REM_LEG_DET, true},
+	{WCD9335_IRQ_FLL_LOCK_LOSS, false},
+	{WCD9335_IRQ_HPH_PA_CNPL_COMPLETE, false},
+	{WCD9335_IRQ_HPH_PA_CNPR_COMPLETE, false},
+	{WCD9335_IRQ_EAR_PA_CNP_COMPLETE, false},
+	{WCD9335_IRQ_LINE_PA1_CNP_COMPLETE, false},
+	{WCD9335_IRQ_LINE_PA2_CNP_COMPLETE, false},
+	{WCD9335_IRQ_LINE_PA3_CNP_COMPLETE, false},
+	{WCD9335_IRQ_LINE_PA4_CNP_COMPLETE, false},
+	{WCD9335_IRQ_HPH_PA_OCPL_FAULT, false},
+	{WCD9335_IRQ_HPH_PA_OCPR_FAULT, false},
+	{WCD9335_IRQ_EAR_PA_OCP_FAULT, false},
+	{WCD9335_IRQ_SOUNDWIRE, false},
+	{WCD9335_IRQ_VDD_DIG_RAMP_COMPLETE, false},
+	{WCD9335_IRQ_RCO_ERROR, false},
+	{WCD9335_IRQ_SVA_ERROR, false},
+	{WCD9335_IRQ_MAD_AUDIO, false},
+	{WCD9335_IRQ_MAD_BEACON, false},
+	{WCD9335_IRQ_SVA_OUTBOX1, true},
+	{WCD9335_IRQ_SVA_OUTBOX2, true},
+	{WCD9335_IRQ_MAD_ULTRASOUND, false},
+	{WCD9335_IRQ_VBAT_ATTACK, false},
+	{WCD9335_IRQ_VBAT_RESTORE, false},
+};
+
+static const struct intr_data wcd934x_intr_table[] = {
+	{WCD9XXX_IRQ_SLIMBUS, false},
+	{WCD934X_IRQ_MBHC_SW_DET, true},
+	{WCD934X_IRQ_MBHC_BUTTON_PRESS_DET, true},
+	{WCD934X_IRQ_MBHC_BUTTON_RELEASE_DET, true},
+	{WCD934X_IRQ_MBHC_ELECT_INS_REM_DET, true},
+	{WCD934X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, true},
+	{WCD934X_IRQ_MISC, false},
+	{WCD934X_IRQ_HPH_PA_CNPL_COMPLETE, false},
+	{WCD934X_IRQ_HPH_PA_CNPR_COMPLETE, false},
+	{WCD934X_IRQ_EAR_PA_CNP_COMPLETE, false},
+	{WCD934X_IRQ_LINE_PA1_CNP_COMPLETE, false},
+	{WCD934X_IRQ_LINE_PA2_CNP_COMPLETE, false},
+	{WCD934X_IRQ_SLNQ_ANALOG_ERROR, false},
+	{WCD934X_IRQ_RESERVED_3, false},
+	{WCD934X_IRQ_HPH_PA_OCPL_FAULT, false},
+	{WCD934X_IRQ_HPH_PA_OCPR_FAULT, false},
+	{WCD934X_IRQ_EAR_PA_OCP_FAULT, false},
+	{WCD934X_IRQ_SOUNDWIRE, false},
+	{WCD934X_IRQ_VDD_DIG_RAMP_COMPLETE, false},
+	{WCD934X_IRQ_RCO_ERROR, false},
+	{WCD934X_IRQ_CPE_ERROR, false},
+	{WCD934X_IRQ_MAD_AUDIO, false},
+	{WCD934X_IRQ_MAD_BEACON, false},
+	{WCD934X_IRQ_CPE1_INTR, true},
+	{WCD934X_IRQ_RESERVED_4, false},
+	{WCD934X_IRQ_MAD_ULTRASOUND, false},
+	{WCD934X_IRQ_VBAT_ATTACK, false},
+	{WCD934X_IRQ_VBAT_RESTORE, false},
+};
+
+/*
+ * wcd9335_bring_down: Bringdown WCD Codec
+ *
+ * @wcd9xxx: Pointer to wcd9xxx structure
+ *
+ * Returns 0 for success or negative error code for failure
+ */
+static int wcd9335_bring_down(struct wcd9xxx *wcd9xxx)
+{
+	if (!wcd9xxx || !wcd9xxx->regmap)
+		return -EINVAL;
+
+	regmap_write(wcd9xxx->regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
+		     0x04);
+
+	return 0;
+}
+
+/*
+ * wcd9335_bring_up: Bringup WCD Codec
+ *
+ * @wcd9xxx: Pointer to the wcd9xxx structure
+ *
+ * Returns 0 for success or negative error code for failure
+ */
+static int wcd9335_bring_up(struct wcd9xxx *wcd9xxx)
+{
+	int ret = 0;
+	int val, byte0;
+	struct regmap *wcd_regmap;
+
+	if (!wcd9xxx)
+		return -EINVAL;
+
+	if (!wcd9xxx->regmap) {
+		dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
+			__func__);
+		return -EINVAL;
+	}
+	wcd_regmap = wcd9xxx->regmap;
+
+	regmap_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT0, &val);
+	regmap_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0, &byte0);
+
+	if ((val < 0) || (byte0 < 0)) {
+		dev_err(wcd9xxx->dev, "%s: tasha codec version detection fail!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if ((val & 0x80) && (byte0 == 0x0)) {
+		dev_info(wcd9xxx->dev, "%s: wcd9335 codec version is v1.1\n",
+			 __func__);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x01);
+		regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_2, 0xFC);
+		regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_4, 0x21);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
+			     0x5);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
+			     0x7);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
+			     0x3);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x3);
+	} else if (byte0 == 0x1) {
+		dev_info(wcd9xxx->dev, "%s: wcd9335 codec version is v2.0\n",
+			 __func__);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x01);
+		regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_TEST_2, 0x00);
+		regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_8, 0x6F);
+		regmap_write(wcd_regmap, WCD9335_BIAS_VBG_FINE_ADJ, 0x65);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
+			     0x5);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
+			     0x7);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
+			     0x3);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x3);
+	} else if ((byte0 == 0) && (!(val & 0x80))) {
+		dev_info(wcd9xxx->dev, "%s: wcd9335 codec version is v1.0\n",
+			 __func__);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x01);
+		regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_2, 0xFC);
+		regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_4, 0x21);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
+			     0x3);
+		regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x3);
+	} else {
+		dev_err(wcd9xxx->dev, "%s: tasha codec version unknown\n",
+			__func__);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/*
+ * wcd9335_get_cdc_info: Get codec specific information
+ *
+ * @wcd9xxx: pointer to wcd9xxx structure
+ * @wcd_type: pointer to wcd9xxx_codec_type structure
+ *
+ * Returns 0 for success or negative error code for failure
+ */
+static int wcd9335_get_cdc_info(struct wcd9xxx *wcd9xxx,
+			   struct wcd9xxx_codec_type *wcd_type)
+{
+	u16 id_minor, id_major;
+	struct regmap *wcd_regmap;
+	int rc, val, version = 0;
+
+	if (!wcd9xxx || !wcd_type)
+		return -EINVAL;
+
+	if (!wcd9xxx->regmap) {
+		dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
+			__func__);
+		return -EINVAL;
+	}
+	wcd_regmap = wcd9xxx->regmap;
+
+	rc = regmap_bulk_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
+			(u8 *)&id_minor, sizeof(u16));
+	if (rc)
+		return -EINVAL;
+
+	rc = regmap_bulk_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE2,
+			      (u8 *)&id_major, sizeof(u16));
+	if (rc)
+		return -EINVAL;
+
+	dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
+		 __func__, id_major, id_minor);
+
+	/* Version detection */
+	if (id_major == TASHA_MAJOR) {
+		regmap_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT0,
+			    &val);
+		version = ((u8)val & 0x80) >> 7;
+	} else if (id_major == TASHA2P0_MAJOR)
+		version = 2;
+	else
+		dev_err(wcd9xxx->dev, "%s: wcd9335 version unknown (major 0x%x, minor 0x%x)\n",
+			__func__, id_major, id_minor);
+
+	/* Fill codec type info */
+	wcd_type->id_major = id_major;
+	wcd_type->id_minor = id_minor;
+	wcd_type->num_irqs = WCD9335_NUM_IRQS;
+	wcd_type->version = version;
+	wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1;
+	wcd_type->i2c_chip_status = 0x01;
+	wcd_type->intr_tbl = wcd9335_intr_table;
+	wcd_type->intr_tbl_size = ARRAY_SIZE(wcd9335_intr_table);
+
+	wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] =
+						WCD9335_INTR_PIN1_STATUS0;
+	wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] =
+						WCD9335_INTR_PIN1_CLEAR0;
+	wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] =
+						WCD9335_INTR_PIN1_MASK0;
+	wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] =
+						WCD9335_INTR_LEVEL0;
+	wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] =
+						WCD9335_INTR_CLR_COMMIT;
+
+	return rc;
+}
+
+/*
+ * wcd934x_bring_down: Bringdown WCD Codec
+ *
+ * @wcd9xxx: Pointer to wcd9xxx structure
+ *
+ * Returns 0 for success or negative error code for failure
+ */
+static int wcd934x_bring_down(struct wcd9xxx *wcd9xxx)
+{
+	if (!wcd9xxx || !wcd9xxx->regmap)
+		return -EINVAL;
+
+	regmap_write(wcd9xxx->regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
+		     0x04);
+
+	return 0;
+}
+
+/*
+ * wcd934x_bring_up: Bringup WCD Codec
+ *
+ * @wcd9xxx: Pointer to the wcd9xxx structure
+ *
+ * Returns 0 for success or negative error code for failure
+ */
+static int wcd934x_bring_up(struct wcd9xxx *wcd9xxx)
+{
+	struct regmap *wcd_regmap;
+
+	if (!wcd9xxx)
+		return -EINVAL;
+
+	if (!wcd9xxx->regmap) {
+		dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
+			__func__);
+		return -EINVAL;
+	}
+	wcd_regmap = wcd9xxx->regmap;
+
+	regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x01);
+	regmap_write(wcd_regmap, WCD934X_SIDO_NEW_VOUT_A_STARTUP, 0x19);
+	regmap_write(wcd_regmap, WCD934X_SIDO_NEW_VOUT_D_STARTUP, 0x15);
+	/* Add 1msec delay for VOUT to settle */
+	usleep_range(1000, 1100);
+	regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
+	regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7);
+	regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x3);
+	regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x7);
+	regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
+
+	return 0;
+}
+
+/*
+ * wcd934x_get_cdc_info: Get codec specific information
+ *
+ * @wcd9xxx: pointer to wcd9xxx structure
+ * @wcd_type: pointer to wcd9xxx_codec_type structure
+ *
+ * Returns 0 for success or negative error code for failure
+ */
+static int wcd934x_get_cdc_info(struct wcd9xxx *wcd9xxx,
+			   struct wcd9xxx_codec_type *wcd_type)
+{
+	u16 id_minor, id_major;
+	struct regmap *wcd_regmap;
+	int rc, version = -1;
+
+	if (!wcd9xxx || !wcd_type)
+		return -EINVAL;
+
+	if (!wcd9xxx->regmap) {
+		dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null\n", __func__);
+		return -EINVAL;
+	}
+	wcd_regmap = wcd9xxx->regmap;
+
+	rc = regmap_bulk_read(wcd_regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
+			      (u8 *)&id_minor, sizeof(u16));
+	if (rc)
+		return -EINVAL;
+
+	rc = regmap_bulk_read(wcd_regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2,
+			      (u8 *)&id_major, sizeof(u16));
+	if (rc)
+		return -EINVAL;
+
+	dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
+		 __func__, id_major, id_minor);
+
+	if (id_major != TAVIL_MAJOR)
+		goto version_unknown;
+
+	/*
+	 * As fine version info cannot be retrieved before tavil probe.
+	 * Assign coarse versions for possible future use before tavil probe.
+	 */
+	if (id_minor == cpu_to_le16(0))
+		version = TAVIL_VERSION_1_0;
+	else if (id_minor == cpu_to_le16(0x01))
+		version = TAVIL_VERSION_1_1;
+
+version_unknown:
+	if (version < 0)
+		dev_err(wcd9xxx->dev, "%s: wcd934x version unknown\n",
+			__func__);
+
+	/* Fill codec type info */
+	wcd_type->id_major = id_major;
+	wcd_type->id_minor = id_minor;
+	wcd_type->num_irqs = WCD934X_NUM_IRQS;
+	wcd_type->version = version;
+	wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1;
+	wcd_type->i2c_chip_status = 0x01;
+	wcd_type->intr_tbl = wcd934x_intr_table;
+	wcd_type->intr_tbl_size = ARRAY_SIZE(wcd934x_intr_table);
+
+	wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] =
+						WCD934X_INTR_PIN1_STATUS0;
+	wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] =
+						WCD934X_INTR_PIN1_CLEAR0;
+	wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] =
+						WCD934X_INTR_PIN1_MASK0;
+	wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] =
+						WCD934X_INTR_LEVEL0;
+	wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] =
+						WCD934X_INTR_CLR_COMMIT;
+
+	return rc;
+}
+
+codec_bringdown_fn wcd9xxx_bringdown_fn(int type)
+{
+	codec_bringdown_fn cdc_bdown_fn;
+
+	switch (type) {
+	case WCD934X:
+		cdc_bdown_fn = wcd934x_bring_down;
+		break;
+	case WCD9335:
+		cdc_bdown_fn = wcd9335_bring_down;
+		break;
+	default:
+		cdc_bdown_fn = NULL;
+		break;
+	}
+
+	return cdc_bdown_fn;
+}
+
+codec_bringup_fn wcd9xxx_bringup_fn(int type)
+{
+	codec_bringup_fn cdc_bup_fn;
+
+	switch (type) {
+	case WCD934X:
+		cdc_bup_fn = wcd934x_bring_up;
+		break;
+	case WCD9335:
+		cdc_bup_fn = wcd9335_bring_up;
+		break;
+	default:
+		cdc_bup_fn = NULL;
+		break;
+	}
+
+	return cdc_bup_fn;
+}
+
+codec_type_fn wcd9xxx_get_codec_info_fn(int type)
+{
+	codec_type_fn cdc_type_fn;
+
+	switch (type) {
+	case WCD934X:
+		cdc_type_fn = wcd934x_get_cdc_info;
+		break;
+	case WCD9335:
+		cdc_type_fn = wcd9335_get_cdc_info;
+		break;
+	default:
+		cdc_type_fn = NULL;
+		break;
+	}
+
+	return cdc_type_fn;
+}
+

+ 584 - 0
drivers/mfd/wcd9xxx-slimslave.c

@@ -0,0 +1,584 @@
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/slab.h>
+#include <linux/mutex.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+
+struct wcd9xxx_slim_sch {
+	u16 rx_port_ch_reg_base;
+	u16 port_tx_cfg_reg_base;
+	u16 port_rx_cfg_reg_base;
+};
+
+static struct wcd9xxx_slim_sch sh_ch;
+
+static int wcd9xxx_alloc_slim_sh_ch(struct wcd9xxx *wcd9xxx,
+				    u8 wcd9xxx_pgd_la, u32 cnt,
+				    struct wcd9xxx_ch *channels, u32 path);
+
+static int wcd9xxx_dealloc_slim_sh_ch(struct slim_device *slim,
+				      u32 cnt, struct wcd9xxx_ch *channels);
+
+static int wcd9xxx_configure_ports(struct wcd9xxx *wcd9xxx)
+{
+	if (wcd9xxx->codec_type->slim_slave_type ==
+	    WCD9XXX_SLIM_SLAVE_ADDR_TYPE_0) {
+		sh_ch.rx_port_ch_reg_base = 0x180;
+		sh_ch.port_rx_cfg_reg_base = 0x040;
+		sh_ch.port_tx_cfg_reg_base = 0x040;
+	} else {
+		sh_ch.rx_port_ch_reg_base =
+			0x180 - (TAIKO_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS * 4);
+		sh_ch.port_rx_cfg_reg_base =
+			0x040 - TAIKO_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS;
+		sh_ch.port_tx_cfg_reg_base = 0x050;
+	}
+
+	return 0;
+}
+
+/**
+ * wcd9xxx_init_slimslave
+ *
+ * @wcd9xxx: pointer to wcd9xxx struct
+ * @wcd9xxx_pgd_la: pgd_la value
+ * @tx_num: tx number
+ * @rx_num: rx number
+ * @tx_slot: pointer to tx slot
+ * @rx_slot: pointer to rx slot
+ *
+ * Returns 0 on success, appropriate error code otherwise
+ */
+int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la,
+			   unsigned int tx_num, unsigned int *tx_slot,
+			   unsigned int rx_num, unsigned int *rx_slot)
+{
+	int ret = 0;
+	int i;
+
+	ret = wcd9xxx_configure_ports(wcd9xxx);
+	if (ret) {
+		pr_err("%s: Failed to configure register address offset\n",
+		       __func__);
+		goto err;
+	}
+
+	if (!rx_num || rx_num > wcd9xxx->num_rx_port) {
+		pr_err("%s: invalid rx num %d\n", __func__, rx_num);
+		return -EINVAL;
+	}
+	if (wcd9xxx->rx_chs) {
+		wcd9xxx->num_rx_port = rx_num;
+		for (i = 0; i < rx_num; i++) {
+			wcd9xxx->rx_chs[i].ch_num = rx_slot[i];
+			INIT_LIST_HEAD(&wcd9xxx->rx_chs[i].list);
+		}
+		ret = wcd9xxx_alloc_slim_sh_ch(wcd9xxx, wcd9xxx_pgd_la,
+						wcd9xxx->num_rx_port,
+						wcd9xxx->rx_chs,
+						SLIM_SINK);
+		if (ret) {
+			pr_err("%s: Failed to alloc %d rx slimbus channels\n",
+				__func__, wcd9xxx->num_rx_port);
+			kfree(wcd9xxx->rx_chs);
+			wcd9xxx->rx_chs = NULL;
+			wcd9xxx->num_rx_port = 0;
+		}
+	} else {
+		pr_err("Not able to allocate memory for %d slimbus rx ports\n",
+			wcd9xxx->num_rx_port);
+	}
+
+	if (!tx_num || tx_num > wcd9xxx->num_tx_port) {
+		pr_err("%s: invalid tx num %d\n", __func__, tx_num);
+		return -EINVAL;
+	}
+	if (wcd9xxx->tx_chs) {
+		wcd9xxx->num_tx_port = tx_num;
+		for (i = 0; i < tx_num; i++) {
+			wcd9xxx->tx_chs[i].ch_num = tx_slot[i];
+			INIT_LIST_HEAD(&wcd9xxx->tx_chs[i].list);
+		}
+		ret = wcd9xxx_alloc_slim_sh_ch(wcd9xxx, wcd9xxx_pgd_la,
+						wcd9xxx->num_tx_port,
+						wcd9xxx->tx_chs,
+						SLIM_SRC);
+		if (ret) {
+			pr_err("%s: Failed to alloc %d tx slimbus channels\n",
+				__func__, wcd9xxx->num_tx_port);
+			kfree(wcd9xxx->tx_chs);
+			wcd9xxx->tx_chs = NULL;
+			wcd9xxx->num_tx_port = 0;
+		}
+	} else {
+		pr_err("Not able to allocate memory for %d slimbus tx ports\n",
+			wcd9xxx->num_tx_port);
+	}
+	return 0;
+err:
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_init_slimslave);
+
+int wcd9xxx_deinit_slimslave(struct wcd9xxx *wcd9xxx)
+{
+	if (wcd9xxx->num_rx_port) {
+		wcd9xxx_dealloc_slim_sh_ch(wcd9xxx->slim,
+					wcd9xxx->num_rx_port,
+					wcd9xxx->rx_chs);
+		wcd9xxx->num_rx_port = 0;
+	}
+	if (wcd9xxx->num_tx_port) {
+		wcd9xxx_dealloc_slim_sh_ch(wcd9xxx->slim,
+					wcd9xxx->num_tx_port,
+					wcd9xxx->tx_chs);
+		wcd9xxx->num_tx_port = 0;
+	}
+	return 0;
+}
+
+
+static int wcd9xxx_alloc_slim_sh_ch(struct wcd9xxx *wcd9xxx,
+				    u8 wcd9xxx_pgd_la, u32 cnt,
+				    struct wcd9xxx_ch *channels, u32 path)
+{
+	int ret = 0;
+	u32 ch_idx;
+
+	/* The slimbus channel allocation seem take longer time
+	 * so do the allocation up front to avoid delay in start of
+	 * playback
+	 */
+	pr_debug("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la);
+	for (ch_idx = 0; ch_idx < cnt; ch_idx++) {
+		ret = slim_get_slaveport(wcd9xxx_pgd_la,
+					channels[ch_idx].port,
+					&channels[ch_idx].sph, path);
+		pr_debug("%s: pgd_la[%d] channels[%d].port[%d]\n"
+			"channels[%d].sph[%d] path[%d]\n",
+			__func__, wcd9xxx_pgd_la, ch_idx,
+			channels[ch_idx].port,
+			ch_idx, channels[ch_idx].sph, path);
+		if (ret < 0) {
+			pr_err("%s: slave port failure id[%d] ret[%d]\n",
+				__func__, channels[ch_idx].ch_num, ret);
+			goto err;
+		}
+
+		ret = slim_query_ch(wcd9xxx->slim,
+				    channels[ch_idx].ch_num,
+				    &channels[ch_idx].ch_h);
+		if (ret < 0) {
+			pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
+				__func__, channels[ch_idx].ch_num, ret);
+			goto err;
+		}
+	}
+err:
+	return ret;
+}
+
+static int wcd9xxx_dealloc_slim_sh_ch(struct slim_device *slim,
+			u32 cnt, struct wcd9xxx_ch *channels)
+{
+	int idx = 0;
+	int ret = 0;
+	/* slim_dealloc_ch */
+	for (idx = 0; idx < cnt; idx++) {
+		ret = slim_dealloc_ch(slim, channels[idx].ch_h);
+		if (ret < 0) {
+			pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
+				__func__, ret, channels[idx].ch_h);
+		}
+	}
+	return ret;
+}
+
+/* Enable slimbus slave device for RX path */
+int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx,
+			    struct list_head *wcd9xxx_ch_list,
+			    unsigned int rate, unsigned int bit_width,
+			    u16 *grph)
+{
+	u8 ch_cnt = 0;
+	u16 ch_h[SLIM_MAX_RX_PORTS] = {0};
+	u8  payload = 0;
+	u16 codec_port = 0;
+	int ret;
+	struct slim_ch prop;
+	struct wcd9xxx_ch *rx;
+	int size = ARRAY_SIZE(ch_h);
+
+	/* Configure slave interface device */
+
+	list_for_each_entry(rx, wcd9xxx_ch_list, list) {
+		payload |= 1 << rx->shift;
+		if (ch_cnt < size) {
+			ch_h[ch_cnt] = rx->ch_h;
+			ch_cnt++;
+			pr_debug("list ch->ch_h %d ch->sph %d\n",
+				 rx->ch_h, rx->sph);
+		} else {
+			pr_err("%s: allocated channel number %u is out of max rangae %d\n",
+			       __func__, ch_cnt,
+			       size);
+			ret = EINVAL;
+			goto err;
+		}
+	}
+	pr_debug("%s: ch_cnt[%d] rate=%d WATER_MARK_VAL %d\n",
+		 __func__, ch_cnt, rate, WATER_MARK_VAL);
+	/* slim_define_ch api */
+	prop.prot = SLIM_AUTO_ISO;
+	if ((rate == 44100) || (rate == 88200) || (rate == 176400) ||
+	    (rate == 352800)) {
+		prop.baser = SLIM_RATE_11025HZ;
+		prop.ratem = (rate/11025);
+	} else {
+		prop.baser = SLIM_RATE_4000HZ;
+		prop.ratem = (rate/4000);
+	}
+	prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
+	prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
+	prop.sampleszbits = bit_width;
+
+	pr_debug("Before slim_define_ch:\n"
+		 "ch_cnt %d,ch_h[0] %d ch_h[1] %d, grph %d\n",
+		 ch_cnt, ch_h[0], ch_h[1], *grph);
+	ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt,
+			     true, grph);
+	if (ret < 0) {
+		pr_err("%s: slim_define_ch failed ret[%d]\n",
+		       __func__, ret);
+		goto err;
+	}
+
+	list_for_each_entry(rx, wcd9xxx_ch_list, list) {
+		codec_port = rx->port;
+		pr_debug("%s: codec_port %d rx 0x%p, payload %d\n"
+			 "sh_ch.rx_port_ch_reg_base0 0x%x\n"
+			 "sh_ch.port_rx_cfg_reg_base 0x%x\n",
+			 __func__, codec_port, rx, payload,
+			 sh_ch.rx_port_ch_reg_base,
+			sh_ch.port_rx_cfg_reg_base);
+
+		/* look for the valid port range and chose the
+		 * payload accordingly
+		 */
+		/* write to interface device */
+		ret = wcd9xxx_interface_reg_write(wcd9xxx,
+				SB_PGD_RX_PORT_MULTI_CHANNEL_0(
+				sh_ch.rx_port_ch_reg_base, codec_port),
+				payload);
+
+		if (ret < 0) {
+			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
+				__func__,
+				SB_PGD_RX_PORT_MULTI_CHANNEL_0(
+				sh_ch.rx_port_ch_reg_base, codec_port),
+				payload, ret);
+			goto err;
+		}
+		/* configure the slave port for water mark and enable*/
+		ret = wcd9xxx_interface_reg_write(wcd9xxx,
+				SB_PGD_PORT_CFG_BYTE_ADDR(
+				sh_ch.port_rx_cfg_reg_base, codec_port),
+				WATER_MARK_VAL);
+		if (ret < 0) {
+			pr_err("%s:watermark set failure for port[%d] ret[%d]",
+				__func__, codec_port, ret);
+		}
+
+		ret = slim_connect_sink(wcd9xxx->slim, &rx->sph, 1, rx->ch_h);
+		if (ret < 0) {
+			pr_err("%s: slim_connect_sink failed ret[%d]\n",
+				__func__, ret);
+			goto err_close_slim_sch;
+		}
+	}
+	/* slim_control_ch */
+	ret = slim_control_ch(wcd9xxx->slim, *grph, SLIM_CH_ACTIVATE,
+			      true);
+	if (ret < 0) {
+		pr_err("%s: slim_control_ch failed ret[%d]\n",
+			__func__, ret);
+		goto err_close_slim_sch;
+	}
+	return 0;
+
+err_close_slim_sch:
+	/*  release all acquired handles */
+	wcd9xxx_close_slim_sch_rx(wcd9xxx, wcd9xxx_ch_list, *grph);
+err:
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_cfg_slim_sch_rx);
+
+/* Enable slimbus slave device for RX path */
+int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx,
+			    struct list_head *wcd9xxx_ch_list,
+			    unsigned int rate, unsigned int bit_width,
+			    u16 *grph)
+{
+	u16 ch_cnt = 0;
+	u16 payload = 0;
+	u16 ch_h[SLIM_MAX_TX_PORTS] = {0};
+	u16 codec_port;
+	int ret = 0;
+	struct wcd9xxx_ch *tx;
+	int size = ARRAY_SIZE(ch_h);
+
+	struct slim_ch prop;
+
+	list_for_each_entry(tx, wcd9xxx_ch_list, list) {
+		payload |= 1 << tx->shift;
+		if (ch_cnt < size) {
+			ch_h[ch_cnt] = tx->ch_h;
+			ch_cnt++;
+		} else {
+			pr_err("%s: allocated channel number %u is out of max rangae %d\n",
+			       __func__, ch_cnt,
+			       size);
+			ret = EINVAL;
+			goto err;
+		}
+	}
+
+	/* slim_define_ch api */
+	prop.prot = SLIM_AUTO_ISO;
+	prop.baser = SLIM_RATE_4000HZ;
+	prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
+	prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
+	prop.ratem = (rate/4000);
+	prop.sampleszbits = bit_width;
+	ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt,
+			     true, grph);
+	if (ret < 0) {
+		pr_err("%s: slim_define_ch failed ret[%d]\n",
+		       __func__, ret);
+		goto err;
+	}
+
+	pr_debug("%s: ch_cnt[%d] rate[%d] bitwidth[%u]\n", __func__, ch_cnt,
+		 rate, bit_width);
+	list_for_each_entry(tx, wcd9xxx_ch_list, list) {
+		codec_port = tx->port;
+		pr_debug("%s: codec_port %d tx 0x%p, payload 0x%x\n",
+			 __func__, codec_port, tx, payload);
+		/* write to interface device */
+		ret = wcd9xxx_interface_reg_write(wcd9xxx,
+				SB_PGD_TX_PORT_MULTI_CHANNEL_0(codec_port),
+				payload & 0x00FF);
+		if (ret < 0) {
+			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
+				__func__,
+				SB_PGD_TX_PORT_MULTI_CHANNEL_0(codec_port),
+				payload, ret);
+			goto err;
+		}
+		/* ports 8,9 */
+		ret = wcd9xxx_interface_reg_write(wcd9xxx,
+				SB_PGD_TX_PORT_MULTI_CHANNEL_1(codec_port),
+				(payload & 0xFF00)>>8);
+		if (ret < 0) {
+			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
+				__func__,
+				SB_PGD_TX_PORT_MULTI_CHANNEL_1(codec_port),
+				payload, ret);
+			goto err;
+		}
+		/* configure the slave port for water mark and enable*/
+		ret = wcd9xxx_interface_reg_write(wcd9xxx,
+				SB_PGD_PORT_CFG_BYTE_ADDR(
+				sh_ch.port_tx_cfg_reg_base, codec_port),
+				WATER_MARK_VAL);
+		if (ret < 0) {
+			pr_err("%s:watermark set failure for port[%d] ret[%d]",
+				__func__, codec_port, ret);
+		}
+
+		ret = slim_connect_src(wcd9xxx->slim, tx->sph, tx->ch_h);
+
+		if (ret < 0) {
+			pr_err("%s: slim_connect_src failed ret[%d]\n",
+			       __func__, ret);
+			goto err;
+		}
+	}
+	/* slim_control_ch */
+	ret = slim_control_ch(wcd9xxx->slim, *grph, SLIM_CH_ACTIVATE,
+			      true);
+	if (ret < 0) {
+		pr_err("%s: slim_control_ch failed ret[%d]\n",
+			__func__, ret);
+		goto err;
+	}
+	return 0;
+err:
+	/* release all acquired handles */
+	wcd9xxx_close_slim_sch_tx(wcd9xxx, wcd9xxx_ch_list, *grph);
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_cfg_slim_sch_tx);
+
+int wcd9xxx_close_slim_sch_rx(struct wcd9xxx *wcd9xxx,
+			      struct list_head *wcd9xxx_ch_list, u16 grph)
+{
+	u32 sph[SLIM_MAX_RX_PORTS] = {0};
+	int ch_cnt = 0;
+	int ret = 0;
+	struct wcd9xxx_ch *rx;
+
+	list_for_each_entry(rx, wcd9xxx_ch_list, list)
+		sph[ch_cnt++] = rx->sph;
+
+	pr_debug("%s ch_cht %d, sph[0] %d sph[1] %d\n", __func__, ch_cnt,
+		sph[0], sph[1]);
+
+	/* slim_control_ch (REMOVE) */
+	pr_debug("%s before slim_control_ch grph %d\n", __func__, grph);
+	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
+	if (ret < 0) {
+		pr_err("%s: slim_control_ch failed ret[%d]\n", __func__, ret);
+		goto err;
+	}
+err:
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_close_slim_sch_rx);
+
+int wcd9xxx_close_slim_sch_tx(struct wcd9xxx *wcd9xxx,
+			      struct list_head *wcd9xxx_ch_list,
+			      u16 grph)
+{
+	u32 sph[SLIM_MAX_TX_PORTS] = {0};
+	int ret = 0;
+	int ch_cnt = 0;
+	struct wcd9xxx_ch *tx;
+
+	pr_debug("%s\n", __func__);
+	list_for_each_entry(tx, wcd9xxx_ch_list, list)
+		sph[ch_cnt++] = tx->sph;
+
+	pr_debug("%s ch_cht %d, sph[0] %d sph[1] %d\n",
+		__func__, ch_cnt, sph[0], sph[1]);
+	/* slim_control_ch (REMOVE) */
+	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
+	if (ret < 0) {
+		pr_err("%s: slim_control_ch failed ret[%d]\n",
+			__func__, ret);
+		goto err;
+	}
+err:
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_close_slim_sch_tx);
+
+int wcd9xxx_get_slave_port(unsigned int ch_num)
+{
+	int ret = 0;
+
+	ret = (ch_num - BASE_CH_NUM);
+	pr_debug("%s: ch_num[%d] slave port[%d]\n", __func__, ch_num, ret);
+	if (ret < 0) {
+		pr_err("%s: Error:- Invalid slave port found = %d\n",
+			__func__, ret);
+		return -EINVAL;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_get_slave_port);
+
+int wcd9xxx_disconnect_port(struct wcd9xxx *wcd9xxx,
+			    struct list_head *wcd9xxx_ch_list, u16 grph)
+{
+	u32 sph[SLIM_MAX_TX_PORTS + SLIM_MAX_RX_PORTS] = {0};
+	int ch_cnt = 0;
+	int ret = 0;
+	struct wcd9xxx_ch *slim_ch;
+
+	list_for_each_entry(slim_ch, wcd9xxx_ch_list, list)
+		sph[ch_cnt++] = slim_ch->sph;
+
+	/* slim_disconnect_port */
+	ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
+	if (ret < 0) {
+		pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+			__func__, ret);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_disconnect_port);
+
+/* This function is called with mutex acquired */
+int wcd9xxx_rx_vport_validation(u32 port_id,
+				struct list_head *codec_dai_list)
+{
+	struct wcd9xxx_ch *ch;
+	int ret = 0;
+
+	pr_debug("%s: port_id %u\n", __func__, port_id);
+
+	list_for_each_entry(ch,
+		codec_dai_list, list) {
+		pr_debug("%s: ch->port %u\n", __func__, ch->port);
+		if (ch->port == port_id) {
+			ret = -EINVAL;
+			break;
+		}
+	}
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_rx_vport_validation);
+
+
+/* This function is called with mutex acquired */
+int wcd9xxx_tx_vport_validation(u32 table, u32 port_id,
+				struct wcd9xxx_codec_dai_data *codec_dai,
+				u32 num_codec_dais)
+{
+	struct wcd9xxx_ch *ch;
+	int ret = 0;
+	u32 index;
+	unsigned long vtable = table;
+	u32 size = sizeof(table) * BITS_PER_BYTE;
+
+	pr_debug("%s: vtable 0x%lx port_id %u size %d\n", __func__,
+		 vtable, port_id, size);
+	for_each_set_bit(index, &vtable, size) {
+		if (index < num_codec_dais) {
+			list_for_each_entry(ch,
+					&codec_dai[index].wcd9xxx_ch_list,
+					list) {
+				pr_debug("%s: index %u ch->port %u vtable 0x%lx\n",
+						__func__, index, ch->port,
+						vtable);
+				if (ch->port == port_id) {
+					pr_err("%s: TX%u is used by AIF%u_CAP Mixer\n",
+							__func__, port_id + 1,
+							(index + 1)/2);
+					ret = -EINVAL;
+					break;
+				}
+			}
+		} else {
+			pr_err("%s: Invalid index %d of codec dai",
+					__func__, index);
+			ret = -EINVAL;
+		}
+		if (ret)
+			break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_tx_vport_validation);

+ 1198 - 0
drivers/mfd/wcd9xxx-utils.c

@@ -0,0 +1,1198 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-irq.h>
+#include <linux/mfd/msm-cdc-supply.h>
+#include <linux/mfd/msm-cdc-pinctrl.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-utils.h>
+
+#define REG_BYTES 2
+#define VAL_BYTES 1
+/*
+ * Page Register Address that APP Proc uses to
+ * access WCD9335 Codec registers is identified
+ * as 0x00
+ */
+#define PAGE_REG_ADDR 0x00
+
+static enum wcd9xxx_intf_status wcd9xxx_intf = -1;
+
+static struct mfd_cell tavil_devs[] = {
+	{
+		.name = "qcom-wcd-pinctrl",
+		.of_compatible = "qcom,wcd-pinctrl",
+	},
+	{
+		.name = "tavil_codec",
+	},
+};
+
+static struct mfd_cell tasha_devs[] = {
+	{
+		.name = "tasha_codec",
+	},
+};
+
+static struct mfd_cell tomtom_devs[] = {
+	{
+		.name = "tomtom_codec",
+	},
+};
+
+static int wcd9xxx_read_of_property_u32(struct device *dev, const char *name,
+					u32 *val)
+{
+	int rc = 0;
+
+	rc = of_property_read_u32(dev->of_node, name, val);
+	if (rc)
+		dev_err(dev, "%s: Looking up %s property in node %s failed",
+			__func__, name, dev->of_node->full_name);
+
+	return rc;
+}
+
+static void wcd9xxx_dt_parse_micbias_info(struct device *dev,
+					  struct wcd9xxx_micbias_setting *mb)
+{
+	u32 prop_val;
+	int rc;
+
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias-ldoh-v", NULL)) {
+		rc = wcd9xxx_read_of_property_u32(dev,
+						  "qcom,cdc-micbias-ldoh-v",
+						  &prop_val);
+		if (!rc)
+			mb->ldoh_v  =  (u8)prop_val;
+	}
+
+	/* MB1 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias-cfilt1-mv",
+			     NULL)) {
+		rc = wcd9xxx_read_of_property_u32(dev,
+						  "qcom,cdc-micbias-cfilt1-mv",
+						   &prop_val);
+		if (!rc)
+			mb->cfilt1_mv = prop_val;
+
+		rc = wcd9xxx_read_of_property_u32(dev,
+						"qcom,cdc-micbias1-cfilt-sel",
+						&prop_val);
+		if (!rc)
+			mb->bias1_cfilt_sel = (u8)prop_val;
+
+	} else if (of_find_property(dev->of_node, "qcom,cdc-micbias1-mv",
+				    NULL)) {
+		rc = wcd9xxx_read_of_property_u32(dev,
+						  "qcom,cdc-micbias1-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb1_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias1 DT property not found\n",
+			__func__);
+	}
+
+	/* MB2 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias-cfilt2-mv",
+			     NULL)) {
+		rc = wcd9xxx_read_of_property_u32(dev,
+						  "qcom,cdc-micbias-cfilt2-mv",
+						   &prop_val);
+		if (!rc)
+			mb->cfilt2_mv = prop_val;
+
+		rc = wcd9xxx_read_of_property_u32(dev,
+						"qcom,cdc-micbias2-cfilt-sel",
+						&prop_val);
+		if (!rc)
+			mb->bias2_cfilt_sel = (u8)prop_val;
+
+	} else if (of_find_property(dev->of_node, "qcom,cdc-micbias2-mv",
+				    NULL)) {
+		rc = wcd9xxx_read_of_property_u32(dev,
+						  "qcom,cdc-micbias2-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb2_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias2 DT property not found\n",
+			__func__);
+	}
+
+	/* MB3 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias-cfilt3-mv",
+			     NULL)) {
+		rc = wcd9xxx_read_of_property_u32(dev,
+						  "qcom,cdc-micbias-cfilt3-mv",
+						   &prop_val);
+		if (!rc)
+			mb->cfilt3_mv = prop_val;
+
+		rc = wcd9xxx_read_of_property_u32(dev,
+						"qcom,cdc-micbias3-cfilt-sel",
+						&prop_val);
+		if (!rc)
+			mb->bias3_cfilt_sel = (u8)prop_val;
+
+	} else if (of_find_property(dev->of_node, "qcom,cdc-micbias3-mv",
+				    NULL)) {
+		rc = wcd9xxx_read_of_property_u32(dev,
+						  "qcom,cdc-micbias3-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb3_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias3 DT property not found\n",
+			__func__);
+	}
+
+	/* MB4 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias4-cfilt-sel",
+			     NULL)) {
+		rc = wcd9xxx_read_of_property_u32(dev,
+						"qcom,cdc-micbias4-cfilt-sel",
+						&prop_val);
+		if (!rc)
+			mb->bias4_cfilt_sel = (u8)prop_val;
+
+	} else if (of_find_property(dev->of_node, "qcom,cdc-micbias4-mv",
+				    NULL)) {
+		rc = wcd9xxx_read_of_property_u32(dev,
+						  "qcom,cdc-micbias4-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb4_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias4 DT property not found\n",
+			__func__);
+	}
+
+	mb->bias1_cap_mode =
+	   (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
+	 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
+	mb->bias2_cap_mode =
+	   (of_property_read_bool(dev->of_node, "qcom,cdc-micbias2-ext-cap") ?
+	    MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
+	mb->bias3_cap_mode =
+	   (of_property_read_bool(dev->of_node, "qcom,cdc-micbias3-ext-cap") ?
+	    MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
+	mb->bias4_cap_mode =
+	   (of_property_read_bool(dev->of_node, "qcom,cdc-micbias4-ext-cap") ?
+	    MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
+
+	mb->bias2_is_headset_only =
+		of_property_read_bool(dev->of_node,
+				      "qcom,cdc-micbias2-headset-only");
+
+	/* Print micbias info */
+	dev_dbg(dev, "%s: ldoh_v  %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
+		__func__, (u32)mb->ldoh_v, (u32)mb->cfilt1_mv,
+		(u32)mb->cfilt2_mv, (u32)mb->cfilt3_mv);
+
+	dev_dbg(dev, "%s: micb1_mv %u micb2_mv %u micb3_mv %u micb4_mv %u",
+		__func__, mb->micb1_mv, mb->micb2_mv,
+		mb->micb3_mv, mb->micb4_mv);
+
+	dev_dbg(dev, "%s: bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
+		__func__, (u32)mb->bias1_cfilt_sel, (u32)mb->bias2_cfilt_sel);
+
+	dev_dbg(dev, "%s: bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
+		__func__, (u32)mb->bias3_cfilt_sel, (u32)mb->bias4_cfilt_sel);
+
+	dev_dbg(dev, "%s: bias1_ext_cap %d bias2_ext_cap %d\n",
+		__func__, mb->bias1_cap_mode, mb->bias2_cap_mode);
+
+	dev_dbg(dev, "%s: bias3_ext_cap %d bias4_ext_cap %d\n",
+		__func__, mb->bias3_cap_mode, mb->bias4_cap_mode);
+
+	dev_dbg(dev, "%s: bias2_is_headset_only %d\n",
+		__func__, mb->bias2_is_headset_only);
+}
+
+/*
+ * wcd9xxx_validate_dmic_sample_rate:
+ *	Given the dmic_sample_rate and mclk rate, validate the
+ *	dmic_sample_rate. If dmic rate is found to be invalid,
+ *	assign the dmic rate as undefined, so individual codec
+ *	drivers can use their own defaults
+ * @dev: the device for which the dmic is to be configured
+ * @dmic_sample_rate: The input dmic_sample_rate
+ * @mclk_rate: The input codec mclk rate
+ * @dmic_rate_type: String to indicate the type of dmic sample
+ *		    rate, used for debug/error logging.
+ */
+static u32 wcd9xxx_validate_dmic_sample_rate(struct device *dev,
+		u32 dmic_sample_rate, u32 mclk_rate,
+		const char *dmic_rate_type)
+{
+	u32 div_factor;
+
+	if (dmic_sample_rate == WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED ||
+	    mclk_rate % dmic_sample_rate != 0)
+		goto undefined_rate;
+
+	div_factor = mclk_rate / dmic_sample_rate;
+
+	switch (div_factor) {
+	case 2:
+	case 3:
+	case 4:
+	case 8:
+	case 16:
+		/* Valid dmic DIV factors */
+		dev_dbg(dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n",
+			__func__, div_factor, mclk_rate);
+		break;
+	case 6:
+		/*
+		 * DIV 6 is valid for both 9.6MHz and 12.288MHz
+		 * MCLK on Tavil. Older codecs support DIV6 only
+		 * for 12.288MHz MCLK.
+		 */
+		if ((mclk_rate == WCD9XXX_MCLK_CLK_9P6HZ) &&
+		    (of_device_is_compatible(dev->of_node,
+					     "qcom,tavil-slim-pgd")))
+			dev_dbg(dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n",
+				__func__, div_factor, mclk_rate);
+		else if (mclk_rate != WCD9XXX_MCLK_CLK_12P288MHZ)
+			goto undefined_rate;
+		break;
+	default:
+		/* Any other DIV factor is invalid */
+		goto undefined_rate;
+	}
+
+	return dmic_sample_rate;
+
+undefined_rate:
+	dev_dbg(dev, "%s: Invalid %s = %d, for mclk %d\n",
+		 __func__, dmic_rate_type, dmic_sample_rate, mclk_rate);
+	dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
+
+	return dmic_sample_rate;
+}
+
+/*
+ * wcd9xxx_populate_dt_data:
+ *	Parse device tree properties for the given codec device
+ *
+ * @dev: pointer to codec device
+ *
+ * Returns pointer to the platform data resulting from parsing
+ * device tree.
+ */
+struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev)
+{
+	struct wcd9xxx_pdata *pdata;
+	u32 dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
+	u32 mad_dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
+	u32 ecpp_dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
+	u32 dmic_clk_drive = WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED;
+	u32 prop_val;
+	int rc = 0;
+
+	if (!dev || !dev->of_node)
+		return NULL;
+
+	pdata = devm_kzalloc(dev, sizeof(struct wcd9xxx_pdata),
+			     GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	/* Parse power supplies */
+	msm_cdc_get_power_supplies(dev, &pdata->regulator,
+				   &pdata->num_supplies);
+	if (!pdata->regulator || (pdata->num_supplies <= 0)) {
+		dev_err(dev, "%s: no power supplies defined for codec\n",
+			__func__);
+		goto err_power_sup;
+	}
+
+	/* Parse micbias info */
+	wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
+
+	pdata->wcd_rst_np = of_parse_phandle(dev->of_node,
+					     "qcom,wcd-rst-gpio-node", 0);
+	if (!pdata->wcd_rst_np) {
+		dev_err(dev, "%s: Looking up %s property in node %s failed\n",
+			__func__, "qcom,wcd-rst-gpio-node",
+			dev->of_node->full_name);
+		goto err_parse_dt_prop;
+	}
+
+	if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-mclk-clk-rate",
+					   &prop_val)))
+		pdata->mclk_rate = prop_val;
+
+	if (pdata->mclk_rate != WCD9XXX_MCLK_CLK_9P6HZ &&
+	    pdata->mclk_rate != WCD9XXX_MCLK_CLK_12P288MHZ) {
+		dev_err(dev, "%s: Invalid mclk_rate = %u\n", __func__,
+			pdata->mclk_rate);
+		goto err_parse_dt_prop;
+	}
+
+	if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-dmic-sample-rate",
+					   &prop_val)))
+		dmic_sample_rate = prop_val;
+
+	pdata->dmic_sample_rate = wcd9xxx_validate_dmic_sample_rate(dev,
+							dmic_sample_rate,
+							pdata->mclk_rate,
+							"audio_dmic_rate");
+	if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-mad-dmic-rate",
+					   &prop_val)))
+		mad_dmic_sample_rate = prop_val;
+
+	pdata->mad_dmic_sample_rate = wcd9xxx_validate_dmic_sample_rate(dev,
+							mad_dmic_sample_rate,
+							pdata->mclk_rate,
+							"mad_dmic_rate");
+
+	if (of_find_property(dev->of_node, "qcom,cdc-ecpp-dmic-rate", NULL)) {
+		rc = wcd9xxx_read_of_property_u32(dev,
+						  "qcom,cdc-ecpp-dmic-rate",
+						  &prop_val);
+		if (!rc)
+			ecpp_dmic_sample_rate = prop_val;
+	}
+
+	pdata->ecpp_dmic_sample_rate = wcd9xxx_validate_dmic_sample_rate(dev,
+							ecpp_dmic_sample_rate,
+							pdata->mclk_rate,
+							"ecpp_dmic_rate");
+
+	if (!(of_property_read_u32(dev->of_node,
+				   "qcom,cdc-dmic-clk-drv-strength",
+				   &prop_val))) {
+		dmic_clk_drive = prop_val;
+
+		if (dmic_clk_drive != 2 && dmic_clk_drive != 4 &&
+		    dmic_clk_drive != 8 && dmic_clk_drive != 16)
+			dev_err(dev, "Invalid cdc-dmic-clk-drv-strength %d\n",
+				dmic_clk_drive);
+	}
+
+	pdata->dmic_clk_drv = dmic_clk_drive;
+
+	return pdata;
+
+err_parse_dt_prop:
+	devm_kfree(dev, pdata->regulator);
+	pdata->regulator = NULL;
+	pdata->num_supplies = 0;
+err_power_sup:
+	devm_kfree(dev, pdata);
+	return NULL;
+}
+EXPORT_SYMBOL(wcd9xxx_populate_dt_data);
+
+static bool is_wcd9xxx_reg_power_down(struct wcd9xxx *wcd9xxx, u16 rreg)
+{
+	bool ret = false;
+	int i;
+	struct wcd9xxx_power_region *wcd9xxx_pwr;
+
+	if (!wcd9xxx)
+		return ret;
+
+	for (i = 0; i < WCD9XXX_MAX_PWR_REGIONS; i++) {
+		wcd9xxx_pwr = wcd9xxx->wcd9xxx_pwr[i];
+		if (!wcd9xxx_pwr)
+			continue;
+		if (((wcd9xxx_pwr->pwr_collapse_reg_min == 0) &&
+		     (wcd9xxx_pwr->pwr_collapse_reg_max == 0)) ||
+		    (wcd9xxx_pwr->power_state ==
+		     WCD_REGION_POWER_COLLAPSE_REMOVE))
+			ret = false;
+		else if (((wcd9xxx_pwr->power_state ==
+			   WCD_REGION_POWER_DOWN) ||
+			  (wcd9xxx_pwr->power_state ==
+			   WCD_REGION_POWER_COLLAPSE_BEGIN)) &&
+			 (rreg >= wcd9xxx_pwr->pwr_collapse_reg_min) &&
+			 (rreg <= wcd9xxx_pwr->pwr_collapse_reg_max))
+			ret = true;
+	}
+	return ret;
+}
+
+/*
+ * wcd9xxx_page_write:
+ *	Retrieve page number from register and
+ *	write that page number to the page address.
+ *	Called under io_lock acquisition.
+ *
+ * @wcd9xxx: pointer to wcd9xxx
+ * @reg: Register address from which page number is retrieved
+ *
+ * Returns 0 for success and negative error code for failure.
+ */
+int wcd9xxx_page_write(struct wcd9xxx *wcd9xxx, unsigned short *reg)
+{
+	int ret = 0;
+	unsigned short c_reg, reg_addr;
+	u8 pg_num, prev_pg_num;
+
+	if (wcd9xxx->type != WCD9335 && wcd9xxx->type != WCD934X)
+		return ret;
+
+	c_reg = *reg;
+	pg_num = c_reg >> 8;
+	reg_addr = c_reg & 0xff;
+	if (wcd9xxx->prev_pg_valid) {
+		prev_pg_num = wcd9xxx->prev_pg;
+		if (prev_pg_num != pg_num) {
+			ret = wcd9xxx->write_dev(
+					wcd9xxx, PAGE_REG_ADDR, 1,
+					(void *) &pg_num, false);
+			if (ret < 0)
+				pr_err("page write error, pg_num: 0x%x\n",
+					pg_num);
+			else {
+				wcd9xxx->prev_pg = pg_num;
+				dev_dbg(wcd9xxx->dev, "%s: Page 0x%x Write to 0x00\n",
+					__func__, pg_num);
+			}
+		}
+	} else {
+		ret = wcd9xxx->write_dev(
+				wcd9xxx, PAGE_REG_ADDR, 1, (void *) &pg_num,
+				false);
+		if (ret < 0)
+			pr_err("page write error, pg_num: 0x%x\n", pg_num);
+		else {
+			wcd9xxx->prev_pg = pg_num;
+			wcd9xxx->prev_pg_valid = true;
+			dev_dbg(wcd9xxx->dev, "%s: Page 0x%x Write to 0x00\n",
+				__func__, pg_num);
+		}
+	}
+	*reg = reg_addr;
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_page_write);
+
+static int regmap_bus_read(void *context, const void *reg, size_t reg_size,
+			   void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct wcd9xxx *wcd9xxx = dev_get_drvdata(dev);
+	unsigned short c_reg, rreg;
+	int ret, i;
+
+	if (!wcd9xxx) {
+		dev_err(dev, "%s: wcd9xxx is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (!reg || !val) {
+		dev_err(dev, "%s: reg or val is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (reg_size != REG_BYTES) {
+		dev_err(dev, "%s: register size %zd bytes, not supported\n",
+			__func__, reg_size);
+		return -EINVAL;
+	}
+
+	mutex_lock(&wcd9xxx->io_lock);
+	c_reg = *(u16 *)reg;
+	rreg = c_reg;
+
+	if (is_wcd9xxx_reg_power_down(wcd9xxx, rreg)) {
+		ret = 0;
+		for (i = 0; i < val_size; i++)
+			((u8 *)val)[i] = 0;
+		goto err;
+	}
+	ret = wcd9xxx_page_write(wcd9xxx, &c_reg);
+	if (ret)
+		goto err;
+	ret = wcd9xxx->read_dev(wcd9xxx, c_reg, val_size, val, false);
+	if (ret < 0)
+		dev_err(dev, "%s: Codec read failed (%d), reg: 0x%x, size:%zd\n",
+			__func__, ret, rreg, val_size);
+	else {
+		for (i = 0; i < val_size; i++)
+			dev_dbg(dev, "%s: Read 0x%02x from 0x%x\n",
+				__func__, ((u8 *)val)[i], rreg + i);
+	}
+err:
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	return ret;
+}
+
+static int regmap_bus_gather_write(void *context,
+				   const void *reg, size_t reg_size,
+				   const void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct wcd9xxx *wcd9xxx = dev_get_drvdata(dev);
+	unsigned short c_reg, rreg;
+	int ret, i;
+
+	if (!wcd9xxx) {
+		dev_err(dev, "%s: wcd9xxx is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (!reg || !val) {
+		dev_err(dev, "%s: reg or val is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (reg_size != REG_BYTES) {
+		dev_err(dev, "%s: register size %zd bytes, not supported\n",
+			__func__, reg_size);
+		return -EINVAL;
+	}
+	mutex_lock(&wcd9xxx->io_lock);
+	c_reg = *(u16 *)reg;
+	rreg = c_reg;
+
+	if (is_wcd9xxx_reg_power_down(wcd9xxx, rreg)) {
+		ret = 0;
+		goto err;
+	}
+	ret = wcd9xxx_page_write(wcd9xxx, &c_reg);
+	if (ret)
+		goto err;
+
+	for (i = 0; i < val_size; i++)
+		dev_dbg(dev, "Write %02x to 0x%x\n", ((u8 *)val)[i],
+			rreg + i);
+
+	ret = wcd9xxx->write_dev(wcd9xxx, c_reg, val_size, (void *) val,
+				 false);
+	if (ret < 0)
+		dev_err(dev, "%s: Codec write failed (%d), reg:0x%x, size:%zd\n",
+			__func__, ret, rreg, val_size);
+
+err:
+	mutex_unlock(&wcd9xxx->io_lock);
+	return ret;
+}
+
+static int regmap_bus_write(void *context, const void *data, size_t count)
+{
+	struct device *dev = context;
+	struct wcd9xxx *wcd9xxx = dev_get_drvdata(dev);
+
+	if (!wcd9xxx)
+		return -EINVAL;
+
+	WARN_ON(count < REG_BYTES);
+
+	if (count > (REG_BYTES + VAL_BYTES)) {
+		if (wcd9xxx->multi_reg_write)
+			return wcd9xxx->multi_reg_write(wcd9xxx,
+							data, count);
+	} else
+		return regmap_bus_gather_write(context, data, REG_BYTES,
+					       data + REG_BYTES,
+					       count - REG_BYTES);
+
+	dev_err(dev, "%s: bus multi reg write failure\n", __func__);
+
+	return -EINVAL;
+}
+
+static struct regmap_bus regmap_bus_config = {
+	.write = regmap_bus_write,
+	.gather_write = regmap_bus_gather_write,
+	.read = regmap_bus_read,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+/*
+ * wcd9xxx_regmap_init:
+ *	Initialize wcd9xxx register map
+ *
+ * @dev: pointer to wcd device
+ * @config: pointer to register map config
+ *
+ * Returns pointer to regmap structure for success
+ * or NULL in case of failure.
+ */
+struct regmap *wcd9xxx_regmap_init(struct device *dev,
+				   const struct regmap_config *config)
+{
+	return devm_regmap_init(dev, &regmap_bus_config, dev, config);
+}
+EXPORT_SYMBOL(wcd9xxx_regmap_init);
+
+/*
+ * wcd9xxx_reset:
+ *	Reset wcd9xxx codec
+ *
+ * @dev: pointer to wcd device
+ *
+ * Returns 0 for success or negative error code in case of failure
+ */
+int wcd9xxx_reset(struct device *dev)
+{
+	struct wcd9xxx *wcd9xxx;
+	int rc;
+	int value;
+
+	if (!dev)
+		return -ENODEV;
+
+	wcd9xxx = dev_get_drvdata(dev);
+	if (!wcd9xxx)
+		return -EINVAL;
+
+	if (!wcd9xxx->wcd_rst_np) {
+		dev_err(dev, "%s: reset gpio device node not specified\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	value = msm_cdc_pinctrl_get_state(wcd9xxx->wcd_rst_np);
+	if (value > 0) {
+		wcd9xxx->avoid_cdc_rstlow = 1;
+		return 0;
+	}
+
+	rc = msm_cdc_pinctrl_select_sleep_state(wcd9xxx->wcd_rst_np);
+	if (rc) {
+		dev_err(dev, "%s: wcd sleep state request fail!\n",
+			__func__);
+		return rc;
+	}
+
+	/* 20ms sleep required after pulling the reset gpio to LOW */
+	msleep(20);
+
+	rc = msm_cdc_pinctrl_select_active_state(wcd9xxx->wcd_rst_np);
+	if (rc) {
+		dev_err(dev, "%s: wcd active state request fail!\n",
+			__func__);
+		return rc;
+	}
+	msleep(20);
+
+	return rc;
+}
+EXPORT_SYMBOL(wcd9xxx_reset);
+
+/*
+ * wcd9xxx_reset_low:
+ *	Pull the wcd9xxx codec reset_n to low
+ *
+ * @dev: pointer to wcd device
+ *
+ * Returns 0 for success or negative error code in case of failure
+ */
+int wcd9xxx_reset_low(struct device *dev)
+{
+	struct wcd9xxx *wcd9xxx;
+	int rc;
+
+	if (!dev)
+		return -ENODEV;
+
+	wcd9xxx = dev_get_drvdata(dev);
+	if (!wcd9xxx)
+		return -EINVAL;
+
+	if (!wcd9xxx->wcd_rst_np) {
+		dev_err(dev, "%s: reset gpio device node not specified\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (wcd9xxx->avoid_cdc_rstlow) {
+		wcd9xxx->avoid_cdc_rstlow = 0;
+		dev_dbg(dev, "%s: avoid pull down of reset GPIO\n", __func__);
+		return 0;
+	}
+
+	rc = msm_cdc_pinctrl_select_sleep_state(wcd9xxx->wcd_rst_np);
+	if (rc)
+		dev_err(dev, "%s: wcd sleep state request fail!\n",
+			__func__);
+
+	return rc;
+}
+EXPORT_SYMBOL(wcd9xxx_reset_low);
+
+/*
+ * wcd9xxx_bringup:
+ *	Toggle reset analog and digital cores of wcd9xxx codec
+ *
+ * @dev: pointer to wcd device
+ *
+ * Returns 0 for success or negative error code in case of failure
+ */
+int wcd9xxx_bringup(struct device *dev)
+{
+	struct wcd9xxx *wcd9xxx;
+	int rc;
+	codec_bringup_fn cdc_bup_fn;
+
+	if (!dev)
+		return -ENODEV;
+
+	wcd9xxx = dev_get_drvdata(dev);
+	if (!wcd9xxx)
+		return -EINVAL;
+
+	cdc_bup_fn = wcd9xxx_bringup_fn(wcd9xxx->type);
+	if (!cdc_bup_fn) {
+		dev_err(dev, "%s: Codec bringup fn NULL!\n",
+			__func__);
+		return -EINVAL;
+	}
+	rc = cdc_bup_fn(wcd9xxx);
+	if (rc)
+		dev_err(dev, "%s: Codec bringup error, rc: %d\n",
+			__func__, rc);
+
+	return rc;
+}
+EXPORT_SYMBOL(wcd9xxx_bringup);
+
+/*
+ * wcd9xxx_bringup:
+ *	Set analog and digital cores of wcd9xxx codec in reset state
+ *
+ * @dev: pointer to wcd device
+ *
+ * Returns 0 for success or negative error code in case of failure
+ */
+int wcd9xxx_bringdown(struct device *dev)
+{
+	struct wcd9xxx *wcd9xxx;
+	int rc;
+	codec_bringdown_fn cdc_bdown_fn;
+
+	if (!dev)
+		return -ENODEV;
+
+	wcd9xxx = dev_get_drvdata(dev);
+	if (!wcd9xxx)
+		return -EINVAL;
+
+	cdc_bdown_fn = wcd9xxx_bringdown_fn(wcd9xxx->type);
+	if (!cdc_bdown_fn) {
+		dev_err(dev, "%s: Codec bring down fn NULL!\n",
+			__func__);
+		return -EINVAL;
+	}
+	rc = cdc_bdown_fn(wcd9xxx);
+	if (rc)
+		dev_err(dev, "%s: Codec bring down error, rc: %d\n",
+			__func__, rc);
+
+	return rc;
+}
+EXPORT_SYMBOL(wcd9xxx_bringdown);
+
+/*
+ * wcd9xxx_get_codec_info:
+ *	Fill codec specific information like interrupts, version
+ *
+ * @dev: pointer to wcd device
+ *
+ * Returns 0 for success or negative error code in case of failure
+ */
+int wcd9xxx_get_codec_info(struct device *dev)
+{
+	struct wcd9xxx *wcd9xxx;
+	int rc;
+	codec_type_fn cdc_type_fn;
+	struct wcd9xxx_codec_type *cinfo;
+
+	if (!dev)
+		return -ENODEV;
+
+	wcd9xxx = dev_get_drvdata(dev);
+	if (!wcd9xxx)
+		return -EINVAL;
+
+	cdc_type_fn = wcd9xxx_get_codec_info_fn(wcd9xxx->type);
+	if (!cdc_type_fn) {
+		dev_err(dev, "%s: Codec fill type fn NULL!\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	cinfo = wcd9xxx->codec_type;
+	if (!cinfo)
+		return -EINVAL;
+
+	rc = cdc_type_fn(wcd9xxx, cinfo);
+	if (rc) {
+		dev_err(dev, "%s: Codec type fill failed, rc:%d\n",
+			__func__, rc);
+		return rc;
+
+	}
+
+	switch (wcd9xxx->type) {
+	case WCD934X:
+		cinfo->dev = tavil_devs;
+		cinfo->size = ARRAY_SIZE(tavil_devs);
+		break;
+	case WCD9335:
+		cinfo->dev = tasha_devs;
+		cinfo->size = ARRAY_SIZE(tasha_devs);
+		break;
+	case WCD9330:
+		cinfo->dev = tomtom_devs;
+		cinfo->size = ARRAY_SIZE(tomtom_devs);
+		break;
+	default:
+		cinfo->dev = NULL;
+		cinfo->size = 0;
+		break;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(wcd9xxx_get_codec_info);
+
+/*
+ * wcd9xxx_core_irq_init:
+ *	Initialize wcd9xxx codec irq instance
+ *
+ * @wcd9xxx_core_res: pointer to wcd core resource
+ *
+ * Returns 0 for success or negative error code in case of failure
+ */
+int wcd9xxx_core_irq_init(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res)
+{
+	int ret = 0;
+
+	if (!wcd9xxx_core_res)
+		return -EINVAL;
+
+	if (wcd9xxx_core_res->irq != 1) {
+		ret = wcd9xxx_irq_init(wcd9xxx_core_res);
+		if (ret)
+			pr_err("IRQ initialization failed\n");
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_core_irq_init);
+
+/*
+ * wcd9xxx_assign_irq:
+ *	Assign irq and irq_base to wcd9xxx core resource
+ *
+ * @wcd9xxx_core_res: pointer to wcd core resource
+ * @irq: irq number
+ * @irq_base: base irq number
+ *
+ * Returns 0 for success or negative error code in case of failure
+ */
+int wcd9xxx_assign_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res,
+	unsigned int irq,
+	unsigned int irq_base)
+{
+	if (!wcd9xxx_core_res)
+		return -EINVAL;
+
+	wcd9xxx_core_res->irq = irq;
+	wcd9xxx_core_res->irq_base = irq_base;
+
+	return 0;
+}
+EXPORT_SYMBOL(wcd9xxx_assign_irq);
+
+/*
+ * wcd9xxx_core_res_init:
+ *	Initialize wcd core resource instance
+ *
+ * @wcd9xxx_core_res: pointer to wcd core resource
+ * @num_irqs: number of irqs for wcd9xxx core
+ * @num_irq_regs: number of irq registers
+ * @wcd_regmap: pointer to the wcd register map
+ *
+ * Returns 0 for success or negative error code in case of failure
+ */
+int wcd9xxx_core_res_init(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res,
+	int num_irqs, int num_irq_regs, struct regmap *wcd_regmap)
+{
+	if (!wcd9xxx_core_res || !wcd_regmap)
+		return -EINVAL;
+
+	mutex_init(&wcd9xxx_core_res->pm_lock);
+	wcd9xxx_core_res->wlock_holders = 0;
+	wcd9xxx_core_res->pm_state = WCD9XXX_PM_SLEEPABLE;
+	init_waitqueue_head(&wcd9xxx_core_res->pm_wq);
+	pm_qos_add_request(&wcd9xxx_core_res->pm_qos_req,
+				PM_QOS_CPU_DMA_LATENCY,
+				PM_QOS_DEFAULT_VALUE);
+
+	wcd9xxx_core_res->num_irqs = num_irqs;
+	wcd9xxx_core_res->num_irq_regs = num_irq_regs;
+	wcd9xxx_core_res->wcd_core_regmap = wcd_regmap;
+
+	pr_info("%s: num_irqs = %d, num_irq_regs = %d\n",
+			__func__, wcd9xxx_core_res->num_irqs,
+			wcd9xxx_core_res->num_irq_regs);
+
+	return 0;
+}
+EXPORT_SYMBOL(wcd9xxx_core_res_init);
+
+/*
+ * wcd9xxx_core_res_deinit:
+ *	Deinit wcd core resource instance
+ *
+ * @wcd9xxx_core_res: pointer to wcd core resource
+ */
+void wcd9xxx_core_res_deinit(struct wcd9xxx_core_resource *wcd9xxx_core_res)
+{
+	if (!wcd9xxx_core_res)
+		return;
+
+	pm_qos_remove_request(&wcd9xxx_core_res->pm_qos_req);
+	mutex_destroy(&wcd9xxx_core_res->pm_lock);
+}
+EXPORT_SYMBOL(wcd9xxx_core_res_deinit);
+
+/*
+ * wcd9xxx_pm_cmpxchg:
+ *	Check old state and exchange with pm new state
+ *	if old state matches with current state
+ *
+ * @wcd9xxx_core_res: pointer to wcd core resource
+ * @o: pm old state
+ * @n: pm new state
+ *
+ * Returns old state
+ */
+enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(
+		struct wcd9xxx_core_resource *wcd9xxx_core_res,
+		enum wcd9xxx_pm_state o,
+		enum wcd9xxx_pm_state n)
+{
+	enum wcd9xxx_pm_state old;
+
+	if (!wcd9xxx_core_res)
+		return o;
+
+	mutex_lock(&wcd9xxx_core_res->pm_lock);
+	old = wcd9xxx_core_res->pm_state;
+	if (old == o)
+		wcd9xxx_core_res->pm_state = n;
+	mutex_unlock(&wcd9xxx_core_res->pm_lock);
+
+	return old;
+}
+EXPORT_SYMBOL(wcd9xxx_pm_cmpxchg);
+
+/*
+ * wcd9xxx_core_res_suspend:
+ *	Suspend callback function for wcd9xxx core
+ *
+ * @wcd9xxx_core_res: pointer to wcd core resource
+ * @pm_message_t: pm message
+ *
+ * Returns 0 for success or negative error code for failure/busy
+ */
+int wcd9xxx_core_res_suspend(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res,
+	pm_message_t pmesg)
+{
+	int ret = 0;
+
+	pr_debug("%s: enter\n", __func__);
+	/*
+	 * pm_qos_update_request() can be called after this suspend chain call
+	 * started. thus suspend can be called while lock is being held
+	 */
+	mutex_lock(&wcd9xxx_core_res->pm_lock);
+	if (wcd9xxx_core_res->pm_state == WCD9XXX_PM_SLEEPABLE) {
+		pr_debug("%s: suspending system, state %d, wlock %d\n",
+			 __func__, wcd9xxx_core_res->pm_state,
+			 wcd9xxx_core_res->wlock_holders);
+		wcd9xxx_core_res->pm_state = WCD9XXX_PM_ASLEEP;
+	} else if (wcd9xxx_core_res->pm_state == WCD9XXX_PM_AWAKE) {
+		/*
+		 * unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
+		 * then set to WCD9XXX_PM_ASLEEP
+		 */
+		pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
+			 __func__, wcd9xxx_core_res->pm_state,
+			 wcd9xxx_core_res->wlock_holders);
+		mutex_unlock(&wcd9xxx_core_res->pm_lock);
+		if (!(wait_event_timeout(wcd9xxx_core_res->pm_wq,
+					 wcd9xxx_pm_cmpxchg(wcd9xxx_core_res,
+						  WCD9XXX_PM_SLEEPABLE,
+						  WCD9XXX_PM_ASLEEP) ==
+							WCD9XXX_PM_SLEEPABLE,
+					 HZ))) {
+			pr_debug("%s: suspend failed state %d, wlock %d\n",
+				 __func__, wcd9xxx_core_res->pm_state,
+				 wcd9xxx_core_res->wlock_holders);
+			ret = -EBUSY;
+		} else {
+			pr_debug("%s: done, state %d, wlock %d\n", __func__,
+				 wcd9xxx_core_res->pm_state,
+				 wcd9xxx_core_res->wlock_holders);
+		}
+		mutex_lock(&wcd9xxx_core_res->pm_lock);
+	} else if (wcd9xxx_core_res->pm_state == WCD9XXX_PM_ASLEEP) {
+		pr_warn("%s: system is already suspended, state %d, wlock %dn",
+			__func__, wcd9xxx_core_res->pm_state,
+			wcd9xxx_core_res->wlock_holders);
+	}
+	mutex_unlock(&wcd9xxx_core_res->pm_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_core_res_suspend);
+
+/*
+ * wcd9xxx_core_res_resume:
+ *	Resume callback function for wcd9xxx core
+ *
+ * @wcd9xxx_core_res: pointer to wcd core resource
+ *
+ * Returns 0 for success or negative error code for failure/busy
+ */
+int wcd9xxx_core_res_resume(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res)
+{
+	int ret = 0;
+
+	pr_debug("%s: enter\n", __func__);
+	mutex_lock(&wcd9xxx_core_res->pm_lock);
+	if (wcd9xxx_core_res->pm_state == WCD9XXX_PM_ASLEEP) {
+		pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
+				wcd9xxx_core_res->pm_state,
+				wcd9xxx_core_res->wlock_holders);
+		wcd9xxx_core_res->pm_state = WCD9XXX_PM_SLEEPABLE;
+	} else {
+		pr_warn("%s: system is already awake, state %d wlock %d\n",
+				__func__, wcd9xxx_core_res->pm_state,
+				wcd9xxx_core_res->wlock_holders);
+	}
+	mutex_unlock(&wcd9xxx_core_res->pm_lock);
+	wake_up_all(&wcd9xxx_core_res->pm_wq);
+
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_core_res_resume);
+
+/*
+ * wcd9xxx_get_intf_type:
+ *	Get interface type of wcd9xxx core
+ *
+ * Returns interface type
+ */
+enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void)
+{
+	return wcd9xxx_intf;
+}
+EXPORT_SYMBOL(wcd9xxx_get_intf_type);
+
+/*
+ * wcd9xxx_set_intf_type:
+ *	Set interface type of wcd9xxx core
+ *
+ */
+void wcd9xxx_set_intf_type(enum wcd9xxx_intf_status intf_status)
+{
+	wcd9xxx_intf = intf_status;
+}
+EXPORT_SYMBOL(wcd9xxx_set_intf_type);
+
+/*
+ * wcd9xxx_set_power_state: set power state for the region
+ * @wcd9xxx: handle to wcd core
+ * @state: power state to be set
+ * @region: region index
+ *
+ * Returns error code in case of failure or 0 for success
+ */
+int wcd9xxx_set_power_state(struct wcd9xxx *wcd9xxx,
+			    enum codec_power_states state,
+			    enum wcd_power_regions region)
+{
+	if (!wcd9xxx) {
+		pr_err("%s: wcd9xxx is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if ((region < 0) || (region >= WCD9XXX_MAX_PWR_REGIONS)) {
+		dev_err(wcd9xxx->dev, "%s: region index %d out of bounds\n",
+			__func__, region);
+		return -EINVAL;
+	}
+	if (!wcd9xxx->wcd9xxx_pwr[region]) {
+		dev_err(wcd9xxx->dev, "%s: memory not created for region: %d\n",
+			__func__, region);
+		return -EINVAL;
+	}
+	mutex_lock(&wcd9xxx->io_lock);
+	wcd9xxx->wcd9xxx_pwr[region]->power_state = state;
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(wcd9xxx_set_power_state);
+
+/*
+ * wcd9xxx_get_current_power_state: Get power state of the region
+ * @wcd9xxx: handle to wcd core
+ * @region: region index
+ *
+ * Returns current power state of the region or error code for failure
+ */
+int wcd9xxx_get_current_power_state(struct wcd9xxx *wcd9xxx,
+				    enum wcd_power_regions region)
+{
+	int state;
+
+	if (!wcd9xxx) {
+		pr_err("%s: wcd9xxx is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if ((region < 0) || (region >= WCD9XXX_MAX_PWR_REGIONS)) {
+		dev_err(wcd9xxx->dev, "%s: region index %d out of bounds\n",
+			__func__, region);
+		return -EINVAL;
+	}
+	if (!wcd9xxx->wcd9xxx_pwr[region]) {
+		dev_err(wcd9xxx->dev, "%s: memory not created for region: %d\n",
+			__func__, region);
+		return -EINVAL;
+	}
+
+	mutex_lock(&wcd9xxx->io_lock);
+	state = wcd9xxx->wcd9xxx_pwr[region]->power_state;
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	return state;
+}
+EXPORT_SYMBOL(wcd9xxx_get_current_power_state);

+ 5 - 0
drivers/misc/Makefile

@@ -0,0 +1,5 @@
+#
+# Makefile for misc devices that really don't fit anywhere else.
+#
+
+obj-y				+= qcom/

+ 19 - 0
drivers/misc/qcom/Kconfig

@@ -0,0 +1,19 @@
+config MSM_QDSP6V2_CODECS
+	bool "Audio QDSP6V2 APR support"
+	select SND_SOC_QDSP6V2
+	help
+	  Enable Audio codecs with APR IPC protocol support between
+	  application processor and QDSP6 for B-family. APR is
+	  used by audio driver to configure QDSP6's
+	  ASM, ADM and AFE.
+
+config MSM_ULTRASOUND
+	bool "QDSP6V2 HW Ultrasound support"
+	select SND_SOC_QDSP6V2
+	help
+	  Enable HW Ultrasound support in QDSP6V2.
+	  QDSP6V2 can support HW encoder & decoder and
+	  ultrasound processing. It will enable
+	  ultrasound data paths between
+	  HW and services, calculating input events
+	  upon the ultrasound data.

+ 1 - 0
drivers/misc/qcom/Makefile

@@ -0,0 +1 @@
+obj-y		+= qdsp6v2/

+ 6 - 0
drivers/misc/qcom/qdsp6v2/Makefile

@@ -0,0 +1,6 @@
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o g711mlaw_in.o g711alaw_in.o audio_utils.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_alac.o audio_ape.o audio_utils_aio.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_g711mlaw.o audio_g711alaw.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS)  += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o audio_hwacc_effects.o
+obj-$(CONFIG_MSM_ULTRASOUND) += ultrasound/

+ 709 - 0
drivers/misc/qcom/qdsp6v2/aac_in.c

@@ -0,0 +1,709 @@
+/*
+ * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/msm_audio_aac.h>
+#include <linux/compat.h>
+#include <linux/atomic.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+
+/* Buffer with meta*/
+#define PCM_BUF_SIZE		(4096 + sizeof(struct meta_in))
+
+/* Maximum 5 frames in buffer with meta */
+#define FRAME_SIZE		(1 + ((1536+sizeof(struct meta_out_dsp)) * 5))
+
+#define AAC_FORMAT_ADTS 65535
+
+#define MAX_SAMPLE_RATE_384K 384000
+
+static long aac_in_ioctl_shared(struct file *file, unsigned int cmd, void *arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+	int cnt = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct msm_audio_aac_enc_config *enc_cfg;
+		struct msm_audio_aac_config *aac_config;
+		uint32_t aac_mode = AAC_ENC_MODE_AAC_LC;
+
+		enc_cfg = audio->enc_cfg;
+		aac_config = audio->codec_cfg;
+		/* ENCODE CFG (after new set of API's are published )bharath*/
+		pr_debug("%s:session id %d: default buf alloc[%d]\n", __func__,
+				audio->ac->session, audio->buf_alloc);
+		if (audio->enabled == 1) {
+			pr_info("%s:AUDIO_START already over\n", __func__);
+			rc = 0;
+			break;
+		}
+
+		if (audio->opened) {
+			rc = audio_in_buf_alloc(audio);
+			if (rc < 0) {
+				pr_err("%s:session id %d: buffer allocation failed\n",
+					 __func__, audio->ac->session);
+				break;
+			}
+		} else {
+			if (audio->feedback == NON_TUNNEL_MODE) {
+				pr_debug("%s: starting in non_tunnel mode",
+					__func__);
+				rc = q6asm_open_read_write(audio->ac,
+					FORMAT_MPEG4_AAC, FORMAT_LINEAR_PCM);
+				if (rc < 0) {
+					pr_err("%s:open read write failed\n",
+						__func__);
+					break;
+				}
+			}
+			if (audio->feedback == TUNNEL_MODE) {
+				pr_debug("%s: starting in tunnel mode",
+					__func__);
+				rc = q6asm_open_read(audio->ac,
+							FORMAT_MPEG4_AAC);
+
+				if (rc < 0) {
+					pr_err("%s:open read failed\n",
+							__func__);
+					break;
+				}
+			}
+			audio->stopped = 0;
+		}
+
+		pr_debug("%s:sbr_ps_flag = %d, sbr_flag = %d\n", __func__,
+			aac_config->sbr_ps_on_flag, aac_config->sbr_on_flag);
+		if (aac_config->sbr_ps_on_flag)
+			aac_mode = AAC_ENC_MODE_EAAC_P;
+		else if (aac_config->sbr_on_flag)
+			aac_mode = AAC_ENC_MODE_AAC_P;
+		else
+			aac_mode = AAC_ENC_MODE_AAC_LC;
+
+		rc = q6asm_enc_cfg_blk_aac(audio->ac,
+					audio->buf_cfg.frames_per_buf,
+					enc_cfg->sample_rate,
+					enc_cfg->channels,
+					enc_cfg->bit_rate,
+					aac_mode,
+					enc_cfg->stream_format);
+		if (rc < 0) {
+			pr_err("%s:session id %d: cmd media format block failed\n",
+				__func__, audio->ac->session);
+			break;
+		}
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			rc = q6asm_media_format_block_pcm(audio->ac,
+						audio->pcm_cfg.sample_rate,
+						audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("%s:session id %d: media format block failed\n",
+				__func__, audio->ac->session);
+				break;
+			}
+		}
+		rc = audio_in_enable(audio);
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s:session id %d: Audio Start procedure failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			break;
+		}
+		while (cnt++ < audio->str_cfg.buffer_count)
+			q6asm_read(audio->ac);
+		pr_debug("%s:session id %d: AUDIO_START success enable[%d]\n",
+				__func__, audio->ac->session, audio->enabled);
+		break;
+	}
+	case AUDIO_STOP: {
+		pr_debug("%s:session id %d: Rxed AUDIO_STOP\n", __func__,
+				audio->ac->session);
+		rc = audio_in_disable(audio);
+		if (rc  < 0) {
+			pr_err("%s:session id %d: Audio Stop procedure failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			break;
+		}
+		break;
+	}
+	case AUDIO_GET_AAC_ENC_CONFIG: {
+		struct msm_audio_aac_enc_config *cfg;
+		struct msm_audio_aac_enc_config *enc_cfg;
+
+		cfg = (struct msm_audio_aac_enc_config *)arg;
+		if (cfg == NULL) {
+			pr_err("%s: NULL config pointer for %s\n",
+			__func__, "AUDIO_GET_AAC_CONFIG");
+			rc = -EINVAL;
+			break;
+		}
+		memset(cfg, 0, sizeof(*cfg));
+		enc_cfg = audio->enc_cfg;
+		if (enc_cfg->channels == CH_MODE_MONO)
+			cfg->channels = 1;
+		else
+			cfg->channels = 2;
+
+		cfg->sample_rate = enc_cfg->sample_rate;
+		cfg->bit_rate = enc_cfg->bit_rate;
+		switch (enc_cfg->stream_format) {
+		case 0x00:
+			cfg->stream_format = AUDIO_AAC_FORMAT_ADTS;
+			break;
+		case 0x01:
+			cfg->stream_format = AUDIO_AAC_FORMAT_LOAS;
+			break;
+		case 0x02:
+			cfg->stream_format = AUDIO_AAC_FORMAT_ADIF;
+			break;
+		default:
+		case 0x03:
+			cfg->stream_format = AUDIO_AAC_FORMAT_RAW;
+		}
+		pr_debug("%s:session id %d: Get-aac-cfg: format=%d sr=%d bitrate=%d\n",
+			__func__, audio->ac->session,
+			cfg->stream_format, cfg->sample_rate, cfg->bit_rate);
+		break;
+	}
+	case AUDIO_SET_AAC_ENC_CONFIG: {
+		struct msm_audio_aac_enc_config *cfg;
+		struct msm_audio_aac_enc_config *enc_cfg;
+		uint32_t min_bitrate, max_bitrate;
+
+		cfg = (struct msm_audio_aac_enc_config *)arg;
+		if (cfg == NULL) {
+			pr_err("%s: NULL config pointer for %s\n",
+			"AUDIO_SET_AAC_ENC_CONFIG", __func__);
+			rc = -EINVAL;
+			break;
+		}
+		enc_cfg = audio->enc_cfg;
+		pr_debug("%s:session id %d: Set-aac-cfg: stream=%d\n", __func__,
+			audio->ac->session, cfg->stream_format);
+
+		switch (cfg->stream_format) {
+		case AUDIO_AAC_FORMAT_ADTS:
+			enc_cfg->stream_format = 0x00;
+			break;
+		case AUDIO_AAC_FORMAT_LOAS:
+			enc_cfg->stream_format = 0x01;
+			break;
+		case AUDIO_AAC_FORMAT_ADIF:
+			enc_cfg->stream_format = 0x02;
+			break;
+		case AUDIO_AAC_FORMAT_RAW:
+			enc_cfg->stream_format = 0x03;
+			break;
+		default:
+			pr_err("%s:session id %d: unsupported AAC format %d\n",
+				__func__, audio->ac->session,
+				cfg->stream_format);
+			rc = -EINVAL;
+			break;
+		}
+
+		if (cfg->channels == 1) {
+			cfg->channels = CH_MODE_MONO;
+		} else if (cfg->channels == 2) {
+			cfg->channels = CH_MODE_STEREO;
+		} else {
+			rc = -EINVAL;
+			break;
+		}
+
+		if (cfg->sample_rate > MAX_SAMPLE_RATE_384K) {
+			pr_err("%s: ERROR: invalid sample rate = %u",
+				__func__, cfg->sample_rate);
+			rc = -EINVAL;
+			break;
+		}
+
+		min_bitrate = ((cfg->sample_rate)*(cfg->channels))/2;
+		/* This calculation should be based on AAC mode. But we cannot
+		 * get AAC mode in this setconfig. min_bitrate's logical max
+		 * value is 24000. So if min_bitrate is higher than 24000,
+		 * choose 24000.
+		 */
+		if (min_bitrate > 24000)
+			min_bitrate = 24000;
+		max_bitrate = 6*(cfg->sample_rate)*(cfg->channels);
+		if (max_bitrate > 192000)
+			max_bitrate = 192000;
+		if ((cfg->bit_rate < min_bitrate) ||
+			(cfg->bit_rate > max_bitrate)) {
+			pr_err("%s: bitrate permissible: max=%d, min=%d\n",
+				__func__, max_bitrate, min_bitrate);
+			pr_err("%s: ERROR in setting bitrate = %d\n",
+				__func__, cfg->bit_rate);
+			rc = -EINVAL;
+			break;
+		}
+		enc_cfg->sample_rate = cfg->sample_rate;
+		enc_cfg->channels = cfg->channels;
+		enc_cfg->bit_rate = cfg->bit_rate;
+		pr_debug("%s:session id %d: Set-aac-cfg:SR= 0x%x ch=0x%x bitrate=0x%x, format(adts/raw) = %d\n",
+			__func__, audio->ac->session, enc_cfg->sample_rate,
+			enc_cfg->channels, enc_cfg->bit_rate,
+			enc_cfg->stream_format);
+		break;
+	}
+	case AUDIO_SET_AAC_CONFIG: {
+		struct msm_audio_aac_config *aac_cfg;
+		struct msm_audio_aac_config *audio_aac_cfg;
+		struct msm_audio_aac_enc_config *enc_cfg;
+
+		enc_cfg = audio->enc_cfg;
+		audio_aac_cfg = audio->codec_cfg;
+		aac_cfg = (struct msm_audio_aac_config *)arg;
+
+		if (aac_cfg == NULL) {
+			pr_err("%s: NULL config pointer %s\n",
+				__func__, "AUDIO_SET_AAC_CONFIG");
+			rc = -EINVAL;
+			break;
+		}
+		pr_debug("%s:session id %d: AUDIO_SET_AAC_CONFIG: sbr_flag = %d sbr_ps_flag = %d\n",
+			 __func__, audio->ac->session, aac_cfg->sbr_on_flag,
+			 aac_cfg->sbr_ps_on_flag);
+		audio_aac_cfg->sbr_on_flag = aac_cfg->sbr_on_flag;
+		audio_aac_cfg->sbr_ps_on_flag = aac_cfg->sbr_ps_on_flag;
+		if ((audio_aac_cfg->sbr_on_flag == 1) ||
+			 (audio_aac_cfg->sbr_ps_on_flag == 1)) {
+			if (enc_cfg->sample_rate < 24000) {
+				pr_err("%s: ERROR in setting samplerate = %d\n",
+					__func__, enc_cfg->sample_rate);
+				rc = -EINVAL;
+				break;
+			}
+		}
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static long aac_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = aac_in_ioctl_shared(file, cmd, NULL);
+		break;
+	}
+	case AUDIO_GET_AAC_ENC_CONFIG: {
+		struct msm_audio_aac_enc_config cfg;
+
+		rc = aac_in_ioctl_shared(file, cmd, &cfg);
+		if (rc) {
+			pr_err("%s:AUDIO_GET_AAC_ENC_CONFIG failed. rc=%d\n",
+				__func__, rc);
+			break;
+		}
+		if (copy_to_user((void *)arg, &cfg, sizeof(cfg))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AAC_ENC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_AAC_ENC_CONFIG: {
+		struct msm_audio_aac_enc_config cfg;
+
+		if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AAC_ENC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = aac_in_ioctl_shared(file, cmd, &cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_ENC_CONFIG failed. rc=%d\n",
+				__func__, rc);
+		break;
+	}
+	case AUDIO_GET_AAC_CONFIG: {
+		if (copy_to_user((void *)arg, &audio->codec_cfg,
+				 sizeof(struct msm_audio_aac_config))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_AAC_CONFIG: {
+		struct msm_audio_aac_config aac_cfg;
+
+		if (copy_from_user(&aac_cfg, (void *)arg,
+				 sizeof(struct msm_audio_aac_config))) {
+			pr_err("%s: copy_to_user for AUDIO_SET_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = aac_in_ioctl_shared(file, cmd, &aac_cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_CONFIG failed. rc=%d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd=%d\n", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_aac_enc_config32 {
+	u32 channels;
+	u32 sample_rate;
+	u32 bit_rate;
+	u32 stream_format;
+};
+
+struct msm_audio_aac_config32 {
+	s16 format;
+	u16 audio_object;
+	u16 ep_config;       /* 0 ~ 3 useful only obj = ERLC */
+	u16 aac_section_data_resilience_flag;
+	u16 aac_scalefactor_data_resilience_flag;
+	u16 aac_spectral_data_resilience_flag;
+	u16 sbr_on_flag;
+	u16 sbr_ps_on_flag;
+	u16 dual_mono_mode;
+	u16 channel_configuration;
+	u16 sample_rate;
+};
+
+enum {
+	AUDIO_SET_AAC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_aac_config32),
+	AUDIO_GET_AAC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_aac_config32),
+	AUDIO_SET_AAC_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+3), struct msm_audio_aac_enc_config32),
+	AUDIO_GET_AAC_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+4), struct msm_audio_aac_enc_config32)
+};
+
+static long aac_in_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = aac_in_ioctl_shared(file, cmd, NULL);
+		break;
+	}
+	case AUDIO_GET_AAC_ENC_CONFIG_32: {
+		struct msm_audio_aac_enc_config cfg;
+		struct msm_audio_aac_enc_config32 cfg_32;
+
+		memset(&cfg_32, 0, sizeof(cfg_32));
+
+		cmd = AUDIO_GET_AAC_ENC_CONFIG;
+		rc = aac_in_ioctl_shared(file, cmd, &cfg);
+		if (rc) {
+			pr_err("%s:AUDIO_GET_AAC_ENC_CONFIG_32 failed. Rc= %d\n",
+				__func__, rc);
+			break;
+		}
+		cfg_32.channels = cfg.channels;
+		cfg_32.sample_rate = cfg.sample_rate;
+		cfg_32.bit_rate = cfg.bit_rate;
+		cfg_32.stream_format = cfg.stream_format;
+		if (copy_to_user((void *)arg, &cfg_32, sizeof(cfg_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AAC_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_AAC_ENC_CONFIG_32: {
+		struct msm_audio_aac_enc_config cfg;
+		struct msm_audio_aac_enc_config32 cfg_32;
+
+		if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_GET_AAC_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		cfg.channels = cfg_32.channels;
+		cfg.sample_rate = cfg_32.sample_rate;
+		cfg.bit_rate = cfg_32.bit_rate;
+		cfg.stream_format = cfg_32.stream_format;
+		/* The command should be converted from 32 bit to normal
+		 * before the shared ioctl is called as shared ioctl
+		 * can process only normal commands
+		 */
+		cmd = AUDIO_SET_AAC_ENC_CONFIG;
+		rc = aac_in_ioctl_shared(file, cmd, &cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_ENC_CONFIG_32 failed. rc=%d\n",
+				__func__, rc);
+		break;
+	}
+	case AUDIO_GET_AAC_CONFIG_32: {
+		struct msm_audio_aac_config *aac_config;
+		struct msm_audio_aac_config32 aac_config_32;
+
+		aac_config = (struct msm_audio_aac_config *)audio->codec_cfg;
+		aac_config_32.format = aac_config->format;
+		aac_config_32.audio_object = aac_config->audio_object;
+		aac_config_32.ep_config = aac_config->ep_config;
+		aac_config_32.aac_section_data_resilience_flag =
+			aac_config->aac_section_data_resilience_flag;
+		aac_config_32.aac_scalefactor_data_resilience_flag =
+			aac_config->aac_scalefactor_data_resilience_flag;
+		aac_config_32.aac_spectral_data_resilience_flag =
+			aac_config->aac_spectral_data_resilience_flag;
+		aac_config_32.sbr_on_flag = aac_config->sbr_on_flag;
+		aac_config_32.sbr_ps_on_flag = aac_config->sbr_ps_on_flag;
+		aac_config_32.dual_mono_mode = aac_config->dual_mono_mode;
+		aac_config_32.channel_configuration =
+				aac_config->channel_configuration;
+		aac_config_32.sample_rate = aac_config->sample_rate;
+
+		if (copy_to_user((void *)arg, &aac_config_32,
+				 sizeof(aac_config_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_AAC_CONFIG_32: {
+		struct msm_audio_aac_config aac_cfg;
+		struct msm_audio_aac_config32 aac_cfg_32;
+
+		if (copy_from_user(&aac_cfg_32, (void *)arg,
+					sizeof(aac_cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AAC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		aac_cfg.format = aac_cfg_32.format;
+		aac_cfg.audio_object = aac_cfg_32.audio_object;
+		aac_cfg.ep_config = aac_cfg_32.ep_config;
+		aac_cfg.aac_section_data_resilience_flag =
+			aac_cfg_32.aac_section_data_resilience_flag;
+		aac_cfg.aac_scalefactor_data_resilience_flag =
+			aac_cfg_32.aac_scalefactor_data_resilience_flag;
+		aac_cfg.aac_spectral_data_resilience_flag =
+			aac_cfg_32.aac_spectral_data_resilience_flag;
+		aac_cfg.sbr_on_flag = aac_cfg_32.sbr_on_flag;
+		aac_cfg.sbr_ps_on_flag = aac_cfg_32.sbr_ps_on_flag;
+		aac_cfg.dual_mono_mode = aac_cfg_32.dual_mono_mode;
+		aac_cfg.channel_configuration =
+				aac_cfg_32.channel_configuration;
+		aac_cfg.sample_rate = aac_cfg_32.sample_rate;
+
+		cmd = AUDIO_SET_AAC_CONFIG;
+		rc = aac_in_ioctl_shared(file, cmd, &aac_cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d\n", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+#else
+#define aac_in_compat_ioctl NULL
+#endif
+
+static int aac_in_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_in *audio = NULL;
+	struct msm_audio_aac_enc_config *enc_cfg;
+	struct msm_audio_aac_config *aac_config;
+	int rc = 0;
+
+	audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	/* Allocate memory for encoder config param */
+	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_aac_enc_config),
+				GFP_KERNEL);
+	if (audio->enc_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+	enc_cfg = audio->enc_cfg;
+
+	audio->codec_cfg = kzalloc(sizeof(struct msm_audio_aac_config),
+				GFP_KERNEL);
+	if (audio->codec_cfg == NULL) {
+		kfree(audio->enc_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	aac_config = audio->codec_cfg;
+
+	mutex_init(&audio->lock);
+	mutex_init(&audio->read_lock);
+	mutex_init(&audio->write_lock);
+	spin_lock_init(&audio->dsp_lock);
+	init_waitqueue_head(&audio->read_wait);
+	init_waitqueue_head(&audio->write_wait);
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->str_cfg.buffer_size = FRAME_SIZE;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->min_frame_size = 1536;
+	audio->max_frames_per_buf = 5;
+	enc_cfg->sample_rate = 8000;
+	enc_cfg->channels = 1;
+	enc_cfg->bit_rate = 16000;
+	enc_cfg->stream_format = 0x00;/* 0:ADTS, 3:RAW */
+	audio->buf_cfg.meta_info_enable = 0x01;
+	audio->buf_cfg.frames_per_buf   = 0x01;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	audio->pcm_cfg.buffer_size  = PCM_BUF_SIZE;
+	aac_config->format = AUDIO_AAC_FORMAT_ADTS;
+	aac_config->audio_object = AUDIO_AAC_OBJECT_LC;
+	aac_config->sbr_on_flag = 0;
+	aac_config->sbr_ps_on_flag = 0;
+	aac_config->channel_configuration = 1;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb)q6asm_in_cb,
+							(void *)audio);
+
+	if (!audio->ac) {
+		pr_err("%s: Could not allocate memory for audio client\n",
+			__func__);
+		kfree(audio->enc_cfg);
+		kfree(audio->codec_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	/* open aac encoder in tunnel mode */
+	audio->buf_cfg.frames_per_buf = 0x01;
+
+	if ((file->f_mode & FMODE_WRITE) &&
+		(file->f_mode & FMODE_READ)) {
+		audio->feedback = NON_TUNNEL_MODE;
+		rc = q6asm_open_read_write(audio->ac, FORMAT_MPEG4_AAC,
+						FORMAT_LINEAR_PCM);
+
+		if (rc < 0) {
+			pr_err("%s:session id %d: NT Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->buf_cfg.meta_info_enable = 0x01;
+		pr_info("%s:session id %d: NT mode encoder success\n", __func__,
+				audio->ac->session);
+	} else if (!(file->f_mode & FMODE_WRITE) &&
+				(file->f_mode & FMODE_READ)) {
+		audio->feedback = TUNNEL_MODE;
+		rc = q6asm_open_read(audio->ac, FORMAT_MPEG4_AAC);
+
+		if (rc < 0) {
+			pr_err("%s:session id %d: Tunnel Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		/* register for tx overflow (valid for tunnel mode only) */
+		rc = q6asm_reg_tx_overflow(audio->ac, 0x01);
+		if (rc < 0) {
+			pr_err("%s:session id %d: TX Overflow registration failed rc=%d\n",
+				__func__,
+				audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->buf_cfg.meta_info_enable = 0x00;
+		pr_info("%s:session id %d: T mode encoder success\n", __func__,
+			audio->ac->session);
+	} else {
+		pr_err("%s:session id %d: Unexpected mode\n", __func__,
+				audio->ac->session);
+		rc = -EACCES;
+		goto fail;
+	}
+	audio->opened = 1;
+	audio->reset_event = false;
+	atomic_set(&audio->in_count, PCM_BUF_COUNT);
+	atomic_set(&audio->out_count, 0x00);
+	audio->enc_compat_ioctl = aac_in_compat_ioctl;
+	audio->enc_ioctl = aac_in_ioctl;
+	file->private_data = audio;
+
+	pr_info("%s:session id %d: success\n", __func__, audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->enc_cfg);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_in_fops = {
+	.owner		= THIS_MODULE,
+	.open		= aac_in_open,
+	.release	= audio_in_release,
+	.read		= audio_in_read,
+	.write		= audio_in_write,
+	.unlocked_ioctl	= audio_in_ioctl,
+	.compat_ioctl	= audio_in_compat_ioctl
+};
+
+struct miscdevice audio_aac_in_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_aac_in",
+	.fops	= &audio_in_fops,
+};
+
+static int __init aac_in_init(void)
+{
+	return misc_register(&audio_aac_in_misc);
+}
+device_initcall(aac_in_init);

+ 402 - 0
drivers/misc/qcom/qdsp6v2/amrnb_in.c

@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2010-2012, 2014, 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/msm_audio_amrnb.h>
+#include <linux/compat.h>
+#include <linux/atomic.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+/* Buffer with meta*/
+#define PCM_BUF_SIZE		(4096 + sizeof(struct meta_in))
+
+/* Maximum 10 frames in buffer with meta */
+#define FRAME_SIZE		(1 + ((32+sizeof(struct meta_out_dsp)) * 10))
+
+static long amrnb_in_ioctl_shared(struct file *file,
+				unsigned int cmd, void *arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+	int cnt = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct msm_audio_amrnb_enc_config_v2 *enc_cfg;
+
+		enc_cfg = audio->enc_cfg;
+		pr_debug("%s:session id %d: default buf alloc[%d]\n", __func__,
+				audio->ac->session, audio->buf_alloc);
+		if (audio->enabled == 1) {
+			pr_info("%s:AUDIO_START already over\n", __func__);
+			rc = 0;
+			break;
+		}
+		rc = audio_in_buf_alloc(audio);
+		if (rc < 0) {
+			pr_err("%s:session id %d: buffer allocation failed\n",
+				__func__, audio->ac->session);
+			break;
+		}
+
+		rc = q6asm_enc_cfg_blk_amrnb(audio->ac,
+			audio->buf_cfg.frames_per_buf,
+			enc_cfg->band_mode,
+			enc_cfg->dtx_enable);
+
+		if (rc < 0) {
+			pr_err("%s:session id %d: cmd amrnb media format block failed\n",
+				__func__, audio->ac->session);
+			break;
+		}
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			rc = q6asm_media_format_block_pcm(audio->ac,
+				audio->pcm_cfg.sample_rate,
+				audio->pcm_cfg.channel_count);
+
+			if (rc < 0) {
+				pr_err("%s:session id %d: media format block failed\n",
+				__func__, audio->ac->session);
+				break;
+			}
+		}
+		pr_debug("%s:session id %d: AUDIO_START enable[%d]\n",
+				__func__, audio->ac->session,
+				audio->enabled);
+		rc = audio_in_enable(audio);
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s:session id %d: Audio Start procedure failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			break;
+		}
+		while (cnt++ < audio->str_cfg.buffer_count)
+			q6asm_read(audio->ac); /* Push buffer to DSP */
+		rc = 0;
+		pr_debug("%s:session id %d: AUDIO_START success enable[%d]\n",
+				__func__, audio->ac->session, audio->enabled);
+		break;
+	}
+	case AUDIO_STOP: {
+		pr_debug("%s:AUDIO_STOP\n", __func__);
+		rc = audio_in_disable(audio);
+		if (rc  < 0) {
+			pr_err("%s:session id %d: Audio Stop procedure failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_AMRNB_ENC_CONFIG_V2: {
+		struct msm_audio_amrnb_enc_config_v2 *cfg;
+		struct msm_audio_amrnb_enc_config_v2 *enc_cfg;
+
+		cfg = (struct msm_audio_amrnb_enc_config_v2 *)arg;
+		if (cfg == NULL) {
+			pr_err("%s: NULL config pointer for %s\n",
+					__func__,
+					"AUDIO_SET_AMRNB_ENC_CONFIG_V2");
+			rc = -EINVAL;
+			break;
+		}
+
+		enc_cfg = audio->enc_cfg;
+		if (cfg->band_mode > 8 ||
+			 cfg->band_mode < 1) {
+			pr_err("%s:session id %d: invalid band mode\n",
+				__func__, audio->ac->session);
+			rc = -EINVAL;
+			break;
+		}
+		/* AMR NB encoder accepts values between 0-7
+		 * while openmax provides value between 1-8
+		 * as per spec
+		 */
+		enc_cfg->band_mode = (cfg->band_mode - 1);
+		enc_cfg->dtx_enable = (cfg->dtx_enable ? 1 : 0);
+		enc_cfg->frame_format = 0;
+		pr_debug("%s:session id %d: band_mode = 0x%x dtx_enable=0x%x\n",
+				__func__, audio->ac->session,
+				enc_cfg->band_mode, enc_cfg->dtx_enable);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static long amrnb_in_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc =  amrnb_in_ioctl_shared(file, cmd, NULL);
+		break;
+	}
+	case AUDIO_GET_AMRNB_ENC_CONFIG_V2: {
+		if (copy_to_user((void *)arg, audio->enc_cfg,
+			sizeof(struct msm_audio_amrnb_enc_config_v2))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AMRNB_ENC_CONFIG_V2 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_AMRNB_ENC_CONFIG_V2: {
+		struct msm_audio_amrnb_enc_config_v2 cfg;
+
+		if (copy_from_user(&cfg, (void *) arg,
+				sizeof(cfg))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AMRNB_ENC_CONFIG_V2 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = amrnb_in_ioctl_shared(file, cmd, &cfg);
+		if (rc)
+			pr_err("%s: AUDIO_SET_AMRNB_ENC_CONFIG_V2 failed. rc=%d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd=%d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_amrnb_enc_config_v2_32 {
+	u32 band_mode;
+	u32 dtx_enable;
+	u32 frame_format;
+};
+
+enum {
+	AUDIO_GET_AMRNB_ENC_CONFIG_V2_32 = _IOW(AUDIO_IOCTL_MAGIC,
+		(AUDIO_MAX_COMMON_IOCTL_NUM+2),
+		struct msm_audio_amrnb_enc_config_v2_32),
+	AUDIO_SET_AMRNB_ENC_CONFIG_V2_32 = _IOR(AUDIO_IOCTL_MAGIC,
+		(AUDIO_MAX_COMMON_IOCTL_NUM+3),
+		struct msm_audio_amrnb_enc_config_v2_32)
+};
+
+static long amrnb_in_compat_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc =  amrnb_in_ioctl_shared(file, cmd, NULL);
+		break;
+	}
+	case AUDIO_GET_AMRNB_ENC_CONFIG_V2_32: {
+		struct msm_audio_amrnb_enc_config_v2 *amrnb_config;
+		struct msm_audio_amrnb_enc_config_v2_32 amrnb_config_32;
+
+		memset(&amrnb_config_32, 0, sizeof(amrnb_config_32));
+
+		amrnb_config =
+		(struct msm_audio_amrnb_enc_config_v2 *)audio->enc_cfg;
+		amrnb_config_32.band_mode = amrnb_config->band_mode;
+		amrnb_config_32.dtx_enable = amrnb_config->dtx_enable;
+		amrnb_config_32.frame_format = amrnb_config->frame_format;
+
+		if (copy_to_user((void *)arg, &amrnb_config_32,
+			sizeof(amrnb_config_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AMRNB_ENC_CONFIG_V2_32 failed",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_AMRNB_ENC_CONFIG_V2_32: {
+		struct msm_audio_amrnb_enc_config_v2_32 cfg_32;
+
+		if (copy_from_user(&cfg_32, (void *) arg,
+				sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AMRNB_ENC_CONFIG_V2_32 failed\n",
+					__func__);
+			rc = -EFAULT;
+			break;
+		}
+		cmd = AUDIO_SET_AMRNB_ENC_CONFIG_V2;
+		rc = amrnb_in_ioctl_shared(file, cmd, &cfg_32);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AMRNB_ENC_CONFIG_V2 failed rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+#else
+#define amrnb_in_compat_ioctl NULL
+#endif
+
+static int amrnb_in_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_in *audio = NULL;
+	struct msm_audio_amrnb_enc_config_v2 *enc_cfg;
+	int rc = 0;
+
+	audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	/* Allocate memory for encoder config param */
+	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_amrnb_enc_config_v2),
+				GFP_KERNEL);
+	if (audio->enc_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+	enc_cfg = audio->enc_cfg;
+
+	mutex_init(&audio->lock);
+	mutex_init(&audio->read_lock);
+	mutex_init(&audio->write_lock);
+	spin_lock_init(&audio->dsp_lock);
+	init_waitqueue_head(&audio->read_wait);
+	init_waitqueue_head(&audio->write_wait);
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->str_cfg.buffer_size = FRAME_SIZE;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->min_frame_size = 32;
+	audio->max_frames_per_buf = 10;
+	audio->pcm_cfg.buffer_size = PCM_BUF_SIZE;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	enc_cfg->band_mode = 7;
+	enc_cfg->dtx_enable = 0;
+	audio->pcm_cfg.channel_count = 1;
+	audio->pcm_cfg.sample_rate = 8000;
+	audio->buf_cfg.meta_info_enable = 0x01;
+	audio->buf_cfg.frames_per_buf = 0x01;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb)q6asm_in_cb,
+				(void *)audio);
+
+	if (!audio->ac) {
+		pr_err("%s: Could not allocate memory for audio client\n",
+			__func__);
+		kfree(audio->enc_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open amrnb encoder in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) &&
+		(file->f_mode & FMODE_READ)) {
+		audio->feedback = NON_TUNNEL_MODE;
+		rc = q6asm_open_read_write(audio->ac, FORMAT_AMRNB,
+					FORMAT_LINEAR_PCM);
+		if (rc < 0) {
+			pr_err("%s:session id %d: NT mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		pr_info("%s:session id %d: NT mode encoder success\n",
+				__func__, audio->ac->session);
+	} else if (!(file->f_mode & FMODE_WRITE) &&
+				(file->f_mode & FMODE_READ)) {
+		audio->feedback = TUNNEL_MODE;
+		rc = q6asm_open_read(audio->ac, FORMAT_AMRNB);
+		if (rc < 0) {
+			pr_err("%s:session id %d: T mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		/* register for tx overflow (valid for tunnel mode only) */
+		rc = q6asm_reg_tx_overflow(audio->ac, 0x01);
+		if (rc < 0) {
+			pr_err("%s:session id %d: TX Overflow registration failed rc=%d\n",
+				__func__, audio->ac->session,
+				rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		pr_info("%s:session id %d: T mode encoder success\n",
+				__func__, audio->ac->session);
+	} else {
+		pr_err("%s:session id %d: Unexpected mode\n", __func__,
+				audio->ac->session);
+		rc = -EACCES;
+		goto fail;
+	}
+
+	audio->opened = 1;
+	atomic_set(&audio->in_count, PCM_BUF_COUNT);
+	atomic_set(&audio->out_count, 0x00);
+	audio->enc_compat_ioctl = amrnb_in_compat_ioctl;
+	audio->enc_ioctl = amrnb_in_ioctl;
+	file->private_data = audio;
+
+	pr_info("%s:session id %d: success\n", __func__, audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->enc_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_in_fops = {
+	.owner		= THIS_MODULE,
+	.open		= amrnb_in_open,
+	.release	= audio_in_release,
+	.read		= audio_in_read,
+	.write		= audio_in_write,
+	.unlocked_ioctl	= audio_in_ioctl,
+	.compat_ioctl   = audio_in_compat_ioctl
+};
+
+struct miscdevice audio_amrnb_in_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_amrnb_in",
+	.fops	= &audio_in_fops,
+};
+
+static int __init amrnb_in_init(void)
+{
+	return misc_register(&audio_amrnb_in_misc);
+}
+
+device_initcall(amrnb_in_init);

+ 400 - 0
drivers/misc/qcom/qdsp6v2/amrwb_in.c

@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2011-2012, 2014, 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/dma-mapping.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/msm_audio_amrwb.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <linux/compat.h>
+#include <linux/atomic.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+/* Buffer with meta*/
+#define PCM_BUF_SIZE		(4096 + sizeof(struct meta_in))
+
+/* Maximum 10 frames in buffer with meta */
+#define FRAME_SIZE		(1 + ((61+sizeof(struct meta_out_dsp)) * 10))
+
+static long amrwb_in_ioctl_shared(struct file *file,
+				  unsigned int cmd, void *arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+	int cnt = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct msm_audio_amrwb_enc_config *enc_cfg;
+
+		enc_cfg = audio->enc_cfg;
+		pr_debug("%s:session id %d: default buf alloc[%d]\n", __func__,
+				audio->ac->session, audio->buf_alloc);
+		if (audio->enabled == 1) {
+			pr_info("%s:AUDIO_START already over\n", __func__);
+			rc = 0;
+			break;
+		}
+		rc = audio_in_buf_alloc(audio);
+		if (rc < 0) {
+			pr_err("%s:session id %d: buffer allocation failed\n",
+				__func__, audio->ac->session);
+			break;
+		}
+
+		rc = q6asm_enc_cfg_blk_amrwb(audio->ac,
+			audio->buf_cfg.frames_per_buf,
+			enc_cfg->band_mode,
+			enc_cfg->dtx_enable);
+
+		if (rc < 0) {
+			pr_err("%s:session id %d: cmd amrwb media format block failed\n",
+				__func__, audio->ac->session);
+			break;
+		}
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			rc = q6asm_media_format_block_pcm(audio->ac,
+				audio->pcm_cfg.sample_rate,
+				audio->pcm_cfg.channel_count);
+
+			if (rc < 0) {
+				pr_err("%s:session id %d: media format block failed\n",
+				__func__, audio->ac->session);
+				break;
+			}
+		}
+		pr_debug("%s:session id %d: AUDIO_START enable[%d]\n",
+				__func__, audio->ac->session,
+				audio->enabled);
+		rc = audio_in_enable(audio);
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s:session id %d: Audio Start procedure failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			break;
+		}
+		while (cnt++ < audio->str_cfg.buffer_count)
+			q6asm_read(audio->ac); /* Push buffer to DSP */
+		rc = 0;
+		pr_debug("%s:session id %d: AUDIO_START success enable[%d]\n",
+				__func__, audio->ac->session, audio->enabled);
+		break;
+	}
+	case AUDIO_STOP: {
+		pr_debug("%s:AUDIO_STOP\n", __func__);
+		rc = audio_in_disable(audio);
+		if (rc  < 0) {
+			pr_err("%s:session id %d: Audio Stop procedure failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_AMRWB_ENC_CONFIG: {
+		struct msm_audio_amrwb_enc_config *cfg;
+		struct msm_audio_amrwb_enc_config *enc_cfg;
+
+		enc_cfg = audio->enc_cfg;
+		cfg = (struct msm_audio_amrwb_enc_config *)arg;
+		if (cfg == NULL) {
+			pr_err("%s: NULL config pointer for %s\n",
+					__func__, "AUDIO_SET_AMRWB_ENC_CONFIG");
+			rc = -EINVAL;
+			break;
+		}
+
+		if (cfg->band_mode > 8) {
+			pr_err("%s:session id %d: invalid band mode\n",
+				__func__, audio->ac->session);
+			rc = -EINVAL;
+			break;
+		}
+		/* ToDo: AMR WB encoder accepts values between 0-8
+		 * while openmax provides value between 9-17
+		 * as per spec
+		 */
+		enc_cfg->band_mode = cfg->band_mode;
+		enc_cfg->dtx_enable = (cfg->dtx_enable ? 1 : 0);
+		/* Currently DSP does not support different frameformat */
+		enc_cfg->frame_format = 0;
+		pr_debug("%s:session id %d: band_mode = 0x%x dtx_enable=0x%x\n",
+				__func__, audio->ac->session,
+				enc_cfg->band_mode, enc_cfg->dtx_enable);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static long amrwb_in_ioctl(struct file *file,
+				  unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = amrwb_in_ioctl_shared(file, cmd, NULL);
+		break;
+	}
+	case AUDIO_GET_AMRWB_ENC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->enc_cfg,
+				sizeof(struct msm_audio_amrwb_enc_config)))
+			pr_err("%s: copy_to_user for AUDIO_GET_AMRWB_ENC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		break;
+	}
+	case AUDIO_SET_AMRWB_ENC_CONFIG: {
+		struct msm_audio_amrwb_enc_config cfg;
+
+		if (copy_from_user(&cfg, (void *) arg,
+				sizeof(cfg))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AMRWB_ENC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = amrwb_in_ioctl_shared(file, cmd, &cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_ENC_CONFIG failed. rc=%d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_amrwb_enc_config_32 {
+	u32 band_mode;
+	u32 dtx_enable;
+	u32 frame_format;
+};
+
+enum {
+	AUDIO_GET_AMRWB_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+		(AUDIO_MAX_COMMON_IOCTL_NUM+0),
+		struct msm_audio_amrwb_enc_config_32),
+	AUDIO_SET_AMRWB_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+		(AUDIO_MAX_COMMON_IOCTL_NUM+1),
+		struct msm_audio_amrwb_enc_config_32)
+};
+
+static long amrwb_in_compat_ioctl(struct file *file,
+				  unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = amrwb_in_ioctl_shared(file, cmd, NULL);
+		break;
+	}
+	case AUDIO_GET_AMRWB_ENC_CONFIG_32: {
+		struct msm_audio_amrwb_enc_config *amrwb_config;
+		struct msm_audio_amrwb_enc_config_32 amrwb_config_32;
+
+		memset(&amrwb_config_32, 0, sizeof(amrwb_config_32));
+
+		amrwb_config =
+		(struct msm_audio_amrwb_enc_config *)audio->enc_cfg;
+		amrwb_config_32.band_mode = amrwb_config->band_mode;
+		amrwb_config_32.dtx_enable = amrwb_config->dtx_enable;
+		amrwb_config_32.frame_format = amrwb_config->frame_format;
+
+		if (copy_to_user((void *)arg, &amrwb_config_32,
+			sizeof(struct msm_audio_amrwb_enc_config_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AMRWB_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_AMRWB_ENC_CONFIG_32: {
+		struct msm_audio_amrwb_enc_config cfg_32;
+
+		if (copy_from_user(&cfg_32, (void *) arg,
+				sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AMRWB_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		cmd = AUDIO_SET_AMRWB_ENC_CONFIG;
+		rc = amrwb_in_ioctl_shared(file, cmd, &cfg_32);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_ENC_CONFIG failed. rc=%d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+#else
+#define amrwb_in_compat_ioctl NULL
+#endif
+
+static int amrwb_in_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_in *audio = NULL;
+	struct msm_audio_amrwb_enc_config *enc_cfg;
+	int rc = 0;
+
+	audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	/* Allocate memory for encoder config param */
+	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_amrwb_enc_config),
+				GFP_KERNEL);
+	if (audio->enc_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+	enc_cfg = audio->enc_cfg;
+
+	mutex_init(&audio->lock);
+	mutex_init(&audio->read_lock);
+	mutex_init(&audio->write_lock);
+	spin_lock_init(&audio->dsp_lock);
+	init_waitqueue_head(&audio->read_wait);
+	init_waitqueue_head(&audio->write_wait);
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->str_cfg.buffer_size = FRAME_SIZE;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->min_frame_size = 32;
+	audio->max_frames_per_buf = 10;
+	audio->pcm_cfg.buffer_size = PCM_BUF_SIZE;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	enc_cfg->band_mode = 8;
+	enc_cfg->dtx_enable = 0;
+	audio->pcm_cfg.channel_count = 1;
+	audio->pcm_cfg.sample_rate = 16000;
+	audio->buf_cfg.meta_info_enable = 0x01;
+	audio->buf_cfg.frames_per_buf = 0x01;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb)q6asm_in_cb,
+				(void *)audio);
+
+	if (!audio->ac) {
+		pr_err("%s:audio[%pK]: Could not allocate memory for audio client\n",
+			__func__, audio);
+		kfree(audio->enc_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open amrwb encoder in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) &&
+		(file->f_mode & FMODE_READ)) {
+		audio->feedback = NON_TUNNEL_MODE;
+		rc = q6asm_open_read_write(audio->ac, FORMAT_AMRWB,
+					FORMAT_LINEAR_PCM);
+		if (rc < 0) {
+			pr_err("%s:session id %d: NT mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		pr_info("%s:session id %d: NT mode encoder success\n",
+				__func__, audio->ac->session);
+	} else if (!(file->f_mode & FMODE_WRITE) &&
+				(file->f_mode & FMODE_READ)) {
+		audio->feedback = TUNNEL_MODE;
+		rc = q6asm_open_read(audio->ac, FORMAT_AMRWB);
+		if (rc < 0) {
+			pr_err("%s:session id %d: T mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		/* register for tx overflow (valid for tunnel mode only) */
+		rc = q6asm_reg_tx_overflow(audio->ac, 0x01);
+		if (rc < 0) {
+			pr_err("%s:session id %d: TX Overflow registration failed rc=%d\n",
+				__func__, audio->ac->session,
+				rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		pr_info("%s:session id %d: T mode encoder success\n",
+				__func__, audio->ac->session);
+	} else {
+		pr_err("%s:session id %d: Unexpected mode\n", __func__,
+				audio->ac->session);
+		rc = -EACCES;
+		goto fail;
+	}
+
+	audio->opened = 1;
+	atomic_set(&audio->in_count, PCM_BUF_COUNT);
+	atomic_set(&audio->out_count, 0x00);
+	audio->enc_compat_ioctl = amrwb_in_compat_ioctl;
+	audio->enc_ioctl = amrwb_in_ioctl;
+	file->private_data = audio;
+
+	pr_info("%s:session id %d: success\n", __func__, audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->enc_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_in_fops = {
+	.owner		= THIS_MODULE,
+	.open		= amrwb_in_open,
+	.release	= audio_in_release,
+	.read		= audio_in_read,
+	.write		= audio_in_write,
+	.unlocked_ioctl	= audio_in_ioctl,
+	.compat_ioctl   = audio_in_compat_ioctl
+};
+
+struct miscdevice audio_amrwb_in_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_amrwb_in",
+	.fops	= &audio_in_fops,
+};
+
+static int __init amrwb_in_init(void)
+{
+	return misc_register(&audio_amrwb_in_misc);
+}
+
+device_initcall(amrwb_in_init);

+ 474 - 0
drivers/misc/qcom/qdsp6v2/audio_aac.c

@@ -0,0 +1,474 @@
+/* aac audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/msm_audio_aac.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+#define AUDIO_AAC_DUAL_MONO_INVALID -1
+#define PCM_BUFSZ_MIN_AAC	((8*1024) + sizeof(struct dec_meta_out))
+
+static struct miscdevice audio_aac_misc;
+static struct ws_mgr audio_aac_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_aac_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+				void *arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct asm_aac_cfg aac_cfg;
+		struct msm_audio_aac_config *aac_config;
+		uint32_t sbr_ps = 0x00;
+
+		pr_debug("%s: AUDIO_START session_id[%d]\n", __func__,
+							audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac, 0, 0);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+		/* turn on both sbr and ps */
+		rc = q6asm_enable_sbrps(audio->ac, sbr_ps);
+		if (rc < 0)
+			pr_err("sbr-ps enable failed\n");
+		aac_config = (struct msm_audio_aac_config *)audio->codec_cfg;
+		if (aac_config->sbr_ps_on_flag)
+			aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
+		else if (aac_config->sbr_on_flag)
+			aac_cfg.aot = AAC_ENC_MODE_AAC_P;
+		else
+			aac_cfg.aot = AAC_ENC_MODE_AAC_LC;
+
+		switch (aac_config->format) {
+		case AUDIO_AAC_FORMAT_ADTS:
+			aac_cfg.format = 0x00;
+			break;
+		case AUDIO_AAC_FORMAT_LOAS:
+			aac_cfg.format = 0x01;
+			break;
+		case AUDIO_AAC_FORMAT_ADIF:
+			aac_cfg.format = 0x02;
+			break;
+		default:
+		case AUDIO_AAC_FORMAT_RAW:
+			aac_cfg.format = 0x03;
+		}
+		aac_cfg.ep_config = aac_config->ep_config;
+		aac_cfg.section_data_resilience =
+			aac_config->aac_section_data_resilience_flag;
+		aac_cfg.scalefactor_data_resilience =
+			aac_config->aac_scalefactor_data_resilience_flag;
+		aac_cfg.spectral_data_resilience =
+			aac_config->aac_spectral_data_resilience_flag;
+		aac_cfg.ch_cfg = audio->pcm_cfg.channel_count;
+		if (audio->feedback == TUNNEL_MODE) {
+			aac_cfg.sample_rate = aac_config->sample_rate;
+			aac_cfg.ch_cfg = aac_config->channel_configuration;
+		} else {
+			aac_cfg.sample_rate =  audio->pcm_cfg.sample_rate;
+			aac_cfg.ch_cfg = audio->pcm_cfg.channel_count;
+		}
+
+		pr_debug("%s:format=%x aot=%d  ch=%d sr=%d\n",
+			__func__, aac_cfg.format,
+			aac_cfg.aot, aac_cfg.ch_cfg,
+			aac_cfg.sample_rate);
+
+		/* Configure Media format block */
+		rc = q6asm_media_format_block_aac(audio->ac, &aac_cfg);
+		if (rc < 0) {
+			pr_err("cmd media format block failed\n");
+			break;
+		}
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			rc = enable_volume_ramp(audio);
+			if (rc < 0) {
+				pr_err("%s: Failed to enable volume ramp\n",
+					__func__);
+			}
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_info("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+						audio->ac->session,
+						audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	case AUDIO_SET_AAC_CONFIG: {
+		struct msm_audio_aac_config *aac_config;
+		uint16_t sce_left = 1, sce_right = 2;
+
+		pr_debug("%s: AUDIO_SET_AAC_CONFIG\n", __func__);
+		aac_config = (struct msm_audio_aac_config *)arg;
+		if (aac_config == NULL) {
+			pr_err("%s: Invalid config pointer\n", __func__);
+			rc = -EINVAL;
+			break;
+		}
+		memcpy(audio->codec_cfg, aac_config,
+				sizeof(struct msm_audio_aac_config));
+		/* PL_PR is 0 only need to check PL_SR */
+		if (aac_config->dual_mono_mode >
+		    AUDIO_AAC_DUAL_MONO_PL_SR) {
+			pr_err("%s:Invalid dual_mono mode =%d\n", __func__,
+			aac_config->dual_mono_mode);
+		} else {
+			/* convert the data from user into sce_left
+			 * and sce_right based on the definitions
+			 */
+			pr_debug("%s: modify dual_mono mode =%d\n", __func__,
+				 aac_config->dual_mono_mode);
+			switch (aac_config->dual_mono_mode) {
+			case AUDIO_AAC_DUAL_MONO_PL_PR:
+				sce_left = 1;
+				sce_right = 1;
+				break;
+			case AUDIO_AAC_DUAL_MONO_SL_SR:
+				sce_left = 2;
+				sce_right = 2;
+				break;
+			case AUDIO_AAC_DUAL_MONO_SL_PR:
+				sce_left = 2;
+				sce_right = 1;
+				break;
+			case AUDIO_AAC_DUAL_MONO_PL_SR:
+			default:
+				sce_left = 1;
+				sce_right = 2;
+				break;
+			}
+			rc = q6asm_cfg_dual_mono_aac(audio->ac,
+						sce_left, sce_right);
+			if (rc < 0)
+				pr_err("%s:asm cmd dualmono failed rc=%d\n",
+					 __func__, rc);
+		}
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		break;
+	}
+	return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_AAC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->codec_cfg,
+			sizeof(struct msm_audio_aac_config))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_AAC_CONFIG: {
+		struct msm_audio_aac_config aac_config;
+
+		pr_debug("%s: AUDIO_SET_AAC_CONFIG\n", __func__);
+		if (copy_from_user(&aac_config, (void *)arg,
+			sizeof(aac_config))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AAC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = audio_ioctl_shared(file, cmd, &aac_config);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n",
+						__func__, rc);
+		break;
+	}
+	default: {
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("%s[%pK]:Failed in utils_ioctl: %d\n",
+				__func__, audio, rc);
+	}
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_aac_config32 {
+	s16 format;
+	u16 audio_object;
+	u16 ep_config;	/* 0 ~ 3 useful only obj = ERLC */
+	u16 aac_section_data_resilience_flag;
+	u16 aac_scalefactor_data_resilience_flag;
+	u16 aac_spectral_data_resilience_flag;
+	u16 sbr_on_flag;
+	u16 sbr_ps_on_flag;
+	u16 dual_mono_mode;
+	u16 channel_configuration;
+	u16 sample_rate;
+};
+
+enum {
+	AUDIO_SET_AAC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_aac_config32),
+	AUDIO_GET_AAC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_aac_config32)
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_AAC_CONFIG_32: {
+		struct msm_audio_aac_config *aac_config;
+		struct msm_audio_aac_config32 aac_config_32;
+
+		aac_config = (struct msm_audio_aac_config *)audio->codec_cfg;
+		aac_config_32.format = aac_config->format;
+		aac_config_32.audio_object = aac_config->audio_object;
+		aac_config_32.ep_config = aac_config->ep_config;
+		aac_config_32.aac_section_data_resilience_flag =
+			aac_config->aac_section_data_resilience_flag;
+		aac_config_32.aac_scalefactor_data_resilience_flag =
+			 aac_config->aac_scalefactor_data_resilience_flag;
+		aac_config_32.aac_spectral_data_resilience_flag =
+			aac_config->aac_spectral_data_resilience_flag;
+		aac_config_32.sbr_on_flag = aac_config->sbr_on_flag;
+		aac_config_32.sbr_ps_on_flag = aac_config->sbr_ps_on_flag;
+		aac_config_32.dual_mono_mode = aac_config->dual_mono_mode;
+		aac_config_32.channel_configuration =
+					aac_config->channel_configuration;
+		aac_config_32.sample_rate = aac_config->sample_rate;
+
+		if (copy_to_user((void *)arg, &aac_config_32,
+			sizeof(aac_config_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_AAC_CONFIG_32: {
+		struct msm_audio_aac_config aac_config;
+		struct msm_audio_aac_config32 aac_config_32;
+
+		pr_debug("%s: AUDIO_SET_AAC_CONFIG\n", __func__);
+		if (copy_from_user(&aac_config_32, (void *)arg,
+			sizeof(aac_config_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AAC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		aac_config.format = aac_config_32.format;
+		aac_config.audio_object = aac_config_32.audio_object;
+		aac_config.ep_config = aac_config_32.ep_config;
+		aac_config.aac_section_data_resilience_flag =
+			aac_config_32.aac_section_data_resilience_flag;
+		aac_config.aac_scalefactor_data_resilience_flag =
+			aac_config_32.aac_scalefactor_data_resilience_flag;
+		aac_config.aac_spectral_data_resilience_flag =
+			aac_config_32.aac_spectral_data_resilience_flag;
+		aac_config.sbr_on_flag = aac_config_32.sbr_on_flag;
+		aac_config.sbr_ps_on_flag = aac_config_32.sbr_ps_on_flag;
+		aac_config.dual_mono_mode = aac_config_32.dual_mono_mode;
+		aac_config.channel_configuration =
+				aac_config_32.channel_configuration;
+		aac_config.sample_rate = aac_config_32.sample_rate;
+
+		cmd = AUDIO_SET_AAC_CONFIG;
+		rc = audio_ioctl_shared(file, cmd, &aac_config);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default: {
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("%s[%pK]:Failed in utils_ioctl: %d\n",
+				__func__, audio, rc);
+	}
+	}
+	return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+	struct msm_audio_aac_config *aac_config = NULL;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_aac_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	audio->codec_cfg = kzalloc(sizeof(struct msm_audio_aac_config),
+					GFP_KERNEL);
+	if (audio->codec_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+	aac_config = audio->codec_cfg;
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN_AAC;
+	audio->miscdevice = &audio_aac_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_aac_ws_mgr;
+	aac_config->dual_mono_mode = AUDIO_AAC_DUAL_MONO_INVALID;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio->codec_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_MPEG4_AAC);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		/* open AAC decoder, expected frames is always 1
+		 * audio->buf_cfg.frames_per_buf = 0x01;
+		 */
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_MPEG4_AAC);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof(name), "msm_aac_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
+					    NULL, (void *)audio,
+					    &audio_aac_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:aacdec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_aac_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+	.compat_ioctl = audio_compat_ioctl
+};
+
+static struct miscdevice audio_aac_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_aac",
+	.fops = &audio_aac_fops,
+};
+
+static int __init audio_aac_init(void)
+{
+	int ret = misc_register(&audio_aac_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_aac_misc.this_device, true);
+	audio_aac_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_aac_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_aac_init);

+ 435 - 0
drivers/misc/qcom/qdsp6v2/audio_alac.c

@@ -0,0 +1,435 @@
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/types.h>
+#include <linux/msm_audio_alac.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_alac_misc;
+static struct ws_mgr audio_alac_ws_mgr;
+
+static const struct file_operations audio_alac_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+
+static struct dentry *config_debugfs_create_file(const char *name, void *data)
+{
+	return debugfs_create_file(name, S_IFREG | 0444,
+				NULL, (void *)data, &audio_alac_debug_fops);
+}
+
+static int alac_channel_map(u8 *channel_mapping, uint32_t channels);
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+						void *arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct asm_alac_cfg alac_cfg;
+		struct msm_audio_alac_config *alac_config;
+		u8 channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+
+		memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+
+		if (alac_channel_map(channel_mapping,
+			audio->pcm_cfg.channel_count)) {
+			pr_err("%s: setting channel map failed %d\n",
+					__func__, audio->pcm_cfg.channel_count);
+		}
+
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm_v2(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count,
+					16, /*bits per sample*/
+					false, false, channel_mapping);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+		alac_config = (struct msm_audio_alac_config *)audio->codec_cfg;
+		alac_cfg.frame_length = alac_config->frameLength;
+		alac_cfg.compatible_version = alac_config->compatVersion;
+		alac_cfg.bit_depth = alac_config->bitDepth;
+		alac_cfg.pb = alac_config->pb;
+		alac_cfg.mb = alac_config->mb;
+		alac_cfg.kb = alac_config->kb;
+		alac_cfg.num_channels = alac_config->channelCount;
+		alac_cfg.max_run = alac_config->maxRun;
+		alac_cfg.max_frame_bytes = alac_config->maxSize;
+		alac_cfg.avg_bit_rate = alac_config->averageBitRate;
+		alac_cfg.sample_rate = alac_config->sampleRate;
+		alac_cfg.channel_layout_tag = alac_config->channelLayout;
+		pr_debug("%s: frame_length %d compatible_version %d bit_depth %d pb %d mb %d kb %d num_channels %d max_run %d max_frame_bytes %d avg_bit_rate %d sample_rate %d channel_layout_tag %d\n",
+				__func__, alac_config->frameLength,
+				alac_config->compatVersion,
+				alac_config->bitDepth, alac_config->pb,
+				alac_config->mb, alac_config->kb,
+				alac_config->channelCount, alac_config->maxRun,
+				alac_config->maxSize,
+				alac_config->averageBitRate,
+				alac_config->sampleRate,
+				alac_config->channelLayout);
+		/* Configure Media format block */
+		rc = q6asm_media_format_block_alac(audio->ac, &alac_cfg,
+							audio->ac->stream_id);
+		if (rc < 0) {
+			pr_err("cmd media format block failed\n");
+			break;
+		}
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("AUDIO_START success enable[%d]\n", audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		break;
+	}
+	return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_ALAC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->codec_cfg,
+			sizeof(struct msm_audio_alac_config))) {
+			pr_err("%s:copy_to_user for AUDIO_GET_ALAC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_ALAC_CONFIG: {
+		if (copy_from_user(audio->codec_cfg, (void *)arg,
+			sizeof(struct msm_audio_alac_config))) {
+			pr_err("%s:copy_from_user for AUDIO_SET_ALAC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	default: {
+		rc = audio->codec_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("Failed in utils_ioctl: %d\n", rc);
+		break;
+	}
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_alac_config_32 {
+	u32 frameLength;
+	u8 compatVersion;
+	u8 bitDepth;
+	u8 pb;
+	u8 mb;
+	u8 kb;
+	u8 channelCount;
+	u16 maxRun;
+	u32 maxSize;
+	u32 averageBitRate;
+	u32 sampleRate;
+	u32 channelLayout;
+};
+
+enum {
+	AUDIO_GET_ALAC_CONFIG_32 =  _IOR(AUDIO_IOCTL_MAGIC,
+	(AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_alac_config_32),
+	AUDIO_SET_ALAC_CONFIG_32 =  _IOW(AUDIO_IOCTL_MAGIC,
+	(AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_alac_config_32)
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+						unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_ALAC_CONFIG_32: {
+		struct msm_audio_alac_config *alac_config;
+		struct msm_audio_alac_config_32 alac_config_32;
+
+		memset(&alac_config_32, 0, sizeof(alac_config_32));
+
+		alac_config = (struct msm_audio_alac_config *)audio->codec_cfg;
+		alac_config_32.frameLength = alac_config->frameLength;
+		alac_config_32.compatVersion =
+				alac_config->compatVersion;
+		alac_config_32.bitDepth = alac_config->bitDepth;
+		alac_config_32.pb = alac_config->pb;
+		alac_config_32.mb = alac_config->mb;
+		alac_config_32.kb = alac_config->kb;
+		alac_config_32.channelCount = alac_config->channelCount;
+		alac_config_32.maxRun = alac_config->maxRun;
+		alac_config_32.maxSize = alac_config->maxSize;
+		alac_config_32.averageBitRate = alac_config->averageBitRate;
+		alac_config_32.sampleRate = alac_config->sampleRate;
+		alac_config_32.channelLayout = alac_config->channelLayout;
+
+		if (copy_to_user((void *)arg, &alac_config_32,
+			sizeof(alac_config_32))) {
+			pr_err("%s: copy_to_user for GET_ALAC_CONFIG_32 failed\n",
+				 __func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_ALAC_CONFIG_32: {
+		struct msm_audio_alac_config *alac_config;
+		struct msm_audio_alac_config_32 alac_config_32;
+
+		if (copy_from_user(&alac_config_32, (void *)arg,
+			sizeof(alac_config_32))) {
+			pr_err("%s: copy_from_user for SET_ALAC_CONFIG_32 failed\n"
+				, __func__);
+			rc = -EFAULT;
+			break;
+		}
+		alac_config = (struct msm_audio_alac_config *)audio->codec_cfg;
+		alac_config->frameLength = alac_config_32.frameLength;
+		alac_config->compatVersion =
+				alac_config_32.compatVersion;
+		alac_config->bitDepth = alac_config_32.bitDepth;
+		alac_config->pb = alac_config_32.pb;
+		alac_config->mb = alac_config_32.mb;
+		alac_config->kb = alac_config_32.kb;
+		alac_config->channelCount = alac_config_32.channelCount;
+		alac_config->maxRun = alac_config_32.maxRun;
+		alac_config->maxSize = alac_config_32.maxSize;
+		alac_config->averageBitRate = alac_config_32.averageBitRate;
+		alac_config->sampleRate = alac_config_32.sampleRate;
+		alac_config->channelLayout = alac_config_32.channelLayout;
+
+		break;
+	}
+	default: {
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("Failed in utils_ioctl: %d\n", rc);
+		break;
+	}
+	}
+	return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_alac_" + 5];
+
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+	if (!audio)
+		return -ENOMEM;
+
+	audio->codec_cfg = kzalloc(sizeof(struct msm_audio_alac_config),
+					GFP_KERNEL);
+	if (!audio->codec_cfg) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_alac_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_alac_ws_mgr;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio->codec_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_ALAC);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		/* open ALAC decoder, expected frames is always 1*/
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_ALAC);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+	snprintf(name, sizeof(name), "msm_alac_%04x", audio->ac->session);
+	audio->dentry = config_debugfs_create_file(name, (void *)audio);
+
+	if (IS_ERR_OR_NULL(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+	pr_debug("%s:alacdec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static int alac_channel_map(u8 *channel_mapping, uint32_t channels)
+{
+	u8 *lchannel_mapping;
+
+	lchannel_mapping = channel_mapping;
+	pr_debug("%s:  channels passed: %d\n", __func__, channels);
+	if (channels == 1)  {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+	} else if (channels == 2) {
+		lchannel_mapping[0] = PCM_CHANNEL_FL;
+		lchannel_mapping[1] = PCM_CHANNEL_FR;
+	} else if (channels == 3) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+	} else if (channels == 4) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_CS;
+	} else if (channels == 5) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_LS;
+		lchannel_mapping[4] = PCM_CHANNEL_RS;
+	} else if (channels == 6) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_LS;
+		lchannel_mapping[4] = PCM_CHANNEL_RS;
+		lchannel_mapping[5] = PCM_CHANNEL_LFE;
+	} else if (channels == 7) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_LS;
+		lchannel_mapping[4] = PCM_CHANNEL_RS;
+		lchannel_mapping[5] = PCM_CHANNEL_CS;
+		lchannel_mapping[6] = PCM_CHANNEL_LFE;
+	} else if (channels == 8) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FLC;
+		lchannel_mapping[2] = PCM_CHANNEL_FRC;
+		lchannel_mapping[3] = PCM_CHANNEL_FL;
+		lchannel_mapping[4] = PCM_CHANNEL_FR;
+		lchannel_mapping[5] = PCM_CHANNEL_LS;
+		lchannel_mapping[6] = PCM_CHANNEL_RS;
+		lchannel_mapping[7] = PCM_CHANNEL_LFE;
+	} else {
+		pr_err("%s: ERROR.unsupported num_ch = %u\n",
+				__func__, channels);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct file_operations audio_alac_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+	.compat_ioctl = audio_compat_ioctl
+};
+
+static struct miscdevice audio_alac_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_alac",
+	.fops = &audio_alac_fops,
+};
+
+static int __init audio_alac_init(void)
+{
+	int ret = misc_register(&audio_alac_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_alac_misc.this_device, true);
+	audio_alac_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_alac_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_alac_init);

+ 226 - 0
drivers/misc/qcom/qdsp6v2/audio_amrnb.c

@@ -0,0 +1,226 @@
+/* amrnb audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/types.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_amrnb_misc;
+static struct ws_mgr audio_amrnb_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_amrnb_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("AUDIO_START success enable[%d]\n", audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+				audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("%s: pcm output block config failed rc=%d\n",
+					__func__, rc);
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s: Audio Start procedure failed rc=%d\n",
+				__func__, rc);
+			break;
+		}
+		pr_debug("AUDIO_START success enable[%d]\n", audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%pK]: Calling compat ioctl\n", __func__, audio);
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_amrnb_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_amrnb_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_amrnb_ws_mgr;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_AMRNB);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_AMRNB);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof(name), "msm_amrnb_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
+					    NULL, (void *)audio,
+					    &audio_amrnb_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:amrnb decoder open success, session_id = %d\n", __func__,
+				audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_amrnb_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+	.compat_ioctl = audio_compat_ioctl,
+};
+
+static struct miscdevice audio_amrnb_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_amrnb",
+	.fops = &audio_amrnb_fops,
+};
+
+static int __init audio_amrnb_init(void)
+{
+	int ret = misc_register(&audio_amrnb_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_amrnb_misc.this_device, true);
+	audio_amrnb_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_amrnb_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_amrnb_init);

+ 231 - 0
drivers/misc/qcom/qdsp6v2/audio_amrwb.c

@@ -0,0 +1,231 @@
+/* amrwb audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/compat.h>
+#include <linux/types.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_amrwb_misc;
+static struct ws_mgr audio_amrwb_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_amrwb_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+						audio->ac->session,
+						audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+				audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("%s: pcm output block config failed rc=%d\n",
+					__func__, rc);
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s: Audio Start procedure failed rc=%d\n",
+				__func__, rc);
+			break;
+		}
+		pr_debug("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+				audio->ac->session,
+				audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%pK]: Calling compat ioctl\n", __func__, audio);
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_amrwb_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_amrwb_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_amrwb_ws_mgr;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_AMRWB);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_AMRWB);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof(name), "msm_amrwb_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
+					    NULL, (void *)audio,
+					    &audio_amrwb_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s: AMRWB dec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_amrwb_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+	.compat_ioctl = audio_compat_ioctl,
+};
+
+static struct miscdevice audio_amrwb_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_amrwb",
+	.fops = &audio_amrwb_fops,
+};
+
+static int __init audio_amrwb_init(void)
+{
+	int ret = misc_register(&audio_amrwb_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_amrwb_misc.this_device, true);
+	audio_amrwb_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_amrwb_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_amrwb_init);

+ 397 - 0
drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c

@@ -0,0 +1,397 @@
+/* amr-wbplus audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/msm_audio_amrwbplus.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_amrwbplus_misc;
+static struct ws_mgr audio_amrwbplus_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_amrwbplus_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+static void config_debug_fs(struct q6audio_aio *audio)
+{
+	if (audio != NULL) {
+		char name[sizeof("msm_amrwbplus_") + 5];
+
+		snprintf(name, sizeof(name), "msm_amrwbplus_%04x",
+			audio->ac->session);
+		audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
+						NULL, (void *)audio,
+						&audio_amrwbplus_debug_fops);
+		if (IS_ERR(audio->dentry))
+			pr_debug("debugfs_create_file failed\n");
+	}
+}
+#else
+static void config_debug_fs(struct q6audio_aio *audio)
+{
+}
+#endif
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+					void *arg)
+{
+	struct asm_amrwbplus_cfg q6_amrwbplus_cfg;
+	struct msm_audio_amrwbplus_config_v2 *amrwbplus_drv_config;
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+		pr_err("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+			audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+			audio->pcm_cfg.sample_rate,
+			audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+		amrwbplus_drv_config =
+		(struct msm_audio_amrwbplus_config_v2 *)audio->codec_cfg;
+
+		q6_amrwbplus_cfg.size_bytes     =
+			amrwbplus_drv_config->size_bytes;
+		q6_amrwbplus_cfg.version        =
+			amrwbplus_drv_config->version;
+		q6_amrwbplus_cfg.num_channels   =
+			amrwbplus_drv_config->num_channels;
+		q6_amrwbplus_cfg.amr_band_mode  =
+			amrwbplus_drv_config->amr_band_mode;
+		q6_amrwbplus_cfg.amr_dtx_mode   =
+			amrwbplus_drv_config->amr_dtx_mode;
+		q6_amrwbplus_cfg.amr_frame_fmt  =
+			amrwbplus_drv_config->amr_frame_fmt;
+		q6_amrwbplus_cfg.amr_lsf_idx    =
+			amrwbplus_drv_config->amr_lsf_idx;
+
+		rc = q6asm_media_format_block_amrwbplus(audio->ac,
+							&q6_amrwbplus_cfg);
+		if (rc < 0) {
+			pr_err("q6asm_media_format_block_amrwb+ failed...\n");
+			break;
+		}
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("%s:AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+			audio->ac->session,
+			audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+
+		break;
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd,
+						unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_AMRWBPLUS_CONFIG_V2: {
+		if ((audio) && (arg) && (audio->codec_cfg)) {
+			if (copy_to_user((void *)arg, audio->codec_cfg,
+				sizeof(struct msm_audio_amrwbplus_config_v2))) {
+				rc = -EFAULT;
+				pr_err("%s: copy_to_user for AUDIO_GET_AMRWBPLUS_CONFIG_V2 failed\n",
+					__func__);
+				break;
+			}
+			} else {
+				pr_err("%s: wb+ config v2 invalid parameters\n"
+					, __func__);
+				rc = -EFAULT;
+				break;
+			}
+		break;
+	}
+	case AUDIO_SET_AMRWBPLUS_CONFIG_V2: {
+		if ((audio) && (arg) && (audio->codec_cfg)) {
+			if (copy_from_user(audio->codec_cfg, (void *)arg,
+				sizeof(struct msm_audio_amrwbplus_config_v2))) {
+				rc = -EFAULT;
+				pr_err("%s: copy_from_user for AUDIO_SET_AMRWBPLUS_CONFIG_V2 failed\n",
+					__func__);
+				break;
+			}
+			} else {
+				pr_err("%s: wb+ config invalid parameters\n",
+					__func__);
+				rc = -EFAULT;
+				break;
+			}
+		break;
+	}
+	default: {
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+		break;
+	}
+	}
+	return rc;
+}
+#ifdef CONFIG_COMPAT
+struct msm_audio_amrwbplus_config_v2_32 {
+	u32 size_bytes;
+	u32 version;
+	u32 num_channels;
+	u32 amr_band_mode;
+	u32 amr_dtx_mode;
+	u32 amr_frame_fmt;
+	u32 amr_lsf_idx;
+};
+
+enum {
+	AUDIO_GET_AMRWBPLUS_CONFIG_V2_32 = _IOR(AUDIO_IOCTL_MAGIC,
+		(AUDIO_MAX_COMMON_IOCTL_NUM+2),
+		struct msm_audio_amrwbplus_config_v2_32),
+	AUDIO_SET_AMRWBPLUS_CONFIG_V2_32 = _IOW(AUDIO_IOCTL_MAGIC,
+		(AUDIO_MAX_COMMON_IOCTL_NUM+3),
+		struct msm_audio_amrwbplus_config_v2_32)
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+					unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_AMRWBPLUS_CONFIG_V2_32: {
+		if (audio && arg && (audio->codec_cfg)) {
+			struct msm_audio_amrwbplus_config_v2 *amrwbplus_config;
+			struct msm_audio_amrwbplus_config_v2_32
+						amrwbplus_config_32;
+
+			memset(&amrwbplus_config_32, 0,
+					sizeof(amrwbplus_config_32));
+
+			amrwbplus_config =
+				(struct msm_audio_amrwbplus_config_v2 *)
+				audio->codec_cfg;
+			amrwbplus_config_32.size_bytes =
+					amrwbplus_config->size_bytes;
+			amrwbplus_config_32.version =
+					amrwbplus_config->version;
+			amrwbplus_config_32.num_channels =
+					amrwbplus_config->num_channels;
+			amrwbplus_config_32.amr_band_mode =
+					amrwbplus_config->amr_band_mode;
+			amrwbplus_config_32.amr_dtx_mode =
+					amrwbplus_config->amr_dtx_mode;
+			amrwbplus_config_32.amr_frame_fmt =
+					amrwbplus_config->amr_frame_fmt;
+			amrwbplus_config_32.amr_lsf_idx =
+					amrwbplus_config->amr_lsf_idx;
+
+			if (copy_to_user((void *)arg, &amrwbplus_config_32,
+				sizeof(amrwbplus_config_32))) {
+				rc = -EFAULT;
+				pr_err("%s: copy_to_user for AUDIO_GET_AMRWBPLUS_CONFIG_V2_32 failed\n"
+					, __func__);
+			}
+		} else {
+			pr_err("%s: wb+ Get config v2 invalid parameters\n"
+				, __func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_AMRWBPLUS_CONFIG_V2_32: {
+		if ((audio) && (arg) && (audio->codec_cfg)) {
+			struct msm_audio_amrwbplus_config_v2 *amrwbplus_config;
+			struct msm_audio_amrwbplus_config_v2_32
+							amrwbplus_config_32;
+
+			if (copy_from_user(&amrwbplus_config_32, (void *)arg,
+			sizeof(struct msm_audio_amrwbplus_config_v2_32))) {
+				rc = -EFAULT;
+				pr_err("%s: copy_from_user for AUDIO_SET_AMRWBPLUS_CONFIG_V2_32 failed\n"
+					, __func__);
+				break;
+			}
+			amrwbplus_config =
+			 (struct msm_audio_amrwbplus_config_v2 *)
+						audio->codec_cfg;
+			amrwbplus_config->size_bytes =
+					amrwbplus_config_32.size_bytes;
+			amrwbplus_config->version =
+					amrwbplus_config_32.version;
+			amrwbplus_config->num_channels =
+					amrwbplus_config_32.num_channels;
+			amrwbplus_config->amr_band_mode =
+					amrwbplus_config_32.amr_band_mode;
+			amrwbplus_config->amr_dtx_mode =
+					amrwbplus_config_32.amr_dtx_mode;
+			amrwbplus_config->amr_frame_fmt =
+					amrwbplus_config_32.amr_frame_fmt;
+			amrwbplus_config->amr_lsf_idx =
+					amrwbplus_config_32.amr_lsf_idx;
+		} else {
+			pr_err("%s: wb+ config invalid parameters\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	default: {
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+		break;
+	}
+	}
+	return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	audio->codec_cfg =
+	kzalloc(sizeof(struct msm_audio_amrwbplus_config_v2), GFP_KERNEL);
+	if (audio->codec_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_amrwbplus_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_amrwbplus_ws_mgr;
+
+	audio->ac =
+	q6asm_audio_client_alloc((app_cb) q6_audio_cb, (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio->codec_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					FORMAT_AMR_WB_PLUS);
+		if (rc < 0) {
+			pr_err("amrwbplus NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_AMR_WB_PLUS);
+		if (rc < 0) {
+			pr_err("wb+ T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("audio_amrwbplus Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+	config_debug_fs(audio);
+	pr_debug("%s: AMRWBPLUS dec success mode[%d]session[%d]\n", __func__,
+		audio->feedback,
+		audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_amrwbplus_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+	.compat_ioctl = audio_compat_ioctl
+};
+
+static struct miscdevice audio_amrwbplus_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_amrwbplus",
+	.fops = &audio_amrwbplus_fops,
+};
+
+static int __init audio_amrwbplus_init(void)
+{
+	int ret = misc_register(&audio_amrwbplus_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_amrwbplus_misc.this_device, true);
+	audio_amrwbplus_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_amrwbplus_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_amrwbplus_init);

+ 359 - 0
drivers/misc/qcom/qdsp6v2/audio_ape.c

@@ -0,0 +1,359 @@
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/types.h>
+#include <linux/msm_audio_ape.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_ape_misc;
+static struct ws_mgr audio_ape_ws_mgr;
+
+static const struct file_operations audio_ape_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+static struct dentry *config_debugfs_create_file(const char *name, void *data)
+{
+	return debugfs_create_file(name, S_IFREG | 0444,
+			NULL, (void *)data, &audio_ape_debug_fops);
+}
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+						void *arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct asm_ape_cfg ape_cfg;
+		struct msm_audio_ape_config *ape_config;
+
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+		ape_config = (struct msm_audio_ape_config *)audio->codec_cfg;
+		ape_cfg.compatible_version = ape_config->compatibleVersion;
+		ape_cfg.compression_level = ape_config->compressionLevel;
+		ape_cfg.format_flags = ape_config->formatFlags;
+		ape_cfg.blocks_per_frame = ape_config->blocksPerFrame;
+		ape_cfg.final_frame_blocks = ape_config->finalFrameBlocks;
+		ape_cfg.total_frames = ape_config->totalFrames;
+		ape_cfg.bits_per_sample = ape_config->bitsPerSample;
+		ape_cfg.num_channels = ape_config->numChannels;
+		ape_cfg.sample_rate = ape_config->sampleRate;
+		ape_cfg.seek_table_present = ape_config->seekTablePresent;
+		pr_debug("%s: compatibleVersion %d compressionLevel %d formatFlags %d blocksPerFrame %d finalFrameBlocks %d totalFrames %d bitsPerSample %d numChannels %d sampleRate %d seekTablePresent %d\n",
+				__func__, ape_config->compatibleVersion,
+				ape_config->compressionLevel,
+				ape_config->formatFlags,
+				ape_config->blocksPerFrame,
+				ape_config->finalFrameBlocks,
+				ape_config->totalFrames,
+				ape_config->bitsPerSample,
+				ape_config->numChannels,
+				ape_config->sampleRate,
+				ape_config->seekTablePresent);
+		/* Configure Media format block */
+		rc = q6asm_media_format_block_ape(audio->ac, &ape_cfg,
+							audio->ac->stream_id);
+		if (rc < 0) {
+			pr_err("cmd media format block failed\n");
+			break;
+		}
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("AUDIO_START success enable[%d]\n", audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		break;
+	}
+	return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_APE_CONFIG: {
+		if (copy_to_user((void *)arg, audio->codec_cfg,
+			sizeof(struct msm_audio_ape_config))) {
+			pr_err("%s:copy_to_user for AUDIO_GET_APE_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_APE_CONFIG: {
+		if (copy_from_user(audio->codec_cfg, (void *)arg,
+			sizeof(struct msm_audio_ape_config))) {
+			pr_err("%s:copy_from_user for AUDIO_SET_APE_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	default: {
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("Failed in utils_ioctl: %d\n", rc);
+		break;
+	}
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_ape_config_32 {
+	u16 compatibleVersion;
+	u16 compressionLevel;
+	u32 formatFlags;
+	u32 blocksPerFrame;
+	u32 finalFrameBlocks;
+	u32 totalFrames;
+	u16 bitsPerSample;
+	u16 numChannels;
+	u32 sampleRate;
+	u32 seekTablePresent;
+
+};
+
+enum {
+	AUDIO_GET_APE_CONFIG_32 =  _IOR(AUDIO_IOCTL_MAGIC,
+	(AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_ape_config_32),
+	AUDIO_SET_APE_CONFIG_32 =  _IOW(AUDIO_IOCTL_MAGIC,
+	(AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_ape_config_32)
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+						unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_APE_CONFIG_32: {
+		struct msm_audio_ape_config *ape_config;
+		struct msm_audio_ape_config_32 ape_config_32;
+
+		memset(&ape_config_32, 0, sizeof(ape_config_32));
+
+		ape_config = (struct msm_audio_ape_config *)audio->codec_cfg;
+		ape_config_32.compatibleVersion = ape_config->compatibleVersion;
+		ape_config_32.compressionLevel =
+				ape_config->compressionLevel;
+		ape_config_32.formatFlags = ape_config->formatFlags;
+		ape_config_32.blocksPerFrame = ape_config->blocksPerFrame;
+		ape_config_32.finalFrameBlocks = ape_config->finalFrameBlocks;
+		ape_config_32.totalFrames = ape_config->totalFrames;
+		ape_config_32.bitsPerSample = ape_config->bitsPerSample;
+		ape_config_32.numChannels = ape_config->numChannels;
+		ape_config_32.sampleRate = ape_config->sampleRate;
+		ape_config_32.seekTablePresent = ape_config->seekTablePresent;
+
+		if (copy_to_user((void *)arg, &ape_config_32,
+			sizeof(ape_config_32))) {
+			pr_err("%s: copy_to_user for GET_APE_CONFIG_32 failed\n",
+				 __func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_APE_CONFIG_32: {
+		struct msm_audio_ape_config *ape_config;
+		struct msm_audio_ape_config_32 ape_config_32;
+
+		if (copy_from_user(&ape_config_32, (void *)arg,
+			sizeof(ape_config_32))) {
+			pr_err("%s: copy_from_user for SET_APE_CONFIG_32 failed\n"
+				, __func__);
+			rc = -EFAULT;
+			break;
+		}
+		ape_config = (struct msm_audio_ape_config *)audio->codec_cfg;
+		ape_config->compatibleVersion = ape_config_32.compatibleVersion;
+		ape_config->compressionLevel =
+				ape_config_32.compressionLevel;
+		ape_config->formatFlags = ape_config_32.formatFlags;
+		ape_config->blocksPerFrame = ape_config_32.blocksPerFrame;
+		ape_config->finalFrameBlocks = ape_config_32.finalFrameBlocks;
+		ape_config->totalFrames = ape_config_32.totalFrames;
+		ape_config->bitsPerSample = ape_config_32.bitsPerSample;
+		ape_config->numChannels = ape_config_32.numChannels;
+		ape_config->sampleRate = ape_config_32.sampleRate;
+		ape_config->seekTablePresent = ape_config_32.seekTablePresent;
+
+		break;
+	}
+	default: {
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("Failed in utils_ioctl: %d\n", rc);
+		break;
+	}
+	}
+	return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_ape_" + 5];
+
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+	if (!audio)
+		return -ENOMEM;
+
+	audio->codec_cfg = kzalloc(sizeof(struct msm_audio_ape_config),
+					GFP_KERNEL);
+	if (!audio->codec_cfg) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_ape_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_ape_ws_mgr;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio->codec_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_APE);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		/* open APE decoder, expected frames is always 1*/
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_APE);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+	snprintf(name, sizeof(name), "msm_ape_%04x", audio->ac->session);
+	audio->dentry = config_debugfs_create_file(name, (void *)audio);
+
+	if (IS_ERR_OR_NULL(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+	pr_debug("%s:apedec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_ape_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+	.compat_ioctl = audio_compat_ioctl
+};
+
+static struct miscdevice audio_ape_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_ape",
+	.fops = &audio_ape_fops,
+};
+
+static int __init audio_ape_init(void)
+{
+	int ret = misc_register(&audio_ape_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_ape_misc.this_device, true);
+	audio_ape_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_ape_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_ape_init);

+ 184 - 0
drivers/misc/qcom/qdsp6v2/audio_evrc.c

@@ -0,0 +1,184 @@
+/* evrc audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 "audio_utils_aio.h"
+
+static struct miscdevice audio_evrc_misc;
+static struct ws_mgr audio_evrc_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_evrc_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+						audio->ac->session,
+						audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_evrc_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_evrc_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_evrc_ws_mgr;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_EVRC);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_EVRC);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof(name), "msm_evrc_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
+					    NULL, (void *)audio,
+					    &audio_evrc_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:dec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_evrc_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+};
+
+static struct miscdevice audio_evrc_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_evrc",
+	.fops = &audio_evrc_fops,
+};
+
+static int __init audio_evrc_init(void)
+{
+	int ret = misc_register(&audio_evrc_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_evrc_misc.this_device, true);
+	audio_evrc_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_evrc_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_evrc_init);

+ 396 - 0
drivers/misc/qcom/qdsp6v2/audio_g711alaw.c

@@ -0,0 +1,396 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/types.h>
+#include <linux/msm_audio_g711_dec.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_g711alaw_misc;
+static struct ws_mgr audio_g711_ws_mgr;
+
+static const struct file_operations audio_g711_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+
+static struct dentry *config_debugfs_create_file(const char *name, void *data)
+{
+	return debugfs_create_file(name, S_IFREG | 0444,
+				NULL, (void *)data, &audio_g711_debug_fops);
+}
+
+static int g711_channel_map(u8 *channel_mapping, uint32_t channels);
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+						void *arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct asm_g711_dec_cfg g711_dec_cfg;
+		struct msm_audio_g711_dec_config *g711_dec_config;
+		u8 channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+
+		memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+		memset(&g711_dec_cfg, 0, sizeof(g711_dec_cfg));
+
+		if (g711_channel_map(channel_mapping,
+			audio->pcm_cfg.channel_count)) {
+			pr_err("%s: setting channel map failed %d\n",
+					__func__, audio->pcm_cfg.channel_count);
+		}
+
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm_v2(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count,
+					16, /*bits per sample*/
+					false, false, channel_mapping);
+			if (rc < 0) {
+				pr_err("%s: pcm output block config failed rc=%d\n",
+						 __func__, rc);
+				break;
+			}
+		}
+		g711_dec_config =
+			(struct msm_audio_g711_dec_config *)audio->codec_cfg;
+		g711_dec_cfg.sample_rate = g711_dec_config->sample_rate;
+		/* Configure Media format block */
+		rc = q6asm_media_format_block_g711(audio->ac, &g711_dec_cfg,
+							audio->ac->stream_id);
+		if (rc < 0) {
+			pr_err("%s: cmd media format block failed rc=%d\n",
+				__func__, rc);
+			break;
+		}
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s: Audio Start procedure failed rc=%d\n",
+						__func__, rc);
+			break;
+		}
+		pr_debug("%s: AUDIO_START success enable[%d]\n",
+					 __func__, audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		break;
+	}
+	return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_G711_DEC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->codec_cfg,
+			sizeof(struct msm_audio_g711_dec_config))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_G711_DEC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_G711_DEC_CONFIG: {
+		if (copy_from_user(audio->codec_cfg, (void *)arg,
+			sizeof(struct msm_audio_g711_dec_config))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_G711_DEC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	default: {
+		rc = audio->codec_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("%s: Failed in audio_aio_ioctl: %d cmd=%d\n",
+				__func__, rc, cmd);
+		break;
+	}
+	}
+	return  rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_g711_dec_config_32 {
+	u32 sample_rate;
+};
+
+enum {
+	AUDIO_SET_G711_DEC_CONFIG_32 =  _IOW(AUDIO_IOCTL_MAGIC,
+	(AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_g711_dec_config_32),
+	AUDIO_GET_G711_DEC_CONFIG_32 =  _IOR(AUDIO_IOCTL_MAGIC,
+	(AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_g711_dec_config_32)
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+						unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_G711_DEC_CONFIG_32: {
+		struct msm_audio_g711_dec_config *g711_dec_config;
+		struct msm_audio_g711_dec_config_32 g711_dec_config_32;
+
+		memset(&g711_dec_config_32, 0, sizeof(g711_dec_config_32));
+
+		g711_dec_config =
+			(struct msm_audio_g711_dec_config *)audio->codec_cfg;
+		g711_dec_config_32.sample_rate = g711_dec_config->sample_rate;
+
+		if (copy_to_user((void *)arg, &g711_dec_config_32,
+			sizeof(g711_dec_config_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_G711_DEC_CONFIG_32 failed\n",
+				 __func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_G711_DEC_CONFIG_32: {
+		struct msm_audio_g711_dec_config *g711_dec_config;
+		struct msm_audio_g711_dec_config_32 g711_dec_config_32;
+
+		memset(&g711_dec_config_32, 0, sizeof(g711_dec_config_32));
+
+		if (copy_from_user(&g711_dec_config_32, (void *)arg,
+			sizeof(g711_dec_config_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_G711_DEC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+
+		g711_dec_config =
+			(struct msm_audio_g711_dec_config *)audio->codec_cfg;
+		g711_dec_config->sample_rate = g711_dec_config_32.sample_rate;
+
+		break;
+	}
+	default: {
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("%s: Failed in audio_aio_compat_ioctl: %d cmd=%d\n",
+				__func__, rc, cmd);
+		break;
+	}
+	}
+	return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_g711_" + 5];
+
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (!audio)
+		return -ENOMEM;
+	audio->codec_cfg = kzalloc(sizeof(struct msm_audio_g711_dec_config),
+					GFP_KERNEL);
+	if (!audio->codec_cfg) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_g711alaw_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_g711_ws_mgr;
+
+	init_waitqueue_head(&audio->event_wait);
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("%s: Could not allocate memory for audio client\n",
+					 __func__);
+		kfree(audio->codec_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+	/* open in T/NT mode */ /*foramt:G711_ALAW*/
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_G711_ALAW_FS);
+		if (rc < 0) {
+			pr_err("%s: NT mode Open failed rc=%d\n", __func__, rc);
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		/* open G711 decoder, expected frames is always 1*/
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_G711_ALAW_FS);
+		if (rc < 0) {
+			pr_err("%s: T mode Open failed rc=%d\n", __func__, rc);
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("%s: %d mode is not supported mode\n",
+				__func__, file->f_mode);
+		rc = -EACCES;
+		goto fail;
+	}
+
+	snprintf(name, sizeof(name), "msm_g711_%04x", audio->ac->session);
+	audio->dentry = config_debugfs_create_file(name, (void *)audio);
+
+	if (IS_ERR_OR_NULL(audio->dentry))
+		pr_debug("%s: debugfs_create_file failed\n", __func__);
+	pr_debug("%s: g711dec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static int g711_channel_map(u8 *channel_mapping, uint32_t channels)
+{
+	u8 *lchannel_mapping;
+
+	lchannel_mapping = channel_mapping;
+	pr_debug("%s: channels passed: %d\n", __func__, channels);
+	if (channels == 1)  {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+	} else if (channels == 2) {
+		lchannel_mapping[0] = PCM_CHANNEL_FL;
+		lchannel_mapping[1] = PCM_CHANNEL_FR;
+	} else if (channels == 3) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+	} else if (channels == 4) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_CS;
+	} else if (channels == 5) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_LS;
+		lchannel_mapping[4] = PCM_CHANNEL_RS;
+	} else if (channels == 6) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_LS;
+		lchannel_mapping[4] = PCM_CHANNEL_RS;
+		lchannel_mapping[5] = PCM_CHANNEL_LFE;
+	} else if (channels == 7) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_LS;
+		lchannel_mapping[4] = PCM_CHANNEL_RS;
+		lchannel_mapping[5] = PCM_CHANNEL_CS;
+		lchannel_mapping[6] = PCM_CHANNEL_LFE;
+	} else if (channels == 8) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FLC;
+		lchannel_mapping[2] = PCM_CHANNEL_FRC;
+		lchannel_mapping[3] = PCM_CHANNEL_FL;
+		lchannel_mapping[4] = PCM_CHANNEL_FR;
+		lchannel_mapping[5] = PCM_CHANNEL_LS;
+		lchannel_mapping[6] = PCM_CHANNEL_RS;
+		lchannel_mapping[7] = PCM_CHANNEL_LFE;
+	} else {
+		pr_err("%s: ERROR.unsupported num_ch = %u\n",
+				__func__, channels);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct file_operations audio_g711_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.compat_ioctl = audio_compat_ioctl,
+	.fsync = audio_aio_fsync,
+};
+
+static struct miscdevice audio_g711alaw_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_g711alaw",
+	.fops = &audio_g711_fops,
+};
+
+static int __init audio_g711alaw_init(void)
+{
+	int ret = misc_register(&audio_g711alaw_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_g711alaw_misc.this_device, true);
+	audio_g711_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_g711_ws_mgr.ws_lock);
+
+	return ret;
+}
+static void __exit audio_g711alaw_exit(void)
+{
+	misc_deregister(&audio_g711alaw_misc);
+	mutex_destroy(&audio_g711_ws_mgr.ws_lock);
+}
+
+device_initcall(audio_g711alaw_init);
+__exitcall(audio_g711alaw_exit);

+ 396 - 0
drivers/misc/qcom/qdsp6v2/audio_g711mlaw.c

@@ -0,0 +1,396 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/types.h>
+#include <linux/msm_audio_g711_dec.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_g711mlaw_misc;
+static struct ws_mgr audio_g711_ws_mgr;
+
+static const struct file_operations audio_g711_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+
+static struct dentry *config_debugfs_create_file(const char *name, void *data)
+{
+	return debugfs_create_file(name, S_IFREG | 0444,
+				NULL, (void *)data, &audio_g711_debug_fops);
+}
+
+static int g711_channel_map(u8 *channel_mapping, uint32_t channels);
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+						void *arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct asm_g711_dec_cfg g711_dec_cfg;
+		struct msm_audio_g711_dec_config *g711_dec_config;
+		u8 channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+
+		memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+		memset(&g711_dec_cfg, 0, sizeof(g711_dec_cfg));
+
+		if (g711_channel_map(channel_mapping,
+			audio->pcm_cfg.channel_count)) {
+			pr_err("%s: setting channel map failed %d\n",
+					__func__, audio->pcm_cfg.channel_count);
+		}
+
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm_v2(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count,
+					16, /*bits per sample*/
+					false, false, channel_mapping);
+			if (rc < 0) {
+				pr_err("%s: pcm output block config failed rc=%d\n",
+						 __func__, rc);
+				break;
+			}
+		}
+		g711_dec_config =
+			(struct msm_audio_g711_dec_config *)audio->codec_cfg;
+		g711_dec_cfg.sample_rate = g711_dec_config->sample_rate;
+		/* Configure Media format block */
+		rc = q6asm_media_format_block_g711(audio->ac, &g711_dec_cfg,
+							audio->ac->stream_id);
+		if (rc < 0) {
+			pr_err("%s: cmd media format block failed rc=%d\n",
+				__func__, rc);
+			break;
+		}
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s: Audio Start procedure failed rc=%d\n",
+						__func__, rc);
+			break;
+		}
+		pr_debug("%s: AUDIO_START success enable[%d]\n",
+						__func__, audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		break;
+	}
+	return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_G711_DEC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->codec_cfg,
+			sizeof(struct msm_audio_g711_dec_config))) {
+			pr_err("%s: AUDIO_GET_G711_DEC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_G711_DEC_CONFIG: {
+		if (copy_from_user(audio->codec_cfg, (void *)arg,
+			sizeof(struct msm_audio_g711_dec_config))) {
+			pr_err("%s: AUDIO_SET_G711_DEC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	default: {
+		rc = audio->codec_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("%s: Failed in audio_aio_ioctl: %d cmd=%d\n",
+				__func__, rc, cmd);
+		break;
+	}
+	}
+	return  rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_g711_dec_config_32 {
+	u32 sample_rate;
+};
+
+enum {
+	AUDIO_SET_G711_DEC_CONFIG_32 =  _IOW(AUDIO_IOCTL_MAGIC,
+	(AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_g711_dec_config_32),
+	AUDIO_GET_G711_DEC_CONFIG_32 =  _IOR(AUDIO_IOCTL_MAGIC,
+	(AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_g711_dec_config_32)
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+						unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_G711_DEC_CONFIG_32: {
+		struct msm_audio_g711_dec_config *g711_dec_config;
+		struct msm_audio_g711_dec_config_32 g711_dec_config_32;
+
+		memset(&g711_dec_config_32, 0, sizeof(g711_dec_config_32));
+
+		g711_dec_config =
+			(struct msm_audio_g711_dec_config *)audio->codec_cfg;
+		g711_dec_config_32.sample_rate = g711_dec_config->sample_rate;
+
+		if (copy_to_user((void *)arg, &g711_dec_config_32,
+			sizeof(g711_dec_config_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_G711_DEC_CONFIG failed\n",
+				 __func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_G711_DEC_CONFIG_32: {
+		struct msm_audio_g711_dec_config *g711_dec_config;
+		struct msm_audio_g711_dec_config_32 g711_dec_config_32;
+
+		memset(&g711_dec_config_32, 0, sizeof(g711_dec_config_32));
+
+		if (copy_from_user(&g711_dec_config_32, (void *)arg,
+			sizeof(g711_dec_config_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_G711_DEC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		g711_dec_config =
+			(struct msm_audio_g711_dec_config *)audio->codec_cfg;
+		g711_dec_config->sample_rate = g711_dec_config_32.sample_rate;
+
+		break;
+	}
+	default: {
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("%s: Failed in audio_aio_compat_ioctl: %d cmd=%d\n",
+				__func__, rc, cmd);
+		break;
+	}
+	}
+	return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_g711_" + 5];
+
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (!audio)
+		return -ENOMEM;
+	audio->codec_cfg = kzalloc(sizeof(struct msm_audio_g711_dec_config),
+					GFP_KERNEL);
+	if (!audio->codec_cfg) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_g711mlaw_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_g711_ws_mgr;
+
+	init_waitqueue_head(&audio->event_wait);
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("%s: Could not allocate memory for audio client\n",
+					__func__);
+		kfree(audio->codec_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+	/* open in T/NT mode */ /*foramt:G711_ALAW*/
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_G711_MLAW_FS);
+		if (rc < 0) {
+			pr_err("%s: NT mode Open failed rc=%d\n", __func__, rc);
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		/* open G711 decoder, expected frames is always 1*/
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_G711_MLAW_FS);
+		if (rc < 0) {
+			pr_err("%s: T mode Open failed rc=%d\n", __func__, rc);
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("%s: %d mode is not supported\n", __func__,
+					file->f_mode);
+		rc = -EACCES;
+		goto fail;
+	}
+
+	snprintf(name, sizeof(name), "msm_g711_%04x", audio->ac->session);
+	audio->dentry = config_debugfs_create_file(name, (void *)audio);
+
+	if (IS_ERR_OR_NULL(audio->dentry))
+		pr_debug("%s: debugfs_create_file failed\n", __func__);
+	pr_debug("%s: g711dec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static int g711_channel_map(u8 *channel_mapping, uint32_t channels)
+{
+	u8 *lchannel_mapping;
+
+	lchannel_mapping = channel_mapping;
+	pr_debug("%s: channels passed: %d\n", __func__, channels);
+	if (channels == 1)  {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+	} else if (channels == 2) {
+		lchannel_mapping[0] = PCM_CHANNEL_FL;
+		lchannel_mapping[1] = PCM_CHANNEL_FR;
+	} else if (channels == 3) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+	} else if (channels == 4) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_CS;
+	} else if (channels == 5) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_LS;
+		lchannel_mapping[4] = PCM_CHANNEL_RS;
+	} else if (channels == 6) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_LS;
+		lchannel_mapping[4] = PCM_CHANNEL_RS;
+		lchannel_mapping[5] = PCM_CHANNEL_LFE;
+	} else if (channels == 7) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FL;
+		lchannel_mapping[2] = PCM_CHANNEL_FR;
+		lchannel_mapping[3] = PCM_CHANNEL_LS;
+		lchannel_mapping[4] = PCM_CHANNEL_RS;
+		lchannel_mapping[5] = PCM_CHANNEL_CS;
+		lchannel_mapping[6] = PCM_CHANNEL_LFE;
+	} else if (channels == 8) {
+		lchannel_mapping[0] = PCM_CHANNEL_FC;
+		lchannel_mapping[1] = PCM_CHANNEL_FLC;
+		lchannel_mapping[2] = PCM_CHANNEL_FRC;
+		lchannel_mapping[3] = PCM_CHANNEL_FL;
+		lchannel_mapping[4] = PCM_CHANNEL_FR;
+		lchannel_mapping[5] = PCM_CHANNEL_LS;
+		lchannel_mapping[6] = PCM_CHANNEL_RS;
+		lchannel_mapping[7] = PCM_CHANNEL_LFE;
+	} else {
+		pr_err("%s: ERROR.unsupported num_ch = %u\n",
+				__func__, channels);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct file_operations audio_g711_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.compat_ioctl = audio_compat_ioctl,
+	.fsync = audio_aio_fsync,
+};
+
+static struct miscdevice audio_g711mlaw_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_g711mlaw",
+	.fops = &audio_g711_fops,
+};
+
+static int __init audio_g711mlaw_init(void)
+{
+	int ret = misc_register(&audio_g711mlaw_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_g711mlaw_misc.this_device, true);
+	audio_g711_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_g711_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+static void __exit audio_g711mlaw_exit(void)
+{
+	misc_deregister(&audio_g711mlaw_misc);
+	mutex_destroy(&audio_g711_ws_mgr.ws_lock);
+}
+
+device_initcall(audio_g711mlaw_init);
+__exitcall(audio_g711mlaw_exit);

+ 778 - 0
drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c

@@ -0,0 +1,778 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/msm_audio.h>
+#include <linux/compat.h>
+#include "q6audio_common.h"
+#include "audio_utils_aio.h"
+#include <sound/msm-audio-effects-q6-v2.h>
+
+#define MAX_CHANNELS_SUPPORTED		8
+#define WAIT_TIMEDOUT_DURATION_SECS	1
+
+struct q6audio_effects {
+	wait_queue_head_t		read_wait;
+	wait_queue_head_t		write_wait;
+
+	struct audio_client             *ac;
+	struct msm_hwacc_effects_config  config;
+
+	struct mutex			lock;
+
+	atomic_t			in_count;
+	atomic_t			out_count;
+
+	int				opened;
+	int				started;
+	int				buf_alloc;
+	struct msm_nt_eff_all_config audio_effects;
+};
+
+static void audio_effects_init_pp(struct audio_client *ac)
+{
+	int ret = 0;
+	struct asm_softvolume_params softvol = {
+		.period = SOFT_VOLUME_PERIOD,
+		.step = SOFT_VOLUME_STEP,
+		.rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
+	};
+
+	if (!ac) {
+		pr_err("%s: audio client null to init pp\n", __func__);
+		return;
+	}
+	ret = q6asm_set_softvolume_v2(ac, &softvol,
+				      SOFT_VOLUME_INSTANCE_1);
+	if (ret < 0)
+		pr_err("%s: Send SoftVolume Param failed ret=%d\n",
+			__func__, ret);
+}
+
+static void audio_effects_deinit_pp(struct audio_client *ac)
+{
+	if (!ac) {
+		pr_err("%s: audio client null to deinit pp\n", __func__);
+		return;
+	}
+}
+
+static void audio_effects_event_handler(uint32_t opcode, uint32_t token,
+				 uint32_t *payload,  void *priv)
+{
+	struct q6audio_effects *effects;
+
+	if (!payload || !priv) {
+		pr_err("%s: invalid data to handle events, payload: %pK, priv: %pK\n",
+			__func__, payload, priv);
+		return;
+	}
+
+	effects = (struct q6audio_effects *)priv;
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE_V2: {
+		atomic_inc(&effects->out_count);
+		wake_up(&effects->write_wait);
+		break;
+	}
+	case ASM_DATA_EVENT_READ_DONE_V2: {
+		atomic_inc(&effects->in_count);
+		wake_up(&effects->read_wait);
+		break;
+	}
+	case APR_BASIC_RSP_RESULT: {
+		pr_debug("%s: APR_BASIC_RSP_RESULT Cmd[0x%x] Status[0x%x]\n",
+			 __func__, payload[0], payload[1]);
+		switch (payload[0]) {
+		case ASM_SESSION_CMD_RUN_V2:
+			pr_debug("ASM_SESSION_CMD_RUN_V2\n");
+			break;
+		default:
+			pr_debug("%s: Payload = [0x%x] stat[0x%x]\n",
+				 __func__, payload[0], payload[1]);
+			break;
+		}
+		break;
+	}
+	default:
+		pr_debug("%s: Unhandled Event 0x%x token = 0x%x\n",
+			 __func__, opcode, token);
+		break;
+	}
+}
+
+static int audio_effects_shared_ioctl(struct file *file, unsigned int cmd,
+				      unsigned long arg)
+{
+	struct q6audio_effects *effects = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s: AUDIO_START\n", __func__);
+
+		mutex_lock(&effects->lock);
+
+		rc = q6asm_open_read_write_v2(effects->ac,
+					FORMAT_LINEAR_PCM,
+					FORMAT_MULTI_CHANNEL_LINEAR_PCM,
+					effects->config.meta_mode_enabled,
+					effects->config.output.bits_per_sample,
+					true /*overwrite topology*/,
+					ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER);
+		if (rc < 0) {
+			pr_err("%s: Open failed for hw accelerated effects:rc=%d\n",
+				__func__, rc);
+			rc = -EINVAL;
+			mutex_unlock(&effects->lock);
+			goto ioctl_fail;
+		}
+		effects->opened = 1;
+
+		pr_debug("%s: dec buf size: %d, num_buf: %d, enc buf size: %d, num_buf: %d\n",
+			 __func__, effects->config.output.buf_size,
+			 effects->config.output.num_buf,
+			 effects->config.input.buf_size,
+			 effects->config.input.num_buf);
+		rc = q6asm_audio_client_buf_alloc_contiguous(IN, effects->ac,
+					effects->config.output.buf_size,
+					effects->config.output.num_buf);
+		if (rc < 0) {
+			pr_err("%s: Write buffer Allocation failed rc = %d\n",
+				__func__, rc);
+			rc = -ENOMEM;
+			mutex_unlock(&effects->lock);
+			goto ioctl_fail;
+		}
+		atomic_set(&effects->in_count, effects->config.input.num_buf);
+		rc = q6asm_audio_client_buf_alloc_contiguous(OUT, effects->ac,
+					effects->config.input.buf_size,
+					effects->config.input.num_buf);
+		if (rc < 0) {
+			pr_err("%s: Read buffer Allocation failed rc = %d\n",
+				__func__, rc);
+			rc = -ENOMEM;
+			mutex_unlock(&effects->lock);
+			goto readbuf_fail;
+		}
+		atomic_set(&effects->out_count, effects->config.output.num_buf);
+		effects->buf_alloc = 1;
+
+		pr_debug("%s: enc: sample_rate: %d, num_channels: %d\n",
+			 __func__, effects->config.input.sample_rate,
+			effects->config.input.num_channels);
+		rc = q6asm_enc_cfg_blk_pcm(effects->ac,
+					   effects->config.input.sample_rate,
+					   effects->config.input.num_channels);
+		if (rc < 0) {
+			pr_err("%s: pcm read block config failed\n", __func__);
+			rc = -EINVAL;
+			mutex_unlock(&effects->lock);
+			goto cfg_fail;
+		}
+		pr_debug("%s: dec: sample_rate: %d, num_channels: %d, bit_width: %d\n",
+			 __func__, effects->config.output.sample_rate,
+			effects->config.output.num_channels,
+			effects->config.output.bits_per_sample);
+		rc = q6asm_media_format_block_pcm_format_support(
+				effects->ac, effects->config.output.sample_rate,
+				effects->config.output.num_channels,
+				effects->config.output.bits_per_sample);
+		if (rc < 0) {
+			pr_err("%s: pcm write format block config failed\n",
+				__func__);
+			rc = -EINVAL;
+			mutex_unlock(&effects->lock);
+			goto cfg_fail;
+		}
+
+		audio_effects_init_pp(effects->ac);
+
+		rc = q6asm_run(effects->ac, 0x00, 0x00, 0x00);
+		if (!rc)
+			effects->started = 1;
+		else {
+			effects->started = 0;
+			pr_err("%s: ASM run state failed\n", __func__);
+		}
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	case AUDIO_EFFECTS_WRITE: {
+		char *bufptr = NULL;
+		uint32_t idx = 0;
+		uint32_t size = 0;
+
+		mutex_lock(&effects->lock);
+
+		if (!effects->started) {
+			rc = -EFAULT;
+			mutex_unlock(&effects->lock);
+			goto ioctl_fail;
+		}
+
+		rc = wait_event_timeout(effects->write_wait,
+					atomic_read(&effects->out_count),
+					WAIT_TIMEDOUT_DURATION_SECS * HZ);
+		if (!rc) {
+			pr_err("%s: write wait_event_timeout\n", __func__);
+			rc = -EFAULT;
+			 mutex_unlock(&effects->lock);
+			goto ioctl_fail;
+		}
+		if (!atomic_read(&effects->out_count)) {
+			pr_err("%s: pcm stopped out_count 0\n", __func__);
+			rc = -EFAULT;
+			mutex_unlock(&effects->lock);
+			goto ioctl_fail;
+		}
+
+		bufptr = q6asm_is_cpu_buf_avail(IN, effects->ac, &size, &idx);
+		if (bufptr) {
+			if ((effects->config.buf_cfg.output_len > size) ||
+				copy_from_user(bufptr, (void *)arg,
+					effects->config.buf_cfg.output_len)) {
+				rc = -EFAULT;
+				mutex_unlock(&effects->lock);
+				goto ioctl_fail;
+			}
+			rc = q6asm_write(effects->ac,
+					 effects->config.buf_cfg.output_len,
+					 0, 0, NO_TIMESTAMP);
+			if (rc < 0) {
+				rc = -EFAULT;
+				mutex_unlock(&effects->lock);
+				goto ioctl_fail;
+			}
+			atomic_dec(&effects->out_count);
+		} else {
+			pr_err("%s: AUDIO_EFFECTS_WRITE: Buffer dropped\n",
+				__func__);
+		}
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	case AUDIO_EFFECTS_READ: {
+		char *bufptr = NULL;
+		uint32_t idx = 0;
+		uint32_t size = 0;
+
+		mutex_lock(&effects->lock);
+
+		if (!effects->started) {
+			rc = -EFAULT;
+			mutex_unlock(&effects->lock);
+			goto ioctl_fail;
+		}
+
+		atomic_set(&effects->in_count, 0);
+
+		q6asm_read_v2(effects->ac, effects->config.buf_cfg.input_len);
+		/* Read might fail initially, don't error out */
+		if (rc < 0)
+			pr_err("%s: read failed\n", __func__);
+
+		rc = wait_event_timeout(effects->read_wait,
+					atomic_read(&effects->in_count),
+					WAIT_TIMEDOUT_DURATION_SECS * HZ);
+		if (!rc) {
+			pr_err("%s: read wait_event_timeout\n", __func__);
+			rc = -EFAULT;
+			mutex_unlock(&effects->lock);
+			goto ioctl_fail;
+		}
+		if (!atomic_read(&effects->in_count)) {
+			pr_err("%s: pcm stopped in_count 0\n", __func__);
+			rc = -EFAULT;
+			mutex_unlock(&effects->lock);
+			goto ioctl_fail;
+		}
+
+		bufptr = q6asm_is_cpu_buf_avail(OUT, effects->ac, &size, &idx);
+		if (bufptr) {
+			if (!((void *)arg)) {
+				rc = -EFAULT;
+				mutex_unlock(&effects->lock);
+				goto ioctl_fail;
+			}
+			if ((effects->config.buf_cfg.input_len > size) ||
+				copy_to_user((void *)arg, bufptr,
+					  effects->config.buf_cfg.input_len)) {
+				rc = -EFAULT;
+				mutex_unlock(&effects->lock);
+				goto ioctl_fail;
+			}
+		}
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	default:
+		pr_err("%s: Invalid effects config module\n", __func__);
+		rc = -EINVAL;
+		break;
+	}
+ioctl_fail:
+	return rc;
+readbuf_fail:
+	q6asm_audio_client_buf_free_contiguous(IN,
+					effects->ac);
+	return rc;
+cfg_fail:
+	q6asm_audio_client_buf_free_contiguous(IN,
+					effects->ac);
+	q6asm_audio_client_buf_free_contiguous(OUT,
+					effects->ac);
+	effects->buf_alloc = 0;
+	return rc;
+}
+
+static long audio_effects_set_pp_param(struct q6audio_effects *effects,
+				long *values)
+{
+	int rc = 0;
+	int effects_module = values[0];
+
+	switch (effects_module) {
+	case VIRTUALIZER_MODULE:
+		pr_debug("%s: VIRTUALIZER_MODULE\n", __func__);
+		if (msm_audio_effects_is_effmodule_supp_in_top(
+			effects_module, effects->ac->topology))
+			msm_audio_effects_virtualizer_handler(
+				effects->ac,
+				&(effects->audio_effects.virtualizer),
+				(long *)&values[1]);
+		break;
+	case REVERB_MODULE:
+		pr_debug("%s: REVERB_MODULE\n", __func__);
+		if (msm_audio_effects_is_effmodule_supp_in_top(
+			effects_module, effects->ac->topology))
+			msm_audio_effects_reverb_handler(effects->ac,
+				 &(effects->audio_effects.reverb),
+				 (long *)&values[1]);
+		break;
+	case BASS_BOOST_MODULE:
+		pr_debug("%s: BASS_BOOST_MODULE\n", __func__);
+		if (msm_audio_effects_is_effmodule_supp_in_top(
+			effects_module, effects->ac->topology))
+			msm_audio_effects_bass_boost_handler(
+				effects->ac,
+				&(effects->audio_effects.bass_boost),
+				(long *)&values[1]);
+		break;
+	case PBE_MODULE:
+		pr_debug("%s: PBE_MODULE\n", __func__);
+		if (msm_audio_effects_is_effmodule_supp_in_top(
+			effects_module, effects->ac->topology))
+			msm_audio_effects_pbe_handler(
+				effects->ac,
+				&(effects->audio_effects.pbe),
+				(long *)&values[1]);
+		break;
+	case EQ_MODULE:
+		pr_debug("%s: EQ_MODULE\n", __func__);
+		if (msm_audio_effects_is_effmodule_supp_in_top(
+			effects_module, effects->ac->topology))
+			msm_audio_effects_popless_eq_handler(
+				effects->ac,
+				&(effects->audio_effects.equalizer),
+				(long *)&values[1]);
+		break;
+	case SOFT_VOLUME_MODULE:
+		pr_debug("%s: SA PLUS VOLUME_MODULE\n", __func__);
+		msm_audio_effects_volume_handler_v2(effects->ac,
+				&(effects->audio_effects.saplus_vol),
+				(long *)&values[1], SOFT_VOLUME_INSTANCE_1);
+		break;
+	case SOFT_VOLUME2_MODULE:
+		pr_debug("%s: TOPOLOGY SWITCH VOLUME MODULE\n",
+			 __func__);
+		if (msm_audio_effects_is_effmodule_supp_in_top(
+			effects_module, effects->ac->topology))
+			msm_audio_effects_volume_handler_v2(effects->ac,
+			      &(effects->audio_effects.topo_switch_vol),
+			      (long *)&values[1], SOFT_VOLUME_INSTANCE_2);
+		break;
+	default:
+		pr_err("%s: Invalid effects config module\n", __func__);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static long audio_effects_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	struct q6audio_effects *effects = file->private_data;
+	int rc = 0;
+	long argvalues[MAX_PP_PARAMS_SZ] = {0};
+
+	switch (cmd) {
+	case AUDIO_SET_EFFECTS_CONFIG: {
+		pr_debug("%s: AUDIO_SET_EFFECTS_CONFIG\n", __func__);
+		mutex_lock(&effects->lock);
+		memset(&effects->config, 0, sizeof(effects->config));
+		if (copy_from_user(&effects->config, (void *)arg,
+				   sizeof(effects->config))) {
+			pr_err("%s: copy from user for AUDIO_SET_EFFECTS_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		pr_debug("%s: write buf_size: %d, num_buf: %d, sample_rate: %d, channel: %d\n",
+			 __func__, effects->config.output.buf_size,
+			 effects->config.output.num_buf,
+			 effects->config.output.sample_rate,
+			 effects->config.output.num_channels);
+		pr_debug("%s: read buf_size: %d, num_buf: %d, sample_rate: %d, channel: %d\n",
+			 __func__, effects->config.input.buf_size,
+			 effects->config.input.num_buf,
+			 effects->config.input.sample_rate,
+			 effects->config.input.num_channels);
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	case AUDIO_EFFECTS_SET_BUF_LEN: {
+		mutex_lock(&effects->lock);
+		if (copy_from_user(&effects->config.buf_cfg, (void *)arg,
+				   sizeof(effects->config.buf_cfg))) {
+			pr_err("%s: copy from user for AUDIO_EFFECTS_SET_BUF_LEN failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		pr_debug("%s: write buf len: %d, read buf len: %d\n",
+			 __func__, effects->config.buf_cfg.output_len,
+			 effects->config.buf_cfg.input_len);
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	case AUDIO_EFFECTS_GET_BUF_AVAIL: {
+		struct msm_hwacc_buf_avail buf_avail;
+
+		buf_avail.input_num_avail = atomic_read(&effects->in_count);
+		buf_avail.output_num_avail = atomic_read(&effects->out_count);
+		mutex_lock(&effects->lock);
+		pr_debug("%s: write buf avail: %d, read buf avail: %d\n",
+			 __func__, buf_avail.output_num_avail,
+			 buf_avail.input_num_avail);
+		if (copy_to_user((void *)arg, &buf_avail,
+				   sizeof(buf_avail))) {
+			pr_err("%s: copy to user for AUDIO_EFFECTS_GET_NUM_BUF_AVAIL failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	case AUDIO_EFFECTS_SET_PP_PARAMS: {
+		mutex_lock(&effects->lock);
+		if (copy_from_user(argvalues, (void *)arg,
+				   MAX_PP_PARAMS_SZ*sizeof(long))) {
+			pr_err("%s: copy from user for pp params failed\n",
+				__func__);
+			mutex_unlock(&effects->lock);
+			return -EFAULT;
+		}
+		rc = audio_effects_set_pp_param(effects, argvalues);
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	default:
+		pr_debug("%s: Calling shared ioctl\n", __func__);
+		rc = audio_effects_shared_ioctl(file, cmd, arg);
+		break;
+	}
+	if (rc)
+		pr_err("%s: cmd 0x%x failed\n", __func__, cmd);
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_hwacc_data_config32 {
+	__u32 buf_size;
+	__u32 num_buf;
+	__u32 num_channels;
+	__u8 channel_map[MAX_CHANNELS_SUPPORTED];
+	__u32 sample_rate;
+	__u32 bits_per_sample;
+};
+
+struct msm_hwacc_buf_cfg32 {
+	__u32 input_len;
+	__u32 output_len;
+};
+
+struct msm_hwacc_buf_avail32 {
+	__u32 input_num_avail;
+	__u32 output_num_avail;
+};
+
+struct msm_hwacc_effects_config32 {
+	struct msm_hwacc_data_config32 input;
+	struct msm_hwacc_data_config32 output;
+	struct msm_hwacc_buf_cfg32 buf_cfg;
+	__u32 meta_mode_enabled;
+	__u32 overwrite_topology;
+	__s32 topology;
+};
+
+enum {
+	AUDIO_SET_EFFECTS_CONFIG32 = _IOW(AUDIO_IOCTL_MAGIC, 99,
+					  struct msm_hwacc_effects_config32),
+	AUDIO_EFFECTS_SET_BUF_LEN32 = _IOW(AUDIO_IOCTL_MAGIC, 100,
+					   struct msm_hwacc_buf_cfg32),
+	AUDIO_EFFECTS_GET_BUF_AVAIL32 = _IOW(AUDIO_IOCTL_MAGIC, 101,
+					     struct msm_hwacc_buf_avail32),
+	AUDIO_EFFECTS_WRITE32 = _IOW(AUDIO_IOCTL_MAGIC, 102, compat_uptr_t),
+	AUDIO_EFFECTS_READ32 = _IOWR(AUDIO_IOCTL_MAGIC, 103, compat_uptr_t),
+	AUDIO_EFFECTS_SET_PP_PARAMS32 = _IOW(AUDIO_IOCTL_MAGIC, 104,
+					   compat_uptr_t),
+	AUDIO_START32 = _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned int),
+};
+
+static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd,
+					unsigned long arg)
+{
+	struct q6audio_effects *effects = file->private_data;
+	int rc = 0, i;
+
+	switch (cmd) {
+	case AUDIO_SET_EFFECTS_CONFIG32: {
+		struct msm_hwacc_effects_config32 config32;
+		struct msm_hwacc_effects_config *config = &effects->config;
+
+		mutex_lock(&effects->lock);
+		memset(&effects->config, 0, sizeof(effects->config));
+		if (copy_from_user(&config32, (void *)arg,
+				   sizeof(config32))) {
+			pr_err("%s: copy to user for AUDIO_SET_EFFECTS_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			mutex_unlock(&effects->lock);
+			break;
+		}
+		config->input.buf_size = config32.input.buf_size;
+		config->input.num_buf = config32.input.num_buf;
+		config->input.num_channels = config32.input.num_channels;
+		config->input.sample_rate = config32.input.sample_rate;
+		config->input.bits_per_sample = config32.input.bits_per_sample;
+		config->input.buf_size = config32.input.buf_size;
+		for (i = 0; i < MAX_CHANNELS_SUPPORTED; i++)
+			config->input.channel_map[i] =
+						config32.input.channel_map[i];
+		config->output.buf_size = config32.output.buf_size;
+		config->output.num_buf = config32.output.num_buf;
+		config->output.num_channels = config32.output.num_channels;
+		config->output.sample_rate = config32.output.sample_rate;
+		config->output.bits_per_sample =
+					 config32.output.bits_per_sample;
+		config->output.buf_size = config32.output.buf_size;
+		for (i = 0; i < MAX_CHANNELS_SUPPORTED; i++)
+			config->output.channel_map[i] =
+						config32.output.channel_map[i];
+		config->buf_cfg.input_len = config32.buf_cfg.input_len;
+		config->buf_cfg.output_len = config32.buf_cfg.output_len;
+		config->meta_mode_enabled = config32.meta_mode_enabled;
+		config->overwrite_topology = config32.overwrite_topology;
+		config->topology = config32.topology;
+		pr_debug("%s: write buf_size: %d, num_buf: %d, sample_rate: %d, channels: %d\n",
+			 __func__, effects->config.output.buf_size,
+			 effects->config.output.num_buf,
+			 effects->config.output.sample_rate,
+			 effects->config.output.num_channels);
+		pr_debug("%s: read buf_size: %d, num_buf: %d, sample_rate: %d, channels: %d\n",
+			 __func__, effects->config.input.buf_size,
+			 effects->config.input.num_buf,
+			 effects->config.input.sample_rate,
+			 effects->config.input.num_channels);
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	case AUDIO_EFFECTS_SET_BUF_LEN32: {
+		struct msm_hwacc_buf_cfg32 buf_cfg32;
+		struct msm_hwacc_effects_config *config = &effects->config;
+
+		mutex_lock(&effects->lock);
+		if (copy_from_user(&buf_cfg32, (void *)arg,
+				   sizeof(buf_cfg32))) {
+			pr_err("%s: copy from user for AUDIO_EFFECTS_SET_BUF_LEN failed\n",
+				__func__);
+			rc = -EFAULT;
+			mutex_unlock(&effects->lock);
+			break;
+		}
+		config->buf_cfg.input_len = buf_cfg32.input_len;
+		config->buf_cfg.output_len = buf_cfg32.output_len;
+		pr_debug("%s: write buf len: %d, read buf len: %d\n",
+			 __func__, effects->config.buf_cfg.output_len,
+			 effects->config.buf_cfg.input_len);
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	case AUDIO_EFFECTS_GET_BUF_AVAIL32: {
+		struct msm_hwacc_buf_avail32 buf_avail;
+
+		memset(&buf_avail, 0, sizeof(buf_avail));
+
+		mutex_lock(&effects->lock);
+		buf_avail.input_num_avail = atomic_read(&effects->in_count);
+		buf_avail.output_num_avail = atomic_read(&effects->out_count);
+		pr_debug("%s: write buf avail: %d, read buf avail: %d\n",
+			 __func__, buf_avail.output_num_avail,
+			 buf_avail.input_num_avail);
+		if (copy_to_user((void *)arg, &buf_avail,
+				   sizeof(buf_avail))) {
+			pr_err("%s: copy to user for AUDIO_EFFECTS_GET_NUM_BUF_AVAIL failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	case AUDIO_EFFECTS_SET_PP_PARAMS32: {
+		long argvalues[MAX_PP_PARAMS_SZ] = {0};
+		int argvalues32[MAX_PP_PARAMS_SZ] = {0};
+
+		mutex_lock(&effects->lock);
+		if (copy_from_user(argvalues32, (void *)arg,
+				   MAX_PP_PARAMS_SZ*sizeof(int))) {
+			pr_err("%s: copy from user failed for pp params\n",
+				__func__);
+			mutex_unlock(&effects->lock);
+			return -EFAULT;
+		}
+		for (i = 0; i < MAX_PP_PARAMS_SZ; i++)
+			argvalues[i] = argvalues32[i];
+
+		rc = audio_effects_set_pp_param(effects, argvalues);
+		mutex_unlock(&effects->lock);
+		break;
+	}
+	case AUDIO_START32: {
+		rc = audio_effects_shared_ioctl(file, AUDIO_START, arg);
+		break;
+	}
+	case AUDIO_EFFECTS_WRITE32: {
+		rc = audio_effects_shared_ioctl(file, AUDIO_EFFECTS_WRITE, arg);
+		break;
+	}
+	case AUDIO_EFFECTS_READ32: {
+		rc = audio_effects_shared_ioctl(file, AUDIO_EFFECTS_READ, arg);
+		break;
+	}
+	default:
+		pr_debug("%s: unhandled ioctl\n", __func__);
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+#endif
+
+static int audio_effects_release(struct inode *inode, struct file *file)
+{
+	struct q6audio_effects *effects = file->private_data;
+	int rc = 0;
+
+	if (!effects) {
+		pr_err("%s: effect is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (effects->opened) {
+		rc = wait_event_timeout(effects->write_wait,
+					atomic_read(&effects->out_count),
+					WAIT_TIMEDOUT_DURATION_SECS * HZ);
+		if (!rc)
+			pr_err("%s: write wait_event_timeout failed\n",
+				__func__);
+		rc = wait_event_timeout(effects->read_wait,
+					atomic_read(&effects->in_count),
+					WAIT_TIMEDOUT_DURATION_SECS * HZ);
+		if (!rc)
+			pr_err("%s: read wait_event_timeout failed\n",
+				__func__);
+		rc = q6asm_cmd(effects->ac, CMD_CLOSE);
+		if (rc < 0)
+			pr_err("%s[%pK]:Failed to close the session rc=%d\n",
+				__func__, effects, rc);
+		effects->opened = 0;
+		effects->started = 0;
+
+		audio_effects_deinit_pp(effects->ac);
+	}
+
+	if (effects->buf_alloc) {
+		q6asm_audio_client_buf_free_contiguous(IN, effects->ac);
+		q6asm_audio_client_buf_free_contiguous(OUT, effects->ac);
+	}
+	q6asm_audio_client_free(effects->ac);
+
+	mutex_destroy(&effects->lock);
+	kfree(effects);
+
+	pr_debug("%s: close session success\n", __func__);
+	return rc;
+}
+
+static int audio_effects_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_effects *effects;
+	int rc = 0;
+
+	effects = kzalloc(sizeof(struct q6audio_effects), GFP_KERNEL);
+	if (!effects)
+		return -ENOMEM;
+
+	effects->ac = q6asm_audio_client_alloc(
+					(app_cb)audio_effects_event_handler,
+					(void *)effects);
+	if (!effects->ac) {
+		pr_err("%s: Could not allocate memory for audio client\n",
+			__func__);
+		kfree(effects);
+		return -ENOMEM;
+	}
+
+	init_waitqueue_head(&effects->read_wait);
+	init_waitqueue_head(&effects->write_wait);
+	mutex_init(&effects->lock);
+
+	effects->opened = 0;
+	effects->started = 0;
+	effects->buf_alloc = 0;
+	file->private_data = effects;
+	pr_debug("%s: open session success\n", __func__);
+	return rc;
+}
+
+static const struct file_operations audio_effects_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_effects_open,
+	.release = audio_effects_release,
+	.unlocked_ioctl = audio_effects_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = audio_effects_compat_ioctl,
+#endif
+};
+
+struct miscdevice audio_effects_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_hweffects",
+	.fops = &audio_effects_fops,
+};
+
+static int __init audio_effects_init(void)
+{
+	return misc_register(&audio_effects_misc);
+}
+
+device_initcall(audio_effects_init);
+MODULE_DESCRIPTION("Audio hardware accelerated effects driver");
+MODULE_LICENSE("GPL v2");

+ 188 - 0
drivers/misc/qcom/qdsp6v2/audio_mp3.c

@@ -0,0 +1,188 @@
+/* mp3 audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 "audio_utils_aio.h"
+
+static struct miscdevice audio_mp3_misc;
+static struct ws_mgr audio_mp3_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_mp3_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			rc = enable_volume_ramp(audio);
+			if (rc < 0) {
+				pr_err("%s: Failed to enable volume ramp\n",
+					__func__);
+			}
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_info("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+						audio->ac->session,
+						audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_mp3_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_mp3_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_mp3_ws_mgr;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_MP3);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		/* open MP3 decoder, expected frames is always 1
+		 * audio->buf_cfg.frames_per_buf = 0x01;
+		 */
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_MP3);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof(name), "msm_mp3_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
+					    NULL, (void *)audio,
+					    &audio_mp3_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:mp3dec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_mp3_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+};
+
+static struct miscdevice audio_mp3_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_mp3",
+	.fops = &audio_mp3_fops,
+};
+
+static int __init audio_mp3_init(void)
+{
+	int ret = misc_register(&audio_mp3_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_mp3_misc.this_device, true);
+	audio_mp3_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_mp3_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_mp3_init);

+ 523 - 0
drivers/misc/qcom/qdsp6v2/audio_multi_aac.c

@@ -0,0 +1,523 @@
+/* aac audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/msm_audio_aac.h>
+#include <linux/compat.h>
+#include <soc/qcom/socinfo.h>
+#include "audio_utils_aio.h"
+
+#define AUDIO_AAC_DUAL_MONO_INVALID -1
+
+
+/* Default number of pre-allocated event packets */
+#define PCM_BUFSZ_MIN_AACM	((8*1024) + sizeof(struct dec_meta_out))
+static struct miscdevice audio_multiaac_misc;
+static struct ws_mgr audio_multiaac_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_aac_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+						void *arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct asm_aac_cfg aac_cfg;
+		struct msm_audio_aac_config *aac_config;
+		uint32_t sbr_ps = 0x00;
+
+		aac_config = (struct msm_audio_aac_config *)audio->codec_cfg;
+		if (audio->feedback == TUNNEL_MODE) {
+			aac_cfg.sample_rate = aac_config->sample_rate;
+			aac_cfg.ch_cfg = aac_config->channel_configuration;
+		} else {
+			aac_cfg.sample_rate =  audio->pcm_cfg.sample_rate;
+			aac_cfg.ch_cfg = audio->pcm_cfg.channel_count;
+		}
+		pr_debug("%s: AUDIO_START session_id[%d]\n", __func__,
+						audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm_native(audio->ac,
+				aac_cfg.sample_rate,
+				aac_cfg.ch_cfg);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+		/* turn on both sbr and ps */
+		rc = q6asm_enable_sbrps(audio->ac, sbr_ps);
+		if (rc < 0)
+			pr_err("sbr-ps enable failed\n");
+		if (aac_config->sbr_ps_on_flag)
+			aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
+		else if (aac_config->sbr_on_flag)
+			aac_cfg.aot = AAC_ENC_MODE_AAC_P;
+		else
+			aac_cfg.aot = AAC_ENC_MODE_AAC_LC;
+
+		switch (aac_config->format) {
+		case AUDIO_AAC_FORMAT_ADTS:
+			aac_cfg.format = 0x00;
+			break;
+		case AUDIO_AAC_FORMAT_LOAS:
+			aac_cfg.format = 0x01;
+			break;
+		case AUDIO_AAC_FORMAT_ADIF:
+			aac_cfg.format = 0x02;
+			break;
+		default:
+		case AUDIO_AAC_FORMAT_RAW:
+			aac_cfg.format = 0x03;
+		}
+		aac_cfg.ep_config = aac_config->ep_config;
+		aac_cfg.section_data_resilience =
+			aac_config->aac_section_data_resilience_flag;
+		aac_cfg.scalefactor_data_resilience =
+			aac_config->aac_scalefactor_data_resilience_flag;
+		aac_cfg.spectral_data_resilience =
+			aac_config->aac_spectral_data_resilience_flag;
+
+		pr_debug("%s:format=%x aot=%d  ch=%d sr=%d\n",
+			__func__, aac_cfg.format,
+			aac_cfg.aot, aac_cfg.ch_cfg,
+			aac_cfg.sample_rate);
+
+		/* Configure Media format block */
+		rc = q6asm_media_format_block_multi_aac(audio->ac, &aac_cfg);
+		if (rc < 0) {
+			pr_err("cmd media format block failed\n");
+			break;
+		}
+		rc = q6asm_set_encdec_chan_map(audio->ac, 2);
+		if (rc < 0) {
+			pr_err("%s: cmd set encdec_chan_map failed\n",
+				__func__);
+			break;
+		}
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_info("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+						audio->ac->session,
+						audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	case AUDIO_SET_AAC_CONFIG: {
+		struct msm_audio_aac_config *aac_config;
+		uint16_t sce_left = 1, sce_right = 2;
+
+		if (arg == NULL) {
+			pr_err("%s: NULL config pointer\n", __func__);
+			rc = -EINVAL;
+			break;
+		}
+		memcpy(audio->codec_cfg, arg,
+				sizeof(struct msm_audio_aac_config));
+		aac_config = audio->codec_cfg;
+		if (aac_config->dual_mono_mode >
+		    AUDIO_AAC_DUAL_MONO_PL_SR) {
+			pr_err("%s:AUDIO_SET_AAC_CONFIG: Invalid dual_mono mode =%d\n",
+				 __func__, aac_config->dual_mono_mode);
+		} else {
+			/* convert the data from user into sce_left
+			 * and sce_right based on the definitions
+			 */
+			pr_debug("%s: AUDIO_SET_AAC_CONFIG: modify dual_mono mode =%d\n",
+				 __func__, aac_config->dual_mono_mode);
+			switch (aac_config->dual_mono_mode) {
+			case AUDIO_AAC_DUAL_MONO_PL_PR:
+				sce_left = 1;
+				sce_right = 1;
+				break;
+			case AUDIO_AAC_DUAL_MONO_SL_SR:
+				sce_left = 2;
+				sce_right = 2;
+				break;
+			case AUDIO_AAC_DUAL_MONO_SL_PR:
+				sce_left = 2;
+				sce_right = 1;
+				break;
+			case AUDIO_AAC_DUAL_MONO_PL_SR:
+			default:
+				sce_left = 1;
+				sce_right = 2;
+				break;
+			}
+			rc = q6asm_cfg_dual_mono_aac(audio->ac,
+						sce_left, sce_right);
+			if (rc < 0)
+				pr_err("%s: asm cmd dualmono failed rc=%d\n",
+							 __func__, rc);
+		}			break;
+		break;
+	}
+	case AUDIO_SET_AAC_MIX_CONFIG:	{
+		u32 *mix_coeff = (u32 *)arg;
+
+		if (!arg) {
+			pr_err("%s: Invalid param for %s\n",
+				__func__, "AUDIO_SET_AAC_MIX_CONFIG");
+			rc = -EINVAL;
+			break;
+		}
+		pr_debug("%s, AUDIO_SET_AAC_MIX_CONFIG", __func__);
+		pr_debug("%s, value of coeff = %d",
+					__func__, *mix_coeff);
+		q6asm_cfg_aac_sel_mix_coef(audio->ac, *mix_coeff);
+		if (rc < 0)
+			pr_err("%s asm aac_sel_mix_coef failed rc=%d\n",
+				 __func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_AAC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->codec_cfg,
+			sizeof(struct msm_audio_aac_config))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG failed\n"
+				, __func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_AAC_CONFIG: {
+		struct msm_audio_aac_config aac_config;
+
+		if (copy_from_user(&aac_config, (void *)arg,
+			sizeof(aac_config))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AAC_CONFIG failed\n"
+				, __func__);
+			rc = -EFAULT;
+		}
+		rc = audio_ioctl_shared(file, cmd, &aac_config);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	case AUDIO_SET_AAC_MIX_CONFIG:	{
+		u32 mix_config;
+
+		pr_debug("%s, AUDIO_SET_AAC_MIX_CONFIG", __func__);
+		if (copy_from_user(&mix_config, (void *)arg,
+			sizeof(u32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AAC_MIX_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = audio_ioctl_shared(file, cmd, &mix_config);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n",
+			__func__, rc);
+		break;
+	}
+	default: {
+		pr_debug("Calling utils ioctl\n");
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_aac_config32 {
+	s16 format;
+	u16 audio_object;
+	u16 ep_config;  /* 0 ~ 3 useful only obj = ERLC */
+	u16 aac_section_data_resilience_flag;
+	u16 aac_scalefactor_data_resilience_flag;
+	u16 aac_spectral_data_resilience_flag;
+	u16 sbr_on_flag;
+	u16 sbr_ps_on_flag;
+	u16 dual_mono_mode;
+	u16 channel_configuration;
+	u16 sample_rate;
+};
+
+enum {
+	AUDIO_SET_AAC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+		(AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_aac_config32),
+	AUDIO_GET_AAC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+		(AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_aac_config32),
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+							unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_AAC_CONFIG_32: {
+		struct msm_audio_aac_config *aac_config;
+		struct msm_audio_aac_config32 aac_config_32;
+
+		memset(&aac_config_32, 0, sizeof(aac_config_32));
+
+		aac_config = (struct msm_audio_aac_config *)audio->codec_cfg;
+		aac_config_32.format = aac_config->format;
+		aac_config_32.audio_object = aac_config->audio_object;
+		aac_config_32.ep_config = aac_config->ep_config;
+		aac_config_32.aac_section_data_resilience_flag =
+			aac_config->aac_section_data_resilience_flag;
+		aac_config_32.aac_scalefactor_data_resilience_flag =
+			aac_config->aac_scalefactor_data_resilience_flag;
+		aac_config_32.aac_spectral_data_resilience_flag =
+			aac_config->aac_spectral_data_resilience_flag;
+		aac_config_32.sbr_on_flag = aac_config->sbr_on_flag;
+		aac_config_32.sbr_ps_on_flag = aac_config->sbr_ps_on_flag;
+		aac_config_32.dual_mono_mode = aac_config->dual_mono_mode;
+		aac_config_32.channel_configuration =
+			aac_config->channel_configuration;
+		aac_config_32.sample_rate = aac_config->sample_rate;
+
+		if (copy_to_user((void *)arg, &aac_config_32,
+			sizeof(aac_config_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_AAC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_AAC_CONFIG_32: {
+		struct msm_audio_aac_config aac_config;
+		struct msm_audio_aac_config32 aac_config_32;
+
+		pr_debug("%s: AUDIO_SET_AAC_CONFIG\n", __func__);
+		if (copy_from_user(&aac_config_32, (void *)arg,
+			sizeof(aac_config_32))) {
+			pr_err(
+				"%s: copy_from_user for AUDIO_SET_AAC_CONFIG_32 failed",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		aac_config.format = aac_config_32.format;
+		aac_config.audio_object = aac_config_32.audio_object;
+		aac_config.ep_config = aac_config_32.ep_config;
+		aac_config.aac_section_data_resilience_flag =
+			aac_config_32.aac_section_data_resilience_flag;
+		aac_config.aac_scalefactor_data_resilience_flag =
+			aac_config_32.aac_scalefactor_data_resilience_flag;
+		aac_config.aac_spectral_data_resilience_flag =
+			aac_config_32.aac_spectral_data_resilience_flag;
+		aac_config.sbr_on_flag = aac_config_32.sbr_on_flag;
+		aac_config.sbr_ps_on_flag = aac_config_32.sbr_ps_on_flag;
+		aac_config.dual_mono_mode = aac_config_32.dual_mono_mode;
+		aac_config.channel_configuration =
+				aac_config_32.channel_configuration;
+		aac_config.sample_rate = aac_config_32.sample_rate;
+
+		cmd = AUDIO_SET_AAC_CONFIG;
+		rc = audio_ioctl_shared(file, cmd, &aac_config);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_CONFIG failed. rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	case AUDIO_SET_AAC_MIX_CONFIG: {
+		u32 mix_config;
+
+		pr_debug("%s, AUDIO_SET_AAC_MIX_CONFIG\n", __func__);
+		if (copy_from_user(&mix_config, (void *)arg,
+			sizeof(u32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_AAC_MIX_CONFIG failed\n"
+				, __func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = audio_ioctl_shared(file, cmd, &mix_config);
+		if (rc)
+			pr_err("%s:AUDIO_SET_AAC_CONFIG failed. Rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default: {
+		pr_debug("Calling utils ioctl\n");
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+	}
+	}
+	return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+	struct msm_audio_aac_config *aac_config = NULL;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_multi_aac_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	audio->codec_cfg = kzalloc(sizeof(struct msm_audio_aac_config),
+					GFP_KERNEL);
+	if (audio->codec_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	aac_config = audio->codec_cfg;
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN_AACM;
+	audio->miscdevice = &audio_multiaac_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_multiaac_ws_mgr;
+	aac_config->dual_mono_mode = AUDIO_AAC_DUAL_MONO_INVALID;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio->codec_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_MPEG4_MULTI_AAC);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		/* open AAC decoder, expected frames is always 1
+		 * audio->buf_cfg.frames_per_buf = 0x01;
+		 */
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_MPEG4_MULTI_AAC);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof(name), "msm_multi_aac_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
+					    NULL, (void *)audio,
+					    &audio_aac_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:AAC 5.1 Decoder OPEN success mode[%d]session[%d]\n",
+		__func__, audio->feedback, audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_aac_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+	.compat_ioctl = audio_compat_ioctl
+};
+
+static struct miscdevice audio_multiaac_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_multi_aac",
+	.fops = &audio_aac_fops,
+};
+
+static int __init audio_aac_init(void)
+{
+	int ret = misc_register(&audio_multiaac_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_multiaac_misc.this_device, true);
+	audio_multiaac_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_multiaac_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_aac_init);

+ 191 - 0
drivers/misc/qcom/qdsp6v2/audio_qcelp.c

@@ -0,0 +1,191 @@
+/* qcelp(v13k) audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 "audio_utils_aio.h"
+
+#define FRAME_SIZE_DEC_QCELP  ((32) + sizeof(struct dec_meta_in))
+
+static struct miscdevice audio_qcelp_misc;
+static struct ws_mgr audio_qcelp_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_qcelp_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+						audio->ac->session,
+						audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_qcelp_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->str_cfg.buffer_size = FRAME_SIZE_DEC_QCELP;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	audio->pcm_cfg.sample_rate = 8000;
+	audio->pcm_cfg.channel_count = 1;
+	audio->miscdevice = &audio_qcelp_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_qcelp_ws_mgr;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_V13K);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_V13K);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof(name), "msm_qcelp_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
+					    NULL, (void *)audio,
+					    &audio_qcelp_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:dec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_qcelp_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+};
+
+static struct miscdevice audio_qcelp_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_qcelp",
+	.fops = &audio_qcelp_fops,
+};
+
+static int __init audio_qcelp_init(void)
+{
+	int ret = misc_register(&audio_qcelp_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_qcelp_misc.this_device, true);
+	audio_qcelp_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_qcelp_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_qcelp_init);

+ 954 - 0
drivers/misc/qcom/qdsp6v2/audio_utils.c

@@ -0,0 +1,954 @@
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/atomic.h>
+#include <linux/compat.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+/*
+ * Define maximum buffer size. Below values are chosen considering the higher
+ * values used among all native drivers.
+ */
+#define MAX_FRAME_SIZE	1536
+#define MAX_FRAMES	5
+#define META_SIZE	(sizeof(struct meta_out_dsp))
+#define MAX_BUFFER_SIZE	(1 + ((MAX_FRAME_SIZE + META_SIZE) * MAX_FRAMES))
+
+static int audio_in_pause(struct q6audio_in  *audio)
+{
+	int rc;
+
+	rc = q6asm_cmd(audio->ac, CMD_PAUSE);
+	if (rc < 0)
+		pr_err("%s:session id %d: pause cmd failed rc=%d\n", __func__,
+				audio->ac->session, rc);
+
+	return rc;
+}
+
+static int audio_in_flush(struct q6audio_in  *audio)
+{
+	int rc;
+
+	pr_debug("%s:session id %d: flush\n", __func__, audio->ac->session);
+	/* Flush if session running */
+	if (audio->enabled) {
+		/* Implicitly issue a pause to the encoder before flushing */
+		rc = audio_in_pause(audio);
+		if (rc < 0) {
+			pr_err("%s:session id %d: pause cmd failed rc=%d\n",
+				 __func__, audio->ac->session, rc);
+			return rc;
+		}
+
+		rc = q6asm_cmd(audio->ac, CMD_FLUSH);
+		if (rc < 0) {
+			pr_err("%s:session id %d: flush cmd failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			return rc;
+		}
+		/* 2nd arg: 0 -> run immediately
+		 * 3rd arg: 0 -> msw_ts,
+		 * 4th arg: 0 ->lsw_ts
+		 */
+		q6asm_run(audio->ac, 0x00, 0x00, 0x00);
+		pr_debug("Rerun the session\n");
+	}
+	audio->rflush = 1;
+	audio->wflush = 1;
+	memset(audio->out_frame_info, 0, sizeof(audio->out_frame_info));
+	wake_up(&audio->read_wait);
+	/* get read_lock to ensure no more waiting read thread */
+	mutex_lock(&audio->read_lock);
+	audio->rflush = 0;
+	mutex_unlock(&audio->read_lock);
+	wake_up(&audio->write_wait);
+	/* get write_lock to ensure no more waiting write thread */
+	mutex_lock(&audio->write_lock);
+	audio->wflush = 0;
+	mutex_unlock(&audio->write_lock);
+	pr_debug("%s:session id %d: in_bytes %d\n", __func__,
+			audio->ac->session, atomic_read(&audio->in_bytes));
+	pr_debug("%s:session id %d: in_samples %d\n", __func__,
+			audio->ac->session, atomic_read(&audio->in_samples));
+	atomic_set(&audio->in_bytes, 0);
+	atomic_set(&audio->in_samples, 0);
+	atomic_set(&audio->out_count, 0);
+	return 0;
+}
+
+/* must be called with audio->lock held */
+int audio_in_enable(struct q6audio_in  *audio)
+{
+	if (audio->enabled)
+		return 0;
+
+	/* 2nd arg: 0 -> run immediately
+	 * 3rd arg: 0 -> msw_ts,
+	 * 4th arg: 0 ->lsw_ts
+	 */
+	return q6asm_run(audio->ac, 0x00, 0x00, 0x00);
+}
+
+/* must be called with audio->lock held */
+int audio_in_disable(struct q6audio_in  *audio)
+{
+	int rc = 0;
+
+	if (!audio->stopped) {
+		audio->enabled = 0;
+		audio->opened = 0;
+		pr_debug("%s:session id %d: inbytes[%d] insamples[%d]\n",
+				__func__, audio->ac->session,
+				atomic_read(&audio->in_bytes),
+				atomic_read(&audio->in_samples));
+
+		rc = q6asm_cmd(audio->ac, CMD_CLOSE);
+		if (rc < 0)
+			pr_err("%s:session id %d: Failed to close the session rc=%d\n",
+				__func__, audio->ac->session,
+				rc);
+		audio->stopped = 1;
+		memset(audio->out_frame_info, 0,
+				sizeof(audio->out_frame_info));
+		wake_up(&audio->read_wait);
+		wake_up(&audio->write_wait);
+	}
+	pr_debug("%s:session id %d: enabled[%d]\n", __func__,
+			audio->ac->session, audio->enabled);
+	return rc;
+}
+
+int audio_in_buf_alloc(struct q6audio_in *audio)
+{
+	int rc = 0;
+
+	switch (audio->buf_alloc) {
+	case NO_BUF_ALLOC:
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			rc = q6asm_audio_client_buf_alloc(IN,
+				audio->ac,
+				ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size),
+				audio->pcm_cfg.buffer_count);
+			if (rc < 0) {
+				pr_err("%s:session id %d: Buffer Alloc failed\n",
+						__func__,
+						audio->ac->session);
+				rc = -ENOMEM;
+				break;
+			}
+			audio->buf_alloc |= BUF_ALLOC_IN;
+		}
+		rc = q6asm_audio_client_buf_alloc(OUT, audio->ac,
+				ALIGN_BUF_SIZE(audio->str_cfg.buffer_size),
+				audio->str_cfg.buffer_count);
+		if (rc < 0) {
+			pr_err("%s:session id %d: Buffer Alloc failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+			rc = -ENOMEM;
+			break;
+		}
+		audio->buf_alloc |= BUF_ALLOC_OUT;
+		break;
+	case BUF_ALLOC_IN:
+		rc = q6asm_audio_client_buf_alloc(OUT, audio->ac,
+				ALIGN_BUF_SIZE(audio->str_cfg.buffer_size),
+				audio->str_cfg.buffer_count);
+		if (rc < 0) {
+			pr_err("%s:session id %d: Buffer Alloc failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+			rc = -ENOMEM;
+			break;
+		}
+		audio->buf_alloc |= BUF_ALLOC_OUT;
+		break;
+	case BUF_ALLOC_OUT:
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			rc = q6asm_audio_client_buf_alloc(IN, audio->ac,
+				ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size),
+				audio->pcm_cfg.buffer_count);
+			if (rc < 0) {
+				pr_err("%s:session id %d: Buffer Alloc failed\n",
+					__func__,
+					audio->ac->session);
+				rc = -ENOMEM;
+				break;
+			}
+			audio->buf_alloc |= BUF_ALLOC_IN;
+		}
+		break;
+	default:
+		pr_debug("%s:session id %d: buf[%d]\n", __func__,
+					audio->ac->session, audio->buf_alloc);
+	}
+
+	return rc;
+}
+
+int audio_in_set_config(struct file *file,
+		struct msm_audio_config *cfg)
+{
+	int rc = 0;
+	struct q6audio_in  *audio = file->private_data;
+
+	if (audio->feedback != NON_TUNNEL_MODE) {
+		pr_err("%s:session id %d: Not sufficient permission to change the record mode\n",
+			__func__, audio->ac->session);
+		rc = -EACCES;
+		goto ret;
+	}
+	if ((cfg->buffer_count > PCM_BUF_COUNT) ||
+		(cfg->buffer_count == 1))
+		cfg->buffer_count = PCM_BUF_COUNT;
+
+	audio->pcm_cfg.buffer_count = cfg->buffer_count;
+	audio->pcm_cfg.buffer_size  = cfg->buffer_size;
+	audio->pcm_cfg.channel_count = cfg->channel_count;
+	audio->pcm_cfg.sample_rate = cfg->sample_rate;
+	if (audio->opened && audio->feedback == NON_TUNNEL_MODE) {
+		rc = q6asm_audio_client_buf_alloc(IN, audio->ac,
+			ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size),
+			audio->pcm_cfg.buffer_count);
+		if (rc < 0) {
+			pr_err("%s:session id %d: Buffer Alloc failed\n",
+				__func__, audio->ac->session);
+			rc = -ENOMEM;
+			goto ret;
+		}
+	}
+	audio->buf_alloc |= BUF_ALLOC_IN;
+	rc = 0;
+	pr_debug("%s:session id %d: AUDIO_SET_CONFIG %d %d\n", __func__,
+			audio->ac->session, audio->pcm_cfg.buffer_count,
+			audio->pcm_cfg.buffer_size);
+ret:
+	return rc;
+}
+/* ------------------- device --------------------- */
+static long audio_in_ioctl_shared(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_FLUSH: {
+		/* Make sure we're stopped and we wake any threads
+		 * that might be blocked holding the read_lock.
+		 * While audio->stopped read threads will always
+		 * exit immediately.
+		 */
+		rc = audio_in_flush(audio);
+		if (rc < 0)
+			pr_err("%s:session id %d: Flush Fail rc=%d\n",
+				__func__, audio->ac->session, rc);
+		else { /* Register back the flushed read buffer with DSP */
+			int cnt = 0;
+
+			while (cnt++ < audio->str_cfg.buffer_count)
+				q6asm_read(audio->ac); /* Push buffer to DSP */
+			pr_debug("register the read buffer\n");
+		}
+		break;
+	}
+	case AUDIO_PAUSE: {
+		pr_debug("%s:session id %d: AUDIO_PAUSE\n", __func__,
+					audio->ac->session);
+		if (audio->enabled)
+			audio_in_pause(audio);
+		break;
+	}
+	case AUDIO_GET_SESSION_ID: {
+		if (copy_to_user((void *) arg, &audio->ac->session,
+			sizeof(u16))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_SESSION_ID failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+long audio_in_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	if (cmd == AUDIO_GET_STATS) {
+		struct msm_audio_stats stats;
+
+		memset(&stats, 0, sizeof(stats));
+		stats.byte_count = atomic_read(&audio->in_bytes);
+		stats.sample_count = atomic_read(&audio->in_samples);
+		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
+			return -EFAULT;
+		return rc;
+	}
+
+	mutex_lock(&audio->lock);
+	switch (cmd) {
+	case AUDIO_FLUSH:
+	case AUDIO_PAUSE:
+	case AUDIO_GET_SESSION_ID:
+		rc = audio_in_ioctl_shared(file, cmd, arg);
+		break;
+	case AUDIO_GET_STREAM_CONFIG: {
+		struct msm_audio_stream_config cfg;
+
+		memset(&cfg, 0, sizeof(cfg));
+		cfg.buffer_size = audio->str_cfg.buffer_size;
+		cfg.buffer_count = audio->str_cfg.buffer_count;
+		if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
+			rc = -EFAULT;
+		pr_debug("%s:session id %d: AUDIO_GET_STREAM_CONFIG %d %d\n",
+				__func__, audio->ac->session, cfg.buffer_size,
+				cfg.buffer_count);
+		break;
+	}
+	case AUDIO_SET_STREAM_CONFIG: {
+		struct msm_audio_stream_config cfg;
+
+		if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_STREAM_CONFIG failed\n"
+				, __func__);
+			rc = -EFAULT;
+			break;
+		}
+		/* Minimum single frame size,
+		 * but with in maximum frames number
+		 */
+		if ((cfg.buffer_size < (audio->min_frame_size +
+			sizeof(struct meta_out_dsp))) ||
+			(cfg.buffer_count < FRAME_NUM)) {
+			rc = -EINVAL;
+			break;
+		}
+		if (cfg.buffer_size > MAX_BUFFER_SIZE) {
+			rc = -EINVAL;
+			break;
+		}
+		audio->str_cfg.buffer_size = cfg.buffer_size;
+		audio->str_cfg.buffer_count = cfg.buffer_count;
+		if (audio->opened) {
+			rc = q6asm_audio_client_buf_alloc(OUT, audio->ac,
+				ALIGN_BUF_SIZE(audio->str_cfg.buffer_size),
+				audio->str_cfg.buffer_count);
+			if (rc < 0) {
+				pr_err("%s: session id %d: Buffer Alloc failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+				rc = -ENOMEM;
+				break;
+			}
+		}
+		audio->buf_alloc |= BUF_ALLOC_OUT;
+		rc = 0;
+		pr_debug("%s:session id %d: AUDIO_SET_STREAM_CONFIG %d %d\n",
+				__func__, audio->ac->session,
+				audio->str_cfg.buffer_size,
+				audio->str_cfg.buffer_count);
+		break;
+	}
+	case AUDIO_SET_BUF_CFG: {
+		struct msm_audio_buf_cfg  cfg;
+
+		if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
+			rc = -EFAULT;
+			break;
+		}
+		if ((audio->feedback == NON_TUNNEL_MODE) &&
+			!cfg.meta_info_enable) {
+			rc = -EFAULT;
+			break;
+		}
+
+		/* Restrict the num of frames per buf to coincide with
+		 * default buf size
+		 */
+		if (cfg.frames_per_buf > audio->max_frames_per_buf) {
+			rc = -EFAULT;
+			break;
+		}
+		audio->buf_cfg.meta_info_enable = cfg.meta_info_enable;
+		audio->buf_cfg.frames_per_buf = cfg.frames_per_buf;
+		pr_debug("%s:session id %d: Set-buf-cfg: meta[%d] framesperbuf[%d]\n",
+				__func__,
+				audio->ac->session, cfg.meta_info_enable,
+				cfg.frames_per_buf);
+		break;
+	}
+	case AUDIO_GET_BUF_CFG: {
+		pr_debug("%s:session id %d: Get-buf-cfg: meta[%d] framesperbuf[%d]\n",
+			__func__,
+			audio->ac->session, audio->buf_cfg.meta_info_enable,
+			audio->buf_cfg.frames_per_buf);
+
+		if (copy_to_user((void *)arg, &audio->buf_cfg,
+					sizeof(struct msm_audio_buf_cfg)))
+			rc = -EFAULT;
+		break;
+	}
+	case AUDIO_GET_CONFIG: {
+		if (copy_to_user((void *)arg, &audio->pcm_cfg,
+					sizeof(struct msm_audio_config)))
+			rc = -EFAULT;
+		break;
+
+	}
+	case AUDIO_SET_CONFIG: {
+		struct msm_audio_config cfg;
+
+		if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = audio_in_set_config(file, &cfg);
+		break;
+	}
+	default:
+		/* call codec specific ioctl */
+		rc = audio->enc_ioctl(file, cmd, arg);
+	}
+	mutex_unlock(&audio->lock);
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_stats32 {
+	u32 byte_count;
+	u32 sample_count;
+	u32 unused[2];
+};
+
+struct msm_audio_stream_config32 {
+	u32 buffer_size;
+	u32 buffer_count;
+};
+
+struct msm_audio_config32 {
+	u32 buffer_size;
+	u32 buffer_count;
+	u32 channel_count;
+	u32 sample_rate;
+	u32 type;
+	u32 meta_field;
+	u32 bits;
+	u32 unused[3];
+};
+
+struct msm_audio_buf_cfg32 {
+	u32 meta_info_enable;
+	u32 frames_per_buf;
+};
+
+enum {
+	AUDIO_GET_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, 3,
+			struct msm_audio_config32),
+	AUDIO_SET_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, 4,
+			struct msm_audio_config32),
+	AUDIO_GET_STATS_32 = _IOR(AUDIO_IOCTL_MAGIC, 5,
+			struct msm_audio_stats32),
+	AUDIO_SET_STREAM_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, 80,
+			struct msm_audio_stream_config32),
+	AUDIO_GET_STREAM_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, 81,
+			struct msm_audio_stream_config32),
+	AUDIO_SET_BUF_CFG_32 = _IOW(AUDIO_IOCTL_MAGIC, 94,
+			struct msm_audio_buf_cfg32),
+	AUDIO_GET_BUF_CFG_32 = _IOW(AUDIO_IOCTL_MAGIC, 93,
+			struct msm_audio_buf_cfg32),
+};
+
+long audio_in_compat_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	if (cmd == AUDIO_GET_STATS_32) {
+		struct msm_audio_stats32 stats_32;
+
+		memset(&stats_32, 0, sizeof(stats_32));
+		stats_32.byte_count = atomic_read(&audio->in_bytes);
+		stats_32.sample_count = atomic_read(&audio->in_samples);
+		if (copy_to_user((void *) arg, &stats_32, sizeof(stats_32))) {
+			pr_err("%s: copy_to_user failed for AUDIO_GET_STATS_32\n",
+				__func__);
+			return -EFAULT;
+		}
+		return rc;
+	}
+
+	mutex_lock(&audio->lock);
+	switch (cmd) {
+	case AUDIO_FLUSH:
+	case AUDIO_PAUSE:
+	case AUDIO_GET_SESSION_ID:
+		rc = audio_in_ioctl_shared(file, cmd, arg);
+		break;
+	case AUDIO_GET_STREAM_CONFIG_32: {
+		struct msm_audio_stream_config32 cfg_32;
+
+		memset(&cfg_32, 0, sizeof(cfg_32));
+		cfg_32.buffer_size = audio->str_cfg.buffer_size;
+		cfg_32.buffer_count = audio->str_cfg.buffer_count;
+		if (copy_to_user((void *)arg, &cfg_32, sizeof(cfg_32))) {
+			pr_err("%s: Copy to user failed\n", __func__);
+			rc = -EFAULT;
+		}
+		pr_debug("%s:session id %d: AUDIO_GET_STREAM_CONFIG %d %d\n",
+				__func__, audio->ac->session,
+				cfg_32.buffer_size,
+				cfg_32.buffer_count);
+		break;
+	}
+	case AUDIO_SET_STREAM_CONFIG_32: {
+		struct msm_audio_stream_config32 cfg_32;
+		struct msm_audio_stream_config cfg;
+
+		if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_STREAM_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		cfg.buffer_size = cfg_32.buffer_size;
+		cfg.buffer_count = cfg_32.buffer_count;
+		/* Minimum single frame size,
+		 * but with in maximum frames number
+		 */
+		if ((cfg.buffer_size < (audio->min_frame_size +
+			sizeof(struct meta_out_dsp))) ||
+			(cfg.buffer_count < FRAME_NUM)) {
+			rc = -EINVAL;
+			break;
+		}
+		audio->str_cfg.buffer_size = cfg.buffer_size;
+		audio->str_cfg.buffer_count = cfg.buffer_count;
+		if (audio->opened) {
+			rc = q6asm_audio_client_buf_alloc(OUT, audio->ac,
+				ALIGN_BUF_SIZE(audio->str_cfg.buffer_size),
+				audio->str_cfg.buffer_count);
+			if (rc < 0) {
+				pr_err("%s: session id %d:\n",
+					__func__, audio->ac->session);
+				pr_err("Buffer Alloc failed rc=%d\n", rc);
+				rc = -ENOMEM;
+				break;
+			}
+		}
+		audio->buf_alloc |= BUF_ALLOC_OUT;
+		pr_debug("%s:session id %d: AUDIO_SET_STREAM_CONFIG %d %d\n",
+				__func__, audio->ac->session,
+				audio->str_cfg.buffer_size,
+				audio->str_cfg.buffer_count);
+		break;
+	}
+	case AUDIO_SET_BUF_CFG_32: {
+		struct msm_audio_buf_cfg32 cfg_32;
+		struct msm_audio_buf_cfg cfg;
+
+		if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_BUG_CFG_32 failed",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		cfg.meta_info_enable = cfg_32.meta_info_enable;
+		cfg.frames_per_buf = cfg_32.frames_per_buf;
+
+		if ((audio->feedback == NON_TUNNEL_MODE) &&
+			!cfg.meta_info_enable) {
+			rc = -EFAULT;
+			break;
+		}
+
+		/* Restrict the num of frames per buf to coincide with
+		 * default buf size
+		 */
+		if (cfg.frames_per_buf > audio->max_frames_per_buf) {
+			rc = -EFAULT;
+			break;
+		}
+		audio->buf_cfg.meta_info_enable = cfg.meta_info_enable;
+		audio->buf_cfg.frames_per_buf = cfg.frames_per_buf;
+		pr_debug("%s:session id %d: Set-buf-cfg: meta[%d] framesperbuf[%d]\n",
+			__func__, audio->ac->session, cfg.meta_info_enable,
+			cfg.frames_per_buf);
+		break;
+	}
+	case AUDIO_GET_BUF_CFG_32: {
+		struct msm_audio_buf_cfg32 cfg_32;
+
+		pr_debug("%s:session id %d: Get-buf-cfg: meta[%d] framesperbuf[%d]\n",
+			__func__,
+			audio->ac->session, audio->buf_cfg.meta_info_enable,
+			audio->buf_cfg.frames_per_buf);
+		cfg_32.meta_info_enable = audio->buf_cfg.meta_info_enable;
+		cfg_32.frames_per_buf = audio->buf_cfg.frames_per_buf;
+
+		if (copy_to_user((void *)arg, &cfg_32,
+			sizeof(struct msm_audio_buf_cfg32))) {
+			pr_err("%s: Copy to user failed\n", __func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_GET_CONFIG_32: {
+		struct msm_audio_config32 cfg_32;
+
+		memset(&cfg_32, 0, sizeof(cfg_32));
+		cfg_32.buffer_size = audio->pcm_cfg.buffer_size;
+		cfg_32.buffer_count = audio->pcm_cfg.buffer_count;
+		cfg_32.channel_count = audio->pcm_cfg.channel_count;
+		cfg_32.sample_rate = audio->pcm_cfg.sample_rate;
+		cfg_32.type = audio->pcm_cfg.type;
+		cfg_32.meta_field = audio->pcm_cfg.meta_field;
+		cfg_32.bits = audio->pcm_cfg.bits;
+
+		if (copy_to_user((void *)arg, &cfg_32,
+					sizeof(struct msm_audio_config32))) {
+			pr_err("%s: Copy to user failed\n", __func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_CONFIG_32: {
+		struct msm_audio_config32 cfg_32;
+		struct msm_audio_config cfg;
+
+		if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		cfg.buffer_size = cfg_32.buffer_size;
+		cfg.buffer_count = cfg_32.buffer_count;
+		cfg.channel_count = cfg_32.channel_count;
+		cfg.sample_rate = cfg_32.sample_rate;
+		cfg.type = cfg_32.type;
+		cfg.meta_field = cfg_32.meta_field;
+		cfg.bits = cfg_32.bits;
+		rc = audio_in_set_config(file, &cfg);
+		break;
+	}
+	default:
+		  /* call codec specific ioctl */
+		  rc = audio->enc_compat_ioctl(file, cmd, arg);
+	}
+	mutex_unlock(&audio->lock);
+	return rc;
+}
+#endif
+
+ssize_t audio_in_read(struct file *file,
+				char __user *buf,
+				size_t count, loff_t *pos)
+{
+	struct q6audio_in  *audio = file->private_data;
+	const char __user *start = buf;
+	unsigned char *data;
+	uint32_t offset = 0;
+	uint32_t size = 0;
+	int rc = 0;
+	uint32_t idx;
+	struct meta_out_dsp meta;
+	uint32_t bytes_to_copy = 0;
+	uint32_t mfield_size = (audio->buf_cfg.meta_info_enable == 0) ? 0 :
+		(sizeof(unsigned char) +
+		(sizeof(struct meta_out_dsp)*(audio->buf_cfg.frames_per_buf)));
+
+	memset(&meta, 0, sizeof(meta));
+	pr_debug("%s:session id %d: read - %zd\n", __func__, audio->ac->session,
+			count);
+	if (audio->reset_event)
+		return -ENETRESET;
+
+	if (!audio->enabled)
+		return -EFAULT;
+	mutex_lock(&audio->read_lock);
+	while (count > 0) {
+		rc = wait_event_interruptible(
+			audio->read_wait,
+			((atomic_read(&audio->out_count) > 0) ||
+			(audio->stopped) ||
+			 audio->rflush || audio->eos_rsp ||
+			audio->event_abort));
+
+		if (audio->event_abort) {
+			rc = -EIO;
+			break;
+		}
+
+
+		if (rc < 0)
+			break;
+
+		if ((audio->stopped && !(atomic_read(&audio->out_count))) ||
+			audio->rflush) {
+			pr_debug("%s:session id %d: driver in stop state or flush,No more buf to read",
+				__func__,
+				audio->ac->session);
+			rc = 0;/* End of File */
+			break;
+		}
+		if (!(atomic_read(&audio->out_count)) &&
+			(audio->eos_rsp == 1) &&
+			(count >= (sizeof(unsigned char) +
+				sizeof(struct meta_out_dsp)))) {
+			unsigned char num_of_frames;
+
+			pr_info("%s:session id %d: eos %d at output\n",
+				__func__, audio->ac->session, audio->eos_rsp);
+			if (buf != start)
+				break;
+			num_of_frames = 0xFF;
+			if (copy_to_user(buf, &num_of_frames,
+					sizeof(unsigned char))) {
+				rc = -EFAULT;
+				break;
+			}
+			buf += sizeof(unsigned char);
+			meta.frame_size = 0xFFFF;
+			meta.encoded_pcm_samples = 0xFFFF;
+			meta.msw_ts = 0x00;
+			meta.lsw_ts = 0x00;
+			meta.nflags = AUD_EOS_SET;
+			audio->eos_rsp = 0;
+			if (copy_to_user(buf, &meta, sizeof(meta))) {
+				rc = -EFAULT;
+				break;
+			}
+			buf += sizeof(meta);
+			break;
+		}
+		data = (unsigned char *)q6asm_is_cpu_buf_avail(OUT, audio->ac,
+						&size, &idx);
+		if ((count >= (size + mfield_size)) && data) {
+			if (audio->buf_cfg.meta_info_enable) {
+				if (copy_to_user(buf,
+					&audio->out_frame_info[idx][0],
+					sizeof(unsigned char))) {
+					rc = -EFAULT;
+					break;
+				}
+				bytes_to_copy =
+					(size + audio->out_frame_info[idx][1]);
+				/* Number of frames information copied */
+				buf += sizeof(unsigned char);
+				count -= sizeof(unsigned char);
+			} else {
+				offset = audio->out_frame_info[idx][1];
+				bytes_to_copy = size;
+			}
+
+			pr_debug("%s:session id %d: offset=%d nr of frames= %d\n",
+					__func__, audio->ac->session,
+					audio->out_frame_info[idx][1],
+					audio->out_frame_info[idx][0]);
+
+			if (copy_to_user(buf, &data[offset], bytes_to_copy)) {
+				rc = -EFAULT;
+				break;
+			}
+			count -= bytes_to_copy;
+			buf += bytes_to_copy;
+		} else {
+			pr_err("%s:session id %d: short read data[%pK] bytesavail[%d]bytesrequest[%zd]\n",
+				__func__,
+				audio->ac->session,
+				data, size, count);
+		}
+		atomic_dec(&audio->out_count);
+		q6asm_read(audio->ac);
+		break;
+	}
+	mutex_unlock(&audio->read_lock);
+
+	pr_debug("%s:session id %d: read: %zd bytes\n", __func__,
+			audio->ac->session, (buf-start));
+	if (buf > start)
+		return buf - start;
+	return rc;
+}
+
+static int extract_meta_info(char *buf, unsigned long *msw_ts,
+		unsigned long *lsw_ts, unsigned int *flags)
+{
+	struct meta_in *meta = (struct meta_in *)buf;
+	*msw_ts = meta->ntimestamp.highpart;
+	*lsw_ts = meta->ntimestamp.lowpart;
+	*flags = meta->nflags;
+	return 0;
+}
+
+ssize_t audio_in_write(struct file *file,
+		const char __user *buf,
+		size_t count, loff_t *pos)
+{
+	struct q6audio_in *audio = file->private_data;
+	const char __user *start = buf;
+	size_t xfer = 0;
+	char *cpy_ptr;
+	int rc = 0;
+	unsigned char *data;
+	uint32_t size = 0;
+	uint32_t idx = 0;
+	uint32_t nflags = 0;
+	unsigned long msw_ts = 0;
+	unsigned long lsw_ts = 0;
+	uint32_t mfield_size = (audio->buf_cfg.meta_info_enable == 0) ? 0 :
+			sizeof(struct meta_in);
+
+	pr_debug("%s:session id %d: to write[%zd]\n", __func__,
+			audio->ac->session, count);
+	if (audio->reset_event)
+		return -ENETRESET;
+
+	if (!audio->enabled)
+		return -EFAULT;
+	mutex_lock(&audio->write_lock);
+
+	while (count > 0) {
+		rc = wait_event_interruptible(audio->write_wait,
+				     ((atomic_read(&audio->in_count) > 0) ||
+				      (audio->stopped) ||
+				      (audio->wflush) || (audio->event_abort)));
+
+		if (audio->event_abort) {
+			rc = -EIO;
+			break;
+		}
+
+		if (rc < 0)
+			break;
+		if (audio->stopped || audio->wflush) {
+			pr_debug("%s: session id %d: stop or flush\n", __func__,
+					audio->ac->session);
+			rc = -EBUSY;
+			break;
+		}
+		/* if no PCM data, might have only eos buffer
+		 * such case do not hold cpu buffer
+		 */
+		if ((buf == start) && (count == mfield_size)) {
+			char eos_buf[sizeof(struct meta_in)];
+			/* Processing beginning of user buffer */
+			if (copy_from_user(eos_buf, buf, mfield_size)) {
+				rc = -EFAULT;
+				break;
+			}
+			/* Check if EOS flag is set and buffer has
+			 * contains just meta field
+			 */
+			extract_meta_info(eos_buf, &msw_ts, &lsw_ts,
+						&nflags);
+			buf += mfield_size;
+			/* send the EOS and return */
+			pr_debug("%s:session id %d: send EOS 0x%8x\n",
+				__func__,
+				audio->ac->session, nflags);
+			break;
+		}
+		data = (unsigned char *)q6asm_is_cpu_buf_avail(IN, audio->ac,
+						&size, &idx);
+		if (!data) {
+			pr_debug("%s:session id %d: No buf available\n",
+				__func__, audio->ac->session);
+			continue;
+		}
+		cpy_ptr = data;
+		if (audio->buf_cfg.meta_info_enable) {
+			if (buf == start) {
+				/* Processing beginning of user buffer */
+				if (copy_from_user(cpy_ptr, buf, mfield_size)) {
+					rc = -EFAULT;
+					break;
+				}
+				/* Check if EOS flag is set and buffer has
+				 * contains just meta field
+				 */
+				extract_meta_info(cpy_ptr, &msw_ts, &lsw_ts,
+						&nflags);
+				buf += mfield_size;
+				count -= mfield_size;
+			} else {
+				pr_debug("%s:session id %d: continuous buffer\n",
+						__func__, audio->ac->session);
+			}
+		}
+		xfer = (count > (audio->pcm_cfg.buffer_size)) ?
+				(audio->pcm_cfg.buffer_size) : count;
+
+		if (copy_from_user(cpy_ptr, buf, xfer)) {
+			rc = -EFAULT;
+			break;
+		}
+		rc = q6asm_write(audio->ac, xfer, msw_ts, lsw_ts, 0x00);
+		if (rc < 0) {
+			rc = -EFAULT;
+			break;
+		}
+		atomic_dec(&audio->in_count);
+		count -= xfer;
+		buf += xfer;
+	}
+	mutex_unlock(&audio->write_lock);
+	pr_debug("%s:session id %d: eos_condition 0x%x buf[0x%pK] start[0x%pK]\n",
+				__func__, audio->ac->session,
+				nflags, buf, start);
+	if (nflags & AUD_EOS_SET) {
+		rc = q6asm_cmd(audio->ac, CMD_EOS);
+		pr_info("%s:session id %d: eos %d at input\n", __func__,
+				audio->ac->session, audio->eos_rsp);
+	}
+	pr_debug("%s:session id %d: Written %zd Avail Buf[%d]", __func__,
+			audio->ac->session, (buf - start - mfield_size),
+			atomic_read(&audio->in_count));
+	if (!rc) {
+		if (buf > start)
+			return buf - start;
+	}
+	return rc;
+}
+
+int audio_in_release(struct inode *inode, struct file *file)
+{
+	struct q6audio_in  *audio = file->private_data;
+
+	pr_info("%s: session id %d\n", __func__, audio->ac->session);
+	mutex_lock(&audio->lock);
+	audio_in_disable(audio);
+	q6asm_audio_client_free(audio->ac);
+	mutex_unlock(&audio->lock);
+	kfree(audio->enc_cfg);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return 0;
+}

+ 114 - 0
drivers/misc/qcom/qdsp6v2/audio_utils.h

@@ -0,0 +1,114 @@
+/* Copyright (c) 2010-2015, 2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/msm_audio.h>
+#include <linux/compat.h>
+#include "q6audio_common.h"
+
+#define FRAME_NUM	(8)
+
+#define PCM_BUF_COUNT		(2)
+
+#define AUD_EOS_SET  0x01
+#define TUNNEL_MODE     0x0000
+#define NON_TUNNEL_MODE 0x0001
+
+#define NO_BUF_ALLOC	0x00
+#define BUF_ALLOC_IN    0x01
+#define BUF_ALLOC_OUT   0x02
+#define BUF_ALLOC_INOUT 0x03
+#define ALIGN_BUF_SIZE(size) ((size + 4095) & (~4095))
+
+struct timestamp {
+	u32 lowpart;
+	u32 highpart;
+} __packed;
+
+struct meta_in {
+	unsigned short offset;
+	struct timestamp ntimestamp;
+	unsigned int nflags;
+} __packed;
+
+struct meta_out_dsp {
+	u32 offset_to_frame;
+	u32 frame_size;
+	u32 encoded_pcm_samples;
+	u32 msw_ts;
+	u32 lsw_ts;
+	u32 nflags;
+} __packed;
+
+struct meta_out {
+	unsigned char num_of_frames;
+	struct meta_out_dsp meta_out_dsp[];
+} __packed;
+
+struct q6audio_in {
+	spinlock_t			dsp_lock;
+	atomic_t			in_bytes;
+	atomic_t			in_samples;
+
+	struct mutex			lock;
+	struct mutex			read_lock;
+	struct mutex			write_lock;
+	wait_queue_head_t		read_wait;
+	wait_queue_head_t		write_wait;
+
+	struct audio_client             *ac;
+	struct msm_audio_stream_config  str_cfg;
+	void				*enc_cfg;
+	struct msm_audio_buf_cfg        buf_cfg;
+	struct msm_audio_config		pcm_cfg;
+	void				*codec_cfg;
+
+	/* number of buffers available to read/write */
+	atomic_t			in_count;
+	atomic_t			out_count;
+
+	/* first idx: num of frames per buf, second idx: offset to frame */
+	uint32_t			out_frame_info[FRAME_NUM][2];
+	int				eos_rsp;
+	int				opened;
+	int				enabled;
+	int				stopped;
+	int				event_abort;
+	int				feedback; /* Flag indicates whether used
+						   * in Non Tunnel mode
+						   */
+	int				rflush;
+	int				wflush;
+	int				buf_alloc;
+	uint16_t			min_frame_size;
+	uint16_t			max_frames_per_buf;
+	bool				reset_event;
+	long (*enc_ioctl)(struct file *, unsigned int, unsigned long);
+	long (*enc_compat_ioctl)(struct file *, unsigned int, unsigned long);
+};
+
+int audio_in_enable(struct q6audio_in  *audio);
+int audio_in_disable(struct q6audio_in  *audio);
+int audio_in_buf_alloc(struct q6audio_in *audio);
+long audio_in_ioctl(struct file *file,
+		unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+long audio_in_compat_ioctl(struct file *file,
+		unsigned int cmd, unsigned long arg);
+#else
+#define audio_in_compat_ioctl NULL
+#endif
+ssize_t audio_in_read(struct file *file, char __user *buf,
+		size_t count, loff_t *pos);
+ssize_t audio_in_write(struct file *file, const char __user *buf,
+		size_t count, loff_t *pos);
+int audio_in_release(struct inode *inode, struct file *file);
+int audio_in_set_config(struct file *file, struct msm_audio_config *cfg);

+ 2142 - 0
drivers/misc/qcom/qdsp6v2/audio_utils_aio.c

@@ -0,0 +1,2142 @@
+/* Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/atomic.h>
+#include <asm/ioctls.h>
+#include <linux/debugfs.h>
+#include <linux/msm_audio_ion.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+#ifdef CONFIG_USE_DEV_CTRL_VOLUME
+#include <linux/qdsp6v2/audio_dev_ctl.h>
+#endif /*CONFIG_USE_DEV_CTRL_VOLUME*/
+#ifdef CONFIG_DEBUG_FS
+int audio_aio_debug_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+ssize_t audio_aio_debug_read(struct file *file, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	const int debug_bufmax = 4096;
+	static char buffer[4096];
+	int n = 0;
+	struct q6audio_aio *audio = file->private_data;
+
+	mutex_lock(&audio->lock);
+	n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
+	n += scnprintf(buffer + n, debug_bufmax - n,
+			"enabled %d\n", audio->enabled);
+	n += scnprintf(buffer + n, debug_bufmax - n,
+			"stopped %d\n", audio->stopped);
+	n += scnprintf(buffer + n, debug_bufmax - n,
+			"feedback %d\n", audio->feedback);
+	mutex_unlock(&audio->lock);
+	/* Following variables are only useful for debugging when
+	 * when playback halts unexpectedly. Thus, no mutual exclusion
+	 * enforced
+	 */
+	n += scnprintf(buffer + n, debug_bufmax - n,
+			"wflush %d\n", audio->wflush);
+	n += scnprintf(buffer + n, debug_bufmax - n,
+			"rflush %d\n", audio->rflush);
+	n += scnprintf(buffer + n, debug_bufmax - n,
+			"inqueue empty %d\n", list_empty(&audio->in_queue));
+	n += scnprintf(buffer + n, debug_bufmax - n,
+			"outqueue empty %d\n", list_empty(&audio->out_queue));
+	buffer[n] = 0;
+	return simple_read_from_buffer(buf, count, ppos, buffer, n);
+}
+#endif
+
+static long audio_aio_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg);
+#ifdef CONFIG_COMPAT
+static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg);
+#else
+#define audio_aio_compat_ioctl NULL
+#endif
+int insert_eos_buf(struct q6audio_aio *audio,
+		struct audio_aio_buffer_node *buf_node)
+{
+	struct dec_meta_out *eos_buf = buf_node->kvaddr;
+
+	pr_debug("%s[%pK]:insert_eos_buf\n", __func__, audio);
+	eos_buf->num_of_frames = 0xFFFFFFFF;
+	eos_buf->meta_out_dsp[0].offset_to_frame = 0x0;
+	eos_buf->meta_out_dsp[0].nflags = AUDIO_DEC_EOS_SET;
+	return sizeof(struct dec_meta_out) +
+		sizeof(eos_buf->meta_out_dsp[0]);
+}
+
+/* Routine which updates read buffers of driver/dsp,
+ * for flush operation as DSP output might not have proper
+ * value set
+ */
+static int insert_meta_data_flush(struct q6audio_aio *audio,
+	struct audio_aio_buffer_node *buf_node)
+{
+	struct dec_meta_out *meta_data = buf_node->kvaddr;
+
+	meta_data->num_of_frames = 0x0;
+	meta_data->meta_out_dsp[0].offset_to_frame = 0x0;
+	meta_data->meta_out_dsp[0].nflags = 0x0;
+	return sizeof(struct dec_meta_out) +
+		sizeof(meta_data->meta_out_dsp[0]);
+}
+
+static int audio_aio_ion_lookup_vaddr(struct q6audio_aio *audio, void *addr,
+					unsigned long len,
+					struct audio_aio_ion_region **region)
+{
+	struct audio_aio_ion_region *region_elt;
+
+	int match_count = 0;
+
+	*region = NULL;
+
+	/* returns physical address or zero */
+	list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
+		if (addr >= region_elt->vaddr &&
+			addr < region_elt->vaddr + region_elt->len &&
+			addr + len <= region_elt->vaddr + region_elt->len &&
+			addr + len > addr) {
+			/* to avoid integer addition overflow */
+
+			/* offset since we could pass vaddr inside a registered
+			 * ion buffer
+			 */
+
+			match_count++;
+			if (!*region)
+				*region = region_elt;
+		}
+	}
+
+	if (match_count > 1) {
+		pr_err("%s[%pK]:multiple hits for vaddr %pK, len %ld\n",
+			__func__, audio, addr, len);
+		list_for_each_entry(region_elt, &audio->ion_region_queue,
+					list) {
+			if (addr >= region_elt->vaddr &&
+			addr < region_elt->vaddr + region_elt->len &&
+			addr + len <= region_elt->vaddr + region_elt->len &&
+			addr + len > addr)
+				pr_err("\t%s[%pK]:%pK, %ld --> %pK\n",
+					__func__, audio,
+					region_elt->vaddr,
+					region_elt->len,
+					&region_elt->paddr);
+		}
+	}
+
+	return *region ? 0 : -1;
+}
+
+static phys_addr_t audio_aio_ion_fixup(struct q6audio_aio *audio, void *addr,
+				unsigned long len, int ref_up, void **kvaddr)
+{
+	struct audio_aio_ion_region *region;
+	phys_addr_t paddr;
+	int ret;
+
+	ret = audio_aio_ion_lookup_vaddr(audio, addr, len, &region);
+	if (ret) {
+		pr_err("%s[%pK]:lookup (%pK, %ld) failed\n",
+				__func__, audio, addr, len);
+		return 0;
+	}
+	if (ref_up)
+		region->ref_cnt++;
+	else
+		region->ref_cnt--;
+	pr_debug("%s[%pK]:found region %pK ref_cnt %d\n",
+			__func__, audio, region, region->ref_cnt);
+	paddr = region->paddr + (addr - region->vaddr);
+	/* provide kernel virtual address for accessing meta information */
+	if (kvaddr)
+		*kvaddr = (void *) (region->kvaddr + (addr - region->vaddr));
+	return paddr;
+}
+
+static int audio_aio_pause(struct q6audio_aio  *audio)
+{
+	int rc = -EINVAL;
+
+	pr_debug("%s[%pK], enabled = %d\n", __func__, audio,
+			audio->enabled);
+	if (audio->enabled) {
+		rc = q6asm_cmd(audio->ac, CMD_PAUSE);
+		if (rc < 0)
+			pr_err("%s[%pK]: pause cmd failed rc=%d\n",
+				__func__, audio, rc);
+
+		if (rc == 0) {
+			/* Send suspend only if pause was successful */
+			rc = q6asm_cmd(audio->ac, CMD_SUSPEND);
+			if (rc < 0)
+				pr_err("%s[%pK]: suspend cmd failed rc=%d\n",
+					__func__, audio, rc);
+		} else
+			pr_err("%s[%pK]: not sending suspend since pause failed\n",
+				__func__, audio);
+
+	} else
+		pr_err("%s[%pK]: Driver not enabled\n", __func__, audio);
+	return rc;
+}
+
+static int audio_aio_flush(struct q6audio_aio  *audio)
+{
+	int rc = 0;
+
+	if (audio->enabled) {
+		/* Implicitly issue a pause to the decoder before flushing if
+		 * it is not in pause state
+		 */
+		if (!(audio->drv_status & ADRV_STATUS_PAUSE)) {
+			rc = audio_aio_pause(audio);
+			if (rc < 0)
+				pr_err("%s[%pK}: pause cmd failed rc=%d\n",
+					__func__, audio,
+					rc);
+			else
+				audio->drv_status |= ADRV_STATUS_PAUSE;
+		}
+		rc = q6asm_cmd(audio->ac, CMD_FLUSH);
+		if (rc < 0)
+			pr_err("%s[%pK]: flush cmd failed rc=%d\n",
+				__func__, audio, rc);
+		/* Not in stop state, reenable the stream */
+		if (audio->stopped == 0) {
+			rc = audio_aio_enable(audio);
+			if (rc)
+				pr_err("%s[%pK]:audio re-enable failed\n",
+					__func__, audio);
+			else {
+				audio->enabled = 1;
+				if (audio->drv_status & ADRV_STATUS_PAUSE)
+					audio->drv_status &= ~ADRV_STATUS_PAUSE;
+			}
+		}
+	}
+	pr_debug("%s[%pK]:in_bytes %d\n",
+			__func__, audio, atomic_read(&audio->in_bytes));
+	pr_debug("%s[%pK]:in_samples %d\n",
+			__func__, audio, atomic_read(&audio->in_samples));
+	atomic_set(&audio->in_bytes, 0);
+	atomic_set(&audio->in_samples, 0);
+	return rc;
+}
+
+static int audio_aio_outport_flush(struct q6audio_aio *audio)
+{
+	int rc;
+
+	rc = q6asm_cmd(audio->ac, CMD_OUT_FLUSH);
+	if (rc < 0)
+		pr_err("%s[%pK}: output port flush cmd failed rc=%d\n",
+			__func__, audio, rc);
+	return rc;
+}
+
+/* Write buffer to DSP / Handle Ack from DSP */
+void audio_aio_async_write_ack(struct q6audio_aio *audio, uint32_t token,
+				uint32_t *payload)
+{
+	unsigned long flags;
+	union msm_audio_event_payload event_payload;
+	struct audio_aio_buffer_node *used_buf;
+
+	/* No active flush in progress */
+	if (audio->wflush)
+		return;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
+	if (list_empty(&audio->out_queue)) {
+		pr_warn("%s: ignore unexpected event from dsp\n", __func__);
+		spin_unlock_irqrestore(&audio->dsp_lock, flags);
+		return;
+	}
+	used_buf = list_first_entry(&audio->out_queue,
+					struct audio_aio_buffer_node, list);
+	if (token == used_buf->token) {
+		list_del(&used_buf->list);
+		spin_unlock_irqrestore(&audio->dsp_lock, flags);
+		pr_debug("%s[%pK]:consumed buffer\n", __func__, audio);
+		event_payload.aio_buf = used_buf->buf;
+		audio_aio_post_event(audio, AUDIO_EVENT_WRITE_DONE,
+					event_payload);
+		kfree(used_buf);
+		if (list_empty(&audio->out_queue) &&
+			(audio->drv_status & ADRV_STATUS_FSYNC)) {
+			pr_debug("%s[%pK]: list is empty, reached EOS in Tunnel\n",
+				 __func__, audio);
+			wake_up(&audio->write_wait);
+		}
+	} else {
+		pr_err("%s[%pK]:expected=%x ret=%x\n",
+			__func__, audio, used_buf->token, token);
+		spin_unlock_irqrestore(&audio->dsp_lock, flags);
+	}
+}
+
+/* ------------------- device --------------------- */
+void audio_aio_async_out_flush(struct q6audio_aio *audio)
+{
+	struct audio_aio_buffer_node *buf_node;
+	struct list_head *ptr, *next;
+	union msm_audio_event_payload payload;
+	unsigned long flags;
+
+	pr_debug("%s[%pK}\n", __func__, audio);
+	/* EOS followed by flush, EOS response not guranteed, free EOS i/p
+	 * buffer
+	 */
+	spin_lock_irqsave(&audio->dsp_lock, flags);
+
+	if (audio->eos_flag && (audio->eos_write_payload.aio_buf.buf_addr)) {
+		pr_debug("%s[%pK]: EOS followed by flush received,acknowledge eos i/p buffer immediately\n",
+			__func__, audio);
+		audio_aio_post_event(audio, AUDIO_EVENT_WRITE_DONE,
+				audio->eos_write_payload);
+		memset(&audio->eos_write_payload, 0,
+			sizeof(union msm_audio_event_payload));
+	}
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
+	list_for_each_safe(ptr, next, &audio->out_queue) {
+		buf_node = list_entry(ptr, struct audio_aio_buffer_node, list);
+		list_del(&buf_node->list);
+		payload.aio_buf = buf_node->buf;
+		audio_aio_post_event(audio, AUDIO_EVENT_WRITE_DONE, payload);
+		kfree(buf_node);
+		pr_debug("%s[%pK]: Propagate WRITE_DONE during flush\n",
+				__func__, audio);
+	}
+}
+
+void audio_aio_async_in_flush(struct q6audio_aio *audio)
+{
+	struct audio_aio_buffer_node *buf_node;
+	struct list_head *ptr, *next;
+	union msm_audio_event_payload payload;
+
+	pr_debug("%s[%pK]\n", __func__, audio);
+	list_for_each_safe(ptr, next, &audio->in_queue) {
+		buf_node = list_entry(ptr, struct audio_aio_buffer_node, list);
+		list_del(&buf_node->list);
+		/* Forcefull send o/p eos buffer after flush, if no eos response
+		 * received by dsp even after sending eos command
+		 */
+		if ((audio->eos_rsp != 1) && audio->eos_flag) {
+			pr_debug("%s[%pK]: send eos on o/p buffer during flush\n",
+				 __func__, audio);
+			payload.aio_buf = buf_node->buf;
+			payload.aio_buf.data_len =
+					insert_eos_buf(audio, buf_node);
+			audio->eos_flag = 0;
+		} else {
+			payload.aio_buf = buf_node->buf;
+			payload.aio_buf.data_len =
+					insert_meta_data_flush(audio, buf_node);
+		}
+		audio_aio_post_event(audio, AUDIO_EVENT_READ_DONE, payload);
+		kfree(buf_node);
+		pr_debug("%s[%pK]: Propagate READ_DONE during flush\n",
+				__func__, audio);
+	}
+}
+
+int audio_aio_enable(struct q6audio_aio  *audio)
+{
+	/* 2nd arg: 0 -> run immediately
+	 * 3rd arg: 0 -> msw_ts,
+	 * 4th arg: 0 ->lsw_ts
+	 */
+	return q6asm_run(audio->ac, 0x00, 0x00, 0x00);
+}
+
+int audio_aio_disable(struct q6audio_aio *audio)
+{
+	int rc = 0;
+
+	if (audio->opened) {
+		audio->enabled = 0;
+		audio->opened = 0;
+		pr_debug("%s[%pK]: inbytes[%d] insamples[%d]\n", __func__,
+			audio, atomic_read(&audio->in_bytes),
+			atomic_read(&audio->in_samples));
+		/* Close the session */
+		rc = q6asm_cmd(audio->ac, CMD_CLOSE);
+		if (rc < 0)
+			pr_err("%s[%pK]:Failed to close the session rc=%d\n",
+				__func__, audio, rc);
+		audio->stopped = 1;
+		wake_up(&audio->write_wait);
+		wake_up(&audio->cmd_wait);
+	}
+	pr_debug("%s[%pK]:enabled[%d]\n", __func__, audio, audio->enabled);
+	return rc;
+}
+
+void audio_aio_reset_ion_region(struct q6audio_aio *audio)
+{
+	struct audio_aio_ion_region *region;
+	struct list_head *ptr, *next;
+
+	list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+		region = list_entry(ptr, struct audio_aio_ion_region, list);
+		list_del(&region->list);
+		msm_audio_ion_free_legacy(audio->client, region->handle);
+		kfree(region);
+	}
+}
+
+void audio_aio_reset_event_queue(struct q6audio_aio *audio)
+{
+	unsigned long flags;
+	struct audio_aio_event *drv_evt;
+	struct list_head *ptr, *next;
+
+	spin_lock_irqsave(&audio->event_queue_lock, flags);
+	list_for_each_safe(ptr, next, &audio->event_queue) {
+		drv_evt = list_first_entry(&audio->event_queue,
+				   struct audio_aio_event, list);
+		list_del(&drv_evt->list);
+		kfree(drv_evt);
+	}
+	list_for_each_safe(ptr, next, &audio->free_event_queue) {
+		drv_evt = list_first_entry(&audio->free_event_queue,
+				   struct audio_aio_event, list);
+		list_del(&drv_evt->list);
+		kfree(drv_evt);
+	}
+	spin_unlock_irqrestore(&audio->event_queue_lock, flags);
+}
+
+static void audio_aio_unmap_ion_region(struct q6audio_aio *audio)
+{
+	struct audio_aio_ion_region *region;
+	struct list_head *ptr, *next;
+	int rc = -EINVAL;
+
+	pr_debug("%s[%pK]:\n", __func__, audio);
+	list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+		region = list_entry(ptr, struct audio_aio_ion_region, list);
+		if (region != NULL) {
+			pr_debug("%s[%pK]: phy_address = 0x%pK\n",
+				__func__, audio, &region->paddr);
+			rc = q6asm_memory_unmap(audio->ac,
+						region->paddr, IN);
+			if (rc < 0)
+				pr_err("%s[%pK]: memory unmap failed\n",
+					__func__, audio);
+		}
+	}
+}
+
+#ifdef CONFIG_USE_DEV_CTRL_VOLUME
+
+static void audio_aio_listner(u32 evt_id, union auddev_evt_data *evt_payload,
+			void *private_data)
+{
+	struct q6audio_aio *audio = (struct q6audio_aio *) private_data;
+	int rc  = 0;
+
+	switch (evt_id) {
+	case AUDDEV_EVT_STREAM_VOL_CHG:
+		audio->volume = evt_payload->session_vol;
+		pr_debug("%s[%pK]: AUDDEV_EVT_STREAM_VOL_CHG, stream vol %d, enabled = %d\n",
+			__func__, audio, audio->volume, audio->enabled);
+		if (audio->enabled == 1) {
+			if (audio->ac) {
+				rc = q6asm_set_volume(audio->ac, audio->volume);
+				if (rc < 0) {
+					pr_err("%s[%pK]: Send Volume command failed rc=%d\n",
+						__func__, audio, rc);
+				}
+			}
+		}
+		break;
+	default:
+		pr_err("%s[%pK]:ERROR:wrong event\n", __func__, audio);
+		break;
+	}
+}
+
+int register_volume_listener(struct q6audio_aio *audio)
+{
+	int rc  = 0;
+
+	audio->device_events = AUDDEV_EVT_STREAM_VOL_CHG;
+	audio->drv_status &= ~ADRV_STATUS_PAUSE;
+
+	rc = auddev_register_evt_listner(audio->device_events,
+					AUDDEV_CLNT_DEC,
+					audio->ac->session,
+					audio_aio_listner,
+					(void *)audio);
+	if (rc < 0) {
+		pr_err("%s[%pK]: Event listener failed\n", __func__, audio);
+		rc = -EACCES;
+	}
+	return rc;
+}
+void unregister_volume_listener(struct q6audio_aio *audio)
+{
+	auddev_unregister_evt_listner(AUDDEV_CLNT_DEC, audio->ac->session);
+}
+
+int enable_volume_ramp(struct q6audio_aio *audio)
+{
+	int rc = 0;
+	struct asm_softpause_params softpause;
+	struct asm_softvolume_params softvol;
+
+	if (audio->ac == NULL)
+		return -EINVAL;
+	pr_debug("%s[%pK]\n", __func__, audio);
+	softpause.enable = SOFT_PAUSE_ENABLE;
+	softpause.period = SOFT_PAUSE_PERIOD;
+	softpause.step = SOFT_PAUSE_STEP;
+	softpause.rampingcurve = SOFT_PAUSE_CURVE_LINEAR;
+
+	softvol.period = SOFT_VOLUME_PERIOD;
+	softvol.step = SOFT_VOLUME_STEP;
+	softvol.rampingcurve = SOFT_VOLUME_CURVE_LINEAR;
+
+	if (softpause.rampingcurve == SOFT_PAUSE_CURVE_LINEAR)
+		softpause.step = SOFT_PAUSE_STEP_LINEAR;
+	if (softvol.rampingcurve == SOFT_VOLUME_CURVE_LINEAR)
+		softvol.step = SOFT_VOLUME_STEP_LINEAR;
+	rc = q6asm_set_volume(audio->ac, audio->volume);
+	if (rc < 0) {
+		pr_err("%s: Send Volume command failed rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+	rc = q6asm_set_softpause(audio->ac, &softpause);
+	if (rc < 0) {
+		pr_err("%s: Send SoftPause Param failed rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+	rc = q6asm_set_softvolume(audio->ac, &softvol);
+	if (rc < 0) {
+		pr_err("%s: Send SoftVolume Param failed rc=%d\n",
+		__func__, rc);
+		return rc;
+	}
+	/* disable mute by default */
+	rc = q6asm_set_mute(audio->ac, 0);
+	if (rc < 0) {
+		pr_err("%s: Send mute command failed rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+	return rc;
+}
+
+#else /*CONFIG_USE_DEV_CTRL_VOLUME*/
+int register_volume_listener(struct q6audio_aio *audio)
+{
+	return 0;/* do nothing */
+}
+void unregister_volume_listener(struct q6audio_aio *audio)
+{
+	return;/* do nothing */
+}
+int enable_volume_ramp(struct q6audio_aio *audio)
+{
+	return 0; /* do nothing */
+}
+#endif /*CONFIG_USE_DEV_CTRL_VOLUME*/
+
+int audio_aio_release(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = file->private_data;
+
+	pr_debug("%s[%pK]\n", __func__, audio);
+	mutex_lock(&audio->lock);
+	mutex_lock(&audio->read_lock);
+	mutex_lock(&audio->write_lock);
+	audio->wflush = 1;
+	if (audio->wakelock_voted &&
+		(audio->audio_ws_mgr != NULL) &&
+		(audio->miscdevice != NULL)) {
+		audio->wakelock_voted = false;
+		mutex_lock(&audio->audio_ws_mgr->ws_lock);
+		if ((audio->audio_ws_mgr->ref_cnt > 0) &&
+				(--audio->audio_ws_mgr->ref_cnt == 0)) {
+			pm_relax(audio->miscdevice->this_device);
+		}
+		mutex_unlock(&audio->audio_ws_mgr->ws_lock);
+	}
+	if (audio->enabled)
+		audio_aio_flush(audio);
+	audio->wflush = 0;
+	audio->drv_ops.out_flush(audio);
+	audio->drv_ops.in_flush(audio);
+	audio_aio_disable(audio);
+	audio_aio_unmap_ion_region(audio);
+	audio_aio_reset_ion_region(audio);
+	msm_audio_ion_client_destroy(audio->client);
+	audio->event_abort = 1;
+	wake_up(&audio->event_wait);
+	audio_aio_reset_event_queue(audio);
+	q6asm_audio_client_free(audio->ac);
+	mutex_unlock(&audio->write_lock);
+	mutex_unlock(&audio->read_lock);
+	mutex_unlock(&audio->lock);
+	mutex_destroy(&audio->lock);
+	mutex_destroy(&audio->read_lock);
+	mutex_destroy(&audio->write_lock);
+	mutex_destroy(&audio->get_event_lock);
+	unregister_volume_listener(audio);
+
+#ifdef CONFIG_DEBUG_FS
+	debugfs_remove(audio->dentry);
+#endif
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return 0;
+}
+
+int audio_aio_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+{
+	int rc = 0;
+	struct q6audio_aio *audio = file->private_data;
+
+	if (!audio->enabled || audio->feedback)
+		return -EINVAL;
+
+	/* Blocking client sends more data */
+	mutex_lock(&audio->lock);
+	audio->drv_status |= ADRV_STATUS_FSYNC;
+	mutex_unlock(&audio->lock);
+
+	pr_debug("%s[%pK]:\n", __func__, audio);
+
+	audio->eos_rsp = 0;
+
+	pr_debug("%s[%pK]Wait for write done from DSP\n", __func__, audio);
+	rc = wait_event_interruptible(audio->write_wait,
+					(list_empty(&audio->out_queue)) ||
+					audio->wflush || audio->stopped);
+
+	if (audio->stopped || audio->wflush) {
+		pr_debug("%s[%pK]: Audio Flushed or Stopped,this is not EOS\n"
+			, __func__, audio);
+		audio->wflush = 0;
+		rc = -EBUSY;
+	}
+
+	if (rc < 0) {
+		pr_err("%s[%pK]: wait event for list_empty failed, rc = %d\n",
+			__func__, audio, rc);
+		goto done;
+	}
+
+	rc = q6asm_cmd(audio->ac, CMD_EOS);
+	pr_debug("%s[%pK]: EOS cmd sent to DSP\n", __func__, audio);
+
+	if (rc < 0)
+		pr_err("%s[%pK]: q6asm_cmd failed, rc = %d",
+			__func__, audio, rc);
+
+	pr_debug("%s[%pK]: wait for RENDERED_EOS from DSP\n"
+		, __func__, audio);
+	rc = wait_event_interruptible(audio->write_wait,
+					(audio->eos_rsp || audio->wflush ||
+					audio->stopped));
+
+	if (rc < 0) {
+		pr_err("%s[%pK]: wait event for eos_rsp failed, rc = %d\n",
+			__func__, audio, rc);
+		goto done;
+	}
+
+	if (audio->stopped || audio->wflush) {
+		audio->wflush = 0;
+		pr_debug("%s[%pK]: Audio Flushed or Stopped,this is not EOS\n"
+			, __func__, audio);
+		rc = -EBUSY;
+	}
+
+	if (audio->eos_rsp == 1)
+		pr_debug("%s[%pK]: EOS\n", __func__, audio);
+
+
+done:
+	mutex_lock(&audio->lock);
+	audio->drv_status &= ~ADRV_STATUS_FSYNC;
+	mutex_unlock(&audio->lock);
+
+	return rc;
+}
+
+static int audio_aio_events_pending(struct q6audio_aio *audio)
+{
+	unsigned long flags;
+	int empty;
+
+	spin_lock_irqsave(&audio->event_queue_lock, flags);
+	empty = !list_empty(&audio->event_queue);
+	spin_unlock_irqrestore(&audio->event_queue_lock, flags);
+	return empty || audio->event_abort || audio->reset_event;
+}
+
+static long audio_aio_process_event_req_common(struct q6audio_aio *audio,
+					struct msm_audio_event *usr_evt)
+{
+	long rc;
+	struct audio_aio_event *drv_evt = NULL;
+	int timeout;
+	unsigned long flags;
+
+	timeout = usr_evt->timeout_ms;
+
+	if (timeout > 0) {
+		rc = wait_event_interruptible_timeout(audio->event_wait,
+						audio_aio_events_pending
+						(audio),
+						msecs_to_jiffies
+						(timeout));
+		if (rc == 0)
+			return -ETIMEDOUT;
+	} else {
+		rc = wait_event_interruptible(audio->event_wait,
+		audio_aio_events_pending(audio));
+	}
+	if (rc < 0)
+		return rc;
+
+	if (audio->reset_event) {
+		audio->reset_event = false;
+		pr_err("In SSR, post ENETRESET err\n");
+		return -ENETRESET;
+	}
+
+	if (audio->event_abort) {
+		audio->event_abort = 0;
+		return -ENODEV;
+	}
+
+	rc = 0;
+
+	spin_lock_irqsave(&audio->event_queue_lock, flags);
+	if (!list_empty(&audio->event_queue)) {
+		drv_evt = list_first_entry(&audio->event_queue,
+		   struct audio_aio_event, list);
+		list_del(&drv_evt->list);
+	}
+	if (drv_evt) {
+		usr_evt->event_type = drv_evt->event_type;
+		usr_evt->event_payload = drv_evt->payload;
+		list_add_tail(&drv_evt->list, &audio->free_event_queue);
+	} else {
+		pr_err("%s[%pK]:Unexpected path\n", __func__, audio);
+		spin_unlock_irqrestore(&audio->event_queue_lock, flags);
+		return -EPERM;
+	}
+	spin_unlock_irqrestore(&audio->event_queue_lock, flags);
+
+	if (drv_evt->event_type == AUDIO_EVENT_WRITE_DONE) {
+		pr_debug("%s[%pK]:posted AUDIO_EVENT_WRITE_DONE to user\n",
+			__func__, audio);
+		mutex_lock(&audio->write_lock);
+		audio_aio_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
+		drv_evt->payload.aio_buf.buf_len, 0, 0);
+		mutex_unlock(&audio->write_lock);
+	} else if (drv_evt->event_type == AUDIO_EVENT_READ_DONE) {
+		pr_debug("%s[%pK]:posted AUDIO_EVENT_READ_DONE to user\n",
+			__func__, audio);
+		mutex_lock(&audio->read_lock);
+		audio_aio_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
+		drv_evt->payload.aio_buf.buf_len, 0, 0);
+		mutex_unlock(&audio->read_lock);
+	}
+
+	/* Some read buffer might be held up in DSP,release all
+	 * Once EOS indicated
+	 */
+	if (audio->eos_rsp && !list_empty(&audio->in_queue)) {
+		pr_debug("%s[%pK]:Send flush command to release read buffers held up in DSP\n",
+			__func__, audio);
+		mutex_lock(&audio->lock);
+		audio_aio_flush(audio);
+		mutex_unlock(&audio->lock);
+	}
+
+	return rc;
+}
+
+static long audio_aio_process_event_req(struct q6audio_aio *audio,
+					void __user *arg)
+{
+	long rc;
+	struct msm_audio_event usr_evt;
+
+	if (copy_from_user(&usr_evt, arg, sizeof(struct msm_audio_event))) {
+		pr_err("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	rc = audio_aio_process_event_req_common(audio, &usr_evt);
+
+	if (copy_to_user(arg, &usr_evt, sizeof(usr_evt))) {
+		pr_err("%s: copy_to_user failed\n", __func__);
+		rc = -EFAULT;
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+
+struct msm_audio_aio_buf32 {
+	compat_uptr_t buf_addr;
+	u32 buf_len;
+	u32 data_len;
+	compat_uptr_t private_data;
+	u16 mfield_sz; /*only useful for data has meta field */
+};
+
+struct msm_audio_bitstream_info32 {
+	u32 codec_type;
+	u32 chan_info;
+	u32 sample_rate;
+	u32 bit_stream_info;
+	u32 bit_rate;
+	u32 unused[3];
+};
+
+struct msm_audio_bitstream_error_info32 {
+	u32 dec_id;
+	u32 err_msg_indicator;
+	u32 err_type;
+};
+
+union msm_audio_event_payload32 {
+	struct msm_audio_aio_buf32 aio_buf;
+	struct msm_audio_bitstream_info32 stream_info;
+	struct msm_audio_bitstream_error_info32 error_info;
+	s32 reserved;
+};
+
+struct msm_audio_event32 {
+	s32 event_type;
+	s32 timeout_ms;
+	union msm_audio_event_payload32 event_payload;
+};
+
+static long audio_aio_process_event_req_compat(struct q6audio_aio *audio,
+					void __user *arg)
+{
+	long rc;
+	struct msm_audio_event32 usr_evt_32;
+	struct msm_audio_event usr_evt;
+	memset(&usr_evt, 0, sizeof(struct msm_audio_event));
+
+	if (copy_from_user(&usr_evt_32, arg,
+				sizeof(struct msm_audio_event32))) {
+		pr_err("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+	usr_evt.timeout_ms = usr_evt_32.timeout_ms;
+
+	rc = audio_aio_process_event_req_common(audio, &usr_evt);
+	if (rc < 0) {
+		pr_err("%s: audio process event failed, rc = %ld",
+			__func__, rc);
+		return rc;
+	}
+
+	usr_evt_32.event_type = usr_evt.event_type;
+	switch (usr_evt_32.event_type) {
+	case AUDIO_EVENT_SUSPEND:
+	case AUDIO_EVENT_RESUME:
+	case AUDIO_EVENT_WRITE_DONE:
+	case AUDIO_EVENT_READ_DONE:
+		usr_evt_32.event_payload.aio_buf.buf_addr =
+			ptr_to_compat(usr_evt.event_payload.aio_buf.buf_addr);
+		usr_evt_32.event_payload.aio_buf.buf_len =
+			usr_evt.event_payload.aio_buf.buf_len;
+		usr_evt_32.event_payload.aio_buf.data_len =
+			usr_evt.event_payload.aio_buf.data_len;
+		usr_evt_32.event_payload.aio_buf.private_data =
+		ptr_to_compat(usr_evt.event_payload.aio_buf.private_data);
+		usr_evt_32.event_payload.aio_buf.mfield_sz =
+			usr_evt.event_payload.aio_buf.mfield_sz;
+		break;
+	case AUDIO_EVENT_STREAM_INFO:
+		usr_evt_32.event_payload.stream_info.codec_type =
+			usr_evt.event_payload.stream_info.codec_type;
+		usr_evt_32.event_payload.stream_info.chan_info =
+			usr_evt.event_payload.stream_info.chan_info;
+		usr_evt_32.event_payload.stream_info.sample_rate =
+			usr_evt.event_payload.stream_info.sample_rate;
+		usr_evt_32.event_payload.stream_info.bit_stream_info =
+			usr_evt.event_payload.stream_info.bit_stream_info;
+		usr_evt_32.event_payload.stream_info.bit_rate =
+			usr_evt.event_payload.stream_info.bit_rate;
+		break;
+	case AUDIO_EVENT_BITSTREAM_ERROR_INFO:
+		usr_evt_32.event_payload.error_info.dec_id =
+			usr_evt.event_payload.error_info.dec_id;
+		usr_evt_32.event_payload.error_info.err_msg_indicator =
+			usr_evt.event_payload.error_info.err_msg_indicator;
+		usr_evt_32.event_payload.error_info.err_type =
+			usr_evt.event_payload.error_info.err_type;
+		break;
+	default:
+		pr_debug("%s: unknown audio event type = %d rc = %ld",
+			 __func__, usr_evt_32.event_type, rc);
+		return rc;
+	}
+	if (copy_to_user(arg, &usr_evt_32, sizeof(usr_evt_32))) {
+		pr_err("%s: copy_to_user failed\n", __func__);
+		rc = -EFAULT;
+	}
+	return rc;
+}
+#endif
+
+static int audio_aio_ion_check(struct q6audio_aio *audio,
+				void *vaddr, unsigned long len)
+{
+	struct audio_aio_ion_region *region_elt;
+	struct audio_aio_ion_region t = {.vaddr = vaddr, .len = len };
+
+	list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
+		if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
+			OVERLAPS(region_elt, &t)) {
+			pr_err("%s[%pK]:region (vaddr %pK len %ld) clashes with registered region (vaddr %pK paddr %pK len %ld)\n",
+				__func__, audio, vaddr, len,
+				region_elt->vaddr,
+				&region_elt->paddr, region_elt->len);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int audio_aio_ion_add(struct q6audio_aio *audio,
+				struct msm_audio_ion_info *info)
+{
+	ion_phys_addr_t paddr = 0;
+	size_t len = 0;
+	struct audio_aio_ion_region *region;
+	int rc = -EINVAL;
+	struct ion_handle *handle = NULL;
+	unsigned long ionflag;
+	void *kvaddr = NULL;
+
+	pr_debug("%s[%pK]:\n", __func__, audio);
+	region = kmalloc(sizeof(*region), GFP_KERNEL);
+
+	if (!region) {
+		rc = -ENOMEM;
+		goto end;
+	}
+
+	rc = msm_audio_ion_import_legacy("Audio_Dec_Client", audio->client,
+				&handle, info->fd, &ionflag,
+				0, &paddr, &len, &kvaddr);
+	if (rc) {
+		pr_err("%s: msm audio ion alloc failed\n", __func__);
+		goto import_error;
+	}
+
+	rc = audio_aio_ion_check(audio, info->vaddr, len);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_ion_check failed\n", __func__);
+		goto ion_error;
+	}
+
+	region->handle = handle;
+	region->vaddr = info->vaddr;
+	region->fd = info->fd;
+	region->paddr = paddr;
+	region->kvaddr = kvaddr;
+	region->len = len;
+	region->ref_cnt = 0;
+	pr_debug("%s[%pK]:add region paddr %pK vaddr %pK, len %lu kvaddr %pK\n",
+		__func__, audio,
+		&region->paddr, region->vaddr, region->len,
+		region->kvaddr);
+	list_add_tail(&region->list, &audio->ion_region_queue);
+	rc = q6asm_memory_map(audio->ac,  paddr, IN, len, 1);
+	if (rc < 0) {
+		pr_err("%s[%pK]: memory map failed\n", __func__, audio);
+		goto mmap_error;
+	} else {
+		goto end;
+	}
+mmap_error:
+	list_del(&region->list);
+ion_error:
+	msm_audio_ion_free_legacy(audio->client, handle);
+import_error:
+	kfree(region);
+end:
+	return rc;
+}
+
+static int audio_aio_ion_remove(struct q6audio_aio *audio,
+				struct msm_audio_ion_info *info)
+{
+	struct audio_aio_ion_region *region;
+	struct list_head *ptr, *next;
+	int rc = -EINVAL;
+
+	pr_debug("%s[%pK]:info fd %d vaddr %pK\n",
+		__func__, audio, info->fd, info->vaddr);
+
+	list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+		region = list_entry(ptr, struct audio_aio_ion_region, list);
+
+		if ((region->fd == info->fd) &&
+			(region->vaddr == info->vaddr)) {
+			if (region->ref_cnt) {
+				pr_debug("%s[%pK]:region %pK in use ref_cnt %d\n",
+					__func__, audio, region,
+					region->ref_cnt);
+				break;
+			}
+			pr_debug("%s[%pK]:remove region fd %d vaddr %pK\n",
+				__func__, audio, info->fd, info->vaddr);
+			rc = q6asm_memory_unmap(audio->ac,
+						region->paddr, IN);
+			if (rc < 0)
+				pr_err("%s[%pK]: memory unmap failed\n",
+					__func__, audio);
+
+			list_del(&region->list);
+			msm_audio_ion_free_legacy(audio->client,
+						 region->handle);
+			kfree(region);
+			rc = 0;
+			break;
+		}
+	}
+
+	return rc;
+}
+
+static int audio_aio_async_write(struct q6audio_aio *audio,
+				struct audio_aio_buffer_node *buf_node)
+{
+	int rc;
+	struct audio_client *ac;
+	struct audio_aio_write_param param;
+
+	if (!audio || !buf_node) {
+		pr_err("%s NULL pointer audio=[0x%pK], buf_node=[0x%pK]\n",
+			__func__, audio, buf_node);
+		return -EINVAL;
+	}
+	pr_debug("%s[%pK]: Send write buff %pK phy %pK len %d meta_enable = %d\n",
+		__func__, audio, buf_node, &buf_node->paddr,
+		buf_node->buf.data_len,
+		audio->buf_cfg.meta_info_enable);
+	pr_debug("%s[%pK]: flags = 0x%x\n", __func__, audio,
+		buf_node->meta_info.meta_in.nflags);
+
+	ac = audio->ac;
+	/* Offset with  appropriate meta */
+	if (audio->feedback) {
+		/* Non Tunnel mode */
+		param.paddr = buf_node->paddr + sizeof(struct dec_meta_in);
+		param.len = buf_node->buf.data_len - sizeof(struct dec_meta_in);
+	} else {
+		/* Tunnel mode */
+		param.paddr = buf_node->paddr;
+		param.len = buf_node->buf.data_len;
+	}
+	param.msw_ts = buf_node->meta_info.meta_in.ntimestamp.highpart;
+	param.lsw_ts = buf_node->meta_info.meta_in.ntimestamp.lowpart;
+	param.flags  = buf_node->meta_info.meta_in.nflags;
+	/* If no meta_info enaled, indicate no time stamp valid */
+	if (!audio->buf_cfg.meta_info_enable)
+		param.flags = 0xFF00;
+
+	if (buf_node->meta_info.meta_in.nflags & AUDIO_DEC_EOF_SET)
+		param.flags |= AUDIO_DEC_EOF_SET;
+
+	param.uid = ac->session;
+	/* Read command will populate session id as token */
+	buf_node->token = ac->session;
+	rc = q6asm_async_write(ac, &param);
+	if (rc < 0)
+		pr_err("%s[%pK]:failed\n", __func__, audio);
+	return rc;
+}
+
+void audio_aio_post_event(struct q6audio_aio *audio, int type,
+			union msm_audio_event_payload payload)
+{
+	struct audio_aio_event *e_node = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->event_queue_lock, flags);
+
+	if (!list_empty(&audio->free_event_queue)) {
+		e_node = list_first_entry(&audio->free_event_queue,
+					struct audio_aio_event, list);
+		list_del(&e_node->list);
+	} else {
+		e_node = kmalloc(sizeof(struct audio_aio_event), GFP_ATOMIC);
+		if (!e_node) {
+			spin_unlock_irqrestore(&audio->event_queue_lock, flags);
+			return;
+		}
+	}
+
+	e_node->event_type = type;
+	e_node->payload = payload;
+
+	list_add_tail(&e_node->list, &audio->event_queue);
+	spin_unlock_irqrestore(&audio->event_queue_lock, flags);
+	wake_up(&audio->event_wait);
+}
+
+static int audio_aio_async_read(struct q6audio_aio *audio,
+				struct audio_aio_buffer_node *buf_node)
+{
+	struct audio_client *ac;
+	struct audio_aio_read_param param;
+	int rc;
+
+	pr_debug("%s[%pK]: Send read buff %pK phy %pK len %d\n",
+		__func__, audio, buf_node,
+		&buf_node->paddr, buf_node->buf.buf_len);
+	ac = audio->ac;
+	/* Provide address so driver can append nr frames information */
+	param.paddr = buf_node->paddr +
+		sizeof(struct dec_meta_out);
+	param.len = buf_node->buf.buf_len -
+		sizeof(struct dec_meta_out);
+	param.uid = ac->session;
+	/* Write command will populate session_id as token */
+	buf_node->token = ac->session;
+	rc = q6asm_async_read(ac, &param);
+	if (rc < 0)
+		pr_err("%s[%pK]:failed\n", __func__, audio);
+	return rc;
+}
+
+static int audio_aio_buf_add_shared(struct q6audio_aio *audio, u32 dir,
+				struct audio_aio_buffer_node *buf_node)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	pr_debug("%s[%pK]:node %pK dir %x buf_addr %pK buf_len %d data_len %d\n",
+		 __func__, audio, buf_node, dir, buf_node->buf.buf_addr,
+		buf_node->buf.buf_len, buf_node->buf.data_len);
+	buf_node->paddr = audio_aio_ion_fixup(audio, buf_node->buf.buf_addr,
+						buf_node->buf.buf_len, 1,
+						&buf_node->kvaddr);
+	if (dir) {
+		/* write */
+		if (!buf_node->paddr ||
+			(buf_node->paddr & 0x1) ||
+			(!audio->feedback && !buf_node->buf.data_len)) {
+			kfree(buf_node);
+			return -EINVAL;
+		}
+		extract_meta_out_info(audio, buf_node, 1);
+		/* Not a EOS buffer */
+		if (!(buf_node->meta_info.meta_in.nflags & AUDIO_DEC_EOS_SET)) {
+			spin_lock_irqsave(&audio->dsp_lock, flags);
+			ret = audio_aio_async_write(audio, buf_node);
+			/* EOS buffer handled in driver */
+			list_add_tail(&buf_node->list, &audio->out_queue);
+			spin_unlock_irqrestore(&audio->dsp_lock, flags);
+		} else if (buf_node->meta_info.meta_in.nflags
+				   & AUDIO_DEC_EOS_SET) {
+			if (!audio->wflush) {
+				pr_debug("%s[%pK]:Send EOS cmd at i/p\n",
+					__func__, audio);
+				/* Driver will forcefully post writedone event
+				 * once eos ack recived from DSP
+				 */
+				audio->eos_write_payload.aio_buf =
+					buf_node->buf;
+				audio->eos_flag = 1;
+				audio->eos_rsp = 0;
+				q6asm_cmd(audio->ac, CMD_EOS);
+				kfree(buf_node);
+			} else { /* Flush in progress, send back i/p
+				  * EOS buffer as is
+				  */
+				union msm_audio_event_payload event_payload;
+
+				event_payload.aio_buf = buf_node->buf;
+				audio_aio_post_event(audio,
+						AUDIO_EVENT_WRITE_DONE,
+						event_payload);
+				kfree(buf_node);
+			}
+		}
+	} else {
+		/* read */
+		if (!buf_node->paddr ||
+			(buf_node->paddr & 0x1) ||
+			(buf_node->buf.buf_len < PCM_BUFSZ_MIN)) {
+			kfree(buf_node);
+			return -EINVAL;
+		}
+		/* No EOS reached */
+		if (!audio->eos_rsp) {
+			spin_lock_irqsave(&audio->dsp_lock, flags);
+			ret = audio_aio_async_read(audio, buf_node);
+			/* EOS buffer handled in driver */
+			list_add_tail(&buf_node->list, &audio->in_queue);
+			spin_unlock_irqrestore(&audio->dsp_lock, flags);
+		}
+		/* EOS reached at input side fake all upcoming read buffer to
+		 * indicate the same
+		 */
+		else {
+			union msm_audio_event_payload event_payload;
+
+			event_payload.aio_buf = buf_node->buf;
+			event_payload.aio_buf.data_len =
+				insert_eos_buf(audio, buf_node);
+			pr_debug("%s[%pK]: propagate READ_DONE as EOS done\n",
+				__func__, audio);
+			audio_aio_post_event(audio, AUDIO_EVENT_READ_DONE,
+					event_payload);
+			kfree(buf_node);
+		}
+	}
+	return ret;
+}
+#ifdef CONFIG_COMPAT
+static int audio_aio_buf_add_compat(struct q6audio_aio *audio, u32 dir,
+				void __user *arg)
+{
+	struct audio_aio_buffer_node *buf_node;
+	struct msm_audio_aio_buf32 aio_buf_32;
+
+	buf_node = kzalloc(sizeof(*buf_node), GFP_KERNEL);
+
+	if (!buf_node)
+		return -ENOMEM;
+
+	if (copy_from_user(&aio_buf_32, arg, sizeof(aio_buf_32))) {
+		kfree(buf_node);
+		pr_err("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	buf_node->buf.buf_addr = compat_ptr(aio_buf_32.buf_addr);
+	buf_node->buf.buf_len = aio_buf_32.buf_len;
+	buf_node->buf.data_len = aio_buf_32.data_len;
+	buf_node->buf.private_data = compat_ptr(aio_buf_32.private_data);
+	buf_node->buf.mfield_sz = aio_buf_32.mfield_sz;
+
+	return audio_aio_buf_add_shared(audio, dir, buf_node);
+}
+#endif
+
+static int audio_aio_buf_add(struct q6audio_aio *audio, u32 dir,
+				void __user *arg)
+{
+	struct audio_aio_buffer_node *buf_node;
+
+	buf_node = kzalloc(sizeof(*buf_node), GFP_KERNEL);
+
+	if (!buf_node)
+		return -ENOMEM;
+
+	if (copy_from_user(&buf_node->buf, arg, sizeof(buf_node->buf))) {
+		kfree(buf_node);
+		pr_err("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	return audio_aio_buf_add_shared(audio, dir, buf_node);
+}
+
+void audio_aio_ioport_reset(struct q6audio_aio *audio)
+{
+	if (audio->drv_status & ADRV_STATUS_AIO_INTF) {
+		/* If fsync is in progress, make sure
+		 * return value of fsync indicates
+		 * abort due to flush
+		 */
+		if (audio->drv_status & ADRV_STATUS_FSYNC) {
+			pr_debug("%s[%pK]:fsync in progress\n",
+				 __func__, audio);
+			audio->drv_ops.out_flush(audio);
+		} else
+			audio->drv_ops.out_flush(audio);
+		if (audio->feedback == NON_TUNNEL_MODE)
+			audio->drv_ops.in_flush(audio);
+	}
+}
+
+int audio_aio_open(struct q6audio_aio *audio, struct file *file)
+{
+	int rc = 0;
+	int i;
+	struct audio_aio_event *e_node = NULL;
+	struct list_head *ptr, *next;
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->str_cfg.buffer_size = FRAME_SIZE;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	audio->pcm_cfg.sample_rate = 48000;
+	audio->pcm_cfg.channel_count = 2;
+
+	/* Only AIO interface */
+	if (file->f_flags & O_NONBLOCK) {
+		pr_debug("%s[%pK]:set to aio interface\n", __func__, audio);
+		audio->drv_status |= ADRV_STATUS_AIO_INTF;
+		audio->drv_ops.out_flush = audio_aio_async_out_flush;
+		audio->drv_ops.in_flush = audio_aio_async_in_flush;
+		q6asm_set_io_mode(audio->ac, ASYNC_IO_MODE);
+	} else {
+		pr_err("%s[%pK]:SIO interface not supported\n",
+			__func__, audio);
+		rc = -EACCES;
+		goto fail;
+	}
+
+	/* Initialize all locks of audio instance */
+	mutex_init(&audio->lock);
+	mutex_init(&audio->read_lock);
+	mutex_init(&audio->write_lock);
+	mutex_init(&audio->get_event_lock);
+	spin_lock_init(&audio->dsp_lock);
+	spin_lock_init(&audio->event_queue_lock);
+	init_waitqueue_head(&audio->cmd_wait);
+	init_waitqueue_head(&audio->write_wait);
+	init_waitqueue_head(&audio->event_wait);
+	INIT_LIST_HEAD(&audio->out_queue);
+	INIT_LIST_HEAD(&audio->in_queue);
+	INIT_LIST_HEAD(&audio->ion_region_queue);
+	INIT_LIST_HEAD(&audio->free_event_queue);
+	INIT_LIST_HEAD(&audio->event_queue);
+
+	audio->drv_ops.out_flush(audio);
+	audio->opened = 1;
+	audio->reset_event = false;
+	file->private_data = audio;
+	audio->codec_ioctl = audio_aio_ioctl;
+	audio->codec_compat_ioctl = audio_aio_compat_ioctl;
+	for (i = 0; i < AUDIO_EVENT_NUM; i++) {
+		e_node = kmalloc(sizeof(struct audio_aio_event), GFP_KERNEL);
+		if (e_node)
+			list_add_tail(&e_node->list, &audio->free_event_queue);
+		else {
+			rc = -ENOMEM;
+			goto cleanup;
+		}
+	}
+	audio->client = msm_audio_ion_client_create("Audio_Dec_Client");
+	if (IS_ERR_OR_NULL(audio->client)) {
+		pr_err("Unable to create ION client\n");
+		rc = -ENOMEM;
+		goto cleanup;
+	}
+	pr_debug("Ion client create in audio_aio_open %pK", audio->client);
+
+	rc = register_volume_listener(audio);
+	if (rc < 0)
+		goto ion_cleanup;
+
+	return 0;
+ion_cleanup:
+	msm_audio_ion_client_destroy(audio->client);
+	audio->client = NULL;
+cleanup:
+	list_for_each_safe(ptr, next, &audio->free_event_queue) {
+		e_node = list_first_entry(&audio->free_event_queue,
+				   struct audio_aio_event, list);
+		list_del(&e_node->list);
+		kfree(e_node);
+	}
+fail:
+	return rc;
+}
+
+static long audio_aio_shared_ioctl(struct file *file, unsigned int cmd,
+			unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_ABORT_GET_EVENT: {
+		audio->event_abort = 1;
+		wake_up(&audio->event_wait);
+		break;
+	}
+	case AUDIO_OUTPORT_FLUSH: {
+		pr_debug("%s[%pK]:AUDIO_OUTPORT_FLUSH\n", __func__, audio);
+		mutex_lock(&audio->read_lock);
+		rc = audio_aio_outport_flush(audio);
+		if (rc < 0) {
+			pr_err("%s[%pK]: AUDIO_OUTPORT_FLUSH failed\n",
+				__func__, audio);
+			rc = -EINTR;
+		}
+		mutex_unlock(&audio->read_lock);
+		break;
+	}
+	case AUDIO_STOP: {
+		pr_debug("%s[%pK]: AUDIO_STOP session_id[%d]\n", __func__,
+				audio, audio->ac->session);
+		mutex_lock(&audio->lock);
+		audio->stopped = 1;
+		rc = audio_aio_flush(audio);
+		if (rc < 0) {
+			pr_err("%s[%pK]:Audio Stop procedure failed rc=%d\n",
+				__func__, audio, rc);
+			mutex_unlock(&audio->lock);
+			break;
+		}
+		audio->enabled = 0;
+		audio->drv_status &= ~ADRV_STATUS_PAUSE;
+		if (audio->drv_status & ADRV_STATUS_FSYNC) {
+			pr_debug("%s[%pK] Waking up the audio_aio_fsync\n",
+					__func__, audio);
+			wake_up(&audio->write_wait);
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_PAUSE: {
+		pr_debug("%s[%pK]:AUDIO_PAUSE %ld\n", __func__, audio, arg);
+		mutex_lock(&audio->lock);
+		if (arg == 1) {
+			rc = audio_aio_pause(audio);
+			if (rc < 0) {
+				pr_err("%s[%pK]: pause FAILED rc=%d\n",
+					__func__, audio, rc);
+				mutex_unlock(&audio->lock);
+				break;
+			}
+			audio->drv_status |= ADRV_STATUS_PAUSE;
+		} else if (arg == 0) {
+			if (audio->drv_status & ADRV_STATUS_PAUSE) {
+				rc = audio_aio_enable(audio);
+				if (rc)
+					pr_err("%s[%pK]: audio enable failed\n",
+					__func__, audio);
+				else {
+					audio->drv_status &= ~ADRV_STATUS_PAUSE;
+					audio->enabled = 1;
+				}
+			}
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_FLUSH: {
+		pr_debug("%s[%pK]: AUDIO_FLUSH sessionid[%d]\n", __func__,
+			audio, audio->ac->session);
+		mutex_lock(&audio->lock);
+		audio->rflush = 1;
+		audio->wflush = 1;
+		if (audio->drv_status & ADRV_STATUS_FSYNC) {
+			pr_debug("%s[%pK] Waking up the audio_aio_fsync\n",
+				__func__, audio);
+			wake_up(&audio->write_wait);
+		}
+		/* Flush DSP */
+		rc = audio_aio_flush(audio);
+		/* Flush input / Output buffer in software*/
+		audio_aio_ioport_reset(audio);
+		if (rc < 0) {
+			pr_err("%s[%pK]:AUDIO_FLUSH interrupted\n",
+				__func__, audio);
+			rc = -EINTR;
+		} else {
+			audio->rflush = 0;
+			if (audio->drv_status & ADRV_STATUS_FSYNC)
+				wake_up(&audio->write_wait);
+			else
+				audio->wflush = 0;
+
+		}
+		audio->eos_flag = 0;
+		audio->eos_rsp = 0;
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_GET_SESSION_ID: {
+		mutex_lock(&audio->lock);
+		if (copy_to_user((void *)arg, &audio->ac->session,
+			sizeof(u16))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_SESSION_ID failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_PM_AWAKE: {
+		if ((audio->audio_ws_mgr ==  NULL) ||
+				(audio->miscdevice == NULL)) {
+			pr_err("%s[%pK]: invalid ws_mgr or miscdevice",
+					__func__, audio);
+			rc = -EACCES;
+			break;
+		}
+		pr_debug("%s[%pK]:AUDIO_PM_AWAKE\n", __func__, audio);
+		mutex_lock(&audio->lock);
+		if (!audio->wakelock_voted) {
+			audio->wakelock_voted = true;
+			mutex_lock(&audio->audio_ws_mgr->ws_lock);
+			if (audio->audio_ws_mgr->ref_cnt++ == 0)
+				pm_stay_awake(audio->miscdevice->this_device);
+			mutex_unlock(&audio->audio_ws_mgr->ws_lock);
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_PM_RELAX: {
+		if ((audio->audio_ws_mgr ==  NULL) ||
+				(audio->miscdevice == NULL)) {
+			pr_err("%s[%pK]: invalid ws_mgr or miscdevice",
+					__func__, audio);
+			rc = -EACCES;
+			break;
+		}
+		pr_debug("%s[%pK]:AUDIO_PM_RELAX\n", __func__, audio);
+		mutex_lock(&audio->lock);
+		if (audio->wakelock_voted) {
+			audio->wakelock_voted = false;
+			mutex_lock(&audio->audio_ws_mgr->ws_lock);
+			if ((audio->audio_ws_mgr->ref_cnt > 0) &&
+					(--audio->audio_ws_mgr->ref_cnt == 0)) {
+				pm_relax(audio->miscdevice->this_device);
+			}
+			mutex_unlock(&audio->audio_ws_mgr->ws_lock);
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc =  -EINVAL;
+	}
+	return rc;
+
+
+}
+
+static long audio_aio_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_ABORT_GET_EVENT:
+	case AUDIO_OUTPORT_FLUSH:
+	case AUDIO_STOP:
+	case AUDIO_PAUSE:
+	case AUDIO_FLUSH:
+	case AUDIO_GET_SESSION_ID:
+	case AUDIO_PM_AWAKE:
+	case AUDIO_PM_RELAX:
+		rc = audio_aio_shared_ioctl(file, cmd, arg);
+		break;
+	case AUDIO_GET_STATS: {
+		struct msm_audio_stats stats;
+		uint64_t timestamp;
+
+		memset(&stats, 0, sizeof(struct msm_audio_stats));
+		stats.byte_count = atomic_read(&audio->in_bytes);
+		stats.sample_count = atomic_read(&audio->in_samples);
+		rc = q6asm_get_session_time(audio->ac, &timestamp);
+		if (rc >= 0)
+			memcpy(&stats.unused[0], &timestamp, sizeof(timestamp));
+		else
+			pr_debug("Error while getting timestamp\n");
+		if (copy_to_user((void *)arg, &stats, sizeof(stats))) {
+			pr_err("%s: copy_frm_user for AUDIO_GET_STATS failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_GET_EVENT: {
+		pr_debug("%s[%pK]:AUDIO_GET_EVENT\n", __func__, audio);
+		if (mutex_trylock(&audio->get_event_lock)) {
+			rc = audio_aio_process_event_req(audio,
+						(void __user *)arg);
+			mutex_unlock(&audio->get_event_lock);
+		} else
+			rc = -EBUSY;
+		break;
+	}
+	case AUDIO_ASYNC_WRITE: {
+		mutex_lock(&audio->write_lock);
+		if (audio->drv_status & ADRV_STATUS_FSYNC)
+			rc = -EBUSY;
+		else {
+			if (audio->enabled)
+				rc = audio_aio_buf_add(audio, 1,
+						(void __user *)arg);
+			else
+				rc = -EPERM;
+		}
+		mutex_unlock(&audio->write_lock);
+		break;
+	}
+	case AUDIO_ASYNC_READ: {
+		mutex_lock(&audio->read_lock);
+		if (audio->feedback)
+			rc = audio_aio_buf_add(audio, 0,
+					(void __user *)arg);
+		else
+			rc = -EPERM;
+		mutex_unlock(&audio->read_lock);
+		break;
+	}
+
+	case AUDIO_GET_STREAM_CONFIG: {
+		struct msm_audio_stream_config cfg;
+
+		mutex_lock(&audio->lock);
+		memset(&cfg, 0, sizeof(cfg));
+		cfg.buffer_size = audio->str_cfg.buffer_size;
+		cfg.buffer_count = audio->str_cfg.buffer_count;
+		pr_debug("%s[%pK]:GET STREAM CFG %d %d\n",
+			__func__, audio, cfg.buffer_size, cfg.buffer_count);
+		if (copy_to_user((void *)arg, &cfg, sizeof(cfg))) {
+			pr_err(
+				"%s: copy_to_user for AUDIO_GET_STREAM_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_SET_STREAM_CONFIG: {
+		struct msm_audio_stream_config cfg;
+
+		pr_debug("%s[%pK]:SET STREAM CONFIG\n", __func__, audio);
+		mutex_lock(&audio->lock);
+		if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
+			pr_err(
+				"%s: copy_from_user for AUDIO_SET_STREAM_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			mutex_unlock(&audio->lock);
+			break;
+		}
+		audio->str_cfg.buffer_size = FRAME_SIZE;
+		audio->str_cfg.buffer_count = FRAME_NUM;
+		rc = 0;
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_GET_CONFIG: {
+		struct msm_audio_config cfg;
+
+		mutex_lock(&audio->lock);
+		if (copy_to_user((void *)arg, &audio->pcm_cfg, sizeof(cfg))) {
+			pr_err(
+				"%s: copy_to_user for AUDIO_GET_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_SET_CONFIG: {
+		struct msm_audio_config config;
+
+		pr_err("%s[%pK]:AUDIO_SET_CONFIG\n", __func__, audio);
+		mutex_lock(&audio->lock);
+		if (copy_from_user(&config, (void *)arg, sizeof(config))) {
+			pr_err(
+				"%s: copy_from_user for AUDIO_SET_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			mutex_unlock(&audio->lock);
+			break;
+		}
+		if (audio->feedback != NON_TUNNEL_MODE) {
+			pr_err("%s[%pK]:Not sufficient permission to change the playback mode\n",
+				 __func__, audio);
+			rc = -EACCES;
+			mutex_unlock(&audio->lock);
+			break;
+		}
+		if ((config.buffer_count > PCM_BUF_COUNT) ||
+			(config.buffer_count == 1))
+			config.buffer_count = PCM_BUF_COUNT;
+
+		if (config.buffer_size < PCM_BUFSZ_MIN)
+			config.buffer_size = PCM_BUFSZ_MIN;
+
+		audio->pcm_cfg.buffer_count = config.buffer_count;
+		audio->pcm_cfg.buffer_size = config.buffer_size;
+		audio->pcm_cfg.channel_count = config.channel_count;
+		audio->pcm_cfg.sample_rate = config.sample_rate;
+		rc = 0;
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_SET_BUF_CFG: {
+		struct msm_audio_buf_cfg  cfg;
+
+		mutex_lock(&audio->lock);
+		if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
+			pr_err(
+				"%s: copy_from_user for AUDIO_GET_BUF CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			mutex_unlock(&audio->lock);
+			break;
+		}
+		if ((audio->feedback == NON_TUNNEL_MODE) &&
+			!cfg.meta_info_enable) {
+			rc = -EFAULT;
+			mutex_unlock(&audio->lock);
+			break;
+		}
+
+		audio->buf_cfg.meta_info_enable = cfg.meta_info_enable;
+		pr_debug("%s[%pK]:session id %d: Set-buf-cfg: meta[%d]",
+				__func__, audio,
+				audio->ac->session, cfg.meta_info_enable);
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_GET_BUF_CFG: {
+		pr_debug("%s[%pK]:session id %d: Get-buf-cfg: meta[%d] framesperbuf[%d]\n",
+			 __func__, audio,
+			audio->ac->session, audio->buf_cfg.meta_info_enable,
+			audio->buf_cfg.frames_per_buf);
+
+		mutex_lock(&audio->lock);
+		if (copy_to_user((void *)arg, &audio->buf_cfg,
+			sizeof(struct msm_audio_buf_cfg))) {
+			pr_err(
+				"%s: copy_to_user for AUDIO_GET_BUF_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_REGISTER_ION: {
+		struct msm_audio_ion_info info;
+
+		pr_debug("%s[%pK]:AUDIO_REGISTER_ION\n", __func__, audio);
+		mutex_lock(&audio->lock);
+		if (copy_from_user(&info, (void *)arg, sizeof(info))) {
+			pr_err(
+				"%s: copy_from_user for AUDIO_REGISTER_ION failed\n",
+				__func__);
+			rc = -EFAULT;
+		} else {
+			mutex_lock(&audio->read_lock);
+			mutex_lock(&audio->write_lock);
+			rc = audio_aio_ion_add(audio, &info);
+			mutex_unlock(&audio->write_lock);
+			mutex_unlock(&audio->read_lock);
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_DEREGISTER_ION: {
+		struct msm_audio_ion_info info;
+
+		mutex_lock(&audio->lock);
+		pr_debug("%s[%pK]:AUDIO_DEREGISTER_ION\n", __func__, audio);
+		if (copy_from_user(&info, (void *)arg, sizeof(info))) {
+			pr_err(
+				"%s: copy_from_user for AUDIO_DEREGISTER_ION failed\n",
+				__func__);
+			rc = -EFAULT;
+		} else {
+			mutex_lock(&audio->read_lock);
+			mutex_lock(&audio->write_lock);
+			rc = audio_aio_ion_remove(audio, &info);
+			mutex_unlock(&audio->write_lock);
+			mutex_unlock(&audio->read_lock);
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc =  -EINVAL;
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_stream_config32 {
+	u32 buffer_size;
+	u32 buffer_count;
+};
+
+struct msm_audio_stats32 {
+	u32 byte_count;
+	u32 sample_count;
+	u32 unused[2];
+};
+
+struct msm_audio_config32 {
+	u32 buffer_size;
+	u32 buffer_count;
+	u32 channel_count;
+	u32 sample_rate;
+	u32 type;
+	u32 meta_field;
+	u32 bits;
+	u32 unused[3];
+};
+
+struct msm_audio_buf_cfg32 {
+	u32 meta_info_enable;
+	u32 frames_per_buf;
+};
+
+struct msm_audio_ion_info32 {
+	int fd;
+	compat_uptr_t vaddr;
+};
+
+enum {
+	AUDIO_GET_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, 3,
+			struct msm_audio_config32),
+	AUDIO_SET_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, 4,
+			struct msm_audio_config32),
+	AUDIO_GET_STATS_32 = _IOR(AUDIO_IOCTL_MAGIC, 5,
+			struct msm_audio_stats32),
+	AUDIO_GET_EVENT_32 = _IOR(AUDIO_IOCTL_MAGIC, 13,
+			struct msm_audio_event32),
+	AUDIO_ASYNC_WRITE_32 = _IOW(AUDIO_IOCTL_MAGIC, 17,
+			struct msm_audio_aio_buf32),
+	AUDIO_ASYNC_READ_32 = _IOW(AUDIO_IOCTL_MAGIC, 18,
+			struct msm_audio_aio_buf32),
+	AUDIO_SET_STREAM_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, 80,
+			struct msm_audio_stream_config32),
+	AUDIO_GET_STREAM_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, 81,
+			struct msm_audio_stream_config32),
+	AUDIO_GET_BUF_CFG_32 = _IOW(AUDIO_IOCTL_MAGIC, 93,
+			struct msm_audio_buf_cfg32),
+	AUDIO_SET_BUF_CFG_32 = _IOW(AUDIO_IOCTL_MAGIC, 94,
+			struct msm_audio_buf_cfg32),
+	AUDIO_REGISTER_ION_32 = _IOW(AUDIO_IOCTL_MAGIC, 97,
+			struct msm_audio_ion_info32),
+	AUDIO_DEREGISTER_ION_32 = _IOW(AUDIO_IOCTL_MAGIC, 98,
+			struct msm_audio_ion_info32),
+};
+
+static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd,
+			unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_ABORT_GET_EVENT:
+	case AUDIO_OUTPORT_FLUSH:
+	case AUDIO_STOP:
+	case AUDIO_PAUSE:
+	case AUDIO_FLUSH:
+	case AUDIO_GET_SESSION_ID:
+	case AUDIO_PM_AWAKE:
+	case AUDIO_PM_RELAX:
+		rc = audio_aio_shared_ioctl(file, cmd, arg);
+		break;
+	case AUDIO_GET_STATS_32: {
+		struct msm_audio_stats32 stats;
+		uint64_t timestamp;
+
+		memset(&stats, 0, sizeof(struct msm_audio_stats32));
+		stats.byte_count = atomic_read(&audio->in_bytes);
+		stats.sample_count = atomic_read(&audio->in_samples);
+		rc = q6asm_get_session_time(audio->ac, &timestamp);
+		if (rc >= 0)
+			memcpy(&stats.unused[0], &timestamp, sizeof(timestamp));
+		else
+			pr_debug("Error while getting timestamp\n");
+		if (copy_to_user((void *)arg, &stats, sizeof(stats))) {
+			pr_err(
+				"%s: copy_to_user for AUDIO_GET_STATS_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_GET_EVENT_32: {
+		pr_debug("%s[%pK]:AUDIO_GET_EVENT\n", __func__, audio);
+		if (mutex_trylock(&audio->get_event_lock)) {
+			rc = audio_aio_process_event_req_compat(audio,
+						(void __user *)arg);
+			mutex_unlock(&audio->get_event_lock);
+		} else
+			rc = -EBUSY;
+		break;
+	}
+	case AUDIO_ASYNC_WRITE_32: {
+		mutex_lock(&audio->write_lock);
+		if (audio->drv_status & ADRV_STATUS_FSYNC)
+			rc = -EBUSY;
+		else {
+			if (audio->enabled)
+				rc = audio_aio_buf_add_compat(audio, 1,
+						(void __user *)arg);
+			else
+				rc = -EPERM;
+		}
+		mutex_unlock(&audio->write_lock);
+		break;
+	}
+	case AUDIO_ASYNC_READ_32: {
+		mutex_lock(&audio->read_lock);
+		if (audio->feedback)
+			rc = audio_aio_buf_add_compat(audio, 0,
+					(void __user *)arg);
+		else
+			rc = -EPERM;
+		mutex_unlock(&audio->read_lock);
+		break;
+	}
+
+	case AUDIO_GET_STREAM_CONFIG_32: {
+		struct msm_audio_stream_config32 cfg;
+
+		mutex_lock(&audio->lock);
+		memset(&cfg, 0, sizeof(cfg));
+		cfg.buffer_size = audio->str_cfg.buffer_size;
+		cfg.buffer_count = audio->str_cfg.buffer_count;
+		pr_debug("%s[%pK]:GET STREAM CFG %d %d\n",
+			__func__, audio, cfg.buffer_size, cfg.buffer_count);
+		if (copy_to_user((void *)arg, &cfg, sizeof(cfg))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_STREAM_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_SET_STREAM_CONFIG_32: {
+		struct msm_audio_stream_config32 cfg_32;
+		struct msm_audio_stream_config cfg;
+
+		pr_debug("%s[%pK]:SET STREAM CONFIG\n", __func__, audio);
+		mutex_lock(&audio->lock);
+		if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_STREAM_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			mutex_unlock(&audio->lock);
+			break;
+		}
+		cfg.buffer_size = cfg_32.buffer_size;
+		cfg.buffer_count = cfg_32.buffer_count;
+
+		audio->str_cfg.buffer_size = FRAME_SIZE;
+		audio->str_cfg.buffer_count = FRAME_NUM;
+		rc = 0;
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_GET_CONFIG_32: {
+		struct msm_audio_config32 cfg_32;
+
+		mutex_lock(&audio->lock);
+		memset(&cfg_32, 0, sizeof(cfg_32));
+		cfg_32.buffer_size = audio->pcm_cfg.buffer_size;
+		cfg_32.buffer_count = audio->pcm_cfg.buffer_count;
+		cfg_32.channel_count = audio->pcm_cfg.channel_count;
+		cfg_32.sample_rate = audio->pcm_cfg.sample_rate;
+		cfg_32.type = audio->pcm_cfg.type;
+		cfg_32.meta_field = audio->pcm_cfg.meta_field;
+		cfg_32.bits = audio->pcm_cfg.bits;
+
+		if (copy_to_user((void *)arg, &cfg_32, sizeof(cfg_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_SET_CONFIG_32: {
+		struct msm_audio_config config;
+		struct msm_audio_config32 config_32;
+
+		mutex_lock(&audio->lock);
+
+		if (audio->feedback != NON_TUNNEL_MODE) {
+			pr_err("%s[%pK]:Not sufficient permission to change the playback mode\n",
+				 __func__, audio);
+			rc = -EACCES;
+			mutex_unlock(&audio->lock);
+			break;
+		}
+		pr_err("%s[%pK]:AUDIO_SET_CONFIG\n", __func__, audio);
+		if (copy_from_user(&config_32, (void *)arg,
+					sizeof(config_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			mutex_unlock(&audio->lock);
+			break;
+		}
+		config.buffer_size = config_32.buffer_size;
+		config.buffer_count = config_32.buffer_count;
+		config.channel_count = config_32.channel_count;
+		config.sample_rate = config_32.sample_rate;
+		config.type = config_32.type;
+		config.meta_field = config_32.meta_field;
+		config.bits = config_32.bits;
+
+		if ((config.buffer_count > PCM_BUF_COUNT) ||
+			(config.buffer_count == 1))
+			config.buffer_count = PCM_BUF_COUNT;
+
+		if (config.buffer_size < PCM_BUFSZ_MIN)
+			config.buffer_size = PCM_BUFSZ_MIN;
+
+		audio->pcm_cfg.buffer_count = config.buffer_count;
+		audio->pcm_cfg.buffer_size = config.buffer_size;
+		audio->pcm_cfg.channel_count = config.channel_count;
+		audio->pcm_cfg.sample_rate = config.sample_rate;
+		rc = 0;
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_SET_BUF_CFG_32: {
+		struct msm_audio_buf_cfg cfg;
+		struct msm_audio_buf_cfg32 cfg_32;
+
+		mutex_lock(&audio->lock);
+		if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			mutex_unlock(&audio->lock);
+			break;
+		}
+		cfg.meta_info_enable = cfg_32.meta_info_enable;
+		cfg.frames_per_buf = cfg_32.frames_per_buf;
+
+		if ((audio->feedback == NON_TUNNEL_MODE) &&
+			!cfg.meta_info_enable) {
+			rc = -EFAULT;
+			mutex_unlock(&audio->lock);
+			break;
+		}
+
+		audio->buf_cfg.meta_info_enable = cfg.meta_info_enable;
+		pr_debug("%s[%pK]:session id %d: Set-buf-cfg: meta[%d]",
+				__func__, audio,
+				audio->ac->session, cfg.meta_info_enable);
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_GET_BUF_CFG_32: {
+		struct msm_audio_buf_cfg32 cfg_32;
+
+		pr_debug("%s[%pK]:session id %d: Get-buf-cfg: meta[%d] framesperbuf[%d]\n",
+			 __func__, audio,
+			audio->ac->session, audio->buf_cfg.meta_info_enable,
+			audio->buf_cfg.frames_per_buf);
+		mutex_lock(&audio->lock);
+		memset(&cfg_32, 0, sizeof(cfg_32));
+		cfg_32.meta_info_enable = audio->buf_cfg.meta_info_enable;
+		cfg_32.frames_per_buf = audio->buf_cfg.frames_per_buf;
+		if (copy_to_user((void *)arg, &cfg_32,
+			sizeof(struct msm_audio_buf_cfg32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_BUF_CFG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_REGISTER_ION_32: {
+		struct msm_audio_ion_info32 info_32;
+		struct msm_audio_ion_info info;
+
+		pr_debug("%s[%pK]:AUDIO_REGISTER_ION\n", __func__, audio);
+		mutex_lock(&audio->lock);
+		if (copy_from_user(&info_32, (void *)arg, sizeof(info_32))) {
+			pr_err("%s: copy_from_user for AUDIO_REGISTER_ION_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		} else {
+			info.fd = info_32.fd;
+			info.vaddr = compat_ptr(info_32.vaddr);
+			mutex_lock(&audio->read_lock);
+			mutex_lock(&audio->write_lock);
+			rc = audio_aio_ion_add(audio, &info);
+			mutex_unlock(&audio->write_lock);
+			mutex_unlock(&audio->read_lock);
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	case AUDIO_DEREGISTER_ION_32: {
+		struct msm_audio_ion_info32 info_32;
+		struct msm_audio_ion_info info;
+
+		mutex_lock(&audio->lock);
+		pr_debug("%s[%pK]:AUDIO_DEREGISTER_ION\n", __func__, audio);
+		if (copy_from_user(&info_32, (void *)arg, sizeof(info_32))) {
+			pr_err("%s: copy_from_user for	AUDIO_DEREGISTER_ION_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		} else {
+			info.fd = info_32.fd;
+			info.vaddr = compat_ptr(info_32.vaddr);
+			mutex_lock(&audio->read_lock);
+			mutex_lock(&audio->write_lock);
+			rc = audio_aio_ion_remove(audio, &info);
+			mutex_unlock(&audio->write_lock);
+			mutex_unlock(&audio->read_lock);
+		}
+		mutex_unlock(&audio->lock);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc =  -EINVAL;
+	}
+	return rc;
+}
+#endif

+ 232 - 0
drivers/misc/qcom/qdsp6v2/audio_utils_aio.h

@@ -0,0 +1,232 @@
+/* Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/fs.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <linux/wakelock.h>
+#include <linux/msm_audio.h>
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/msm_ion.h>
+#include <asm/ioctls.h>
+#include <linux/atomic.h>
+#include "q6audio_common.h"
+
+#define TUNNEL_MODE     0x0000
+#define NON_TUNNEL_MODE 0x0001
+
+#define ADRV_STATUS_AIO_INTF 0x00000001 /* AIO interface */
+#define ADRV_STATUS_FSYNC 0x00000008
+#define ADRV_STATUS_PAUSE 0x00000010
+#define AUDIO_DEC_EOS_SET  0x00000001
+#define AUDIO_DEC_EOF_SET  0x00000010
+#define AUDIO_EVENT_NUM		10
+
+#define __CONTAINS(r, v, l) ({                                  \
+	typeof(r) __r = r;                                      \
+	typeof(v) __v = v;                                      \
+	typeof(v) __e = __v + l;                                \
+	int res = ((__v >= __r->vaddr) &&                       \
+		(__e <= __r->vaddr + __r->len));                \
+	res;                                                    \
+})
+
+#define CONTAINS(r1, r2) ({                                     \
+	typeof(r2) __r2 = r2;                                   \
+	__CONTAINS(r1, __r2->vaddr, __r2->len);                 \
+})
+
+#define IN_RANGE(r, v) ({                                       \
+	typeof(r) __r = r;                                      \
+	typeof(v) __vv = v;                                     \
+	int res = ((__vv >= __r->vaddr) &&                      \
+		(__vv < (__r->vaddr + __r->len)));              \
+	res;                                                    \
+})
+
+#define OVERLAPS(r1, r2) ({                                     \
+	typeof(r1) __r1 = r1;                                   \
+	typeof(r2) __r2 = r2;                                   \
+	typeof(__r2->vaddr) __v = __r2->vaddr;                  \
+	typeof(__v) __e = __v + __r2->len - 1;                  \
+	int res = (IN_RANGE(__r1, __v) || IN_RANGE(__r1, __e)); \
+	res;                                                    \
+})
+
+struct timestamp {
+	u32 lowpart;
+	u32 highpart;
+} __packed;
+
+struct meta_out_dsp {
+	u32 offset_to_frame;
+	u32 frame_size;
+	u32 encoded_pcm_samples;
+	u32 msw_ts;
+	u32 lsw_ts;
+	u32 nflags;
+} __packed;
+
+struct dec_meta_in {
+	unsigned char reserved[18];
+	unsigned short offset;
+	struct timestamp ntimestamp;
+	unsigned int nflags;
+} __packed;
+
+struct dec_meta_out {
+	unsigned int reserved[7];
+	unsigned int num_of_frames;
+	struct meta_out_dsp meta_out_dsp[];
+} __packed;
+
+/* General meta field to store meta info locally */
+union  meta_data {
+	struct dec_meta_out meta_out;
+	struct dec_meta_in meta_in;
+} __packed;
+
+/* per device wakeup source manager */
+struct ws_mgr {
+	struct mutex       ws_lock;
+	uint32_t           ref_cnt;
+};
+
+#define PCM_BUF_COUNT           (2)
+/* Buffer with meta */
+#define PCM_BUFSZ_MIN           ((4*1024) + sizeof(struct dec_meta_out))
+
+/* FRAME_NUM must be a power of two */
+#define FRAME_NUM               (2)
+#define FRAME_SIZE	((4*1536) + sizeof(struct dec_meta_in))
+
+struct audio_aio_ion_region {
+	struct list_head list;
+	struct ion_handle *handle;
+	int fd;
+	void *vaddr;
+	phys_addr_t paddr;
+	void *kvaddr;
+	unsigned long len;
+	unsigned int ref_cnt;
+};
+
+struct audio_aio_event {
+	struct list_head list;
+	int event_type;
+	union msm_audio_event_payload payload;
+};
+
+struct audio_aio_buffer_node {
+	struct list_head list;
+	struct msm_audio_aio_buf buf;
+	unsigned long paddr;
+	uint32_t token;
+	void            *kvaddr;
+	union meta_data meta_info;
+};
+
+struct q6audio_aio;
+struct audio_aio_drv_operations {
+	void (*out_flush)(struct q6audio_aio *);
+	void (*in_flush)(struct q6audio_aio *);
+};
+
+struct q6audio_aio {
+	atomic_t in_bytes;
+	atomic_t in_samples;
+
+	struct msm_audio_stream_config str_cfg;
+	struct msm_audio_buf_cfg        buf_cfg;
+	struct msm_audio_config pcm_cfg;
+	void *codec_cfg;
+
+	struct audio_client *ac;
+
+	struct mutex lock;
+	struct mutex read_lock;
+	struct mutex write_lock;
+	struct mutex get_event_lock;
+	wait_queue_head_t cmd_wait;
+	wait_queue_head_t write_wait;
+	wait_queue_head_t event_wait;
+	spinlock_t dsp_lock;
+	spinlock_t event_queue_lock;
+
+	struct miscdevice *miscdevice;
+	uint32_t wakelock_voted;
+	struct ws_mgr *audio_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *dentry;
+#endif
+	struct list_head out_queue;     /* queue to retain output buffers */
+	struct list_head in_queue;      /* queue to retain input buffers */
+	struct list_head free_event_queue;
+	struct list_head event_queue;
+	struct list_head ion_region_queue;     /* protected by lock */
+	struct ion_client *client;
+	struct audio_aio_drv_operations drv_ops;
+	union msm_audio_event_payload eos_write_payload;
+	uint32_t device_events;
+	uint16_t volume;
+	uint32_t drv_status;
+	int event_abort;
+	int eos_rsp;
+	int eos_flag;
+	int opened;
+	int enabled;
+	int stopped;
+	int feedback;
+	int rflush;             /* Read  flush */
+	int wflush;             /* Write flush */
+	bool reset_event;
+	long (*codec_ioctl)(struct file *, unsigned int, unsigned long);
+	long (*codec_compat_ioctl)(struct file *, unsigned int, unsigned long);
+};
+
+void audio_aio_async_write_ack(struct q6audio_aio *audio, uint32_t token,
+				uint32_t *payload);
+
+void audio_aio_async_read_ack(struct q6audio_aio *audio, uint32_t token,
+			uint32_t *payload);
+
+int insert_eos_buf(struct q6audio_aio *audio,
+		struct audio_aio_buffer_node *buf_node);
+
+void extract_meta_out_info(struct q6audio_aio *audio,
+		struct audio_aio_buffer_node *buf_node, int dir);
+
+int audio_aio_open(struct q6audio_aio *audio, struct file *file);
+int audio_aio_enable(struct q6audio_aio  *audio);
+void audio_aio_post_event(struct q6audio_aio *audio, int type,
+		union msm_audio_event_payload payload);
+int audio_aio_release(struct inode *inode, struct file *file);
+int audio_aio_fsync(struct file *file, loff_t start, loff_t end, int datasync);
+void audio_aio_async_out_flush(struct q6audio_aio *audio);
+void audio_aio_async_in_flush(struct q6audio_aio *audio);
+void audio_aio_ioport_reset(struct q6audio_aio *audio);
+int enable_volume_ramp(struct q6audio_aio *audio);
+#ifdef CONFIG_DEBUG_FS
+int audio_aio_debug_open(struct inode *inode, struct file *file);
+ssize_t audio_aio_debug_read(struct file *file, char __user *buf,
+			size_t count, loff_t *ppos);
+#endif

+ 345 - 0
drivers/misc/qcom/qdsp6v2/audio_wma.c

@@ -0,0 +1,345 @@
+/* wma audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/types.h>
+#include <linux/msm_audio_wma.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_wma_misc;
+static struct ws_mgr audio_wma_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_wma_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+						void *arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct asm_wma_cfg wma_cfg;
+		struct msm_audio_wma_config_v2 *wma_config;
+
+		pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+		wma_config = (struct msm_audio_wma_config_v2 *)audio->codec_cfg;
+		wma_cfg.format_tag = wma_config->format_tag;
+		wma_cfg.ch_cfg = wma_config->numchannels;
+		wma_cfg.sample_rate =  wma_config->samplingrate;
+		wma_cfg.avg_bytes_per_sec = wma_config->avgbytespersecond;
+		wma_cfg.block_align = wma_config->block_align;
+		wma_cfg.valid_bits_per_sample =
+				wma_config->validbitspersample;
+		wma_cfg.ch_mask =  wma_config->channelmask;
+		wma_cfg.encode_opt = wma_config->encodeopt;
+		/* Configure Media format block */
+		rc = q6asm_media_format_block_wma(audio->ac, &wma_cfg,
+				audio->ac->stream_id);
+		if (rc < 0) {
+			pr_err("cmd media format block failed\n");
+			break;
+		}
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("AUDIO_START success enable[%d]\n", audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		break;
+	}
+	return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_WMA_CONFIG_V2: {
+		if (copy_to_user((void *)arg, audio->codec_cfg,
+			sizeof(struct msm_audio_wma_config_v2))) {
+			pr_err("%s:copy_to_user for AUDIO_SET_WMA_CONFIG_V2 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_WMA_CONFIG_V2: {
+		if (copy_from_user(audio->codec_cfg, (void *)arg,
+			sizeof(struct msm_audio_wma_config_v2))) {
+			pr_err("%s:copy_from_user for AUDIO_SET_WMA_CONFIG_V2 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	default: {
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("Failed in utils_ioctl: %d\n", rc);
+		break;
+	}
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_wma_config_v2_32 {
+	u16 format_tag;
+	u16 numchannels;
+	u32 samplingrate;
+	u32 avgbytespersecond;
+	u16 block_align;
+	u16 validbitspersample;
+	u32 channelmask;
+	u16 encodeopt;
+};
+
+enum {
+	AUDIO_GET_WMA_CONFIG_V2_32 =  _IOR(AUDIO_IOCTL_MAGIC,
+	(AUDIO_MAX_COMMON_IOCTL_NUM+2), struct msm_audio_wma_config_v2_32),
+	AUDIO_SET_WMA_CONFIG_V2_32 =  _IOW(AUDIO_IOCTL_MAGIC,
+	(AUDIO_MAX_COMMON_IOCTL_NUM+3), struct msm_audio_wma_config_v2_32)
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+						unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	case AUDIO_GET_WMA_CONFIG_V2_32: {
+		struct msm_audio_wma_config_v2 *wma_config;
+		struct msm_audio_wma_config_v2_32 wma_config_32;
+
+		memset(&wma_config_32, 0, sizeof(wma_config_32));
+
+		wma_config = (struct msm_audio_wma_config_v2 *)audio->codec_cfg;
+		wma_config_32.format_tag = wma_config->format_tag;
+		wma_config_32.numchannels = wma_config->numchannels;
+		wma_config_32.samplingrate = wma_config->samplingrate;
+		wma_config_32.avgbytespersecond = wma_config->avgbytespersecond;
+		wma_config_32.block_align = wma_config->block_align;
+		wma_config_32.validbitspersample =
+					wma_config->validbitspersample;
+		wma_config_32.channelmask = wma_config->channelmask;
+		wma_config_32.encodeopt = wma_config->encodeopt;
+		if (copy_to_user((void *)arg, &wma_config_32,
+			sizeof(wma_config_32))) {
+			pr_err("%s: copy_to_user for GET_WMA_CONFIG_V2_32 failed\n",
+				 __func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_WMA_CONFIG_V2_32: {
+		struct msm_audio_wma_config_v2 *wma_config;
+		struct msm_audio_wma_config_v2_32 wma_config_32;
+
+		if (copy_from_user(&wma_config_32, (void *)arg,
+			sizeof(wma_config_32))) {
+			pr_err("%s: copy_from_user for SET_WMA_CONFIG_V2_32 failed\n"
+				, __func__);
+			rc = -EFAULT;
+			break;
+		}
+		wma_config = (struct msm_audio_wma_config_v2 *)audio->codec_cfg;
+		wma_config->format_tag = wma_config_32.format_tag;
+		wma_config->numchannels = wma_config_32.numchannels;
+		wma_config->samplingrate = wma_config_32.samplingrate;
+		wma_config->avgbytespersecond = wma_config_32.avgbytespersecond;
+		wma_config->block_align = wma_config_32.block_align;
+		wma_config->validbitspersample =
+				wma_config_32.validbitspersample;
+		wma_config->channelmask = wma_config_32.channelmask;
+		wma_config->encodeopt = wma_config_32.encodeopt;
+		break;
+	}
+	default: {
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("Failed in utils_ioctl: %d\n", rc);
+		break;
+	}
+	}
+	return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_wma_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	audio->codec_cfg = kzalloc(sizeof(struct msm_audio_wma_config_v2),
+					GFP_KERNEL);
+	if (audio->codec_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_wma_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_wma_ws_mgr;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio->codec_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_WMA_V9);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		/* open WMA decoder, expected frames is always 1*/
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_WMA_V9);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof(name), "msm_wma_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
+					    NULL, (void *)audio,
+					    &audio_wma_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:wmadec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_wma_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+	.compat_ioctl = audio_compat_ioctl
+};
+
+static struct miscdevice audio_wma_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_wma",
+	.fops = &audio_wma_fops,
+};
+
+static int __init audio_wma_init(void)
+{
+	int ret = misc_register(&audio_wma_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_wma_misc.this_device, true);
+	audio_wma_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_wma_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_wma_init);

+ 418 - 0
drivers/misc/qcom/qdsp6v2/audio_wmapro.c

@@ -0,0 +1,418 @@
+/* wmapro audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/types.h>
+#include <linux/msm_audio_wmapro.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_wmapro_misc;
+static struct ws_mgr audio_wmapro_ws_mgr;
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_wmapro_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+						void *arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct asm_wmapro_cfg wmapro_cfg;
+		struct msm_audio_wmapro_config *wmapro_config;
+
+		pr_debug("%s: AUDIO_START session_id[%d]\n", __func__,
+						audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm_v2(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count,
+					16, /* bits per sample */
+					true, /* use default channel map */
+					true, /* use back channel map flavor */
+					NULL);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+		wmapro_config = (struct msm_audio_wmapro_config *)
+				audio->codec_cfg;
+		if ((wmapro_config->formattag == 0x162) ||
+		(wmapro_config->formattag == 0x163) ||
+		(wmapro_config->formattag == 0x166) ||
+		(wmapro_config->formattag == 0x167)) {
+			wmapro_cfg.format_tag = wmapro_config->formattag;
+		} else {
+			pr_err("%s:AUDIO_START failed: formattag = %d\n",
+				__func__, wmapro_config->formattag);
+			rc = -EINVAL;
+			break;
+		}
+		if (wmapro_config->numchannels > 0) {
+			wmapro_cfg.ch_cfg = wmapro_config->numchannels;
+		} else {
+			pr_err("%s:AUDIO_START failed: channels = %d\n",
+				__func__, wmapro_config->numchannels);
+			rc = -EINVAL;
+			break;
+		}
+		if (wmapro_config->samplingrate > 0) {
+			wmapro_cfg.sample_rate = wmapro_config->samplingrate;
+		} else {
+			pr_err("%s:AUDIO_START failed: sample_rate = %d\n",
+				__func__, wmapro_config->samplingrate);
+			rc = -EINVAL;
+			break;
+		}
+		wmapro_cfg.avg_bytes_per_sec =
+				wmapro_config->avgbytespersecond;
+		if ((wmapro_config->asfpacketlength <= 13376) ||
+		(wmapro_config->asfpacketlength > 0)) {
+			wmapro_cfg.block_align =
+				wmapro_config->asfpacketlength;
+		} else {
+			pr_err("%s:AUDIO_START failed: block_align = %d\n",
+				__func__, wmapro_config->asfpacketlength);
+			rc = -EINVAL;
+			break;
+		}
+		if ((wmapro_config->validbitspersample == 16) ||
+			(wmapro_config->validbitspersample == 24)) {
+			wmapro_cfg.valid_bits_per_sample =
+				wmapro_config->validbitspersample;
+		} else {
+			pr_err("%s:AUDIO_START failed: bitspersample = %d\n",
+				__func__, wmapro_config->validbitspersample);
+			rc = -EINVAL;
+			break;
+		}
+		wmapro_cfg.ch_mask = wmapro_config->channelmask;
+		wmapro_cfg.encode_opt = wmapro_config->encodeopt;
+		wmapro_cfg.adv_encode_opt =
+				wmapro_config->advancedencodeopt;
+		wmapro_cfg.adv_encode_opt2 =
+				wmapro_config->advancedencodeopt2;
+		/* Configure Media format block */
+		rc = q6asm_media_format_block_wmapro(audio->ac, &wmapro_cfg,
+				audio->ac->stream_id);
+		if (rc < 0) {
+			pr_err("cmd media format block failed\n");
+			break;
+		}
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("AUDIO_START success enable[%d]\n", audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd %d\n", __func__, cmd);
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_GET_WMAPRO_CONFIG: {
+		if (copy_to_user((void *)arg, audio->codec_cfg,
+			 sizeof(struct msm_audio_wmapro_config))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_WMAPRO_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_WMAPRO_CONFIG: {
+		if (copy_from_user(audio->codec_cfg, (void *)arg,
+			sizeof(struct msm_audio_wmapro_config))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_WMAPRO_CONFIG_V2 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	default: {
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("Failed in utils_ioctl: %d\n", rc);
+		break;
+	}
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+
+struct msm_audio_wmapro_config32 {
+	u16 armdatareqthr;
+	u8  validbitspersample;
+	u8  numchannels;
+	u16 formattag;
+	u32 samplingrate;
+	u32 avgbytespersecond;
+	u16 asfpacketlength;
+	u32 channelmask;
+	u16 encodeopt;
+	u16 advancedencodeopt;
+	u32 advancedencodeopt2;
+};
+
+enum {
+	AUDIO_GET_WMAPRO_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_wmapro_config32),
+	AUDIO_SET_WMAPRO_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_wmapro_config32)
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+					unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_GET_WMAPRO_CONFIG_32: {
+		struct msm_audio_wmapro_config *wmapro_config;
+		struct msm_audio_wmapro_config32 wmapro_config_32;
+
+		memset(&wmapro_config_32, 0, sizeof(wmapro_config_32));
+
+		wmapro_config =
+			(struct msm_audio_wmapro_config *)audio->codec_cfg;
+		wmapro_config_32.armdatareqthr = wmapro_config->armdatareqthr;
+		wmapro_config_32.validbitspersample =
+					wmapro_config->validbitspersample;
+		wmapro_config_32.numchannels = wmapro_config->numchannels;
+		wmapro_config_32.formattag = wmapro_config->formattag;
+		wmapro_config_32.samplingrate = wmapro_config->samplingrate;
+		wmapro_config_32.avgbytespersecond =
+					wmapro_config->avgbytespersecond;
+		wmapro_config_32.asfpacketlength =
+					wmapro_config->asfpacketlength;
+		wmapro_config_32.channelmask = wmapro_config->channelmask;
+		wmapro_config_32.encodeopt = wmapro_config->encodeopt;
+		wmapro_config_32.advancedencodeopt =
+					wmapro_config->advancedencodeopt;
+		wmapro_config_32.advancedencodeopt2 =
+					wmapro_config->advancedencodeopt2;
+
+		if (copy_to_user((void *)arg, &wmapro_config_32,
+			 sizeof(struct msm_audio_wmapro_config32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_WMAPRO_CONFIG_V2_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_WMAPRO_CONFIG_32: {
+		struct msm_audio_wmapro_config *wmapro_config;
+		struct msm_audio_wmapro_config32 wmapro_config_32;
+
+		if (copy_from_user(&wmapro_config_32, (void *)arg,
+			sizeof(struct msm_audio_wmapro_config32))) {
+			pr_err(
+				"%s: copy_from_user for AUDIO_SET_WMAPRO_CONFG_V2_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		wmapro_config =
+			(struct msm_audio_wmapro_config *)audio->codec_cfg;
+		wmapro_config->armdatareqthr = wmapro_config_32.armdatareqthr;
+		wmapro_config->validbitspersample =
+					wmapro_config_32.validbitspersample;
+		wmapro_config->numchannels = wmapro_config_32.numchannels;
+		wmapro_config->formattag = wmapro_config_32.formattag;
+		wmapro_config->samplingrate = wmapro_config_32.samplingrate;
+		wmapro_config->avgbytespersecond =
+					wmapro_config_32.avgbytespersecond;
+		wmapro_config->asfpacketlength =
+					wmapro_config_32.asfpacketlength;
+		wmapro_config->channelmask = wmapro_config_32.channelmask;
+		wmapro_config->encodeopt = wmapro_config_32.encodeopt;
+		wmapro_config->advancedencodeopt =
+					wmapro_config_32.advancedencodeopt;
+		wmapro_config->advancedencodeopt2 =
+					wmapro_config_32.advancedencodeopt2;
+		break;
+	}
+	case AUDIO_START: {
+		rc = audio_ioctl_shared(file, cmd, (void *)arg);
+		break;
+	}
+	default: {
+		pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_compat_ioctl(file, cmd, arg);
+		if (rc)
+			pr_err("Failed in utils_ioctl: %d\n", rc);
+		break;
+	}
+	}
+	return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_wmapro_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	audio->codec_cfg = kzalloc(sizeof(struct msm_audio_wmapro_config),
+					GFP_KERNEL);
+	if (audio->codec_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->miscdevice = &audio_wmapro_misc;
+	audio->wakelock_voted = false;
+	audio->audio_ws_mgr = &audio_wmapro_ws_mgr;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio->codec_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	rc = audio_aio_open(audio, file);
+	if (rc < 0) {
+		pr_err("%s: audio_aio_open rc=%d\n",
+			__func__, rc);
+		goto fail;
+	}
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_WMA_V10PRO);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		/* open WMA decoder, expected frames is always 1*/
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_WMA_V10PRO);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof(name), "msm_wmapro_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
+					    NULL, (void *)audio,
+					    &audio_wmapro_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:wmapro decoder open success, session_id = %d\n", __func__,
+				audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_wmapro_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+	.compat_ioctl = audio_compat_ioctl
+};
+
+static struct miscdevice audio_wmapro_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_wmapro",
+	.fops = &audio_wmapro_fops,
+};
+
+static int __init audio_wmapro_init(void)
+{
+	int ret = misc_register(&audio_wmapro_misc);
+
+	if (ret == 0)
+		device_init_wakeup(audio_wmapro_misc.this_device, true);
+	audio_wmapro_ws_mgr.ref_cnt = 0;
+	mutex_init(&audio_wmapro_ws_mgr.ws_lock);
+
+	return ret;
+}
+
+device_initcall(audio_wmapro_init);

+ 410 - 0
drivers/misc/qcom/qdsp6v2/evrc_in.c

@@ -0,0 +1,410 @@
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/msm_audio_qcp.h>
+#include <linux/atomic.h>
+#include <linux/compat.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+/* Buffer with meta*/
+#define PCM_BUF_SIZE		(4096 + sizeof(struct meta_in))
+
+/* Maximum 10 frames in buffer with meta */
+#define FRAME_SIZE		(1 + ((23+sizeof(struct meta_out_dsp)) * 10))
+
+static long evrc_in_ioctl_shared(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+	int cnt = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct msm_audio_evrc_enc_config *enc_cfg;
+
+		enc_cfg = audio->enc_cfg;
+		pr_debug("%s:session id %d: default buf alloc[%d]\n", __func__,
+				audio->ac->session, audio->buf_alloc);
+		if (audio->enabled == 1) {
+			pr_info("%s:AUDIO_START already over\n", __func__);
+			rc = 0;
+			break;
+		}
+		rc = audio_in_buf_alloc(audio);
+		if (rc < 0) {
+			pr_err("%s:session id %d: buffer allocation failed\n",
+				__func__, audio->ac->session);
+			break;
+		}
+
+		/* rate_modulation_cmd set to zero
+		 * currently not configurable from user space
+		 */
+		rc = q6asm_enc_cfg_blk_evrc(audio->ac,
+			audio->buf_cfg.frames_per_buf,
+			enc_cfg->min_bit_rate,
+			enc_cfg->max_bit_rate, 0);
+
+		if (rc < 0) {
+			pr_err("%s:session id %d: cmd evrc media format block failed\n",
+					__func__, audio->ac->session);
+			break;
+		}
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			rc = q6asm_media_format_block_pcm(audio->ac,
+				audio->pcm_cfg.sample_rate,
+				audio->pcm_cfg.channel_count);
+
+			if (rc < 0) {
+				pr_err("%s:session id %d: media format block failed\n",
+					__func__, audio->ac->session);
+				break;
+			}
+		}
+		pr_debug("%s:session id %d: AUDIO_START enable[%d]\n",
+				__func__, audio->ac->session, audio->enabled);
+		rc = audio_in_enable(audio);
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s:session id %d: Audio Start procedure failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+			break;
+		}
+		while (cnt++ < audio->str_cfg.buffer_count)
+			q6asm_read(audio->ac); /* Push buffer to DSP */
+		rc = 0;
+		pr_debug("%s:session id %d: AUDIO_START success enable[%d]\n",
+				__func__, audio->ac->session, audio->enabled);
+		break;
+	}
+	case AUDIO_STOP: {
+		pr_debug("%s:session id %d: AUDIO_STOP\n", __func__,
+				audio->ac->session);
+		rc = audio_in_disable(audio);
+		if (rc  < 0) {
+			pr_err("%s:session id %d: Audio Stop procedure failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_EVRC_ENC_CONFIG: {
+		struct msm_audio_evrc_enc_config *cfg;
+		struct msm_audio_evrc_enc_config *enc_cfg;
+
+		enc_cfg = audio->enc_cfg;
+		cfg = (struct msm_audio_evrc_enc_config *)arg;
+		if (cfg == NULL) {
+			pr_err("%s: NULL config pointer for %s\n",
+					__func__, "AUDIO_SET_EVRC_ENC_CONFIG");
+			rc = -EINVAL;
+			break;
+		}
+		if (cfg->min_bit_rate > 4 ||
+			 cfg->min_bit_rate < 1 ||
+			 (cfg->min_bit_rate == 2)) {
+			pr_err("%s:session id %d: invalid min bitrate\n",
+					__func__, audio->ac->session);
+			rc = -EINVAL;
+			break;
+		}
+		if (cfg->max_bit_rate > 4 ||
+			 cfg->max_bit_rate < 1 ||
+			 (cfg->max_bit_rate == 2)) {
+			pr_err("%s:session id %d: invalid max bitrate\n",
+				__func__, audio->ac->session);
+			rc = -EINVAL;
+			break;
+		}
+		enc_cfg->min_bit_rate = cfg->min_bit_rate;
+		enc_cfg->max_bit_rate = cfg->max_bit_rate;
+		pr_debug("%s:session id %d: min_bit_rate= 0x%x max_bit_rate=0x%x\n",
+			__func__,
+			audio->ac->session, enc_cfg->min_bit_rate,
+			enc_cfg->max_bit_rate);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static long evrc_in_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = evrc_in_ioctl_shared(file, cmd, arg);
+		break;
+	}
+	case AUDIO_GET_EVRC_ENC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->enc_cfg,
+			sizeof(struct msm_audio_evrc_enc_config))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_EVRC_ENC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_EVRC_ENC_CONFIG: {
+		struct msm_audio_evrc_enc_config cfg;
+
+		if (copy_from_user(&cfg, (void *) arg,
+				sizeof(struct msm_audio_evrc_enc_config))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_EVRC_ENC_CONFIG failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = evrc_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_EVRC_ENC_CONFIG failed. rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_evrc_enc_config32 {
+	u32 cdma_rate;
+	u32 min_bit_rate;
+	u32 max_bit_rate;
+};
+
+enum {
+	AUDIO_SET_EVRC_ENC_CONFIG_32 =  _IOW(AUDIO_IOCTL_MAGIC,
+		2, struct msm_audio_evrc_enc_config32),
+	AUDIO_GET_EVRC_ENC_CONFIG_32 =  _IOR(AUDIO_IOCTL_MAGIC,
+		3, struct msm_audio_evrc_enc_config32)
+};
+
+static long evrc_in_compat_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = evrc_in_ioctl_shared(file, cmd, arg);
+		break;
+	}
+	case AUDIO_GET_EVRC_ENC_CONFIG_32: {
+		struct msm_audio_evrc_enc_config32 cfg_32;
+		struct msm_audio_evrc_enc_config *enc_cfg;
+
+		memset(&cfg_32, 0, sizeof(cfg_32));
+
+		enc_cfg = audio->enc_cfg;
+		cfg_32.cdma_rate = enc_cfg->cdma_rate;
+		cfg_32.min_bit_rate = enc_cfg->min_bit_rate;
+		cfg_32.max_bit_rate = enc_cfg->max_bit_rate;
+
+		if (copy_to_user((void *)arg, &cfg_32,
+			sizeof(cfg_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_EVRC_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_EVRC_ENC_CONFIG_32: {
+		struct msm_audio_evrc_enc_config cfg;
+		struct msm_audio_evrc_enc_config32 cfg_32;
+
+		if (copy_from_user(&cfg_32, (void *) arg,
+				sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_EVRC_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		cfg.cdma_rate = cfg_32.cdma_rate;
+		cfg.min_bit_rate = cfg_32.min_bit_rate;
+		cfg.max_bit_rate = cfg_32.max_bit_rate;
+		cmd = AUDIO_SET_EVRC_ENC_CONFIG;
+		rc = evrc_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_EVRC_ENC_CONFIG failed. rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+#else
+#define evrc_in_compat_ioctl NULL
+#endif
+
+static int evrc_in_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_in *audio = NULL;
+	struct msm_audio_evrc_enc_config *enc_cfg;
+	int rc = 0;
+
+	audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	/* Allocate memory for encoder config param */
+	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_evrc_enc_config),
+				GFP_KERNEL);
+	if (audio->enc_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+	enc_cfg = audio->enc_cfg;
+	mutex_init(&audio->lock);
+	mutex_init(&audio->read_lock);
+	mutex_init(&audio->write_lock);
+	spin_lock_init(&audio->dsp_lock);
+	init_waitqueue_head(&audio->read_wait);
+	init_waitqueue_head(&audio->write_wait);
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->str_cfg.buffer_size = FRAME_SIZE;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->min_frame_size = 23;
+	audio->max_frames_per_buf = 10;
+	audio->pcm_cfg.buffer_size = PCM_BUF_SIZE;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	enc_cfg->min_bit_rate = 4;
+	enc_cfg->max_bit_rate = 4;
+	audio->pcm_cfg.channel_count = 1;
+	audio->pcm_cfg.sample_rate = 8000;
+	audio->buf_cfg.meta_info_enable = 0x01;
+	audio->buf_cfg.frames_per_buf = 0x01;
+	audio->event_abort = 0;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb)q6asm_in_cb,
+				(void *)audio);
+
+	if (!audio->ac) {
+		pr_err("%s: Could not allocate memory for audio client\n",
+				__func__);
+		kfree(audio->enc_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open evrc encoder in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) &&
+		(file->f_mode & FMODE_READ)) {
+		audio->feedback = NON_TUNNEL_MODE;
+		rc = q6asm_open_read_write(audio->ac, FORMAT_EVRC,
+					FORMAT_LINEAR_PCM);
+		if (rc < 0) {
+			pr_err("%s:session id %d: NT mode Open failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		pr_info("%s:session id %d: NT mode encoder success\n",
+				__func__, audio->ac->session);
+	} else if (!(file->f_mode & FMODE_WRITE) &&
+				(file->f_mode & FMODE_READ)) {
+		audio->feedback = TUNNEL_MODE;
+		rc = q6asm_open_read(audio->ac, FORMAT_EVRC);
+		if (rc < 0) {
+			pr_err("%s:session id %d: T mode Open failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		/* register for tx overflow (valid for tunnel mode only) */
+		rc = q6asm_reg_tx_overflow(audio->ac, 0x01);
+		if (rc < 0) {
+			pr_err("%s:session id %d: TX Overflow registration failed rc=%d\n",
+				__func__,
+				audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		pr_info("%s:session id %d: T mode encoder success\n", __func__,
+				audio->ac->session);
+	} else {
+		pr_err("%s:session id %d: Unexpected mode\n", __func__,
+				audio->ac->session);
+		rc = -EACCES;
+		goto fail;
+	}
+
+	audio->opened = 1;
+	audio->reset_event = false;
+	atomic_set(&audio->in_count, PCM_BUF_COUNT);
+	atomic_set(&audio->out_count, 0x00);
+	audio->enc_compat_ioctl = evrc_in_compat_ioctl;
+	audio->enc_ioctl = evrc_in_ioctl;
+	file->private_data = audio;
+
+	pr_info("%s:session id %d: success\n", __func__, audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->enc_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_in_fops = {
+	.owner		= THIS_MODULE,
+	.open		= evrc_in_open,
+	.release	= audio_in_release,
+	.read		= audio_in_read,
+	.write		= audio_in_write,
+	.unlocked_ioctl	= audio_in_ioctl,
+	.compat_ioctl   = audio_in_compat_ioctl
+};
+
+struct miscdevice audio_evrc_in_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_evrc_in",
+	.fops	= &audio_in_fops,
+};
+
+static int __init evrc_in_init(void)
+{
+	return misc_register(&audio_evrc_in_misc);
+}
+
+device_initcall(evrc_in_init);

+ 382 - 0
drivers/misc/qcom/qdsp6v2/g711alaw_in.c

@@ -0,0 +1,382 @@
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/msm_audio_g711.h>
+#include <linux/atomic.h>
+#include <linux/compat.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+/* Buffer with meta*/
+#define PCM_BUF_SIZE		(4096 + sizeof(struct meta_in))
+
+/* Maximum 10 frames in buffer with meta */
+#define FRAME_SIZE		(1 + ((320+sizeof(struct meta_out_dsp)) * 10))
+static long g711_in_ioctl_shared(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+	int cnt = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct msm_audio_g711_enc_config *enc_cfg;
+
+		enc_cfg = (struct msm_audio_g711_enc_config *)audio->enc_cfg;
+		pr_debug("%s:session id %d: default buf alloc[%d]\n", __func__,
+				audio->ac->session, audio->buf_alloc);
+		if (audio->enabled == 1) {
+			rc = 0;
+			break;
+		}
+		rc = audio_in_buf_alloc(audio);
+		if (rc < 0) {
+			pr_err("%s:session id %d: buffer allocation failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			break;
+		}
+		pr_debug("%s: sample rate %d", __func__, enc_cfg->sample_rate);
+		rc = q6asm_enc_cfg_blk_g711(audio->ac,
+			audio->buf_cfg.frames_per_buf,
+			enc_cfg->sample_rate);
+
+		if (rc < 0) {
+			pr_err("%s:session id %d: cmd g711 media format block failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+			break;
+		}
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			rc = q6asm_media_format_block_pcm(audio->ac,
+				audio->pcm_cfg.sample_rate,
+				audio->pcm_cfg.channel_count);
+
+			if (rc < 0) {
+				pr_err("%s:session id %d: media format block failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+				break;
+			}
+		}
+		pr_debug("%s:session id %d: AUDIO_START enable[%d]\n", __func__,
+				audio->ac->session, audio->enabled);
+		rc = audio_in_enable(audio);
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s:session id %d: Audio Start procedure failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+			break;
+		}
+		while (cnt++ < audio->str_cfg.buffer_count)
+			q6asm_read(audio->ac); /* Push buffer to DSP */
+		rc = 0;
+		pr_debug("%s:session id %d: AUDIO_START success enable[%d]\n",
+				__func__, audio->ac->session, audio->enabled);
+		break;
+	}
+	case AUDIO_STOP: {
+		pr_debug("%s:session id %d: AUDIO_STOP\n", __func__,
+				audio->ac->session);
+		rc = audio_in_disable(audio);
+		if (rc  < 0) {
+			pr_err("%s:session id %d: Audio Stop procedure failed rc=%d\n",
+				__func__, audio->ac->session,
+					rc);
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_G711_ENC_CONFIG: {
+		struct msm_audio_g711_enc_config *cfg;
+		struct msm_audio_g711_enc_config *enc_cfg;
+
+		enc_cfg = (struct msm_audio_g711_enc_config *)audio->enc_cfg;
+
+		cfg = (struct msm_audio_g711_enc_config *)arg;
+		if (cfg == NULL) {
+			pr_err("%s: NULL config pointer\n", __func__);
+			rc = -EINVAL;
+			break;
+		}
+		if (cfg->sample_rate != 8000 &&
+			 cfg->sample_rate != 16000) {
+			pr_err("%s:session id %d: invalid sample rate\n",
+					__func__, audio->ac->session);
+			rc = -EINVAL;
+			break;
+		}
+		enc_cfg->sample_rate = cfg->sample_rate;
+		pr_debug("%s:session id %d: sample_rate= 0x%x",
+			__func__,
+			audio->ac->session, enc_cfg->sample_rate);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -ENOIOCTLCMD;
+	}
+	return rc;
+}
+
+static long g711_in_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = g711_in_ioctl_shared(file, cmd, arg);
+		break;
+	}
+	case AUDIO_GET_G711_ENC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->enc_cfg,
+			sizeof(struct msm_audio_g711_enc_config))) {
+			pr_err(
+				"%s: copy_to_user for AUDIO_GET_g711_ENC_CONFIG failed",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_G711_ENC_CONFIG: {
+		struct msm_audio_g711_enc_config cfg;
+
+		if (copy_from_user(&cfg, (void *) arg,
+				sizeof(cfg))) {
+			pr_err(
+				"%s: copy_from_user for AUDIO_GET_G711_ENC_CONFIG failed",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = g711_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+		if (rc)
+			pr_err("%s:AUDIO_GET_G711_ENC_CONFIG failed. Rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -ENOIOCTLCMD;
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_g711_enc_config32 {
+	uint32_t sample_rate;
+};
+
+enum {
+	AUDIO_SET_G711_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_g711_enc_config32),
+	AUDIO_GET_G711_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_g711_enc_config32)
+};
+
+static long g711_in_compat_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = g711_in_ioctl_shared(file, cmd, arg);
+		break;
+	}
+	case AUDIO_GET_G711_ENC_CONFIG_32: {
+		struct msm_audio_g711_enc_config32 cfg_32;
+		struct msm_audio_g711_enc_config32 *enc_cfg;
+
+		enc_cfg = (struct msm_audio_g711_enc_config32 *)audio->enc_cfg;
+		cfg_32.sample_rate = enc_cfg->sample_rate;
+		if (copy_to_user((void *)arg, &cfg_32,
+			sizeof(cfg_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_G711_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_G711_ENC_CONFIG_32: {
+		struct msm_audio_g711_enc_config32 cfg_32;
+		struct msm_audio_g711_enc_config32 cfg;
+
+		if (copy_from_user(&cfg_32, (void *) arg,
+				sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_G711_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		cfg.sample_rate = cfg_32.sample_rate;
+		cmd = AUDIO_SET_G711_ENC_CONFIG;
+		rc = g711_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_G711_ENC_CONFIG failed. rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -ENOIOCTLCMD;
+	}
+	return rc;
+}
+#else
+#define g711_in_compat_ioctl NULL
+#endif
+
+static int g711_in_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_in *audio = NULL;
+	struct msm_audio_g711_enc_config *enc_cfg;
+	int rc = 0;
+
+	audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+	/* Allocate memory for encoder config param */
+	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_g711_enc_config),
+				GFP_KERNEL);
+	if (audio->enc_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+	enc_cfg = audio->enc_cfg;
+
+	mutex_init(&audio->lock);
+	mutex_init(&audio->read_lock);
+	mutex_init(&audio->write_lock);
+	spin_lock_init(&audio->dsp_lock);
+	init_waitqueue_head(&audio->read_wait);
+	init_waitqueue_head(&audio->write_wait);
+
+	/*
+	 * Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->str_cfg.buffer_size = FRAME_SIZE;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->min_frame_size = 320;
+	audio->max_frames_per_buf = 10;
+	audio->pcm_cfg.buffer_size = PCM_BUF_SIZE;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	enc_cfg->sample_rate = 8000;
+	audio->pcm_cfg.channel_count = 1;
+	audio->pcm_cfg.sample_rate = 8000;
+	audio->buf_cfg.meta_info_enable = 0x01;
+	audio->buf_cfg.frames_per_buf = 0x01;
+	audio->event_abort = 0;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb)q6asm_in_cb,
+				(void *)audio);
+
+	if (!audio->ac) {
+		kfree(audio->enc_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open g711 encoder in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) &&
+		(file->f_mode & FMODE_READ)) {
+		audio->feedback = NON_TUNNEL_MODE;
+		rc = q6asm_open_read_write(audio->ac, FORMAT_G711_ALAW_FS,
+					FORMAT_LINEAR_PCM);
+		if (rc < 0) {
+			pr_err("%s:session id %d: NT mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+	} else if (!(file->f_mode & FMODE_WRITE) &&
+				(file->f_mode & FMODE_READ)) {
+		audio->feedback = TUNNEL_MODE;
+		rc = q6asm_open_read(audio->ac, FORMAT_G711_ALAW_FS);
+		if (rc < 0) {
+			pr_err("%s:session id %d: T mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		/* register for tx overflow (valid for tunnel mode only) */
+		rc = q6asm_reg_tx_overflow(audio->ac, 0x01);
+		if (rc < 0) {
+			pr_err("%s:session id %d: TX Overflow registration failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+	} else {
+		pr_err("%s:session id %d: Unexpected mode\n", __func__,
+				audio->ac->session);
+		rc = -EACCES;
+		goto fail;
+	}
+
+	audio->opened = 1;
+	audio->reset_event = false;
+	atomic_set(&audio->in_count, PCM_BUF_COUNT);
+	atomic_set(&audio->out_count, 0x00);
+	audio->enc_compat_ioctl = g711_in_compat_ioctl;
+	audio->enc_ioctl = g711_in_ioctl;
+	file->private_data = audio;
+
+	pr_info("%s:session id %d: success\n", __func__, audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->enc_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_in_fops = {
+	.owner		= THIS_MODULE,
+	.open		= g711_in_open,
+	.release	= audio_in_release,
+	.read		= audio_in_read,
+	.write		= audio_in_write,
+	.unlocked_ioctl	= audio_in_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = audio_in_compat_ioctl,
+#endif
+};
+
+struct miscdevice audio_g711alaw_in_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_g711alaw_in",
+	.fops	= &audio_in_fops,
+};
+
+static int __init g711alaw_in_init(void)
+{
+	return misc_register(&audio_g711alaw_in_misc);
+}
+
+device_initcall(g711alaw_in_init);

+ 385 - 0
drivers/misc/qcom/qdsp6v2/g711mlaw_in.c

@@ -0,0 +1,385 @@
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/msm_audio_g711.h>
+#include <linux/atomic.h>
+#include <linux/compat.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+#ifdef CONFIG_COMPAT
+#undef PROC_ADD
+#endif
+/* Buffer with meta*/
+#define PCM_BUF_SIZE		(4096 + sizeof(struct meta_in))
+
+/* Maximum 10 frames in buffer with meta */
+#define FRAME_SIZE		(1 + ((320+sizeof(struct meta_out_dsp)) * 10))
+static long g711_in_ioctl_shared(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+	int cnt = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct msm_audio_g711_enc_config *enc_cfg;
+
+		enc_cfg = (struct msm_audio_g711_enc_config *)audio->enc_cfg;
+		pr_debug("%s:session id %d: default buf alloc[%d]\n", __func__,
+				audio->ac->session, audio->buf_alloc);
+		if (audio->enabled == 1) {
+			rc = 0;
+			break;
+		}
+		rc = audio_in_buf_alloc(audio);
+		if (rc < 0) {
+			pr_err("%s:session id %d: buffer allocation failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			break;
+		}
+		pr_debug("%s: sample rate %d", __func__, enc_cfg->sample_rate);
+		rc = q6asm_enc_cfg_blk_g711(audio->ac,
+			audio->buf_cfg.frames_per_buf,
+			enc_cfg->sample_rate);
+
+		if (rc < 0) {
+			pr_err("%s:session id %d: cmd g711 media format block failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+			break;
+		}
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			rc = q6asm_media_format_block_pcm(audio->ac,
+				audio->pcm_cfg.sample_rate,
+				audio->pcm_cfg.channel_count);
+
+			if (rc < 0) {
+				pr_err("%s:session id %d: media format block failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+				break;
+			}
+		}
+		pr_debug("%s:session id %d: AUDIO_START enable[%d]\n", __func__,
+				audio->ac->session, audio->enabled);
+		rc = audio_in_enable(audio);
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s:session id %d: Audio Start procedure failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+			break;
+		}
+		while (cnt++ < audio->str_cfg.buffer_count)
+			q6asm_read(audio->ac); /* Push buffer to DSP */
+		rc = 0;
+		pr_debug("%s:session id %d: AUDIO_START success enable[%d]\n",
+				__func__, audio->ac->session, audio->enabled);
+		break;
+	}
+	case AUDIO_STOP: {
+		pr_debug("%s:session id %d: AUDIO_STOP\n", __func__,
+				audio->ac->session);
+		rc = audio_in_disable(audio);
+		if (rc  < 0) {
+			pr_err("%s:session id %d: Audio Stop procedure failed rc=%d\n",
+				__func__, audio->ac->session,
+					rc);
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_G711_ENC_CONFIG: {
+		struct msm_audio_g711_enc_config *cfg;
+		struct msm_audio_g711_enc_config *enc_cfg;
+
+		enc_cfg = (struct msm_audio_g711_enc_config *)audio->enc_cfg;
+
+		cfg = (struct msm_audio_g711_enc_config *)arg;
+		if (cfg == NULL) {
+			pr_err("%s: NULL config pointer\n", __func__);
+			rc = -EINVAL;
+			break;
+		}
+		if (cfg->sample_rate != 8000 &&
+			 cfg->sample_rate != 16000) {
+			pr_err("%s:session id %d: invalid sample rate\n",
+					__func__, audio->ac->session);
+			rc = -EINVAL;
+			break;
+		}
+		enc_cfg->sample_rate = cfg->sample_rate;
+		pr_debug("%s:session id %d: sample_rate= 0x%x",
+			__func__,
+			audio->ac->session, enc_cfg->sample_rate);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -ENOIOCTLCMD;
+	}
+	return rc;
+}
+
+static long g711_in_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = g711_in_ioctl_shared(file, cmd, arg);
+		break;
+	}
+	case AUDIO_GET_G711_ENC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->enc_cfg,
+			sizeof(struct msm_audio_g711_enc_config))) {
+			pr_err(
+				"%s: copy_to_user for AUDIO_GET_g711_ENC_CONFIG failed",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_G711_ENC_CONFIG: {
+		struct msm_audio_g711_enc_config cfg;
+
+		if (copy_from_user(&cfg, (void *) arg,
+				sizeof(cfg))) {
+			pr_err(
+				"%s: copy_from_user for AUDIO_GET_G711_ENC_CONFIG failed",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = g711_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+		if (rc)
+			pr_err("%s:AUDIO_GET_G711_ENC_CONFIG failed. Rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -ENOIOCTLCMD;
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_g711_enc_config32 {
+	uint32_t sample_rate;
+};
+
+enum {
+	AUDIO_SET_G711_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_g711_enc_config32),
+	AUDIO_GET_G711_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+	  (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_g711_enc_config32)
+};
+
+static long g711_in_compat_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = g711_in_ioctl_shared(file, cmd, arg);
+		break;
+	}
+	case AUDIO_GET_G711_ENC_CONFIG_32: {
+		struct msm_audio_g711_enc_config32 cfg_32;
+		struct msm_audio_g711_enc_config32 *enc_cfg;
+
+		enc_cfg = (struct msm_audio_g711_enc_config32 *)audio->enc_cfg;
+		cfg_32.sample_rate = enc_cfg->sample_rate;
+		if (copy_to_user((void *)arg, &cfg_32,
+			sizeof(cfg_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_G711_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_G711_ENC_CONFIG_32: {
+		struct msm_audio_g711_enc_config32 cfg_32;
+		struct msm_audio_g711_enc_config32 cfg;
+
+		if (copy_from_user(&cfg_32, (void *) arg,
+				sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_G711_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		cfg.sample_rate = cfg_32.sample_rate;
+		cmd = AUDIO_SET_G711_ENC_CONFIG;
+		rc = g711_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_G711_ENC_CONFIG failed. rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -ENOIOCTLCMD;
+	}
+	return rc;
+}
+#else
+#define g711_in_compat_ioctl NULL
+#endif
+
+static int g711_in_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_in *audio = NULL;
+	struct msm_audio_g711_enc_config *enc_cfg;
+	int rc = 0;
+
+	audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+	/* Allocate memory for encoder config param */
+	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_g711_enc_config),
+				GFP_KERNEL);
+	if (audio->enc_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+	enc_cfg = audio->enc_cfg;
+
+	mutex_init(&audio->lock);
+	mutex_init(&audio->read_lock);
+	mutex_init(&audio->write_lock);
+	spin_lock_init(&audio->dsp_lock);
+	init_waitqueue_head(&audio->read_wait);
+	init_waitqueue_head(&audio->write_wait);
+
+	/*
+	 * Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->str_cfg.buffer_size = FRAME_SIZE;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->min_frame_size = 320;
+	audio->max_frames_per_buf = 10;
+	audio->pcm_cfg.buffer_size = PCM_BUF_SIZE;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	enc_cfg->sample_rate = 8000;
+	audio->pcm_cfg.channel_count = 1;
+	audio->pcm_cfg.sample_rate = 8000;
+	audio->buf_cfg.meta_info_enable = 0x01;
+	audio->buf_cfg.frames_per_buf = 0x01;
+	audio->event_abort = 0;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb)q6asm_in_cb,
+				(void *)audio);
+
+	if (!audio->ac) {
+		kfree(audio->enc_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open g711 encoder in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) &&
+		(file->f_mode & FMODE_READ)) {
+		audio->feedback = NON_TUNNEL_MODE;
+		rc = q6asm_open_read_write(audio->ac, FORMAT_G711_MLAW_FS,
+					FORMAT_LINEAR_PCM);
+		if (rc < 0) {
+			pr_err("%s:session id %d: NT mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+	} else if (!(file->f_mode & FMODE_WRITE) &&
+				(file->f_mode & FMODE_READ)) {
+		audio->feedback = TUNNEL_MODE;
+		rc = q6asm_open_read(audio->ac, FORMAT_G711_MLAW_FS);
+		if (rc < 0) {
+			pr_err("%s:session id %d: T mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		/* register for tx overflow (valid for tunnel mode only) */
+		rc = q6asm_reg_tx_overflow(audio->ac, 0x01);
+		if (rc < 0) {
+			pr_err("%s:session id %d: TX Overflow registration failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+	} else {
+		pr_err("%s:session id %d: Unexpected mode\n", __func__,
+				audio->ac->session);
+		rc = -EACCES;
+		goto fail;
+	}
+
+	audio->opened = 1;
+	audio->reset_event = false;
+	atomic_set(&audio->in_count, PCM_BUF_COUNT);
+	atomic_set(&audio->out_count, 0x00);
+	audio->enc_compat_ioctl = g711_in_compat_ioctl;
+	audio->enc_ioctl = g711_in_ioctl;
+	file->private_data = audio;
+
+	pr_info("%s:session id %d: success\n", __func__, audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->enc_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_in_fops = {
+	.owner		= THIS_MODULE,
+	.open		= g711_in_open,
+	.release	= audio_in_release,
+	.read		= audio_in_read,
+	.write		= audio_in_write,
+	.unlocked_ioctl = audio_in_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = audio_in_compat_ioctl,
+#endif
+};
+
+struct miscdevice audio_g711mlaw_in_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_g711mlaw_in",
+	.fops	= &audio_in_fops,
+};
+
+static int __init g711mlaw_in_init(void)
+{
+	return misc_register(&audio_g711mlaw_in_misc);
+}
+
+device_initcall(g711mlaw_in_init);

+ 37 - 0
drivers/misc/qcom/qdsp6v2/q6audio_common.h

@@ -0,0 +1,37 @@
+/* Copyright (c) 2012-2014, 2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+
+/* For Decoders */
+#ifndef __Q6_AUDIO_COMMON_H__
+#define __Q6_AUDIO_COMMON_H__
+
+#include <sound/apr_audio-v2.h>
+#include <sound/q6asm-v2.h>
+
+
+void q6_audio_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv);
+
+void audio_aio_cb(uint32_t opcode, uint32_t token,
+			uint32_t *payload,  void *audio);
+
+
+/* For Encoders */
+void q6asm_in_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv);
+
+void  audio_in_get_dsp_frames(void *audio,
+		uint32_t token,	uint32_t *payload);
+
+#endif /*__Q6_AUDIO_COMMON_H__*/

+ 106 - 0
drivers/misc/qcom/qdsp6v2/q6audio_v2.c

@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012-2013, 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/atomic.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+void q6asm_in_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv)
+{
+	struct q6audio_in *audio = (struct q6audio_in *)priv;
+	unsigned long flags;
+
+	pr_debug("%s:session id %d: opcode[0x%x]\n", __func__,
+			audio->ac->session, opcode);
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
+	switch (opcode) {
+	case ASM_DATA_EVENT_READ_DONE_V2:
+		audio_in_get_dsp_frames(audio, token, payload);
+		break;
+	case ASM_DATA_EVENT_WRITE_DONE_V2:
+		atomic_inc(&audio->in_count);
+		wake_up(&audio->write_wait);
+		break;
+	case ASM_DATA_EVENT_RENDERED_EOS:
+		audio->eos_rsp = 1;
+		wake_up(&audio->read_wait);
+		break;
+	case ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2:
+		break;
+	case ASM_SESSION_EVENTX_OVERFLOW:
+		pr_err("%s:session id %d: ASM_SESSION_EVENT_TX_OVERFLOW\n",
+			__func__, audio->ac->session);
+		break;
+	case RESET_EVENTS:
+		pr_debug("%s:received RESET EVENTS\n", __func__);
+		audio->enabled = 0;
+		audio->stopped = 1;
+		audio->event_abort = 1;
+		audio->reset_event = true;
+		wake_up(&audio->read_wait);
+		wake_up(&audio->write_wait);
+		break;
+	default:
+		pr_debug("%s:session id %d: Ignore opcode[0x%x]\n", __func__,
+			audio->ac->session, opcode);
+		break;
+	}
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
+}
+
+void  audio_in_get_dsp_frames(void *priv,
+	uint32_t token,	uint32_t *payload)
+{
+	struct q6audio_in *audio = (struct q6audio_in *)priv;
+	uint32_t index;
+
+	index = q6asm_get_buf_index_from_token(token);
+	pr_debug("%s:session id %d: index=%d nr frames=%d offset[%d]\n",
+			__func__, audio->ac->session, token, payload[9],
+			payload[5]);
+	pr_debug("%s:session id %d: timemsw=%d lsw=%d\n", __func__,
+			audio->ac->session, payload[7], payload[6]);
+	pr_debug("%s:session id %d: uflags=0x%8x uid=0x%8x\n", __func__,
+			audio->ac->session, payload[8], payload[10]);
+	pr_debug("%s:session id %d: enc_framesotal_size=0x%8x\n", __func__,
+			audio->ac->session, payload[4]);
+
+	/* Ensure the index is within max array size: FRAME_NUM */
+	if (index >= FRAME_NUM) {
+		pr_err("%s: Invalid index %d\n",
+			__func__, index);
+		return;
+	}
+
+	audio->out_frame_info[index][0] = payload[9];
+	audio->out_frame_info[index][1] = payload[5];
+
+	/* statistics of read */
+	atomic_add(payload[4], &audio->in_bytes);
+	atomic_add(payload[9], &audio->in_samples);
+
+	if (atomic_read(&audio->out_count) <= audio->str_cfg.buffer_count) {
+		atomic_inc(&audio->out_count);
+		wake_up(&audio->read_wait);
+	}
+}

+ 223 - 0
drivers/misc/qcom/qdsp6v2/q6audio_v2_aio.c

@@ -0,0 +1,223 @@
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/atomic.h>
+#include <asm/ioctls.h>
+#include "audio_utils_aio.h"
+
+void q6_audio_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv)
+{
+	struct q6audio_aio *audio = (struct q6audio_aio *)priv;
+
+	pr_debug("%s:opcode = %x token = 0x%x\n", __func__, opcode, token);
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE_V2:
+	case ASM_DATA_EVENT_READ_DONE_V2:
+	case ASM_DATA_EVENT_RENDERED_EOS:
+	case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
+	case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
+	case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
+	case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY:
+	case RESET_EVENTS:
+		audio_aio_cb(opcode, token, payload, audio);
+		break;
+	default:
+		pr_debug("%s:Unhandled event = 0x%8x\n", __func__, opcode);
+		break;
+	}
+}
+
+void audio_aio_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload,  void *priv/*struct q6audio_aio *audio*/)
+{
+	struct q6audio_aio *audio = (struct q6audio_aio *)priv;
+	union msm_audio_event_payload e_payload;
+
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE_V2:
+		pr_debug("%s[%pK]:ASM_DATA_EVENT_WRITE_DONE token = 0x%x\n",
+			__func__, audio, token);
+		audio_aio_async_write_ack(audio, token, payload);
+		break;
+	case ASM_DATA_EVENT_READ_DONE_V2:
+		pr_debug("%s[%pK]:ASM_DATA_EVENT_READ_DONE token = 0x%x\n",
+			__func__, audio, token);
+		audio_aio_async_read_ack(audio, token, payload);
+		break;
+	case ASM_DATA_EVENT_RENDERED_EOS:
+		/* EOS Handle */
+		pr_debug("%s[%pK]:ASM_DATA_CMDRSP_EOS\n", __func__, audio);
+		if (audio->feedback) { /* Non-Tunnel mode */
+			audio->eos_rsp = 1;
+			/* propagate input EOS i/p buffer,
+			 * after receiving DSP acknowledgment
+			 */
+			if (audio->eos_flag &&
+				(audio->eos_write_payload.aio_buf.buf_addr)) {
+				audio_aio_post_event(audio,
+						AUDIO_EVENT_WRITE_DONE,
+						audio->eos_write_payload);
+				memset(&audio->eos_write_payload, 0,
+					sizeof(union msm_audio_event_payload));
+				audio->eos_flag = 0;
+			}
+		} else { /* Tunnel mode */
+			audio->eos_rsp = 1;
+			wake_up(&audio->write_wait);
+			wake_up(&audio->cmd_wait);
+		}
+		break;
+	case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
+	case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
+		pr_debug("%s[%pK]:payload0[%x] payloa1d[%x]opcode= 0x%x\n",
+			__func__, audio, payload[0], payload[1], opcode);
+		break;
+	case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
+	case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY:
+		pr_debug("%s[%pK]: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0]-sr = %d, payload[1]-chl = %d, payload[2] = %d, payload[3] = %d\n",
+					 __func__, audio, payload[0],
+					 payload[1], payload[2], payload[3]);
+
+		pr_debug("%s[%pK]: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, sr(prev) = %d, chl(prev) = %d,",
+		__func__, audio, audio->pcm_cfg.sample_rate,
+		audio->pcm_cfg.channel_count);
+
+		audio->pcm_cfg.sample_rate = payload[0];
+		audio->pcm_cfg.channel_count = payload[1] & 0xFFFF;
+		e_payload.stream_info.chan_info = audio->pcm_cfg.channel_count;
+		e_payload.stream_info.sample_rate = audio->pcm_cfg.sample_rate;
+		audio_aio_post_event(audio, AUDIO_EVENT_STREAM_INFO, e_payload);
+		break;
+	case RESET_EVENTS:
+		pr_err("%s: Received opcode:0x%x\n", __func__, opcode);
+		audio->stopped = 1;
+		audio->reset_event = true;
+		wake_up(&audio->event_wait);
+		break;
+	default:
+		break;
+	}
+}
+
+void extract_meta_out_info(struct q6audio_aio *audio,
+		struct audio_aio_buffer_node *buf_node, int dir)
+{
+	struct dec_meta_out *meta_data = buf_node->kvaddr;
+	uint32_t temp;
+
+	if (dir) { /* input buffer - Write */
+		if (audio->buf_cfg.meta_info_enable)
+			memcpy(&buf_node->meta_info.meta_in,
+			(char *)buf_node->kvaddr, sizeof(struct dec_meta_in));
+		else
+			memset(&buf_node->meta_info.meta_in,
+			0, sizeof(struct dec_meta_in));
+		pr_debug("%s[%pK]:i/p: msw_ts %d lsw_ts %d nflags 0x%8x\n",
+			__func__, audio,
+			buf_node->meta_info.meta_in.ntimestamp.highpart,
+			buf_node->meta_info.meta_in.ntimestamp.lowpart,
+			buf_node->meta_info.meta_in.nflags);
+	} else { /* output buffer - Read */
+		memcpy((char *)buf_node->kvaddr,
+			&buf_node->meta_info.meta_out,
+			sizeof(struct dec_meta_out));
+		meta_data->meta_out_dsp[0].nflags = 0x00000000;
+		temp = meta_data->meta_out_dsp[0].msw_ts;
+		meta_data->meta_out_dsp[0].msw_ts =
+				meta_data->meta_out_dsp[0].lsw_ts;
+		meta_data->meta_out_dsp[0].lsw_ts = temp;
+
+		pr_debug("%s[%pK]:o/p: msw_ts %d lsw_ts %d nflags 0x%8x, num_frames = %d\n",
+		__func__, audio,
+		((struct dec_meta_out *)buf_node->kvaddr)->
+			meta_out_dsp[0].msw_ts,
+		((struct dec_meta_out *)buf_node->kvaddr)->
+			meta_out_dsp[0].lsw_ts,
+		((struct dec_meta_out *)buf_node->kvaddr)->
+			meta_out_dsp[0].nflags,
+		((struct dec_meta_out *)buf_node->kvaddr)->num_of_frames);
+	}
+}
+
+/* Read buffer from DSP / Handle Ack from DSP */
+void audio_aio_async_read_ack(struct q6audio_aio *audio, uint32_t token,
+			uint32_t *payload)
+{
+	unsigned long flags;
+	union msm_audio_event_payload event_payload;
+	struct audio_aio_buffer_node *filled_buf;
+
+	pr_debug("%s\n", __func__);
+
+	/* No active flush in progress */
+	if (audio->rflush)
+		return;
+
+	/* Statistics of read */
+	atomic_add(payload[4], &audio->in_bytes);
+	atomic_add(payload[9], &audio->in_samples);
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
+	if (list_empty(&audio->in_queue)) {
+		spin_unlock_irqrestore(&audio->dsp_lock, flags);
+		pr_warn("%s unexpected ack from dsp\n", __func__);
+		return;
+	}
+	filled_buf = list_first_entry(&audio->in_queue,
+					struct audio_aio_buffer_node, list);
+
+	pr_debug("%s token: 0x[%x], filled_buf->token: 0x[%x]",
+				 __func__, token, filled_buf->token);
+	if (token == (filled_buf->token)) {
+		list_del(&filled_buf->list);
+		spin_unlock_irqrestore(&audio->dsp_lock, flags);
+		event_payload.aio_buf = filled_buf->buf;
+		/* Read done Buffer due to flush/normal condition
+		 * after EOS event, so append EOS buffer
+		 */
+		if (audio->eos_rsp == 0x1) {
+			event_payload.aio_buf.data_len =
+			insert_eos_buf(audio, filled_buf);
+			/* Reset flag back to indicate eos intimated */
+			audio->eos_rsp = 0;
+		} else {
+			filled_buf->meta_info.meta_out.num_of_frames
+							 = payload[9];
+			event_payload.aio_buf.data_len = payload[4]
+				 + payload[5] + sizeof(struct dec_meta_out);
+			pr_debug("%s[%pK]:nr of frames 0x%8x len=%d\n",
+				__func__, audio,
+				filled_buf->meta_info.meta_out.num_of_frames,
+				event_payload.aio_buf.data_len);
+			extract_meta_out_info(audio, filled_buf, 0);
+			audio->eos_rsp = 0;
+		}
+		pr_debug("%s, posting read done to the app here\n", __func__);
+		audio_aio_post_event(audio, AUDIO_EVENT_READ_DONE,
+					event_payload);
+		kfree(filled_buf);
+	} else {
+		pr_err("%s[%pK]:expected=%x ret=%x\n",
+			__func__, audio, filled_buf->token, token);
+		spin_unlock_irqrestore(&audio->dsp_lock, flags);
+	}
+}

+ 410 - 0
drivers/misc/qcom/qdsp6v2/qcelp_in.c

@@ -0,0 +1,410 @@
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/msm_audio_qcp.h>
+#include <linux/atomic.h>
+#include <linux/compat.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+/* Buffer with meta*/
+#define PCM_BUF_SIZE		(4096 + sizeof(struct meta_in))
+
+/* Maximum 10 frames in buffer with meta */
+#define FRAME_SIZE		(1 + ((35+sizeof(struct meta_out_dsp)) * 10))
+
+static long qcelp_in_ioctl_shared(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+	int cnt = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct msm_audio_qcelp_enc_config *enc_cfg;
+
+		enc_cfg = audio->enc_cfg;
+		pr_debug("%s:session id %d: default buf alloc[%d]\n", __func__,
+				audio->ac->session, audio->buf_alloc);
+		if (audio->enabled == 1) {
+			pr_info("%s:AUDIO_START already over\n", __func__);
+			rc = 0;
+			break;
+		}
+		rc = audio_in_buf_alloc(audio);
+		if (rc < 0) {
+			pr_err("%s:session id %d: buffer allocation failed\n",
+				__func__, audio->ac->session);
+			break;
+		}
+
+		/* reduced_rate_level, rate_modulation_cmd set to zero
+		 * currently not configurable from user space
+		 */
+		rc = q6asm_enc_cfg_blk_qcelp(audio->ac,
+			audio->buf_cfg.frames_per_buf,
+			enc_cfg->min_bit_rate,
+			enc_cfg->max_bit_rate, 0, 0);
+
+		if (rc < 0) {
+			pr_err("%s:session id %d: cmd qcelp media format block failed\n",
+					__func__, audio->ac->session);
+			break;
+		}
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			rc = q6asm_media_format_block_pcm(audio->ac,
+				audio->pcm_cfg.sample_rate,
+				audio->pcm_cfg.channel_count);
+
+			if (rc < 0) {
+				pr_err("%s:session id %d: media format block failed\n",
+					__func__, audio->ac->session);
+				break;
+			}
+		}
+		pr_debug("%s:session id %d: AUDIO_START enable[%d]\n", __func__,
+				audio->ac->session, audio->enabled);
+		rc = audio_in_enable(audio);
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s:session id %d: Audio Start procedure failed rc=%d\n",
+					__func__, audio->ac->session, rc);
+			break;
+		}
+		while (cnt++ < audio->str_cfg.buffer_count)
+			q6asm_read(audio->ac); /* Push buffer to DSP */
+		rc = 0;
+		pr_debug("%s:session id %d: AUDIO_START success enable[%d]\n",
+				__func__, audio->ac->session, audio->enabled);
+		break;
+	}
+	case AUDIO_STOP: {
+		pr_debug("%s:session id %d: AUDIO_STOP\n", __func__,
+				audio->ac->session);
+		rc = audio_in_disable(audio);
+		if (rc  < 0) {
+			pr_err("%s:session id %d: Audio Stop procedure failed rc=%d\n",
+				__func__, audio->ac->session,
+					rc);
+			break;
+		}
+		break;
+	}
+	case AUDIO_SET_QCELP_ENC_CONFIG: {
+		struct msm_audio_qcelp_enc_config *cfg;
+		struct msm_audio_qcelp_enc_config *enc_cfg;
+
+		enc_cfg = audio->enc_cfg;
+		cfg = (struct msm_audio_qcelp_enc_config *)arg;
+		if (cfg == NULL) {
+			pr_err("%s: NULL config pointer\n", __func__);
+			rc = -EINVAL;
+			break;
+		}
+		if (cfg->min_bit_rate > 4 ||
+			 cfg->min_bit_rate < 1) {
+			pr_err("%s:session id %d: invalid min bitrate\n",
+					__func__, audio->ac->session);
+			rc = -EINVAL;
+			break;
+		}
+		if (cfg->max_bit_rate > 4 ||
+			 cfg->max_bit_rate < 1) {
+			pr_err("%s:session id %d: invalid max bitrate\n",
+					__func__, audio->ac->session);
+			rc = -EINVAL;
+			break;
+		}
+		enc_cfg->cdma_rate = cfg->cdma_rate;
+		enc_cfg->min_bit_rate = cfg->min_bit_rate;
+		enc_cfg->max_bit_rate = cfg->max_bit_rate;
+		pr_debug("%s:session id %d: min_bit_rate= 0x%x max_bit_rate=0x%x\n",
+			__func__,
+			audio->ac->session, enc_cfg->min_bit_rate,
+			enc_cfg->max_bit_rate);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static long qcelp_in_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = qcelp_in_ioctl_shared(file, cmd, arg);
+		break;
+	}
+	case AUDIO_GET_QCELP_ENC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->enc_cfg,
+			sizeof(struct msm_audio_qcelp_enc_config))) {
+			pr_err(
+				"%s: copy_to_user for AUDIO_GET_QCELP_ENC_CONFIG failed",
+				__func__);
+			rc = -EFAULT;
+		}
+		break;
+	}
+	case AUDIO_SET_QCELP_ENC_CONFIG: {
+		struct msm_audio_qcelp_enc_config cfg;
+
+		if (copy_from_user(&cfg, (void *) arg,
+				sizeof(cfg))) {
+			pr_err(
+				"%s: copy_from_user for AUDIO_SET_QCELP_ENC_CONFIG failed",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = qcelp_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_QCELP_ENC_CONFIG failed. Rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_qcelp_enc_config32 {
+	u32 cdma_rate;
+	u32 min_bit_rate;
+	u32 max_bit_rate;
+};
+
+enum {
+	AUDIO_SET_QCELP_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+		0, struct msm_audio_qcelp_enc_config32),
+	AUDIO_GET_QCELP_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+		1, struct msm_audio_qcelp_enc_config32)
+};
+
+static long qcelp_in_compat_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START:
+	case AUDIO_STOP: {
+		rc = qcelp_in_ioctl_shared(file, cmd, arg);
+		break;
+	}
+	case AUDIO_GET_QCELP_ENC_CONFIG_32: {
+		struct msm_audio_qcelp_enc_config32 cfg_32;
+		struct msm_audio_qcelp_enc_config *enc_cfg;
+
+		memset(&cfg_32, 0, sizeof(cfg_32));
+
+		enc_cfg = (struct msm_audio_qcelp_enc_config *)audio->enc_cfg;
+		cfg_32.cdma_rate = enc_cfg->cdma_rate;
+		cfg_32.min_bit_rate = enc_cfg->min_bit_rate;
+		cfg_32.max_bit_rate = enc_cfg->max_bit_rate;
+		if (copy_to_user((void *)arg, &cfg_32,
+			sizeof(cfg_32))) {
+			pr_err("%s: copy_to_user for AUDIO_GET_QCELP_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+}
+		break;
+	}
+	case AUDIO_SET_QCELP_ENC_CONFIG_32: {
+		struct msm_audio_qcelp_enc_config32 cfg_32;
+		struct msm_audio_qcelp_enc_config cfg;
+
+		if (copy_from_user(&cfg_32, (void *) arg,
+				sizeof(cfg_32))) {
+			pr_err("%s: copy_from_user for AUDIO_SET_QCELP_ENC_CONFIG_32 failed\n",
+				__func__);
+			rc = -EFAULT;
+			break;
+		}
+		cfg.cdma_rate = cfg_32.cdma_rate;
+		cfg.min_bit_rate = cfg_32.min_bit_rate;
+		cfg.max_bit_rate = cfg_32.max_bit_rate;
+		cmd = AUDIO_SET_QCELP_ENC_CONFIG;
+		rc = qcelp_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+		if (rc)
+			pr_err("%s:AUDIO_SET_QCELP_ENC_CONFIG failed. rc= %d\n",
+				__func__, rc);
+		break;
+	}
+	default:
+		pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+#else
+#define qcelp_in_compat_ioctl NULL
+#endif
+
+static int qcelp_in_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_in *audio = NULL;
+	struct msm_audio_qcelp_enc_config *enc_cfg;
+	int rc = 0;
+
+	audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
+
+	if (audio == NULL)
+		return -ENOMEM;
+
+	/* Allocate memory for encoder config param */
+	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_qcelp_enc_config),
+				GFP_KERNEL);
+	if (audio->enc_cfg == NULL) {
+		kfree(audio);
+		return -ENOMEM;
+	}
+	enc_cfg = audio->enc_cfg;
+
+	mutex_init(&audio->lock);
+	mutex_init(&audio->read_lock);
+	mutex_init(&audio->write_lock);
+	spin_lock_init(&audio->dsp_lock);
+	init_waitqueue_head(&audio->read_wait);
+	init_waitqueue_head(&audio->write_wait);
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->str_cfg.buffer_size = FRAME_SIZE;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->min_frame_size = 35;
+	audio->max_frames_per_buf = 10;
+	audio->pcm_cfg.buffer_size = PCM_BUF_SIZE;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	enc_cfg->min_bit_rate = 4;
+	enc_cfg->max_bit_rate = 4;
+	audio->pcm_cfg.channel_count = 1;
+	audio->pcm_cfg.sample_rate = 8000;
+	audio->buf_cfg.meta_info_enable = 0x01;
+	audio->buf_cfg.frames_per_buf = 0x01;
+	audio->event_abort = 0;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb)q6asm_in_cb,
+				(void *)audio);
+
+	if (!audio->ac) {
+		pr_err("%s: Could not allocate memory for audio client\n",
+				__func__);
+		kfree(audio->enc_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open qcelp encoder in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) &&
+		(file->f_mode & FMODE_READ)) {
+		audio->feedback = NON_TUNNEL_MODE;
+		rc = q6asm_open_read_write(audio->ac, FORMAT_V13K,
+					FORMAT_LINEAR_PCM);
+		if (rc < 0) {
+			pr_err("%s:session id %d: NT mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		pr_info("%s:session id %d: NT mode encoder success\n", __func__,
+				audio->ac->session);
+	} else if (!(file->f_mode & FMODE_WRITE) &&
+				(file->f_mode & FMODE_READ)) {
+		audio->feedback = TUNNEL_MODE;
+		rc = q6asm_open_read(audio->ac, FORMAT_V13K);
+		if (rc < 0) {
+			pr_err("%s:session id %d: T mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		/* register for tx overflow (valid for tunnel mode only) */
+		rc = q6asm_reg_tx_overflow(audio->ac, 0x01);
+		if (rc < 0) {
+			pr_err("%s:session id %d: TX Overflow registration failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		pr_info("%s:session id %d: T mode encoder success\n", __func__,
+				audio->ac->session);
+	} else {
+		pr_err("%s:session id %d: Unexpected mode\n", __func__,
+				audio->ac->session);
+		rc = -EACCES;
+		goto fail;
+	}
+
+	audio->opened = 1;
+	audio->reset_event = false;
+	atomic_set(&audio->in_count, PCM_BUF_COUNT);
+	atomic_set(&audio->out_count, 0x00);
+	audio->enc_compat_ioctl = qcelp_in_compat_ioctl;
+	audio->enc_ioctl = qcelp_in_ioctl;
+	file->private_data = audio;
+
+	pr_info("%s:session id %d: success\n", __func__, audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->enc_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_in_fops = {
+	.owner		= THIS_MODULE,
+	.open		= qcelp_in_open,
+	.release	= audio_in_release,
+	.read		= audio_in_read,
+	.write		= audio_in_write,
+	.unlocked_ioctl	= audio_in_ioctl,
+	.compat_ioctl   = audio_in_compat_ioctl
+};
+
+struct miscdevice audio_qcelp_in_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_qcelp_in",
+	.fops	= &audio_in_fops,
+};
+
+static int __init qcelp_in_init(void)
+{
+	return misc_register(&audio_qcelp_in_misc);
+}
+
+device_initcall(qcelp_in_init);

+ 2 - 0
drivers/misc/qcom/qdsp6v2/ultrasound/Makefile

@@ -0,0 +1,2 @@
+ccflags-y := -I$(src)/..
+obj-$(CONFIG_MSM_ULTRASOUND) += usf.o usfcdev.o q6usm.o

+ 1467 - 0
drivers/misc/qcom/qdsp6v2/ultrasound/q6usm.c

@@ -0,0 +1,1467 @@
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/mutex.h>
+#include <linux/wait.h>
+#include <linux/msm_audio_ion.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/msm_audio.h>
+#include <sound/apr_audio-v2.h>
+#include <linux/qdsp6v2/apr_us.h>
+#include "q6usm.h"
+
+#define ADSP_MEMORY_MAP_SHMEM8_4K_POOL 3
+
+#define MEM_4K_OFFSET 4095
+#define MEM_4K_MASK 0xfffff000
+
+#define USM_SESSION_MAX 0x02 /* aDSP:USM limit */
+
+#define READDONE_IDX_STATUS     0
+
+#define WRITEDONE_IDX_STATUS    0
+
+/* Standard timeout in the asynchronous ops */
+#define Q6USM_TIMEOUT_JIFFIES	(1*HZ) /* 1 sec */
+
+static DEFINE_MUTEX(session_lock);
+
+static struct us_client *session[USM_SESSION_MAX];
+static int32_t q6usm_mmapcallback(struct apr_client_data *data, void *priv);
+static int32_t q6usm_callback(struct apr_client_data *data, void *priv);
+static void q6usm_add_hdr(struct us_client *usc, struct apr_hdr *hdr,
+			  uint32_t pkt_size, bool cmd_flg);
+
+struct usm_mmap {
+	atomic_t ref_cnt;
+	atomic_t cmd_state;
+	wait_queue_head_t cmd_wait;
+	void *apr;
+	int mem_handle;
+};
+
+static struct usm_mmap this_mmap;
+
+static void q6usm_add_mmaphdr(struct apr_hdr *hdr,
+			      uint32_t pkt_size, bool cmd_flg, u32 token)
+{
+	hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				       APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	hdr->src_port = 0;
+	hdr->dest_port = 0;
+	if (cmd_flg) {
+		hdr->token = token;
+		atomic_set(&this_mmap.cmd_state, 1);
+	}
+	hdr->pkt_size  = pkt_size;
+}
+
+static int q6usm_memory_map(phys_addr_t buf_add, int dir, uint32_t bufsz,
+		uint32_t bufcnt, uint32_t session, uint32_t *mem_handle)
+{
+	struct usm_cmd_memory_map_region mem_region_map;
+	int rc = 0;
+
+	if (this_mmap.apr == NULL) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	q6usm_add_mmaphdr(&mem_region_map.hdr,
+			  sizeof(struct usm_cmd_memory_map_region), true,
+			  ((session << 8) | dir));
+
+	mem_region_map.hdr.opcode = USM_CMD_SHARED_MEM_MAP_REGION;
+	mem_region_map.mempool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
+
+	mem_region_map.num_regions = 1;
+	mem_region_map.flags = 0;
+
+	mem_region_map.shm_addr_lsw = lower_32_bits(buf_add);
+	mem_region_map.shm_addr_msw =
+			msm_audio_populate_upper_32_bits(buf_add);
+	mem_region_map.mem_size_bytes = bufsz * bufcnt;
+
+	rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_region_map);
+	if (rc < 0) {
+		pr_err("%s: mem_map op[0x%x]rc[%d]\n",
+		       __func__, mem_region_map.hdr.opcode, rc);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+
+	rc = wait_event_timeout(this_mmap.cmd_wait,
+				(atomic_read(&this_mmap.cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout. waited for memory_map\n", __func__);
+	} else {
+		*mem_handle = this_mmap.mem_handle;
+		rc = 0;
+	}
+fail_cmd:
+	return rc;
+}
+
+int q6usm_memory_unmap(phys_addr_t buf_add, int dir, uint32_t session,
+			uint32_t mem_handle)
+{
+	struct usm_cmd_memory_unmap_region mem_unmap;
+	int rc = 0;
+
+	if (this_mmap.apr == NULL) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	q6usm_add_mmaphdr(&mem_unmap.hdr,
+			  sizeof(struct usm_cmd_memory_unmap_region), true,
+			  ((session << 8) | dir));
+	mem_unmap.hdr.opcode = USM_CMD_SHARED_MEM_UNMAP_REGION;
+	mem_unmap.mem_map_handle = mem_handle;
+
+	rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_unmap);
+	if (rc < 0) {
+		pr_err("%s: mem_unmap op[0x%x] rc[%d]\n",
+		       __func__, mem_unmap.hdr.opcode, rc);
+		goto fail_cmd;
+	}
+
+	rc = wait_event_timeout(this_mmap.cmd_wait,
+				(atomic_read(&this_mmap.cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout. waited for memory_unmap\n", __func__);
+	} else
+		rc = 0;
+fail_cmd:
+	return rc;
+}
+
+static int q6usm_session_alloc(struct us_client *usc)
+{
+	int ind = 0;
+
+	mutex_lock(&session_lock);
+	for (ind = 0; ind < USM_SESSION_MAX; ++ind) {
+		if (!session[ind]) {
+			session[ind] = usc;
+			mutex_unlock(&session_lock);
+			++ind; /* session id: 0 reserved */
+			pr_debug("%s: session[%d] was allocated\n",
+				  __func__, ind);
+			return ind;
+		}
+	}
+	mutex_unlock(&session_lock);
+	return -ENOMEM;
+}
+
+static void q6usm_session_free(struct us_client *usc)
+{
+	/* Session index was incremented during allocation */
+	uint16_t ind = (uint16_t)usc->session - 1;
+
+	pr_debug("%s: to free session[%d]\n", __func__, ind);
+	if (ind < USM_SESSION_MAX) {
+		mutex_lock(&session_lock);
+		session[ind] = NULL;
+		mutex_unlock(&session_lock);
+	}
+}
+
+static int q6usm_us_client_buf_free(unsigned int dir,
+			     struct us_client *usc)
+{
+	struct us_port_data *port;
+	int rc = 0;
+
+	if ((usc == NULL) ||
+	    ((dir != IN) && (dir != OUT)))
+		return -EINVAL;
+
+	mutex_lock(&usc->cmd_lock);
+	port = &usc->port[dir];
+	if (port == NULL) {
+		mutex_unlock(&usc->cmd_lock);
+		return -EINVAL;
+	}
+
+	if (port->data == NULL) {
+		mutex_unlock(&usc->cmd_lock);
+		return 0;
+	}
+
+	rc = q6usm_memory_unmap(port->phys, dir, usc->session,
+				*((uint32_t *)port->ext));
+	pr_debug("%s: data[%pK]phys[%llx][%pK]\n", __func__,
+		 (void *)port->data, (u64)port->phys, (void *)&port->phys);
+
+	msm_audio_ion_free(port->client, port->handle);
+
+	port->data = NULL;
+	port->phys = 0;
+	port->buf_size = 0;
+	port->buf_cnt = 0;
+	port->client = NULL;
+	port->handle = NULL;
+
+	mutex_unlock(&usc->cmd_lock);
+	return rc;
+}
+
+int q6usm_us_param_buf_free(unsigned int dir,
+			struct us_client *usc)
+{
+	struct us_port_data *port;
+	int rc = 0;
+
+	if ((usc == NULL) ||
+		((dir != IN) && (dir != OUT)))
+		return -EINVAL;
+
+	mutex_lock(&usc->cmd_lock);
+	port = &usc->port[dir];
+	if (port == NULL) {
+		mutex_unlock(&usc->cmd_lock);
+		return -EINVAL;
+	}
+
+	if (port->param_buf == NULL) {
+		mutex_unlock(&usc->cmd_lock);
+		return 0;
+	}
+
+	rc = q6usm_memory_unmap(port->param_phys, dir, usc->session,
+				*((uint32_t *)port->param_buf_mem_handle));
+	pr_debug("%s: data[%pK]phys[%llx][%pK]\n", __func__,
+		 (void *)port->param_buf, (u64)port->param_phys,
+		 (void *)&port->param_phys);
+
+	msm_audio_ion_free(port->param_client, port->param_handle);
+
+	port->param_buf = NULL;
+	port->param_phys = 0;
+	port->param_buf_size = 0;
+	port->param_client = NULL;
+	port->param_handle = NULL;
+
+	mutex_unlock(&usc->cmd_lock);
+	return rc;
+}
+
+void q6usm_us_client_free(struct us_client *usc)
+{
+	int loopcnt = 0;
+	struct us_port_data *port;
+	uint32_t *p_mem_handle = NULL;
+
+	if ((usc == NULL) ||
+	    !(usc->session))
+		return;
+
+	for (loopcnt = 0; loopcnt <= OUT; ++loopcnt) {
+		port = &usc->port[loopcnt];
+		if (port->data == NULL)
+			continue;
+		pr_debug("%s: loopcnt = %d\n", __func__, loopcnt);
+		q6usm_us_client_buf_free(loopcnt, usc);
+		q6usm_us_param_buf_free(loopcnt, usc);
+	}
+	q6usm_session_free(usc);
+	apr_deregister(usc->apr);
+
+	pr_debug("%s: APR De-Register\n", __func__);
+
+	if (atomic_read(&this_mmap.ref_cnt) <= 0) {
+		pr_err("%s: APR Common Port Already Closed\n", __func__);
+		goto done;
+	}
+
+	atomic_dec(&this_mmap.ref_cnt);
+	if (atomic_read(&this_mmap.ref_cnt) == 0) {
+		apr_deregister(this_mmap.apr);
+		pr_debug("%s: APR De-Register common port\n", __func__);
+	}
+
+done:
+	p_mem_handle = (uint32_t *)usc->port[IN].ext;
+	kfree(p_mem_handle);
+	kfree(usc);
+	pr_debug("%s:\n", __func__);
+}
+
+struct us_client *q6usm_us_client_alloc(
+	void (*cb)(uint32_t, uint32_t, uint32_t *, void *),
+	void *priv)
+{
+	struct us_client *usc;
+	uint32_t *p_mem_handle = NULL;
+	int n;
+	int lcnt = 0;
+
+	usc = kzalloc(sizeof(struct us_client), GFP_KERNEL);
+	if (usc == NULL)
+		return NULL;
+
+	p_mem_handle = kzalloc(sizeof(uint32_t) * 4, GFP_KERNEL);
+	if (p_mem_handle == NULL) {
+		kfree(usc);
+		return NULL;
+	}
+
+	n = q6usm_session_alloc(usc);
+	if (n <= 0)
+		goto fail_session;
+	usc->session = n;
+	usc->cb = cb;
+	usc->priv = priv;
+	usc->apr = apr_register("ADSP", "USM",
+				(apr_fn)q6usm_callback,
+				((usc->session) << 8 | 0x0001),
+				usc);
+
+	if (usc->apr == NULL) {
+		pr_err("%s: Registration with APR failed\n", __func__);
+		goto fail;
+	}
+	pr_debug("%s: Registering the common port with APR\n", __func__);
+	if (atomic_read(&this_mmap.ref_cnt) == 0) {
+		this_mmap.apr = apr_register("ADSP", "USM",
+					     (apr_fn)q6usm_mmapcallback,
+					     0x0FFFFFFFF, &this_mmap);
+		if (this_mmap.apr == NULL) {
+			pr_err("%s: USM port registration failed\n",
+			       __func__);
+			goto fail;
+		}
+	}
+
+	atomic_inc(&this_mmap.ref_cnt);
+	init_waitqueue_head(&usc->cmd_wait);
+	mutex_init(&usc->cmd_lock);
+	for (lcnt = 0; lcnt <= OUT; ++lcnt) {
+		mutex_init(&usc->port[lcnt].lock);
+		spin_lock_init(&usc->port[lcnt].dsp_lock);
+		usc->port[lcnt].ext = (void *)p_mem_handle++;
+		usc->port[lcnt].param_buf_mem_handle = (void *)p_mem_handle++;
+		pr_err("%s: usc->port[%d].ext=%pK;\n",
+		       __func__, lcnt, usc->port[lcnt].ext);
+	}
+	atomic_set(&usc->cmd_state, 0);
+
+	return usc;
+fail:
+	kfree(p_mem_handle);
+	q6usm_us_client_free(usc);
+	return NULL;
+fail_session:
+	kfree(p_mem_handle);
+	kfree(usc);
+	return NULL;
+}
+
+int q6usm_us_client_buf_alloc(unsigned int dir,
+			      struct us_client *usc,
+			      unsigned int bufsz,
+			      unsigned int bufcnt)
+{
+	int rc = 0;
+	struct us_port_data *port = NULL;
+	unsigned int size = bufsz*bufcnt;
+	size_t len;
+
+	if ((usc == NULL) ||
+	    ((dir != IN) && (dir != OUT)) || (size == 0) ||
+	    (usc->session <= 0 || usc->session > USM_SESSION_MAX)) {
+		pr_err("%s: wrong parameters: size=%d; bufcnt=%d\n",
+		       __func__, size, bufcnt);
+		return -EINVAL;
+	}
+
+	mutex_lock(&usc->cmd_lock);
+
+	port = &usc->port[dir];
+
+	/* The size to allocate should be multiple of 4K bytes */
+	size = PAGE_ALIGN(size);
+
+	rc = msm_audio_ion_alloc("ultrasound_client",
+		&port->client, &port->handle,
+		size, &port->phys,
+		&len, &port->data);
+
+	if (rc) {
+		pr_err("%s: US ION allocation failed, rc = %d\n",
+			__func__, rc);
+		mutex_unlock(&usc->cmd_lock);
+		return -ENOMEM;
+	}
+
+	port->buf_cnt = bufcnt;
+	port->buf_size = bufsz;
+	pr_debug("%s: data[%pK]; phys[%llx]; [%pK]\n", __func__,
+		 (void *)port->data,
+		 (u64)port->phys,
+		 (void *)&port->phys);
+
+	rc = q6usm_memory_map(port->phys, dir, size, 1, usc->session,
+				(uint32_t *)port->ext);
+	if (rc < 0) {
+		pr_err("%s: CMD Memory_map failed\n", __func__);
+		mutex_unlock(&usc->cmd_lock);
+		q6usm_us_client_buf_free(dir, usc);
+		q6usm_us_param_buf_free(dir, usc);
+	} else {
+		mutex_unlock(&usc->cmd_lock);
+		rc = 0;
+	}
+
+	return rc;
+}
+
+int q6usm_us_param_buf_alloc(unsigned int dir,
+			struct us_client *usc,
+			unsigned int bufsz)
+{
+	int rc = 0;
+	struct us_port_data *port = NULL;
+	unsigned int size = bufsz;
+	size_t len;
+
+	if ((usc == NULL) ||
+		((dir != IN) && (dir != OUT)) ||
+		(usc->session <= 0 || usc->session > USM_SESSION_MAX)) {
+		pr_err("%s: wrong parameters: direction=%d, bufsz=%d\n",
+			__func__, dir, bufsz);
+		return -EINVAL;
+	}
+
+	mutex_lock(&usc->cmd_lock);
+
+	port = &usc->port[dir];
+
+	if (bufsz == 0) {
+		pr_debug("%s: bufsz=0, get/set param commands are forbidden\n",
+			__func__);
+		port->param_buf = NULL;
+		mutex_unlock(&usc->cmd_lock);
+		return rc;
+	}
+
+	/* The size to allocate should be multiple of 4K bytes */
+	size = PAGE_ALIGN(size);
+
+	rc = msm_audio_ion_alloc("ultrasound_client",
+		&port->param_client, &port->param_handle,
+		size, &port->param_phys,
+		&len, &port->param_buf);
+
+	if (rc) {
+		pr_err("%s: US ION allocation failed, rc = %d\n",
+			__func__, rc);
+		mutex_unlock(&usc->cmd_lock);
+		return -ENOMEM;
+	}
+
+	port->param_buf_size = bufsz;
+	pr_debug("%s: param_buf[%pK]; param_phys[%llx]; [%pK]\n", __func__,
+		 (void *)port->param_buf,
+		 (u64)port->param_phys,
+		 (void *)&port->param_phys);
+
+	rc = q6usm_memory_map(port->param_phys, (IN | OUT), size, 1,
+			usc->session, (uint32_t *)port->param_buf_mem_handle);
+	if (rc < 0) {
+		pr_err("%s: CMD Memory_map failed\n", __func__);
+		mutex_unlock(&usc->cmd_lock);
+		q6usm_us_client_buf_free(dir, usc);
+		q6usm_us_param_buf_free(dir, usc);
+	} else {
+		mutex_unlock(&usc->cmd_lock);
+		rc = 0;
+	}
+
+	return rc;
+}
+
+static int32_t q6usm_mmapcallback(struct apr_client_data *data, void *priv)
+{
+	uint32_t token;
+	uint32_t *payload = data->payload;
+
+	pr_debug("%s: ptr0[0x%x]; ptr1[0x%x]; opcode[0x%x]\n",
+		 __func__, payload[0], payload[1], data->opcode);
+	pr_debug("%s: token[0x%x]; payload_size[%d]; src[%d]; dest[%d];\n",
+		 __func__, data->token, data->payload_size,
+		 data->src_port, data->dest_port);
+
+	if (data->opcode == APR_BASIC_RSP_RESULT) {
+		/* status field check */
+		if (payload[1]) {
+			pr_err("%s: wrong response[%d] on cmd [%d]\n",
+			       __func__, payload[1], payload[0]);
+		} else {
+			token = data->token;
+			switch (payload[0]) {
+			case USM_CMD_SHARED_MEM_UNMAP_REGION:
+				if (atomic_read(&this_mmap.cmd_state)) {
+					atomic_set(&this_mmap.cmd_state, 0);
+					wake_up(&this_mmap.cmd_wait);
+				}
+				/* fallthrough */
+			case USM_CMD_SHARED_MEM_MAP_REGION:
+				/* For MEM_MAP, additional answer is waited, */
+				/* therfore, no wake-up here */
+				pr_debug("%s: cmd[0x%x]; result[0x%x]\n",
+					 __func__, payload[0], payload[1]);
+				break;
+			default:
+				pr_debug("%s: wrong command[0x%x]\n",
+					 __func__, payload[0]);
+				break;
+			}
+		}
+	} else {
+		if (data->opcode == USM_CMDRSP_SHARED_MEM_MAP_REGION) {
+			this_mmap.mem_handle = payload[0];
+			pr_debug("%s: memory map handle = 0x%x",
+				__func__, payload[0]);
+			if (atomic_read(&this_mmap.cmd_state)) {
+				atomic_set(&this_mmap.cmd_state, 0);
+				wake_up(&this_mmap.cmd_wait);
+			}
+		}
+	}
+	return 0;
+}
+
+
+static int32_t q6usm_callback(struct apr_client_data *data, void *priv)
+{
+	struct us_client *usc = (struct us_client *)priv;
+	unsigned long dsp_flags;
+	uint32_t *payload = data->payload;
+	uint32_t token = data->token;
+	uint32_t opcode = Q6USM_EVENT_UNDEF;
+
+	if (usc == NULL) {
+		pr_err("%s: client info is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (data->opcode == APR_BASIC_RSP_RESULT) {
+		/* status field check */
+		if (payload[1]) {
+			pr_err("%s: wrong response[%d] on cmd [%d]\n",
+			       __func__, payload[1], payload[0]);
+			if (usc->cb)
+				usc->cb(data->opcode, token,
+					(uint32_t *)data->payload, usc->priv);
+		} else {
+			switch (payload[0]) {
+			case USM_SESSION_CMD_RUN:
+			case USM_STREAM_CMD_CLOSE:
+				if (token != usc->session) {
+					pr_err("%s: wrong token[%d]",
+					       __func__, token);
+					break;
+				}
+			case USM_STREAM_CMD_OPEN_READ:
+			case USM_STREAM_CMD_OPEN_WRITE:
+			case USM_STREAM_CMD_SET_ENC_PARAM:
+			case USM_DATA_CMD_MEDIA_FORMAT_UPDATE:
+			case USM_SESSION_CMD_SIGNAL_DETECT_MODE:
+			case USM_STREAM_CMD_SET_PARAM:
+			case USM_STREAM_CMD_GET_PARAM:
+				if (atomic_read(&usc->cmd_state)) {
+					atomic_set(&usc->cmd_state, 0);
+					wake_up(&usc->cmd_wait);
+				}
+				if (usc->cb)
+					usc->cb(data->opcode, token,
+						(uint32_t *)data->payload,
+						usc->priv);
+				break;
+			default:
+				break;
+			}
+		}
+		return 0;
+	}
+
+	switch (data->opcode) {
+	case RESET_EVENTS: {
+		pr_err("%s: Reset event is received: %d %d\n",
+				__func__,
+				data->reset_event,
+				data->reset_proc);
+
+		opcode = RESET_EVENTS;
+
+		apr_reset(this_mmap.apr);
+		this_mmap.apr = NULL;
+
+		apr_reset(usc->apr);
+		usc->apr = NULL;
+
+		break;
+	}
+
+
+	case USM_DATA_EVENT_READ_DONE: {
+		struct us_port_data *port = &usc->port[OUT];
+
+		opcode = Q6USM_EVENT_READ_DONE;
+		spin_lock_irqsave(&port->dsp_lock, dsp_flags);
+		if (payload[READDONE_IDX_STATUS]) {
+			pr_err("%s: wrong READDONE[%d]; token[%d]\n",
+			       __func__,
+			       payload[READDONE_IDX_STATUS],
+			       token);
+			token = USM_WRONG_TOKEN;
+			spin_unlock_irqrestore(&port->dsp_lock,
+					       dsp_flags);
+			break;
+		}
+
+		if (port->expected_token != token) {
+			u32 cpu_buf = port->cpu_buf;
+
+			pr_err("%s: expected[%d] != token[%d]\n",
+				__func__, port->expected_token, token);
+			pr_debug("%s: dsp_buf=%d; cpu_buf=%d;\n",
+				__func__,   port->dsp_buf, cpu_buf);
+
+			token = USM_WRONG_TOKEN;
+			/* To prevent data handle continiue */
+			port->expected_token = USM_WRONG_TOKEN;
+			spin_unlock_irqrestore(&port->dsp_lock,
+					       dsp_flags);
+			break;
+		} /* port->expected_token != data->token */
+
+		port->expected_token = token + 1;
+		if (port->expected_token == port->buf_cnt)
+			port->expected_token = 0;
+
+		/* gap support */
+		if (port->expected_token != port->cpu_buf) {
+			port->dsp_buf = port->expected_token;
+			token = port->dsp_buf; /* for callback */
+		} else
+			port->dsp_buf = token;
+
+		spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
+		break;
+	} /* case USM_DATA_EVENT_READ_DONE */
+
+	case USM_DATA_EVENT_WRITE_DONE: {
+		struct us_port_data *port = &usc->port[IN];
+
+		opcode = Q6USM_EVENT_WRITE_DONE;
+		if (payload[WRITEDONE_IDX_STATUS]) {
+			pr_err("%s: wrong WRITEDONE_IDX_STATUS[%d]\n",
+			       __func__,
+			       payload[WRITEDONE_IDX_STATUS]);
+			break;
+		}
+
+		spin_lock_irqsave(&port->dsp_lock, dsp_flags);
+		port->dsp_buf = token + 1;
+		if (port->dsp_buf == port->buf_cnt)
+			port->dsp_buf = 0;
+		spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
+
+		break;
+	} /* case USM_DATA_EVENT_WRITE_DONE */
+
+	case USM_SESSION_EVENT_SIGNAL_DETECT_RESULT: {
+		pr_debug("%s: US detect result: result=%d",
+			 __func__,
+			 payload[0]);
+		opcode = Q6USM_EVENT_SIGNAL_DETECT_RESULT;
+
+		break;
+	} /* case USM_SESSION_EVENT_SIGNAL_DETECT_RESULT */
+
+	default:
+		return 0;
+
+	} /* switch */
+
+	if (usc->cb)
+		usc->cb(opcode, token,
+			data->payload, usc->priv);
+
+	return 0;
+}
+
+uint32_t q6usm_get_virtual_address(int dir,
+				   struct us_client *usc,
+				   struct vm_area_struct *vms)
+{
+	uint32_t ret = 0xffffffff;
+
+	if (vms && (usc != NULL) && ((dir == IN) || (dir == OUT))) {
+		struct us_port_data *port = &usc->port[dir];
+		int size = PAGE_ALIGN(port->buf_size * port->buf_cnt);
+		struct audio_buffer ab;
+
+		ab.phys = port->phys;
+		ab.data = port->data;
+		ab.used = 1;
+		ab.size = size;
+		ab.actual_size = size;
+		ab.handle = port->handle;
+		ab.client = port->client;
+
+		ret = msm_audio_ion_mmap(&ab, vms);
+
+	}
+	return ret;
+}
+
+static void q6usm_add_hdr(struct us_client *usc, struct apr_hdr *hdr,
+			  uint32_t pkt_size, bool cmd_flg)
+{
+	mutex_lock(&usc->cmd_lock);
+	hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				       APR_HDR_LEN(sizeof(struct apr_hdr)),
+				       APR_PKT_VER);
+	hdr->src_svc = ((struct apr_svc *)usc->apr)->id;
+	hdr->src_domain = APR_DOMAIN_APPS;
+	hdr->dest_svc = APR_SVC_USM;
+	hdr->dest_domain = APR_DOMAIN_ADSP;
+	hdr->src_port = (usc->session << 8) | 0x0001;
+	hdr->dest_port = (usc->session << 8) | 0x0001;
+	if (cmd_flg) {
+		hdr->token = usc->session;
+		atomic_set(&usc->cmd_state, 1);
+	}
+	hdr->pkt_size  = pkt_size;
+	mutex_unlock(&usc->cmd_lock);
+}
+
+static uint32_t q6usm_ext2int_format(uint32_t ext_format)
+{
+	uint32_t int_format = INVALID_FORMAT;
+
+	switch (ext_format) {
+	case FORMAT_USPS_EPOS:
+		int_format = US_POINT_EPOS_FORMAT_V2;
+		break;
+	case FORMAT_USRAW:
+		int_format = US_RAW_FORMAT_V2;
+		break;
+	case FORMAT_USPROX:
+		int_format = US_PROX_FORMAT_V4;
+		break;
+	case FORMAT_USGES_SYNC:
+		int_format = US_GES_SYNC_FORMAT;
+		break;
+	case FORMAT_USRAW_SYNC:
+		int_format = US_RAW_SYNC_FORMAT;
+		break;
+	default:
+		pr_err("%s: Invalid format[%d]\n", __func__, ext_format);
+		break;
+	}
+
+	return int_format;
+}
+
+int q6usm_open_read(struct us_client *usc,
+		    uint32_t format)
+{
+	uint32_t int_format = INVALID_FORMAT;
+	int rc = 0x00;
+	struct usm_stream_cmd_open_read open;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: client or its apr is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: session[%d]", __func__, usc->session);
+
+	q6usm_add_hdr(usc, &open.hdr, sizeof(open), true);
+	open.hdr.opcode = USM_STREAM_CMD_OPEN_READ;
+	open.src_endpoint = 0; /* AFE */
+	open.pre_proc_top = 0; /* No preprocessing required */
+
+	int_format = q6usm_ext2int_format(format);
+	if (int_format == INVALID_FORMAT)
+		return -EINVAL;
+
+	open.uMode = STREAM_PRIORITY_NORMAL;
+	open.format = int_format;
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) &open);
+	if (rc < 0) {
+		pr_err("%s: open failed op[0x%x]rc[%d]\n",
+		       __func__, open.hdr.opcode, rc);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout, waited for OPEN_READ rc[%d]\n",
+		       __func__, rc);
+		goto fail_cmd;
+	} else
+		rc = 0;
+fail_cmd:
+	return rc;
+}
+
+
+int q6usm_enc_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg)
+{
+	uint32_t int_format = INVALID_FORMAT;
+	struct usm_stream_cmd_encdec_cfg_blk  enc_cfg_obj;
+	struct usm_stream_cmd_encdec_cfg_blk  *enc_cfg = &enc_cfg_obj;
+	int rc = 0;
+	uint32_t total_cfg_size =
+		sizeof(struct usm_stream_cmd_encdec_cfg_blk);
+	uint32_t round_params_size = 0;
+	uint8_t  is_allocated = 0;
+
+
+	if ((usc == NULL) || (us_cfg == NULL)) {
+		pr_err("%s: wrong input", __func__);
+		return -EINVAL;
+	}
+
+	int_format = q6usm_ext2int_format(us_cfg->format_id);
+	if (int_format == INVALID_FORMAT) {
+		pr_err("%s: wrong input format[%d]",
+		       __func__, us_cfg->format_id);
+		return -EINVAL;
+	}
+
+	/* Transparent configuration data is after enc_cfg */
+	/* Integer number of u32s is required */
+	round_params_size = ((us_cfg->params_size + 3)/4) * 4;
+	if (round_params_size > USM_MAX_CFG_DATA_SIZE) {
+		/* Dynamic allocated encdec_cfg_blk is required */
+		/* static part use */
+		round_params_size -= USM_MAX_CFG_DATA_SIZE;
+		total_cfg_size += round_params_size;
+		enc_cfg = kzalloc(total_cfg_size, GFP_KERNEL);
+		if (enc_cfg == NULL) {
+			pr_err("%s: enc_cfg[%d] allocation failed\n",
+			       __func__, total_cfg_size);
+			return -ENOMEM;
+		}
+		is_allocated = 1;
+	} else
+		round_params_size = 0;
+
+	q6usm_add_hdr(usc, &enc_cfg->hdr, total_cfg_size, true);
+
+	enc_cfg->hdr.opcode = USM_STREAM_CMD_SET_ENC_PARAM;
+	enc_cfg->param_id = USM_PARAM_ID_ENCDEC_ENC_CFG_BLK;
+	enc_cfg->param_size = sizeof(struct usm_encode_cfg_blk)+
+				round_params_size;
+	enc_cfg->enc_blk.frames_per_buf = 1;
+	enc_cfg->enc_blk.format_id = int_format;
+	enc_cfg->enc_blk.cfg_size = sizeof(struct usm_cfg_common)+
+				    USM_MAX_CFG_DATA_SIZE +
+				    round_params_size;
+	memcpy(&(enc_cfg->enc_blk.cfg_common), &(us_cfg->cfg_common),
+	       sizeof(struct usm_cfg_common));
+
+	/* Transparent data copy */
+	memcpy(enc_cfg->enc_blk.transp_data, us_cfg->params,
+	       us_cfg->params_size);
+	pr_debug("%s: cfg_size[%d], params_size[%d]\n",
+		__func__,
+		enc_cfg->enc_blk.cfg_size,
+		us_cfg->params_size);
+	pr_debug("%s: params[%d,%d,%d,%d, %d,%d,%d,%d]\n",
+		__func__,
+		enc_cfg->enc_blk.transp_data[0],
+		enc_cfg->enc_blk.transp_data[1],
+		enc_cfg->enc_blk.transp_data[2],
+		enc_cfg->enc_blk.transp_data[3],
+		enc_cfg->enc_blk.transp_data[4],
+		enc_cfg->enc_blk.transp_data[5],
+		enc_cfg->enc_blk.transp_data[6],
+		enc_cfg->enc_blk.transp_data[7]
+	       );
+	pr_debug("%s: srate:%d, ch=%d, bps= %d;\n",
+		__func__, enc_cfg->enc_blk.cfg_common.sample_rate,
+		enc_cfg->enc_blk.cfg_common.ch_cfg,
+		enc_cfg->enc_blk.cfg_common.bits_per_sample);
+	pr_debug("dmap:[0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x]; dev_id=0x%x\n",
+		enc_cfg->enc_blk.cfg_common.data_map[0],
+		enc_cfg->enc_blk.cfg_common.data_map[1],
+		enc_cfg->enc_blk.cfg_common.data_map[2],
+		enc_cfg->enc_blk.cfg_common.data_map[3],
+		enc_cfg->enc_blk.cfg_common.data_map[4],
+		enc_cfg->enc_blk.cfg_common.data_map[5],
+		enc_cfg->enc_blk.cfg_common.data_map[6],
+		enc_cfg->enc_blk.cfg_common.data_map[7],
+		enc_cfg->enc_blk.cfg_common.dev_id);
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) enc_cfg);
+	if (rc < 0) {
+		pr_err("%s:Comamnd open failed\n", __func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout opcode[0x%x]\n",
+		       __func__, enc_cfg->hdr.opcode);
+	} else
+		rc = 0;
+
+fail_cmd:
+	if (is_allocated == 1)
+		kfree(enc_cfg);
+
+	return rc;
+}
+
+int q6usm_dec_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg)
+{
+
+	uint32_t int_format = INVALID_FORMAT;
+	struct usm_stream_media_format_update dec_cfg_obj;
+	struct usm_stream_media_format_update *dec_cfg = &dec_cfg_obj;
+
+	int rc = 0;
+	uint32_t total_cfg_size = sizeof(struct usm_stream_media_format_update);
+	uint32_t round_params_size = 0;
+	uint8_t  is_allocated = 0;
+
+
+	if ((usc == NULL) || (us_cfg == NULL)) {
+		pr_err("%s: wrong input", __func__);
+		return -EINVAL;
+	}
+
+	int_format = q6usm_ext2int_format(us_cfg->format_id);
+	if (int_format == INVALID_FORMAT) {
+		pr_err("%s: wrong input format[%d]",
+		       __func__, us_cfg->format_id);
+		return -EINVAL;
+	}
+
+	/* Transparent configuration data is after enc_cfg */
+	/* Integer number of u32s is required */
+	round_params_size = ((us_cfg->params_size + 3)/4) * 4;
+	if (round_params_size > USM_MAX_CFG_DATA_SIZE) {
+		/* Dynamic allocated encdec_cfg_blk is required */
+		/* static part use */
+		round_params_size -= USM_MAX_CFG_DATA_SIZE;
+		total_cfg_size += round_params_size;
+		dec_cfg = kzalloc(total_cfg_size, GFP_KERNEL);
+		if (dec_cfg == NULL) {
+			pr_err("%s:dec_cfg[%d] allocation failed\n",
+			       __func__, total_cfg_size);
+			return -ENOMEM;
+		}
+		is_allocated = 1;
+	} else { /* static transp_data is enough */
+		round_params_size = 0;
+	}
+
+	q6usm_add_hdr(usc, &dec_cfg->hdr, total_cfg_size, true);
+
+	dec_cfg->hdr.opcode = USM_DATA_CMD_MEDIA_FORMAT_UPDATE;
+	dec_cfg->format_id = int_format;
+	dec_cfg->cfg_size = sizeof(struct usm_cfg_common) +
+			    USM_MAX_CFG_DATA_SIZE +
+			    round_params_size;
+	memcpy(&(dec_cfg->cfg_common), &(us_cfg->cfg_common),
+	       sizeof(struct usm_cfg_common));
+	/* Transparent data copy */
+	memcpy(dec_cfg->transp_data, us_cfg->params, us_cfg->params_size);
+	pr_debug("%s: cfg_size[%d], params_size[%d]; parambytes[%d,%d,%d,%d]\n",
+		__func__,
+		dec_cfg->cfg_size,
+		us_cfg->params_size,
+		dec_cfg->transp_data[0],
+		dec_cfg->transp_data[1],
+		dec_cfg->transp_data[2],
+		dec_cfg->transp_data[3]
+	       );
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) dec_cfg);
+	if (rc < 0) {
+		pr_err("%s:Comamnd open failed\n", __func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout opcode[0x%x]\n",
+		       __func__, dec_cfg->hdr.opcode);
+	} else
+		rc = 0;
+
+fail_cmd:
+	if (is_allocated == 1)
+		kfree(dec_cfg);
+
+	return rc;
+}
+
+int q6usm_open_write(struct us_client *usc,
+		     uint32_t format)
+{
+	int rc = 0;
+	uint32_t int_format = INVALID_FORMAT;
+	struct usm_stream_cmd_open_write open;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: session[%d]", __func__, usc->session);
+
+	q6usm_add_hdr(usc, &open.hdr, sizeof(open), true);
+	open.hdr.opcode = USM_STREAM_CMD_OPEN_WRITE;
+
+	int_format = q6usm_ext2int_format(format);
+	if (int_format == INVALID_FORMAT) {
+		pr_err("%s: wrong format[%d]", __func__, format);
+		return -EINVAL;
+	}
+
+	open.format = int_format;
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) &open);
+	if (rc < 0) {
+		pr_err("%s:open failed op[0x%x]rc[%d]\n",
+		       __func__, open.hdr.opcode, rc);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s:timeout. waited for OPEN_WRITR rc[%d]\n",
+		       __func__, rc);
+		goto fail_cmd;
+	} else
+		rc = 0;
+
+fail_cmd:
+	return rc;
+}
+
+int q6usm_run(struct us_client *usc, uint32_t flags,
+	      uint32_t msw_ts, uint32_t lsw_ts)
+{
+	struct usm_stream_cmd_run run;
+	int rc = 0;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	q6usm_add_hdr(usc, &run.hdr, sizeof(run), true);
+
+	run.hdr.opcode = USM_SESSION_CMD_RUN;
+	run.flags    = flags;
+	run.msw_ts   = msw_ts;
+	run.lsw_ts   = lsw_ts;
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) &run);
+	if (rc < 0) {
+		pr_err("%s: Commmand run failed[%d]\n", __func__, rc);
+		goto fail_cmd;
+	}
+
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout. waited for run success rc[%d]\n",
+		       __func__, rc);
+	} else
+		rc = 0;
+
+fail_cmd:
+	return rc;
+}
+
+
+
+int q6usm_read(struct us_client *usc, uint32_t read_ind)
+{
+	struct usm_stream_cmd_read read;
+	struct us_port_data *port = NULL;
+	int rc = 0;
+	u32 read_counter = 0;
+	u32 loop_ind = 0;
+	u64 buf_addr = 0;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	port = &usc->port[OUT];
+
+	if (read_ind > port->buf_cnt) {
+		pr_err("%s: wrong read_ind[%d]\n",
+		       __func__, read_ind);
+		return -EINVAL;
+	}
+	if (read_ind == port->cpu_buf) {
+		pr_err("%s: no free region\n", __func__);
+		return 0;
+	}
+
+	if (read_ind > port->cpu_buf) { /* 1 range */
+		read_counter = read_ind - port->cpu_buf;
+	} else { /* 2 ranges */
+		read_counter = (port->buf_cnt - port->cpu_buf) + read_ind;
+	}
+
+	q6usm_add_hdr(usc, &read.hdr, sizeof(read), false);
+
+	read.hdr.opcode = USM_DATA_CMD_READ;
+	read.buf_size = port->buf_size;
+	buf_addr = (u64)(port->phys) + port->buf_size * (port->cpu_buf);
+	read.buf_addr_lsw = lower_32_bits(buf_addr);
+	read.buf_addr_msw = msm_audio_populate_upper_32_bits(buf_addr);
+	read.mem_map_handle = *((uint32_t *)(port->ext));
+
+	for (loop_ind = 0; loop_ind < read_counter; ++loop_ind) {
+		u32 temp_cpu_buf = port->cpu_buf;
+
+		buf_addr = (u64)(port->phys) +
+				port->buf_size * (port->cpu_buf);
+		read.buf_addr_lsw = lower_32_bits(buf_addr);
+		read.buf_addr_msw = msm_audio_populate_upper_32_bits(buf_addr);
+		read.seq_id = port->cpu_buf;
+		read.hdr.token = port->cpu_buf;
+		read.counter = 1;
+
+		++(port->cpu_buf);
+		if (port->cpu_buf == port->buf_cnt)
+			port->cpu_buf = 0;
+
+		rc = apr_send_pkt(usc->apr, (uint32_t *) &read);
+
+		if (rc < 0) {
+			port->cpu_buf = temp_cpu_buf;
+
+			pr_err("%s:read op[0x%x]rc[%d]\n",
+			       __func__, read.hdr.opcode, rc);
+			break;
+		}
+
+		rc = 0;
+	} /* bufs loop */
+
+	return rc;
+}
+
+int q6usm_write(struct us_client *usc, uint32_t write_ind)
+{
+	int rc = 0;
+	struct usm_stream_cmd_write cmd_write;
+	struct us_port_data *port = NULL;
+	u32 current_dsp_buf = 0;
+	u64 buf_addr = 0;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	port = &usc->port[IN];
+
+	current_dsp_buf = port->dsp_buf;
+	/* free region, caused by new dsp_buf report from DSP, */
+	/* can be only extended */
+	if (port->cpu_buf >= current_dsp_buf) {
+		/* 2 -part free region, including empty buffer */
+		if ((write_ind <= port->cpu_buf)  &&
+		    (write_ind > current_dsp_buf)) {
+			pr_err("%s: wrong w_ind[%d]; d_buf=%d; c_buf=%d\n",
+			       __func__, write_ind,
+			       current_dsp_buf, port->cpu_buf);
+			return -EINVAL;
+		}
+	} else {
+		/* 1 -part free region */
+		if ((write_ind <= port->cpu_buf)  ||
+		    (write_ind > current_dsp_buf)) {
+			pr_err("%s: wrong w_ind[%d]; d_buf=%d; c_buf=%d\n",
+			       __func__, write_ind,
+			       current_dsp_buf, port->cpu_buf);
+			return -EINVAL;
+		}
+	}
+
+	q6usm_add_hdr(usc, &cmd_write.hdr, sizeof(cmd_write), false);
+
+	cmd_write.hdr.opcode = USM_DATA_CMD_WRITE;
+	cmd_write.buf_size = port->buf_size;
+	buf_addr = (u64)(port->phys) + port->buf_size * (port->cpu_buf);
+	cmd_write.buf_addr_lsw = lower_32_bits(buf_addr);
+	cmd_write.buf_addr_msw = msm_audio_populate_upper_32_bits(buf_addr);
+	cmd_write.mem_map_handle = *((uint32_t *)(port->ext));
+	cmd_write.res0 = 0;
+	cmd_write.res1 = 0;
+	cmd_write.res2 = 0;
+
+	while (port->cpu_buf != write_ind) {
+		u32 temp_cpu_buf = port->cpu_buf;
+
+		buf_addr = (u64)(port->phys) +
+				port->buf_size * (port->cpu_buf);
+		cmd_write.buf_addr_lsw = lower_32_bits(buf_addr);
+		cmd_write.buf_addr_msw =
+				msm_audio_populate_upper_32_bits(buf_addr);
+		cmd_write.seq_id = port->cpu_buf;
+		cmd_write.hdr.token = port->cpu_buf;
+
+		++(port->cpu_buf);
+		if (port->cpu_buf == port->buf_cnt)
+			port->cpu_buf = 0;
+
+		rc = apr_send_pkt(usc->apr, (uint32_t *) &cmd_write);
+
+		if (rc < 0) {
+			port->cpu_buf = temp_cpu_buf;
+			pr_err("%s:write op[0x%x];rc[%d];cpu_buf[%d]\n",
+			       __func__, cmd_write.hdr.opcode,
+			       rc, port->cpu_buf);
+			break;
+		}
+
+		rc = 0;
+	}
+
+	return rc;
+}
+
+bool q6usm_is_write_buf_full(struct us_client *usc, uint32_t *free_region)
+{
+	struct us_port_data *port = NULL;
+	u32 cpu_buf = 0;
+
+	if ((usc == NULL) || !free_region) {
+		pr_err("%s: input data wrong\n", __func__);
+		return false;
+	}
+	port = &usc->port[IN];
+	cpu_buf = port->cpu_buf + 1;
+	if (cpu_buf == port->buf_cnt)
+		cpu_buf = 0;
+
+	*free_region = port->dsp_buf;
+
+	return cpu_buf == *free_region;
+}
+
+int q6usm_cmd(struct us_client *usc, int cmd)
+{
+	struct apr_hdr hdr;
+	int rc = 0;
+	atomic_t *state;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	q6usm_add_hdr(usc, &hdr, sizeof(hdr), true);
+	switch (cmd) {
+	case CMD_CLOSE:
+		hdr.opcode = USM_STREAM_CMD_CLOSE;
+		state = &usc->cmd_state;
+		break;
+
+	default:
+		pr_err("%s:Invalid format[%d]\n", __func__, cmd);
+		goto fail_cmd;
+	}
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) &hdr);
+	if (rc < 0) {
+		pr_err("%s: Command 0x%x failed\n", __func__, hdr.opcode);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(usc->cmd_wait, (atomic_read(state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s:timeout. waited for response opcode[0x%x]\n",
+		       __func__, hdr.opcode);
+	} else
+		rc = 0;
+fail_cmd:
+	return rc;
+}
+
+int q6usm_set_us_detection(struct us_client *usc,
+			   struct usm_session_cmd_detect_info *detect_info,
+			   uint16_t detect_info_size)
+{
+	int rc = 0;
+
+	if ((usc == NULL) ||
+	    (detect_info_size == 0) ||
+	    (detect_info == NULL)) {
+		pr_err("%s: wrong input: usc=0x%pK, inf_size=%d; info=0x%pK",
+		       __func__,
+		       usc,
+		       detect_info_size,
+		       detect_info);
+		return -EINVAL;
+	}
+
+	q6usm_add_hdr(usc, &detect_info->hdr, detect_info_size, true);
+
+	detect_info->hdr.opcode = USM_SESSION_CMD_SIGNAL_DETECT_MODE;
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *)detect_info);
+	if (rc < 0) {
+		pr_err("%s:Comamnd signal detect failed\n", __func__);
+		return -EINVAL;
+	}
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: CMD_SIGNAL_DETECT_MODE: timeout=%d\n",
+		       __func__, Q6USM_TIMEOUT_JIFFIES);
+	} else
+		rc = 0;
+
+	return rc;
+}
+
+int q6usm_set_us_stream_param(int dir, struct us_client *usc,
+		uint32_t module_id, uint32_t param_id, uint32_t buf_size)
+{
+	int rc = 0;
+	struct usm_stream_cmd_set_param cmd_set_param;
+	struct us_port_data *port = NULL;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	port = &usc->port[dir];
+
+	q6usm_add_hdr(usc, &cmd_set_param.hdr, sizeof(cmd_set_param), true);
+
+	cmd_set_param.hdr.opcode = USM_STREAM_CMD_SET_PARAM;
+	cmd_set_param.buf_size = buf_size;
+	cmd_set_param.buf_addr_msw =
+			msm_audio_populate_upper_32_bits(port->param_phys);
+	cmd_set_param.buf_addr_lsw = lower_32_bits(port->param_phys);
+	cmd_set_param.mem_map_handle =
+			*((uint32_t *)(port->param_buf_mem_handle));
+	cmd_set_param.module_id = module_id;
+	cmd_set_param.param_id = param_id;
+	cmd_set_param.hdr.token = 0;
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) &cmd_set_param);
+
+	if (rc < 0) {
+		pr_err("%s:write op[0x%x];rc[%d]\n",
+			__func__, cmd_set_param.hdr.opcode, rc);
+	}
+
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: CMD_SET_PARAM: timeout=%d\n",
+			__func__, Q6USM_TIMEOUT_JIFFIES);
+	} else
+		rc = 0;
+
+	return rc;
+}
+
+int q6usm_get_us_stream_param(int dir, struct us_client *usc,
+		uint32_t module_id, uint32_t param_id, uint32_t buf_size)
+{
+	int rc = 0;
+	struct usm_stream_cmd_get_param cmd_get_param;
+	struct us_port_data *port = NULL;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	port = &usc->port[dir];
+
+	q6usm_add_hdr(usc, &cmd_get_param.hdr, sizeof(cmd_get_param), true);
+
+	cmd_get_param.hdr.opcode = USM_STREAM_CMD_GET_PARAM;
+	cmd_get_param.buf_size = buf_size;
+	cmd_get_param.buf_addr_msw =
+			msm_audio_populate_upper_32_bits(port->param_phys);
+	cmd_get_param.buf_addr_lsw = lower_32_bits(port->param_phys);
+	cmd_get_param.mem_map_handle =
+			*((uint32_t *)(port->param_buf_mem_handle));
+	cmd_get_param.module_id = module_id;
+	cmd_get_param.param_id = param_id;
+	cmd_get_param.hdr.token = 0;
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) &cmd_get_param);
+
+	if (rc < 0) {
+		pr_err("%s:write op[0x%x];rc[%d]\n",
+			__func__, cmd_get_param.hdr.opcode, rc);
+	}
+
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: CMD_GET_PARAM: timeout=%d\n",
+			__func__, Q6USM_TIMEOUT_JIFFIES);
+	} else
+		rc = 0;
+
+	return rc;
+}
+
+static int __init q6usm_init(void)
+{
+	pr_debug("%s\n", __func__);
+	init_waitqueue_head(&this_mmap.cmd_wait);
+	memset(session, 0, sizeof(session));
+	return 0;
+}
+
+device_initcall(q6usm_init);

+ 130 - 0
drivers/misc/qcom/qdsp6v2/ultrasound/q6usm.h

@@ -0,0 +1,130 @@
+/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+#ifndef __Q6_USM_H__
+#define __Q6_USM_H__
+
+#include <linux/qdsp6v2/apr_us.h>
+
+#define Q6USM_EVENT_UNDEF                0
+#define Q6USM_EVENT_READ_DONE            1
+#define Q6USM_EVENT_WRITE_DONE           2
+#define Q6USM_EVENT_SIGNAL_DETECT_RESULT 3
+
+/* cyclic buffer with 1 gap support */
+#define USM_MIN_BUF_CNT 3
+
+#define FORMAT_USPS_EPOS	0x00000000
+#define FORMAT_USRAW		0x00000001
+#define FORMAT_USPROX		0x00000002
+#define FORMAT_USGES_SYNC	0x00000003
+#define FORMAT_USRAW_SYNC	0x00000004
+#define INVALID_FORMAT		0xffffffff
+
+#define IN			0x000
+#define OUT			0x001
+
+#define USM_WRONG_TOKEN		0xffffffff
+#define USM_UNDEF_TOKEN		0xfffffffe
+
+#define CMD_CLOSE		0x0004
+
+/* bit 0:1 represents priority of stream */
+#define STREAM_PRIORITY_NORMAL	0x0000
+#define STREAM_PRIORITY_LOW	0x0001
+#define STREAM_PRIORITY_HIGH	0x0002
+
+/* bit 4 represents META enable of encoded data buffer */
+#define BUFFER_META_ENABLE	0x0010
+
+struct us_port_data {
+	dma_addr_t	phys;
+	/* cyclic region of buffers with 1 gap */
+	void		*data;
+	/* number of buffers in the region */
+	uint32_t	buf_cnt;
+	/* size of buffer */
+	size_t		buf_size;
+	/* write index */
+	uint32_t	dsp_buf;
+	/* read index */
+	uint32_t	cpu_buf;
+	/* expected token from dsp */
+	uint32_t	expected_token;
+	/* read or write locks */
+	struct mutex	lock;
+	spinlock_t	dsp_lock;
+	/* ION memory handle */
+	struct      ion_handle *handle;
+	/* ION memory client */
+	struct      ion_client *client;
+	/* extended parameters, related to q6 variants */
+	void		*ext;
+	/* physical address of parameter buffer */
+	dma_addr_t	param_phys;
+	/* buffer which stores the parameter data */
+	void		*param_buf;
+	/* size of parameter buffer */
+	uint32_t	param_buf_size;
+	/* parameter buffer memory handle */
+	void		*param_buf_mem_handle;
+	/* ION memory handle for parameter buffer */
+	struct      ion_handle *param_handle;
+	/* ION memory client for parameter buffer */
+	struct      ion_client *param_client;
+};
+
+struct us_client {
+	int			session;
+	/* idx:1 out port, 0: in port*/
+	struct us_port_data	port[2];
+
+	struct apr_svc		*apr;
+	struct mutex		cmd_lock;
+
+	atomic_t		cmd_state;
+	atomic_t		eos_state;
+	wait_queue_head_t	cmd_wait;
+
+	void (*cb)(uint32_t, uint32_t, uint32_t *, void *);
+	void			*priv;
+};
+
+int q6usm_run(struct us_client *usc, uint32_t flags,
+	      uint32_t msw_ts, uint32_t lsw_ts);
+int q6usm_cmd(struct us_client *usc, int cmd);
+int q6usm_us_client_buf_alloc(unsigned int dir, struct us_client *usc,
+			      unsigned int bufsz, unsigned int bufcnt);
+int q6usm_us_param_buf_alloc(unsigned int dir, struct us_client *usc,
+			      unsigned int bufsz);
+int q6usm_enc_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg);
+int q6usm_dec_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg);
+int q6usm_read(struct us_client *usc, uint32_t read_ind);
+struct us_client *q6usm_us_client_alloc(
+	void (*cb)(uint32_t, uint32_t, uint32_t *, void *),
+	void *priv);
+int q6usm_open_read(struct us_client *usc, uint32_t format);
+void q6usm_us_client_free(struct us_client *usc);
+uint32_t q6usm_get_virtual_address(int dir, struct us_client *usc,
+				   struct vm_area_struct *vms);
+int q6usm_open_write(struct us_client *usc,  uint32_t format);
+int q6usm_write(struct us_client *usc, uint32_t write_ind);
+bool q6usm_is_write_buf_full(struct us_client *usc, uint32_t *free_region);
+int q6usm_set_us_detection(struct us_client *usc,
+			   struct usm_session_cmd_detect_info *detect_info,
+			   uint16_t detect_info_size);
+int q6usm_set_us_stream_param(int dir, struct us_client *usc,
+		uint32_t module_id, uint32_t param_id, uint32_t buf_size);
+int q6usm_get_us_stream_param(int dir, struct us_client *usc,
+		uint32_t module_id, uint32_t param_id, uint32_t buf_size);
+
+#endif /* __Q6_USM_H__ */

+ 2465 - 0
drivers/misc/qcom/qdsp6v2/ultrasound/usf.c

@@ -0,0 +1,2465 @@
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/compat.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/input.h>
+#include <linux/uaccess.h>
+#include <linux/time.h>
+#include <linux/kmemleak.h>
+#include <linux/wakelock.h>
+#include <linux/mutex.h>
+#include <sound/apr_audio.h>
+#include <linux/qdsp6v2/usf.h>
+#include "q6usm.h"
+#include "usfcdev.h"
+
+/* The driver version*/
+#define DRV_VERSION "1.7.1"
+#define USF_VERSION_ID 0x0171
+
+/* Standard timeout in the asynchronous ops */
+#define USF_TIMEOUT_JIFFIES (1*HZ) /* 1 sec */
+
+/* Undefined USF device */
+#define USF_UNDEF_DEV_ID 0xffff
+
+/* TX memory mapping flag */
+#define USF_VM_READ 1
+/* RX memory mapping flag */
+#define USF_VM_WRITE 2
+
+/* Number of events, copied from the user space to kernel one */
+#define USF_EVENTS_PORTION_SIZE 20
+
+/* Indexes in range definitions */
+#define MIN_IND 0
+#define MAX_IND 1
+
+/* The coordinates indexes */
+#define X_IND 0
+#define Y_IND 1
+#define Z_IND 2
+
+/* Shared memory limits */
+/* max_buf_size = (port_size(65535*2) * port_num(8) * group_size(3) */
+#define USF_MAX_BUF_SIZE 3145680
+#define USF_MAX_BUF_NUM  32
+
+/* max size for buffer set from user space */
+#define USF_MAX_USER_BUF_SIZE 100000
+
+/* Place for opreation result, received from QDSP6 */
+#define APR_RESULT_IND 1
+
+/* Place for US detection result, received from QDSP6 */
+#define APR_US_DETECT_RESULT_IND 0
+
+#define BITS_IN_BYTE 8
+
+/* Time to stay awake after tx read event (e.g., proximity) */
+#define STAY_AWAKE_AFTER_READ_MSECS 3000
+
+/* The driver states */
+enum usf_state_type {
+	USF_IDLE_STATE,
+	USF_OPENED_STATE,
+	USF_CONFIGURED_STATE,
+	USF_WORK_STATE,
+	USF_ADSP_RESTART_STATE,
+	USF_ERROR_STATE
+};
+
+/* The US detection status upon FW/HW based US detection results */
+enum usf_us_detect_type {
+	USF_US_DETECT_UNDEF,
+	USF_US_DETECT_YES,
+	USF_US_DETECT_NO
+};
+
+struct usf_xx_type {
+	/* Name of the client - event calculator */
+	char client_name[USF_MAX_CLIENT_NAME_SIZE];
+	/* The driver state in TX or RX direction */
+	enum usf_state_type usf_state;
+	/* wait for q6 events mechanism */
+	wait_queue_head_t wait;
+	/* IF with q6usm info */
+	struct us_client *usc;
+	/* Q6:USM' Encoder/decoder configuration */
+	struct us_encdec_cfg encdec_cfg;
+	/* Shared buffer (with Q6:USM) size */
+	uint32_t buffer_size;
+	/* Number of the shared buffers (with Q6:USM) */
+	uint32_t buffer_count;
+	/* Shared memory (Cyclic buffer with 1 gap) control */
+	uint32_t new_region;
+	uint32_t prev_region;
+	/* Q6:USM's events handler */
+	void (*cb)(uint32_t, uint32_t, uint32_t *, void *);
+	/* US detection result */
+	enum usf_us_detect_type us_detect_type;
+	/* User's update info isn't acceptable */
+	u8 user_upd_info_na;
+};
+
+struct usf_type {
+	/* TX device component configuration & control */
+	struct usf_xx_type usf_tx;
+	/* RX device component configuration & control */
+	struct usf_xx_type usf_rx;
+	/* Index into the opened device container */
+	/* To prevent mutual usage of the same device */
+	uint16_t dev_ind;
+	/* Event types, supported by device */
+	uint16_t event_types;
+	/*  The input devices are "input" module registered clients */
+	struct input_dev *input_ifs[USF_MAX_EVENT_IND];
+	/* Bitmap of types of events, conflicting to USF's ones */
+	uint16_t conflicting_event_types;
+	/* Bitmap of types of events from devs, conflicting with USF */
+	uint16_t conflicting_event_filters;
+	/* The requested buttons bitmap */
+	uint16_t req_buttons_bitmap;
+	/* Mutex for exclusive operations (all public APIs) */
+	struct mutex mutex;
+};
+
+struct usf_input_dev_type {
+	/* Input event type, supported by the input device */
+	uint16_t event_type;
+	/* Input device name */
+	const char *input_dev_name;
+	/* Input device registration function */
+	int (*prepare_dev)(uint16_t, struct usf_type *,
+			    struct us_input_info_type *,
+			   const char *);
+	/* Input event notification function */
+	void (*notify_event)(struct usf_type *,
+			     uint16_t,
+			     struct usf_event_type *
+			     );
+};
+
+
+/* The MAX number of the supported devices */
+#define MAX_DEVS_NUMBER	1
+
+/*
+ * code for a special button that is used to show/hide a
+ * hovering cursor in the input framework. Must be in
+ * sync with the button code definition in the framework
+ * (EventHub.h)
+ */
+#define BTN_USF_HOVERING_CURSOR         0x230
+
+/* Supported buttons container */
+static const int s_button_map[] = {
+	BTN_STYLUS,
+	BTN_STYLUS2,
+	BTN_TOOL_PEN,
+	BTN_TOOL_RUBBER,
+	BTN_TOOL_FINGER,
+	BTN_USF_HOVERING_CURSOR
+};
+
+/* The opened devices container */
+static atomic_t s_opened_devs[MAX_DEVS_NUMBER];
+
+static struct wakeup_source usf_wakeup_source;
+
+#define USF_NAME_PREFIX "usf_"
+#define USF_NAME_PREFIX_SIZE 4
+
+
+static struct input_dev *allocate_dev(uint16_t ind, const char *name)
+{
+	struct input_dev *in_dev = input_allocate_device();
+
+	if (in_dev == NULL) {
+		pr_err("%s: input_allocate_device() failed\n", __func__);
+	} else {
+		/* Common part configuration */
+		in_dev->name = name;
+		in_dev->phys = NULL;
+		in_dev->id.bustype = BUS_HOST;
+		in_dev->id.vendor  = 0x0001;
+		in_dev->id.product = 0x0001;
+		in_dev->id.version = USF_VERSION_ID;
+	}
+	return in_dev;
+}
+
+static int prepare_tsc_input_device(uint16_t ind,
+				struct usf_type *usf_info,
+				struct us_input_info_type *input_info,
+				const char *name)
+{
+	int i = 0;
+
+	int num_buttons = min(ARRAY_SIZE(s_button_map),
+		sizeof(input_info->req_buttons_bitmap) *
+		BITS_IN_BYTE);
+	uint16_t max_buttons_bitmap = ((1 << ARRAY_SIZE(s_button_map)) - 1);
+
+	struct input_dev *in_dev = allocate_dev(ind, name);
+
+	if (in_dev == NULL)
+		return -ENOMEM;
+
+	if (input_info->req_buttons_bitmap > max_buttons_bitmap) {
+		pr_err("%s: Requested buttons[%d] exceeds max buttons available[%d]\n",
+		__func__,
+		input_info->req_buttons_bitmap,
+		max_buttons_bitmap);
+		input_free_device(in_dev);
+		return -EINVAL;
+	}
+
+	usf_info->input_ifs[ind] = in_dev;
+	usf_info->req_buttons_bitmap =
+		input_info->req_buttons_bitmap;
+	in_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	in_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	for (i = 0; i < num_buttons; i++)
+		if (input_info->req_buttons_bitmap & (1 << i))
+			in_dev->keybit[BIT_WORD(s_button_map[i])] |=
+			BIT_MASK(s_button_map[i]);
+
+	input_set_abs_params(in_dev, ABS_X,
+			     input_info->tsc_x_dim[MIN_IND],
+			     input_info->tsc_x_dim[MAX_IND],
+			     0, 0);
+	input_set_abs_params(in_dev, ABS_Y,
+			     input_info->tsc_y_dim[MIN_IND],
+			     input_info->tsc_y_dim[MAX_IND],
+			     0, 0);
+	input_set_abs_params(in_dev, ABS_DISTANCE,
+			     input_info->tsc_z_dim[MIN_IND],
+			     input_info->tsc_z_dim[MAX_IND],
+			     0, 0);
+
+	input_set_abs_params(in_dev, ABS_PRESSURE,
+			     input_info->tsc_pressure[MIN_IND],
+			     input_info->tsc_pressure[MAX_IND],
+			     0, 0);
+
+	input_set_abs_params(in_dev, ABS_TILT_X,
+			     input_info->tsc_x_tilt[MIN_IND],
+			     input_info->tsc_x_tilt[MAX_IND],
+			     0, 0);
+	input_set_abs_params(in_dev, ABS_TILT_Y,
+			     input_info->tsc_y_tilt[MIN_IND],
+			     input_info->tsc_y_tilt[MAX_IND],
+			     0, 0);
+
+	return 0;
+}
+
+static int prepare_mouse_input_device(uint16_t ind, struct usf_type *usf_info,
+			struct us_input_info_type *input_info,
+			const char *name)
+{
+	struct input_dev *in_dev = allocate_dev(ind, name);
+
+	if (in_dev == NULL)
+		return -ENOMEM;
+
+	usf_info->input_ifs[ind] = in_dev;
+	in_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+
+	in_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+						BIT_MASK(BTN_RIGHT) |
+						BIT_MASK(BTN_MIDDLE);
+	in_dev->relbit[0] =  BIT_MASK(REL_X) |
+				BIT_MASK(REL_Y) |
+				BIT_MASK(REL_Z);
+
+	return 0;
+}
+
+static int prepare_keyboard_input_device(
+					uint16_t ind,
+					struct usf_type *usf_info,
+					struct us_input_info_type *input_info,
+					const char *name)
+{
+	struct input_dev *in_dev = allocate_dev(ind, name);
+
+	if (in_dev == NULL)
+		return -ENOMEM;
+
+	usf_info->input_ifs[ind] = in_dev;
+	in_dev->evbit[0] |= BIT_MASK(EV_KEY);
+	/* All keys are permitted */
+	memset(in_dev->keybit, 0xff, sizeof(in_dev->keybit));
+
+	return 0;
+}
+
+static void notify_tsc_event(struct usf_type *usf_info,
+			     uint16_t if_ind,
+			     struct usf_event_type *event)
+
+{
+	int i = 0;
+	int num_buttons = min(ARRAY_SIZE(s_button_map),
+		sizeof(usf_info->req_buttons_bitmap) *
+		BITS_IN_BYTE);
+
+	struct input_dev *input_if = usf_info->input_ifs[if_ind];
+	struct point_event_type *pe = &(event->event_data.point_event);
+
+	input_report_abs(input_if, ABS_X, pe->coordinates[X_IND]);
+	input_report_abs(input_if, ABS_Y, pe->coordinates[Y_IND]);
+	input_report_abs(input_if, ABS_DISTANCE, pe->coordinates[Z_IND]);
+
+	input_report_abs(input_if, ABS_TILT_X, pe->inclinations[X_IND]);
+	input_report_abs(input_if, ABS_TILT_Y, pe->inclinations[Y_IND]);
+
+	input_report_abs(input_if, ABS_PRESSURE, pe->pressure);
+	input_report_key(input_if, BTN_TOUCH, !!(pe->pressure));
+
+	for (i = 0; i < num_buttons; i++) {
+		uint16_t mask = (1 << i),
+		btn_state = !!(pe->buttons_state_bitmap & mask);
+		if (usf_info->req_buttons_bitmap & mask)
+			input_report_key(input_if, s_button_map[i], btn_state);
+	}
+
+	input_sync(input_if);
+
+	pr_debug("%s: TSC event: xyz[%d;%d;%d], incl[%d;%d], pressure[%d], buttons[%d]\n",
+		 __func__,
+		 pe->coordinates[X_IND],
+		 pe->coordinates[Y_IND],
+		 pe->coordinates[Z_IND],
+		 pe->inclinations[X_IND],
+		 pe->inclinations[Y_IND],
+		 pe->pressure,
+		 pe->buttons_state_bitmap);
+}
+
+static void notify_mouse_event(struct usf_type *usf_info,
+			       uint16_t if_ind,
+			       struct usf_event_type *event)
+{
+	struct input_dev *input_if = usf_info->input_ifs[if_ind];
+	struct mouse_event_type *me = &(event->event_data.mouse_event);
+
+	input_report_rel(input_if, REL_X, me->rels[X_IND]);
+	input_report_rel(input_if, REL_Y, me->rels[Y_IND]);
+	input_report_rel(input_if, REL_Z, me->rels[Z_IND]);
+
+	input_report_key(input_if, BTN_LEFT,
+			 me->buttons_states & USF_BUTTON_LEFT_MASK);
+	input_report_key(input_if, BTN_MIDDLE,
+			 me->buttons_states & USF_BUTTON_MIDDLE_MASK);
+	input_report_key(input_if, BTN_RIGHT,
+			 me->buttons_states & USF_BUTTON_RIGHT_MASK);
+
+	input_sync(input_if);
+
+	pr_debug("%s: mouse event: dx[%d], dy[%d], buttons_states[%d]\n",
+		 __func__, me->rels[X_IND],
+		 me->rels[Y_IND], me->buttons_states);
+}
+
+static void notify_key_event(struct usf_type *usf_info,
+			     uint16_t if_ind,
+			     struct usf_event_type *event)
+{
+	struct input_dev *input_if = usf_info->input_ifs[if_ind];
+	struct key_event_type *ke = &(event->event_data.key_event);
+
+	input_report_key(input_if, ke->key, ke->key_state);
+	input_sync(input_if);
+	pr_debug("%s: key event: key[%d], state[%d]\n",
+		 __func__,
+		 ke->key,
+		 ke->key_state);
+
+}
+
+static struct usf_input_dev_type s_usf_input_devs[] = {
+	{USF_TSC_EVENT, "usf_tsc",
+		prepare_tsc_input_device, notify_tsc_event},
+	{USF_TSC_PTR_EVENT, "usf_tsc_ptr",
+		prepare_tsc_input_device, notify_tsc_event},
+	{USF_MOUSE_EVENT, "usf_mouse",
+		prepare_mouse_input_device, notify_mouse_event},
+	{USF_KEYBOARD_EVENT, "usf_kb",
+		prepare_keyboard_input_device, notify_key_event},
+	{USF_TSC_EXT_EVENT, "usf_tsc_ext",
+		prepare_tsc_input_device, notify_tsc_event},
+};
+
+static void usf_rx_cb(uint32_t opcode, uint32_t token,
+		      uint32_t *payload, void *priv)
+{
+	struct usf_xx_type *usf_xx = (struct usf_xx_type *) priv;
+
+	if (usf_xx == NULL) {
+		pr_err("%s: the private data is NULL\n", __func__);
+		return;
+	}
+
+	switch (opcode) {
+	case Q6USM_EVENT_WRITE_DONE:
+		wake_up(&usf_xx->wait);
+		break;
+
+	case RESET_EVENTS:
+		pr_err("%s: received RESET_EVENTS\n", __func__);
+		usf_xx->usf_state = USF_ADSP_RESTART_STATE;
+		wake_up(&usf_xx->wait);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void usf_tx_cb(uint32_t opcode, uint32_t token,
+		      uint32_t *payload, void *priv)
+{
+	struct usf_xx_type *usf_xx = (struct usf_xx_type *) priv;
+
+	if (usf_xx == NULL) {
+		pr_err("%s: the private data is NULL\n", __func__);
+		return;
+	}
+
+	switch (opcode) {
+	case Q6USM_EVENT_READ_DONE:
+		pr_debug("%s: acquiring %d msec wake lock\n", __func__,
+				STAY_AWAKE_AFTER_READ_MSECS);
+		__pm_wakeup_event(&usf_wakeup_source,
+				  STAY_AWAKE_AFTER_READ_MSECS);
+		if (token == USM_WRONG_TOKEN)
+			usf_xx->usf_state = USF_ERROR_STATE;
+		usf_xx->new_region = token;
+		wake_up(&usf_xx->wait);
+		break;
+
+	case Q6USM_EVENT_SIGNAL_DETECT_RESULT:
+		usf_xx->us_detect_type = (payload[APR_US_DETECT_RESULT_IND]) ?
+					USF_US_DETECT_YES :
+					USF_US_DETECT_NO;
+
+		wake_up(&usf_xx->wait);
+		break;
+
+	case APR_BASIC_RSP_RESULT:
+		if (payload[APR_RESULT_IND]) {
+			usf_xx->usf_state = USF_ERROR_STATE;
+			usf_xx->new_region = USM_WRONG_TOKEN;
+			wake_up(&usf_xx->wait);
+		}
+		break;
+
+	case RESET_EVENTS:
+		pr_err("%s: received RESET_EVENTS\n", __func__);
+		usf_xx->usf_state = USF_ADSP_RESTART_STATE;
+		wake_up(&usf_xx->wait);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void release_xx(struct usf_xx_type *usf_xx)
+{
+	if (usf_xx != NULL) {
+		if (usf_xx->usc) {
+			q6usm_us_client_free(usf_xx->usc);
+			usf_xx->usc = NULL;
+		}
+
+		if (usf_xx->encdec_cfg.params != NULL) {
+			kfree(usf_xx->encdec_cfg.params);
+			usf_xx->encdec_cfg.params = NULL;
+		}
+	}
+}
+
+static void usf_disable(struct usf_xx_type *usf_xx)
+{
+	if (usf_xx != NULL) {
+		if ((usf_xx->usf_state != USF_IDLE_STATE) &&
+		    (usf_xx->usf_state != USF_OPENED_STATE)) {
+			(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+			usf_xx->usf_state = USF_OPENED_STATE;
+			wake_up(&usf_xx->wait);
+		}
+		release_xx(usf_xx);
+	}
+}
+
+static int config_xx(struct usf_xx_type *usf_xx, struct us_xx_info_type *config)
+{
+	int rc = 0;
+	uint16_t data_map_size = 0;
+	uint16_t min_map_size = 0;
+
+	if ((usf_xx == NULL) ||
+	    (config == NULL))
+		return -EINVAL;
+
+	if ((config->buf_size == 0) ||
+	    (config->buf_size > USF_MAX_BUF_SIZE) ||
+	    (config->buf_num == 0) ||
+	    (config->buf_num > USF_MAX_BUF_NUM)) {
+		pr_err("%s: wrong params: buf_size=%d; buf_num=%d\n",
+		       __func__, config->buf_size, config->buf_num);
+		return -EINVAL;
+	}
+
+	data_map_size = sizeof(usf_xx->encdec_cfg.cfg_common.data_map);
+	min_map_size = min(data_map_size, config->port_cnt);
+
+	if (config->client_name != NULL) {
+		if (strncpy_from_user(usf_xx->client_name,
+				      (char __user *)config->client_name,
+				      sizeof(usf_xx->client_name) - 1) < 0) {
+			pr_err("%s: get client name failed\n", __func__);
+			return -EINVAL;
+		}
+	}
+
+	pr_debug("%s: name=%s; buf_size:%d; dev_id:0x%x; sample_rate:%d\n",
+		__func__, usf_xx->client_name, config->buf_size,
+		config->dev_id, config->sample_rate);
+
+	pr_debug("%s: buf_num:%d; format:%d; port_cnt:%d; data_size=%d\n",
+		__func__, config->buf_num, config->stream_format,
+		config->port_cnt, config->params_data_size);
+
+	pr_debug("%s: id[0]=%d, id[1]=%d, id[2]=%d, id[3]=%d, id[4]=%d,\n",
+		__func__,
+		config->port_id[0],
+		config->port_id[1],
+		config->port_id[2],
+		config->port_id[3],
+		config->port_id[4]);
+
+	pr_debug("id[5]=%d, id[6]=%d, id[7]=%d\n",
+		config->port_id[5],
+		config->port_id[6],
+		config->port_id[7]);
+
+	/* q6usm allocation & configuration */
+	usf_xx->buffer_size = config->buf_size;
+	usf_xx->buffer_count = config->buf_num;
+	usf_xx->encdec_cfg.cfg_common.bits_per_sample =
+				config->bits_per_sample;
+	usf_xx->encdec_cfg.cfg_common.sample_rate = config->sample_rate;
+	/* AFE port e.g. AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX */
+	usf_xx->encdec_cfg.cfg_common.dev_id = config->dev_id;
+
+	usf_xx->encdec_cfg.cfg_common.ch_cfg = config->port_cnt;
+	memcpy((void *)&usf_xx->encdec_cfg.cfg_common.data_map,
+	       (void *)config->port_id,
+	       min_map_size);
+
+	usf_xx->encdec_cfg.format_id = config->stream_format;
+	usf_xx->encdec_cfg.params_size = config->params_data_size;
+	usf_xx->user_upd_info_na = 1; /* it's used in US_GET_TX_UPDATE */
+
+	if (config->params_data_size > 0) { /* transparent data copy */
+		usf_xx->encdec_cfg.params = kzalloc(config->params_data_size,
+						    GFP_KERNEL);
+		/* False memory leak here - pointer in packed struct
+		 * is undetected by kmemleak tool
+		 */
+		kmemleak_ignore(usf_xx->encdec_cfg.params);
+		if (usf_xx->encdec_cfg.params == NULL) {
+			pr_err("%s: params memory alloc[%d] failure\n",
+				__func__,
+				config->params_data_size);
+			return -ENOMEM;
+		}
+		rc = copy_from_user(usf_xx->encdec_cfg.params,
+				    (uint8_t __user *)config->params_data,
+				    config->params_data_size);
+		if (rc) {
+			pr_err("%s: transparent data copy failure\n",
+			       __func__);
+			kfree(usf_xx->encdec_cfg.params);
+			usf_xx->encdec_cfg.params = NULL;
+			return -EFAULT;
+		}
+		pr_debug("%s: params_size[%d]; params[%d,%d,%d,%d, %d]\n",
+			 __func__,
+			 config->params_data_size,
+			 usf_xx->encdec_cfg.params[0],
+			 usf_xx->encdec_cfg.params[1],
+			 usf_xx->encdec_cfg.params[2],
+			 usf_xx->encdec_cfg.params[3],
+			 usf_xx->encdec_cfg.params[4]
+			);
+	}
+
+	usf_xx->usc = q6usm_us_client_alloc(usf_xx->cb, (void *)usf_xx);
+	if (!usf_xx->usc) {
+		pr_err("%s: Could not allocate q6usm client\n", __func__);
+		rc = -EFAULT;
+	}
+
+	return rc;
+}
+
+static bool usf_match(uint16_t event_type_ind, struct input_dev *dev)
+{
+	bool rc = false;
+
+	rc = (event_type_ind < MAX_EVENT_TYPE_NUM) &&
+		((dev->name == NULL) ||
+		strcmp(dev->name, USF_NAME_PREFIX));
+	pr_debug("%s: name=[%s]; rc=%d\n",
+		 __func__, dev->name, rc);
+
+	return rc;
+}
+
+static bool usf_register_conflicting_events(uint16_t event_types)
+{
+	bool rc = true;
+	uint16_t ind = 0;
+	uint16_t mask = 1;
+
+	for (ind = 0; ind < MAX_EVENT_TYPE_NUM; ++ind) {
+		if (event_types & mask) {
+			rc = usfcdev_register(ind, usf_match);
+			if (!rc)
+				break;
+		}
+		mask = mask << 1;
+	}
+
+	return rc;
+}
+
+static void usf_unregister_conflicting_events(uint16_t event_types)
+{
+	uint16_t ind = 0;
+	uint16_t mask = 1;
+
+	for (ind = 0; ind < MAX_EVENT_TYPE_NUM; ++ind) {
+		if (event_types & mask)
+			usfcdev_unregister(ind);
+		mask = mask << 1;
+	}
+}
+
+static void usf_set_event_filters(struct usf_type *usf, uint16_t event_filters)
+{
+	uint16_t ind = 0;
+	uint16_t mask = 1;
+
+	if (usf->conflicting_event_filters != event_filters) {
+		for (ind = 0; ind < MAX_EVENT_TYPE_NUM; ++ind) {
+			if (usf->conflicting_event_types & mask)
+				usfcdev_set_filter(ind, event_filters&mask);
+			mask = mask << 1;
+		}
+		usf->conflicting_event_filters = event_filters;
+	}
+}
+
+static int register_input_device(struct usf_type *usf_info,
+				 struct us_input_info_type *input_info)
+{
+	int rc = 0;
+	bool ret = true;
+	uint16_t ind = 0;
+
+	if ((usf_info == NULL) ||
+	    (input_info == NULL) ||
+	    !(input_info->event_types & USF_ALL_EVENTS)) {
+		pr_err("%s: wrong input parameter(s)\n", __func__);
+		return -EINVAL;
+	}
+
+	for (ind = 0; ind < USF_MAX_EVENT_IND; ++ind) {
+		if (usf_info->input_ifs[ind] != NULL) {
+			pr_err("%s: input_if[%d] is already allocated\n",
+				__func__, ind);
+			return -EFAULT;
+		}
+		if ((input_info->event_types &
+			s_usf_input_devs[ind].event_type) &&
+		     s_usf_input_devs[ind].prepare_dev) {
+			rc = (*s_usf_input_devs[ind].prepare_dev)(
+				ind,
+				usf_info,
+				input_info,
+				s_usf_input_devs[ind].input_dev_name);
+			if (rc)
+				return rc;
+
+			rc = input_register_device(usf_info->input_ifs[ind]);
+			if (rc) {
+				pr_err("%s: input_reg_dev() failed; rc=%d\n",
+					__func__, rc);
+				input_free_device(usf_info->input_ifs[ind]);
+				usf_info->input_ifs[ind] = NULL;
+			} else {
+				usf_info->event_types |=
+					s_usf_input_devs[ind].event_type;
+				pr_debug("%s: input device[%s] was registered\n",
+					__func__,
+					s_usf_input_devs[ind].input_dev_name);
+			}
+		} /* supported event */
+	} /* event types loop */
+
+	ret = usf_register_conflicting_events(
+			input_info->conflicting_event_types);
+	if (ret)
+		usf_info->conflicting_event_types =
+			input_info->conflicting_event_types;
+
+	return 0;
+}
+
+
+static void handle_input_event(struct usf_type *usf_info,
+			       uint16_t event_counter,
+			       struct usf_event_type __user *event)
+{
+	uint16_t ind = 0;
+	uint16_t events_num = 0;
+	struct usf_event_type usf_events[USF_EVENTS_PORTION_SIZE];
+	int rc = 0;
+
+	if ((usf_info == NULL) ||
+	    (event == NULL) || (!event_counter)) {
+		return;
+	}
+
+	while (event_counter > 0) {
+		if (event_counter > USF_EVENTS_PORTION_SIZE) {
+			events_num = USF_EVENTS_PORTION_SIZE;
+			event_counter -= USF_EVENTS_PORTION_SIZE;
+		} else {
+			events_num = event_counter;
+			event_counter = 0;
+		}
+		rc = copy_from_user(usf_events,
+				(struct usf_event_type __user *)event,
+				events_num * sizeof(struct usf_event_type));
+		if (rc) {
+			pr_err("%s: copy upd_rx_info from user; rc=%d\n",
+				__func__, rc);
+			return;
+		}
+		for (ind = 0; ind < events_num; ++ind) {
+			struct usf_event_type *p_event = &usf_events[ind];
+			uint16_t if_ind = p_event->event_type_ind;
+
+			if ((if_ind >= USF_MAX_EVENT_IND) ||
+			    (usf_info->input_ifs[if_ind] == NULL))
+				continue; /* event isn't supported */
+
+			if (s_usf_input_devs[if_ind].notify_event)
+				(*s_usf_input_devs[if_ind].notify_event)(
+								usf_info,
+								if_ind,
+								p_event);
+		} /* loop in the portion */
+	} /* all events loop */
+}
+
+static int usf_start_tx(struct usf_xx_type *usf_xx)
+{
+	int rc = q6usm_run(usf_xx->usc, 0, 0, 0);
+
+	pr_debug("%s: tx: q6usm_run; rc=%d\n", __func__, rc);
+	if (!rc) {
+		if (usf_xx->buffer_count >= USM_MIN_BUF_CNT) {
+			/* supply all buffers */
+			rc = q6usm_read(usf_xx->usc,
+					usf_xx->buffer_count);
+			pr_debug("%s: q6usm_read[%d]\n",
+				 __func__, rc);
+
+			if (rc)
+				pr_err("%s: buf read failed",
+				       __func__);
+			else
+				usf_xx->usf_state =
+					USF_WORK_STATE;
+		} else
+			usf_xx->usf_state =
+				USF_WORK_STATE;
+	}
+
+	return rc;
+} /* usf_start_tx */
+
+static int usf_start_rx(struct usf_xx_type *usf_xx)
+{
+	int rc = q6usm_run(usf_xx->usc, 0, 0, 0);
+
+	pr_debug("%s: rx: q6usm_run; rc=%d\n",
+		 __func__, rc);
+	if (!rc)
+		usf_xx->usf_state = USF_WORK_STATE;
+
+	return rc;
+} /* usf_start_rx */
+
+static int __usf_set_us_detection(struct usf_type *usf,
+				  struct us_detect_info_type *detect_info)
+{
+	uint32_t timeout = 0;
+	struct usm_session_cmd_detect_info *p_allocated_memory = NULL;
+	struct usm_session_cmd_detect_info usm_detect_info;
+	struct usm_session_cmd_detect_info *p_usm_detect_info =
+						&usm_detect_info;
+	uint32_t detect_info_size = sizeof(struct usm_session_cmd_detect_info);
+	struct usf_xx_type *usf_xx =  &usf->usf_tx;
+	int rc = 0;
+
+	if (detect_info->us_detector != US_DETECT_FW) {
+		pr_err("%s: unsupported detector: %d\n",
+			__func__, detect_info->us_detector);
+		return -EINVAL;
+	}
+
+	if ((detect_info->params_data_size != 0) &&
+	    (detect_info->params_data != NULL)) {
+		uint8_t *p_data = NULL;
+
+		detect_info_size += detect_info->params_data_size;
+		 p_allocated_memory = kzalloc(detect_info_size, GFP_KERNEL);
+		if (p_allocated_memory == NULL) {
+			pr_err("%s: detect_info[%d] allocation failed\n",
+			       __func__, detect_info_size);
+			return -ENOMEM;
+		}
+		p_usm_detect_info = p_allocated_memory;
+		p_data = (uint8_t *)p_usm_detect_info +
+			sizeof(struct usm_session_cmd_detect_info);
+
+		rc = copy_from_user(p_data,
+			(uint8_t __user *)(detect_info->params_data),
+			detect_info->params_data_size);
+		if (rc) {
+			pr_err("%s: copy params from user; rc=%d\n",
+				__func__, rc);
+			kfree(p_allocated_memory);
+			return -EFAULT;
+		}
+		p_usm_detect_info->algorithm_cfg_size =
+				detect_info->params_data_size;
+	} else
+		usm_detect_info.algorithm_cfg_size = 0;
+
+	p_usm_detect_info->detect_mode = detect_info->us_detect_mode;
+	p_usm_detect_info->skip_interval = detect_info->skip_time;
+
+	usf_xx->us_detect_type = USF_US_DETECT_UNDEF;
+
+	rc = q6usm_set_us_detection(usf_xx->usc,
+				    p_usm_detect_info,
+				    detect_info_size);
+	if (rc || (detect_info->detect_timeout == USF_NO_WAIT_TIMEOUT)) {
+		kfree(p_allocated_memory);
+		return rc;
+	}
+
+	/* Get US detection result */
+	if (detect_info->detect_timeout == USF_INFINITIVE_TIMEOUT) {
+		rc = wait_event_interruptible(usf_xx->wait,
+						(usf_xx->us_detect_type !=
+						USF_US_DETECT_UNDEF) ||
+						(usf_xx->usf_state ==
+						USF_ADSP_RESTART_STATE));
+	} else {
+		if (detect_info->detect_timeout == USF_DEFAULT_TIMEOUT)
+			timeout = USF_TIMEOUT_JIFFIES;
+		else
+			timeout = detect_info->detect_timeout * HZ;
+	}
+	rc = wait_event_interruptible_timeout(usf_xx->wait,
+					(usf_xx->us_detect_type !=
+					USF_US_DETECT_UNDEF) ||
+					(usf_xx->usf_state ==
+					USF_ADSP_RESTART_STATE), timeout);
+
+	/* In the case of aDSP restart, "no US" is assumed */
+	if (usf_xx->usf_state == USF_ADSP_RESTART_STATE)
+		rc = -EFAULT;
+
+	/* In the case of timeout, "no US" is assumed */
+	if (rc < 0)
+		pr_err("%s: Getting US detection failed rc[%d]\n",
+		       __func__, rc);
+	else {
+		usf->usf_rx.us_detect_type = usf->usf_tx.us_detect_type;
+		detect_info->is_us =
+			(usf_xx->us_detect_type == USF_US_DETECT_YES);
+	}
+
+	kfree(p_allocated_memory);
+
+	return rc;
+} /* __usf_set_us_detection */
+
+static int usf_set_us_detection(struct usf_type *usf, unsigned long arg)
+{
+	struct us_detect_info_type detect_info;
+
+	int rc = copy_from_user(&detect_info,
+				(struct us_detect_info_type __user *) arg,
+				sizeof(detect_info));
+
+	if (rc) {
+		pr_err("%s: copy detect_info from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	if (detect_info.params_data_size > USF_MAX_USER_BUF_SIZE) {
+		pr_err("%s: user buffer size exceeds maximum\n",
+			__func__);
+		return -EFAULT;
+	}
+
+	rc = __usf_set_us_detection(usf, &detect_info);
+	if (rc < 0) {
+		pr_err("%s: set us detection failed; rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	rc = copy_to_user((void __user *)arg,
+			  &detect_info,
+			  sizeof(detect_info));
+	if (rc) {
+		pr_err("%s: copy detect_info to user; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	return rc;
+} /* usf_set_us_detection */
+
+static int __usf_set_tx_info(struct usf_type *usf,
+			     struct us_tx_info_type *config_tx)
+{
+	struct usf_xx_type *usf_xx =  &usf->usf_tx;
+	int rc = 0;
+
+	usf_xx->new_region = USM_UNDEF_TOKEN;
+	usf_xx->prev_region = USM_UNDEF_TOKEN;
+	usf_xx->cb = usf_tx_cb;
+
+	init_waitqueue_head(&usf_xx->wait);
+
+	if (config_tx->us_xx_info.client_name != NULL) {
+		int res = strncpy_from_user(
+			usf_xx->client_name,
+			(char __user *)(config_tx->us_xx_info.client_name),
+			sizeof(usf_xx->client_name)-1);
+		if (res < 0) {
+			pr_err("%s: get client name failed\n",
+			       __func__);
+			return -EINVAL;
+		}
+	}
+
+	rc = config_xx(usf_xx, &(config_tx->us_xx_info));
+	if (rc)
+		return rc;
+
+	rc = q6usm_open_read(usf_xx->usc,
+			     usf_xx->encdec_cfg.format_id);
+	if (rc)
+		return rc;
+
+	rc = q6usm_us_client_buf_alloc(OUT, usf_xx->usc,
+				       usf_xx->buffer_size,
+				       usf_xx->buffer_count);
+	if (rc) {
+		(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+		return rc;
+	}
+
+	rc = q6usm_us_param_buf_alloc(OUT, usf_xx->usc,
+			config_tx->us_xx_info.max_get_set_param_buf_size);
+	if (rc) {
+		(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+		return rc;
+	}
+
+	rc = q6usm_enc_cfg_blk(usf_xx->usc,
+			       &usf_xx->encdec_cfg);
+	if (!rc &&
+	     (config_tx->input_info.event_types != USF_NO_EVENT)) {
+		rc = register_input_device(usf,
+					   &(config_tx->input_info));
+	}
+
+	if (rc)
+		(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+	else
+		usf_xx->usf_state = USF_CONFIGURED_STATE;
+
+	return rc;
+} /* __usf_set_tx_info */
+
+static int usf_set_tx_info(struct usf_type *usf, unsigned long arg)
+{
+	struct us_tx_info_type config_tx;
+
+	int rc = copy_from_user(&config_tx,
+			    (struct us_tx_info_type __user *) arg,
+			    sizeof(config_tx));
+
+	if (rc) {
+		pr_err("%s: copy config_tx from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	if (config_tx.us_xx_info.params_data_size > USF_MAX_USER_BUF_SIZE) {
+		pr_err("%s: user buffer size exceeds maximum\n",
+			__func__);
+		return -EFAULT;
+	}
+
+	return __usf_set_tx_info(usf, &config_tx);
+} /* usf_set_tx_info */
+
+static int __usf_set_rx_info(struct usf_type *usf,
+			     struct us_rx_info_type *config_rx)
+{
+	struct usf_xx_type *usf_xx =  &usf->usf_rx;
+	int rc = 0;
+
+	usf_xx->new_region = USM_UNDEF_TOKEN;
+	usf_xx->prev_region = USM_UNDEF_TOKEN;
+
+	usf_xx->cb = usf_rx_cb;
+
+	rc = config_xx(usf_xx, &(config_rx->us_xx_info));
+	if (rc)
+		return rc;
+
+	rc = q6usm_open_write(usf_xx->usc,
+			      usf_xx->encdec_cfg.format_id);
+	if (rc)
+		return rc;
+
+	rc = q6usm_us_client_buf_alloc(
+				IN,
+				usf_xx->usc,
+				usf_xx->buffer_size,
+				usf_xx->buffer_count);
+	if (rc) {
+		(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+		return rc;
+	}
+
+	rc = q6usm_us_param_buf_alloc(IN, usf_xx->usc,
+			config_rx->us_xx_info.max_get_set_param_buf_size);
+	if (rc) {
+		(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+		return rc;
+	}
+
+	rc = q6usm_dec_cfg_blk(usf_xx->usc,
+			       &usf_xx->encdec_cfg);
+	if (rc)
+		(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+	else {
+		init_waitqueue_head(&usf_xx->wait);
+		usf_xx->usf_state = USF_CONFIGURED_STATE;
+	}
+
+	return rc;
+} /* __usf_set_rx_info */
+
+static int usf_set_rx_info(struct usf_type *usf, unsigned long arg)
+{
+	struct us_rx_info_type config_rx;
+
+	int rc = copy_from_user(&config_rx,
+				(struct us_rx_info_type __user *) arg,
+				sizeof(config_rx));
+
+	if (rc) {
+		pr_err("%s: copy config_rx from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	if (config_rx.us_xx_info.params_data_size > USF_MAX_USER_BUF_SIZE) {
+		pr_err("%s: user buffer size exceeds maximum\n",
+			__func__);
+		return -EFAULT;
+	}
+
+	return __usf_set_rx_info(usf, &config_rx);
+} /* usf_set_rx_info */
+
+static int __usf_get_tx_update(struct usf_type *usf,
+			struct us_tx_update_info_type *upd_tx_info)
+{
+	unsigned long prev_jiffies = 0;
+	uint32_t timeout = 0;
+	struct usf_xx_type *usf_xx =  &usf->usf_tx;
+	int rc = 0;
+
+	if (!usf_xx->user_upd_info_na) {
+		usf_set_event_filters(usf, upd_tx_info->event_filters);
+		handle_input_event(usf,
+				   upd_tx_info->event_counter,
+				   upd_tx_info->event);
+
+		/* Release available regions */
+		rc = q6usm_read(usf_xx->usc,
+				upd_tx_info->free_region);
+		if (rc)
+			return rc;
+	} else
+		usf_xx->user_upd_info_na = 0;
+
+	/* Get data ready regions */
+	if (upd_tx_info->timeout == USF_INFINITIVE_TIMEOUT) {
+		rc = wait_event_interruptible(usf_xx->wait,
+			   (usf_xx->prev_region !=
+			    usf_xx->new_region) ||
+			   (usf_xx->usf_state !=
+			    USF_WORK_STATE));
+	} else {
+		if (upd_tx_info->timeout == USF_NO_WAIT_TIMEOUT)
+			rc = (usf_xx->prev_region != usf_xx->new_region);
+		else {
+			prev_jiffies = jiffies;
+			if (upd_tx_info->timeout == USF_DEFAULT_TIMEOUT) {
+				timeout = USF_TIMEOUT_JIFFIES;
+				rc = wait_event_timeout(
+						usf_xx->wait,
+						(usf_xx->prev_region !=
+						 usf_xx->new_region) ||
+						(usf_xx->usf_state !=
+						 USF_WORK_STATE),
+						timeout);
+			} else {
+				timeout = upd_tx_info->timeout * HZ;
+				rc = wait_event_interruptible_timeout(
+						usf_xx->wait,
+						(usf_xx->prev_region !=
+						 usf_xx->new_region) ||
+						(usf_xx->usf_state !=
+						 USF_WORK_STATE),
+						timeout);
+			}
+		}
+		if (!rc) {
+			pr_debug("%s: timeout. prev_j=%lu; j=%lu\n",
+				__func__, prev_jiffies, jiffies);
+			pr_debug("%s: timeout. prev=%d; new=%d\n",
+				__func__, usf_xx->prev_region,
+				usf_xx->new_region);
+			pr_debug("%s: timeout. free_region=%d;\n",
+				__func__, upd_tx_info->free_region);
+			if (usf_xx->prev_region ==
+			    usf_xx->new_region) {
+				pr_err("%s:read data: timeout\n",
+				       __func__);
+				return -ETIME;
+			}
+		}
+	}
+
+	if ((usf_xx->usf_state != USF_WORK_STATE) ||
+	    (rc == -ERESTARTSYS)) {
+		pr_err("%s: Get ready region failure; state[%d]; rc[%d]\n",
+		       __func__, usf_xx->usf_state, rc);
+		return -EINTR;
+	}
+
+	upd_tx_info->ready_region = usf_xx->new_region;
+	usf_xx->prev_region = upd_tx_info->ready_region;
+
+	if (upd_tx_info->ready_region == USM_WRONG_TOKEN) {
+		pr_err("%s: TX path corrupted; prev=%d\n",
+		       __func__, usf_xx->prev_region);
+		return -EIO;
+	}
+
+	return rc;
+} /* __usf_get_tx_update */
+
+static int usf_get_tx_update(struct usf_type *usf, unsigned long arg)
+{
+	struct us_tx_update_info_type upd_tx_info;
+
+	int rc = copy_from_user(&upd_tx_info,
+				(struct us_tx_update_info_type __user *) arg,
+				sizeof(upd_tx_info));
+
+	if (rc < 0) {
+		pr_err("%s: copy upd_tx_info from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	rc = __usf_get_tx_update(usf, &upd_tx_info);
+	if (rc < 0) {
+		pr_err("%s: get tx update failed; rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	rc = copy_to_user((void __user *)arg,
+			  &upd_tx_info,
+			  sizeof(upd_tx_info));
+	if (rc) {
+		pr_err("%s: copy upd_tx_info to user; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	return rc;
+} /* usf_get_tx_update */
+
+static int __usf_set_rx_update(struct usf_xx_type *usf_xx,
+			       struct us_rx_update_info_type *upd_rx_info)
+{
+	int rc = 0;
+
+	/* Send available data regions */
+	if (upd_rx_info->ready_region !=
+	    usf_xx->buffer_count) {
+		rc = q6usm_write(
+			usf_xx->usc,
+			upd_rx_info->ready_region);
+		if (rc)
+			return rc;
+	}
+
+	/* Get free regions */
+	rc = wait_event_timeout(
+		usf_xx->wait,
+		!q6usm_is_write_buf_full(
+			usf_xx->usc,
+			&(upd_rx_info->free_region)) ||
+		(usf_xx->usf_state == USF_IDLE_STATE),
+		USF_TIMEOUT_JIFFIES);
+
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s:timeout. wait for write buf not full\n",
+		       __func__);
+	} else {
+		if (usf_xx->usf_state !=
+		    USF_WORK_STATE) {
+			pr_err("%s: RX: state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			rc = -EINTR;
+		}
+	}
+
+	return rc;
+} /* __usf_set_rx_update */
+
+static int usf_set_rx_update(struct usf_xx_type *usf_xx, unsigned long arg)
+{
+	struct us_rx_update_info_type upd_rx_info;
+
+	int rc = copy_from_user(&upd_rx_info,
+				(struct us_rx_update_info_type __user *) arg,
+				sizeof(upd_rx_info));
+
+	if (rc) {
+		pr_err("%s: copy upd_rx_info from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	rc = __usf_set_rx_update(usf_xx, &upd_rx_info);
+	if (rc < 0) {
+		pr_err("%s: set rx update failed; rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	rc = copy_to_user((void __user *)arg,
+			&upd_rx_info,
+			sizeof(upd_rx_info));
+	if (rc) {
+		pr_err("%s: copy rx_info to user; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	return rc;
+} /* usf_set_rx_update */
+
+static void usf_release_input(struct usf_type *usf)
+{
+	uint16_t ind = 0;
+
+	usf_unregister_conflicting_events(
+					usf->conflicting_event_types);
+	usf->conflicting_event_types = 0;
+	for (ind = 0; ind < USF_MAX_EVENT_IND; ++ind) {
+		if (usf->input_ifs[ind] == NULL)
+			continue;
+		input_unregister_device(usf->input_ifs[ind]);
+		usf->input_ifs[ind] = NULL;
+		pr_debug("%s input_unregister_device[%s]\n",
+			 __func__,
+			 s_usf_input_devs[ind].input_dev_name);
+	}
+} /* usf_release_input */
+
+static int usf_stop_tx(struct usf_type *usf)
+{
+	struct usf_xx_type *usf_xx =  &usf->usf_tx;
+
+	usf_release_input(usf);
+	usf_disable(usf_xx);
+
+	return 0;
+} /* usf_stop_tx */
+
+static int __usf_get_version(struct us_version_info_type *version_info)
+{
+	int rc = 0;
+
+	if (version_info->buf_size < sizeof(DRV_VERSION)) {
+		pr_err("%s: buf_size (%d) < version string size (%zu)\n",
+			__func__, version_info->buf_size, sizeof(DRV_VERSION));
+		return -EINVAL;
+	}
+
+	rc = copy_to_user((void __user *)(version_info->pbuf),
+			  DRV_VERSION,
+			  sizeof(DRV_VERSION));
+	if (rc) {
+		pr_err("%s: copy to version_info.pbuf; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	return rc;
+} /* __usf_get_version */
+
+static int usf_get_version(unsigned long arg)
+{
+	struct us_version_info_type version_info;
+
+	int rc = copy_from_user(&version_info,
+				(struct us_version_info_type __user *) arg,
+				sizeof(version_info));
+
+	if (rc) {
+		pr_err("%s: copy version_info from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	rc = __usf_get_version(&version_info);
+	if (rc < 0) {
+		pr_err("%s: get version failed; rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	rc = copy_to_user((void __user *)arg,
+			  &version_info,
+			  sizeof(version_info));
+	if (rc) {
+		pr_err("%s: copy version_info to user; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	return rc;
+} /* usf_get_version */
+
+static int __usf_set_stream_param(struct usf_xx_type *usf_xx,
+				struct us_stream_param_type *set_stream_param,
+				int dir)
+{
+	struct us_client *usc = usf_xx->usc;
+	struct us_port_data *port;
+	int rc = 0;
+
+	if (usc == NULL) {
+		pr_err("%s: usc is null\n",
+			__func__);
+		return -EFAULT;
+	}
+
+	port = &usc->port[dir];
+	if (port == NULL) {
+		pr_err("%s: port is null\n",
+			__func__);
+		return -EFAULT;
+	}
+
+	if (port->param_buf == NULL) {
+		pr_err("%s: parameter buffer is null\n",
+			__func__);
+		return -EFAULT;
+	}
+
+	if (set_stream_param->buf_size > port->param_buf_size) {
+		pr_err("%s: buf_size (%d) > maximum buf size (%d)\n",
+			__func__, set_stream_param->buf_size,
+			port->param_buf_size);
+		return -EINVAL;
+	}
+
+	if (set_stream_param->buf_size == 0) {
+		pr_err("%s: buf_size is 0\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = copy_from_user(port->param_buf,
+			(uint8_t __user *) set_stream_param->pbuf,
+			set_stream_param->buf_size);
+	if (rc) {
+		pr_err("%s: copy param buf from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	rc = q6usm_set_us_stream_param(dir, usc, set_stream_param->module_id,
+					set_stream_param->param_id,
+					set_stream_param->buf_size);
+	if (rc) {
+		pr_err("%s: q6usm_set_us_stream_param failed; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	return rc;
+}
+
+static int usf_set_stream_param(struct usf_xx_type *usf_xx,
+				unsigned long arg, int dir)
+{
+	struct us_stream_param_type set_stream_param;
+	int rc = 0;
+
+	rc = copy_from_user(&set_stream_param,
+			(struct us_stream_param_type __user *) arg,
+			sizeof(set_stream_param));
+
+	if (rc) {
+		pr_err("%s: copy set_stream_param from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	return __usf_set_stream_param(usf_xx, &set_stream_param, dir);
+} /* usf_set_stream_param */
+
+static int __usf_get_stream_param(struct usf_xx_type *usf_xx,
+				struct us_stream_param_type *get_stream_param,
+				int dir)
+{
+	struct us_client *usc = usf_xx->usc;
+	struct us_port_data *port;
+	int rc = 0;
+
+	if (usc == NULL) {
+		pr_err("%s: us_client is null\n",
+			__func__);
+		return -EFAULT;
+	}
+
+	port = &usc->port[dir];
+
+	if (port->param_buf == NULL) {
+		pr_err("%s: parameter buffer is null\n",
+			__func__);
+		return -EFAULT;
+	}
+
+	if (get_stream_param->buf_size > port->param_buf_size) {
+		pr_err("%s: buf_size (%d) > maximum buf size (%d)\n",
+			__func__, get_stream_param->buf_size,
+			port->param_buf_size);
+		return -EINVAL;
+	}
+
+	if (get_stream_param->buf_size == 0) {
+		pr_err("%s: buf_size is 0\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = q6usm_get_us_stream_param(dir, usc, get_stream_param->module_id,
+					get_stream_param->param_id,
+					get_stream_param->buf_size);
+	if (rc) {
+		pr_err("%s: q6usm_get_us_stream_param failed; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	rc = copy_to_user((uint8_t __user *) get_stream_param->pbuf,
+			port->param_buf,
+			get_stream_param->buf_size);
+	if (rc) {
+		pr_err("%s: copy param buf to user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	return rc;
+}
+
+static int usf_get_stream_param(struct usf_xx_type *usf_xx,
+				unsigned long arg, int dir)
+{
+	struct us_stream_param_type get_stream_param;
+	int rc = 0;
+
+	rc = copy_from_user(&get_stream_param,
+			(struct us_stream_param_type __user *) arg,
+			sizeof(get_stream_param));
+
+	if (rc) {
+		pr_err("%s: copy get_stream_param from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	return __usf_get_stream_param(usf_xx, &get_stream_param, dir);
+} /* usf_get_stream_param */
+
+static long __usf_ioctl(struct usf_type *usf,
+		unsigned int cmd,
+		unsigned long arg)
+{
+
+	int rc = 0;
+	struct usf_xx_type *usf_xx = NULL;
+
+	switch (cmd) {
+	case US_START_TX: {
+		usf_xx = &usf->usf_tx;
+		if (usf_xx->usf_state == USF_CONFIGURED_STATE)
+			rc = usf_start_tx(usf_xx);
+		else {
+			pr_err("%s: start_tx: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			return -EBADFD;
+		}
+		break;
+	}
+
+	case US_START_RX: {
+		usf_xx = &usf->usf_rx;
+		if (usf_xx->usf_state == USF_CONFIGURED_STATE)
+			rc = usf_start_rx(usf_xx);
+		else {
+			pr_err("%s: start_rx: wrong state[%d]\n",
+				__func__,
+				usf_xx->usf_state);
+			return -EBADFD;
+		}
+		break;
+	}
+
+	case US_SET_TX_INFO: {
+		usf_xx = &usf->usf_tx;
+		if (usf_xx->usf_state == USF_OPENED_STATE)
+			rc = usf_set_tx_info(usf, arg);
+		else {
+			pr_err("%s: set_tx_info: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			return -EBADFD;
+		}
+
+		break;
+	} /* US_SET_TX_INFO */
+
+	case US_SET_RX_INFO: {
+		usf_xx = &usf->usf_rx;
+		if (usf_xx->usf_state == USF_OPENED_STATE)
+			rc = usf_set_rx_info(usf, arg);
+		else {
+			pr_err("%s: set_rx_info: wrong state[%d]\n",
+				__func__,
+				usf_xx->usf_state);
+			return -EBADFD;
+		}
+
+		break;
+	} /* US_SET_RX_INFO */
+
+	case US_GET_TX_UPDATE: {
+		struct usf_xx_type *usf_xx = &usf->usf_tx;
+
+		if (usf_xx->usf_state == USF_WORK_STATE)
+			rc = usf_get_tx_update(usf, arg);
+		else {
+			pr_err("%s: get_tx_update: wrong state[%d]\n", __func__,
+			       usf_xx->usf_state);
+			rc = -EBADFD;
+		}
+		break;
+	} /* US_GET_TX_UPDATE */
+
+	case US_SET_RX_UPDATE: {
+		struct usf_xx_type *usf_xx = &usf->usf_rx;
+
+		if (usf_xx->usf_state == USF_WORK_STATE)
+			rc = usf_set_rx_update(usf_xx, arg);
+		else {
+			pr_err("%s: set_rx_update: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			rc = -EBADFD;
+		}
+		break;
+	} /* US_SET_RX_UPDATE */
+
+	case US_STOP_TX: {
+		usf_xx = &usf->usf_tx;
+		if ((usf_xx->usf_state == USF_WORK_STATE)
+			|| (usf_xx->usf_state == USF_ADSP_RESTART_STATE))
+			rc = usf_stop_tx(usf);
+		else {
+			pr_err("%s: stop_tx: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			return -EBADFD;
+		}
+		break;
+	} /* US_STOP_TX */
+
+	case US_STOP_RX: {
+		usf_xx = &usf->usf_rx;
+		if ((usf_xx->usf_state == USF_WORK_STATE)
+			|| (usf_xx->usf_state == USF_ADSP_RESTART_STATE))
+			usf_disable(usf_xx);
+		else {
+			pr_err("%s: stop_rx: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			return -EBADFD;
+		}
+		break;
+	} /* US_STOP_RX */
+
+	case US_SET_DETECTION: {
+		struct usf_xx_type *usf_xx = &usf->usf_tx;
+
+		if (usf_xx->usf_state == USF_WORK_STATE)
+			rc = usf_set_us_detection(usf, arg);
+		else {
+			pr_err("%s: set us detection: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			rc = -EBADFD;
+		}
+		break;
+	} /* US_SET_DETECTION */
+
+	case US_GET_VERSION: {
+		rc = usf_get_version(arg);
+		break;
+	} /* US_GET_VERSION */
+
+	case US_SET_TX_STREAM_PARAM: {
+		rc = usf_set_stream_param(&usf->usf_tx, arg, OUT);
+		break;
+	} /* US_SET_TX_STREAM_PARAM */
+
+	case US_GET_TX_STREAM_PARAM: {
+		rc = usf_get_stream_param(&usf->usf_tx, arg, OUT);
+		break;
+	} /* US_GET_TX_STREAM_PARAM */
+
+	case US_SET_RX_STREAM_PARAM: {
+		rc = usf_set_stream_param(&usf->usf_rx, arg, IN);
+		break;
+	} /* US_SET_RX_STREAM_PARAM */
+
+	case US_GET_RX_STREAM_PARAM: {
+		rc = usf_get_stream_param(&usf->usf_rx, arg, IN);
+		break;
+	} /* US_GET_RX_STREAM_PARAM */
+
+	default:
+		pr_err("%s: unsupported IOCTL command [%d]\n",
+		       __func__,
+		       cmd);
+		rc = -ENOTTY;
+		break;
+	}
+
+	if (rc &&
+	    ((cmd == US_SET_TX_INFO) ||
+	     (cmd == US_SET_RX_INFO)))
+		release_xx(usf_xx);
+
+	return rc;
+} /* __usf_ioctl */
+
+static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct usf_type *usf = file->private_data;
+	int rc = 0;
+
+	mutex_lock(&usf->mutex);
+	rc = __usf_ioctl(usf, cmd, arg);
+	mutex_unlock(&usf->mutex);
+
+	return rc;
+} /* usf_ioctl */
+
+#ifdef CONFIG_COMPAT
+
+#define US_SET_TX_INFO32   _IOW(USF_IOCTL_MAGIC, 0, \
+				struct us_tx_info_type32)
+#define US_GET_TX_UPDATE32 _IOWR(USF_IOCTL_MAGIC, 2, \
+				struct us_tx_update_info_type32)
+#define US_SET_RX_INFO32   _IOW(USF_IOCTL_MAGIC, 3, \
+				struct us_rx_info_type32)
+#define US_SET_RX_UPDATE32 _IOWR(USF_IOCTL_MAGIC, 4, \
+				struct us_rx_update_info_type32)
+#define US_SET_DETECTION32 _IOWR(USF_IOCTL_MAGIC, 8, \
+				struct us_detect_info_type32)
+#define US_GET_VERSION32  _IOWR(USF_IOCTL_MAGIC, 9, \
+				struct us_version_info_type32)
+#define US_SET_TX_STREAM_PARAM32   _IOW(USF_IOCTL_MAGIC, 10, \
+				struct us_stream_param_type32)
+#define US_GET_TX_STREAM_PARAM32  _IOWR(USF_IOCTL_MAGIC, 11, \
+				struct us_stream_param_type32)
+#define US_SET_RX_STREAM_PARAM32   _IOW(USF_IOCTL_MAGIC, 12, \
+				struct us_stream_param_type32)
+#define US_GET_RX_STREAM_PARAM32  _IOWR(USF_IOCTL_MAGIC, 13, \
+				struct us_stream_param_type32)
+
+/* Info structure common for TX and RX */
+struct us_xx_info_type32 {
+/* Input:  general info */
+/* Name of the client - event calculator, ptr to char */
+	const compat_uptr_t client_name;
+/* Selected device identification, accepted in the kernel's CAD */
+	uint32_t dev_id;
+/* 0 - point_epos type; (e.g. 1 - gr_mmrd) */
+	uint32_t stream_format;
+/* Required sample rate in Hz */
+	uint32_t sample_rate;
+/* Size of a buffer (bytes) for US data transfer between the module and USF */
+	uint32_t buf_size;
+/* Number of the buffers for the US data transfer */
+	uint16_t buf_num;
+/* Number of the microphones (TX) or speakers(RX) */
+	uint16_t port_cnt;
+/* Microphones(TX) or speakers(RX) indexes in their enumeration */
+	uint8_t  port_id[USF_MAX_PORT_NUM];
+/* Bits per sample 16 or 32 */
+	uint16_t bits_per_sample;
+/* Input:  Transparent info for encoder in the LPASS */
+/* Parameters data size in bytes */
+	uint16_t params_data_size;
+/* Pointer to the parameters, ptr to uint8_t */
+	compat_uptr_t params_data;
+/* Max size of buffer for get and set parameter */
+	uint32_t max_get_set_param_buf_size;
+};
+
+struct us_tx_info_type32 {
+/* Common info. This struct includes ptr and therefore the 32 version */
+	struct us_xx_info_type32 us_xx_info;
+/* Info specific for TX. This struct doesn't include long or ptr
+ * and therefore no 32 version
+ */
+	struct us_input_info_type input_info;
+};
+
+struct us_tx_update_info_type32 {
+/* Input  general: */
+/* Number of calculated events */
+	uint16_t event_counter;
+/* Calculated events or NULL, ptr to struct usf_event_type */
+	compat_uptr_t event;
+/* Pointer (read index) to the end of available region */
+/* in the shared US data memory */
+	uint32_t free_region;
+/* Time (sec) to wait for data or special values: */
+/* USF_NO_WAIT_TIMEOUT, USF_INFINITIVE_TIMEOUT, USF_DEFAULT_TIMEOUT */
+	uint32_t timeout;
+/* Events (from conflicting devs) to be disabled/enabled */
+	uint16_t event_filters;
+
+/* Input  transparent data: */
+/* Parameters size */
+	uint16_t params_data_size;
+/* Pointer to the parameters, ptr to uint8_t */
+	compat_uptr_t params_data;
+/* Output parameters: */
+/* Pointer (write index) to the end of ready US data region */
+/* in the shared memory */
+	uint32_t ready_region;
+};
+
+struct us_rx_info_type32 {
+	/* Common info */
+	struct us_xx_info_type32 us_xx_info;
+	/* Info specific for RX*/
+};
+
+struct us_rx_update_info_type32 {
+/* Input  general: */
+/* Pointer (write index) to the end of ready US data region */
+/* in the shared memory */
+	uint32_t ready_region;
+/* Input  transparent data: */
+/* Parameters size */
+	uint16_t params_data_size;
+/* pPointer to the parameters, ptr to uint8_t */
+	compat_uptr_t params_data;
+/* Output parameters: */
+/* Pointer (read index) to the end of available region */
+/* in the shared US data memory */
+	uint32_t free_region;
+};
+
+struct us_detect_info_type32 {
+/* US detection place (HW|FW) */
+/* NA in the Active and OFF states */
+	enum us_detect_place_enum us_detector;
+/* US detection mode */
+	enum us_detect_mode_enum  us_detect_mode;
+/* US data dropped during this time (msec) */
+	uint32_t skip_time;
+/* Transparent data size */
+	uint16_t params_data_size;
+/* Pointer to the transparent data, ptr to uint8_t */
+	compat_uptr_t params_data;
+/* Time (sec) to wait for US presence event */
+	uint32_t detect_timeout;
+/* Out parameter: US presence */
+	bool is_us;
+};
+
+struct us_version_info_type32 {
+/* Size of memory for the version string */
+	uint16_t buf_size;
+/* Pointer to the memory for the version string, ptr to char */
+	compat_uptr_t pbuf;
+};
+
+struct us_stream_param_type32 {
+/* Id of module */
+	uint32_t module_id;
+/* Id of parameter */
+	uint32_t param_id;
+/* Size of memory of the parameter buffer */
+	uint32_t buf_size;
+/* Pointer to the memory of the parameter buffer */
+	compat_uptr_t pbuf;
+};
+
+static void usf_compat_xx_info_type(struct us_xx_info_type32 *us_xx_info32,
+				   struct us_xx_info_type *us_xx_info)
+{
+	int i = 0;
+
+	us_xx_info->client_name = compat_ptr(us_xx_info32->client_name);
+	us_xx_info->dev_id = us_xx_info32->dev_id;
+	us_xx_info->stream_format = us_xx_info32->stream_format;
+	us_xx_info->sample_rate = us_xx_info32->sample_rate;
+	us_xx_info->buf_size = us_xx_info32->buf_size;
+	us_xx_info->buf_num = us_xx_info32->buf_num;
+	us_xx_info->port_cnt = us_xx_info32->port_cnt;
+	for (i = 0; i < USF_MAX_PORT_NUM; i++)
+		us_xx_info->port_id[i] = us_xx_info32->port_id[i];
+	us_xx_info->bits_per_sample = us_xx_info32->bits_per_sample;
+	us_xx_info->params_data_size = us_xx_info32->params_data_size;
+	us_xx_info->params_data = compat_ptr(us_xx_info32->params_data);
+	us_xx_info->max_get_set_param_buf_size =
+			    us_xx_info32->max_get_set_param_buf_size;
+}
+
+static int usf_set_tx_info32(struct usf_type *usf, unsigned long arg)
+{
+	struct us_tx_info_type32 config_tx32;
+	struct us_tx_info_type config_tx;
+
+	int rc = copy_from_user(&config_tx32,
+			    (struct us_tx_info_type32 __user *) arg,
+			    sizeof(config_tx32));
+
+	if (rc) {
+		pr_err("%s: copy config_tx from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+	memset(&config_tx, 0, sizeof(config_tx));
+	usf_compat_xx_info_type(&(config_tx32.us_xx_info),
+				&(config_tx.us_xx_info));
+	config_tx.input_info = config_tx32.input_info;
+
+	return __usf_set_tx_info(usf, &config_tx);
+} /* usf_set_tx_info 32*/
+
+static int usf_set_rx_info32(struct usf_type *usf, unsigned long arg)
+{
+	struct us_rx_info_type32 config_rx32;
+	struct us_rx_info_type config_rx;
+
+	int rc = copy_from_user(&config_rx32,
+				(struct us_rx_info_type32 __user *) arg,
+				sizeof(config_rx32));
+
+	if (rc) {
+		pr_err("%s: copy config_rx from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+	memset(&config_rx, 0, sizeof(config_rx));
+	usf_compat_xx_info_type(&(config_rx32.us_xx_info),
+				&(config_rx.us_xx_info));
+
+	return __usf_set_rx_info(usf, &config_rx);
+} /* usf_set_rx_info32 */
+
+static int usf_get_tx_update32(struct usf_type *usf, unsigned long arg)
+{
+	struct us_tx_update_info_type32 upd_tx_info32;
+	struct us_tx_update_info_type upd_tx_info;
+
+	int rc = copy_from_user(&upd_tx_info32,
+				(struct us_tx_update_info_type32 __user *) arg,
+				sizeof(upd_tx_info32));
+
+	if (rc) {
+		pr_err("%s: copy upd_tx_info32 from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	memset(&upd_tx_info, 0, sizeof(upd_tx_info));
+	upd_tx_info.event_counter = upd_tx_info32.event_counter;
+	upd_tx_info.event = compat_ptr(upd_tx_info32.event);
+	upd_tx_info.free_region = upd_tx_info32.free_region;
+	upd_tx_info.timeout = upd_tx_info32.timeout;
+	upd_tx_info.event_filters = upd_tx_info32.event_filters;
+	upd_tx_info.params_data_size = upd_tx_info32.params_data_size;
+	upd_tx_info.params_data = compat_ptr(upd_tx_info32.params_data);
+	upd_tx_info.ready_region = upd_tx_info32.ready_region;
+
+	rc = __usf_get_tx_update(usf, &upd_tx_info);
+	if (rc < 0) {
+		pr_err("%s: get tx update failed; rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	/* Update only the fields that were changed */
+	upd_tx_info32.ready_region = upd_tx_info.ready_region;
+
+	rc = copy_to_user((void __user *)arg, &upd_tx_info32,
+			  sizeof(upd_tx_info32));
+	if (rc) {
+		pr_err("%s: copy upd_tx_info32 to user; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	return rc;
+} /* usf_get_tx_update */
+
+static int usf_set_rx_update32(struct usf_xx_type *usf_xx, unsigned long arg)
+{
+	struct us_rx_update_info_type32 upd_rx_info32;
+	struct us_rx_update_info_type upd_rx_info;
+
+	int rc = copy_from_user(&upd_rx_info32,
+				(struct us_rx_update_info_type32 __user *) arg,
+				sizeof(upd_rx_info32));
+
+	if (rc) {
+		pr_err("%s: copy upd_rx_info32 from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	memset(&upd_rx_info, 0, sizeof(upd_rx_info));
+	upd_rx_info.ready_region = upd_rx_info32.ready_region;
+	upd_rx_info.params_data_size = upd_rx_info32.params_data_size;
+	upd_rx_info.params_data = compat_ptr(upd_rx_info32.params_data);
+	upd_rx_info.free_region = upd_rx_info32.free_region;
+
+	rc = __usf_set_rx_update(usf_xx, &upd_rx_info);
+	if (rc < 0) {
+		pr_err("%s: set rx update failed; rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	/* Update only the fields that were changed */
+	upd_rx_info32.free_region = upd_rx_info.free_region;
+
+	rc = copy_to_user((void __user *)arg,
+			&upd_rx_info32,
+			sizeof(upd_rx_info32));
+	if (rc) {
+		pr_err("%s: copy rx_info32 to user; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	return rc;
+} /* usf_set_rx_update32 */
+
+static int usf_set_us_detection32(struct usf_type *usf, unsigned long arg)
+{
+	struct us_detect_info_type32 detect_info32;
+	struct us_detect_info_type detect_info;
+
+	int rc = copy_from_user(&detect_info32,
+				(struct us_detect_info_type32 __user *) arg,
+				sizeof(detect_info32));
+
+	if (rc) {
+		pr_err("%s: copy detect_info32 from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	if (detect_info32.params_data_size > USF_MAX_USER_BUF_SIZE) {
+		pr_err("%s: user buffer size exceeds maximum\n",
+			__func__);
+		return -EFAULT;
+	}
+
+	memset(&detect_info, 0, sizeof(detect_info));
+	detect_info.us_detector = detect_info32.us_detector;
+	detect_info.us_detect_mode = detect_info32.us_detect_mode;
+	detect_info.skip_time = detect_info32.skip_time;
+	detect_info.params_data_size = detect_info32.params_data_size;
+	detect_info.params_data = compat_ptr(detect_info32.params_data);
+	detect_info.detect_timeout = detect_info32.detect_timeout;
+	detect_info.is_us = detect_info32.is_us;
+
+	rc = __usf_set_us_detection(usf, &detect_info);
+	if (rc < 0) {
+		pr_err("%s: set us detection failed; rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	/* Update only the fields that were changed */
+	detect_info32.is_us = detect_info.is_us;
+
+	rc = copy_to_user((void __user *)arg,
+			  &detect_info32,
+			  sizeof(detect_info32));
+	if (rc) {
+		pr_err("%s: copy detect_info32 to user; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	return rc;
+} /* usf_set_us_detection32 */
+
+static int usf_get_version32(unsigned long arg)
+{
+	struct us_version_info_type32 version_info32;
+	struct us_version_info_type version_info;
+
+	int rc = copy_from_user(&version_info32,
+				(struct us_version_info_type32 __user *) arg,
+				sizeof(version_info32));
+
+	if (rc) {
+		pr_err("%s: copy version_info32 from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	memset(&version_info, 0, sizeof(version_info));
+	version_info.buf_size = version_info32.buf_size;
+	version_info.pbuf = compat_ptr(version_info32.pbuf);
+
+	rc = __usf_get_version(&version_info);
+	if (rc < 0) {
+		pr_err("%s: get version failed; rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	/* None of the fields were changed */
+
+	rc = copy_to_user((void __user *)arg,
+			  &version_info32,
+			  sizeof(version_info32));
+	if (rc) {
+		pr_err("%s: copy version_info32 to user; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	return rc;
+} /* usf_get_version32 */
+
+static int usf_set_stream_param32(struct usf_xx_type *usf_xx,
+				unsigned long arg, int dir)
+{
+	struct us_stream_param_type32 set_stream_param32;
+	struct us_stream_param_type set_stream_param;
+	int rc = 0;
+
+	rc = copy_from_user(&set_stream_param32,
+			(struct us_stream_param_type32 __user *) arg,
+			sizeof(set_stream_param32));
+
+	if (rc) {
+		pr_err("%s: copy set_stream_param from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	memset(&set_stream_param, 0, sizeof(set_stream_param));
+	set_stream_param.module_id = set_stream_param32.module_id;
+	set_stream_param.param_id = set_stream_param32.param_id;
+	set_stream_param.buf_size = set_stream_param32.buf_size;
+	set_stream_param.pbuf = compat_ptr(set_stream_param32.pbuf);
+
+	return __usf_set_stream_param(usf_xx, &set_stream_param, dir);
+} /* usf_set_stream_param32 */
+
+static int usf_get_stream_param32(struct usf_xx_type *usf_xx,
+				unsigned long arg, int dir)
+{
+	struct us_stream_param_type32 get_stream_param32;
+	struct us_stream_param_type get_stream_param;
+	int rc = 0;
+
+	rc = copy_from_user(&get_stream_param32,
+			(struct us_stream_param_type32 __user *) arg,
+			sizeof(get_stream_param32));
+
+	if (rc) {
+		pr_err("%s: copy get_stream_param from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	memset(&get_stream_param, 0, sizeof(get_stream_param));
+	get_stream_param.module_id = get_stream_param32.module_id;
+	get_stream_param.param_id = get_stream_param32.param_id;
+	get_stream_param.buf_size = get_stream_param32.buf_size;
+	get_stream_param.pbuf = compat_ptr(get_stream_param32.pbuf);
+
+	return __usf_get_stream_param(usf_xx, &get_stream_param, dir);
+} /* usf_get_stream_param32 */
+
+static long __usf_compat_ioctl(struct usf_type *usf,
+			     unsigned int cmd,
+			     unsigned long arg)
+{
+	int rc = 0;
+	struct usf_xx_type *usf_xx = NULL;
+
+	switch (cmd) {
+	case US_START_TX:
+	case US_START_RX:
+	case US_STOP_TX:
+	case US_STOP_RX: {
+		return __usf_ioctl(usf, cmd, arg);
+	}
+
+	case US_SET_TX_INFO32: {
+		usf_xx = &usf->usf_tx;
+		if (usf_xx->usf_state == USF_OPENED_STATE)
+			rc = usf_set_tx_info32(usf, arg);
+		else {
+			pr_err("%s: set_tx_info32: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			return -EBADFD;
+		}
+
+		break;
+	} /* US_SET_TX_INFO32 */
+
+	case US_SET_RX_INFO32: {
+		usf_xx = &usf->usf_rx;
+		if (usf_xx->usf_state == USF_OPENED_STATE)
+			rc = usf_set_rx_info32(usf, arg);
+		else {
+			pr_err("%s: set_rx_info32: wrong state[%d]\n",
+				__func__,
+				usf_xx->usf_state);
+			return -EBADFD;
+		}
+
+		break;
+	} /* US_SET_RX_INFO32 */
+
+	case US_GET_TX_UPDATE32: {
+		struct usf_xx_type *usf_xx = &usf->usf_tx;
+
+		if (usf_xx->usf_state == USF_WORK_STATE)
+			rc = usf_get_tx_update32(usf, arg);
+		else {
+			pr_err("%s: get_tx_update32: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			rc = -EBADFD;
+		}
+		break;
+	} /* US_GET_TX_UPDATE32 */
+
+	case US_SET_RX_UPDATE32: {
+		struct usf_xx_type *usf_xx = &usf->usf_rx;
+
+		if (usf_xx->usf_state == USF_WORK_STATE)
+			rc = usf_set_rx_update32(usf_xx, arg);
+		else {
+			pr_err("%s: set_rx_update: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			rc = -EBADFD;
+		}
+		break;
+	} /* US_SET_RX_UPDATE32 */
+
+	case US_SET_DETECTION32: {
+		struct usf_xx_type *usf_xx = &usf->usf_tx;
+
+		if (usf_xx->usf_state == USF_WORK_STATE)
+			rc = usf_set_us_detection32(usf, arg);
+		else {
+			pr_err("%s: set us detection: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			rc = -EBADFD;
+		}
+		break;
+	} /* US_SET_DETECTION32 */
+
+	case US_GET_VERSION32: {
+		rc = usf_get_version32(arg);
+		break;
+	} /* US_GET_VERSION32 */
+
+	case US_SET_TX_STREAM_PARAM32: {
+		rc = usf_set_stream_param32(&usf->usf_tx, arg, OUT);
+		break;
+	} /* US_SET_TX_STREAM_PARAM32 */
+
+	case US_GET_TX_STREAM_PARAM32: {
+		rc = usf_get_stream_param32(&usf->usf_tx, arg, OUT);
+		break;
+	} /* US_GET_TX_STREAM_PARAM32 */
+
+	case US_SET_RX_STREAM_PARAM32: {
+		rc = usf_set_stream_param32(&usf->usf_rx, arg, IN);
+		break;
+	} /* US_SET_RX_STREAM_PARAM32 */
+
+	case US_GET_RX_STREAM_PARAM32: {
+		rc = usf_get_stream_param32(&usf->usf_rx, arg, IN);
+		break;
+	} /* US_GET_RX_STREAM_PARAM32 */
+
+	default:
+		pr_err("%s: unsupported IOCTL command [%d]\n",
+		       __func__,
+		       cmd);
+		rc = -ENOTTY;
+		break;
+	}
+
+	if (rc &&
+	    ((cmd == US_SET_TX_INFO) ||
+	     (cmd == US_SET_RX_INFO)))
+		release_xx(usf_xx);
+
+	return rc;
+} /* __usf_compat_ioctl */
+
+static long usf_compat_ioctl(struct file *file,
+			     unsigned int cmd,
+			     unsigned long arg)
+{
+	struct usf_type *usf = file->private_data;
+	int rc = 0;
+
+	mutex_lock(&usf->mutex);
+	rc = __usf_compat_ioctl(usf, cmd, arg);
+	mutex_unlock(&usf->mutex);
+
+	return rc;
+} /* usf_compat_ioctl */
+#endif /* CONFIG_COMPAT */
+
+static int usf_mmap(struct file *file, struct vm_area_struct *vms)
+{
+	struct usf_type *usf = file->private_data;
+	int dir = OUT;
+	struct usf_xx_type *usf_xx = &usf->usf_tx;
+	int rc = 0;
+
+	mutex_lock(&usf->mutex);
+	if (vms->vm_flags & USF_VM_WRITE) { /* RX buf mapping */
+		dir = IN;
+		usf_xx = &usf->usf_rx;
+	}
+	rc = q6usm_get_virtual_address(dir, usf_xx->usc, vms);
+	mutex_unlock(&usf->mutex);
+
+	return rc;
+}
+
+static uint16_t add_opened_dev(int minor)
+{
+	uint16_t ind = 0;
+
+	for (ind = 0; ind < MAX_DEVS_NUMBER; ++ind) {
+		if (minor == atomic_cmpxchg(&s_opened_devs[ind], 0, minor)) {
+			pr_err("%s: device %d is already opened\n",
+			       __func__, minor);
+			return USF_UNDEF_DEV_ID;
+		} else {
+			pr_debug("%s: device %d is added; ind=%d\n",
+				__func__, minor, ind);
+			return ind;
+		}
+	}
+
+	pr_err("%s: there is no place for device %d\n",
+	       __func__, minor);
+	return USF_UNDEF_DEV_ID;
+}
+
+static int usf_open(struct inode *inode, struct file *file)
+{
+	struct usf_type *usf =  NULL;
+	uint16_t dev_ind = 0;
+	int minor = MINOR(inode->i_rdev);
+
+	dev_ind = add_opened_dev(minor);
+	if (dev_ind == USF_UNDEF_DEV_ID)
+		return -EBUSY;
+
+	usf = kzalloc(sizeof(struct usf_type), GFP_KERNEL);
+	if (usf == NULL)
+		return -ENOMEM;
+
+	wakeup_source_init(&usf_wakeup_source, "usf");
+
+	file->private_data = usf;
+	usf->dev_ind = dev_ind;
+
+	usf->usf_tx.usf_state = USF_OPENED_STATE;
+	usf->usf_rx.usf_state = USF_OPENED_STATE;
+
+	usf->usf_tx.us_detect_type = USF_US_DETECT_UNDEF;
+	usf->usf_rx.us_detect_type = USF_US_DETECT_UNDEF;
+
+	mutex_init(&usf->mutex);
+
+	pr_debug("%s:usf in open\n", __func__);
+	return 0;
+}
+
+static int usf_release(struct inode *inode, struct file *file)
+{
+	struct usf_type *usf = file->private_data;
+
+	pr_debug("%s: release entry\n", __func__);
+
+	mutex_lock(&usf->mutex);
+	usf_release_input(usf);
+
+	usf_disable(&usf->usf_tx);
+	usf_disable(&usf->usf_rx);
+
+	atomic_set(&s_opened_devs[usf->dev_ind], 0);
+
+	wakeup_source_trash(&usf_wakeup_source);
+	mutex_unlock(&usf->mutex);
+	mutex_destroy(&usf->mutex);
+	kfree(usf);
+	pr_debug("%s: release exit\n", __func__);
+	return 0;
+}
+
+extern long usf_compat_ioctl(struct file *file,
+			     unsigned int cmd,
+			     unsigned long arg);
+
+static const struct file_operations usf_fops = {
+	.owner                  = THIS_MODULE,
+	.open                   = usf_open,
+	.release                = usf_release,
+	.unlocked_ioctl = usf_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = usf_compat_ioctl,
+#endif /* CONFIG_COMPAT */
+	.mmap                   = usf_mmap,
+};
+
+static struct miscdevice usf_misc[MAX_DEVS_NUMBER] = {
+	{
+		.minor  = MISC_DYNAMIC_MINOR,
+		.name   = "usf1",
+		.fops   = &usf_fops,
+	},
+};
+
+static int __init usf_init(void)
+{
+	int rc = 0;
+	uint16_t ind = 0;
+
+	pr_debug("%s: USF SW version %s.\n", __func__, DRV_VERSION);
+	pr_debug("%s: Max %d devs registration\n", __func__, MAX_DEVS_NUMBER);
+
+	for (ind = 0; ind < MAX_DEVS_NUMBER; ++ind) {
+		rc = misc_register(&usf_misc[ind]);
+		if (rc) {
+			pr_err("%s: misc_register() failed ind=%d; rc = %d\n",
+			       __func__, ind, rc);
+			break;
+		}
+	}
+
+	return rc;
+}
+
+device_initcall(usf_init);
+
+MODULE_DESCRIPTION("Ultrasound framework driver");

+ 422 - 0
drivers/misc/qcom/qdsp6v2/ultrasound/usfcdev.c

@@ -0,0 +1,422 @@
+/* Copyright (c) 2012-2013, 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/sched.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input/mt.h>
+#include <linux/syscalls.h>
+#include "usfcdev.h"
+
+#define UNDEF_ID    0xffffffff
+#define SLOT_CMD_ID 0
+#define MAX_RETRIES 10
+
+enum usdev_event_status {
+	USFCDEV_EVENT_ENABLED,
+	USFCDEV_EVENT_DISABLING,
+	USFCDEV_EVENT_DISABLED,
+};
+
+struct usfcdev_event {
+	bool (*match_cb)(uint16_t, struct input_dev *dev);
+	bool registered_event;
+	bool interleaved;
+	enum usdev_event_status event_status;
+};
+static struct usfcdev_event s_usfcdev_events[MAX_EVENT_TYPE_NUM];
+
+struct usfcdev_input_command {
+	unsigned int type;
+	unsigned int code;
+	unsigned int value;
+};
+
+static long  s_usf_pid;
+
+static bool usfcdev_filter(struct input_handle *handle,
+			 unsigned int type, unsigned int code, int value);
+static bool usfcdev_match(struct input_handler *handler,
+				struct input_dev *dev);
+static int usfcdev_connect(struct input_handler *handler,
+				struct input_dev *dev,
+				const struct input_device_id *id);
+static void usfcdev_disconnect(struct input_handle *handle);
+
+static const struct input_device_id usfc_tsc_ids[] = {
+	{
+		.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+			INPUT_DEVICE_ID_MATCH_KEYBIT |
+			INPUT_DEVICE_ID_MATCH_ABSBIT,
+		.evbit = { BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY) },
+		.keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
+		/* assumption: ABS_X & ABS_Y are in the same long */
+		.absbit = { [BIT_WORD(ABS_X)] = BIT_MASK(ABS_X) |
+						BIT_MASK(ABS_Y) },
+	},
+	{
+		.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+			INPUT_DEVICE_ID_MATCH_KEYBIT |
+			INPUT_DEVICE_ID_MATCH_ABSBIT,
+		.evbit = { BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY) },
+		.keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
+		/* assumption: MT_.._X & MT_.._Y are in the same long */
+		.absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
+			BIT_MASK(ABS_MT_POSITION_X) |
+			BIT_MASK(ABS_MT_POSITION_Y) },
+	},
+	{ } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, usfc_tsc_ids);
+
+static struct input_handler s_usfc_handlers[MAX_EVENT_TYPE_NUM] = {
+	{ /* TSC handler */
+		.filter         = usfcdev_filter,
+		.match          = usfcdev_match,
+		.connect        = usfcdev_connect,
+		.disconnect     = usfcdev_disconnect,
+		/* .minor can be used as index in the container, */
+		/*  because .fops isn't supported */
+		.minor          = TSC_EVENT_TYPE_IND,
+		.name           = "usfc_tsc_handler",
+		.id_table       = usfc_tsc_ids,
+	},
+};
+
+/*
+ * For each event type, there are a number conflicting devices (handles)
+ * The first registered device (primary) is real TSC device; it's mandatory
+ * Optionally, later registered devices are simulated ones.
+ * They are dynamically managed
+ * The primary device's handles are stored in the below static array
+ */
+static struct input_handle s_usfc_primary_handles[MAX_EVENT_TYPE_NUM] = {
+	{ /* TSC handle */
+		.handler	= &s_usfc_handlers[TSC_EVENT_TYPE_IND],
+		.name		= "usfc_tsc_handle",
+	},
+};
+
+static struct usfcdev_input_command initial_clear_cmds[] = {
+	{EV_ABS, ABS_PRESSURE,               0},
+	{EV_KEY, BTN_TOUCH,                  0},
+};
+
+static struct usfcdev_input_command slot_clear_cmds[] = {
+	{EV_ABS, ABS_MT_SLOT,               0},
+	{EV_ABS, ABS_MT_TRACKING_ID, UNDEF_ID},
+};
+
+static struct usfcdev_input_command no_filter_cmds[] = {
+	{EV_ABS, ABS_MT_SLOT,               0},
+	{EV_ABS, ABS_MT_TRACKING_ID, UNDEF_ID},
+	{EV_SYN, SYN_REPORT,                0},
+};
+
+static bool usfcdev_match(struct input_handler *handler, struct input_dev *dev)
+{
+	bool rc = false;
+	int ind = handler->minor;
+
+	pr_debug("%s: name=[%s]; ind=%d\n", __func__, dev->name, ind);
+
+	if (s_usfcdev_events[ind].registered_event &&
+		s_usfcdev_events[ind].match_cb) {
+		rc = (*s_usfcdev_events[ind].match_cb)((uint16_t)ind, dev);
+		pr_debug("%s: [%s]; rc=%d\n", __func__, dev->name, rc);
+	}
+	return rc;
+}
+
+static int usfcdev_connect(struct input_handler *handler, struct input_dev *dev,
+				const struct input_device_id *id)
+{
+	int ret = 0;
+	uint16_t ind = handler->minor;
+	struct input_handle *usfc_handle = NULL;
+
+	if (s_usfc_primary_handles[ind].dev == NULL) {
+		pr_debug("%s: primary device; ind=%d\n",
+			__func__,
+			ind);
+		usfc_handle = &s_usfc_primary_handles[ind];
+	} else {
+		pr_debug("%s: secondary device; ind=%d\n",
+			__func__,
+			ind);
+		usfc_handle = kzalloc(sizeof(struct input_handle),
+					GFP_KERNEL);
+		if (!usfc_handle)
+			return -ENOMEM;
+
+		usfc_handle->handler = &s_usfc_handlers[ind];
+		usfc_handle->name = s_usfc_primary_handles[ind].name;
+	}
+	usfc_handle->dev = dev;
+	ret = input_register_handle(usfc_handle);
+	pr_debug("%s: name=[%s]; ind=%d; dev=0x%pK\n",
+		 __func__,
+		dev->name,
+		ind,
+		usfc_handle->dev);
+	if (ret)
+		pr_err("%s: input_register_handle[%d] failed: ret=%d\n",
+			__func__,
+			ind,
+			ret);
+	else {
+		ret = input_open_device(usfc_handle);
+		if (ret) {
+			pr_err("%s: input_open_device[%d] failed: ret=%d\n",
+				__func__,
+				ind,
+				ret);
+			input_unregister_handle(usfc_handle);
+		} else
+			pr_debug("%s: device[%d] is opened\n",
+				__func__,
+				ind);
+	}
+
+	return ret;
+}
+
+static void usfcdev_disconnect(struct input_handle *handle)
+{
+	int ind = handle->handler->minor;
+
+	input_close_device(handle);
+	input_unregister_handle(handle);
+	pr_debug("%s: handle[%d], name=[%s] is disconnected\n",
+		__func__,
+		ind,
+		handle->dev->name);
+	if (s_usfc_primary_handles[ind].dev == handle->dev)
+		s_usfc_primary_handles[ind].dev = NULL;
+	else
+		kfree(handle);
+}
+
+static bool usfcdev_filter(struct input_handle *handle,
+			unsigned int type, unsigned int code, int value)
+{
+	uint16_t i = 0;
+	uint16_t ind = (uint16_t)handle->handler->minor;
+	bool rc = (s_usfcdev_events[ind].event_status != USFCDEV_EVENT_ENABLED);
+
+	if (s_usf_pid == sys_getpid()) {
+		/* Pass events from usfcdev driver */
+		rc = false;
+		pr_debug("%s: event_type=%d; type=%d; code=%d; val=%d",
+			__func__,
+			ind,
+			type,
+			code,
+			value);
+	} else if (s_usfcdev_events[ind].event_status ==
+						USFCDEV_EVENT_DISABLING) {
+		uint32_t u_value = value;
+
+		s_usfcdev_events[ind].interleaved = true;
+		/* Pass events for freeing slots from TSC driver */
+		for (i = 0; i < ARRAY_SIZE(no_filter_cmds); ++i) {
+			if ((no_filter_cmds[i].type == type) &&
+			    (no_filter_cmds[i].code == code) &&
+			    (no_filter_cmds[i].value <= u_value)) {
+				rc = false;
+				pr_debug("%s: no_filter_cmds[%d]; %d",
+					__func__,
+					i,
+					no_filter_cmds[i].value);
+				break;
+			}
+		}
+	}
+
+	return rc;
+}
+
+bool usfcdev_register(
+	uint16_t event_type_ind,
+	bool (*match_cb)(uint16_t, struct input_dev *dev))
+{
+	int ret = 0;
+	bool rc = false;
+
+	if ((event_type_ind >= MAX_EVENT_TYPE_NUM) || !match_cb) {
+		pr_err("%s: wrong input: event_type_ind=%d; match_cb=0x%pK\n",
+			__func__,
+			event_type_ind,
+			match_cb);
+		return false;
+	}
+
+	if (s_usfcdev_events[event_type_ind].registered_event) {
+		pr_info("%s: handler[%d] was already registered\n",
+			__func__,
+			event_type_ind);
+		return true;
+	}
+
+	s_usfcdev_events[event_type_ind].registered_event = true;
+	s_usfcdev_events[event_type_ind].match_cb = match_cb;
+	s_usfcdev_events[event_type_ind].event_status = USFCDEV_EVENT_ENABLED;
+	ret = input_register_handler(&s_usfc_handlers[event_type_ind]);
+	if (!ret) {
+		rc = true;
+		pr_debug("%s: handler[%d] was registered\n",
+			__func__,
+			event_type_ind);
+	} else {
+		s_usfcdev_events[event_type_ind].registered_event = false;
+		s_usfcdev_events[event_type_ind].match_cb = NULL;
+		pr_err("%s: handler[%d] registration failed: ret=%d\n",
+			__func__,
+			event_type_ind,
+			ret);
+	}
+
+	return rc;
+}
+
+void usfcdev_unregister(uint16_t event_type_ind)
+{
+	if (event_type_ind >= MAX_EVENT_TYPE_NUM) {
+		pr_err("%s: wrong input: event_type_ind=%d\n",
+			__func__,
+			event_type_ind);
+		return;
+	}
+	if (s_usfcdev_events[event_type_ind].registered_event) {
+		input_unregister_handler(&s_usfc_handlers[event_type_ind]);
+		pr_debug("%s: handler[%d] was unregistered\n",
+			__func__,
+			event_type_ind);
+		s_usfcdev_events[event_type_ind].registered_event = false;
+		s_usfcdev_events[event_type_ind].match_cb = NULL;
+		s_usfcdev_events[event_type_ind].event_status =
+							USFCDEV_EVENT_ENABLED;
+
+	}
+}
+
+static inline void usfcdev_send_cmd(
+	struct input_dev *dev,
+	struct usfcdev_input_command cmd)
+{
+	input_event(dev, cmd.type, cmd.code, cmd.value);
+}
+
+static void usfcdev_clean_dev(uint16_t event_type_ind)
+{
+	struct input_dev *dev = NULL;
+	int i;
+	int j;
+	int retries = 0;
+
+	if (event_type_ind >= MAX_EVENT_TYPE_NUM) {
+		pr_err("%s: wrong input: event_type_ind=%d\n",
+			__func__,
+			event_type_ind);
+		return;
+	}
+	/* Only primary device must exist */
+	dev = s_usfc_primary_handles[event_type_ind].dev;
+	if (dev == NULL) {
+		pr_err("%s: NULL primary device\n",
+		__func__);
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(initial_clear_cmds); i++)
+		usfcdev_send_cmd(dev, initial_clear_cmds[i]);
+	input_sync(dev);
+
+	/* Send commands to free all slots */
+	for (i = 0; i < dev->mt->num_slots; i++) {
+		s_usfcdev_events[event_type_ind].interleaved = false;
+		if (input_mt_get_value(&dev->mt->slots[i],
+					ABS_MT_TRACKING_ID) < 0) {
+			pr_debug("%s: skipping slot %d",
+				__func__, i);
+			continue;
+		}
+		slot_clear_cmds[SLOT_CMD_ID].value = i;
+		for (j = 0; j < ARRAY_SIZE(slot_clear_cmds); j++)
+			usfcdev_send_cmd(dev, slot_clear_cmds[j]);
+
+		if (s_usfcdev_events[event_type_ind].interleaved) {
+			pr_debug("%s: interleaved(%d): slot(%d)",
+				__func__, i, dev->mt->slot);
+			if (retries++ < MAX_RETRIES) {
+				--i;
+				continue;
+			}
+			pr_warn("%s: index(%d) reached max retires",
+				__func__, i);
+		}
+
+		retries = 0;
+		input_sync(dev);
+	}
+}
+
+bool usfcdev_set_filter(uint16_t event_type_ind, bool filter)
+{
+	bool rc = true;
+
+	if (event_type_ind >= MAX_EVENT_TYPE_NUM) {
+		pr_err("%s: wrong input: event_type_ind=%d\n",
+			__func__,
+			event_type_ind);
+		return false;
+	}
+
+	if (s_usfcdev_events[event_type_ind].registered_event) {
+
+		pr_debug("%s: event_type[%d]; filter=%d\n",
+			__func__,
+			event_type_ind,
+			filter
+			);
+		if (filter) {
+			s_usfcdev_events[event_type_ind].event_status =
+						USFCDEV_EVENT_DISABLING;
+			s_usf_pid = sys_getpid();
+			usfcdev_clean_dev(event_type_ind);
+			s_usfcdev_events[event_type_ind].event_status =
+						USFCDEV_EVENT_DISABLED;
+		} else
+			s_usfcdev_events[event_type_ind].event_status =
+						USFCDEV_EVENT_ENABLED;
+	} else {
+		pr_err("%s: event_type[%d] isn't registered\n",
+			__func__,
+			event_type_ind);
+		rc = false;
+	}
+
+	return rc;
+}
+
+static int __init usfcdev_init(void)
+{
+	return 0;
+}
+
+device_initcall(usfcdev_init);
+
+MODULE_DESCRIPTION("Handle of events from devices, conflicting with USF");

+ 28 - 0
drivers/misc/qcom/qdsp6v2/ultrasound/usfcdev.h

@@ -0,0 +1,28 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+#ifndef __USFCDEV_H__
+#define __USFCDEV_H__
+
+#include <linux/input.h>
+
+/* TSC event type index in the containers of the handlers & handles */
+#define TSC_EVENT_TYPE_IND 0
+/* Number of supported event types to be filtered */
+#define MAX_EVENT_TYPE_NUM 1
+
+bool usfcdev_register(
+	uint16_t event_type_ind,
+	bool (*match_cb)(uint16_t, struct input_dev *dev));
+void usfcdev_unregister(uint16_t event_type_ind);
+bool usfcdev_set_filter(uint16_t event_type_ind, bool filter);
+#endif /* __USFCDEV_H__ */

+ 2 - 0
drivers/pinctrl/Makefile

@@ -0,0 +1,2 @@
+
+obj-y		+= qcom/

+ 1 - 0
drivers/pinctrl/core.h

@@ -0,0 +1 @@
+../../../../drivers/pinctrl/core.h

+ 1 - 0
drivers/pinctrl/pinctrl-utils.h

@@ -0,0 +1 @@
+../../../../drivers/pinctrl/pinctrl-utils.h

+ 3 - 0
drivers/pinctrl/qcom/Makefile

@@ -0,0 +1,3 @@
+
+obj-$(CONFIG_PINCTRL_WCD)	+= pinctrl-wcd.o
+obj-$(CONFIG_PINCTRL_LPI)	+= pinctrl-lpi.o

+ 647 - 0
drivers/pinctrl/qcom/pinctrl-lpi.c

@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/qdsp6v2/audio_notifier.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#define LPI_ADDRESS_SIZE			0xC000
+
+#define LPI_GPIO_REG_VAL_CTL			0x00
+#define LPI_GPIO_REG_DIR_CTL			0x04
+
+#define LPI_GPIO_REG_PULL_SHIFT			0x0
+#define LPI_GPIO_REG_PULL_MASK			0x3
+
+#define LPI_GPIO_REG_FUNCTION_SHIFT		0x2
+#define LPI_GPIO_REG_FUNCTION_MASK		0x3C
+
+#define LPI_GPIO_REG_OUT_STRENGTH_SHIFT		0x6
+#define LPI_GPIO_REG_OUT_STRENGTH_MASK		0x1C0
+
+#define LPI_GPIO_REG_OE_SHIFT			0x9
+#define LPI_GPIO_REG_OE_MASK			0x200
+
+#define LPI_GPIO_REG_DIR_SHIFT			0x1
+#define LPI_GPIO_REG_DIR_MASK			0x2
+
+#define LPI_GPIO_BIAS_DISABLE			0x0
+#define LPI_GPIO_PULL_DOWN			0x1
+#define LPI_GPIO_KEEPER				0x2
+#define LPI_GPIO_PULL_UP			0x3
+
+#define LPI_GPIO_FUNC_GPIO			"gpio"
+#define LPI_GPIO_FUNC_FUNC1			"func1"
+#define LPI_GPIO_FUNC_FUNC2			"func2"
+#define LPI_GPIO_FUNC_FUNC3			"func3"
+#define LPI_GPIO_FUNC_FUNC4			"func4"
+#define LPI_GPIO_FUNC_FUNC5			"func5"
+
+static bool lpi_dev_up;
+
+/* The index of each function in lpi_gpio_functions[] array */
+enum lpi_gpio_func_index {
+	LPI_GPIO_FUNC_INDEX_GPIO	= 0x00,
+	LPI_GPIO_FUNC_INDEX_FUNC1	= 0x01,
+	LPI_GPIO_FUNC_INDEX_FUNC2	= 0x02,
+	LPI_GPIO_FUNC_INDEX_FUNC3	= 0x03,
+	LPI_GPIO_FUNC_INDEX_FUNC4	= 0x04,
+	LPI_GPIO_FUNC_INDEX_FUNC5	= 0x05,
+};
+
+/**
+ * struct lpi_gpio_pad - keep current GPIO settings
+ * @offset: Nth GPIO in supported GPIOs.
+ * @output_enabled: Set to true if GPIO output logic is enabled.
+ * @value: value of a pin
+ * @base: Address base of LPI GPIO PAD.
+ * @pullup: Constant current which flow through GPIO output buffer.
+ * @strength: No, Low, Medium, High
+ * @function: See lpi_gpio_functions[]
+ */
+struct lpi_gpio_pad {
+	u16		offset;
+	bool		output_enabled;
+	bool		value;
+	char __iomem	*base;
+	unsigned int	pullup;
+	unsigned int	strength;
+	unsigned int	function;
+};
+
+struct lpi_gpio_state {
+	struct device	*dev;
+	struct pinctrl_dev *ctrl;
+	struct gpio_chip chip;
+	char __iomem	*base;
+};
+
+static const char *const lpi_gpio_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+	"gpio29", "gpio30", "gpio31",
+};
+
+static const u32 lpi_offset[] = {
+	0x00000000,
+	0x00001000,
+	0x00002000,
+	0x00002010,
+	0x00003000,
+	0x00003010,
+	0x00004000,
+	0x00004010,
+	0x00005000,
+	0x00005010,
+	0x00005020,
+	0x00005030,
+	0x00006000,
+	0x00006010,
+	0x00007000,
+	0x00007010,
+	0x00005040,
+	0x00005050,
+	0x00008000,
+	0x00008010,
+	0x00008020,
+	0x00008030,
+	0x00008040,
+	0x00008050,
+	0x00008060,
+	0x00008070,
+	0x00009000,
+	0x00009010,
+	0x0000A000,
+	0x0000A010,
+	0x0000B000,
+	0x0000B010,
+};
+
+static const char *const lpi_gpio_functions[] = {
+	[LPI_GPIO_FUNC_INDEX_GPIO]	= LPI_GPIO_FUNC_GPIO,
+	[LPI_GPIO_FUNC_INDEX_FUNC1]	= LPI_GPIO_FUNC_FUNC1,
+	[LPI_GPIO_FUNC_INDEX_FUNC2]	= LPI_GPIO_FUNC_FUNC2,
+	[LPI_GPIO_FUNC_INDEX_FUNC3]	= LPI_GPIO_FUNC_FUNC3,
+	[LPI_GPIO_FUNC_INDEX_FUNC4]	= LPI_GPIO_FUNC_FUNC4,
+	[LPI_GPIO_FUNC_INDEX_FUNC5]	= LPI_GPIO_FUNC_FUNC5,
+};
+
+static int lpi_gpio_read(struct lpi_gpio_pad *pad, unsigned int addr)
+{
+	int ret;
+
+	if (!lpi_dev_up) {
+		pr_err_ratelimited("%s: ADSP is down due to SSR, return\n",
+				   __func__);
+		return 0;
+	}
+
+	ret = ioread32(pad->base + pad->offset + addr);
+	if (ret < 0)
+		pr_err("%s: read 0x%x failed\n", __func__, addr);
+
+	return ret;
+}
+
+static int lpi_gpio_write(struct lpi_gpio_pad *pad, unsigned int addr,
+			  unsigned int val)
+{
+	if (!lpi_dev_up) {
+		pr_err_ratelimited("%s: ADSP is down due to SSR, return\n",
+				   __func__);
+		return 0;
+	}
+
+	iowrite32(val, pad->base + pad->offset + addr);
+	return 0;
+}
+
+static int lpi_gpio_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	/* Every PIN is a group */
+	return pctldev->desc->npins;
+}
+
+static const char *lpi_gpio_get_group_name(struct pinctrl_dev *pctldev,
+					   unsigned int pin)
+{
+	return pctldev->desc->pins[pin].name;
+}
+
+static int lpi_gpio_get_group_pins(struct pinctrl_dev *pctldev,
+				   unsigned int pin,
+				   const unsigned int **pins,
+				   unsigned int *num_pins)
+{
+	*pins = &pctldev->desc->pins[pin].number;
+	*num_pins = 1;
+	return 0;
+}
+
+static const struct pinctrl_ops lpi_gpio_pinctrl_ops = {
+	.get_groups_count	= lpi_gpio_get_groups_count,
+	.get_group_name		= lpi_gpio_get_group_name,
+	.get_group_pins		= lpi_gpio_get_group_pins,
+	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
+	.dt_free_map		= pinctrl_utils_free_map,
+};
+
+static int lpi_gpio_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(lpi_gpio_functions);
+}
+
+static const char *lpi_gpio_get_function_name(struct pinctrl_dev *pctldev,
+					      unsigned int function)
+{
+	return lpi_gpio_functions[function];
+}
+
+static int lpi_gpio_get_function_groups(struct pinctrl_dev *pctldev,
+					unsigned int function,
+					const char *const **groups,
+					unsigned *const num_qgroups)
+{
+	*groups = lpi_gpio_groups;
+	*num_qgroups = pctldev->desc->npins;
+	return 0;
+}
+
+static int lpi_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
+			    unsigned int pin)
+{
+	struct lpi_gpio_pad *pad;
+	unsigned int val;
+
+	pad = pctldev->desc->pins[pin].drv_data;
+
+	pad->function = function;
+
+	val = lpi_gpio_read(pad, LPI_GPIO_REG_VAL_CTL);
+	val &= ~(LPI_GPIO_REG_FUNCTION_MASK);
+	val |= pad->function << LPI_GPIO_REG_FUNCTION_SHIFT;
+	lpi_gpio_write(pad, LPI_GPIO_REG_VAL_CTL, val);
+	return 0;
+}
+
+static const struct pinmux_ops lpi_gpio_pinmux_ops = {
+	.get_functions_count	= lpi_gpio_get_functions_count,
+	.get_function_name	= lpi_gpio_get_function_name,
+	.get_function_groups	= lpi_gpio_get_function_groups,
+	.set_mux		= lpi_gpio_set_mux,
+};
+
+static int lpi_config_get(struct pinctrl_dev *pctldev,
+			  unsigned int pin, unsigned long *config)
+{
+	unsigned int param = pinconf_to_config_param(*config);
+	struct lpi_gpio_pad *pad;
+	unsigned int arg;
+
+	pad = pctldev->desc->pins[pin].drv_data;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		arg = pad->pullup = LPI_GPIO_BIAS_DISABLE;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		arg = pad->pullup == LPI_GPIO_PULL_DOWN;
+		break;
+	case PIN_CONFIG_BIAS_BUS_HOLD:
+		arg = pad->pullup = LPI_GPIO_KEEPER;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		arg = pad->pullup == LPI_GPIO_PULL_UP;
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+	case PIN_CONFIG_OUTPUT:
+		arg = pad->output_enabled;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+	return 0;
+}
+
+static unsigned int lpi_drive_to_regval(u32 arg)
+{
+	return (arg/2 - 1);
+}
+
+static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
+			  unsigned long *configs, unsigned int nconfs)
+{
+	struct lpi_gpio_pad *pad;
+	unsigned int param, arg;
+	int i, ret = 0, val;
+
+	pad = pctldev->desc->pins[pin].drv_data;
+
+	for (i = 0; i < nconfs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		dev_dbg(pctldev->dev, "%s: param: %d arg: %d pin: %d\n",
+			__func__, param, arg, pin);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			pad->pullup = LPI_GPIO_BIAS_DISABLE;
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			pad->pullup = LPI_GPIO_PULL_DOWN;
+			break;
+		case PIN_CONFIG_BIAS_BUS_HOLD:
+			pad->pullup = LPI_GPIO_KEEPER;
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			pad->pullup = LPI_GPIO_PULL_UP;
+			break;
+		case PIN_CONFIG_INPUT_ENABLE:
+			pad->output_enabled = false;
+			break;
+		case PIN_CONFIG_OUTPUT:
+			pad->output_enabled = true;
+			pad->value = arg;
+			break;
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			pad->strength = arg;
+			break;
+		default:
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	val = lpi_gpio_read(pad, LPI_GPIO_REG_VAL_CTL);
+	val &= ~(LPI_GPIO_REG_PULL_MASK | LPI_GPIO_REG_OUT_STRENGTH_MASK |
+		 LPI_GPIO_REG_OE_MASK);
+	val |= pad->pullup << LPI_GPIO_REG_PULL_SHIFT;
+	val |= lpi_drive_to_regval(pad->strength) <<
+		LPI_GPIO_REG_OUT_STRENGTH_SHIFT;
+	if (pad->output_enabled)
+		val |= pad->value << LPI_GPIO_REG_OE_SHIFT;
+
+	lpi_gpio_write(pad, LPI_GPIO_REG_VAL_CTL, val);
+	lpi_gpio_write(pad, LPI_GPIO_REG_DIR_CTL,
+		       pad->output_enabled << LPI_GPIO_REG_DIR_SHIFT);
+done:
+	return ret;
+}
+
+static const struct pinconf_ops lpi_gpio_pinconf_ops = {
+	.is_generic			= true,
+	.pin_config_group_get		= lpi_config_get,
+	.pin_config_group_set		= lpi_config_set,
+};
+
+static int lpi_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
+{
+	struct lpi_gpio_state *state = gpiochip_get_data(chip);
+	unsigned long config;
+
+	config = pinconf_to_config_packed(PIN_CONFIG_INPUT_ENABLE, 1);
+
+	return lpi_config_set(state->ctrl, pin, &config, 1);
+}
+
+static int lpi_gpio_direction_output(struct gpio_chip *chip,
+				     unsigned int pin, int val)
+{
+	struct lpi_gpio_state *state = gpiochip_get_data(chip);
+	unsigned long config;
+
+	config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, val);
+
+	return lpi_config_set(state->ctrl, pin, &config, 1);
+}
+
+static int lpi_gpio_get(struct gpio_chip *chip, unsigned int pin)
+{
+	struct lpi_gpio_state *state = gpiochip_get_data(chip);
+	struct lpi_gpio_pad *pad;
+	int value;
+
+	pad = state->ctrl->desc->pins[pin].drv_data;
+
+	value = lpi_gpio_read(pad, LPI_GPIO_REG_VAL_CTL);
+	return value;
+}
+
+static void lpi_gpio_set(struct gpio_chip *chip, unsigned int pin, int value)
+{
+	struct lpi_gpio_state *state = gpiochip_get_data(chip);
+	unsigned long config;
+
+	config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, value);
+
+	lpi_config_set(state->ctrl, pin, &config, 1);
+}
+
+static int lpi_notifier_service_cb(struct notifier_block *this,
+				   unsigned long opcode, void *ptr)
+{
+	static bool initial_boot = true;
+
+	pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode);
+
+	switch (opcode) {
+	case AUDIO_NOTIFIER_SERVICE_DOWN:
+		if (initial_boot) {
+			initial_boot = false;
+			break;
+		}
+		lpi_dev_up = false;
+		break;
+	case AUDIO_NOTIFIER_SERVICE_UP:
+		if (initial_boot)
+			initial_boot = false;
+		lpi_dev_up = true;
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block service_nb = {
+	.notifier_call  = lpi_notifier_service_cb,
+	.priority = -INT_MAX,
+};
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/seq_file.h>
+
+static unsigned int lpi_regval_to_drive(u32 val)
+{
+	return (val + 1) * 2;
+}
+
+static void lpi_gpio_dbg_show_one(struct seq_file *s,
+				  struct pinctrl_dev *pctldev,
+				  struct gpio_chip *chip,
+				  unsigned int offset,
+				  unsigned int gpio)
+{
+	struct pinctrl_pin_desc pindesc;
+	struct lpi_gpio_pad *pad;
+	unsigned int func;
+	int is_out;
+	int drive;
+	int pull;
+	u32 ctl_reg;
+
+	static const char * const pulls[] = {
+		"no pull",
+		"pull down",
+		"keeper",
+		"pull up"
+	};
+
+	pctldev = pctldev ? : to_gpio_state(chip)->ctrl;
+	pindesc = pctldev->desc->pins[offset];
+	pad = pctldev->desc->pins[offset].drv_data;
+	ctl_reg = lpi_gpio_read(pad, LPI_GPIO_REG_DIR_CTL);
+	is_out = (ctl_reg & LPI_GPIO_REG_DIR_MASK) >> LPI_GPIO_REG_DIR_SHIFT;
+	ctl_reg = lpi_gpio_read(pad, LPI_GPIO_REG_VAL_CTL);
+
+	func = (ctl_reg & LPI_GPIO_REG_FUNCTION_MASK) >>
+		LPI_GPIO_REG_FUNCTION_SHIFT;
+	drive = (ctl_reg & LPI_GPIO_REG_OUT_STRENGTH_MASK) >>
+		 LPI_GPIO_REG_OUT_STRENGTH_SHIFT;
+	pull = (ctl_reg & LPI_GPIO_REG_PULL_MASK) >> LPI_GPIO_REG_PULL_SHIFT;
+
+	seq_printf(s, " %-8s: %-3s %d",
+		   pindesc.name, is_out ? "out" : "in", func);
+	seq_printf(s, " %dmA", lpi_regval_to_drive(drive));
+	seq_printf(s, " %s", pulls[pull]);
+}
+
+static void lpi_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	unsigned int gpio = chip->base;
+	unsigned int i;
+
+	for (i = 0; i < chip->ngpio; i++, gpio++) {
+		lpi_gpio_dbg_show_one(s, NULL, chip, i, gpio);
+		seq_puts(s, "\n");
+	}
+}
+
+#else
+#define lpi_gpio_dbg_show NULL
+#endif
+
+static const struct gpio_chip lpi_gpio_template = {
+	.direction_input	= lpi_gpio_direction_input,
+	.direction_output	= lpi_gpio_direction_output,
+	.get			= lpi_gpio_get,
+	.set			= lpi_gpio_set,
+	.request		= gpiochip_generic_request,
+	.free			= gpiochip_generic_free,
+	.dbg_show		= lpi_gpio_dbg_show,
+};
+
+static int lpi_pinctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct pinctrl_pin_desc *pindesc;
+	struct pinctrl_desc *pctrldesc;
+	struct lpi_gpio_pad *pad, *pads;
+	struct lpi_gpio_state *state;
+	int ret, npins, i;
+	char __iomem *lpi_base;
+	u32 reg;
+
+	ret = of_property_read_u32(dev->of_node, "reg", &reg);
+	if (ret < 0) {
+		dev_err(dev, "missing base address\n");
+		return ret;
+	}
+
+	ret = of_property_read_u32(dev->of_node, "qcom,num-gpios", &npins);
+	if (ret < 0)
+		return ret;
+
+	WARN_ON(npins > ARRAY_SIZE(lpi_gpio_groups));
+
+	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, state);
+
+	state->dev = &pdev->dev;
+
+	pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);
+	if (!pindesc)
+		return -ENOMEM;
+
+	pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL);
+	if (!pads)
+		return -ENOMEM;
+
+	pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL);
+	if (!pctrldesc)
+		return -ENOMEM;
+
+	pctrldesc->pctlops = &lpi_gpio_pinctrl_ops;
+	pctrldesc->pmxops = &lpi_gpio_pinmux_ops;
+	pctrldesc->confops = &lpi_gpio_pinconf_ops;
+	pctrldesc->owner = THIS_MODULE;
+	pctrldesc->name = dev_name(dev);
+	pctrldesc->pins = pindesc;
+	pctrldesc->npins = npins;
+
+	lpi_base = devm_ioremap(dev, reg, LPI_ADDRESS_SIZE);
+	if (lpi_base == NULL) {
+		dev_err(dev, "%s devm_ioremap failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	state->base = lpi_base;
+
+	for (i = 0; i < npins; i++, pindesc++) {
+		pad = &pads[i];
+		pindesc->drv_data = pad;
+		pindesc->number = i;
+		pindesc->name = lpi_gpio_groups[i];
+
+		pad->base = lpi_base;
+		pad->offset = lpi_offset[i];
+	}
+
+	state->chip = lpi_gpio_template;
+	state->chip.parent = dev;
+	state->chip.base = -1;
+	state->chip.ngpio = npins;
+	state->chip.label = dev_name(dev);
+	state->chip.of_gpio_n_cells = 2;
+	state->chip.can_sleep = false;
+
+	state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);
+	if (IS_ERR(state->ctrl))
+		return PTR_ERR(state->ctrl);
+
+	ret = gpiochip_add_data(&state->chip, state);
+	if (ret) {
+		dev_err(state->dev, "can't add gpio chip\n");
+		goto err_chip;
+	}
+
+	ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
+	if (ret) {
+		dev_err(dev, "failed to add pin range\n");
+		goto err_range;
+	}
+
+	lpi_dev_up = true;
+	ret = audio_notifier_register("lpi_tlmm", AUDIO_NOTIFIER_ADSP_DOMAIN,
+				      &service_nb);
+	if (ret < 0) {
+		pr_err("%s: Audio notifier register failed ret = %d\n",
+			__func__, ret);
+		goto err_range;
+	}
+
+	return 0;
+
+err_range:
+	gpiochip_remove(&state->chip);
+err_chip:
+	return ret;
+}
+
+static int lpi_pinctrl_remove(struct platform_device *pdev)
+{
+	struct lpi_gpio_state *state = platform_get_drvdata(pdev);
+
+	gpiochip_remove(&state->chip);
+	return 0;
+}
+
+static const struct of_device_id lpi_pinctrl_of_match[] = {
+	{ .compatible = "qcom,lpi-pinctrl" }, /* Generic */
+	{ },
+};
+
+MODULE_DEVICE_TABLE(of, lpi_pinctrl_of_match);
+
+static struct platform_driver lpi_pinctrl_driver = {
+	.driver = {
+		   .name = "qcom-lpi-pinctrl",
+		   .of_match_table = lpi_pinctrl_of_match,
+	},
+	.probe = lpi_pinctrl_probe,
+	.remove = lpi_pinctrl_remove,
+};
+
+module_platform_driver(lpi_pinctrl_driver);
+
+MODULE_DESCRIPTION("QTI LPI GPIO pin control driver");
+MODULE_LICENSE("GPL v2");

+ 435 - 0
drivers/pinctrl/qcom/pinctrl-wcd.c

@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mfd/wcd934x/registers.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#define WCD_REG_DIR_CTL WCD934X_CHIP_TIER_CTRL_GPIO_CTL_OE
+#define WCD_REG_VAL_CTL WCD934X_CHIP_TIER_CTRL_GPIO_CTL_DATA
+#define WCD_GPIO_PULL_UP       1
+#define WCD_GPIO_PULL_DOWN     2
+#define WCD_GPIO_BIAS_DISABLE  3
+#define WCD_GPIO_STRING_LEN    20
+
+/**
+ * struct wcd_gpio_pad - keep current GPIO settings
+ * @offset: offset of gpio.
+ * @is_valid: Set to false, when GPIO in high Z state.
+ * @value: value of a pin
+ * @output_enabled: Set to true if GPIO is output and false if it is input
+ * @pullup: Constant current which flow through GPIO output buffer.
+ * @strength: Drive strength of a pin
+ */
+struct wcd_gpio_pad {
+	u16  offset;
+	bool is_valid;
+	bool value;
+	bool output_enabled;
+	unsigned int pullup;
+	unsigned int strength;
+};
+
+struct wcd_gpio_priv {
+	struct device *dev;
+	struct regmap *map;
+	struct pinctrl_dev *ctrl;
+	struct gpio_chip chip;
+};
+
+static int wcd_gpio_read(struct wcd_gpio_priv *priv_data,
+			  struct wcd_gpio_pad *pad, unsigned int addr)
+{
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(priv_data->map, addr, &val);
+	if (ret < 0)
+		dev_err(priv_data->dev, "%s: read 0x%x failed\n",
+			__func__, addr);
+	else
+		ret = (val >> pad->offset);
+
+	return ret;
+}
+
+static int wcd_gpio_write(struct wcd_gpio_priv *priv_data,
+			   struct wcd_gpio_pad *pad, unsigned int addr,
+			   unsigned int val)
+{
+	int ret;
+
+	ret = regmap_update_bits(priv_data->map, addr, (1 << pad->offset),
+					val << pad->offset);
+	if (ret < 0)
+		dev_err(priv_data->dev, "write 0x%x failed\n", addr);
+
+	return ret;
+}
+
+static int wcd_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	return pctldev->desc->npins;
+}
+
+static const char *wcd_get_group_name(struct pinctrl_dev *pctldev,
+		unsigned int pin)
+{
+	return pctldev->desc->pins[pin].name;
+}
+
+static int wcd_get_group_pins(struct pinctrl_dev *pctldev, unsigned int pin,
+		const unsigned int **pins, unsigned int *num_pins)
+{
+	*pins = &pctldev->desc->pins[pin].number;
+	*num_pins = 1;
+	return 0;
+}
+
+static const struct pinctrl_ops wcd_pinctrl_ops = {
+	.get_groups_count       = wcd_get_groups_count,
+	.get_group_name         = wcd_get_group_name,
+	.get_group_pins         = wcd_get_group_pins,
+	.dt_node_to_map         = pinconf_generic_dt_node_to_map_group,
+	.dt_free_map            = pinctrl_utils_free_map,
+};
+
+static int wcd_config_get(struct pinctrl_dev *pctldev,
+				unsigned int pin, unsigned long *config)
+{
+	unsigned int param = pinconf_to_config_param(*config);
+	struct wcd_gpio_pad *pad;
+	unsigned int arg;
+
+	pad = pctldev->desc->pins[pin].drv_data;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		arg = pad->pullup == WCD_GPIO_PULL_DOWN;
+		break;
+	case PIN_CONFIG_BIAS_DISABLE:
+		arg = pad->pullup = WCD_GPIO_BIAS_DISABLE;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		arg = pad->pullup == WCD_GPIO_PULL_UP;
+		break;
+	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+		arg = !pad->is_valid;
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		arg = pad->output_enabled;
+		break;
+	case PIN_CONFIG_OUTPUT:
+		arg = pad->value;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+	return 0;
+}
+
+static int wcd_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
+				unsigned long *configs, unsigned int nconfs)
+{
+	struct wcd_gpio_priv *priv_data = pinctrl_dev_get_drvdata(pctldev);
+	struct wcd_gpio_pad *pad;
+	unsigned int param, arg;
+	int i, ret;
+
+	pad = pctldev->desc->pins[pin].drv_data;
+
+	for (i = 0; i < nconfs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		dev_dbg(priv_data->dev, "%s: param: %d arg: %d",
+			__func__, param, arg);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			pad->pullup = WCD_GPIO_BIAS_DISABLE;
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			pad->pullup = WCD_GPIO_PULL_UP;
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			pad->pullup = WCD_GPIO_PULL_DOWN;
+			break;
+		case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+			pad->is_valid = false;
+			break;
+		case PIN_CONFIG_INPUT_ENABLE:
+			pad->output_enabled = false;
+			break;
+		case PIN_CONFIG_OUTPUT:
+			pad->output_enabled = true;
+			pad->value = arg;
+			break;
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			pad->strength = arg;
+			break;
+		default:
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	if (pad->output_enabled) {
+		ret = wcd_gpio_write(priv_data, pad, WCD_REG_DIR_CTL,
+				     pad->output_enabled);
+		if (ret < 0)
+			goto done;
+		ret = wcd_gpio_write(priv_data, pad, WCD_REG_VAL_CTL,
+				     pad->value);
+	} else
+		ret = wcd_gpio_write(priv_data, pad, WCD_REG_DIR_CTL,
+				     pad->output_enabled);
+done:
+	return ret;
+}
+
+static const struct pinconf_ops wcd_pinconf_ops = {
+	.is_generic  = true,
+	.pin_config_group_get = wcd_config_get,
+	.pin_config_group_set = wcd_config_set,
+};
+
+static int wcd_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
+{
+	struct wcd_gpio_priv *priv_data = gpiochip_get_data(chip);
+	unsigned long config;
+
+	config = pinconf_to_config_packed(PIN_CONFIG_INPUT_ENABLE, 1);
+
+	return wcd_config_set(priv_data->ctrl, pin, &config, 1);
+}
+
+static int wcd_gpio_direction_output(struct gpio_chip *chip,
+				      unsigned int pin, int val)
+{
+	struct wcd_gpio_priv *priv_data = gpiochip_get_data(chip);
+	unsigned long config;
+
+	config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, val);
+
+	return wcd_config_set(priv_data->ctrl, pin, &config, 1);
+}
+
+static int wcd_gpio_get(struct gpio_chip *chip, unsigned int pin)
+{
+	struct wcd_gpio_priv *priv_data = gpiochip_get_data(chip);
+	struct wcd_gpio_pad *pad;
+	int value;
+
+	pad = priv_data->ctrl->desc->pins[pin].drv_data;
+
+	if (!pad->is_valid)
+		return -EINVAL;
+
+	value = wcd_gpio_read(priv_data, pad, WCD_REG_VAL_CTL);
+	return value;
+}
+
+static void wcd_gpio_set(struct gpio_chip *chip, unsigned int pin, int value)
+{
+	struct wcd_gpio_priv *priv_data = gpiochip_get_data(chip);
+	unsigned long config;
+
+	config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, value);
+
+	wcd_config_set(priv_data->ctrl, pin, &config, 1);
+}
+
+static const struct gpio_chip wcd_gpio_chip = {
+	.direction_input  = wcd_gpio_direction_input,
+	.direction_output = wcd_gpio_direction_output,
+	.get = wcd_gpio_get,
+	.set = wcd_gpio_set,
+};
+
+static int wcd_pinctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct pinctrl_pin_desc *pindesc;
+	struct pinctrl_desc *pctrldesc;
+	struct wcd_gpio_pad *pad, *pads;
+	struct wcd_gpio_priv *priv_data;
+	int ret, i, j;
+	u32 npins;
+	char **name;
+
+	ret = of_property_read_u32(dev->of_node, "qcom,num-gpios", &npins);
+	if (ret) {
+		dev_err(dev, "%s: Looking up %s property in node %s failed\n",
+			__func__, "qcom,num-gpios", dev->of_node->full_name);
+		ret = -EINVAL;
+		goto err_priv_alloc;
+	}
+	if (!npins) {
+		dev_err(dev, "%s: no.of pins are 0\n", __func__);
+		ret = -EINVAL;
+		goto err_priv_alloc;
+	}
+
+	priv_data = devm_kzalloc(dev, sizeof(*priv_data), GFP_KERNEL);
+	if (!priv_data) {
+		ret = -ENOMEM;
+		goto err_priv_alloc;
+	}
+
+	priv_data->dev = dev;
+	priv_data->map = dev_get_regmap(dev->parent, NULL);
+	if (!priv_data->map) {
+		dev_err(dev, "%s: failed to get regmap\n", __func__);
+		ret = -EINVAL;
+		goto err_regmap;
+	}
+
+	pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);
+	if (!pindesc) {
+		ret = -ENOMEM;
+		goto err_pinsec_alloc;
+	}
+
+	pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL);
+	if (!pads) {
+		ret = -ENOMEM;
+		goto err_pads_alloc;
+	}
+
+	pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL);
+	if (!pctrldesc) {
+		ret = -ENOMEM;
+		goto err_pinctrl_alloc;
+	}
+
+	pctrldesc->pctlops = &wcd_pinctrl_ops;
+	pctrldesc->confops = &wcd_pinconf_ops;
+	pctrldesc->owner = THIS_MODULE;
+	pctrldesc->name = dev_name(dev);
+	pctrldesc->pins = pindesc;
+	pctrldesc->npins = npins;
+
+	name = devm_kcalloc(dev, npins, sizeof(char *), GFP_KERNEL);
+	if (!name) {
+		ret = -ENOMEM;
+		goto err_name_alloc;
+	}
+	for (i = 0; i < npins; i++, pindesc++) {
+		name[i] = devm_kzalloc(dev, sizeof(char) * WCD_GPIO_STRING_LEN,
+				       GFP_KERNEL);
+		if (!name[i]) {
+			ret = -ENOMEM;
+			goto err_pin;
+		}
+		pad = &pads[i];
+		pindesc->drv_data = pad;
+		pindesc->number = i;
+		snprintf(name[i], (WCD_GPIO_STRING_LEN - 1), "gpio%d", (i+1));
+		pindesc->name = name[i];
+		pad->offset = i;
+		pad->is_valid  = true;
+	}
+
+	priv_data->chip = wcd_gpio_chip;
+	priv_data->chip.parent = dev;
+	priv_data->chip.base = -1;
+	priv_data->chip.ngpio = npins;
+	priv_data->chip.label = dev_name(dev);
+	priv_data->chip.of_gpio_n_cells = 2;
+	priv_data->chip.can_sleep = false;
+
+	priv_data->ctrl = devm_pinctrl_register(dev, pctrldesc, priv_data);
+	if (IS_ERR(priv_data->ctrl)) {
+		dev_err(dev, "%s: failed to register to pinctrl\n", __func__);
+		ret = PTR_ERR(priv_data->ctrl);
+		goto err_pin;
+	}
+
+	ret = gpiochip_add_data(&priv_data->chip, priv_data);
+	if (ret) {
+		dev_err(dev, "%s: can't add gpio chip\n", __func__);
+		goto err_pin;
+	}
+
+	ret = gpiochip_add_pin_range(&priv_data->chip, dev_name(dev), 0, 0,
+				     npins);
+	if (ret) {
+		dev_err(dev, "%s: failed to add pin range\n", __func__);
+		goto err_range;
+	}
+	platform_set_drvdata(pdev, priv_data);
+
+	return 0;
+
+err_range:
+	gpiochip_remove(&priv_data->chip);
+err_pin:
+	for (j = 0; j < i; j++)
+		devm_kfree(dev, name[j]);
+	devm_kfree(dev, name);
+err_name_alloc:
+	devm_kfree(dev, pctrldesc);
+err_pinctrl_alloc:
+	devm_kfree(dev, pads);
+err_pads_alloc:
+	devm_kfree(dev, pindesc);
+err_pinsec_alloc:
+err_regmap:
+	devm_kfree(dev, priv_data);
+err_priv_alloc:
+	return ret;
+}
+
+static int wcd_pinctrl_remove(struct platform_device *pdev)
+{
+	struct wcd_gpio_priv *priv_data = platform_get_drvdata(pdev);
+
+	gpiochip_remove(&priv_data->chip);
+
+	return 0;
+}
+
+static const struct of_device_id wcd_pinctrl_of_match[] = {
+	{ .compatible = "qcom,wcd-pinctrl" },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(of, wcd_pinctrl_of_match);
+
+static struct platform_driver wcd_pinctrl_driver = {
+	.driver = {
+		   .name = "qcom-wcd-pinctrl",
+		   .of_match_table = wcd_pinctrl_of_match,
+	},
+	.probe = wcd_pinctrl_probe,
+	.remove = wcd_pinctrl_remove,
+};
+
+module_platform_driver(wcd_pinctrl_driver);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc WCD GPIO pin control driver");
+MODULE_LICENSE("GPL v2");

+ 5 - 0
drivers/soc/Makefile

@@ -0,0 +1,5 @@
+#
+# Makefile for the Linux Kernel SOC specific device drivers.
+#
+
+obj-y	+= qcom/

+ 1 - 0
drivers/soc/qcom/Makefile

@@ -0,0 +1 @@
+obj-y			+=	qdsp6v2/

+ 8 - 0
drivers/soc/qcom/qdsp6v2/Makefile

@@ -0,0 +1,8 @@
+obj-$(CONFIG_MSM_QDSP6_APRV2_GLINK) += apr.o apr_v2.o apr_tal_glink.o
+obj-$(CONFIG_MSM_QDSP6_APRV3_GLINK) += apr.o apr_v3.o apr_tal_glink.o
+obj-$(CONFIG_SND_SOC_MSM_QDSP6V2_INTF) += msm_audio_ion.o
+obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
+obj-$(CONFIG_MSM_QDSP6_SSR) += audio_ssr.o
+obj-$(CONFIG_MSM_QDSP6_PDR) += audio_pdr.o
+obj-$(CONFIG_MSM_QDSP6_NOTIFIER) += audio_notifier.o
+obj-$(CONFIG_MSM_CDSP_LOADER) += cdsp-loader.o

+ 316 - 0
drivers/soc/qcom/qdsp6v2/adsp-loader.c

@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2012-2014, 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/qdsp6v2/apr.h>
+#include <linux/of_device.h>
+#include <linux/sysfs.h>
+#include <linux/workqueue.h>
+
+#include <soc/qcom/subsystem_restart.h>
+
+#define Q6_PIL_GET_DELAY_MS 100
+#define BOOT_CMD 1
+#define IMAGE_UNLOAD_CMD 0
+
+static ssize_t adsp_boot_store(struct kobject *kobj,
+	struct kobj_attribute *attr,
+	const char *buf, size_t count);
+
+struct adsp_loader_private {
+	void *pil_h;
+	struct kobject *boot_adsp_obj;
+	struct attribute_group *attr_group;
+};
+
+static struct kobj_attribute adsp_boot_attribute =
+	__ATTR(boot, 0220, NULL, adsp_boot_store);
+
+static struct attribute *attrs[] = {
+	&adsp_boot_attribute.attr,
+	NULL,
+};
+
+static struct work_struct adsp_ldr_work;
+static struct platform_device *adsp_private;
+static void adsp_loader_unload(struct platform_device *pdev);
+
+static void adsp_load_fw(struct work_struct *adsp_ldr_work)
+{
+	struct platform_device *pdev = adsp_private;
+	struct adsp_loader_private *priv = NULL;
+
+	const char *adsp_dt = "qcom,adsp-state";
+	int rc = 0;
+	u32 adsp_state;
+	const char *img_name;
+
+	if (!pdev) {
+		dev_err(&pdev->dev, "%s: Platform device null\n", __func__);
+		goto fail;
+	}
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev,
+			"%s: Device tree information missing\n", __func__);
+		goto fail;
+	}
+
+	rc = of_property_read_u32(pdev->dev.of_node, adsp_dt, &adsp_state);
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: ADSP state = %x\n", __func__, adsp_state);
+		goto fail;
+	}
+
+	rc = of_property_read_string(pdev->dev.of_node,
+					"qcom,proc-img-to-load",
+					&img_name);
+
+	if (rc) {
+		dev_dbg(&pdev->dev,
+			"%s: loading default image ADSP\n", __func__);
+		goto load_adsp;
+	}
+	if (!strcmp(img_name, "modem")) {
+		/* adsp_state always returns "0". So load modem image based on
+		 * apr_modem_state to prevent loading of image twice
+		 */
+		adsp_state = apr_get_modem_state();
+		if (adsp_state == APR_SUBSYS_DOWN) {
+			priv = platform_get_drvdata(pdev);
+			if (!priv) {
+				dev_err(&pdev->dev,
+				" %s: Private data get failed\n", __func__);
+				goto fail;
+			}
+
+			priv->pil_h = subsystem_get("modem");
+			if (IS_ERR(priv->pil_h)) {
+				dev_err(&pdev->dev, "%s: pil get failed,\n",
+					__func__);
+				goto fail;
+			}
+
+			/* Set the state of the ADSP in APR driver */
+			apr_set_modem_state(APR_SUBSYS_LOADED);
+		} else if (adsp_state == APR_SUBSYS_LOADED) {
+			dev_dbg(&pdev->dev,
+			"%s: MDSP state = %x\n", __func__, adsp_state);
+		}
+
+		dev_dbg(&pdev->dev, "%s: Q6/MDSP image is loaded\n", __func__);
+		return;
+	}
+load_adsp:
+	{
+		adsp_state = apr_get_q6_state();
+		if (adsp_state == APR_SUBSYS_DOWN) {
+			priv = platform_get_drvdata(pdev);
+			if (!priv) {
+				dev_err(&pdev->dev,
+				" %s: Private data get failed\n", __func__);
+				goto fail;
+			}
+
+			priv->pil_h = subsystem_get("adsp");
+			if (IS_ERR(priv->pil_h)) {
+				dev_err(&pdev->dev, "%s: pil get failed,\n",
+					__func__);
+				goto fail;
+			}
+
+			/* Set the state of the ADSP in APR driver */
+			apr_set_q6_state(APR_SUBSYS_LOADED);
+		} else if (adsp_state == APR_SUBSYS_LOADED) {
+			dev_dbg(&pdev->dev,
+			"%s: ADSP state = %x\n", __func__, adsp_state);
+		}
+
+		dev_dbg(&pdev->dev, "%s: Q6/ADSP image is loaded\n", __func__);
+		return;
+	}
+fail:
+	dev_err(&pdev->dev, "%s: Q6 image loading failed\n", __func__);
+}
+
+static void adsp_loader_do(struct platform_device *pdev)
+{
+	schedule_work(&adsp_ldr_work);
+}
+
+static ssize_t adsp_boot_store(struct kobject *kobj,
+	struct kobj_attribute *attr,
+	const char *buf,
+	size_t count)
+{
+	int boot = 0;
+
+	if (sscanf(buf, "%du", &boot) != 1) {
+		pr_err("%s: failed to read boot info from string\n", __func__);
+		return -EINVAL;
+	}
+
+	if (boot == BOOT_CMD) {
+		pr_debug("%s: going to call adsp_loader_do\n", __func__);
+		adsp_loader_do(adsp_private);
+	} else if (boot == IMAGE_UNLOAD_CMD) {
+		pr_debug("%s: going to call adsp_unloader\n", __func__);
+		adsp_loader_unload(adsp_private);
+	}
+	return count;
+}
+
+static void adsp_loader_unload(struct platform_device *pdev)
+{
+	struct adsp_loader_private *priv = NULL;
+
+	priv = platform_get_drvdata(pdev);
+
+	if (!priv)
+		return;
+
+	if (priv->pil_h) {
+		dev_dbg(&pdev->dev, "%s: calling subsystem put\n", __func__);
+		subsystem_put(priv->pil_h);
+		priv->pil_h = NULL;
+	}
+}
+
+static int adsp_loader_init_sysfs(struct platform_device *pdev)
+{
+	int ret = -EINVAL;
+	struct adsp_loader_private *priv = NULL;
+
+	adsp_private = NULL;
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	priv->pil_h = NULL;
+	priv->boot_adsp_obj = NULL;
+	priv->attr_group = devm_kzalloc(&pdev->dev,
+				sizeof(*(priv->attr_group)),
+				GFP_KERNEL);
+	if (!priv->attr_group) {
+		ret = -ENOMEM;
+		goto error_return;
+	}
+
+	priv->attr_group->attrs = attrs;
+
+	priv->boot_adsp_obj = kobject_create_and_add("boot_adsp", kernel_kobj);
+	if (!priv->boot_adsp_obj) {
+		dev_err(&pdev->dev, "%s: sysfs create and add failed\n",
+						__func__);
+		ret = -ENOMEM;
+		goto error_return;
+	}
+
+	ret = sysfs_create_group(priv->boot_adsp_obj, priv->attr_group);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: sysfs create group failed %d\n",
+							__func__, ret);
+		goto error_return;
+	}
+
+	adsp_private = pdev;
+
+	return 0;
+
+error_return:
+
+	if (priv->boot_adsp_obj) {
+		kobject_del(priv->boot_adsp_obj);
+		priv->boot_adsp_obj = NULL;
+	}
+
+	return ret;
+}
+
+static int adsp_loader_remove(struct platform_device *pdev)
+{
+	struct adsp_loader_private *priv = NULL;
+
+	priv = platform_get_drvdata(pdev);
+
+	if (!priv)
+		return 0;
+
+	if (priv->pil_h) {
+		subsystem_put(priv->pil_h);
+		priv->pil_h = NULL;
+	}
+
+	if (priv->boot_adsp_obj) {
+		sysfs_remove_group(priv->boot_adsp_obj, priv->attr_group);
+		kobject_del(priv->boot_adsp_obj);
+		priv->boot_adsp_obj = NULL;
+	}
+
+	return 0;
+}
+
+static int adsp_loader_probe(struct platform_device *pdev)
+{
+	int ret = adsp_loader_init_sysfs(pdev);
+
+	if (ret != 0) {
+		dev_err(&pdev->dev, "%s: Error in initing sysfs\n", __func__);
+		return ret;
+	}
+
+	INIT_WORK(&adsp_ldr_work, adsp_load_fw);
+
+	return 0;
+}
+
+static const struct of_device_id adsp_loader_dt_match[] = {
+	{ .compatible = "qcom,adsp-loader" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, adsp_loader_dt_match);
+
+static struct platform_driver adsp_loader_driver = {
+	.driver = {
+		.name = "adsp-loader",
+		.owner = THIS_MODULE,
+		.of_match_table = adsp_loader_dt_match,
+	},
+	.probe = adsp_loader_probe,
+	.remove = adsp_loader_remove,
+};
+
+static int __init adsp_loader_init(void)
+{
+	return platform_driver_register(&adsp_loader_driver);
+}
+module_init(adsp_loader_init);
+
+static void __exit adsp_loader_exit(void)
+{
+	platform_driver_unregister(&adsp_loader_driver);
+}
+module_exit(adsp_loader_exit);
+
+MODULE_DESCRIPTION("ADSP Loader module");
+MODULE_LICENSE("GPL v2");

+ 976 - 0
drivers/soc/qcom/qdsp6v2/apr.c

@@ -0,0 +1,976 @@
+/* Copyright (c) 2010-2014, 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <soc/qcom/subsystem_restart.h>
+#include <soc/qcom/scm.h>
+#include <sound/apr_audio-v2.h>
+#include <linux/qdsp6v2/apr.h>
+#include <linux/qdsp6v2/apr_tal.h>
+#include <linux/qdsp6v2/dsp_debug.h>
+#include <linux/qdsp6v2/audio_notifier.h>
+#include <linux/ipc_logging.h>
+
+#define APR_PKT_IPC_LOG_PAGE_CNT 2
+
+static struct apr_q6 q6;
+static struct apr_client client[APR_DEST_MAX][APR_CLIENT_MAX];
+static void *apr_pkt_ctx;
+static wait_queue_head_t dsp_wait;
+static wait_queue_head_t modem_wait;
+static bool is_modem_up;
+static bool is_initial_boot;
+/* Subsystem restart: QDSP6 data, functions */
+static struct workqueue_struct *apr_reset_workqueue;
+static void apr_reset_deregister(struct work_struct *work);
+static void dispatch_event(unsigned long code, uint16_t proc);
+struct apr_reset_work {
+	void *handle;
+	struct work_struct work;
+};
+
+static bool apr_cf_debug;
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *debugfs_apr_debug;
+static ssize_t apr_debug_write(struct file *filp, const char __user *ubuf,
+			       size_t cnt, loff_t *ppos)
+{
+	char cmd;
+
+	if (copy_from_user(&cmd, ubuf, 1))
+		return -EFAULT;
+
+	apr_cf_debug = (cmd == '1') ? true : false;
+
+	return cnt;
+}
+
+static const struct file_operations apr_debug_ops = {
+	.write = apr_debug_write,
+};
+#endif
+
+#define APR_PKT_INFO(x...) \
+do { \
+	if (apr_pkt_ctx) \
+		ipc_log_string(apr_pkt_ctx, "<APR>: "x); \
+} while (0)
+
+
+struct apr_svc_table {
+	char name[64];
+	int idx;
+	int id;
+	int client_id;
+};
+
+static const struct apr_svc_table svc_tbl_qdsp6[] = {
+	{
+		.name = "AFE",
+		.idx = 0,
+		.id = APR_SVC_AFE,
+		.client_id = APR_CLIENT_AUDIO,
+	},
+	{
+		.name = "ASM",
+		.idx = 1,
+		.id = APR_SVC_ASM,
+		.client_id = APR_CLIENT_AUDIO,
+	},
+	{
+		.name = "ADM",
+		.idx = 2,
+		.id = APR_SVC_ADM,
+		.client_id = APR_CLIENT_AUDIO,
+	},
+	{
+		.name = "CORE",
+		.idx = 3,
+		.id = APR_SVC_ADSP_CORE,
+		.client_id = APR_CLIENT_AUDIO,
+	},
+	{
+		.name = "TEST",
+		.idx = 4,
+		.id = APR_SVC_TEST_CLIENT,
+		.client_id = APR_CLIENT_AUDIO,
+	},
+	{
+		.name = "MVM",
+		.idx = 5,
+		.id = APR_SVC_ADSP_MVM,
+		.client_id = APR_CLIENT_AUDIO,
+	},
+	{
+		.name = "CVS",
+		.idx = 6,
+		.id = APR_SVC_ADSP_CVS,
+		.client_id = APR_CLIENT_AUDIO,
+	},
+	{
+		.name = "CVP",
+		.idx = 7,
+		.id = APR_SVC_ADSP_CVP,
+		.client_id = APR_CLIENT_AUDIO,
+	},
+	{
+		.name = "USM",
+		.idx = 8,
+		.id = APR_SVC_USM,
+		.client_id = APR_CLIENT_AUDIO,
+	},
+	{
+		.name = "VIDC",
+		.idx = 9,
+		.id = APR_SVC_VIDC,
+	},
+	{
+		.name = "LSM",
+		.idx = 10,
+		.id = APR_SVC_LSM,
+		.client_id = APR_CLIENT_AUDIO,
+	},
+};
+
+static struct apr_svc_table svc_tbl_voice[] = {
+	{
+		.name = "VSM",
+		.idx = 0,
+		.id = APR_SVC_VSM,
+		.client_id = APR_CLIENT_VOICE,
+	},
+	{
+		.name = "VPM",
+		.idx = 1,
+		.id = APR_SVC_VPM,
+		.client_id = APR_CLIENT_VOICE,
+	},
+	{
+		.name = "MVS",
+		.idx = 2,
+		.id = APR_SVC_MVS,
+		.client_id = APR_CLIENT_VOICE,
+	},
+	{
+		.name = "MVM",
+		.idx = 3,
+		.id = APR_SVC_MVM,
+		.client_id = APR_CLIENT_VOICE,
+	},
+	{
+		.name = "CVS",
+		.idx = 4,
+		.id = APR_SVC_CVS,
+		.client_id = APR_CLIENT_VOICE,
+	},
+	{
+		.name = "CVP",
+		.idx = 5,
+		.id = APR_SVC_CVP,
+		.client_id = APR_CLIENT_VOICE,
+	},
+	{
+		.name = "SRD",
+		.idx = 6,
+		.id = APR_SVC_SRD,
+		.client_id = APR_CLIENT_VOICE,
+	},
+	{
+		.name = "TEST",
+		.idx = 7,
+		.id = APR_SVC_TEST_CLIENT,
+		.client_id = APR_CLIENT_VOICE,
+	},
+};
+
+enum apr_subsys_state apr_get_modem_state(void)
+{
+	return atomic_read(&q6.modem_state);
+}
+
+void apr_set_modem_state(enum apr_subsys_state state)
+{
+	atomic_set(&q6.modem_state, state);
+}
+
+enum apr_subsys_state apr_cmpxchg_modem_state(enum apr_subsys_state prev,
+					      enum apr_subsys_state new)
+{
+	return atomic_cmpxchg(&q6.modem_state, prev, new);
+}
+
+static void apr_modem_down(unsigned long opcode)
+{
+	apr_set_modem_state(APR_SUBSYS_DOWN);
+	dispatch_event(opcode, APR_DEST_MODEM);
+}
+
+static void apr_modem_up(void)
+{
+	if (apr_cmpxchg_modem_state(APR_SUBSYS_DOWN, APR_SUBSYS_UP) ==
+							APR_SUBSYS_DOWN)
+		wake_up(&modem_wait);
+	is_modem_up = 1;
+}
+
+enum apr_subsys_state apr_get_q6_state(void)
+{
+	return atomic_read(&q6.q6_state);
+}
+EXPORT_SYMBOL(apr_get_q6_state);
+
+int apr_set_q6_state(enum apr_subsys_state state)
+{
+	pr_debug("%s: setting adsp state %d\n", __func__, state);
+	if (state < APR_SUBSYS_DOWN || state > APR_SUBSYS_LOADED)
+		return -EINVAL;
+	atomic_set(&q6.q6_state, state);
+	return 0;
+}
+EXPORT_SYMBOL(apr_set_q6_state);
+
+enum apr_subsys_state apr_cmpxchg_q6_state(enum apr_subsys_state prev,
+					   enum apr_subsys_state new)
+{
+	return atomic_cmpxchg(&q6.q6_state, prev, new);
+}
+
+static void apr_adsp_down(unsigned long opcode)
+{
+	apr_set_q6_state(APR_SUBSYS_DOWN);
+	dispatch_event(opcode, APR_DEST_QDSP6);
+}
+
+static void apr_adsp_up(void)
+{
+	if (apr_cmpxchg_q6_state(APR_SUBSYS_DOWN, APR_SUBSYS_LOADED) ==
+							APR_SUBSYS_DOWN)
+		wake_up(&dsp_wait);
+}
+
+int apr_wait_for_device_up(int dest_id)
+{
+	int rc = -1;
+
+	if (dest_id == APR_DEST_MODEM)
+		rc = wait_event_interruptible_timeout(modem_wait,
+				    (apr_get_modem_state() == APR_SUBSYS_UP),
+				    (1 * HZ));
+	else if (dest_id == APR_DEST_QDSP6)
+		rc = wait_event_interruptible_timeout(dsp_wait,
+				    (apr_get_q6_state() == APR_SUBSYS_UP),
+				    (1 * HZ));
+	else
+		pr_err("%s: unknown dest_id %d\n", __func__, dest_id);
+	/* returns left time */
+	return rc;
+}
+
+int apr_load_adsp_image(void)
+{
+	int rc = 0;
+
+	mutex_lock(&q6.lock);
+	if (apr_get_q6_state() == APR_SUBSYS_UP) {
+		q6.pil = subsystem_get("adsp");
+		if (IS_ERR(q6.pil)) {
+			rc = PTR_ERR(q6.pil);
+			pr_err("APR: Unable to load q6 image, error:%d\n", rc);
+		} else {
+			apr_set_q6_state(APR_SUBSYS_LOADED);
+			pr_debug("APR: Image is loaded, stated\n");
+		}
+	} else if (apr_get_q6_state() == APR_SUBSYS_LOADED) {
+		pr_debug("APR: q6 image already loaded\n");
+	} else {
+		pr_debug("APR: cannot load state %d\n", apr_get_q6_state());
+	}
+	mutex_unlock(&q6.lock);
+	return rc;
+}
+
+struct apr_client *apr_get_client(int dest_id, int client_id)
+{
+	return &client[dest_id][client_id];
+}
+
+int apr_send_pkt(void *handle, uint32_t *buf)
+{
+	struct apr_svc *svc = handle;
+	struct apr_client *clnt;
+	struct apr_hdr *hdr;
+	uint16_t dest_id;
+	uint16_t client_id;
+	uint16_t w_len;
+	int rc;
+	unsigned long flags;
+
+	if (!handle || !buf) {
+		pr_err("APR: Wrong parameters\n");
+		return -EINVAL;
+	}
+	if (svc->need_reset) {
+		pr_err("apr: send_pkt service need reset\n");
+		return -ENETRESET;
+	}
+
+	if ((svc->dest_id == APR_DEST_QDSP6) &&
+	    (apr_get_q6_state() != APR_SUBSYS_LOADED)) {
+		pr_err("%s: Still dsp is not Up\n", __func__);
+		return -ENETRESET;
+	} else if ((svc->dest_id == APR_DEST_MODEM) &&
+		   (apr_get_modem_state() == APR_SUBSYS_DOWN)) {
+		pr_err("apr: Still Modem is not Up\n");
+		return -ENETRESET;
+	}
+
+	spin_lock_irqsave(&svc->w_lock, flags);
+	dest_id = svc->dest_id;
+	client_id = svc->client_id;
+	clnt = &client[dest_id][client_id];
+
+	if (!client[dest_id][client_id].handle) {
+		pr_err("APR: Still service is not yet opened\n");
+		spin_unlock_irqrestore(&svc->w_lock, flags);
+		return -EINVAL;
+	}
+	hdr = (struct apr_hdr *)buf;
+
+	hdr->src_domain = APR_DOMAIN_APPS;
+	hdr->src_svc = svc->id;
+	hdr->dest_domain = svc->dest_domain;
+	hdr->dest_svc = svc->id;
+
+	if (unlikely(apr_cf_debug)) {
+		APR_PKT_INFO(
+		"Tx: src_addr[0x%X] dest_addr[0x%X] opcode[0x%X] token[0x%X]",
+		(hdr->src_domain << 8) | hdr->src_svc,
+		(hdr->dest_domain << 8) | hdr->dest_svc, hdr->opcode,
+		hdr->token);
+	}
+
+	rc = apr_tal_write(clnt->handle, buf,
+			(struct apr_pkt_priv *)&svc->pkt_owner,
+			hdr->pkt_size);
+	if (rc >= 0) {
+		w_len = rc;
+		if (w_len != hdr->pkt_size) {
+			pr_err("%s: Unable to write whole APR pkt successfully: %d\n",
+			       __func__, rc);
+			rc = -EINVAL;
+		}
+	} else {
+		pr_err("%s: Write APR pkt failed with error %d\n",
+			__func__, rc);
+	}
+	spin_unlock_irqrestore(&svc->w_lock, flags);
+
+	return rc;
+}
+
+int apr_pkt_config(void *handle, struct apr_pkt_cfg *cfg)
+{
+	struct apr_svc *svc = (struct apr_svc *)handle;
+	uint16_t dest_id;
+	uint16_t client_id;
+	struct apr_client *clnt;
+
+	if (!handle) {
+		pr_err("%s: Invalid handle\n", __func__);
+		return -EINVAL;
+	}
+
+	if (svc->need_reset) {
+		pr_err("%s: service need reset\n", __func__);
+		return -ENETRESET;
+	}
+
+	svc->pkt_owner = cfg->pkt_owner;
+	dest_id = svc->dest_id;
+	client_id = svc->client_id;
+	clnt = &client[dest_id][client_id];
+
+	return apr_tal_rx_intents_config(clnt->handle,
+		cfg->intents.num_of_intents, cfg->intents.size);
+}
+
+struct apr_svc *apr_register(char *dest, char *svc_name, apr_fn svc_fn,
+				uint32_t src_port, void *priv)
+{
+	struct apr_client *clnt;
+	int client_id = 0;
+	int svc_idx = 0;
+	int svc_id = 0;
+	int dest_id = 0;
+	int domain_id = 0;
+	int temp_port = 0;
+	struct apr_svc *svc = NULL;
+	int rc = 0;
+	bool can_open_channel = true;
+
+	if (!dest || !svc_name || !svc_fn)
+		return NULL;
+
+	if (!strcmp(dest, "ADSP"))
+		domain_id = APR_DOMAIN_ADSP;
+	else if (!strcmp(dest, "MODEM")) {
+		/* Don't request for SMD channels if destination is MODEM,
+		 * as these channels are no longer used and these clients
+		 * are to listen only for MODEM SSR events
+		 */
+		can_open_channel = false;
+		domain_id = APR_DOMAIN_MODEM;
+	} else {
+		pr_err("APR: wrong destination\n");
+		goto done;
+	}
+
+	dest_id = apr_get_dest_id(dest);
+
+	if (dest_id == APR_DEST_QDSP6) {
+		if (apr_get_q6_state() != APR_SUBSYS_LOADED) {
+			pr_err("%s: adsp not up\n", __func__);
+			return NULL;
+		}
+		pr_debug("%s: adsp Up\n", __func__);
+	} else if (dest_id == APR_DEST_MODEM) {
+		if (apr_get_modem_state() == APR_SUBSYS_DOWN) {
+			if (is_modem_up) {
+				pr_err("%s: modem shutdown due to SSR, ret",
+					__func__);
+				return NULL;
+			}
+			pr_debug("%s: Wait for modem to bootup\n", __func__);
+			rc = apr_wait_for_device_up(APR_DEST_MODEM);
+			if (rc == 0) {
+				pr_err("%s: Modem is not Up\n", __func__);
+				return NULL;
+			}
+		}
+		pr_debug("%s: modem Up\n", __func__);
+	}
+
+	if (apr_get_svc(svc_name, domain_id, &client_id, &svc_idx, &svc_id)) {
+		pr_err("%s: apr_get_svc failed\n", __func__);
+		goto done;
+	}
+
+	clnt = &client[dest_id][client_id];
+	mutex_lock(&clnt->m_lock);
+	if (!clnt->handle && can_open_channel) {
+		clnt->handle = apr_tal_open(client_id, dest_id,
+				APR_DL_SMD, apr_cb_func, NULL);
+		if (!clnt->handle) {
+			svc = NULL;
+			pr_err("APR: Unable to open handle\n");
+			mutex_unlock(&clnt->m_lock);
+			goto done;
+		}
+	}
+	mutex_unlock(&clnt->m_lock);
+	svc = &clnt->svc[svc_idx];
+	mutex_lock(&svc->m_lock);
+	clnt->id = client_id;
+	if (svc->need_reset) {
+		mutex_unlock(&svc->m_lock);
+		pr_err("APR: Service needs reset\n");
+		goto done;
+	}
+	svc->id = svc_id;
+	svc->dest_id = dest_id;
+	svc->client_id = client_id;
+	svc->dest_domain = domain_id;
+	svc->pkt_owner = APR_PKT_OWNER_DRIVER;
+
+	if (src_port != 0xFFFFFFFF) {
+		temp_port = ((src_port >> 8) * 8) + (src_port & 0xFF);
+		pr_debug("port = %d t_port = %d\n", src_port, temp_port);
+		if (temp_port >= APR_MAX_PORTS || temp_port < 0) {
+			pr_err("APR: temp_port out of bounds\n");
+			mutex_unlock(&svc->m_lock);
+			return NULL;
+		}
+		if (!svc->svc_cnt)
+			clnt->svc_cnt++;
+		svc->port_cnt++;
+		svc->port_fn[temp_port] = svc_fn;
+		svc->port_priv[temp_port] = priv;
+		svc->svc_cnt++;
+	} else {
+		if (!svc->fn) {
+			if (!svc->svc_cnt)
+				clnt->svc_cnt++;
+			svc->fn = svc_fn;
+			svc->priv = priv;
+			svc->svc_cnt++;
+		}
+	}
+
+	mutex_unlock(&svc->m_lock);
+done:
+	return svc;
+}
+
+
+void apr_cb_func(void *buf, int len, void *priv)
+{
+	struct apr_client_data data;
+	struct apr_client *apr_client;
+	struct apr_svc *c_svc;
+	struct apr_hdr *hdr;
+	uint16_t hdr_size;
+	uint16_t msg_type;
+	uint16_t ver;
+	uint16_t src;
+	uint16_t svc;
+	uint16_t clnt;
+	int i;
+	int temp_port = 0;
+	uint32_t *ptr;
+
+	pr_debug("APR2: len = %d\n", len);
+	ptr = buf;
+	pr_debug("\n*****************\n");
+	for (i = 0; i < len/4; i++)
+		pr_debug("%x  ", ptr[i]);
+	pr_debug("\n");
+	pr_debug("\n*****************\n");
+
+	if (!buf || len <= APR_HDR_SIZE) {
+		pr_err("APR: Improper apr pkt received:%pK %d\n", buf, len);
+		return;
+	}
+	hdr = buf;
+
+	ver = hdr->hdr_field;
+	ver = (ver & 0x000F);
+	if (ver > APR_PKT_VER + 1) {
+		pr_err("APR: Wrong version: %d\n", ver);
+		return;
+	}
+
+	hdr_size = hdr->hdr_field;
+	hdr_size = ((hdr_size & 0x00F0) >> 0x4) * 4;
+	if (hdr_size < APR_HDR_SIZE) {
+		pr_err("APR: Wrong hdr size:%d\n", hdr_size);
+		return;
+	}
+
+	if (hdr->pkt_size < APR_HDR_SIZE) {
+		pr_err("APR: Wrong paket size\n");
+		return;
+	}
+	msg_type = hdr->hdr_field;
+	msg_type = (msg_type >> 0x08) & 0x0003;
+	if (msg_type >= APR_MSG_TYPE_MAX && msg_type != APR_BASIC_RSP_RESULT) {
+		pr_err("APR: Wrong message type: %d\n", msg_type);
+		return;
+	}
+
+	if (hdr->src_domain >= APR_DOMAIN_MAX ||
+		hdr->dest_domain >= APR_DOMAIN_MAX ||
+		hdr->src_svc >= APR_SVC_MAX ||
+		hdr->dest_svc >= APR_SVC_MAX) {
+		pr_err("APR: Wrong APR header\n");
+		return;
+	}
+
+	svc = hdr->dest_svc;
+	if (hdr->src_domain == APR_DOMAIN_MODEM) {
+		if (svc == APR_SVC_MVS || svc == APR_SVC_MVM ||
+		    svc == APR_SVC_CVS || svc == APR_SVC_CVP ||
+		    svc == APR_SVC_TEST_CLIENT)
+			clnt = APR_CLIENT_VOICE;
+		else {
+			pr_err("APR: Wrong svc :%d\n", svc);
+			return;
+		}
+	} else if (hdr->src_domain == APR_DOMAIN_ADSP) {
+		if (svc == APR_SVC_AFE || svc == APR_SVC_ASM ||
+		    svc == APR_SVC_VSM || svc == APR_SVC_VPM ||
+		    svc == APR_SVC_ADM || svc == APR_SVC_ADSP_CORE ||
+		    svc == APR_SVC_USM ||
+		    svc == APR_SVC_TEST_CLIENT || svc == APR_SVC_ADSP_MVM ||
+		    svc == APR_SVC_ADSP_CVS || svc == APR_SVC_ADSP_CVP ||
+		    svc == APR_SVC_LSM)
+			clnt = APR_CLIENT_AUDIO;
+		else if (svc == APR_SVC_VIDC)
+			clnt = APR_CLIENT_AUDIO;
+		else {
+			pr_err("APR: Wrong svc :%d\n", svc);
+			return;
+		}
+	} else {
+		pr_err("APR: Pkt from wrong source: %d\n", hdr->src_domain);
+		return;
+	}
+
+	src = apr_get_data_src(hdr);
+	if (src == APR_DEST_MAX)
+		return;
+
+	pr_debug("src =%d clnt = %d\n", src, clnt);
+	apr_client = &client[src][clnt];
+	for (i = 0; i < APR_SVC_MAX; i++)
+		if (apr_client->svc[i].id == svc) {
+			pr_debug("%d\n", apr_client->svc[i].id);
+			c_svc = &apr_client->svc[i];
+			break;
+		}
+
+	if (i == APR_SVC_MAX) {
+		pr_err("APR: service is not registered\n");
+		return;
+	}
+	pr_debug("svc_idx = %d\n", i);
+	pr_debug("%x %x %x %pK %pK\n", c_svc->id, c_svc->dest_id,
+		 c_svc->client_id, c_svc->fn, c_svc->priv);
+	data.payload_size = hdr->pkt_size - hdr_size;
+	data.opcode = hdr->opcode;
+	data.src = src;
+	data.src_port = hdr->src_port;
+	data.dest_port = hdr->dest_port;
+	data.token = hdr->token;
+	data.msg_type = msg_type;
+	data.payload = NULL;
+	if (data.payload_size > 0)
+		data.payload = (char *)hdr + hdr_size;
+
+	if (unlikely(apr_cf_debug)) {
+		if (hdr->opcode == APR_BASIC_RSP_RESULT && data.payload) {
+			uint32_t *ptr = data.payload;
+
+			APR_PKT_INFO(
+			"Rx: src_addr[0x%X] dest_addr[0x%X] opcode[0x%X] token[0x%X] rc[0x%X]",
+			(hdr->src_domain << 8) | hdr->src_svc,
+			(hdr->dest_domain << 8) | hdr->dest_svc,
+			hdr->opcode, hdr->token, ptr[1]);
+		} else {
+			APR_PKT_INFO(
+			"Rx: src_addr[0x%X] dest_addr[0x%X] opcode[0x%X] token[0x%X]",
+			(hdr->src_domain << 8) | hdr->src_svc,
+			(hdr->dest_domain << 8) | hdr->dest_svc, hdr->opcode,
+			hdr->token);
+		}
+	}
+
+	temp_port = ((data.dest_port >> 8) * 8) + (data.dest_port & 0xFF);
+	pr_debug("port = %d t_port = %d\n", data.src_port, temp_port);
+	if (c_svc->port_cnt && c_svc->port_fn[temp_port])
+		c_svc->port_fn[temp_port](&data,  c_svc->port_priv[temp_port]);
+	else if (c_svc->fn)
+		c_svc->fn(&data, c_svc->priv);
+	else
+		pr_err("APR: Rxed a packet for NULL callback\n");
+}
+
+int apr_get_svc(const char *svc_name, int domain_id, int *client_id,
+		int *svc_idx, int *svc_id)
+{
+	int i;
+	int size;
+	struct apr_svc_table *tbl;
+	int ret = 0;
+
+	if (domain_id == APR_DOMAIN_ADSP) {
+		tbl = (struct apr_svc_table *)&svc_tbl_qdsp6;
+		size = ARRAY_SIZE(svc_tbl_qdsp6);
+	} else {
+		tbl = (struct apr_svc_table *)&svc_tbl_voice;
+		size = ARRAY_SIZE(svc_tbl_voice);
+	}
+
+	for (i = 0; i < size; i++) {
+		if (!strcmp(svc_name, tbl[i].name)) {
+			*client_id = tbl[i].client_id;
+			*svc_idx = tbl[i].idx;
+			*svc_id = tbl[i].id;
+			break;
+		}
+	}
+
+	pr_debug("%s: svc_name = %s c_id = %d domain_id = %d\n",
+		 __func__, svc_name, *client_id, domain_id);
+	if (i == size) {
+		pr_err("%s: APR: Wrong svc name %s\n", __func__, svc_name);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void apr_reset_deregister(struct work_struct *work)
+{
+	struct apr_svc *handle = NULL;
+	struct apr_reset_work *apr_reset =
+			container_of(work, struct apr_reset_work, work);
+
+	handle = apr_reset->handle;
+	pr_debug("%s:handle[%pK]\n", __func__, handle);
+	apr_deregister(handle);
+	kfree(apr_reset);
+}
+
+int apr_deregister(void *handle)
+{
+	struct apr_svc *svc = handle;
+	struct apr_client *clnt;
+	uint16_t dest_id;
+	uint16_t client_id;
+
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&svc->m_lock);
+	if (!svc->svc_cnt) {
+		pr_err("%s: svc already deregistered. svc = %pK\n",
+			__func__, svc);
+		mutex_unlock(&svc->m_lock);
+		return -EINVAL;
+	}
+
+	dest_id = svc->dest_id;
+	client_id = svc->client_id;
+	clnt = &client[dest_id][client_id];
+
+	if (svc->svc_cnt > 0) {
+		if (svc->port_cnt)
+			svc->port_cnt--;
+		svc->svc_cnt--;
+		if (!svc->svc_cnt) {
+			client[dest_id][client_id].svc_cnt--;
+			pr_debug("%s: service is reset %pK\n", __func__, svc);
+		}
+	}
+
+	if (!svc->svc_cnt) {
+		svc->priv = NULL;
+		svc->id = 0;
+		svc->fn = NULL;
+		svc->dest_id = 0;
+		svc->client_id = 0;
+		svc->need_reset = 0x0;
+	}
+	if (client[dest_id][client_id].handle &&
+	    !client[dest_id][client_id].svc_cnt) {
+		apr_tal_close(client[dest_id][client_id].handle);
+		client[dest_id][client_id].handle = NULL;
+	}
+	mutex_unlock(&svc->m_lock);
+
+	return 0;
+}
+
+void apr_reset(void *handle)
+{
+	struct apr_reset_work *apr_reset_worker = NULL;
+
+	if (!handle)
+		return;
+	pr_debug("%s: handle[%pK]\n", __func__, handle);
+
+	if (apr_reset_workqueue == NULL) {
+		pr_err("%s: apr_reset_workqueue is NULL\n", __func__);
+		return;
+	}
+
+	apr_reset_worker = kzalloc(sizeof(struct apr_reset_work),
+							GFP_ATOMIC);
+
+	if (apr_reset_worker == NULL) {
+		pr_err("%s: mem failure\n", __func__);
+		return;
+	}
+
+	apr_reset_worker->handle = handle;
+	INIT_WORK(&apr_reset_worker->work, apr_reset_deregister);
+	queue_work(apr_reset_workqueue, &apr_reset_worker->work);
+}
+
+/* Dispatch the Reset events to Modem and audio clients */
+static void dispatch_event(unsigned long code, uint16_t proc)
+{
+	struct apr_client *apr_client;
+	struct apr_client_data data;
+	struct apr_svc *svc;
+	uint16_t clnt;
+	int i, j;
+
+	data.opcode = RESET_EVENTS;
+	data.reset_event = code;
+
+	/* Service domain can be different from the processor */
+	data.reset_proc = apr_get_reset_domain(proc);
+
+	clnt = APR_CLIENT_AUDIO;
+	apr_client = &client[proc][clnt];
+	for (i = 0; i < APR_SVC_MAX; i++) {
+		mutex_lock(&apr_client->svc[i].m_lock);
+		if (apr_client->svc[i].fn) {
+			apr_client->svc[i].need_reset = 0x1;
+			apr_client->svc[i].fn(&data, apr_client->svc[i].priv);
+		}
+		if (apr_client->svc[i].port_cnt) {
+			svc = &(apr_client->svc[i]);
+			svc->need_reset = 0x1;
+			for (j = 0; j < APR_MAX_PORTS; j++)
+				if (svc->port_fn[j])
+					svc->port_fn[j](&data,
+						svc->port_priv[j]);
+		}
+		mutex_unlock(&apr_client->svc[i].m_lock);
+	}
+
+	clnt = APR_CLIENT_VOICE;
+	apr_client = &client[proc][clnt];
+	for (i = 0; i < APR_SVC_MAX; i++) {
+		mutex_lock(&apr_client->svc[i].m_lock);
+		if (apr_client->svc[i].fn) {
+			apr_client->svc[i].need_reset = 0x1;
+			apr_client->svc[i].fn(&data, apr_client->svc[i].priv);
+		}
+		if (apr_client->svc[i].port_cnt) {
+			svc = &(apr_client->svc[i]);
+			svc->need_reset = 0x1;
+			for (j = 0; j < APR_MAX_PORTS; j++)
+				if (svc->port_fn[j])
+					svc->port_fn[j](&data,
+						svc->port_priv[j]);
+		}
+		mutex_unlock(&apr_client->svc[i].m_lock);
+	}
+}
+
+static int apr_notifier_service_cb(struct notifier_block *this,
+				   unsigned long opcode, void *data)
+{
+	struct audio_notifier_cb_data *cb_data = data;
+
+	if (cb_data == NULL) {
+		pr_err("%s: Callback data is NULL!\n", __func__);
+		goto done;
+	}
+
+	pr_debug("%s: Service opcode 0x%lx, domain %d\n",
+		__func__, opcode, cb_data->domain);
+
+	switch (opcode) {
+	case AUDIO_NOTIFIER_SERVICE_DOWN:
+		/*
+		 * Use flag to ignore down notifications during
+		 * initial boot. There is no benefit from error
+		 * recovery notifications during initial boot
+		 * up since everything is expected to be down.
+		 */
+		if (is_initial_boot) {
+			is_initial_boot = false;
+			break;
+		}
+		if (cb_data->domain == AUDIO_NOTIFIER_MODEM_DOMAIN)
+			apr_modem_down(opcode);
+		else
+			apr_adsp_down(opcode);
+		break;
+	case AUDIO_NOTIFIER_SERVICE_UP:
+		is_initial_boot = false;
+		if (cb_data->domain == AUDIO_NOTIFIER_MODEM_DOMAIN)
+			apr_modem_up();
+		else
+			apr_adsp_up();
+		break;
+	default:
+		break;
+	}
+done:
+	return NOTIFY_OK;
+}
+
+static struct notifier_block adsp_service_nb = {
+	.notifier_call  = apr_notifier_service_cb,
+	.priority = 0,
+};
+
+static struct notifier_block modem_service_nb = {
+	.notifier_call  = apr_notifier_service_cb,
+	.priority = 0,
+};
+
+static int __init apr_init(void)
+{
+	int i, j, k;
+
+	for (i = 0; i < APR_DEST_MAX; i++)
+		for (j = 0; j < APR_CLIENT_MAX; j++) {
+			mutex_init(&client[i][j].m_lock);
+			for (k = 0; k < APR_SVC_MAX; k++) {
+				mutex_init(&client[i][j].svc[k].m_lock);
+				spin_lock_init(&client[i][j].svc[k].w_lock);
+			}
+		}
+	apr_set_subsys_state();
+	mutex_init(&q6.lock);
+	apr_reset_workqueue = create_singlethread_workqueue("apr_driver");
+	if (!apr_reset_workqueue)
+		return -ENOMEM;
+
+	apr_pkt_ctx = ipc_log_context_create(APR_PKT_IPC_LOG_PAGE_CNT,
+						"apr", 0);
+	if (!apr_pkt_ctx)
+		pr_err("%s: Unable to create ipc log context\n", __func__);
+
+	is_initial_boot = true;
+	subsys_notif_register("apr_adsp", AUDIO_NOTIFIER_ADSP_DOMAIN,
+			      &adsp_service_nb);
+	subsys_notif_register("apr_modem", AUDIO_NOTIFIER_MODEM_DOMAIN,
+			      &modem_service_nb);
+
+	return 0;
+}
+device_initcall(apr_init);
+
+static int __init apr_late_init(void)
+{
+	int ret = 0;
+
+	init_waitqueue_head(&dsp_wait);
+	init_waitqueue_head(&modem_wait);
+
+	return ret;
+}
+late_initcall(apr_late_init);
+
+#ifdef CONFIG_DEBUG_FS
+static int __init apr_debug_init(void)
+{
+	debugfs_apr_debug = debugfs_create_file("msm_apr_debug",
+						 S_IFREG | 0444, NULL, NULL,
+						 &apr_debug_ops);
+	return 0;
+}
+device_initcall(apr_debug_init);
+#endif

+ 451 - 0
drivers/soc/qcom/qdsp6v2/apr_tal_glink.c

@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <soc/qcom/glink.h>
+#include <linux/qdsp6v2/apr_tal.h>
+
+#define APR_MAXIMUM_NUM_OF_RETRIES 2
+
+struct apr_tx_buf {
+	struct apr_pkt_priv pkt_priv;
+	char buf[APR_MAX_BUF];
+};
+
+struct link_state {
+	uint32_t dest;
+	void *handle;
+	enum glink_link_state link_state;
+	wait_queue_head_t wait;
+};
+
+static struct link_state link_state[APR_DEST_MAX];
+
+static char *svc_names[APR_DEST_MAX][APR_CLIENT_MAX] = {
+	{
+		"apr_audio_svc",
+		"apr_voice_svc",
+	},
+	{
+		"apr_audio_svc",
+		"apr_voice_svc",
+	},
+};
+
+static struct apr_svc_ch_dev
+	apr_svc_ch[APR_DL_MAX][APR_DEST_MAX][APR_CLIENT_MAX];
+
+static struct apr_tx_buf *apr_alloc_buf(int len)
+{
+
+	if (len > APR_MAX_BUF) {
+		pr_err("%s: buf too large [%d]\n", __func__, len);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return kzalloc(sizeof(struct apr_tx_buf), GFP_ATOMIC);
+}
+
+static void apr_free_buf(const void *ptr)
+{
+
+	struct apr_pkt_priv *apr_pkt_priv = (struct apr_pkt_priv *)ptr;
+	struct apr_tx_buf *tx_buf;
+
+	if (!apr_pkt_priv) {
+		pr_err("%s: Invalid apr_pkt_priv\n", __func__);
+		return;
+	}
+
+	if (apr_pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) {
+		tx_buf = container_of((void *)apr_pkt_priv,
+				      struct apr_tx_buf, pkt_priv);
+		pr_debug("%s: Freeing buffer %pK", __func__, tx_buf);
+		kfree(tx_buf);
+	}
+}
+
+
+static int __apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
+			   struct apr_pkt_priv *pkt_priv, int len)
+{
+	int rc = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&apr_ch->w_lock, flags);
+	rc = glink_tx(apr_ch->handle, pkt_priv, data, len, GLINK_TX_ATOMIC);
+	spin_unlock_irqrestore(&apr_ch->w_lock, flags);
+
+	if (rc)
+		pr_err("%s: glink_tx failed, rc[%d]\n", __func__, rc);
+	else
+		rc = len;
+
+	return rc;
+}
+
+int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
+		  struct apr_pkt_priv *pkt_priv, int len)
+{
+	int rc = 0, retries = 0;
+	void *pkt_data = NULL;
+	struct apr_tx_buf *tx_buf = NULL;
+	struct apr_pkt_priv *pkt_priv_ptr = pkt_priv;
+
+	if (!apr_ch->handle || !pkt_priv)
+		return -EINVAL;
+
+	if (pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) {
+		tx_buf = apr_alloc_buf(len);
+		if (IS_ERR_OR_NULL(tx_buf)) {
+			rc = -EINVAL;
+			goto exit;
+		}
+		memcpy(tx_buf->buf, data, len);
+		memcpy(&tx_buf->pkt_priv, pkt_priv, sizeof(tx_buf->pkt_priv));
+		pkt_priv_ptr = &tx_buf->pkt_priv;
+		pkt_data = tx_buf->buf;
+	} else {
+		pkt_data = data;
+	}
+
+	do {
+		if (rc == -EAGAIN)
+			udelay(50);
+
+		rc = __apr_tal_write(apr_ch, pkt_data, pkt_priv_ptr, len);
+	} while (rc == -EAGAIN && retries++ < APR_MAXIMUM_NUM_OF_RETRIES);
+
+	if (rc < 0) {
+		pr_err("%s: Unable to send the packet, rc:%d\n", __func__, rc);
+		if (pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER)
+			kfree(tx_buf);
+	}
+exit:
+	return rc;
+}
+
+void apr_tal_notify_rx(void *handle, const void *priv, const void *pkt_priv,
+		       const void *ptr, size_t size)
+{
+	struct apr_svc_ch_dev *apr_ch = (struct apr_svc_ch_dev *)priv;
+	unsigned long flags;
+
+	if (!apr_ch || !ptr) {
+		pr_err("%s: Invalid apr_ch or ptr\n", __func__);
+		return;
+	}
+
+	pr_debug("%s: Rx packet received\n", __func__);
+
+	spin_lock_irqsave(&apr_ch->r_lock, flags);
+	if (apr_ch->func)
+		apr_ch->func((void *)ptr, size, (void *)pkt_priv);
+	spin_unlock_irqrestore(&apr_ch->r_lock, flags);
+	glink_rx_done(apr_ch->handle, ptr, true);
+}
+
+static void apr_tal_notify_tx_abort(void *handle, const void *priv,
+				    const void *pkt_priv)
+{
+	pr_debug("%s: tx_abort received for pkt_priv:%pK\n",
+		 __func__, pkt_priv);
+	apr_free_buf(pkt_priv);
+}
+
+void apr_tal_notify_tx_done(void *handle, const void *priv,
+			    const void *pkt_priv, const void *ptr)
+{
+	pr_debug("%s: tx_done received for pkt_priv:%pK\n",
+		 __func__, pkt_priv);
+	apr_free_buf(pkt_priv);
+}
+
+bool apr_tal_notify_rx_intent_req(void *handle, const void *priv,
+				  size_t req_size)
+{
+	struct apr_svc_ch_dev *apr_ch = (struct apr_svc_ch_dev *)priv;
+
+	if (!apr_ch) {
+		pr_err("%s: Invalid apr_ch\n", __func__);
+		return false;
+	}
+
+	pr_err("%s: No rx intents queued, unable to receive\n", __func__);
+	return false;
+}
+
+static void apr_tal_notify_remote_rx_intent(void *handle, const void *priv,
+					    size_t size)
+{
+	struct apr_svc_ch_dev *apr_ch = (struct apr_svc_ch_dev *)priv;
+
+	if (!apr_ch) {
+		pr_err("%s: Invalid apr_ch\n", __func__);
+		return;
+	}
+	/*
+	 * This is to make sure that the far end has queued at least one intent
+	 * before we attmpt any IPC. A simple bool flag is used here instead of
+	 * a counter, as the far end is required to guarantee intent
+	 * availability for all use cases once the channel is fully opened.
+	 */
+	pr_debug("%s: remote queued an intent\n", __func__);
+	apr_ch->if_remote_intent_ready = true;
+	wake_up(&apr_ch->wait);
+}
+
+void apr_tal_notify_state(void *handle, const void *priv, unsigned int event)
+{
+	struct apr_svc_ch_dev *apr_ch = (struct apr_svc_ch_dev *)priv;
+
+	if (!apr_ch) {
+		pr_err("%s: Invalid apr_ch\n", __func__);
+		return;
+	}
+
+	apr_ch->channel_state = event;
+	pr_info("%s: Channel state[%d]\n", __func__, event);
+
+	if (event == GLINK_CONNECTED)
+		wake_up(&apr_ch->wait);
+}
+
+int apr_tal_rx_intents_config(struct apr_svc_ch_dev *apr_ch,
+			      int num_of_intents, uint32_t size)
+{
+	int i;
+	int rc;
+
+	if (!apr_ch || !num_of_intents || !size) {
+		pr_err("%s: Invalid parameter\n", __func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num_of_intents; i++) {
+		rc = glink_queue_rx_intent(apr_ch->handle, apr_ch, size);
+		if (rc) {
+			pr_err("%s: Failed to queue rx intent, iteration[%d]\n",
+			       __func__, i);
+			break;
+		}
+	}
+
+	return rc;
+}
+
+struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest, uint32_t dl,
+				    apr_svc_cb_fn func, void *priv)
+{
+	int rc;
+	struct glink_open_config open_cfg;
+	struct apr_svc_ch_dev *apr_ch;
+
+	if ((clnt >= APR_CLIENT_MAX) || (dest >= APR_DEST_MAX) ||
+	    (dl >= APR_DL_MAX)) {
+		pr_err("%s: Invalid params, clnt:%d, dest:%d, dl:%d\n",
+		       __func__, clnt, dest, dl);
+		return NULL;
+	}
+
+	apr_ch = &apr_svc_ch[dl][dest][clnt];
+	mutex_lock(&apr_ch->m_lock);
+	if (apr_ch->handle) {
+		pr_err("%s: This channel is already opened\n", __func__);
+		rc = -EBUSY;
+		goto unlock;
+	}
+
+	if (link_state[dest].link_state != GLINK_LINK_STATE_UP) {
+		rc = wait_event_timeout(link_state[dest].wait,
+			link_state[dest].link_state == GLINK_LINK_STATE_UP,
+			msecs_to_jiffies(APR_OPEN_TIMEOUT_MS));
+		if (rc == 0) {
+			pr_err("%s: Open timeout, dest:%d\n", __func__, dest);
+			rc = -ETIMEDOUT;
+			goto unlock;
+		}
+		pr_debug("%s: Wakeup done, dest:%d\n", __func__, dest);
+	}
+
+	memset(&open_cfg, 0, sizeof(struct glink_open_config));
+	open_cfg.options = GLINK_OPT_INITIAL_XPORT;
+	if (dest == APR_DEST_MODEM)
+		open_cfg.edge = "mpss";
+	else
+		open_cfg.edge = "lpass";
+
+	open_cfg.name = svc_names[dest][clnt];
+	open_cfg.notify_rx = apr_tal_notify_rx;
+	open_cfg.notify_tx_done = apr_tal_notify_tx_done;
+	open_cfg.notify_state = apr_tal_notify_state;
+	open_cfg.notify_rx_intent_req = apr_tal_notify_rx_intent_req;
+	open_cfg.notify_remote_rx_intent = apr_tal_notify_remote_rx_intent;
+	open_cfg.notify_tx_abort = apr_tal_notify_tx_abort;
+	open_cfg.priv = apr_ch;
+	open_cfg.transport = "smem";
+
+	apr_ch->channel_state = GLINK_REMOTE_DISCONNECTED;
+	apr_ch->handle = glink_open(&open_cfg);
+	if (IS_ERR_OR_NULL(apr_ch->handle)) {
+		pr_err("%s: glink_open failed %s\n", __func__,
+		       svc_names[dest][clnt]);
+		apr_ch->handle = NULL;
+		rc = -EINVAL;
+		goto unlock;
+	}
+
+	rc = wait_event_timeout(apr_ch->wait,
+		(apr_ch->channel_state == GLINK_CONNECTED), 5 * HZ);
+	if (rc == 0) {
+		pr_err("%s: TIMEOUT for OPEN event\n", __func__);
+		rc = -ETIMEDOUT;
+		goto close_link;
+	}
+
+	/*
+	 * Remote intent is not required for GLINK <--> SMD IPC, so this is
+	 * designed not to fail the open call.
+	 */
+	rc = wait_event_timeout(apr_ch->wait,
+		apr_ch->if_remote_intent_ready, 5 * HZ);
+	if (rc == 0)
+		pr_err("%s: TIMEOUT for remote intent readiness\n", __func__);
+
+	rc = apr_tal_rx_intents_config(apr_ch, APR_DEFAULT_NUM_OF_INTENTS,
+				       APR_MAX_BUF);
+	if (rc) {
+		pr_err("%s: Unable to queue intents\n", __func__);
+		goto close_link;
+	}
+
+	apr_ch->func = func;
+	apr_ch->priv = priv;
+
+close_link:
+	if (rc) {
+		glink_close(apr_ch->handle);
+		apr_ch->handle = NULL;
+	}
+unlock:
+	mutex_unlock(&apr_ch->m_lock);
+
+	return rc ? NULL : apr_ch;
+}
+
+int apr_tal_close(struct apr_svc_ch_dev *apr_ch)
+{
+	int rc;
+
+	if (!apr_ch || !apr_ch->handle) {
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	mutex_lock(&apr_ch->m_lock);
+	rc = glink_close(apr_ch->handle);
+	apr_ch->handle = NULL;
+	apr_ch->func = NULL;
+	apr_ch->priv = NULL;
+	apr_ch->if_remote_intent_ready = false;
+	mutex_unlock(&apr_ch->m_lock);
+exit:
+	return rc;
+}
+
+static void apr_tal_link_state_cb(struct glink_link_state_cb_info *cb_info,
+				  void *priv)
+{
+	uint32_t dest;
+
+	if (!cb_info) {
+		pr_err("%s: Invalid cb_info\n", __func__);
+		return;
+	}
+
+	if (!strcmp(cb_info->edge, "mpss"))
+		dest = APR_DEST_MODEM;
+	else if (!strcmp(cb_info->edge, "lpass"))
+		dest = APR_DEST_QDSP6;
+	else {
+		pr_err("%s:Unknown edge[%s]\n", __func__, cb_info->edge);
+		return;
+	}
+
+	pr_info("%s: edge[%s] link state[%d]\n", __func__, cb_info->edge,
+		cb_info->link_state);
+
+	link_state[dest].link_state = cb_info->link_state;
+	if (link_state[dest].link_state == GLINK_LINK_STATE_UP)
+		wake_up(&link_state[dest].wait);
+}
+
+static struct glink_link_info mpss_link_info = {
+	.transport = "smem",
+	.edge = "mpss",
+	.glink_link_state_notif_cb = apr_tal_link_state_cb,
+};
+
+static struct glink_link_info lpass_link_info = {
+	.transport = "smem",
+	.edge = "lpass",
+	.glink_link_state_notif_cb = apr_tal_link_state_cb,
+};
+
+static int __init apr_tal_init(void)
+{
+	int i, j, k;
+
+	for (i = 0; i < APR_DL_MAX; i++) {
+		for (j = 0; j < APR_DEST_MAX; j++) {
+			for (k = 0; k < APR_CLIENT_MAX; k++) {
+				init_waitqueue_head(&apr_svc_ch[i][j][k].wait);
+				spin_lock_init(&apr_svc_ch[i][j][k].w_lock);
+				spin_lock_init(&apr_svc_ch[i][j][k].r_lock);
+				mutex_init(&apr_svc_ch[i][j][k].m_lock);
+			}
+		}
+	}
+
+	for (i = 0; i < APR_DEST_MAX; i++)
+		init_waitqueue_head(&link_state[i].wait);
+
+	link_state[APR_DEST_MODEM].link_state = GLINK_LINK_STATE_DOWN;
+	link_state[APR_DEST_MODEM].handle =
+		glink_register_link_state_cb(&mpss_link_info, NULL);
+	if (!link_state[APR_DEST_MODEM].handle)
+		pr_err("%s: Unable to register mpss link state\n", __func__);
+
+	link_state[APR_DEST_QDSP6].link_state = GLINK_LINK_STATE_DOWN;
+	link_state[APR_DEST_QDSP6].handle =
+		glink_register_link_state_cb(&lpass_link_info, NULL);
+	if (!link_state[APR_DEST_QDSP6].handle)
+		pr_err("%s: Unable to register lpass link state\n", __func__);
+
+	return 0;
+}
+device_initcall(apr_tal_init);

+ 67 - 0
drivers/soc/qcom/qdsp6v2/apr_v2.c

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/types.h>
+#include <linux/uaccess.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/qdsp6v2/apr.h>
+#include <linux/qdsp6v2/apr_tal.h>
+#include <linux/qdsp6v2/dsp_debug.h>
+#include <linux/qdsp6v2/audio_notifier.h>
+
+enum apr_subsys_state apr_get_subsys_state(void)
+{
+	return apr_get_q6_state();
+}
+
+void apr_set_subsys_state(void)
+{
+	apr_set_q6_state(APR_SUBSYS_DOWN);
+	apr_set_modem_state(APR_SUBSYS_UP);
+}
+
+uint16_t apr_get_data_src(struct apr_hdr *hdr)
+{
+	if (hdr->src_domain == APR_DOMAIN_MODEM)
+		return APR_DEST_MODEM;
+	else if (hdr->src_domain == APR_DOMAIN_ADSP)
+		return APR_DEST_QDSP6;
+
+	pr_err("APR: Pkt from wrong source: %d\n", hdr->src_domain);
+	return APR_DEST_MAX;		/*RETURN INVALID VALUE*/
+}
+
+int apr_get_dest_id(char *dest)
+{
+	if (!strcmp(dest, "ADSP"))
+		return APR_DEST_QDSP6;
+	else
+		return APR_DEST_MODEM;
+}
+
+void subsys_notif_register(char *client_name, int domain,
+			   struct notifier_block *nb)
+{
+	int ret;
+
+	ret = audio_notifier_register(client_name, domain, nb);
+	if (ret < 0)
+		pr_err("%s: Audio notifier register failed for domain %d ret = %d\n",
+			__func__, domain, ret);
+}
+
+uint16_t apr_get_reset_domain(uint16_t proc)
+{
+	return proc;
+}

+ 65 - 0
drivers/soc/qcom/qdsp6v2/apr_v3.c

@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/types.h>
+#include <linux/uaccess.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/qdsp6v2/apr.h>
+#include <linux/qdsp6v2/apr_tal.h>
+#include <linux/qdsp6v2/dsp_debug.h>
+#include <linux/qdsp6v2/audio_notifier.h>
+
+#define DEST_ID APR_DEST_MODEM
+
+enum apr_subsys_state apr_get_subsys_state(void)
+{
+	return apr_get_modem_state();
+}
+
+void apr_set_subsys_state(void)
+{
+	apr_set_modem_state(APR_SUBSYS_DOWN);
+}
+
+uint16_t apr_get_data_src(struct apr_hdr *hdr)
+{
+	return DEST_ID;
+}
+
+int apr_get_dest_id(char *dest)
+{
+	return DEST_ID;
+}
+
+void subsys_notif_register(char *client_name, int domain,
+			   struct notifier_block *nb)
+{
+	int ret;
+
+	if (domain != AUDIO_NOTIFIER_MODEM_DOMAIN) {
+		pr_debug("%s: Unused domain %d not registering with notifier\n",
+			 __func__, domain);
+		return;
+	}
+
+	ret = audio_notifier_register(client_name, domain, nb);
+	if (ret < 0)
+		pr_err("%s: Audio notifier register failed for domain %d ret = %d\n",
+			__func__, domain, ret);
+}
+
+uint16_t apr_get_reset_domain(uint16_t proc)
+{
+	return APR_DEST_QDSP6;
+}

+ 636 - 0
drivers/soc/qcom/qdsp6v2/audio_notifier.c

@@ -0,0 +1,636 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/slab.h>
+#include <linux/qdsp6v2/audio_pdr.h>
+#include <linux/qdsp6v2/audio_ssr.h>
+#include <linux/qdsp6v2/audio_notifier.h>
+#include <soc/qcom/scm.h>
+#include <soc/qcom/subsystem_notif.h>
+#include <soc/qcom/service-notifier.h>
+
+/* Audio states internal to notifier. Client */
+/* used states defined in audio_notifier.h */
+/* for AUDIO_NOTIFIER_SERVICE_DOWN & UP */
+#define NO_SERVICE -2
+#define UNINIT_SERVICE -1
+
+/*
+ * Used for each client registered with audio notifier
+ */
+struct client_data {
+	struct list_head        list;
+	/* Notifier block given by client */
+	struct notifier_block   *nb;
+	char                    client_name[20];
+	int                     service;
+	int                     domain;
+};
+
+/*
+ * Used for each service and domain combination
+ * Tracks information specific to the underlying
+ * service.
+ */
+struct service_info {
+	const char                      name[20];
+	int                             domain_id;
+	int                             state;
+	void                            *handle;
+	/* Notifier block registered to service */
+	struct notifier_block           *nb;
+	/* Used to determine when to register and deregister service */
+	int                             num_of_clients;
+	/* List of all clients registered to the service and domain */
+	struct srcu_notifier_head       client_nb_list;
+};
+
+static int audio_notifer_ssr_adsp_cb(struct notifier_block *this,
+				     unsigned long opcode, void *data);
+static int audio_notifer_ssr_modem_cb(struct notifier_block *this,
+				     unsigned long opcode, void *data);
+static int audio_notifer_pdr_adsp_cb(struct notifier_block *this,
+				     unsigned long opcode, void *data);
+
+static struct notifier_block notifier_ssr_adsp_nb = {
+	.notifier_call  = audio_notifer_ssr_adsp_cb,
+	.priority = 0,
+};
+
+static struct notifier_block notifier_ssr_modem_nb = {
+	.notifier_call  = audio_notifer_ssr_modem_cb,
+	.priority = 0,
+};
+
+static struct notifier_block notifier_pdr_adsp_nb = {
+	.notifier_call  = audio_notifer_pdr_adsp_cb,
+	.priority = 0,
+};
+
+static struct service_info service_data[AUDIO_NOTIFIER_MAX_SERVICES]
+				       [AUDIO_NOTIFIER_MAX_DOMAINS] = {
+
+	{{
+		.name = "SSR_ADSP",
+		.domain_id = AUDIO_SSR_DOMAIN_ADSP,
+		.state = AUDIO_NOTIFIER_SERVICE_DOWN,
+		.nb = &notifier_ssr_adsp_nb
+	},
+	{
+		.name = "SSR_MODEM",
+		.domain_id = AUDIO_SSR_DOMAIN_MODEM,
+		.state = AUDIO_NOTIFIER_SERVICE_DOWN,
+		.nb = &notifier_ssr_modem_nb
+	} },
+
+	{{
+		.name = "PDR_ADSP",
+		.domain_id = AUDIO_PDR_DOMAIN_ADSP,
+		.state = UNINIT_SERVICE,
+		.nb = &notifier_pdr_adsp_nb
+	},
+	{	/* PDR MODEM service not enabled */
+		.name = "INVALID",
+		.state = NO_SERVICE,
+		.nb = NULL
+	} }
+};
+
+/* Master list of all audio notifier clients */
+struct list_head   client_list;
+struct mutex       notifier_mutex;
+
+static int audio_notifer_get_default_service(int domain)
+{
+	int service = NO_SERVICE;
+
+	/* initial service to connect per domain */
+	switch (domain) {
+	case AUDIO_NOTIFIER_ADSP_DOMAIN:
+		service = AUDIO_NOTIFIER_PDR_SERVICE;
+		break;
+	case AUDIO_NOTIFIER_MODEM_DOMAIN:
+		service = AUDIO_NOTIFIER_SSR_SERVICE;
+		break;
+	}
+
+	return service;
+}
+
+static void audio_notifer_disable_service(int service)
+{
+	int i;
+
+	for (i = 0; i < AUDIO_NOTIFIER_MAX_DOMAINS; i++)
+		service_data[service][i].state = NO_SERVICE;
+}
+
+static bool audio_notifer_is_service_enabled(int service)
+{
+	int i;
+
+	for (i = 0; i < AUDIO_NOTIFIER_MAX_DOMAINS; i++)
+		if (service_data[service][i].state != NO_SERVICE)
+			return true;
+	return false;
+}
+
+static void audio_notifer_init_service(int service)
+{
+	int i;
+
+	for (i = 0; i < AUDIO_NOTIFIER_MAX_DOMAINS; i++) {
+		if (service_data[service][i].state == UNINIT_SERVICE)
+			service_data[service][i].state =
+				AUDIO_NOTIFIER_SERVICE_DOWN;
+	}
+}
+
+static int audio_notifer_reg_service(int service, int domain)
+{
+	void *handle;
+	int ret = 0;
+	int curr_state = AUDIO_NOTIFIER_SERVICE_DOWN;
+
+	switch (service) {
+	case AUDIO_NOTIFIER_SSR_SERVICE:
+		handle = audio_ssr_register(
+			service_data[service][domain].domain_id,
+			service_data[service][domain].nb);
+		break;
+	case AUDIO_NOTIFIER_PDR_SERVICE:
+		handle = audio_pdr_service_register(
+			service_data[service][domain].domain_id,
+			service_data[service][domain].nb, &curr_state);
+
+		if (curr_state == SERVREG_NOTIF_SERVICE_STATE_UP_V01)
+			curr_state = AUDIO_NOTIFIER_SERVICE_UP;
+		else
+			curr_state = AUDIO_NOTIFIER_SERVICE_DOWN;
+		break;
+	default:
+		pr_err("%s: Invalid service %d\n",
+			__func__, service);
+		ret = -EINVAL;
+		goto done;
+	}
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: handle is incorrect for service %s\n",
+			__func__, service_data[service][domain].name);
+		ret = -EINVAL;
+		goto done;
+	}
+	service_data[service][domain].state = curr_state;
+	service_data[service][domain].handle = handle;
+
+	pr_info("%s: service %s is in use\n",
+		__func__, service_data[service][domain].name);
+	pr_debug("%s: service %s has current state %d, handle 0x%pK\n",
+		__func__, service_data[service][domain].name,
+		service_data[service][domain].state,
+		service_data[service][domain].handle);
+done:
+	return ret;
+}
+
+static int audio_notifer_dereg_service(int service, int domain)
+{
+	int ret;
+
+	switch (service) {
+	case AUDIO_NOTIFIER_SSR_SERVICE:
+		ret = audio_ssr_deregister(
+			service_data[service][domain].handle,
+			service_data[service][domain].nb);
+		break;
+	case AUDIO_NOTIFIER_PDR_SERVICE:
+		ret = audio_pdr_service_deregister(
+			service_data[service][domain].handle,
+			service_data[service][domain].nb);
+		break;
+	default:
+		pr_err("%s: Invalid service %d\n",
+			__func__, service);
+		ret = -EINVAL;
+		goto done;
+	}
+	if (ret < 0) {
+		pr_err("%s: deregister failed for service %s, ret %d\n",
+			__func__, service_data[service][domain].name, ret);
+		goto done;
+	}
+
+	pr_debug("%s: service %s with handle 0x%pK deregistered\n",
+		__func__, service_data[service][domain].name,
+		service_data[service][domain].handle);
+
+	service_data[service][domain].state = AUDIO_NOTIFIER_SERVICE_DOWN;
+	service_data[service][domain].handle = NULL;
+done:
+	return ret;
+}
+
+static int audio_notifer_reg_client_service(struct client_data *client_data,
+					    int service)
+{
+	int ret = 0;
+	int domain = client_data->domain;
+	struct audio_notifier_cb_data data;
+
+	switch (service) {
+	case AUDIO_NOTIFIER_SSR_SERVICE:
+	case AUDIO_NOTIFIER_PDR_SERVICE:
+		if (service_data[service][domain].num_of_clients == 0)
+			ret = audio_notifer_reg_service(service, domain);
+		break;
+	default:
+		pr_err("%s: Invalid service for client %s, service %d, domain %d\n",
+			__func__, client_data->client_name, service, domain);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (ret < 0) {
+		pr_err("%s: service registration failed on service %s for client %s\n",
+			__func__, service_data[service][domain].name,
+			client_data->client_name);
+		goto done;
+	}
+
+	client_data->service = service;
+	srcu_notifier_chain_register(
+		&service_data[service][domain].client_nb_list,
+		client_data->nb);
+	service_data[service][domain].num_of_clients++;
+
+	pr_debug("%s: registered client %s on service %s, current state 0x%x\n",
+		__func__, client_data->client_name,
+		service_data[service][domain].name,
+		service_data[service][domain].state);
+
+	/*
+	 * PDR registration returns current state
+	 * Force callback of client with current state for PDR
+	 */
+	if (client_data->service == AUDIO_NOTIFIER_PDR_SERVICE) {
+		data.service = service;
+		data.domain = domain;
+		(void)client_data->nb->notifier_call(client_data->nb,
+			service_data[service][domain].state, &data);
+	}
+done:
+	return ret;
+}
+
+static int audio_notifer_reg_client(struct client_data *client_data)
+{
+	int ret = 0;
+	int service;
+	int domain = client_data->domain;
+
+	service = audio_notifer_get_default_service(domain);
+	if (service < 0) {
+		pr_err("%s: service %d is incorrect\n", __func__, service);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Search through services to find a valid one to register client on. */
+	for (; service >= 0; service--) {
+		/* If a service is not initialized, wait for it to come up. */
+		if (service_data[service][domain].state == UNINIT_SERVICE)
+			goto done;
+		/* Skip unsupported service and domain combinations. */
+		if (service_data[service][domain].state < 0)
+			continue;
+		/* Only register clients who have not acquired a service. */
+		if (client_data->service != NO_SERVICE)
+			continue;
+
+		/*
+		 * Only register clients, who have not acquired a service, on
+		 * the best available service for their domain. Uninitialized
+		 * services will try to register all of their clients after
+		 * they initialize correctly or will disable their service and
+		 * register clients on the next best avaialable service.
+		 */
+		pr_debug("%s: register client %s on service %s",
+				__func__, client_data->client_name,
+				service_data[service][domain].name);
+
+		ret = audio_notifer_reg_client_service(client_data, service);
+		if (ret < 0)
+			pr_err("%s: client %s failed to register on service %s",
+				__func__, client_data->client_name,
+				service_data[service][domain].name);
+	}
+
+done:
+	return ret;
+}
+
+static int audio_notifer_dereg_client(struct client_data *client_data)
+{
+	int ret = 0;
+	int service = client_data->service;
+	int domain = client_data->domain;
+
+	switch (client_data->service) {
+	case AUDIO_NOTIFIER_SSR_SERVICE:
+	case AUDIO_NOTIFIER_PDR_SERVICE:
+		if (service_data[service][domain].num_of_clients == 1)
+			ret = audio_notifer_dereg_service(service, domain);
+		break;
+	case NO_SERVICE:
+		goto done;
+	default:
+		pr_err("%s: Invalid service for client %s, service %d\n",
+			__func__, client_data->client_name,
+			client_data->service);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (ret < 0) {
+		pr_err("%s: deregister failed for client %s on service %s, ret %d\n",
+			__func__, client_data->client_name,
+			service_data[service][domain].name, ret);
+		goto done;
+	}
+
+	ret = srcu_notifier_chain_unregister(&service_data[service][domain].
+					     client_nb_list, client_data->nb);
+	if (ret < 0) {
+		pr_err("%s: srcu_notifier_chain_unregister failed, ret %d\n",
+			__func__, ret);
+		goto done;
+	}
+
+	pr_debug("%s: deregistered client %s on service %s\n",
+		__func__, client_data->client_name,
+		service_data[service][domain].name);
+
+	client_data->service = NO_SERVICE;
+	if (service_data[service][domain].num_of_clients > 0)
+		service_data[service][domain].num_of_clients--;
+done:
+	return ret;
+}
+
+static void audio_notifer_reg_all_clients(void)
+{
+	struct list_head *ptr, *next;
+	struct client_data *client_data;
+	int ret;
+
+	list_for_each_safe(ptr, next, &client_list) {
+		client_data = list_entry(ptr, struct client_data, list);
+
+		ret = audio_notifer_reg_client(client_data);
+		if (ret < 0)
+			pr_err("%s: audio_notifer_reg_client failed for client %s, ret %d\n",
+				__func__, client_data->client_name,
+				ret);
+	}
+}
+
+static int audio_notifer_pdr_callback(struct notifier_block *this,
+				      unsigned long opcode, void *data)
+{
+	pr_debug("%s: Audio PDR framework state 0x%lx\n",
+		__func__, opcode);
+	mutex_lock(&notifier_mutex);
+	if (opcode == AUDIO_PDR_FRAMEWORK_DOWN)
+		audio_notifer_disable_service(AUDIO_NOTIFIER_PDR_SERVICE);
+	else
+		audio_notifer_init_service(AUDIO_NOTIFIER_PDR_SERVICE);
+
+	audio_notifer_reg_all_clients();
+	mutex_unlock(&notifier_mutex);
+	return 0;
+}
+
+static struct notifier_block pdr_nb = {
+	.notifier_call  = audio_notifer_pdr_callback,
+	.priority = 0,
+};
+
+static int audio_notifer_convert_opcode(unsigned long opcode,
+					unsigned long *notifier_opcode)
+{
+	int ret = 0;
+
+	switch (opcode) {
+	case SUBSYS_BEFORE_SHUTDOWN:
+	case SERVREG_NOTIF_SERVICE_STATE_DOWN_V01:
+		*notifier_opcode = AUDIO_NOTIFIER_SERVICE_DOWN;
+		break;
+	case SUBSYS_AFTER_POWERUP:
+	case SERVREG_NOTIF_SERVICE_STATE_UP_V01:
+		*notifier_opcode = AUDIO_NOTIFIER_SERVICE_UP;
+		break;
+	default:
+		pr_debug("%s: Unused opcode 0x%lx\n", __func__, opcode);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int audio_notifer_service_cb(unsigned long opcode,
+				    int service, int domain)
+{
+	int ret = 0;
+	unsigned long notifier_opcode;
+	struct audio_notifier_cb_data data;
+
+	if (audio_notifer_convert_opcode(opcode, &notifier_opcode) < 0)
+		goto done;
+
+	data.service = service;
+	data.domain = domain;
+
+	pr_debug("%s: service %s, opcode 0x%lx\n",
+		__func__, service_data[service][domain].name, notifier_opcode);
+
+	mutex_lock(&notifier_mutex);
+
+	service_data[service][domain].state = notifier_opcode;
+	ret = srcu_notifier_call_chain(&service_data[service][domain].
+		client_nb_list, notifier_opcode, &data);
+	if (ret < 0)
+		pr_err("%s: srcu_notifier_call_chain returned %d, service %s, opcode 0x%lx\n",
+			__func__, ret, service_data[service][domain].name,
+			notifier_opcode);
+
+	mutex_unlock(&notifier_mutex);
+done:
+	return NOTIFY_OK;
+}
+
+static int audio_notifer_pdr_adsp_cb(struct notifier_block *this,
+				     unsigned long opcode, void *data)
+{
+	return audio_notifer_service_cb(opcode,
+					AUDIO_NOTIFIER_PDR_SERVICE,
+					AUDIO_NOTIFIER_ADSP_DOMAIN);
+}
+
+static int audio_notifer_ssr_adsp_cb(struct notifier_block *this,
+				     unsigned long opcode, void *data)
+{
+	if (opcode == SUBSYS_BEFORE_SHUTDOWN)
+		audio_ssr_send_nmi(data);
+
+	return audio_notifer_service_cb(opcode,
+					AUDIO_NOTIFIER_SSR_SERVICE,
+					AUDIO_NOTIFIER_ADSP_DOMAIN);
+}
+
+static int audio_notifer_ssr_modem_cb(struct notifier_block *this,
+				      unsigned long opcode, void *data)
+{
+	return audio_notifer_service_cb(opcode,
+					AUDIO_NOTIFIER_SSR_SERVICE,
+					AUDIO_NOTIFIER_MODEM_DOMAIN);
+}
+
+int audio_notifier_deregister(char *client_name)
+{
+	int ret = 0;
+	int ret2;
+	struct list_head *ptr, *next;
+	struct client_data *client_data;
+
+	if (client_name == NULL) {
+		pr_err("%s: client_name is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+	mutex_lock(&notifier_mutex);
+	list_for_each_safe(ptr, next, &client_list) {
+		client_data = list_entry(ptr, struct client_data, list);
+		if (!strcmp(client_name, client_data->client_name)) {
+			ret2 = audio_notifer_dereg_client(client_data);
+			if (ret2 < 0) {
+				pr_err("%s: audio_notifer_dereg_client failed, ret %d\n, service %d, domain %d",
+					__func__, ret2, client_data->service,
+					client_data->domain);
+				ret = ret2;
+				continue;
+			}
+			list_del(&client_data->list);
+			kfree(client_data);
+		}
+	}
+	mutex_unlock(&notifier_mutex);
+done:
+	return ret;
+}
+EXPORT_SYMBOL(audio_notifier_deregister);
+
+int audio_notifier_register(char *client_name, int domain,
+			    struct notifier_block *nb)
+{
+	int ret;
+	struct client_data *client_data;
+
+	if (client_name == NULL) {
+		pr_err("%s: client_name is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	} else if (nb == NULL) {
+		pr_err("%s: Notifier block is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	client_data = kmalloc(sizeof(*client_data), GFP_KERNEL);
+	if (client_data == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	INIT_LIST_HEAD(&client_data->list);
+	client_data->nb = nb;
+	strlcpy(client_data->client_name, client_name,
+		sizeof(client_data->client_name));
+	client_data->service = NO_SERVICE;
+	client_data->domain = domain;
+
+	mutex_lock(&notifier_mutex);
+	ret = audio_notifer_reg_client(client_data);
+	if (ret < 0) {
+		mutex_unlock(&notifier_mutex);
+		pr_err("%s: audio_notifer_reg_client for client %s failed ret = %d\n",
+			__func__, client_data->client_name,
+			ret);
+		kfree(client_data);
+		goto done;
+	}
+	list_add_tail(&client_data->list, &client_list);
+	mutex_unlock(&notifier_mutex);
+done:
+	return ret;
+}
+EXPORT_SYMBOL(audio_notifier_register);
+
+static int __init audio_notifier_subsys_init(void)
+{
+	int i, j;
+
+	mutex_init(&notifier_mutex);
+	INIT_LIST_HEAD(&client_list);
+	for (i = 0; i < AUDIO_NOTIFIER_MAX_SERVICES; i++) {
+		for (j = 0; j < AUDIO_NOTIFIER_MAX_DOMAINS; j++) {
+			if (service_data[i][j].state <= NO_SERVICE)
+				continue;
+
+			srcu_init_notifier_head(
+				&service_data[i][j].client_nb_list);
+		}
+	}
+
+	return 0;
+}
+subsys_initcall(audio_notifier_subsys_init);
+
+static int __init audio_notifier_init(void)
+{
+	int ret;
+
+	ret = audio_pdr_register(&pdr_nb);
+	if (ret < 0) {
+		pr_debug("%s: PDR register failed, ret = %d, disable service\n",
+			__func__, ret);
+		audio_notifer_disable_service(AUDIO_NOTIFIER_PDR_SERVICE);
+	}
+
+	/* Do not return error since PDR enablement is not critical */
+	return 0;
+}
+module_init(audio_notifier_init);
+
+static int __init audio_notifier_late_init(void)
+{
+	/*
+	 * If pdr registration failed, register clients on next service
+	 * Do in late init to ensure that SSR subsystem is initialized
+	 */
+	mutex_lock(&notifier_mutex);
+	if (!audio_notifer_is_service_enabled(AUDIO_NOTIFIER_PDR_SERVICE))
+		audio_notifer_reg_all_clients();
+
+	mutex_unlock(&notifier_mutex);
+	return 0;
+}
+late_initcall(audio_notifier_late_init);

+ 147 - 0
drivers/soc/qcom/qdsp6v2/audio_pdr.c

@@ -0,0 +1,147 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/slab.h>
+#include <linux/qdsp6v2/audio_pdr.h>
+#include <soc/qcom/service-locator.h>
+#include <soc/qcom/service-notifier.h>
+
+static struct pd_qmi_client_data audio_pdr_services[AUDIO_PDR_DOMAIN_MAX] = {
+	{	/* AUDIO_PDR_DOMAIN_ADSP */
+		.client_name = "audio_pdr_adsp",
+		.service_name = "avs/audio"
+	}
+};
+
+struct srcu_notifier_head audio_pdr_cb_list;
+
+static int audio_pdr_locator_callback(struct notifier_block *this,
+				      unsigned long opcode, void *data)
+{
+	unsigned long pdr_state = AUDIO_PDR_FRAMEWORK_DOWN;
+
+	if (opcode == LOCATOR_DOWN) {
+		pr_debug("%s: Service %s is down!", __func__,
+			audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
+			service_name);
+		goto done;
+	}
+
+	memcpy(&audio_pdr_services, data,
+		sizeof(audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP]));
+	if (audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].total_domains == 1) {
+		pr_debug("%s: Service %s, returned total domains %d, ",
+			__func__,
+			audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
+			audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
+			total_domains);
+		pdr_state = AUDIO_PDR_FRAMEWORK_UP;
+		goto done;
+	} else
+		pr_err("%s: Service %s returned invalid total domains %d",
+			__func__,
+			audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
+			audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
+			total_domains);
+done:
+	srcu_notifier_call_chain(&audio_pdr_cb_list, pdr_state, NULL);
+	return NOTIFY_OK;
+}
+
+static struct notifier_block audio_pdr_locator_nb = {
+	.notifier_call = audio_pdr_locator_callback,
+	.priority = 0,
+};
+
+int audio_pdr_register(struct notifier_block *nb)
+{
+	if (nb == NULL) {
+		pr_err("%s: Notifier block is NULL\n", __func__);
+		return -EINVAL;
+	}
+	return srcu_notifier_chain_register(&audio_pdr_cb_list, nb);
+}
+EXPORT_SYMBOL(audio_pdr_register);
+
+void *audio_pdr_service_register(int domain_id,
+				 struct notifier_block *nb, int *curr_state)
+{
+	void *handle;
+
+	if ((domain_id < 0) ||
+	    (domain_id >= AUDIO_PDR_DOMAIN_MAX)) {
+		pr_err("%s: Invalid service ID %d\n", __func__, domain_id);
+		return ERR_PTR(-EINVAL);
+	}
+
+	handle = service_notif_register_notifier(
+		audio_pdr_services[domain_id].domain_list[0].name,
+		audio_pdr_services[domain_id].domain_list[0].instance_id,
+		nb, curr_state);
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: Failed to register for service %s, instance %d\n",
+			__func__,
+			audio_pdr_services[domain_id].domain_list[0].name,
+			audio_pdr_services[domain_id].domain_list[0].
+			instance_id);
+	}
+	return handle;
+}
+EXPORT_SYMBOL(audio_pdr_service_register);
+
+int audio_pdr_service_deregister(void *service_handle,
+	struct notifier_block *nb)
+{
+	int ret;
+
+	if (service_handle == NULL) {
+		pr_err("%s: service handle is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ret = service_notif_unregister_notifier(
+		service_handle, nb);
+	if (ret < 0)
+		pr_err("%s: Failed to deregister service ret %d\n",
+			__func__, ret);
+done:
+	return ret;
+}
+EXPORT_SYMBOL(audio_pdr_service_deregister);
+
+static int __init audio_pdr_subsys_init(void)
+{
+	srcu_init_notifier_head(&audio_pdr_cb_list);
+	return 0;
+}
+subsys_initcall(audio_pdr_subsys_init);
+
+static int __init audio_pdr_late_init(void)
+{
+	int ret;
+
+	ret = get_service_location(
+		audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].client_name,
+		audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
+		&audio_pdr_locator_nb);
+	if (ret < 0) {
+		pr_err("%s get_service_location failed ret %d\n",
+			__func__, ret);
+		srcu_notifier_call_chain(&audio_pdr_cb_list,
+					 AUDIO_PDR_FRAMEWORK_DOWN, NULL);
+	}
+
+	return ret;
+}
+late_initcall(audio_pdr_late_init);

+ 66 - 0
drivers/soc/qcom/qdsp6v2/audio_ssr.c

@@ -0,0 +1,66 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/qdsp6v2/audio_ssr.h>
+#include <soc/qcom/scm.h>
+#include <soc/qcom/subsystem_restart.h>
+#include <soc/qcom/subsystem_notif.h>
+
+#define SCM_Q6_NMI_CMD 0x1
+
+static char *audio_ssr_domains[] = {
+	"adsp",
+	"modem"
+};
+
+void *audio_ssr_register(int domain_id, struct notifier_block *nb)
+{
+	if ((domain_id < 0) ||
+	    (domain_id >= AUDIO_SSR_DOMAIN_MAX)) {
+		pr_err("%s: Invalid service ID %d\n", __func__, domain_id);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return subsys_notif_register_notifier(
+		audio_ssr_domains[domain_id], nb);
+}
+EXPORT_SYMBOL(audio_ssr_register);
+
+int audio_ssr_deregister(void *handle, struct notifier_block *nb)
+{
+	return subsys_notif_unregister_notifier(handle, nb);
+}
+EXPORT_SYMBOL(audio_ssr_deregister);
+
+void audio_ssr_send_nmi(void *ssr_cb_data)
+{
+	struct notif_data *data = (struct notif_data *)ssr_cb_data;
+	struct scm_desc desc;
+
+	if (data && data->crashed) {
+		/* Send NMI to QDSP6 via an SCM call. */
+		if (!is_scm_armv8()) {
+			scm_call_atomic1(SCM_SVC_UTIL,
+					 SCM_Q6_NMI_CMD, 0x1);
+		} else {
+			desc.args[0] = 0x1;
+			desc.arginfo = SCM_ARGS(1);
+			scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_UTIL,
+					 SCM_Q6_NMI_CMD), &desc);
+		}
+		/* The write should go through before q6 is shutdown */
+		mb();
+		pr_debug("%s: Q6 NMI was sent.\n", __func__);
+	}
+}
+EXPORT_SYMBOL(audio_ssr_send_nmi);

+ 280 - 0
drivers/soc/qcom/qdsp6v2/cdsp-loader.c

@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2012-2014, 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/sysfs.h>
+#include <linux/workqueue.h>
+
+#include <soc/qcom/subsystem_restart.h>
+
+#define BOOT_CMD 1
+#define IMAGE_UNLOAD_CMD 0
+
+#define CDSP_SUBSYS_DOWN 0
+#define CDSP_SUBSYS_LOADED 1
+
+static ssize_t cdsp_boot_store(struct kobject *kobj,
+	struct kobj_attribute *attr,
+	const char *buf, size_t count);
+
+struct cdsp_loader_private {
+	void *pil_h;
+	struct kobject *boot_cdsp_obj;
+	struct attribute_group *attr_group;
+};
+
+static struct kobj_attribute cdsp_boot_attribute =
+	__ATTR(boot, 0220, NULL, cdsp_boot_store);
+
+static struct attribute *attrs[] = {
+	&cdsp_boot_attribute.attr,
+	NULL,
+};
+
+static u32 cdsp_state = CDSP_SUBSYS_DOWN;
+static struct platform_device *cdsp_private;
+static struct work_struct cdsp_ldr_work;
+static void cdsp_loader_unload(struct platform_device *pdev);
+
+static void cdsp_load_fw(struct work_struct *cdsp_ldr_work)
+{
+	struct platform_device *pdev = cdsp_private;
+	struct cdsp_loader_private *priv = NULL;
+
+	int rc = 0;
+	const char *img_name;
+
+	if (!pdev) {
+		dev_err(&pdev->dev, "%s: Platform device null\n", __func__);
+		goto fail;
+	}
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev,
+			"%s: Device tree information missing\n", __func__);
+
+		goto fail;
+	}
+
+	rc = of_property_read_string(pdev->dev.of_node,
+					"qcom,proc-img-to-load",
+					&img_name);
+	if (rc)
+		goto fail;
+
+	if (!strcmp(img_name, "cdsp")) {
+		/* cdsp_state always returns "0".*/
+		if (cdsp_state == CDSP_SUBSYS_DOWN) {
+			priv = platform_get_drvdata(pdev);
+			if (!priv) {
+				dev_err(&pdev->dev,
+				" %s: Private data get failed\n", __func__);
+				goto fail;
+			}
+
+			priv->pil_h = subsystem_get("cdsp");
+			if (IS_ERR(priv->pil_h)) {
+				dev_err(&pdev->dev, "%s: pil get failed,\n",
+					__func__);
+				goto fail;
+			}
+
+			/* Set the state of the CDSP.*/
+			cdsp_state = CDSP_SUBSYS_LOADED;
+		} else if (cdsp_state == CDSP_SUBSYS_LOADED) {
+			dev_dbg(&pdev->dev,
+			"%s: CDSP state = %x\n", __func__, cdsp_state);
+		}
+
+		dev_dbg(&pdev->dev, "%s: CDSP image is loaded\n", __func__);
+		return;
+	}
+
+fail:
+	dev_err(&pdev->dev, "%s: CDSP image loading failed\n", __func__);
+}
+
+static void cdsp_loader_do(struct platform_device *pdev)
+{
+	schedule_work(&cdsp_ldr_work);
+}
+
+static ssize_t cdsp_boot_store(struct kobject *kobj,
+	struct kobj_attribute *attr,
+	const char *buf,
+	size_t count)
+{
+	int boot = 0, ret = 0;
+
+	ret = sscanf(buf, "%du", &boot);
+
+	if (ret != 1)
+		pr_debug("%s: invalid arguments for cdsp_loader.\n", __func__);
+
+	if (boot == BOOT_CMD) {
+		pr_debug("%s: going to call cdsp_loader_do\n", __func__);
+		cdsp_loader_do(cdsp_private);
+	} else if (boot == IMAGE_UNLOAD_CMD) {
+		pr_debug("%s: going to call cdsp_unloader\n", __func__);
+		cdsp_loader_unload(cdsp_private);
+	}
+	return count;
+}
+
+static void cdsp_loader_unload(struct platform_device *pdev)
+{
+	struct cdsp_loader_private *priv = NULL;
+
+	priv = platform_get_drvdata(pdev);
+
+	if (!priv)
+		return;
+
+	if (priv->pil_h) {
+		dev_dbg(&pdev->dev, "%s: calling subsystem put\n", __func__);
+		subsystem_put(priv->pil_h);
+		priv->pil_h = NULL;
+	}
+}
+
+static int cdsp_loader_init_sysfs(struct platform_device *pdev)
+{
+	int ret = -EINVAL;
+	struct cdsp_loader_private *priv = NULL;
+
+	cdsp_private = NULL;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	priv->pil_h = NULL;
+	priv->boot_cdsp_obj = NULL;
+	priv->attr_group = devm_kzalloc(&pdev->dev,
+				sizeof(*(priv->attr_group)),
+				GFP_KERNEL);
+	if (!priv->attr_group) {
+		dev_err(&pdev->dev, "%s: malloc attr_group failed\n",
+						__func__);
+		ret = -ENOMEM;
+		goto error_return;
+	}
+
+	priv->attr_group->attrs = attrs;
+
+	priv->boot_cdsp_obj = kobject_create_and_add("boot_cdsp", kernel_kobj);
+	if (!priv->boot_cdsp_obj) {
+		dev_err(&pdev->dev, "%s: sysfs create and add failed\n",
+						__func__);
+		ret = -ENOMEM;
+		goto error_return;
+	}
+
+	ret = sysfs_create_group(priv->boot_cdsp_obj, priv->attr_group);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: sysfs create group failed %d\n",
+							__func__, ret);
+		goto error_return;
+	}
+
+	cdsp_private = pdev;
+
+	return 0;
+
+error_return:
+
+	if (priv->boot_cdsp_obj) {
+		kobject_del(priv->boot_cdsp_obj);
+		priv->boot_cdsp_obj = NULL;
+	}
+
+	return ret;
+}
+
+static int cdsp_loader_remove(struct platform_device *pdev)
+{
+	struct cdsp_loader_private *priv = NULL;
+
+	priv = platform_get_drvdata(pdev);
+
+	if (!priv)
+		return 0;
+
+	if (priv->pil_h) {
+		subsystem_put(priv->pil_h);
+		priv->pil_h = NULL;
+	}
+
+	if (priv->boot_cdsp_obj) {
+		sysfs_remove_group(priv->boot_cdsp_obj, priv->attr_group);
+		kobject_del(priv->boot_cdsp_obj);
+		priv->boot_cdsp_obj = NULL;
+	}
+
+	return 0;
+}
+
+static int cdsp_loader_probe(struct platform_device *pdev)
+{
+	int ret = cdsp_loader_init_sysfs(pdev);
+
+	if (ret != 0) {
+		dev_err(&pdev->dev, "%s: Error in initing sysfs\n", __func__);
+		return ret;
+	}
+
+	INIT_WORK(&cdsp_ldr_work, cdsp_load_fw);
+
+	return 0;
+}
+
+static const struct of_device_id cdsp_loader_dt_match[] = {
+	{ .compatible = "qcom,cdsp-loader" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, cdsp_loader_dt_match);
+
+static struct platform_driver cdsp_loader_driver = {
+	.driver = {
+		.name = "cdsp-loader",
+		.owner = THIS_MODULE,
+		.of_match_table = cdsp_loader_dt_match,
+	},
+	.probe = cdsp_loader_probe,
+	.remove = cdsp_loader_remove,
+};
+
+static int __init cdsp_loader_init(void)
+{
+	return platform_driver_register(&cdsp_loader_driver);
+}
+module_init(cdsp_loader_init);
+
+static void __exit cdsp_loader_exit(void)
+{
+	platform_driver_unregister(&cdsp_loader_driver);
+}
+module_exit(cdsp_loader_exit);
+
+MODULE_DESCRIPTION("CDSP Loader module");
+MODULE_LICENSE("GPL v2");

+ 853 - 0
drivers/soc/qcom/qdsp6v2/msm_audio_ion.c

@@ -0,0 +1,853 @@
+/*
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-buf.h>
+#include <linux/iommu.h>
+#include <linux/platform_device.h>
+#include <linux/qdsp6v2/apr.h>
+#include <linux/of_device.h>
+#include <linux/msm_audio_ion.h>
+#include <linux/export.h>
+#include <asm/dma-iommu.h>
+
+#define MSM_AUDIO_ION_PROBED (1 << 0)
+
+#define MSM_AUDIO_ION_PHYS_ADDR(alloc_data) \
+	alloc_data->table->sgl->dma_address
+
+#define MSM_AUDIO_ION_VA_START 0x10000000
+#define MSM_AUDIO_ION_VA_LEN 0x0FFFFFFF
+
+#define MSM_AUDIO_SMMU_SID_OFFSET 32
+
+struct msm_audio_ion_private {
+	bool smmu_enabled;
+	bool audioheap_enabled;
+	struct device *cb_dev;
+	struct dma_iommu_mapping *mapping;
+	u8 device_status;
+	struct list_head alloc_list;
+	struct mutex list_mutex;
+	u64 smmu_sid_bits;
+	u32 smmu_version;
+};
+
+struct msm_audio_alloc_data {
+	struct ion_client *client;
+	struct ion_handle *handle;
+	size_t len;
+	struct dma_buf *dma_buf;
+	struct dma_buf_attachment *attach;
+	struct sg_table *table;
+	struct list_head list;
+};
+
+static struct msm_audio_ion_private msm_audio_ion_data = {0,};
+
+static int msm_audio_ion_get_phys(struct ion_client *client,
+				  struct ion_handle *handle,
+				  ion_phys_addr_t *addr, size_t *len);
+
+static int msm_audio_dma_buf_map(struct ion_client *client,
+				  struct ion_handle *handle,
+				  ion_phys_addr_t *addr, size_t *len);
+
+static int msm_audio_dma_buf_unmap(struct ion_client *client,
+				   struct ion_handle *handle);
+
+static void msm_audio_ion_add_allocation(
+	struct msm_audio_ion_private *msm_audio_ion_data,
+	struct msm_audio_alloc_data *alloc_data)
+{
+	/*
+	 * Since these APIs can be invoked by multiple
+	 * clients, there is need to make sure the list
+	 * of allocations is always protected
+	 */
+	mutex_lock(&(msm_audio_ion_data->list_mutex));
+	list_add_tail(&(alloc_data->list),
+		      &(msm_audio_ion_data->alloc_list));
+	mutex_unlock(&(msm_audio_ion_data->list_mutex));
+}
+
+int msm_audio_ion_alloc(const char *name, struct ion_client **client,
+			struct ion_handle **handle, size_t bufsz,
+			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+	int rc = -EINVAL;
+	unsigned long err_ion_ptr = 0;
+
+	if ((msm_audio_ion_data.smmu_enabled == true) &&
+	    !(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) {
+		pr_debug("%s:probe is not done, deferred\n", __func__);
+		return -EPROBE_DEFER;
+	}
+	if (!name || !client || !handle || !paddr || !vaddr
+		|| !bufsz || !pa_len) {
+		pr_err("%s: Invalid params\n", __func__);
+		return -EINVAL;
+	}
+	*client = msm_audio_ion_client_create(name);
+	if (IS_ERR_OR_NULL((void *)(*client))) {
+		pr_err("%s: ION create client for AUDIO failed\n", __func__);
+		goto err;
+	}
+
+	*handle = ion_alloc(*client, bufsz, SZ_4K,
+			ION_HEAP(ION_AUDIO_HEAP_ID), 0);
+	if (IS_ERR_OR_NULL((void *) (*handle))) {
+		if (msm_audio_ion_data.smmu_enabled == true) {
+			pr_debug("system heap is used");
+			msm_audio_ion_data.audioheap_enabled = 0;
+			*handle = ion_alloc(*client, bufsz, SZ_4K,
+					ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
+		}
+		if (IS_ERR_OR_NULL((void *) (*handle))) {
+			if (IS_ERR((void *)(*handle)))
+				err_ion_ptr = PTR_ERR((int *)(*handle));
+			pr_err("%s:ION alloc fail err ptr=%ld, smmu_enabled=%d\n",
+			__func__, err_ion_ptr, msm_audio_ion_data.smmu_enabled);
+			rc = -ENOMEM;
+			goto err_ion_client;
+		}
+	} else {
+		pr_debug("audio heap is used");
+		msm_audio_ion_data.audioheap_enabled = 1;
+	}
+
+	rc = msm_audio_ion_get_phys(*client, *handle, paddr, pa_len);
+	if (rc) {
+		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+			__func__, rc);
+		goto err_ion_handle;
+	}
+
+	*vaddr = ion_map_kernel(*client, *handle);
+	if (IS_ERR_OR_NULL((void *)*vaddr)) {
+		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+		goto err_ion_handle;
+	}
+	pr_debug("%s: mapped address = %pK, size=%zd\n", __func__,
+		*vaddr, bufsz);
+
+	if (bufsz != 0) {
+		pr_debug("%s: memset to 0 %pK %zd\n", __func__, *vaddr, bufsz);
+		memset((void *)*vaddr, 0, bufsz);
+	}
+
+	return rc;
+
+err_ion_handle:
+	ion_free(*client, *handle);
+err_ion_client:
+	msm_audio_ion_client_destroy(*client);
+	*handle = NULL;
+	*client = NULL;
+err:
+	return rc;
+}
+EXPORT_SYMBOL(msm_audio_ion_alloc);
+
+int msm_audio_ion_import(const char *name, struct ion_client **client,
+			struct ion_handle **handle, int fd,
+			unsigned long *ionflag, size_t bufsz,
+			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+	int rc = 0;
+
+	if ((msm_audio_ion_data.smmu_enabled == true) &&
+	    !(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) {
+		pr_debug("%s:probe is not done, deferred\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	if (!name || !client || !handle || !paddr || !vaddr || !pa_len) {
+		pr_err("%s: Invalid params\n", __func__);
+		rc = -EINVAL;
+		goto err;
+	}
+
+	*client = msm_audio_ion_client_create(name);
+	if (IS_ERR_OR_NULL((void *)(*client))) {
+		pr_err("%s: ION create client for AUDIO failed\n", __func__);
+		rc = -EINVAL;
+		goto err;
+	}
+
+	/* name should be audio_acdb_client or Audio_Dec_Client,
+	 * bufsz should be 0 and fd shouldn't be 0 as of now
+	 */
+	*handle = ion_import_dma_buf_fd(*client, fd);
+	pr_debug("%s: DMA Buf name=%s, fd=%d handle=%pK\n", __func__,
+							name, fd, *handle);
+	if (IS_ERR_OR_NULL((void *) (*handle))) {
+		pr_err("%s: ion import dma buffer failed\n",
+				__func__);
+		rc = -EINVAL;
+		goto err_destroy_client;
+	}
+
+	if (ionflag != NULL) {
+		rc = ion_handle_get_flags(*client, *handle, ionflag);
+		if (rc) {
+			pr_err("%s: could not get flags for the handle\n",
+				__func__);
+			goto err_ion_handle;
+		}
+	}
+
+	rc = msm_audio_ion_get_phys(*client, *handle, paddr, pa_len);
+	if (rc) {
+		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+				__func__, rc);
+		goto err_ion_handle;
+	}
+
+	*vaddr = ion_map_kernel(*client, *handle);
+	if (IS_ERR_OR_NULL((void *)*vaddr)) {
+		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+		rc = -ENOMEM;
+		goto err_ion_handle;
+	}
+	pr_debug("%s: mapped address = %pK, size=%zd\n", __func__,
+		*vaddr, bufsz);
+
+	return 0;
+
+err_ion_handle:
+	ion_free(*client, *handle);
+err_destroy_client:
+	msm_audio_ion_client_destroy(*client);
+	*client = NULL;
+	*handle = NULL;
+err:
+	return rc;
+}
+
+int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle)
+{
+	if (!client || !handle) {
+		pr_err("%s Invalid params\n", __func__);
+		return -EINVAL;
+	}
+	if (msm_audio_ion_data.smmu_enabled)
+		msm_audio_dma_buf_unmap(client, handle);
+
+	ion_unmap_kernel(client, handle);
+
+	ion_free(client, handle);
+	msm_audio_ion_client_destroy(client);
+	return 0;
+}
+EXPORT_SYMBOL(msm_audio_ion_free);
+
+int msm_audio_ion_mmap(struct audio_buffer *ab,
+		       struct vm_area_struct *vma)
+{
+	struct sg_table *table;
+	unsigned long addr = vma->vm_start;
+	unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
+	struct scatterlist *sg;
+	unsigned int i;
+	struct page *page;
+	int ret;
+
+	pr_debug("%s\n", __func__);
+
+	table = ion_sg_table(ab->client, ab->handle);
+
+	if (IS_ERR(table)) {
+		pr_err("%s: Unable to get sg_table from ion: %ld\n",
+			__func__, PTR_ERR(table));
+		return PTR_ERR(table);
+	} else if (!table) {
+		pr_err("%s: sg_list is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	/* uncached */
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+	/* We need to check if a page is associated with this sg list because:
+	 * If the allocation came from a carveout we currently don't have
+	 * pages associated with carved out memory. This might change in the
+	 * future and we can remove this check and the else statement.
+	 */
+	page = sg_page(table->sgl);
+	if (page) {
+		pr_debug("%s: page is NOT null\n", __func__);
+		for_each_sg(table->sgl, sg, table->nents, i) {
+			unsigned long remainder = vma->vm_end - addr;
+			unsigned long len = sg->length;
+
+			page = sg_page(sg);
+
+			if (offset >= len) {
+				offset -= len;
+				continue;
+			} else if (offset) {
+				page += offset / PAGE_SIZE;
+				len -= offset;
+				offset = 0;
+			}
+			len = min(len, remainder);
+			pr_debug("vma=%pK, addr=%x len=%ld vm_start=%x vm_end=%x vm_page_prot=%lu\n",
+				vma, (unsigned int)addr, len,
+				(unsigned int)vma->vm_start,
+				(unsigned int)vma->vm_end,
+				(unsigned long)vma->vm_page_prot.pgprot);
+			remap_pfn_range(vma, addr, page_to_pfn(page), len,
+					vma->vm_page_prot);
+			addr += len;
+			if (addr >= vma->vm_end)
+				return 0;
+		}
+	} else {
+		ion_phys_addr_t phys_addr;
+		size_t phys_len;
+		size_t va_len = 0;
+
+		pr_debug("%s: page is NULL\n", __func__);
+		ret = ion_phys(ab->client, ab->handle, &phys_addr, &phys_len);
+		if (ret) {
+			pr_err("%s: Unable to get phys address from ION buffer: %d\n"
+				, __func__, ret);
+			return ret;
+		}
+		pr_debug("phys=%pKK len=%zd\n", &phys_addr, phys_len);
+		pr_debug("vma=%pK, vm_start=%x vm_end=%x vm_pgoff=%ld vm_page_prot=%lu\n",
+			vma, (unsigned int)vma->vm_start,
+			(unsigned int)vma->vm_end, vma->vm_pgoff,
+			(unsigned long)vma->vm_page_prot.pgprot);
+		va_len = vma->vm_end - vma->vm_start;
+		if ((offset > phys_len) || (va_len > phys_len-offset)) {
+			pr_err("wrong offset size %ld, lens= %zd, va_len=%zd\n",
+				offset, phys_len, va_len);
+			return -EINVAL;
+		}
+		ret =  remap_pfn_range(vma, vma->vm_start,
+				__phys_to_pfn(phys_addr) + vma->vm_pgoff,
+				vma->vm_end - vma->vm_start,
+				vma->vm_page_prot);
+	}
+	return 0;
+}
+
+
+bool msm_audio_ion_is_smmu_available(void)
+{
+	return msm_audio_ion_data.smmu_enabled;
+}
+
+/* move to static section again */
+struct ion_client *msm_audio_ion_client_create(const char *name)
+{
+	struct ion_client *pclient = NULL;
+
+	pclient = msm_ion_client_create(name);
+	return pclient;
+}
+
+
+void msm_audio_ion_client_destroy(struct ion_client *client)
+{
+	pr_debug("%s: client = %pK smmu_enabled = %d\n", __func__,
+		client, msm_audio_ion_data.smmu_enabled);
+
+	ion_client_destroy(client);
+}
+
+int msm_audio_ion_import_legacy(const char *name, struct ion_client *client,
+			struct ion_handle **handle, int fd,
+			unsigned long *ionflag, size_t bufsz,
+			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+	int rc = 0;
+
+	if (!name || !client || !handle || !paddr || !vaddr || !pa_len) {
+		pr_err("%s: Invalid params\n", __func__);
+		rc = -EINVAL;
+		goto err;
+	}
+	/* client is already created for legacy and given
+	 * name should be audio_acdb_client or Audio_Dec_Client,
+	 * bufsz should be 0 and fd shouldn't be 0 as of now
+	 */
+	*handle = ion_import_dma_buf_fd(client, fd);
+	pr_debug("%s: DMA Buf name=%s, fd=%d handle=%pK\n", __func__,
+							name, fd, *handle);
+	if (IS_ERR_OR_NULL((void *)(*handle))) {
+		pr_err("%s: ion import dma buffer failed\n",
+			__func__);
+		rc = -EINVAL;
+		goto err;
+	}
+
+	if (ionflag != NULL) {
+		rc = ion_handle_get_flags(client, *handle, ionflag);
+		if (rc) {
+			pr_err("%s: could not get flags for the handle\n",
+							__func__);
+			rc = -EINVAL;
+			goto err_ion_handle;
+		}
+	}
+
+	rc = msm_audio_ion_get_phys(client, *handle, paddr, pa_len);
+	if (rc) {
+		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+			__func__, rc);
+		rc = -EINVAL;
+		goto err_ion_handle;
+	}
+
+	/*Need to add condition SMMU enable or not */
+	*vaddr = ion_map_kernel(client, *handle);
+	if (IS_ERR_OR_NULL((void *)*vaddr)) {
+		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+		rc = -EINVAL;
+		goto err_ion_handle;
+	}
+
+	if (bufsz != 0)
+		memset((void *)*vaddr, 0, bufsz);
+
+	return 0;
+
+err_ion_handle:
+	ion_free(client, *handle);
+err:
+	return rc;
+}
+
+int msm_audio_ion_free_legacy(struct ion_client *client,
+			      struct ion_handle *handle)
+{
+	if (msm_audio_ion_data.smmu_enabled)
+		msm_audio_dma_buf_unmap(client, handle);
+
+	ion_unmap_kernel(client, handle);
+
+	ion_free(client, handle);
+	/* no client_destrody in legacy*/
+	return 0;
+}
+
+int msm_audio_ion_cache_operations(struct audio_buffer *abuff, int cache_op)
+{
+	unsigned long ionflag = 0;
+	int rc = 0;
+	int msm_cache_ops = 0;
+
+	if (!abuff) {
+		pr_err("%s: Invalid params: %pK\n", __func__, abuff);
+		return -EINVAL;
+	}
+	rc = ion_handle_get_flags(abuff->client, abuff->handle,
+		&ionflag);
+	if (rc) {
+		pr_err("ion_handle_get_flags failed: %d\n", rc);
+		goto cache_op_failed;
+	}
+
+	/* has to be CACHED */
+	if (ION_IS_CACHED(ionflag)) {
+		/* ION_IOC_INV_CACHES or ION_IOC_CLEAN_CACHES */
+		msm_cache_ops = cache_op;
+		rc = msm_ion_do_cache_op(abuff->client,
+				abuff->handle,
+				(unsigned long *) abuff->data,
+				(unsigned long)abuff->size,
+				msm_cache_ops);
+		if (rc) {
+			pr_err("cache operation failed %d\n", rc);
+			goto cache_op_failed;
+		}
+	}
+cache_op_failed:
+	return rc;
+}
+
+
+static int msm_audio_dma_buf_map(struct ion_client *client,
+		struct ion_handle *handle,
+		ion_phys_addr_t *addr, size_t *len)
+{
+
+	struct msm_audio_alloc_data *alloc_data;
+	struct device *cb_dev;
+	int rc = 0;
+
+	cb_dev = msm_audio_ion_data.cb_dev;
+
+	/* Data required per buffer mapping */
+	alloc_data = kzalloc(sizeof(*alloc_data), GFP_KERNEL);
+	if (!alloc_data)
+		return -ENOMEM;
+
+	/* Get the ION handle size */
+	ion_handle_get_size(client, handle, len);
+
+	alloc_data->client = client;
+	alloc_data->handle = handle;
+	alloc_data->len = *len;
+
+	/* Get the dma_buf handle from ion_handle */
+	alloc_data->dma_buf = ion_share_dma_buf(client, handle);
+	if (IS_ERR(alloc_data->dma_buf)) {
+		rc = PTR_ERR(alloc_data->dma_buf);
+		dev_err(cb_dev,
+			"%s: Fail to get dma_buf handle, rc = %d\n",
+			__func__, rc);
+		goto err_dma_buf;
+	}
+
+	/* Attach the dma_buf to context bank device */
+	alloc_data->attach = dma_buf_attach(alloc_data->dma_buf,
+					    cb_dev);
+	if (IS_ERR(alloc_data->attach)) {
+		rc = PTR_ERR(alloc_data->attach);
+		dev_err(cb_dev,
+			"%s: Fail to attach dma_buf to CB, rc = %d\n",
+			__func__, rc);
+		goto err_attach;
+	}
+
+	/*
+	 * Get the scatter-gather list.
+	 * There is no info as this is a write buffer or
+	 * read buffer, hence the request is bi-directional
+	 * to accommodate both read and write mappings.
+	 */
+	alloc_data->table = dma_buf_map_attachment(alloc_data->attach,
+				DMA_BIDIRECTIONAL);
+	if (IS_ERR(alloc_data->table)) {
+		rc = PTR_ERR(alloc_data->table);
+		dev_err(cb_dev,
+			"%s: Fail to map attachment, rc = %d\n",
+			__func__, rc);
+		goto err_map_attach;
+	}
+
+	rc = dma_map_sg(cb_dev, alloc_data->table->sgl,
+			alloc_data->table->nents,
+			DMA_BIDIRECTIONAL);
+	if (rc != alloc_data->table->nents) {
+		dev_err(cb_dev,
+			"%s: Fail to map SG, rc = %d, nents = %d\n",
+			__func__, rc, alloc_data->table->nents);
+		goto err_map_sg;
+	}
+	/* Make sure not to return rc from dma_map_sg, as it can be nonzero */
+	rc = 0;
+
+	/* physical address from mapping */
+	*addr = MSM_AUDIO_ION_PHYS_ADDR(alloc_data);
+
+	msm_audio_ion_add_allocation(&msm_audio_ion_data,
+				     alloc_data);
+	return rc;
+
+err_map_sg:
+	dma_buf_unmap_attachment(alloc_data->attach,
+				 alloc_data->table,
+				 DMA_BIDIRECTIONAL);
+err_map_attach:
+	dma_buf_detach(alloc_data->dma_buf,
+		       alloc_data->attach);
+err_attach:
+	dma_buf_put(alloc_data->dma_buf);
+
+err_dma_buf:
+	kfree(alloc_data);
+
+	return rc;
+}
+
+static int msm_audio_dma_buf_unmap(struct ion_client *client,
+				   struct ion_handle *handle)
+{
+	int rc = 0;
+	struct msm_audio_alloc_data *alloc_data = NULL;
+	struct list_head *ptr, *next;
+	struct device *cb_dev = msm_audio_ion_data.cb_dev;
+	bool found = false;
+
+	/*
+	 * Though list_for_each_safe is delete safe, lock
+	 * should be explicitly acquired to avoid race condition
+	 * on adding elements to the list.
+	 */
+	mutex_lock(&(msm_audio_ion_data.list_mutex));
+	list_for_each_safe(ptr, next,
+			    &(msm_audio_ion_data.alloc_list)) {
+
+		alloc_data = list_entry(ptr, struct msm_audio_alloc_data,
+					list);
+
+		if (alloc_data->handle == handle &&
+		    alloc_data->client == client) {
+			found = true;
+			dma_unmap_sg(cb_dev,
+				    alloc_data->table->sgl,
+				    alloc_data->table->nents,
+				    DMA_BIDIRECTIONAL);
+
+			dma_buf_unmap_attachment(alloc_data->attach,
+						 alloc_data->table,
+						 DMA_BIDIRECTIONAL);
+
+			dma_buf_detach(alloc_data->dma_buf,
+				       alloc_data->attach);
+
+			dma_buf_put(alloc_data->dma_buf);
+
+			list_del(&(alloc_data->list));
+			kfree(alloc_data);
+			break;
+		}
+	}
+	mutex_unlock(&(msm_audio_ion_data.list_mutex));
+
+	if (!found) {
+		dev_err(cb_dev,
+			"%s: cannot find allocation, ion_handle %pK, ion_client %pK",
+			__func__, handle, client);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int msm_audio_ion_get_phys(struct ion_client *client,
+		struct ion_handle *handle,
+		ion_phys_addr_t *addr, size_t *len)
+{
+	int rc = 0;
+
+	pr_debug("%s: smmu_enabled = %d\n", __func__,
+		msm_audio_ion_data.smmu_enabled);
+
+	if (msm_audio_ion_data.smmu_enabled) {
+		rc = msm_audio_dma_buf_map(client, handle, addr, len);
+		if (rc) {
+			pr_err("%s: failed to map DMA buf, err = %d\n",
+				__func__, rc);
+			goto err;
+		}
+		/* Append the SMMU SID information to the IOVA address */
+		*addr |= msm_audio_ion_data.smmu_sid_bits;
+	} else {
+		rc = ion_phys(client, handle, addr, len);
+	}
+
+	pr_debug("phys=%pK, len=%zd, rc=%d\n", &(*addr), *len, rc);
+err:
+	return rc;
+}
+
+static int msm_audio_smmu_init(struct device *dev)
+{
+	struct dma_iommu_mapping *mapping;
+	int ret;
+
+	mapping = arm_iommu_create_mapping(&platform_bus_type,
+					   MSM_AUDIO_ION_VA_START,
+					   MSM_AUDIO_ION_VA_LEN);
+	if (IS_ERR(mapping))
+		return PTR_ERR(mapping);
+
+	ret = arm_iommu_attach_device(dev, mapping);
+	if (ret) {
+		dev_err(dev, "%s: Attach failed, err = %d\n",
+			__func__, ret);
+		goto fail_attach;
+	}
+
+	msm_audio_ion_data.cb_dev = dev;
+	msm_audio_ion_data.mapping = mapping;
+	INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list);
+	mutex_init(&(msm_audio_ion_data.list_mutex));
+
+	return 0;
+
+fail_attach:
+	arm_iommu_release_mapping(mapping);
+	return ret;
+}
+
+static const struct of_device_id msm_audio_ion_dt_match[] = {
+	{ .compatible = "qcom,msm-audio-ion" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match);
+
+
+u32 msm_audio_ion_get_smmu_sid_mode32(void)
+{
+	if (msm_audio_ion_data.smmu_enabled)
+		return upper_32_bits(msm_audio_ion_data.smmu_sid_bits);
+	else
+		return 0;
+}
+
+u32 msm_audio_populate_upper_32_bits(ion_phys_addr_t pa)
+{
+	if (sizeof(ion_phys_addr_t) == sizeof(u32))
+		return msm_audio_ion_get_smmu_sid_mode32();
+	else
+		return upper_32_bits(pa);
+}
+
+static int msm_audio_ion_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	const char *msm_audio_ion_dt = "qcom,smmu-enabled";
+	const char *msm_audio_ion_smmu = "qcom,smmu-version";
+	const char *msm_audio_ion_smmu_sid_mask = "qcom,smmu-sid-mask";
+	bool smmu_enabled;
+	enum apr_subsys_state q6_state;
+	struct device *dev = &pdev->dev;
+
+	if (dev->of_node == NULL) {
+		dev_err(dev,
+			"%s: device tree is not found\n",
+			__func__);
+		msm_audio_ion_data.smmu_enabled = 0;
+		return 0;
+	}
+
+	smmu_enabled = of_property_read_bool(dev->of_node,
+					     msm_audio_ion_dt);
+	msm_audio_ion_data.smmu_enabled = smmu_enabled;
+
+	if (smmu_enabled) {
+		rc = of_property_read_u32(dev->of_node,
+					msm_audio_ion_smmu,
+					&msm_audio_ion_data.smmu_version);
+		if (rc) {
+			dev_err(dev,
+				"%s: qcom,smmu_version missing in DT node\n",
+				__func__);
+			return rc;
+		}
+		dev_dbg(dev, "%s: SMMU version is (%d)", __func__,
+				msm_audio_ion_data.smmu_version);
+		q6_state = apr_get_q6_state();
+		if (q6_state == APR_SUBSYS_DOWN) {
+			dev_dbg(dev,
+				"defering %s, adsp_state %d\n",
+				__func__, q6_state);
+			return -EPROBE_DEFER;
+		}
+		dev_dbg(dev, "%s: adsp is ready\n", __func__);
+	}
+
+	dev_dbg(dev, "%s: SMMU is %s\n", __func__,
+		(smmu_enabled) ? "Enabled" : "Disabled");
+
+	if (smmu_enabled) {
+		u64 smmu_sid = 0;
+		u64 smmu_sid_mask = 0;
+		struct of_phandle_args iommuspec;
+
+		/* Get SMMU SID information from Devicetree */
+		rc = of_property_read_u64(dev->of_node,
+					  msm_audio_ion_smmu_sid_mask,
+					  &smmu_sid_mask);
+		if (rc) {
+			dev_err(dev,
+				"%s: qcom,smmu-sid-mask missing in DT node, using default\n",
+				__func__);
+			smmu_sid_mask = 0xFFFFFFFFFFFFFFFF;
+		}
+		rc = of_parse_phandle_with_args(dev->of_node, "iommus",
+						"#iommu-cells", 0, &iommuspec);
+		if (rc)
+			dev_err(dev, "%s: could not get smmu SID, ret = %d\n",
+				__func__, rc);
+		else
+			smmu_sid = (iommuspec.args[0] & smmu_sid_mask);
+
+		msm_audio_ion_data.smmu_sid_bits =
+			smmu_sid << MSM_AUDIO_SMMU_SID_OFFSET;
+
+		if (msm_audio_ion_data.smmu_version == 0x2) {
+			rc = msm_audio_smmu_init(dev);
+		} else {
+			dev_err(dev, "%s: smmu version invalid %d\n",
+				__func__, msm_audio_ion_data.smmu_version);
+			rc = -EINVAL;
+		}
+		if (rc)
+			dev_err(dev, "%s: smmu init failed, err = %d\n",
+				__func__, rc);
+	}
+
+	if (!rc)
+		msm_audio_ion_data.device_status |= MSM_AUDIO_ION_PROBED;
+
+	return rc;
+}
+
+static int msm_audio_ion_remove(struct platform_device *pdev)
+{
+	struct dma_iommu_mapping *mapping;
+	struct device *audio_cb_dev;
+
+	mapping = msm_audio_ion_data.mapping;
+	audio_cb_dev = msm_audio_ion_data.cb_dev;
+
+	if (audio_cb_dev && mapping) {
+		arm_iommu_detach_device(audio_cb_dev);
+		arm_iommu_release_mapping(mapping);
+	}
+
+	msm_audio_ion_data.smmu_enabled = 0;
+	msm_audio_ion_data.device_status = 0;
+	return 0;
+}
+
+static struct platform_driver msm_audio_ion_driver = {
+	.driver = {
+		.name = "msm-audio-ion",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_audio_ion_dt_match,
+	},
+	.probe = msm_audio_ion_probe,
+	.remove = msm_audio_ion_remove,
+};
+
+static int __init msm_audio_ion_init(void)
+{
+	return platform_driver_register(&msm_audio_ion_driver);
+}
+module_init(msm_audio_ion_init);
+
+static void __exit msm_audio_ion_exit(void)
+{
+	platform_driver_unregister(&msm_audio_ion_driver);
+}
+module_exit(msm_audio_ion_exit);
+
+MODULE_DESCRIPTION("MSM Audio ION module");
+MODULE_LICENSE("GPL v2");

+ 17 - 0
drivers/soundwire/Kconfig

@@ -0,0 +1,17 @@
+#
+# SOUNDWIRE driver configuration
+#
+menuconfig SOUNDWIRE
+	bool "Soundwire support"
+	help
+	  Soundwire is a two wire interface for audio to connect
+	  simple peripheral components in mobile devices.
+
+if SOUNDWIRE
+config SOUNDWIRE_WCD_CTRL
+	depends on WCD9XXX_CODEC_CORE
+	tristate "QTI WCD CODEC Soundwire controller"
+	default n
+	help
+	  Select driver for QTI's Soundwire Master Component.
+endif

+ 5 - 0
drivers/soundwire/Makefile

@@ -0,0 +1,5 @@
+#
+# Makefile for kernel soundwire framework.
+#
+obj-$(CONFIG_SOUNDWIRE)			+= soundwire.o
+obj-$(CONFIG_SOUNDWIRE_WCD_CTRL)	+= swr-wcd-ctrl.o

+ 1032 - 0
drivers/soundwire/soundwire.c

@@ -0,0 +1,1032 @@
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/of_device.h>
+#include <linux/completion.h>
+#include <linux/idr.h>
+#include <linux/pm_runtime.h>
+#include <linux/soundwire/soundwire.h>
+
+struct boardinfo {
+	struct list_head	list;
+	struct swr_boardinfo	board_info;
+};
+
+static LIST_HEAD(board_list);
+static LIST_HEAD(swr_master_list);
+static DEFINE_MUTEX(board_lock);
+static DEFINE_IDR(master_idr);
+static DEFINE_MUTEX(swr_lock);
+
+static struct device_type swr_dev_type;
+
+#define SOUNDWIRE_NAME_SIZE	32
+
+static void swr_master_put(struct swr_master *master)
+{
+	if (master)
+		put_device(&master->dev);
+}
+
+static struct swr_master *swr_master_get(struct swr_master *master)
+{
+	if (!master || !get_device(&master->dev))
+		return NULL;
+	return master;
+}
+
+static void swr_dev_release(struct device *dev)
+{
+	struct swr_device *swr_dev = to_swr_device(dev);
+	struct swr_master *master;
+
+	if (!swr_dev)
+		return;
+	master = swr_dev->master;
+	if (!master)
+		return;
+	mutex_lock(&master->mlock);
+	list_del_init(&swr_dev->dev_list);
+	mutex_unlock(&master->mlock);
+	swr_master_put(swr_dev->master);
+	kfree(swr_dev);
+}
+
+/**
+ * swr_remove_device - remove a soundwire device
+ * @swr_dev: soundwire device to remove
+ *
+ * Remove a soundwire device. Go through the soundwire
+ * device list that master has and remove swr_dev from
+ * it.
+ */
+void swr_remove_device(struct swr_device *swr_dev)
+{
+	struct swr_device *swr_dev_loop, *safe;
+
+	list_for_each_entry_safe(swr_dev_loop, safe,
+				 &swr_dev->master->devices,
+				 dev_list) {
+		if (swr_dev == swr_dev_loop)
+			list_del(&swr_dev_loop->dev_list);
+	}
+}
+EXPORT_SYMBOL(swr_remove_device);
+
+/**
+ * swr_new_device - instantiate a new soundwire device
+ * @master: Controller to which device is connected
+ * @info: Describes the soundwire device
+ * Context: can sleep
+ *
+ * Create a soundwire device. Binding is handled through driver model
+ * probe/remove methods. A driver may be bound to this device when
+ * the function gets returned.
+ *
+ * Returns a soundwire new device or NULL
+ */
+struct swr_device *swr_new_device(struct swr_master *master,
+				 struct swr_boardinfo const *info)
+{
+	int result;
+	struct swr_device *swr;
+
+	if (!master || !swr_master_get(master)) {
+		pr_err("%s: master is NULL\n", __func__);
+		return NULL;
+	}
+
+	swr = kzalloc(sizeof(*swr), GFP_KERNEL);
+	if (!swr) {
+		put_device(&master->dev);
+		return NULL;
+	}
+	swr->master = master;
+	swr->addr = info->addr;
+	strlcpy(swr->name, info->name, sizeof(swr->name));
+	swr->dev.type = &swr_dev_type;
+	swr->dev.parent = &master->dev;
+	swr->dev.bus = &soundwire_type;
+	swr->dev.release = swr_dev_release;
+	swr->dev.of_node = info->of_node;
+	mutex_lock(&master->mlock);
+	list_add_tail(&swr->dev_list, &master->devices);
+	mutex_unlock(&master->mlock);
+
+	dev_set_name(&swr->dev, "%s.%lx", swr->name, swr->addr);
+	result = device_register(&swr->dev);
+	if (result) {
+		dev_err(&master->dev, "device [%s] register failed err %d\n",
+			swr->name, result);
+		goto err_out;
+	}
+	dev_dbg(&master->dev, "Device [%s] registered with bus id %s\n",
+		swr->name, dev_name(&swr->dev));
+	return swr;
+
+err_out:
+	dev_dbg(&master->dev, "Failed to register swr device %s at 0x%lx %d\n",
+		swr->name, swr->addr, result);
+	swr_master_put(master);
+	kfree(swr);
+	return NULL;
+}
+EXPORT_SYMBOL(swr_new_device);
+
+/**
+ * of_register_swr_devices - register child devices on to the soundwire bus
+ * @master: pointer to soundwire master device
+ *
+ * Registers a soundwire device for each child node of master node which has
+ * a "swr-devid" property
+ *
+ */
+int of_register_swr_devices(struct swr_master *master)
+{
+	struct swr_device *swr;
+	struct device_node *node;
+
+	if (!master->dev.of_node)
+		return -EINVAL;
+
+	for_each_available_child_of_node(master->dev.of_node, node) {
+		struct swr_boardinfo info = {};
+		u64 addr;
+
+		dev_dbg(&master->dev, "of_swr:register %s\n", node->full_name);
+
+		if (of_modalias_node(node, info.name, sizeof(info.name)) < 0) {
+			dev_err(&master->dev, "of_swr:modalias failure %s\n",
+				node->full_name);
+			continue;
+		}
+		if (of_property_read_u64(node, "reg", &addr)) {
+			dev_err(&master->dev, "of_swr:invalid reg %s\n",
+				node->full_name);
+			continue;
+		}
+		info.addr = addr;
+		info.of_node = of_node_get(node);
+		master->num_dev++;
+		swr = swr_new_device(master, &info);
+		if (!swr) {
+			dev_err(&master->dev, "of_swr: Register failed %s\n",
+				node->full_name);
+			of_node_put(node);
+			master->num_dev--;
+			continue;
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(of_register_swr_devices);
+
+/**
+ * swr_port_response - response from master to free the completed transaction
+ * @mstr: pointer to soundwire master device
+ * @tid: transaction id that indicates transaction to be freed.
+ *
+ * Master calls this function to free the compeleted transaction memory
+ */
+void swr_port_response(struct swr_master *mstr, u8 tid)
+{
+	struct swr_params *txn;
+
+	txn = mstr->port_txn[tid];
+
+	if (txn == NULL) {
+		dev_err(&mstr->dev, "%s: transaction is already NULL\n",
+			__func__);
+		return;
+	}
+	mstr->port_txn[tid] = NULL;
+	kfree(txn);
+}
+EXPORT_SYMBOL(swr_port_response);
+
+/**
+ * swr_remove_from_group - remove soundwire slave devices from group
+ * @dev: pointer to the soundwire slave device
+ * dev_num: device number of the soundwire slave device
+ *
+ * Returns error code for failure and 0 for success
+ */
+int swr_remove_from_group(struct swr_device *dev, u8 dev_num)
+{
+	struct swr_master *master;
+
+	if (!dev)
+		return -ENODEV;
+
+	master = dev->master;
+	if (!master)
+		return -EINVAL;
+
+	if (!dev->group_id)
+		return 0;
+
+	if (master->gr_sid == dev_num)
+		return 0;
+
+	if (master->remove_from_group && master->remove_from_group(master))
+		dev_dbg(&master->dev, "%s: falling back to GROUP_NONE\n",
+			__func__);
+
+	return 0;
+}
+EXPORT_SYMBOL(swr_remove_from_group);
+
+/**
+ * swr_slvdev_datapath_control - Enables/Disables soundwire slave device
+ *                               data path
+ * @dev: pointer to soundwire slave device
+ * @dev_num: device number of the soundwire slave device
+ *
+ * Returns error code for failure and 0 for success
+ */
+int swr_slvdev_datapath_control(struct swr_device *dev, u8 dev_num,
+				bool enable)
+{
+	struct swr_master *master;
+
+	if (!dev)
+		return -ENODEV;
+
+	master = dev->master;
+	if (!master)
+		return -EINVAL;
+
+	if (dev->group_id) {
+		/* Broadcast */
+		if (master->gr_sid != dev_num) {
+			if (!master->gr_sid)
+				master->gr_sid = dev_num;
+			else
+				return 0;
+		}
+	}
+
+	if (master->slvdev_datapath_control)
+		master->slvdev_datapath_control(master, enable);
+
+	return 0;
+}
+EXPORT_SYMBOL(swr_slvdev_datapath_control);
+
+/**
+ * swr_connect_port - enable soundwire slave port(s)
+ * @dev: pointer to soundwire slave device
+ * @port_id: logical port id(s) of soundwire slave device
+ * @num_port: number of slave device ports need to be enabled
+ * @ch_mask: channels for each port that needs to be enabled
+ * @ch_rate: rate at which each port/channels operate
+ * @num_ch: number of channels for each port
+ *
+ * soundwire slave device call swr_connect_port API to enable all/some of
+ * its ports and corresponding channels and channel rate. This API will
+ * call master connect_port callback function to calculate frame structure
+ * and enable master and slave ports
+ */
+int swr_connect_port(struct swr_device *dev, u8 *port_id, u8 num_port,
+			u8 *ch_mask, u32 *ch_rate, u8 *num_ch)
+{
+	u8 i = 0;
+	int ret = 0;
+	struct swr_params *txn = NULL;
+	struct swr_params **temp_txn = NULL;
+	struct swr_master *master = dev->master;
+
+	if (!master) {
+		pr_err("%s: Master is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (num_port > SWR_MAX_DEV_PORT_NUM) {
+		dev_err(&master->dev, "%s: num_port %d exceeds max port %d\n",
+			__func__, num_port, SWR_MAX_DEV_PORT_NUM);
+		return -EINVAL;
+	}
+
+	/*
+	 * create "txn" to accommodate ports enablement of
+	 * different slave devices calling swr_connect_port at the
+	 * same time. Once master process the txn data, it calls
+	 * swr_port_response() to free the transaction. Maximum
+	 * of 256 transactions can be allocated.
+	 */
+	txn = kzalloc(sizeof(struct swr_params), GFP_KERNEL);
+	if (!txn)
+		return -ENOMEM;
+
+	mutex_lock(&master->mlock);
+	for (i = 0; i < master->last_tid; i++) {
+		if (master->port_txn[i] == NULL)
+			break;
+	}
+	if (i >= master->last_tid) {
+		if (master->last_tid == 255) {
+			mutex_unlock(&master->mlock);
+			kfree(txn);
+			dev_err(&master->dev, "%s Max tid reached\n",
+				__func__);
+			return -ENOMEM;
+		}
+		temp_txn = krealloc(master->port_txn,
+				(i + 1) * sizeof(struct swr_params *),
+				GFP_KERNEL);
+		if (!temp_txn) {
+			mutex_unlock(&master->mlock);
+			kfree(txn);
+			dev_err(&master->dev, "%s Not able to allocate\n"
+				"master port transaction memory\n",
+				__func__);
+			return -ENOMEM;
+		}
+		master->port_txn = temp_txn;
+		master->last_tid++;
+	}
+	master->port_txn[i] = txn;
+	mutex_unlock(&master->mlock);
+	txn->tid = i;
+
+	txn->dev_id = dev->dev_num;
+	txn->num_port = num_port;
+	for (i = 0; i < num_port; i++) {
+		txn->port_id[i] = port_id[i];
+		txn->num_ch[i]  = num_ch[i];
+		txn->ch_rate[i] = ch_rate[i];
+		txn->ch_en[i]   = ch_mask[i];
+	}
+	ret = master->connect_port(master, txn);
+	return ret;
+}
+EXPORT_SYMBOL(swr_connect_port);
+
+/**
+ * swr_disconnect_port - disable soundwire slave port(s)
+ * @dev: pointer to soundwire slave device
+ * @port_id: logical port id(s) of soundwire slave device
+ * @num_port: number of slave device ports need to be disabled
+ *
+ * soundwire slave device call swr_disconnect_port API to disable all/some of
+ * its ports. This API will call master disconnect_port callback function to
+ * disable master and slave port and (re)configure frame structure
+ */
+int swr_disconnect_port(struct swr_device *dev, u8 *port_id, u8 num_port)
+{
+	u8 i = 0;
+	int ret;
+	struct swr_params *txn = NULL;
+	struct swr_params **temp_txn = NULL;
+	struct swr_master *master = dev->master;
+
+	if (!master) {
+		pr_err("%s: Master is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (num_port > SWR_MAX_DEV_PORT_NUM) {
+		dev_err(&master->dev, "%s: num_port %d exceeds max port %d\n",
+			__func__, num_port, SWR_MAX_DEV_PORT_NUM);
+		return -EINVAL;
+	}
+
+	txn = kzalloc(sizeof(struct swr_params), GFP_KERNEL);
+	if (!txn)
+		return -ENOMEM;
+
+	mutex_lock(&master->mlock);
+	for (i = 0; i < master->last_tid; i++) {
+		if (master->port_txn[i] == NULL)
+			break;
+	}
+	if (i >= master->last_tid) {
+		if (master->last_tid == 255) {
+			mutex_unlock(&master->mlock);
+			kfree(txn);
+			dev_err(&master->dev, "%s Max tid reached\n",
+				__func__);
+			return -ENOMEM;
+		}
+		temp_txn = krealloc(master->port_txn,
+				(i + 1) * sizeof(struct swr_params *),
+				GFP_KERNEL);
+		if (!temp_txn) {
+			mutex_unlock(&master->mlock);
+			kfree(txn);
+			dev_err(&master->dev, "%s Not able to allocate\n"
+				"master port transaction memory\n",
+				__func__);
+			return -ENOMEM;
+		}
+		master->port_txn = temp_txn;
+		master->last_tid++;
+	}
+	master->port_txn[i] = txn;
+	mutex_unlock(&master->mlock);
+	txn->tid = i;
+
+	txn->dev_id = dev->dev_num;
+	txn->num_port = num_port;
+	for (i = 0; i < num_port; i++)
+		txn->port_id[i] = port_id[i];
+	ret = master->disconnect_port(master, txn);
+	return ret;
+}
+EXPORT_SYMBOL(swr_disconnect_port);
+
+/**
+ * swr_get_logical_dev_num - Get soundwire slave logical device number
+ * @dev: pointer to soundwire slave device
+ * @dev_id: physical device id of soundwire slave device
+ * @dev_num: pointer to logical device num of soundwire slave device
+ *
+ * This API will get the logical device number of soundwire slave device
+ */
+int swr_get_logical_dev_num(struct swr_device *dev, u64 dev_id,
+			u8 *dev_num)
+{
+	int ret = 0;
+	struct swr_master *master = dev->master;
+
+	if (!master) {
+		pr_err("%s: Master is NULL\n", __func__);
+		return -EINVAL;
+	}
+	mutex_lock(&master->mlock);
+	ret = master->get_logical_dev_num(master, dev_id, dev_num);
+	if (ret) {
+		pr_err("%s: Error %d to get logical addr for device %llx\n",
+			__func__, ret, dev_id);
+	}
+	mutex_unlock(&master->mlock);
+	return ret;
+}
+EXPORT_SYMBOL(swr_get_logical_dev_num);
+
+/**
+ * swr_read - read soundwire slave device registers
+ * @dev: pointer to soundwire slave device
+ * @dev_num: logical device num of soundwire slave device
+ * @reg_addr: base register address that needs to be read
+ * @buf: pointer to store the values of registers from base address
+ * @len: length of the buffer
+ *
+ * This API will read the value of the register address from
+ * soundwire slave device
+ */
+int swr_read(struct swr_device *dev, u8 dev_num, u16 reg_addr,
+	     void *buf, u32 len)
+{
+	struct swr_master *master = dev->master;
+
+	if (!master)
+		return -EINVAL;
+	return master->read(master, dev_num, reg_addr, buf, len);
+}
+EXPORT_SYMBOL(swr_read);
+
+/**
+ * swr_bulk_write - write soundwire slave device registers
+ * @dev: pointer to soundwire slave device
+ * @dev_num: logical device num of soundwire slave device
+ * @reg_addr: register address of soundwire slave device
+ * @buf: contains value of register address
+ * @len: indicates number of registers
+ *
+ * This API will write the value of the register address to
+ * soundwire slave device
+ */
+int swr_bulk_write(struct swr_device *dev, u8 dev_num, void *reg,
+		   const void *buf, size_t len)
+{
+	struct swr_master *master;
+
+	if (!dev || !dev->master)
+		return -EINVAL;
+
+	master = dev->master;
+	if (dev->group_id) {
+		if (master->gr_sid != dev_num) {
+			if (!master->gr_sid)
+				master->gr_sid = dev_num;
+			else
+				return 0;
+		}
+		dev_num = dev->group_id;
+	}
+	if (master->bulk_write)
+		return master->bulk_write(master, dev_num, reg, buf, len);
+
+	return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(swr_bulk_write);
+
+/**
+ * swr_write - write soundwire slave device registers
+ * @dev: pointer to soundwire slave device
+ * @dev_num: logical device num of soundwire slave device
+ * @reg_addr: register address of soundwire slave device
+ * @buf: contains value of register address
+ *
+ * This API will write the value of the register address to
+ * soundwire slave device
+ */
+int swr_write(struct swr_device *dev, u8 dev_num, u16 reg_addr,
+	      const void *buf)
+{
+	struct swr_master *master = dev->master;
+
+	if (!master)
+		return -EINVAL;
+
+	if (dev->group_id) {
+		if (master->gr_sid != dev_num) {
+			if (!master->gr_sid)
+				master->gr_sid = dev_num;
+			else
+				return 0;
+		}
+		dev_num = dev->group_id;
+	}
+	return master->write(master, dev_num, reg_addr, buf);
+}
+EXPORT_SYMBOL(swr_write);
+
+/**
+ * swr_device_up - Function to bringup the soundwire slave device
+ * @swr_dev: pointer to soundwire slave device
+ * Context: can sleep
+ *
+ * This API will be called by soundwire master to bringup the slave
+ * device.
+ */
+int swr_device_up(struct swr_device *swr_dev)
+{
+	struct device *dev;
+	const struct swr_driver *sdrv;
+
+	if (!swr_dev)
+		return -EINVAL;
+
+	dev = &swr_dev->dev;
+	sdrv = to_swr_driver(dev->driver);
+	if (!sdrv)
+		return 0;
+
+	if (sdrv->device_up)
+		return sdrv->device_up(to_swr_device(dev));
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL(swr_device_up);
+
+/**
+ * swr_device_down - Function to call soundwire slave device down
+ * @swr_dev: pointer to soundwire slave device
+ * Context: can sleep
+ *
+ * This API will be called by soundwire master to put slave device in
+ * shutdown state.
+ */
+int swr_device_down(struct swr_device *swr_dev)
+{
+	struct device *dev;
+	const struct swr_driver *sdrv;
+
+	if (!swr_dev)
+		return -EINVAL;
+
+	dev = &swr_dev->dev;
+	sdrv = to_swr_driver(dev->driver);
+	if (!sdrv)
+		return 0;
+
+	if (sdrv->device_down)
+		return sdrv->device_down(to_swr_device(dev));
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL(swr_device_down);
+
+/**
+ * swr_reset_device - reset soundwire slave device
+ * @swr_dev: pointer to soundwire slave device
+ * Context: can sleep
+ *
+ * This API will be called by soundwire master to reset the slave
+ * device when the slave device is not responding or in undefined
+ * state
+ */
+int swr_reset_device(struct swr_device *swr_dev)
+{
+	struct device *dev;
+	const struct swr_driver *sdrv;
+
+	if (!swr_dev)
+		return -EINVAL;
+
+	dev = &swr_dev->dev;
+	sdrv = to_swr_driver(dev->driver);
+	if (!sdrv)
+		return -EINVAL;
+
+	if (sdrv->reset_device)
+		return sdrv->reset_device(to_swr_device(dev));
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL(swr_reset_device);
+
+/**
+ * swr_set_device_group - Assign group id to the slave devices
+ * @swr_dev: pointer to soundwire slave device
+ * @id: group id to be assigned to slave device
+ * Context: can sleep
+ *
+ * This API will be called either from soundwire master or slave
+ * device to assign group id.
+ */
+int swr_set_device_group(struct swr_device *swr_dev, u8 id)
+{
+	struct swr_master *master;
+
+	if (!swr_dev)
+		return -EINVAL;
+
+	swr_dev->group_id = id;
+	master = swr_dev->master;
+	if (!id && master)
+		master->gr_sid = 0;
+
+	return 0;
+}
+EXPORT_SYMBOL(swr_set_device_group);
+
+static int swr_drv_probe(struct device *dev)
+{
+	const struct swr_driver *sdrv = to_swr_driver(dev->driver);
+
+	if (!sdrv)
+		return -EINVAL;
+
+	if (sdrv->probe)
+		return sdrv->probe(to_swr_device(dev));
+	return -ENODEV;
+}
+
+static int swr_drv_remove(struct device *dev)
+{
+	const struct swr_driver *sdrv = to_swr_driver(dev->driver);
+
+	if (!sdrv)
+		return -EINVAL;
+
+	if (sdrv->remove)
+		return sdrv->remove(to_swr_device(dev));
+	return -ENODEV;
+}
+
+static void swr_drv_shutdown(struct device *dev)
+{
+	const struct swr_driver *sdrv = to_swr_driver(dev->driver);
+
+	if (!sdrv)
+		return;
+
+	if (sdrv->shutdown)
+		sdrv->shutdown(to_swr_device(dev));
+}
+
+/**
+ * swr_driver_register - register a soundwire driver
+ * @drv: the driver to register
+ * Context: can sleep
+ */
+int swr_driver_register(struct swr_driver *drv)
+{
+	drv->driver.bus = &soundwire_type;
+	if (drv->probe)
+		drv->driver.probe = swr_drv_probe;
+	if (drv->remove)
+		drv->driver.remove = swr_drv_remove;
+
+	if (drv->shutdown)
+		drv->driver.shutdown = swr_drv_shutdown;
+
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(swr_driver_register);
+
+/**
+ * swr_driver_unregister - unregister a soundwire driver
+ * @drv: the driver to unregister
+ */
+void swr_driver_unregister(struct swr_driver *drv)
+{
+	if (drv)
+		driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(swr_driver_unregister);
+
+static void swr_match_ctrl_to_boardinfo(struct swr_master *master,
+				struct swr_boardinfo *bi)
+{
+	struct swr_device *swr;
+
+	if (master->bus_num != bi->bus_num) {
+		dev_dbg(&master->dev,
+			"%s: master# %d and bi# %d does not match\n",
+			__func__, master->bus_num, bi->bus_num);
+		return;
+	}
+
+	swr = swr_new_device(master, bi);
+	if (!swr)
+		dev_err(&master->dev, "can't create new device for %s\n",
+			bi->swr_slave->name);
+}
+
+/**
+ * swr_master_add_boarddevices - Add devices registered by board info
+ * @master: master to which these devices are to be added to.
+ *
+ * This API is called by master when it is up and running. If devices
+ * on a master were registered before master, this will make sure that
+ * they get probed when master is up.
+ */
+void swr_master_add_boarddevices(struct swr_master *master)
+{
+	struct boardinfo *bi;
+
+	mutex_lock(&board_lock);
+	list_add_tail(&master->list, &swr_master_list);
+	list_for_each_entry(bi, &board_list, list)
+		swr_match_ctrl_to_boardinfo(master, &bi->board_info);
+	mutex_unlock(&board_lock);
+}
+EXPORT_SYMBOL(swr_master_add_boarddevices);
+
+static void swr_unregister_device(struct swr_device *swr)
+{
+	if (swr)
+		device_unregister(&swr->dev);
+}
+
+static void swr_master_release(struct device *dev)
+{
+	struct swr_master *master = to_swr_master(dev);
+
+	kfree(master);
+}
+
+#define swr_master_attr_gr NULL
+static struct device_type swr_master_type = {
+	.groups     = swr_master_attr_gr,
+	.release    = swr_master_release,
+};
+
+static int __unregister(struct device *dev, void *null)
+{
+	swr_unregister_device(to_swr_device(dev));
+	return 0;
+}
+
+/**
+ * swr_unregister_master - unregister soundwire master controller
+ * @master: the master being unregistered
+ *
+ * This API is called by master controller driver to unregister
+ *  master controller that was registered by swr_register_master API.
+ */
+void swr_unregister_master(struct swr_master *master)
+{
+	int dummy;
+	struct swr_master *m_ctrl;
+
+	mutex_lock(&swr_lock);
+	m_ctrl = idr_find(&master_idr, master->bus_num);
+	mutex_unlock(&swr_lock);
+	if (m_ctrl != master)
+		return;
+
+	mutex_lock(&board_lock);
+	list_del(&master->list);
+	mutex_unlock(&board_lock);
+
+	/* free bus id */
+	mutex_lock(&swr_lock);
+	idr_remove(&master_idr, master->bus_num);
+	mutex_unlock(&swr_lock);
+
+	dummy = device_for_each_child(&master->dev, NULL, __unregister);
+	device_unregister(&master->dev);
+}
+EXPORT_SYMBOL(swr_unregister_master);
+
+/**
+ * swr_register_master - register soundwire master controller
+ * @master: master to be registered
+ *
+ * This API will register master with the framework. master->bus_num
+ * is the desired number with which soundwire framework registers the
+ * master.
+ */
+int swr_register_master(struct swr_master *master)
+{
+	int id;
+	int status = 0;
+
+	mutex_lock(&swr_lock);
+	id = idr_alloc(&master_idr, master, master->bus_num,
+			master->bus_num+1, GFP_KERNEL);
+	mutex_unlock(&swr_lock);
+	if (id < 0)
+		return id;
+	master->bus_num = id;
+
+	/* Can't register until driver model init */
+	if (WARN_ON(!soundwire_type.p)) {
+		status = -EAGAIN;
+		goto done;
+	}
+
+	dev_set_name(&master->dev, "swr%u", master->bus_num);
+	master->dev.bus = &soundwire_type;
+	master->dev.type = &swr_master_type;
+	mutex_init(&master->mlock);
+	status = device_register(&master->dev);
+	if (status < 0)
+		goto done;
+
+	INIT_LIST_HEAD(&master->devices);
+	pr_debug("%s: SWR master registered successfully %s\n",
+		__func__, dev_name(&master->dev));
+	return 0;
+
+done:
+	idr_remove(&master_idr, master->bus_num);
+	return status;
+}
+EXPORT_SYMBOL(swr_register_master);
+
+#define swr_device_attr_gr NULL
+#define swr_device_uevent NULL
+static struct device_type swr_dev_type = {
+	.groups    = swr_device_attr_gr,
+	.uevent    = swr_device_uevent,
+	.release   = swr_dev_release,
+};
+
+static const struct swr_device_id *swr_match(const struct swr_device_id *id,
+					     const struct swr_device *swr_dev)
+{
+	while (id->name[0]) {
+		if (strcmp(swr_dev->name, id->name) == 0)
+			return id;
+		id++;
+	}
+	return NULL;
+}
+
+static int swr_device_match(struct device *dev, struct device_driver *driver)
+{
+	struct swr_device *swr_dev;
+	struct swr_driver *drv = to_swr_driver(driver);
+
+	if (!drv)
+		return -EINVAL;
+
+	if (dev->type == &swr_dev_type)
+		swr_dev = to_swr_device(dev);
+	else
+		return 0;
+	if (drv->id_table)
+		return swr_match(drv->id_table, swr_dev) != NULL;
+
+	if (driver->name)
+		return strcmp(swr_dev->name, driver->name) == 0;
+	return 0;
+}
+#ifdef CONFIG_PM_SLEEP
+static int swr_legacy_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct swr_device *swr_dev = NULL;
+	struct swr_driver *driver;
+
+	if (dev->type == &swr_dev_type)
+		swr_dev = to_swr_device(dev);
+
+	if (!swr_dev || !dev->driver)
+		return 0;
+
+	driver = to_swr_driver(dev->driver);
+	if (!driver->suspend)
+		return 0;
+
+	return driver->suspend(swr_dev, mesg);
+}
+
+static int swr_legacy_resume(struct device *dev)
+{
+	struct swr_device *swr_dev = NULL;
+	struct swr_driver *driver;
+
+	if (dev->type == &swr_dev_type)
+		swr_dev = to_swr_device(dev);
+
+	if (!swr_dev || !dev->driver)
+		return 0;
+
+	driver = to_swr_driver(dev->driver);
+	if (!driver->resume)
+		return 0;
+
+	return driver->resume(swr_dev);
+}
+
+static int swr_pm_suspend(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_suspend(dev);
+	else
+		return swr_legacy_suspend(dev, PMSG_SUSPEND);
+}
+
+static int swr_pm_resume(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_resume(dev);
+	else
+		return swr_legacy_resume(dev);
+}
+#else
+#define swr_pm_suspend	NULL
+#define swr_pm_resume	NULL
+#endif /*CONFIG_PM_SLEEP*/
+
+static const struct dev_pm_ops soundwire_pm = {
+	.suspend = swr_pm_suspend,
+	.resume = swr_pm_resume,
+	SET_RUNTIME_PM_OPS(
+		pm_generic_suspend,
+		pm_generic_resume,
+		NULL
+		)
+};
+
+struct device soundwire_dev = {
+	.init_name = "soundwire",
+};
+
+struct bus_type soundwire_type = {
+	.name		= "soundwire",
+	.match		= swr_device_match,
+	.pm		= &soundwire_pm,
+};
+EXPORT_SYMBOL(soundwire_type);
+
+static void __exit soundwire_exit(void)
+{
+	device_unregister(&soundwire_dev);
+	bus_unregister(&soundwire_type);
+}
+
+static int __init soundwire_init(void)
+{
+	int retval;
+
+	retval = bus_register(&soundwire_type);
+	if (!retval)
+		retval = device_register(&soundwire_dev);
+
+	if (retval)
+		bus_unregister(&soundwire_type);
+
+	return retval;
+}
+postcore_initcall(soundwire_init);
+module_exit(soundwire_exit);
+
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Soundwire module");
+MODULE_ALIAS("platform:soundwire");

+ 1880 - 0
drivers/soundwire/swr-wcd-ctrl.c

@@ -0,0 +1,1880 @@
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/soundwire/soundwire.h>
+#include <linux/soundwire/swr-wcd.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include "swrm_registers.h"
+#include "swr-wcd-ctrl.h"
+
+#define SWR_BROADCAST_CMD_ID            0x0F
+#define SWR_AUTO_SUSPEND_DELAY          3 /* delay in sec */
+#define SWR_DEV_ID_MASK			0xFFFFFFFF
+#define SWR_REG_VAL_PACK(data, dev, id, reg)	\
+			((reg) | ((id) << 16) | ((dev) << 20) | ((data) << 24))
+
+/* pm runtime auto suspend timer in msecs */
+static int auto_suspend_timer = SWR_AUTO_SUSPEND_DELAY * 1000;
+module_param(auto_suspend_timer, int, 0664);
+MODULE_PARM_DESC(auto_suspend_timer, "timer for auto suspend");
+
+static u8 mstr_ports[] = {100, 101, 102, 103, 104, 105, 106, 107};
+static u8 mstr_port_type[] = {SWR_DAC_PORT, SWR_COMP_PORT, SWR_BOOST_PORT,
+			      SWR_DAC_PORT, SWR_COMP_PORT, SWR_BOOST_PORT,
+			      SWR_VISENSE_PORT, SWR_VISENSE_PORT};
+
+struct usecase uc[] = {
+	{0, 0, 0},		/* UC0: no ports */
+	{1, 1, 2400},		/* UC1: Spkr */
+	{1, 4, 600},		/* UC2: Compander */
+	{1, 2, 300},		/* UC3: Smart Boost */
+	{1, 2, 1200},		/* UC4: VI Sense */
+	{4, 9, 4500},		/* UC5: Spkr + Comp + SB + VI */
+	{8, 18, 9000},		/* UC6: 2*(Spkr + Comp + SB + VI) */
+	{2, 2, 4800},		/* UC7: 2*Spkr */
+	{2, 5, 3000},		/* UC8: Spkr + Comp */
+	{4, 10, 6000},		/* UC9: 2*(Spkr + Comp) */
+	{3, 7, 3300},		/* UC10: Spkr + Comp + SB */
+	{6, 14, 6600},		/* UC11: 2*(Spkr + Comp + SB) */
+	{2, 3, 2700},		/* UC12: Spkr + SB */
+	{4, 6, 5400},		/* UC13: 2*(Spkr + SB) */
+	{3, 5, 3900},		/* UC14: Spkr + SB + VI */
+	{6, 10, 7800},		/* UC15: 2*(Spkr + SB + VI) */
+	{2, 3, 3600},		/* UC16: Spkr + VI */
+	{4, 6, 7200},		/* UC17: 2*(Spkr + VI) */
+	{3, 7, 4200},		/* UC18: Spkr + Comp + VI */
+	{6, 14, 8400},		/* UC19: 2*(Spkr + Comp + VI) */
+};
+#define MAX_USECASE	ARRAY_SIZE(uc)
+
+struct port_params pp[MAX_USECASE][SWR_MSTR_PORT_LEN] = {
+	/* UC 0 */
+	{
+		{0, 0, 0},
+	},
+	/* UC 1 */
+	{
+		{7, 1, 0},
+	},
+	/* UC 2 */
+	{
+		{31, 2, 0},
+	},
+	/* UC 3 */
+	{
+		{63, 12, 31},
+	},
+	/* UC 4 */
+	{
+		{15, 7, 0},
+	},
+	/* UC 5 */
+	{
+		{7, 1, 0},
+		{31, 2, 0},
+		{63, 12, 31},
+		{15, 7, 0},
+	},
+	/* UC 6 */
+	{
+		{7, 1, 0},
+		{31, 2, 0},
+		{63, 12, 31},
+		{15, 7, 0},
+		{7, 6, 0},
+		{31, 18, 0},
+		{63, 13, 31},
+		{15, 10, 0},
+	},
+	/* UC 7 */
+	{
+		{7, 1, 0},
+		{7, 6, 0},
+
+	},
+	/* UC 8 */
+	{
+		{7, 1, 0},
+		{31, 2, 0},
+	},
+	/* UC 9 */
+	{
+		{7, 1, 0},
+		{31, 2, 0},
+		{7, 6, 0},
+		{31, 18, 0},
+	},
+	/* UC 10 */
+	{
+		{7, 1, 0},
+		{31, 2, 0},
+		{63, 12, 31},
+	},
+	/* UC 11 */
+	{
+		{7, 1, 0},
+		{31, 2, 0},
+		{63, 12, 31},
+		{7, 6, 0},
+		{31, 18, 0},
+		{63, 13, 31},
+	},
+	/* UC 12 */
+	{
+		{7, 1, 0},
+		{63, 12, 31},
+	},
+	/* UC 13 */
+	{
+		{7, 1, 0},
+		{63, 12, 31},
+		{7, 6, 0},
+		{63, 13, 31},
+	},
+	/* UC 14 */
+	{
+		{7, 1, 0},
+		{63, 12, 31},
+		{15, 7, 0},
+	},
+	/* UC 15 */
+	{
+		{7, 1, 0},
+		{63, 12, 31},
+		{15, 7, 0},
+		{7, 6, 0},
+		{63, 13, 31},
+		{15, 10, 0},
+	},
+	/* UC 16 */
+	{
+		{7, 1, 0},
+		{15, 7, 0},
+	},
+	/* UC 17 */
+	{
+		{7, 1, 0},
+		{15, 7, 0},
+		{7, 6, 0},
+		{15, 10, 0},
+	},
+	/* UC 18 */
+	{
+		{7, 1, 0},
+		{31, 2, 0},
+		{15, 7, 0},
+	},
+	/* UC 19 */
+	{
+		{7, 1, 0},
+		{31, 2, 0},
+		{15, 7, 0},
+		{7, 6, 0},
+		{31, 18, 0},
+		{15, 10, 0},
+	},
+};
+
+enum {
+	SWR_NOT_PRESENT, /* Device is detached/not present on the bus */
+	SWR_ATTACHED_OK, /* Device is attached */
+	SWR_ALERT,       /* Device alters master for any interrupts */
+	SWR_RESERVED,    /* Reserved */
+};
+
+#define SWRM_MAX_PORT_REG    40
+#define SWRM_MAX_INIT_REG    8
+
+#define SWR_MSTR_MAX_REG_ADDR	0x1740
+#define SWR_MSTR_START_REG_ADDR	0x00
+#define SWR_MSTR_MAX_BUF_LEN     32
+#define BYTES_PER_LINE          12
+#define SWR_MSTR_RD_BUF_LEN      8
+#define SWR_MSTR_WR_BUF_LEN      32
+
+static void swrm_copy_data_port_config(struct swr_master *master,
+				       u8 inactive_bank);
+static struct swr_mstr_ctrl *dbgswrm;
+static struct dentry *debugfs_swrm_dent;
+static struct dentry *debugfs_peek;
+static struct dentry *debugfs_poke;
+static struct dentry *debugfs_reg_dump;
+static unsigned int read_data;
+
+
+static bool swrm_is_msm_variant(int val)
+{
+	return (val == SWRM_VERSION_1_3);
+}
+
+static int swrm_debug_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static int get_parameters(char *buf, u32 *param1, int num_of_par)
+{
+	char *token;
+	int base, cnt;
+
+	token = strsep(&buf, " ");
+	for (cnt = 0; cnt < num_of_par; cnt++) {
+		if (token) {
+			if ((token[1] == 'x') || (token[1] == 'X'))
+				base = 16;
+			else
+				base = 10;
+
+			if (kstrtou32(token, base, &param1[cnt]) != 0)
+				return -EINVAL;
+
+			token = strsep(&buf, " ");
+		} else
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static ssize_t swrm_reg_show(char __user *ubuf, size_t count,
+					  loff_t *ppos)
+{
+	int i, reg_val, len;
+	ssize_t total = 0;
+	char tmp_buf[SWR_MSTR_MAX_BUF_LEN];
+
+	if (!ubuf || !ppos)
+		return 0;
+
+	for (i = (((int) *ppos / BYTES_PER_LINE) + SWR_MSTR_START_REG_ADDR);
+		i <= SWR_MSTR_MAX_REG_ADDR; i += 4) {
+		reg_val = dbgswrm->read(dbgswrm->handle, i);
+		len = snprintf(tmp_buf, 25, "0x%.3x: 0x%.2x\n", i, reg_val);
+		if ((total + len) >= count - 1)
+			break;
+		if (copy_to_user((ubuf + total), tmp_buf, len)) {
+			pr_err("%s: fail to copy reg dump\n", __func__);
+			total = -EFAULT;
+			goto copy_err;
+		}
+		*ppos += len;
+		total += len;
+	}
+
+copy_err:
+	return total;
+}
+
+static ssize_t swrm_debug_read(struct file *file, char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	char lbuf[SWR_MSTR_RD_BUF_LEN];
+	char *access_str;
+	ssize_t ret_cnt;
+
+	if (!count || !file || !ppos || !ubuf)
+		return -EINVAL;
+
+	access_str = file->private_data;
+	if (*ppos < 0)
+		return -EINVAL;
+
+	if (!strcmp(access_str, "swrm_peek")) {
+		snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
+		ret_cnt = simple_read_from_buffer(ubuf, count, ppos, lbuf,
+					       strnlen(lbuf, 7));
+	} else if (!strcmp(access_str, "swrm_reg_dump")) {
+		ret_cnt = swrm_reg_show(ubuf, count, ppos);
+	} else {
+		pr_err("%s: %s not permitted to read\n", __func__, access_str);
+		ret_cnt = -EPERM;
+	}
+	return ret_cnt;
+}
+
+static ssize_t swrm_debug_write(struct file *filp,
+	const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	char lbuf[SWR_MSTR_WR_BUF_LEN];
+	int rc;
+	u32 param[5];
+	char *access_str;
+
+	if (!filp || !ppos || !ubuf)
+		return -EINVAL;
+
+	access_str = filp->private_data;
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+
+	lbuf[cnt] = '\0';
+	if (!strcmp(access_str, "swrm_poke")) {
+		/* write */
+		rc = get_parameters(lbuf, param, 2);
+		if ((param[0] <= SWR_MSTR_MAX_REG_ADDR) &&
+			(param[1] <= 0xFFFFFFFF) &&
+			(rc == 0))
+			rc = dbgswrm->write(dbgswrm->handle, param[0],
+					    param[1]);
+		else
+			rc = -EINVAL;
+	} else if (!strcmp(access_str, "swrm_peek")) {
+		/* read */
+		rc = get_parameters(lbuf, param, 1);
+		if ((param[0] <= SWR_MSTR_MAX_REG_ADDR) && (rc == 0))
+			read_data = dbgswrm->read(dbgswrm->handle, param[0]);
+		else
+			rc = -EINVAL;
+	}
+	if (rc == 0)
+		rc = cnt;
+	else
+		pr_err("%s: rc = %d\n", __func__, rc);
+
+	return rc;
+}
+
+static const struct file_operations swrm_debug_ops = {
+	.open = swrm_debug_open,
+	.write = swrm_debug_write,
+	.read = swrm_debug_read,
+};
+
+static int swrm_set_ch_map(struct swr_mstr_ctrl *swrm, void *data)
+{
+	struct swr_mstr_port *pinfo = (struct swr_mstr_port *)data;
+
+	swrm->mstr_port = kzalloc(sizeof(struct swr_mstr_port), GFP_KERNEL);
+	if (swrm->mstr_port == NULL)
+		return -ENOMEM;
+	swrm->mstr_port->num_port = pinfo->num_port;
+	swrm->mstr_port->port = kzalloc((pinfo->num_port * sizeof(u8)),
+					GFP_KERNEL);
+	if (!swrm->mstr_port->port) {
+		kfree(swrm->mstr_port);
+		swrm->mstr_port = NULL;
+		return -ENOMEM;
+	}
+	memcpy(swrm->mstr_port->port, pinfo->port, pinfo->num_port);
+	return 0;
+}
+
+static bool swrm_is_port_en(struct swr_master *mstr)
+{
+	return !!(mstr->num_port);
+}
+
+static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable)
+{
+	if (!swrm->clk || !swrm->handle)
+		return -EINVAL;
+
+	if (enable) {
+		swrm->clk(swrm->handle, true);
+		swrm->state = SWR_MSTR_UP;
+	} else {
+		swrm->clk(swrm->handle, false);
+		swrm->state = SWR_MSTR_DOWN;
+	}
+	return 0;
+}
+
+static int swrm_get_port_config(struct swr_master *master)
+{
+	u32 ch_rate = 0;
+	u32 num_ch = 0;
+	int i, uc_idx;
+	u32 portcount = 0;
+
+	for (i = 0; i < SWR_MSTR_PORT_LEN; i++) {
+		if (master->port[i].port_en) {
+			ch_rate += master->port[i].ch_rate;
+			num_ch += master->port[i].num_ch;
+			portcount++;
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(uc); i++) {
+		if ((uc[i].num_port == portcount) &&
+		    (uc[i].num_ch == num_ch) &&
+		    (uc[i].chrate == ch_rate)) {
+			uc_idx = i;
+			break;
+		}
+	}
+
+	if (i >= ARRAY_SIZE(uc)) {
+		dev_err(&master->dev,
+			"%s: usecase port:%d, num_ch:%d, chrate:%d not found\n",
+			__func__, master->num_port, num_ch, ch_rate);
+		return -EINVAL;
+	}
+	for (i = 0; i < SWR_MSTR_PORT_LEN; i++) {
+		if (master->port[i].port_en) {
+			master->port[i].sinterval = pp[uc_idx][i].si;
+			master->port[i].offset1 = pp[uc_idx][i].off1;
+			master->port[i].offset2 = pp[uc_idx][i].off2;
+		}
+	}
+	return 0;
+}
+
+static int swrm_get_master_port(u8 *mstr_port_id, u8 slv_port_id)
+{
+	int i;
+
+	for (i = 0; i < SWR_MSTR_PORT_LEN; i++) {
+		if (mstr_ports[i] == slv_port_id) {
+			*mstr_port_id = i;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static u32 swrm_get_packed_reg_val(u8 *cmd_id, u8 cmd_data,
+				 u8 dev_addr, u16 reg_addr)
+{
+	u32 val;
+	u8 id = *cmd_id;
+
+	if (id != SWR_BROADCAST_CMD_ID) {
+		if (id < 14)
+			id += 1;
+		else
+			id = 0;
+		*cmd_id = id;
+	}
+	val = SWR_REG_VAL_PACK(cmd_data, dev_addr, id, reg_addr);
+
+	return val;
+}
+
+static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
+				 u8 dev_addr, u8 cmd_id, u16 reg_addr,
+				 u32 len)
+{
+	u32 val;
+	int ret = 0;
+
+	val = swrm_get_packed_reg_val(&swrm->rcmd_id, len, dev_addr, reg_addr);
+	ret = swrm->write(swrm->handle, SWRM_CMD_FIFO_RD_CMD, val);
+	if (ret < 0) {
+		dev_err(swrm->dev, "%s: reg 0x%x write failed, err:%d\n",
+			__func__, val, ret);
+		goto err;
+	}
+	*cmd_data = swrm->read(swrm->handle, SWRM_CMD_FIFO_RD_FIFO_ADDR);
+	dev_dbg(swrm->dev,
+		"%s: reg: 0x%x, cmd_id: 0x%x, dev_id: 0x%x, cmd_data: 0x%x\n",
+		__func__, reg_addr, cmd_id, dev_addr, *cmd_data);
+err:
+	return ret;
+}
+
+static int swrm_cmd_fifo_wr_cmd(struct swr_mstr_ctrl *swrm, u8 cmd_data,
+				 u8 dev_addr, u8 cmd_id, u16 reg_addr)
+{
+	u32 val;
+	int ret = 0;
+
+	if (!cmd_id)
+		val = swrm_get_packed_reg_val(&swrm->wcmd_id, cmd_data,
+					      dev_addr, reg_addr);
+	else
+		val = swrm_get_packed_reg_val(&cmd_id, cmd_data,
+					      dev_addr, reg_addr);
+
+	dev_dbg(swrm->dev,
+		"%s: reg: 0x%x, cmd_id: 0x%x, dev_id: 0x%x, cmd_data: 0x%x\n",
+		__func__, reg_addr, cmd_id, dev_addr, cmd_data);
+	ret = swrm->write(swrm->handle, SWRM_CMD_FIFO_WR_CMD, val);
+	if (ret < 0) {
+		dev_err(swrm->dev, "%s: reg 0x%x write failed, err:%d\n",
+			__func__, val, ret);
+		goto err;
+	}
+	if (cmd_id == 0xF) {
+		/*
+		 * sleep for 10ms for MSM soundwire variant to allow broadcast
+		 * command to complete.
+		 */
+		if (swrm_is_msm_variant(swrm->version))
+			usleep_range(10000, 10100);
+		else
+			wait_for_completion_timeout(&swrm->broadcast,
+						    (2 * HZ/10));
+	}
+err:
+	return ret;
+}
+
+static int swrm_read(struct swr_master *master, u8 dev_num, u16 reg_addr,
+		     void *buf, u32 len)
+{
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+	int ret = 0;
+	int val;
+	u8 *reg_val = (u8 *)buf;
+
+	if (!swrm) {
+		dev_err(&master->dev, "%s: swrm is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (dev_num)
+		ret = swrm_cmd_fifo_rd_cmd(swrm, &val, dev_num, 0, reg_addr,
+					   len);
+	else
+		val = swrm->read(swrm->handle, reg_addr);
+
+	if (!ret)
+		*reg_val = (u8)val;
+
+	pm_runtime_mark_last_busy(&swrm->pdev->dev);
+
+	return ret;
+}
+
+static int swrm_write(struct swr_master *master, u8 dev_num, u16 reg_addr,
+		      const void *buf)
+{
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+	int ret = 0;
+	u8 reg_val = *(u8 *)buf;
+
+	if (!swrm) {
+		dev_err(&master->dev, "%s: swrm is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (dev_num)
+		ret = swrm_cmd_fifo_wr_cmd(swrm, reg_val, dev_num, 0, reg_addr);
+	else
+		ret = swrm->write(swrm->handle, reg_addr, reg_val);
+
+	pm_runtime_mark_last_busy(&swrm->pdev->dev);
+
+	return ret;
+}
+
+static int swrm_bulk_write(struct swr_master *master, u8 dev_num, void *reg,
+			   const void *buf, size_t len)
+{
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+	int ret = 0;
+	int i;
+	u32 *val;
+	u32 *swr_fifo_reg;
+
+	if (!swrm || !swrm->handle) {
+		dev_err(&master->dev, "%s: swrm is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (len <= 0)
+		return -EINVAL;
+
+	if (dev_num) {
+		swr_fifo_reg = kcalloc(len, sizeof(u32), GFP_KERNEL);
+		if (!swr_fifo_reg) {
+			ret = -ENOMEM;
+			goto err;
+		}
+		val = kcalloc(len, sizeof(u32), GFP_KERNEL);
+		if (!val) {
+			ret = -ENOMEM;
+			goto mem_fail;
+		}
+
+		for (i = 0; i < len; i++) {
+			val[i] = swrm_get_packed_reg_val(&swrm->wcmd_id,
+							 ((u8 *)buf)[i],
+							 dev_num,
+							 ((u16 *)reg)[i]);
+			swr_fifo_reg[i] = SWRM_CMD_FIFO_WR_CMD;
+		}
+		ret = swrm->bulk_write(swrm->handle, swr_fifo_reg, val, len);
+		if (ret) {
+			dev_err(&master->dev, "%s: bulk write failed\n",
+				__func__);
+			ret = -EINVAL;
+		}
+	} else {
+		dev_err(&master->dev,
+			"%s: No support of Bulk write for master regs\n",
+			__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	kfree(val);
+mem_fail:
+	kfree(swr_fifo_reg);
+err:
+	pm_runtime_mark_last_busy(&swrm->pdev->dev);
+	return ret;
+}
+
+static u8 get_inactive_bank_num(struct swr_mstr_ctrl *swrm)
+{
+	return (swrm->read(swrm->handle, SWRM_MCP_STATUS) &
+		SWRM_MCP_STATUS_BANK_NUM_MASK) ? 0 : 1;
+}
+
+static void enable_bank_switch(struct swr_mstr_ctrl *swrm, u8 bank,
+				u8 row, u8 col)
+{
+	swrm_cmd_fifo_wr_cmd(swrm, ((row << 3) | col), 0xF, 0xF,
+			SWRS_SCP_FRAME_CTRL_BANK(bank));
+}
+
+static struct swr_port_info *swrm_get_port(struct swr_master *master,
+					   u8 port_id)
+{
+	int i;
+	struct swr_port_info *port = NULL;
+
+	for (i = 0; i < SWR_MSTR_PORT_LEN; i++) {
+		port = &master->port[i];
+		if (port->port_id == port_id) {
+			dev_dbg(&master->dev, "%s: port_id: %d, index: %d\n",
+				__func__, port_id, i);
+			return port;
+		}
+	}
+
+	return NULL;
+}
+
+static struct swr_port_info *swrm_get_avail_port(struct swr_master *master)
+{
+	int i;
+	struct swr_port_info *port = NULL;
+
+	for (i = 0; i < SWR_MSTR_PORT_LEN; i++) {
+		port = &master->port[i];
+		if (port->port_en)
+			continue;
+
+		dev_dbg(&master->dev, "%s: port_id: %d, index: %d\n",
+			__func__, port->port_id, i);
+		return port;
+	}
+
+	return NULL;
+}
+
+static struct swr_port_info *swrm_get_enabled_port(struct swr_master *master,
+						   u8 port_id)
+{
+	int i;
+	struct swr_port_info *port = NULL;
+
+	for (i = 0; i < SWR_MSTR_PORT_LEN; i++) {
+		port = &master->port[i];
+		if ((port->port_id == port_id) && (port->port_en == true))
+			break;
+	}
+	if (i == SWR_MSTR_PORT_LEN)
+		port = NULL;
+	return port;
+}
+
+static bool swrm_remove_from_group(struct swr_master *master)
+{
+	struct swr_device *swr_dev;
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+	bool is_removed = false;
+
+	if (!swrm)
+		goto end;
+
+	mutex_lock(&swrm->mlock);
+	if ((swrm->num_rx_chs > 1) &&
+	    (swrm->num_rx_chs == swrm->num_cfg_devs)) {
+		list_for_each_entry(swr_dev, &master->devices,
+				dev_list) {
+			swr_dev->group_id = SWR_GROUP_NONE;
+			master->gr_sid = 0;
+		}
+		is_removed = true;
+	}
+	mutex_unlock(&swrm->mlock);
+
+end:
+	return is_removed;
+}
+
+static void swrm_cleanup_disabled_data_ports(struct swr_master *master,
+					     u8 bank)
+{
+	u32 value;
+	struct swr_port_info *port;
+	int i;
+	int port_type;
+	struct swrm_mports *mport, *mport_next = NULL;
+	int port_disable_cnt = 0;
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+
+	if (!swrm) {
+		pr_err("%s: swrm is null\n", __func__);
+		return;
+	}
+
+	dev_dbg(swrm->dev, "%s: master num_port: %d\n", __func__,
+		master->num_port);
+
+	mport = list_first_entry_or_null(&swrm->mport_list,
+					struct swrm_mports,
+					list);
+	if (!mport) {
+		dev_err(swrm->dev, "%s: list is empty\n", __func__);
+		return;
+	}
+
+	for (i = 0; i < master->num_port; i++) {
+		port = swrm_get_port(master, mstr_ports[mport->id]);
+		if (!port || port->ch_en)
+			goto inc_loop;
+
+		port_disable_cnt++;
+		port_type = mstr_port_type[mport->id];
+		value = ((port->ch_en)
+				<< SWRM_DP_PORT_CTRL_EN_CHAN_SHFT);
+		value |= ((port->offset2)
+				<< SWRM_DP_PORT_CTRL_OFFSET2_SHFT);
+		value |= ((port->offset1)
+				<< SWRM_DP_PORT_CTRL_OFFSET1_SHFT);
+		value |= port->sinterval;
+
+		swrm->write(swrm->handle,
+			    SWRM_DP_PORT_CTRL_BANK((mport->id+1), bank),
+			    value);
+		swrm_cmd_fifo_wr_cmd(swrm, 0x00, port->dev_id, 0x00,
+				SWRS_DP_CHANNEL_ENABLE_BANK(port_type, bank));
+
+		dev_dbg(swrm->dev, "%s: mport :%d, reg: 0x%x, val: 0x%x\n",
+			__func__, mport->id,
+			(SWRM_DP_PORT_CTRL_BANK((mport->id+1), bank)), value);
+
+inc_loop:
+		mport_next = list_next_entry(mport, list);
+		if (port && !port->ch_en) {
+			list_del(&mport->list);
+			kfree(mport);
+		}
+		if (!mport_next) {
+			dev_err(swrm->dev, "%s: end of list\n", __func__);
+			break;
+		}
+		mport = mport_next;
+	}
+	master->num_port -= port_disable_cnt;
+
+	dev_dbg(swrm->dev, "%s:disable ports: %d, active ports (rem): %d\n",
+		__func__, port_disable_cnt,  master->num_port);
+}
+
+static void swrm_slvdev_datapath_control(struct swr_master *master,
+					 bool enable)
+{
+	u8 bank;
+	u32 value, n_col;
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+	int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK |
+		    SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK |
+		    SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK);
+	u8 inactive_bank;
+
+	if (!swrm) {
+		pr_err("%s: swrm is null\n", __func__);
+		return;
+	}
+
+	bank = get_inactive_bank_num(swrm);
+
+	dev_dbg(swrm->dev, "%s: enable: %d, cfg_devs: %d\n",
+		__func__, enable, swrm->num_cfg_devs);
+
+	if (enable) {
+		/* set Row = 48 and col = 16 */
+		n_col = SWR_MAX_COL;
+	} else {
+		/*
+		 * Do not change to 48x2 if number of channels configured
+		 * as stereo and if disable datapath is called for the
+		 * first slave device
+		 */
+		if (swrm->num_cfg_devs > 0)
+			n_col = SWR_MAX_COL;
+		else
+			n_col = SWR_MIN_COL;
+
+		/*
+		 * All ports are already disabled, no need to perform
+		 * bank-switch and copy operation. This case can arise
+		 * when speaker channels are enabled in stereo mode with
+		 * BROADCAST and disabled in GROUP_NONE
+		 */
+		if (master->num_port == 0)
+			return;
+	}
+
+	value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank));
+	value &= (~mask);
+	value |= ((0 << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
+		  (n_col << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) |
+		  (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
+	swrm->write(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value);
+
+	dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__,
+		SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value);
+
+	enable_bank_switch(swrm, bank, SWR_MAX_ROW, n_col);
+
+	inactive_bank = bank ? 0 : 1;
+	if (enable)
+		swrm_copy_data_port_config(master, inactive_bank);
+	else
+		swrm_cleanup_disabled_data_ports(master, inactive_bank);
+
+	if (!swrm_is_port_en(master)) {
+		dev_dbg(&master->dev, "%s: pm_runtime auto suspend triggered\n",
+			__func__);
+		pm_runtime_mark_last_busy(&swrm->pdev->dev);
+		pm_runtime_put_autosuspend(&swrm->pdev->dev);
+	}
+}
+
+static void swrm_apply_port_config(struct swr_master *master)
+{
+	u8 bank;
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+
+	if (!swrm) {
+		pr_err("%s: Invalid handle to swr controller\n",
+			__func__);
+		return;
+	}
+
+	bank = get_inactive_bank_num(swrm);
+	dev_dbg(swrm->dev, "%s: enter bank: %d master_ports: %d\n",
+		__func__, bank, master->num_port);
+
+
+	swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00,
+			SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank));
+
+	swrm_copy_data_port_config(master, bank);
+}
+
+static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
+{
+	u32 value;
+	struct swr_port_info *port;
+	int i;
+	int port_type;
+	struct swrm_mports *mport;
+	u32 reg[SWRM_MAX_PORT_REG];
+	u32 val[SWRM_MAX_PORT_REG];
+	int len = 0;
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+
+	if (!swrm) {
+		pr_err("%s: swrm is null\n", __func__);
+		return;
+	}
+
+	dev_dbg(swrm->dev, "%s: master num_port: %d\n", __func__,
+		master->num_port);
+
+	mport = list_first_entry_or_null(&swrm->mport_list,
+					struct swrm_mports,
+					list);
+	if (!mport) {
+		dev_err(swrm->dev, "%s: list is empty\n", __func__);
+		return;
+	}
+	for (i = 0; i < master->num_port; i++) {
+
+		port = swrm_get_enabled_port(master, mstr_ports[mport->id]);
+		if (!port)
+			continue;
+		port_type = mstr_port_type[mport->id];
+		if (!port->dev_id || (port->dev_id > master->num_dev)) {
+			dev_dbg(swrm->dev, "%s: invalid device id = %d\n",
+				__func__, port->dev_id);
+			continue;
+		}
+		value = ((port->ch_en)
+				<< SWRM_DP_PORT_CTRL_EN_CHAN_SHFT);
+		value |= ((port->offset2)
+				<< SWRM_DP_PORT_CTRL_OFFSET2_SHFT);
+		value |= ((port->offset1)
+				<< SWRM_DP_PORT_CTRL_OFFSET1_SHFT);
+		value |= port->sinterval;
+
+		reg[len] = SWRM_DP_PORT_CTRL_BANK((mport->id+1), bank);
+		val[len++] = value;
+
+		dev_dbg(swrm->dev, "%s: mport :%d, reg: 0x%x, val: 0x%x\n",
+			__func__, mport->id,
+			(SWRM_DP_PORT_CTRL_BANK((mport->id+1), bank)), value);
+
+		reg[len] = SWRM_CMD_FIFO_WR_CMD;
+		val[len++] = SWR_REG_VAL_PACK(port->ch_en, port->dev_id, 0x00,
+				SWRS_DP_CHANNEL_ENABLE_BANK(port_type, bank));
+
+		reg[len] = SWRM_CMD_FIFO_WR_CMD;
+		val[len++] = SWR_REG_VAL_PACK(port->sinterval,
+				port->dev_id, 0x00,
+				SWRS_DP_SAMPLE_CONTROL_1_BANK(port_type, bank));
+
+		reg[len] = SWRM_CMD_FIFO_WR_CMD;
+		val[len++] = SWR_REG_VAL_PACK(port->offset1,
+				port->dev_id, 0x00,
+				SWRS_DP_OFFSET_CONTROL_1_BANK(port_type, bank));
+
+		if (port_type != 0) {
+			reg[len] = SWRM_CMD_FIFO_WR_CMD;
+			val[len++] = SWR_REG_VAL_PACK(port->offset2,
+					port->dev_id, 0x00,
+					SWRS_DP_OFFSET_CONTROL_2_BANK(port_type,
+									bank));
+		}
+		mport = list_next_entry(mport, list);
+		if (!mport) {
+			dev_err(swrm->dev, "%s: end of list\n", __func__);
+			break;
+		}
+	}
+	swrm->bulk_write(swrm->handle, reg, val, len);
+}
+
+static int swrm_connect_port(struct swr_master *master,
+			struct swr_params *portinfo)
+{
+	int i;
+	struct swr_port_info *port;
+	int ret = 0;
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+	struct swrm_mports *mport;
+	struct list_head *ptr, *next;
+
+	dev_dbg(&master->dev, "%s: enter\n", __func__);
+	if (!portinfo)
+		return -EINVAL;
+
+	if (!swrm) {
+		dev_err(&master->dev,
+			"%s: Invalid handle to swr controller\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&swrm->mlock);
+	if (!swrm_is_port_en(master))
+		pm_runtime_get_sync(&swrm->pdev->dev);
+
+	for (i = 0; i < portinfo->num_port; i++) {
+		mport = kzalloc(sizeof(struct swrm_mports), GFP_KERNEL);
+		if (!mport) {
+			ret = -ENOMEM;
+			goto mem_fail;
+		}
+		ret = swrm_get_master_port(&mport->id,
+						portinfo->port_id[i]);
+		if (ret < 0) {
+			dev_err(&master->dev,
+				"%s: mstr portid for slv port %d not found\n",
+				__func__, portinfo->port_id[i]);
+			goto port_fail;
+		}
+		port = swrm_get_avail_port(master);
+		if (!port) {
+			dev_err(&master->dev,
+				"%s: avail ports not found!\n", __func__);
+			goto port_fail;
+		}
+		list_add(&mport->list, &swrm->mport_list);
+		port->dev_id = portinfo->dev_id;
+		port->port_id = portinfo->port_id[i];
+		port->num_ch = portinfo->num_ch[i];
+		port->ch_rate = portinfo->ch_rate[i];
+		port->ch_en = portinfo->ch_en[i];
+		port->port_en = true;
+		dev_dbg(&master->dev,
+			"%s: mstr port %d, slv port %d ch_rate %d num_ch %d\n",
+			__func__, mport->id, port->port_id, port->ch_rate,
+			port->num_ch);
+	}
+	master->num_port += portinfo->num_port;
+	if (master->num_port >= SWR_MSTR_PORT_LEN)
+		master->num_port = SWR_MSTR_PORT_LEN;
+
+	swrm_get_port_config(master);
+	swr_port_response(master, portinfo->tid);
+	swrm->num_cfg_devs += 1;
+	dev_dbg(&master->dev, "%s: cfg_devs: %d, rx_chs: %d\n",
+		__func__, swrm->num_cfg_devs, swrm->num_rx_chs);
+	if (swrm->num_rx_chs > 1) {
+		if (swrm->num_rx_chs == swrm->num_cfg_devs)
+			swrm_apply_port_config(master);
+	} else {
+		swrm_apply_port_config(master);
+	}
+	mutex_unlock(&swrm->mlock);
+	return 0;
+
+port_fail:
+	kfree(mport);
+mem_fail:
+	list_for_each_safe(ptr, next, &swrm->mport_list) {
+		mport = list_entry(ptr, struct swrm_mports, list);
+		for (i = 0; i < portinfo->num_port; i++) {
+			if (portinfo->port_id[i] == mstr_ports[mport->id]) {
+				port = swrm_get_port(master,
+						portinfo->port_id[i]);
+				if (port)
+					port->ch_en = false;
+				list_del(&mport->list);
+				kfree(mport);
+				break;
+			}
+		}
+	}
+	mutex_unlock(&swrm->mlock);
+	return ret;
+}
+
+static int swrm_disconnect_port(struct swr_master *master,
+			struct swr_params *portinfo)
+{
+	int i;
+	struct swr_port_info *port;
+	u8 bank;
+	u32 value;
+	int ret = 0;
+	u8 mport_id = 0;
+	int port_type = 0;
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+
+	if (!swrm) {
+		dev_err(&master->dev,
+			"%s: Invalid handle to swr controller\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (!portinfo) {
+		dev_err(&master->dev, "%s: portinfo is NULL\n", __func__);
+		return -EINVAL;
+	}
+	mutex_lock(&swrm->mlock);
+	bank = get_inactive_bank_num(swrm);
+	for (i = 0; i < portinfo->num_port; i++) {
+		ret = swrm_get_master_port(&mport_id,
+						portinfo->port_id[i]);
+		if (ret < 0) {
+			dev_err(&master->dev,
+				"%s: mstr portid for slv port %d not found\n",
+				__func__, portinfo->port_id[i]);
+			mutex_unlock(&swrm->mlock);
+			return -EINVAL;
+		}
+		port = swrm_get_enabled_port(master, portinfo->port_id[i]);
+		if (!port) {
+			dev_dbg(&master->dev, "%s: port %d already disabled\n",
+				__func__, portinfo->port_id[i]);
+			continue;
+		}
+		port_type = mstr_port_type[mport_id];
+		port->dev_id = portinfo->dev_id;
+		port->port_en = false;
+		port->ch_en = 0;
+		value = port->ch_en << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT;
+		value |= (port->offset2 << SWRM_DP_PORT_CTRL_OFFSET2_SHFT);
+		value |= (port->offset1 << SWRM_DP_PORT_CTRL_OFFSET1_SHFT);
+		value |= port->sinterval;
+
+
+		swrm->write(swrm->handle,
+			    SWRM_DP_PORT_CTRL_BANK((mport_id+1), bank),
+			    value);
+		swrm_cmd_fifo_wr_cmd(swrm, 0x00, port->dev_id, 0x00,
+				SWRS_DP_CHANNEL_ENABLE_BANK(port_type, bank));
+	}
+
+	swr_port_response(master, portinfo->tid);
+	swrm->num_cfg_devs -= 1;
+	dev_dbg(&master->dev, "%s: cfg_devs: %d, rx_chs: %d, active ports: %d\n",
+		__func__, swrm->num_cfg_devs, swrm->num_rx_chs,
+		master->num_port);
+	mutex_unlock(&swrm->mlock);
+
+	return 0;
+}
+
+static int swrm_check_slave_change_status(struct swr_mstr_ctrl *swrm,
+					int status, u8 *devnum)
+{
+	int i;
+	int new_sts = status;
+	int ret = SWR_NOT_PRESENT;
+
+	if (status != swrm->slave_status) {
+		for (i = 0; i < (swrm->master.num_dev + 1); i++) {
+			if ((status & SWRM_MCP_SLV_STATUS_MASK) !=
+			    (swrm->slave_status & SWRM_MCP_SLV_STATUS_MASK)) {
+				ret = (status & SWRM_MCP_SLV_STATUS_MASK);
+				*devnum = i;
+				break;
+			}
+			status >>= 2;
+			swrm->slave_status >>= 2;
+		}
+		swrm->slave_status = new_sts;
+	}
+	return ret;
+}
+
+static irqreturn_t swr_mstr_interrupt(int irq, void *dev)
+{
+	struct swr_mstr_ctrl *swrm = dev;
+	u32 value, intr_sts;
+	int status, chg_sts, i;
+	u8 devnum = 0;
+	int ret = IRQ_HANDLED;
+
+	pm_runtime_get_sync(&swrm->pdev->dev);
+	intr_sts = swrm->read(swrm->handle, SWRM_INTERRUPT_STATUS);
+	intr_sts &= SWRM_INTERRUPT_STATUS_RMSK;
+	for (i = 0; i < SWRM_INTERRUPT_MAX; i++) {
+		value = intr_sts & (1 << i);
+		if (!value)
+			continue;
+
+		swrm->write(swrm->handle, SWRM_INTERRUPT_CLEAR, value);
+		switch (value) {
+		case SWRM_INTERRUPT_STATUS_SLAVE_PEND_IRQ:
+			dev_dbg(swrm->dev, "SWR slave pend irq\n");
+			break;
+		case SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED:
+			dev_dbg(swrm->dev, "SWR new slave attached\n");
+			break;
+		case SWRM_INTERRUPT_STATUS_CHANGE_ENUM_SLAVE_STATUS:
+			status = swrm->read(swrm->handle, SWRM_MCP_SLV_STATUS);
+			if (status == swrm->slave_status) {
+				dev_dbg(swrm->dev,
+					"%s: No change in slave status: %d\n",
+					__func__, status);
+				break;
+			}
+			chg_sts = swrm_check_slave_change_status(swrm, status,
+								&devnum);
+			switch (chg_sts) {
+			case SWR_NOT_PRESENT:
+				dev_dbg(swrm->dev, "device %d got detached\n",
+					devnum);
+				break;
+			case SWR_ATTACHED_OK:
+				dev_dbg(swrm->dev, "device %d got attached\n",
+					devnum);
+				break;
+			case SWR_ALERT:
+				dev_dbg(swrm->dev,
+					"device %d has pending interrupt\n",
+					devnum);
+				break;
+			}
+			break;
+		case SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET:
+			dev_err_ratelimited(swrm->dev, "SWR bus clash detected\n");
+			break;
+		case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
+			dev_dbg(swrm->dev, "SWR read FIFO overflow\n");
+			break;
+		case SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW:
+			dev_dbg(swrm->dev, "SWR read FIFO underflow\n");
+			break;
+		case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW:
+			dev_dbg(swrm->dev, "SWR write FIFO overflow\n");
+			break;
+		case SWRM_INTERRUPT_STATUS_CMD_ERROR:
+			value = swrm->read(swrm->handle, SWRM_CMD_FIFO_STATUS);
+			dev_err_ratelimited(swrm->dev,
+			"SWR CMD error, fifo status 0x%x, flushing fifo\n",
+					    value);
+			swrm->write(swrm->handle, SWRM_CMD_FIFO_CMD, 0x1);
+			break;
+		case SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION:
+			dev_dbg(swrm->dev, "SWR Port collision detected\n");
+			break;
+		case SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH:
+			dev_dbg(swrm->dev, "SWR read enable valid mismatch\n");
+			break;
+		case SWRM_INTERRUPT_STATUS_SPECIAL_CMD_ID_FINISHED:
+			complete(&swrm->broadcast);
+			dev_dbg(swrm->dev, "SWR cmd id finished\n");
+			break;
+		case SWRM_INTERRUPT_STATUS_NEW_SLAVE_AUTO_ENUM_FINISHED:
+			break;
+		case SWRM_INTERRUPT_STATUS_AUTO_ENUM_FAILED:
+			break;
+		case SWRM_INTERRUPT_STATUS_AUTO_ENUM_TABLE_IS_FULL:
+			break;
+		case SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED:
+			complete(&swrm->reset);
+			break;
+		case SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED:
+			break;
+		default:
+			dev_err_ratelimited(swrm->dev, "SWR unknown interrupt\n");
+			ret = IRQ_NONE;
+			break;
+		}
+	}
+	pm_runtime_mark_last_busy(&swrm->pdev->dev);
+	pm_runtime_put_autosuspend(&swrm->pdev->dev);
+	return ret;
+}
+
+static int swrm_get_device_status(struct swr_mstr_ctrl *swrm, u8 devnum)
+{
+	u32 val;
+
+	swrm->slave_status = swrm->read(swrm->handle, SWRM_MCP_SLV_STATUS);
+	val = (swrm->slave_status >> (devnum * 2));
+	val &= SWRM_MCP_SLV_STATUS_MASK;
+	return val;
+}
+
+static int swrm_get_logical_dev_num(struct swr_master *mstr, u64 dev_id,
+				u8 *dev_num)
+{
+	int i;
+	u64 id = 0;
+	int ret = -EINVAL;
+	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(mstr);
+
+	if (!swrm) {
+		pr_err("%s: Invalid handle to swr controller\n",
+			__func__);
+		return ret;
+	}
+
+	pm_runtime_get_sync(&swrm->pdev->dev);
+	for (i = 1; i < (mstr->num_dev + 1); i++) {
+		id = ((u64)(swrm->read(swrm->handle,
+			    SWRM_ENUMERATOR_SLAVE_DEV_ID_2(i))) << 32);
+		id |= swrm->read(swrm->handle,
+			    SWRM_ENUMERATOR_SLAVE_DEV_ID_1(i));
+		if ((id & SWR_DEV_ID_MASK) == dev_id) {
+			if (swrm_get_device_status(swrm, i) == 0x01) {
+				*dev_num = i;
+				ret = 0;
+			} else {
+				dev_err(swrm->dev, "%s: device is not ready\n",
+					 __func__);
+			}
+			goto found;
+		}
+	}
+	dev_err(swrm->dev, "%s: device id 0x%llx does not match with 0x%llx\n",
+		__func__, id, dev_id);
+found:
+	pm_runtime_mark_last_busy(&swrm->pdev->dev);
+	pm_runtime_put_autosuspend(&swrm->pdev->dev);
+	return ret;
+}
+static int swrm_master_init(struct swr_mstr_ctrl *swrm)
+{
+	int ret = 0;
+	u32 val;
+	u8 row_ctrl = SWR_MAX_ROW;
+	u8 col_ctrl = SWR_MIN_COL;
+	u8 ssp_period = 1;
+	u8 retry_cmd_num = 3;
+	u32 reg[SWRM_MAX_INIT_REG];
+	u32 value[SWRM_MAX_INIT_REG];
+	int len = 0;
+
+	/* Clear Rows and Cols */
+	val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
+		(col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) |
+		(ssp_period << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
+
+	reg[len] = SWRM_MCP_FRAME_CTRL_BANK_ADDR(0);
+	value[len++] = val;
+
+	/* Set Auto enumeration flag */
+	reg[len] = SWRM_ENUMERATOR_CFG_ADDR;
+	value[len++] = 1;
+
+	/* Mask soundwire interrupts */
+	reg[len] = SWRM_INTERRUPT_MASK_ADDR;
+	value[len++] = 0x1FFFD;
+
+	/* Configure No pings */
+	val = swrm->read(swrm->handle, SWRM_MCP_CFG_ADDR);
+	val &= ~SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK;
+	val |= (0x1f << SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_SHFT);
+	reg[len] = SWRM_MCP_CFG_ADDR;
+	value[len++] = val;
+
+	/* Configure number of retries of a read/write cmd */
+	val = (retry_cmd_num << SWRM_CMD_FIFO_CFG_NUM_OF_CMD_RETRY_SHFT);
+	reg[len] = SWRM_CMD_FIFO_CFG_ADDR;
+	value[len++] = val;
+
+	/* Set IRQ to PULSE */
+	reg[len] = SWRM_COMP_CFG_ADDR;
+	value[len++] = 0x02;
+
+	reg[len] = SWRM_COMP_CFG_ADDR;
+	value[len++] = 0x03;
+
+	reg[len] = SWRM_INTERRUPT_CLEAR;
+	value[len++] = 0x08;
+
+	swrm->bulk_write(swrm->handle, reg, value, len);
+
+	return ret;
+}
+
+static int swrm_probe(struct platform_device *pdev)
+{
+	struct swr_mstr_ctrl *swrm;
+	struct swr_ctrl_platform_data *pdata;
+	int ret;
+
+	/* Allocate soundwire master driver structure */
+	swrm = kzalloc(sizeof(struct swr_mstr_ctrl), GFP_KERNEL);
+	if (!swrm) {
+		ret = -ENOMEM;
+		goto err_memory_fail;
+	}
+	swrm->dev = &pdev->dev;
+	swrm->pdev = pdev;
+	platform_set_drvdata(pdev, swrm);
+	swr_set_ctrl_data(&swrm->master, swrm);
+	pdata = dev_get_platdata(&pdev->dev);
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: pdata from parent is NULL\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_pdata_fail;
+	}
+	swrm->handle = (void *)pdata->handle;
+	if (!swrm->handle) {
+		dev_err(&pdev->dev, "%s: swrm->handle is NULL\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_pdata_fail;
+	}
+	swrm->read = pdata->read;
+	if (!swrm->read) {
+		dev_err(&pdev->dev, "%s: swrm->read is NULL\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_pdata_fail;
+	}
+	swrm->write = pdata->write;
+	if (!swrm->write) {
+		dev_err(&pdev->dev, "%s: swrm->write is NULL\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_pdata_fail;
+	}
+	swrm->bulk_write = pdata->bulk_write;
+	if (!swrm->bulk_write) {
+		dev_err(&pdev->dev, "%s: swrm->bulk_write is NULL\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_pdata_fail;
+	}
+	swrm->clk = pdata->clk;
+	if (!swrm->clk) {
+		dev_err(&pdev->dev, "%s: swrm->clk is NULL\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_pdata_fail;
+	}
+	swrm->reg_irq = pdata->reg_irq;
+	if (!swrm->reg_irq) {
+		dev_err(&pdev->dev, "%s: swrm->reg_irq is NULL\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_pdata_fail;
+	}
+	swrm->master.read = swrm_read;
+	swrm->master.write = swrm_write;
+	swrm->master.bulk_write = swrm_bulk_write;
+	swrm->master.get_logical_dev_num = swrm_get_logical_dev_num;
+	swrm->master.connect_port = swrm_connect_port;
+	swrm->master.disconnect_port = swrm_disconnect_port;
+	swrm->master.slvdev_datapath_control = swrm_slvdev_datapath_control;
+	swrm->master.remove_from_group = swrm_remove_from_group;
+	swrm->master.dev.parent = &pdev->dev;
+	swrm->master.dev.of_node = pdev->dev.of_node;
+	swrm->master.num_port = 0;
+	swrm->num_enum_slaves = 0;
+	swrm->rcmd_id = 0;
+	swrm->wcmd_id = 0;
+	swrm->slave_status = 0;
+	swrm->num_rx_chs = 0;
+	swrm->state = SWR_MSTR_RESUME;
+	init_completion(&swrm->reset);
+	init_completion(&swrm->broadcast);
+	mutex_init(&swrm->mlock);
+	INIT_LIST_HEAD(&swrm->mport_list);
+	mutex_init(&swrm->reslock);
+
+	ret = swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm,
+			    SWR_IRQ_REGISTER);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: IRQ register failed ret %d\n",
+			__func__, ret);
+		goto err_irq_fail;
+	}
+
+	ret = swr_register_master(&swrm->master);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: error adding swr master\n", __func__);
+		goto err_mstr_fail;
+	}
+
+	/* Add devices registered with board-info as the
+	 * controller will be up now
+	 */
+	swr_master_add_boarddevices(&swrm->master);
+	mutex_lock(&swrm->mlock);
+	swrm_clk_request(swrm, true);
+	ret = swrm_master_init(swrm);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"%s: Error in master Initializaiton, err %d\n",
+			__func__, ret);
+		mutex_unlock(&swrm->mlock);
+		goto err_mstr_fail;
+	}
+	swrm->version = swrm->read(swrm->handle, SWRM_COMP_HW_VERSION);
+
+	mutex_unlock(&swrm->mlock);
+
+	if (pdev->dev.of_node)
+		of_register_swr_devices(&swrm->master);
+
+	dbgswrm = swrm;
+	debugfs_swrm_dent = debugfs_create_dir(dev_name(&pdev->dev), 0);
+	if (!IS_ERR(debugfs_swrm_dent)) {
+		debugfs_peek = debugfs_create_file("swrm_peek",
+				S_IFREG | 0444, debugfs_swrm_dent,
+				(void *) "swrm_peek", &swrm_debug_ops);
+
+		debugfs_poke = debugfs_create_file("swrm_poke",
+				S_IFREG | 0444, debugfs_swrm_dent,
+				(void *) "swrm_poke", &swrm_debug_ops);
+
+		debugfs_reg_dump = debugfs_create_file("swrm_reg_dump",
+				   S_IFREG | 0444, debugfs_swrm_dent,
+				   (void *) "swrm_reg_dump",
+				   &swrm_debug_ops);
+	}
+	pm_runtime_set_autosuspend_delay(&pdev->dev, auto_suspend_timer);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_mark_last_busy(&pdev->dev);
+
+	return 0;
+err_mstr_fail:
+	swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
+			swrm, SWR_IRQ_FREE);
+err_irq_fail:
+err_pdata_fail:
+	kfree(swrm);
+err_memory_fail:
+	return ret;
+}
+
+static int swrm_remove(struct platform_device *pdev)
+{
+	struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
+
+	swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
+			swrm, SWR_IRQ_FREE);
+	if (swrm->mstr_port) {
+		kfree(swrm->mstr_port->port);
+		swrm->mstr_port->port = NULL;
+		kfree(swrm->mstr_port);
+		swrm->mstr_port = NULL;
+	}
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	swr_unregister_master(&swrm->master);
+	mutex_destroy(&swrm->mlock);
+	mutex_destroy(&swrm->reslock);
+	kfree(swrm);
+	return 0;
+}
+
+static int swrm_clk_pause(struct swr_mstr_ctrl *swrm)
+{
+	u32 val;
+
+	dev_dbg(swrm->dev, "%s: state: %d\n", __func__, swrm->state);
+	swrm->write(swrm->handle, SWRM_INTERRUPT_MASK_ADDR, 0x1FDFD);
+	val = swrm->read(swrm->handle, SWRM_MCP_CFG_ADDR);
+	val |= SWRM_MCP_CFG_BUS_CLK_PAUSE_BMSK;
+	swrm->write(swrm->handle, SWRM_MCP_CFG_ADDR, val);
+	swrm->state = SWR_MSTR_PAUSE;
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int swrm_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
+	int ret = 0;
+	struct swr_master *mstr = &swrm->master;
+	struct swr_device *swr_dev;
+
+	dev_dbg(dev, "%s: pm_runtime: resume, state:%d\n",
+		__func__, swrm->state);
+	mutex_lock(&swrm->reslock);
+	if ((swrm->state == SWR_MSTR_PAUSE) ||
+	    (swrm->state == SWR_MSTR_DOWN)) {
+		if (swrm->state == SWR_MSTR_DOWN) {
+			if (swrm_clk_request(swrm, true))
+				goto exit;
+		}
+		list_for_each_entry(swr_dev, &mstr->devices, dev_list) {
+			ret = swr_device_up(swr_dev);
+			if (ret) {
+				dev_err(dev,
+					"%s: failed to wakeup swr dev %d\n",
+					__func__, swr_dev->dev_num);
+				swrm_clk_request(swrm, false);
+				goto exit;
+			}
+		}
+		swrm->write(swrm->handle, SWRM_COMP_SW_RESET, 0x01);
+		swrm->write(swrm->handle, SWRM_COMP_SW_RESET, 0x01);
+		swrm_master_init(swrm);
+	}
+exit:
+	pm_runtime_set_autosuspend_delay(&pdev->dev, auto_suspend_timer);
+	mutex_unlock(&swrm->reslock);
+	return ret;
+}
+
+static int swrm_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
+	int ret = 0;
+	struct swr_master *mstr = &swrm->master;
+	struct swr_device *swr_dev;
+
+	dev_dbg(dev, "%s: pm_runtime: suspend state: %d\n",
+		__func__, swrm->state);
+	mutex_lock(&swrm->reslock);
+	if ((swrm->state == SWR_MSTR_RESUME) ||
+	    (swrm->state == SWR_MSTR_UP)) {
+		if (swrm_is_port_en(&swrm->master)) {
+			dev_dbg(dev, "%s ports are enabled\n", __func__);
+			ret = -EBUSY;
+			goto exit;
+		}
+		swrm_clk_pause(swrm);
+		swrm->write(swrm->handle, SWRM_COMP_CFG_ADDR, 0x00);
+		list_for_each_entry(swr_dev, &mstr->devices, dev_list) {
+			ret = swr_device_down(swr_dev);
+			if (ret) {
+				dev_err(dev,
+					"%s: failed to shutdown swr dev %d\n",
+					__func__, swr_dev->dev_num);
+				goto exit;
+			}
+		}
+		swrm_clk_request(swrm, false);
+	}
+exit:
+	mutex_unlock(&swrm->reslock);
+	return ret;
+}
+#endif /* CONFIG_PM */
+
+static int swrm_device_down(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
+	int ret = 0;
+	struct swr_master *mstr = &swrm->master;
+	struct swr_device *swr_dev;
+
+	dev_dbg(dev, "%s: swrm state: %d\n", __func__, swrm->state);
+	mutex_lock(&swrm->reslock);
+	if ((swrm->state == SWR_MSTR_RESUME) ||
+	    (swrm->state == SWR_MSTR_UP)) {
+		list_for_each_entry(swr_dev, &mstr->devices, dev_list) {
+			ret = swr_device_down(swr_dev);
+			if (ret)
+				dev_err(dev,
+					"%s: failed to shutdown swr dev %d\n",
+					__func__, swr_dev->dev_num);
+		}
+		dev_dbg(dev, "%s: Shutting down SWRM\n", __func__);
+		pm_runtime_disable(dev);
+		pm_runtime_set_suspended(dev);
+		pm_runtime_enable(dev);
+		swrm_clk_request(swrm, false);
+	}
+	mutex_unlock(&swrm->reslock);
+	return ret;
+}
+
+/**
+ * swrm_wcd_notify - parent device can notify to soundwire master through
+ * this function
+ * @pdev: pointer to platform device structure
+ * @id: command id from parent to the soundwire master
+ * @data: data from parent device to soundwire master
+ */
+int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
+{
+	struct swr_mstr_ctrl *swrm;
+	int ret = 0;
+	struct swr_master *mstr;
+	struct swr_device *swr_dev;
+
+	if (!pdev) {
+		pr_err("%s: pdev is NULL\n", __func__);
+		return -EINVAL;
+	}
+	swrm = platform_get_drvdata(pdev);
+	if (!swrm) {
+		dev_err(&pdev->dev, "%s: swrm is NULL\n", __func__);
+		return -EINVAL;
+	}
+	mstr = &swrm->master;
+
+	switch (id) {
+	case SWR_CH_MAP:
+		if (!data) {
+			dev_err(swrm->dev, "%s: data is NULL\n", __func__);
+			ret = -EINVAL;
+		} else {
+			ret = swrm_set_ch_map(swrm, data);
+		}
+		break;
+	case SWR_DEVICE_DOWN:
+		dev_dbg(swrm->dev, "%s: swr master down called\n", __func__);
+		mutex_lock(&swrm->mlock);
+		if ((swrm->state == SWR_MSTR_PAUSE) ||
+		    (swrm->state == SWR_MSTR_DOWN))
+			dev_dbg(swrm->dev, "%s: SWR master is already Down: %d\n",
+				__func__, swrm->state);
+		else
+			swrm_device_down(&pdev->dev);
+		mutex_unlock(&swrm->mlock);
+		break;
+	case SWR_DEVICE_UP:
+		dev_dbg(swrm->dev, "%s: swr master up called\n", __func__);
+		mutex_lock(&swrm->mlock);
+		mutex_lock(&swrm->reslock);
+		if ((swrm->state == SWR_MSTR_RESUME) ||
+		    (swrm->state == SWR_MSTR_UP)) {
+			dev_dbg(swrm->dev, "%s: SWR master is already UP: %d\n",
+				__func__, swrm->state);
+		} else {
+			pm_runtime_mark_last_busy(&pdev->dev);
+			mutex_unlock(&swrm->reslock);
+			pm_runtime_get_sync(&pdev->dev);
+			mutex_lock(&swrm->reslock);
+			list_for_each_entry(swr_dev, &mstr->devices, dev_list) {
+				ret = swr_reset_device(swr_dev);
+				if (ret) {
+					dev_err(swrm->dev,
+						"%s: failed to reset swr device %d\n",
+						__func__, swr_dev->dev_num);
+					swrm_clk_request(swrm, false);
+				}
+			}
+			pm_runtime_mark_last_busy(&pdev->dev);
+			pm_runtime_put_autosuspend(&pdev->dev);
+		}
+		mutex_unlock(&swrm->reslock);
+		mutex_unlock(&swrm->mlock);
+		break;
+	case SWR_SET_NUM_RX_CH:
+		if (!data) {
+			dev_err(swrm->dev, "%s: data is NULL\n", __func__);
+			ret = -EINVAL;
+		} else {
+			mutex_lock(&swrm->mlock);
+			swrm->num_rx_chs = *(int *)data;
+			if ((swrm->num_rx_chs > 1) && !swrm->num_cfg_devs) {
+				list_for_each_entry(swr_dev, &mstr->devices,
+						    dev_list) {
+					ret = swr_set_device_group(swr_dev,
+								SWR_BROADCAST);
+					if (ret)
+						dev_err(swrm->dev,
+							"%s: set num ch failed\n",
+							__func__);
+				}
+			} else {
+				list_for_each_entry(swr_dev, &mstr->devices,
+						    dev_list) {
+					ret = swr_set_device_group(swr_dev,
+								SWR_GROUP_NONE);
+					if (ret)
+						dev_err(swrm->dev,
+							"%s: set num ch failed\n",
+							__func__);
+				}
+			}
+			mutex_unlock(&swrm->mlock);
+		}
+		break;
+	default:
+		dev_err(swrm->dev, "%s: swr master unknown id %d\n",
+			__func__, id);
+		break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(swrm_wcd_notify);
+
+#ifdef CONFIG_PM_SLEEP
+static int swrm_suspend(struct device *dev)
+{
+	int ret = -EBUSY;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
+
+	dev_dbg(dev, "%s: system suspend, state: %d\n", __func__, swrm->state);
+	if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
+		ret = swrm_runtime_suspend(dev);
+		if (!ret) {
+			/*
+			 * Synchronize runtime-pm and system-pm states:
+			 * At this point, we are already suspended. If
+			 * runtime-pm still thinks its active, then
+			 * make sure its status is in sync with HW
+			 * status. The three below calls let the
+			 * runtime-pm know that we are suspended
+			 * already without re-invoking the suspend
+			 * callback
+			 */
+			pm_runtime_disable(dev);
+			pm_runtime_set_suspended(dev);
+			pm_runtime_enable(dev);
+		}
+	}
+	if (ret == -EBUSY) {
+		/*
+		 * There is a possibility that some audio stream is active
+		 * during suspend. We dont want to return suspend failure in
+		 * that case so that display and relevant components can still
+		 * go to suspend.
+		 * If there is some other error, then it should be passed-on
+		 * to system level suspend
+		 */
+		ret = 0;
+	}
+	return ret;
+}
+
+static int swrm_resume(struct device *dev)
+{
+	int ret = 0;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
+
+	dev_dbg(dev, "%s: system resume, state: %d\n", __func__, swrm->state);
+	if (!pm_runtime_enabled(dev) || !pm_runtime_suspend(dev)) {
+		ret = swrm_runtime_resume(dev);
+		if (!ret) {
+			pm_runtime_mark_last_busy(dev);
+			pm_request_autosuspend(dev);
+		}
+	}
+	return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops swrm_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		swrm_suspend,
+		swrm_resume
+	)
+	SET_RUNTIME_PM_OPS(
+		swrm_runtime_suspend,
+		swrm_runtime_resume,
+		NULL
+	)
+};
+
+static const struct of_device_id swrm_dt_match[] = {
+	{
+		.compatible = "qcom,swr-wcd",
+	},
+	{}
+};
+
+static struct platform_driver swr_mstr_driver = {
+	.probe = swrm_probe,
+	.remove = swrm_remove,
+	.driver = {
+		.name = SWR_WCD_NAME,
+		.owner = THIS_MODULE,
+		.pm = &swrm_dev_pm_ops,
+		.of_match_table = swrm_dt_match,
+	},
+};
+
+static int __init swrm_init(void)
+{
+	return platform_driver_register(&swr_mstr_driver);
+}
+subsys_initcall(swrm_init);
+
+static void __exit swrm_exit(void)
+{
+	platform_driver_unregister(&swr_mstr_driver);
+}
+module_exit(swrm_exit);
+
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("WCD SoundWire Controller");
+MODULE_ALIAS("platform:swr-wcd");

+ 106 - 0
drivers/soundwire/swr-wcd-ctrl.h

@@ -0,0 +1,106 @@
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _SWR_WCD_CTRL_H
+#define _SWR_WCD_CTRL_H
+#include <linux/module.h>
+#include <linux/soundwire/swr-wcd.h>
+
+#define SWR_MAX_ROW		0 /* Rows = 48 */
+#define SWR_MAX_COL		7 /* Cols = 16 */
+#define SWR_MIN_COL		0 /* Cols = 2 */
+
+#define SWR_WCD_NAME	"swr-wcd"
+
+#define SWR_MSTR_PORT_LEN	8 /* Number of master ports */
+
+#define SWRM_VERSION_1_0 0x01010000
+#define SWRM_VERSION_1_2 0x01030000
+#define SWRM_VERSION_1_3 0x01040000
+
+enum {
+	SWR_MSTR_PAUSE,
+	SWR_MSTR_RESUME,
+	SWR_MSTR_UP,
+	SWR_MSTR_DOWN,
+};
+
+enum {
+	SWR_IRQ_FREE,
+	SWR_IRQ_REGISTER,
+};
+
+enum {
+	SWR_DAC_PORT,
+	SWR_COMP_PORT,
+	SWR_BOOST_PORT,
+	SWR_VISENSE_PORT,
+};
+
+struct usecase {
+	u8 num_port;
+	u8 num_ch;
+	u32 chrate;
+};
+
+struct port_params {
+	u8 si;
+	u8 off1;
+	u8 off2;
+};
+
+struct swrm_mports {
+	struct list_head list;
+	u8 id;
+};
+
+struct swr_ctrl_platform_data {
+	void *handle; /* holds priv data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq,
+			void *data), void *swr_handle, int type);
+};
+
+struct swr_mstr_ctrl {
+	struct swr_master master;
+	struct device *dev;
+	struct resource *supplies;
+	struct clk *mclk;
+	struct completion reset;
+	struct completion broadcast;
+	struct mutex mlock;
+	struct mutex reslock;
+	u8 rcmd_id;
+	u8 wcmd_id;
+	void *handle; /* SWR Master handle from client for read and writes */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq,
+			void *data), void *swr_handle, int type);
+	int irq;
+	int version;
+	int num_enum_slaves;
+	int slave_status;
+	struct swr_mstr_port *mstr_port;
+	struct list_head mport_list;
+	int state;
+	struct platform_device *pdev;
+	int num_rx_chs;
+	u8 num_cfg_devs;
+};
+
+#endif /* _SWR_WCD_CTRL_H */

+ 204 - 0
drivers/soundwire/swrm_registers.h

@@ -0,0 +1,204 @@
+/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _SWRM_REGISTERS_H
+#define _SWRM_REGISTERS_H
+
+#define SWRM_BASE_ADDRESS				0x00
+
+#define SWRM_COMP_HW_VERSION                     SWRM_BASE_ADDRESS
+#define SWRM_COMP_CFG_ADDR			(SWRM_BASE_ADDRESS+0x00000004)
+#define SWRM_COMP_CFG_RMSK				0x3
+#define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_BMSK		0x2
+#define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_SHFT		0x1
+#define SWRM_COMP_CFG_ENABLE_BMSK			0x1
+#define SWRM_COMP_CFG_ENABLE_SHFT			0x0
+
+#define SWRM_COMP_SW_RESET		(SWRM_BASE_ADDRESS+0x00000008)
+
+#define SWRM_COMP_PARAMS		(SWRM_BASE_ADDRESS+0x100)
+#define SWRM_COMP_PARAMS_DOUT_PORTS_MASK	0x0000001F
+#define SWRM_COMP_PARAMS_DIN_PORTS_MASK		0x000003E0
+#define SWRM_COMP_PARAMS_WR_FIFO_DEPTH		0x00007C00
+#define SWRM_COMP_PARAMS_RD_FIFO_DEPTH		0x000F8000
+#define SWRM_COMP_PARAMS_AUTO_ENUM_SLAVES	0x00F00000
+#define SWRM_COMP_PARAMS_DATA_LANES		0x07000000
+
+
+#define SWRM_INTERRUPT_STATUS		(SWRM_BASE_ADDRESS+0x00000200)
+#define SWRM_INTERRUPT_STATUS_RMSK		0x1FFFD
+
+#define SWRM_INTERRUPT_STATUS_SLAVE_PEND_IRQ			0x1
+#define SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED		0x2
+#define SWRM_INTERRUPT_STATUS_CHANGE_ENUM_SLAVE_STATUS		0x4
+#define SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET			0x8
+#define SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW			0x10
+#define SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW			0x20
+#define SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW		0x40
+#define SWRM_INTERRUPT_STATUS_CMD_ERROR				0x80
+#define SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION		0x100
+#define SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH		0x200
+#define SWRM_INTERRUPT_STATUS_SPECIAL_CMD_ID_FINISHED		0x400
+#define SWRM_INTERRUPT_STATUS_NEW_SLAVE_AUTO_ENUM_FINISHED	0x800
+#define SWRM_INTERRUPT_STATUS_AUTO_ENUM_FAILED			0x1000
+#define SWRM_INTERRUPT_STATUS_AUTO_ENUM_TABLE_IS_FULL		0x2000
+#define SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED		0x4000
+#define SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED			0x8000
+#define SWRM_INTERRUPT_STATUS_ERROR_PORT_TEST			0x10000
+
+#define SWRM_INTERRUPT_MASK_ADDR		(SWRM_BASE_ADDRESS+0x00000204)
+#define SWRM_INTERRUPT_MASK_RMSK		0x1FFFF
+
+#define SWRM_INTERRUPT_MASK_SLAVE_PEND_IRQ_BMSK			0x1
+#define SWRM_INTERRUPT_MASK_SLAVE_PEND_IRQ_SHFT			0x0
+
+#define SWRM_INTERRUPT_MASK_NEW_SLAVE_ATTACHED_BMSK		0x2
+#define SWRM_INTERRUPT_MASK_NEW_SLAVE_ATTACHED_SHFT		0x1
+
+#define SWRM_INTERRUPT_MASK_CHANGE_ENUM_SLAVE_STATUS_BMSK	0x4
+#define SWRM_INTERRUPT_MASK_CHANGE_ENUM_SLAVE_STATUS_SHFT	0x2
+
+#define SWRM_INTERRUPT_MASK_MASTER_CLASH_DET_BMSK		0x8
+#define SWRM_INTERRUPT_MASK_MASTER_CLASH_DET_SHFT		0x3
+
+#define SWRM_INTERRUPT_MASK_RD_FIFO_OVERFLOW_BMSK		0x10
+#define SWRM_INTERRUPT_MASK_RD_FIFO_OVERFLOW_SHFT		0x4
+
+#define SWRM_INTERRUPT_MASK_RD_FIFO_UNDERFLOW_BMSK		0x20
+#define SWRM_INTERRUPT_MASK_RD_FIFO_UNDERFLOW_SHFT		0x5
+
+#define SWRM_INTERRUPT_MASK_WR_CMD_FIFO_OVERFLOW_BMSK		0x40
+#define SWRM_INTERRUPT_MASK_WR_CMD_FIFO_OVERFLOW_SHFT		0x6
+
+#define SWRM_INTERRUPT_MASK_CMD_ERROR_BMSK			0x80
+#define SWRM_INTERRUPT_MASK_CMD_ERROR_SHFT			0x7
+
+#define SWRM_INTERRUPT_MASK_DOUT_PORT_COLLISION_BMSK		0x100
+#define SWRM_INTERRUPT_MASK_DOUT_PORT_COLLISION_SHFT		0x8
+
+#define SWRM_INTERRUPT_MASK_READ_EN_RD_VALID_MISMATCH_BMSK	0x200
+#define SWRM_INTERRUPT_MASK_READ_EN_RD_VALID_MISMATCH_SHFT	0x9
+
+#define SWRM_INTERRUPT_MASK_SPECIAL_CMD_ID_FINISHED_BMSK	0x400
+#define SWRM_INTERRUPT_MASK_SPECIAL_CMD_ID_FINISHED_SHFT	0xA
+
+#define SWRM_INTERRUPT_MASK_NEW_SLAVE_AUTO_ENUM_FINISHED_BMSK	0x800
+#define SWRM_INTERRUPT_MASK_NEW_SLAVE_AUTO_ENUM_FINISHED_SHFT	0xB
+
+#define SWRM_INTERRUPT_MASK_AUTO_ENUM_FAILED_BMSK		0x1000
+#define SWRM_INTERRUPT_MASK_AUTO_ENUM_FAILED_SHFT		0xC
+
+#define SWRM_INTERRUPT_MASK_AUTO_ENUM_TABLE_IS_FULL_BMSK	0x2000
+#define SWRM_INTERRUPT_MASK_AUTO_ENUM_TABLE_IS_FULL_SHFT	0xD
+
+#define SWRM_INTERRUPT_MASK_BUS_RESET_FINISHED_BMSK		0x4000
+#define SWRM_INTERRUPT_MASK_BUS_RESET_FINISHED_SHFT		0xE
+
+#define SWRM_INTERRUPT_MASK_CLK_STOP_FINISHED_BMSK		0x8000
+#define SWRM_INTERRUPT_MASK_CLK_STOP_FINISHED_SHFT		0xF
+
+#define SWRM_INTERRUPT_MASK_ERROR_PORT_TEST_BMSK		0x10000
+#define SWRM_INTERRUPT_MASK_ERROR_PORT_TEST_SHFT		0x10
+
+#define SWRM_INTERRUPT_MAX					0x11
+
+#define SWRM_INTERRUPT_CLEAR		(SWRM_BASE_ADDRESS+0x00000208)
+
+#define SWRM_CMD_FIFO_WR_CMD		(SWRM_BASE_ADDRESS + 0x00000300)
+#define SWRM_CMD_FIFO_WR_CMD_MASK	0xFFFFFFFF
+#define SWRM_CMD_FIFO_RD_CMD		(SWRM_BASE_ADDRESS + 0x00000304)
+#define SWRM_CMD_FIFO_RD_CMD_MASK	0xFFFFFFF
+#define SWRM_CMD_FIFO_CMD		(SWRM_BASE_ADDRESS + 0x00000308)
+#define SWRM_CMD_FIFO_STATUS		(SWRM_BASE_ADDRESS + 0x0000030C)
+
+#define SWRM_CMD_FIFO_STATUS_WR_CMD_FIFO_CNT_MASK	0x1F00
+#define SWRM_CMD_FIFO_STATUS_RD_CMD_FIFO_CNT_MASK	0x7C00000
+
+#define SWRM_CMD_FIFO_CFG_ADDR			(SWRM_BASE_ADDRESS+0x00000314)
+#define SWRM_CMD_FIFO_CFG_NUM_OF_CMD_RETRY_BMSK		0x7
+#define SWRM_CMD_FIFO_CFG_NUM_OF_CMD_RETRY_SHFT		0x0
+
+#define SWRM_CMD_FIFO_RD_FIFO_ADDR	(SWRM_BASE_ADDRESS + 0x00000318)
+
+#define SWRM_ENUMERATOR_CFG_ADDR		(SWRM_BASE_ADDRESS+0x00000500)
+#define SWRM_ENUMERATOR_CFG_AUTO_ENUM_EN_BMSK		0x1
+#define SWRM_ENUMERATOR_CFG_AUTO_ENUM_EN_SHFT		0x0
+
+#define SWRM_ENUMERATOR_SLAVE_DEV_ID_1(m)   (SWRM_BASE_ADDRESS+0x530+0x8*m)
+#define SWRM_ENUMERATOR_SLAVE_DEV_ID_2(m)   (SWRM_BASE_ADDRESS+0x534+0x8*m)
+
+#define SWRM_MCP_FRAME_CTRL_BANK_ADDR(m)    (SWRM_BASE_ADDRESS+0x101C+0x40*m)
+#define SWRM_MCP_FRAME_CTRL_BANK_RMSK			0x00ff07ff
+#define SWRM_MCP_FRAME_CTRL_BANK_SHFT			0
+#define SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK	0xff0000
+#define SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT	16
+#define SWRM_MCP_FRAME_CTRL_BANK_PHASE_BMSK		0xf800
+#define SWRM_MCP_FRAME_CTRL_BANK_PHASE_SHFT		11
+#define SWRM_MCP_FRAME_CTRL_BANK_CLK_DIV_VALUE_BMSK	0x700
+#define SWRM_MCP_FRAME_CTRL_BANK_CLK_DIV_VALUE_SHFT	8
+#define SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK		0xF8
+#define SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT		3
+#define SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK		0x7
+#define SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT		0
+
+#define SWRM_MCP_BUS_CTRL_ADDR			(SWRM_BASE_ADDRESS+0x00001044)
+#define SWRM_MCP_BUS_CTRL_BUS_RESET_BMSK		0x1
+#define SWRM_MCP_BUS_CTRL_BUS_RESET_SHFT		0x0
+#define SWRM_MCP_BUS_CTRL_CLK_START_BMSK		0x2
+#define SWRM_MCP_BUS_CTRL_CLK_START_SHFT		0x1
+
+#define SWRM_MCP_CFG_ADDR			(SWRM_BASE_ADDRESS+0x00001048)
+#define SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK	0x3E0000
+#define SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_SHFT	0x11
+#define SWRM_MCP_CFG_BUS_CLK_PAUSE_BMSK			0x02
+
+#define SWRM_MCP_STATUS			(SWRM_BASE_ADDRESS+0x104C)
+#define SWRM_MCP_STATUS_BANK_NUM_MASK	0x01
+
+#define SWRM_MCP_SLV_STATUS		(SWRM_BASE_ADDRESS+0x1090)
+#define SWRM_MCP_SLV_STATUS_MASK	0x03
+
+#define SWRM_DP_PORT_CTRL_BANK(n, m)		(SWRM_BASE_ADDRESS + \
+							0x00001124 + \
+							0x100*(n-1) + \
+							0x40*m)
+#define SWRM_DP_PORT_CTRL_BANK_MASK		0xFFFFFFFF
+#define SWRM_DP_PORT_CTRL_EN_CHAN_MASK		0xFF000000
+#define SWRM_DP_PORT_CTRL_EN_CHAN_SHFT		0x18
+#define SWRM_DP_PORT_CTRL_OFFSET2_SHFT		0x10
+#define SWRM_DP_PORT_CTRL_OFFSET1_SHFT		0x08
+#define SWRM_DP_PORT_CTRL_SAMPLE_INTERVAL	0x00
+
+/* Soundwire Slave Register definition */
+
+#define SWRS_BASE_ADDRESS			0x00
+
+#define SWRS_DP_REG_OFFSET(port, bank)		((0x100*port)+(0x10*bank))
+
+#define SWRS_DP_CHANNEL_ENABLE_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x120 + \
+						 SWRS_DP_REG_OFFSET(n, m))
+#define SWRS_DP_SAMPLE_CONTROL_1_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x122 + \
+						 SWRS_DP_REG_OFFSET(n, m))
+#define SWRS_DP_OFFSET_CONTROL_1_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x124 + \
+						 SWRS_DP_REG_OFFSET(n, m))
+#define SWRS_DP_OFFSET_CONTROL_2_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x125 + \
+						 SWRS_DP_REG_OFFSET(n, m))
+#define SWRS_DP_HCONTROL_BANK(n, m)		(SWRS_BASE_ADDRESS + 0x126 + \
+						 SWRS_DP_REG_OFFSET(n, m))
+#define SWRS_DP_BLOCK_CONTROL_3_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x127 + \
+						 SWRS_DP_REG_OFFSET(n, m))
+#define SWRS_SCP_FRAME_CTRL_BANK(m)		(SWRS_BASE_ADDRESS + 0x60 + \
+						 0x10*m)
+#define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m)	(SWRS_BASE_ADDRESS + 0xE0 + \
+						0x10*m)
+
+#endif /* _SWRM_REGISTERS_H */

+ 2 - 0
include/Kbuild

@@ -0,0 +1,2 @@
+# Top-level Makefile calls into asm-$(ARCH)
+# List only non-arch directories below

+ 24 - 0
include/linux/avtimer_kernel.h

@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _AVTIMER_H
+#define _AVTIMER_H
+
+#include <uapi/linux/avtimer.h>
+
+int avcs_core_open(void);
+int avcs_core_disable_power_collapse(int disable);/* true or flase */
+int avcs_core_query_timer(uint64_t *avtimer_tick);
+
+#endif

+ 49 - 0
include/linux/mfd/msm-cdc-pinctrl.h

@@ -0,0 +1,49 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __MFD_CDC_PINCTRL_H_
+#define __MFD_CDC_PINCTRL_H_
+
+#include <linux/types.h>
+#include <linux/of.h>
+
+#if IS_ENABLED(CONFIG_MSM_CDC_PINCTRL)
+extern int msm_cdc_pinctrl_select_sleep_state(struct device_node *np);
+extern int msm_cdc_pinctrl_select_active_state(struct device_node *np);
+extern bool msm_cdc_pinctrl_get_state(struct device_node *np);
+extern int msm_cdc_get_gpio_state(struct device_node *np);
+int msm_cdc_pinctrl_drv_init(void);
+void msm_cdc_pinctrl_drv_exit(void);
+
+#else
+int msm_cdc_pinctrl_select_sleep_state(struct device_node *np)
+{
+	return 0;
+}
+int msm_cdc_pinctrl_select_active_state(struct device_node *np)
+{
+	return 0;
+}
+int msm_cdc_get_gpio_state(struct device_node *np)
+{
+	return 0;
+}
+int msm_cdc_pinctrl_drv_init(void)
+{
+	return 0;
+}
+void msm_cdc_pinctrl_drv_exit(void)
+{
+}
+#endif
+
+#endif

+ 48 - 0
include/linux/mfd/msm-cdc-supply.h

@@ -0,0 +1,48 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __CODEC_POWER_SUPPLY_H__
+#define __CODEC_POWER_SUPPLY_H__
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+
+struct cdc_regulator {
+	const char *name;
+	int min_uV;
+	int max_uV;
+	int optimum_uA;
+	bool ondemand;
+	struct regulator *regulator;
+};
+
+extern int msm_cdc_get_power_supplies(struct device *dev,
+				      struct cdc_regulator **cdc_vreg,
+				      int *total_num_supplies);
+extern int msm_cdc_disable_static_supplies(struct device *dev,
+					struct regulator_bulk_data *supplies,
+					struct cdc_regulator *cdc_vreg,
+					int num_supplies);
+extern int msm_cdc_release_supplies(struct device *dev,
+				    struct regulator_bulk_data *supplies,
+				    struct cdc_regulator *cdc_vreg,
+				    int num_supplies);
+extern int msm_cdc_enable_static_supplies(struct device *dev,
+					  struct regulator_bulk_data *supplies,
+					  struct cdc_regulator *cdc_vreg,
+					  int num_supplies);
+extern int msm_cdc_init_supplies(struct device *dev,
+				 struct regulator_bulk_data **supplies,
+				 struct cdc_regulator *cdc_vreg,
+				 int num_supplies);
+#endif

+ 55 - 0
include/linux/mfd/wcd9335/irq.h

@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __WCD9335_IRQ_H_
+#define __WCD9335_IRQ_H_
+
+enum {
+	/* INTR_REG 0 */
+	WCD9335_IRQ_FLL_LOCK_LOSS = 1,
+	WCD9335_IRQ_HPH_PA_OCPL_FAULT,
+	WCD9335_IRQ_HPH_PA_OCPR_FAULT,
+	WCD9335_IRQ_EAR_PA_OCP_FAULT,
+	WCD9335_IRQ_HPH_PA_CNPL_COMPLETE,
+	WCD9335_IRQ_HPH_PA_CNPR_COMPLETE,
+	WCD9335_IRQ_EAR_PA_CNP_COMPLETE,
+	/* INTR_REG 1 */
+	WCD9335_IRQ_MBHC_SW_DET,
+	WCD9335_IRQ_MBHC_ELECT_INS_REM_DET,
+	WCD9335_IRQ_MBHC_BUTTON_PRESS_DET,
+	WCD9335_IRQ_MBHC_BUTTON_RELEASE_DET,
+	WCD9335_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
+	WCD9335_IRQ_RESERVED_0,
+	WCD9335_IRQ_RESERVED_1,
+	WCD9335_IRQ_RESERVED_2,
+	/* INTR_REG 2 */
+	WCD9335_IRQ_LINE_PA1_CNP_COMPLETE,
+	WCD9335_IRQ_LINE_PA2_CNP_COMPLETE,
+	WCD9335_IRQ_LINE_PA3_CNP_COMPLETE,
+	WCD9335_IRQ_LINE_PA4_CNP_COMPLETE,
+	WCD9335_IRQ_SOUNDWIRE,
+	WCD9335_IRQ_VDD_DIG_RAMP_COMPLETE,
+	WCD9335_IRQ_RCO_ERROR,
+	WCD9335_IRQ_SVA_ERROR,
+	/* INTR_REG 3 */
+	WCD9335_IRQ_MAD_AUDIO,
+	WCD9335_IRQ_MAD_BEACON,
+	WCD9335_IRQ_MAD_ULTRASOUND,
+	WCD9335_IRQ_VBAT_ATTACK,
+	WCD9335_IRQ_VBAT_RESTORE,
+	WCD9335_IRQ_SVA_OUTBOX1,
+	WCD9335_IRQ_SVA_OUTBOX2,
+	WCD9335_NUM_IRQS,
+};
+
+#endif

+ 1348 - 0
include/linux/mfd/wcd9335/registers.h

@@ -0,0 +1,1348 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _WCD9335_REGISTERS_H
+#define _WCD9335_REGISTERS_H
+
+#define WCD9335_PAGE_SIZE 256
+#define WCD9335_NUM_PAGES 256
+
+extern const u8 *wcd9335_reg[WCD9335_NUM_PAGES];
+
+enum {
+	PAGE_0 = 0,
+	PAGE_1,
+	PAGE_2,
+	PAGE_6 = 6,
+	PAGE_10 = 0xA,
+	PAGE_11,
+	PAGE_12,
+	PAGE_13,
+	PAGE_0X80,
+};
+
+/* Page-0 Registers */
+#define WCD9335_PAGE0_PAGE_REGISTER                      0x0000
+#define WCD9335_CODEC_RPM_CLK_BYPASS                     0x0001
+#define WCD9335_CODEC_RPM_CLK_GATE                       0x0002
+#define WCD9335_CODEC_RPM_CLK_MCLK_CFG                   0x0003
+#define WCD9335_CODEC_RPM_RST_CTL                        0x0009
+#define WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL             0x0011
+#define WCD9335_CODEC_RPM_PWR_CPE_DEEPSLP_1              0x0012
+#define WCD9335_CODEC_RPM_PWR_CPE_DEEPSLP_2              0x0013
+#define WCD9335_CODEC_RPM_PWR_CPE_DEEPSLP_3              0x0014
+#define WCD9335_CODEC_RPM_PWR_CPE_IRAM_SHUTDOWN          0x0015
+#define WCD9335_CODEC_RPM_PWR_CPE_DRAM1_SHUTDOWN         0x0016
+#define WCD9335_CODEC_RPM_PWR_CPE_DRAM0_SHUTDOWN_1       0x0017
+#define WCD9335_CODEC_RPM_PWR_CPE_DRAM0_SHUTDOWN_2       0x0018
+#define WCD9335_CODEC_RPM_INT_MASK                       0x001d
+#define WCD9335_CODEC_RPM_INT_STATUS                     0x001e
+#define WCD9335_CODEC_RPM_INT_CLEAR                      0x001f
+#define WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0             0x0021
+#define WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE1             0x0022
+#define WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE2             0x0023
+#define WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE3             0x0024
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_CTL                 0x0025
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_TEST0               0x0026
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_TEST1               0x0027
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT0            0x0029
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT1            0x002a
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT2            0x002b
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT3            0x002c
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT4            0x002d
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT5            0x002e
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT6            0x002f
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT7            0x0030
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT8            0x0031
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT9            0x0032
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT10           0x0033
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT11           0x0034
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT12           0x0035
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT13           0x0036
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT14           0x0037
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT15           0x0038
+#define WCD9335_CHIP_TIER_CTRL_EFUSE_STATUS              0x0039
+#define WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_NONNEGO      0x003a
+#define WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_1            0x003b
+#define WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_2            0x003c
+#define WCD9335_CHIP_TIER_CTRL_I2C_SLAVE_ID_3            0x003d
+#define WCD9335_CHIP_TIER_CTRL_ANA_WAIT_STATE_CTL        0x003e
+#define WCD9335_CHIP_TIER_CTRL_I2C_ACTIVE                0x003f
+#define WCD9335_CHIP_TIER_CTRL_PROC1_MON_CTL             0x0041
+#define WCD9335_CHIP_TIER_CTRL_PROC1_MON_STATUS          0x0042
+#define WCD9335_CHIP_TIER_CTRL_PROC1_MON_CNT_MSB         0x0043
+#define WCD9335_CHIP_TIER_CTRL_PROC1_MON_CNT_LSB         0x0044
+#define WCD9335_CHIP_TIER_CTRL_PROC2_MON_CTL             0x0045
+#define WCD9335_CHIP_TIER_CTRL_PROC2_MON_STATUS          0x0046
+#define WCD9335_CHIP_TIER_CTRL_PROC2_MON_CNT_MSB         0x0047
+#define WCD9335_CHIP_TIER_CTRL_PROC2_MON_CNT_LSB         0x0048
+#define WCD9335_CHIP_TIER_CTRL_PROC3_MON_CTL             0x0049
+#define WCD9335_CHIP_TIER_CTRL_PROC3_MON_STATUS          0x004a
+#define WCD9335_CHIP_TIER_CTRL_PROC3_MON_CNT_MSB         0x004b
+#define WCD9335_CHIP_TIER_CTRL_PROC3_MON_CNT_LSB         0x004c
+#define WCD9335_DATA_HUB_DATA_HUB_RX_I2S_CTL             0x0051
+#define WCD9335_DATA_HUB_DATA_HUB_TX_I2S_CTL             0x0052
+#define WCD9335_DATA_HUB_DATA_HUB_I2S_CLK                0x0053
+#define WCD9335_DATA_HUB_DATA_HUB_RX0_INP_CFG            0x0054
+#define WCD9335_DATA_HUB_DATA_HUB_RX1_INP_CFG            0x0055
+#define WCD9335_DATA_HUB_DATA_HUB_RX2_INP_CFG            0x0056
+#define WCD9335_DATA_HUB_DATA_HUB_RX3_INP_CFG            0x0057
+#define WCD9335_DATA_HUB_DATA_HUB_RX4_INP_CFG            0x0058
+#define WCD9335_DATA_HUB_DATA_HUB_RX5_INP_CFG            0x0059
+#define WCD9335_DATA_HUB_DATA_HUB_RX6_INP_CFG            0x005a
+#define WCD9335_DATA_HUB_DATA_HUB_RX7_INP_CFG            0x005b
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX0_INP_CFG         0x0061
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX1_INP_CFG         0x0062
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX2_INP_CFG         0x0063
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX3_INP_CFG         0x0064
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX4_INP_CFG         0x0065
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX5_INP_CFG         0x0066
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX6_INP_CFG         0x0067
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX7_INP_CFG         0x0068
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX8_INP_CFG         0x0069
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX9_INP_CFG         0x006a
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX10_INP_CFG        0x006b
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX11_INP_CFG        0x006c
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX13_INP_CFG        0x006e
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX14_INP_CFG        0x006f
+#define WCD9335_DATA_HUB_DATA_HUB_SB_TX15_INP_CFG        0x0070
+#define WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD0_L_CFG       0x0071
+#define WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD0_R_CFG       0x0072
+#define WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD1_L_CFG       0x0073
+#define WCD9335_DATA_HUB_DATA_HUB_TX_I2S_SD1_R_CFG       0x0074
+#define WCD9335_DATA_HUB_NATIVE_FIFO_SYNC                0x0075
+#define WCD9335_DATA_HUB_NATIVE_FIFO_STATUS              0x007D
+#define WCD9335_INTR_CFG                                 0x0081
+#define WCD9335_INTR_CLR_COMMIT                          0x0082
+#define WCD9335_INTR_PIN1_MASK0                          0x0089
+#define WCD9335_INTR_PIN1_MASK1                          0x008a
+#define WCD9335_INTR_PIN1_MASK2                          0x008b
+#define WCD9335_INTR_PIN1_MASK3                          0x008c
+#define WCD9335_INTR_PIN1_STATUS0                        0x0091
+#define WCD9335_INTR_PIN1_STATUS1                        0x0092
+#define WCD9335_INTR_PIN1_STATUS2                        0x0093
+#define WCD9335_INTR_PIN1_STATUS3                        0x0094
+#define WCD9335_INTR_PIN1_CLEAR0                         0x0099
+#define WCD9335_INTR_PIN1_CLEAR1                         0x009a
+#define WCD9335_INTR_PIN1_CLEAR2                         0x009b
+#define WCD9335_INTR_PIN1_CLEAR3                         0x009c
+#define WCD9335_INTR_PIN2_MASK0                          0x00a1
+#define WCD9335_INTR_PIN2_MASK1                          0x00a2
+#define WCD9335_INTR_PIN2_MASK2                          0x00a3
+#define WCD9335_INTR_PIN2_MASK3                          0x00a4
+#define WCD9335_INTR_PIN2_STATUS0                        0x00a9
+#define WCD9335_INTR_PIN2_STATUS1                        0x00aa
+#define WCD9335_INTR_PIN2_STATUS2                        0x00ab
+#define WCD9335_INTR_PIN2_STATUS3                        0x00ac
+#define WCD9335_INTR_PIN2_CLEAR0                         0x00b1
+#define WCD9335_INTR_PIN2_CLEAR1                         0x00b2
+#define WCD9335_INTR_PIN2_CLEAR2                         0x00b3
+#define WCD9335_INTR_PIN2_CLEAR3                         0x00b4
+#define WCD9335_INTR_LEVEL0                              0x00e1
+#define WCD9335_INTR_LEVEL1                              0x00e2
+#define WCD9335_INTR_LEVEL2                              0x00e3
+#define WCD9335_INTR_LEVEL3                              0x00e4
+#define WCD9335_INTR_BYPASS0                             0x00e9
+#define WCD9335_INTR_BYPASS1                             0x00ea
+#define WCD9335_INTR_BYPASS2                             0x00eb
+#define WCD9335_INTR_BYPASS3                             0x00ec
+#define WCD9335_INTR_SET0                                0x00f1
+#define WCD9335_INTR_SET1                                0x00f2
+#define WCD9335_INTR_SET2                                0x00f3
+#define WCD9335_INTR_SET3                                0x00f4
+
+/* Page-1 Registers */
+#define WCD9335_PAGE1_PAGE_REGISTER                      0x0100
+#define WCD9335_CPE_FLL_USER_CTL_0                       0x0101
+#define WCD9335_CPE_FLL_USER_CTL_1                       0x0102
+#define WCD9335_CPE_FLL_USER_CTL_2                       0x0103
+#define WCD9335_CPE_FLL_USER_CTL_3                       0x0104
+#define WCD9335_CPE_FLL_USER_CTL_4                       0x0105
+#define WCD9335_CPE_FLL_USER_CTL_5                       0x0106
+#define WCD9335_CPE_FLL_USER_CTL_6                       0x0107
+#define WCD9335_CPE_FLL_USER_CTL_7                       0x0108
+#define WCD9335_CPE_FLL_USER_CTL_8                       0x0109
+#define WCD9335_CPE_FLL_USER_CTL_9                       0x010a
+#define WCD9335_CPE_FLL_L_VAL_CTL_0                      0x010b
+#define WCD9335_CPE_FLL_L_VAL_CTL_1                      0x010c
+#define WCD9335_CPE_FLL_DSM_FRAC_CTL_0                   0x010d
+#define WCD9335_CPE_FLL_DSM_FRAC_CTL_1                   0x010e
+#define WCD9335_CPE_FLL_CONFIG_CTL_0                     0x010f
+#define WCD9335_CPE_FLL_CONFIG_CTL_1                     0x0110
+#define WCD9335_CPE_FLL_CONFIG_CTL_2                     0x0111
+#define WCD9335_CPE_FLL_CONFIG_CTL_3                     0x0112
+#define WCD9335_CPE_FLL_CONFIG_CTL_4                     0x0113
+#define WCD9335_CPE_FLL_TEST_CTL_0                       0x0114
+#define WCD9335_CPE_FLL_TEST_CTL_1                       0x0115
+#define WCD9335_CPE_FLL_TEST_CTL_2                       0x0116
+#define WCD9335_CPE_FLL_TEST_CTL_3                       0x0117
+#define WCD9335_CPE_FLL_TEST_CTL_4                       0x0118
+#define WCD9335_CPE_FLL_TEST_CTL_5                       0x0119
+#define WCD9335_CPE_FLL_TEST_CTL_6                       0x011a
+#define WCD9335_CPE_FLL_TEST_CTL_7                       0x011b
+#define WCD9335_CPE_FLL_FREQ_CTL_0                       0x011c
+#define WCD9335_CPE_FLL_FREQ_CTL_1                       0x011d
+#define WCD9335_CPE_FLL_FREQ_CTL_2                       0x011e
+#define WCD9335_CPE_FLL_FREQ_CTL_3                       0x011f
+#define WCD9335_CPE_FLL_SSC_CTL_0                        0x0120
+#define WCD9335_CPE_FLL_SSC_CTL_1                        0x0121
+#define WCD9335_CPE_FLL_SSC_CTL_2                        0x0122
+#define WCD9335_CPE_FLL_SSC_CTL_3                        0x0123
+#define WCD9335_CPE_FLL_FLL_MODE                         0x0124
+#define WCD9335_CPE_FLL_STATUS_0                         0x0125
+#define WCD9335_CPE_FLL_STATUS_1                         0x0126
+#define WCD9335_CPE_FLL_STATUS_2                         0x0127
+#define WCD9335_CPE_FLL_STATUS_3                         0x0128
+#define WCD9335_I2S_FLL_USER_CTL_0                       0x0141
+#define WCD9335_I2S_FLL_USER_CTL_1                       0x0142
+#define WCD9335_I2S_FLL_USER_CTL_2                       0x0143
+#define WCD9335_I2S_FLL_USER_CTL_3                       0x0144
+#define WCD9335_I2S_FLL_USER_CTL_4                       0x0145
+#define WCD9335_I2S_FLL_USER_CTL_5                       0x0146
+#define WCD9335_I2S_FLL_USER_CTL_6                       0x0147
+#define WCD9335_I2S_FLL_USER_CTL_7                       0x0148
+#define WCD9335_I2S_FLL_USER_CTL_8                       0x0149
+#define WCD9335_I2S_FLL_USER_CTL_9                       0x014a
+#define WCD9335_I2S_FLL_L_VAL_CTL_0                      0x014b
+#define WCD9335_I2S_FLL_L_VAL_CTL_1                      0x014c
+#define WCD9335_I2S_FLL_DSM_FRAC_CTL_0                   0x014d
+#define WCD9335_I2S_FLL_DSM_FRAC_CTL_1                   0x014e
+#define WCD9335_I2S_FLL_CONFIG_CTL_0                     0x014f
+#define WCD9335_I2S_FLL_CONFIG_CTL_1                     0x0150
+#define WCD9335_I2S_FLL_CONFIG_CTL_2                     0x0151
+#define WCD9335_I2S_FLL_CONFIG_CTL_3                     0x0152
+#define WCD9335_I2S_FLL_CONFIG_CTL_4                     0x0153
+#define WCD9335_I2S_FLL_TEST_CTL_0                       0x0154
+#define WCD9335_I2S_FLL_TEST_CTL_1                       0x0155
+#define WCD9335_I2S_FLL_TEST_CTL_2                       0x0156
+#define WCD9335_I2S_FLL_TEST_CTL_3                       0x0157
+#define WCD9335_I2S_FLL_TEST_CTL_4                       0x0158
+#define WCD9335_I2S_FLL_TEST_CTL_5                       0x0159
+#define WCD9335_I2S_FLL_TEST_CTL_6                       0x015a
+#define WCD9335_I2S_FLL_TEST_CTL_7                       0x015b
+#define WCD9335_I2S_FLL_FREQ_CTL_0                       0x015c
+#define WCD9335_I2S_FLL_FREQ_CTL_1                       0x015d
+#define WCD9335_I2S_FLL_FREQ_CTL_2                       0x015e
+#define WCD9335_I2S_FLL_FREQ_CTL_3                       0x015f
+#define WCD9335_I2S_FLL_SSC_CTL_0                        0x0160
+#define WCD9335_I2S_FLL_SSC_CTL_1                        0x0161
+#define WCD9335_I2S_FLL_SSC_CTL_2                        0x0162
+#define WCD9335_I2S_FLL_SSC_CTL_3                        0x0163
+#define WCD9335_I2S_FLL_FLL_MODE                         0x0164
+#define WCD9335_I2S_FLL_STATUS_0                         0x0165
+#define WCD9335_I2S_FLL_STATUS_1                         0x0166
+#define WCD9335_I2S_FLL_STATUS_2                         0x0167
+#define WCD9335_I2S_FLL_STATUS_3                         0x0168
+#define WCD9335_SB_FLL_USER_CTL_0                        0x0181
+#define WCD9335_SB_FLL_USER_CTL_1                        0x0182
+#define WCD9335_SB_FLL_USER_CTL_2                        0x0183
+#define WCD9335_SB_FLL_USER_CTL_3                        0x0184
+#define WCD9335_SB_FLL_USER_CTL_4                        0x0185
+#define WCD9335_SB_FLL_USER_CTL_5                        0x0186
+#define WCD9335_SB_FLL_USER_CTL_6                        0x0187
+#define WCD9335_SB_FLL_USER_CTL_7                        0x0188
+#define WCD9335_SB_FLL_USER_CTL_8                        0x0189
+#define WCD9335_SB_FLL_USER_CTL_9                        0x018a
+#define WCD9335_SB_FLL_L_VAL_CTL_0                       0x018b
+#define WCD9335_SB_FLL_L_VAL_CTL_1                       0x018c
+#define WCD9335_SB_FLL_DSM_FRAC_CTL_0                    0x018d
+#define WCD9335_SB_FLL_DSM_FRAC_CTL_1                    0x018e
+#define WCD9335_SB_FLL_CONFIG_CTL_0                      0x018f
+#define WCD9335_SB_FLL_CONFIG_CTL_1                      0x0190
+#define WCD9335_SB_FLL_CONFIG_CTL_2                      0x0191
+#define WCD9335_SB_FLL_CONFIG_CTL_3                      0x0192
+#define WCD9335_SB_FLL_CONFIG_CTL_4                      0x0193
+#define WCD9335_SB_FLL_TEST_CTL_0                        0x0194
+#define WCD9335_SB_FLL_TEST_CTL_1                        0x0195
+#define WCD9335_SB_FLL_TEST_CTL_2                        0x0196
+#define WCD9335_SB_FLL_TEST_CTL_3                        0x0197
+#define WCD9335_SB_FLL_TEST_CTL_4                        0x0198
+#define WCD9335_SB_FLL_TEST_CTL_5                        0x0199
+#define WCD9335_SB_FLL_TEST_CTL_6                        0x019a
+#define WCD9335_SB_FLL_TEST_CTL_7                        0x019b
+#define WCD9335_SB_FLL_FREQ_CTL_0                        0x019c
+#define WCD9335_SB_FLL_FREQ_CTL_1                        0x019d
+#define WCD9335_SB_FLL_FREQ_CTL_2                        0x019e
+#define WCD9335_SB_FLL_FREQ_CTL_3                        0x019f
+#define WCD9335_SB_FLL_SSC_CTL_0                         0x01a0
+#define WCD9335_SB_FLL_SSC_CTL_1                         0x01a1
+#define WCD9335_SB_FLL_SSC_CTL_2                         0x01a2
+#define WCD9335_SB_FLL_SSC_CTL_3                         0x01a3
+#define WCD9335_SB_FLL_FLL_MODE                          0x01a4
+#define WCD9335_SB_FLL_STATUS_0                          0x01a5
+#define WCD9335_SB_FLL_STATUS_1                          0x01a6
+#define WCD9335_SB_FLL_STATUS_2                          0x01a7
+#define WCD9335_SB_FLL_STATUS_3                          0x01a8
+
+/* Page-2 Registers */
+#define WCD9335_PAGE2_PAGE_REGISTER                      0x0200
+#define WCD9335_CPE_SS_MEM_PTR_0                         0x0201
+#define WCD9335_CPE_SS_MEM_PTR_1                         0x0202
+#define WCD9335_CPE_SS_MEM_PTR_2                         0x0203
+#define WCD9335_CPE_SS_MEM_CTRL                          0x0205
+#define WCD9335_CPE_SS_MEM_BANK_0                        0x0206
+#define WCD9335_CPE_SS_MEM_BANK_1                        0x0207
+#define WCD9335_CPE_SS_MEM_BANK_2                        0x0208
+#define WCD9335_CPE_SS_MEM_BANK_3                        0x0209
+#define WCD9335_CPE_SS_MEM_BANK_4                        0x020a
+#define WCD9335_CPE_SS_MEM_BANK_5                        0x020b
+#define WCD9335_CPE_SS_MEM_BANK_6                        0x020c
+#define WCD9335_CPE_SS_MEM_BANK_7                        0x020d
+#define WCD9335_CPE_SS_MEM_BANK_8                        0x020e
+#define WCD9335_CPE_SS_MEM_BANK_9                        0x020f
+#define WCD9335_CPE_SS_MEM_BANK_10                       0x0210
+#define WCD9335_CPE_SS_MEM_BANK_11                       0x0211
+#define WCD9335_CPE_SS_MEM_BANK_12                       0x0212
+#define WCD9335_CPE_SS_MEM_BANK_13                       0x0213
+#define WCD9335_CPE_SS_MEM_BANK_14                       0x0214
+#define WCD9335_CPE_SS_MEM_BANK_15                       0x0215
+#define WCD9335_CPE_SS_INBOX1_TRG                        0x0216
+#define WCD9335_CPE_SS_INBOX2_TRG                        0x0217
+#define WCD9335_CPE_SS_INBOX1_0                          0x0218
+#define WCD9335_CPE_SS_INBOX1_1                          0x0219
+#define WCD9335_CPE_SS_INBOX1_2                          0x021a
+#define WCD9335_CPE_SS_INBOX1_3                          0x021b
+#define WCD9335_CPE_SS_INBOX1_4                          0x021c
+#define WCD9335_CPE_SS_INBOX1_5                          0x021d
+#define WCD9335_CPE_SS_INBOX1_6                          0x021e
+#define WCD9335_CPE_SS_INBOX1_7                          0x021f
+#define WCD9335_CPE_SS_INBOX1_8                          0x0220
+#define WCD9335_CPE_SS_INBOX1_9                          0x0221
+#define WCD9335_CPE_SS_INBOX1_10                         0x0222
+#define WCD9335_CPE_SS_INBOX1_11                         0x0223
+#define WCD9335_CPE_SS_INBOX1_12                         0x0224
+#define WCD9335_CPE_SS_INBOX1_13                         0x0225
+#define WCD9335_CPE_SS_INBOX1_14                         0x0226
+#define WCD9335_CPE_SS_INBOX1_15                         0x0227
+#define WCD9335_CPE_SS_OUTBOX1_0                         0x0228
+#define WCD9335_CPE_SS_OUTBOX1_1                         0x0229
+#define WCD9335_CPE_SS_OUTBOX1_2                         0x022a
+#define WCD9335_CPE_SS_OUTBOX1_3                         0x022b
+#define WCD9335_CPE_SS_OUTBOX1_4                         0x022c
+#define WCD9335_CPE_SS_OUTBOX1_5                         0x022d
+#define WCD9335_CPE_SS_OUTBOX1_6                         0x022e
+#define WCD9335_CPE_SS_OUTBOX1_7                         0x022f
+#define WCD9335_CPE_SS_OUTBOX1_8                         0x0230
+#define WCD9335_CPE_SS_OUTBOX1_9                         0x0231
+#define WCD9335_CPE_SS_OUTBOX1_10                        0x0232
+#define WCD9335_CPE_SS_OUTBOX1_11                        0x0233
+#define WCD9335_CPE_SS_OUTBOX1_12                        0x0234
+#define WCD9335_CPE_SS_OUTBOX1_13                        0x0235
+#define WCD9335_CPE_SS_OUTBOX1_14                        0x0236
+#define WCD9335_CPE_SS_OUTBOX1_15                        0x0237
+#define WCD9335_CPE_SS_INBOX2_0                          0x0238
+#define WCD9335_CPE_SS_INBOX2_1                          0x0239
+#define WCD9335_CPE_SS_INBOX2_2                          0x023a
+#define WCD9335_CPE_SS_INBOX2_3                          0x023b
+#define WCD9335_CPE_SS_INBOX2_4                          0x023c
+#define WCD9335_CPE_SS_INBOX2_5                          0x023d
+#define WCD9335_CPE_SS_INBOX2_6                          0x023e
+#define WCD9335_CPE_SS_INBOX2_7                          0x023f
+#define WCD9335_CPE_SS_INBOX2_8                          0x0240
+#define WCD9335_CPE_SS_INBOX2_9                          0x0241
+#define WCD9335_CPE_SS_INBOX2_10                         0x0242
+#define WCD9335_CPE_SS_INBOX2_11                         0x0243
+#define WCD9335_CPE_SS_INBOX2_12                         0x0244
+#define WCD9335_CPE_SS_INBOX2_13                         0x0245
+#define WCD9335_CPE_SS_INBOX2_14                         0x0246
+#define WCD9335_CPE_SS_INBOX2_15                         0x0247
+#define WCD9335_CPE_SS_OUTBOX2_0                         0x0248
+#define WCD9335_CPE_SS_OUTBOX2_1                         0x0249
+#define WCD9335_CPE_SS_OUTBOX2_2                         0x024a
+#define WCD9335_CPE_SS_OUTBOX2_3                         0x024b
+#define WCD9335_CPE_SS_OUTBOX2_4                         0x024c
+#define WCD9335_CPE_SS_OUTBOX2_5                         0x024d
+#define WCD9335_CPE_SS_OUTBOX2_6                         0x024e
+#define WCD9335_CPE_SS_OUTBOX2_7                         0x024f
+#define WCD9335_CPE_SS_OUTBOX2_8                         0x0250
+#define WCD9335_CPE_SS_OUTBOX2_9                         0x0251
+#define WCD9335_CPE_SS_OUTBOX2_10                        0x0252
+#define WCD9335_CPE_SS_OUTBOX2_11                        0x0253
+#define WCD9335_CPE_SS_OUTBOX2_12                        0x0254
+#define WCD9335_CPE_SS_OUTBOX2_13                        0x0255
+#define WCD9335_CPE_SS_OUTBOX2_14                        0x0256
+#define WCD9335_CPE_SS_OUTBOX2_15                        0x0257
+#define WCD9335_CPE_SS_OUTBOX1_ACK                       0x0258
+#define WCD9335_CPE_SS_OUTBOX2_ACK                       0x0259
+#define WCD9335_CPE_SS_EC_BUF_INT_PERIOD                 0x025a
+#define WCD9335_CPE_SS_US_BUF_INT_PERIOD                 0x025b
+#define WCD9335_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD         0x025c
+#define WCD9335_CPE_SS_CFG                               0x025d
+#define WCD9335_CPE_SS_US_EC_MUX_CFG                     0x025e
+#define WCD9335_CPE_SS_MAD_CTL                           0x025f
+#define WCD9335_CPE_SS_CPAR_CTL                          0x0260
+#define WCD9335_CPE_SS_TX_PP_BUF_INT_PERIOD              0x0261
+#define WCD9335_CPE_SS_TX_PP_CFG                         0x0262
+#define WCD9335_CPE_SS_DMIC0_CTL                         0x0263
+#define WCD9335_CPE_SS_DMIC1_CTL                         0x0264
+#define WCD9335_CPE_SS_DMIC2_CTL                         0x0265
+#define WCD9335_CPE_SS_DMIC_CFG                          0x0266
+#define WCD9335_CPE_SS_SVA_CFG                           0x0267
+#define WCD9335_CPE_SS_CPAR_CFG                          0x0271
+#define WCD9335_CPE_SS_WDOG_CFG                          0x0272
+#define WCD9335_CPE_SS_BACKUP_INT                        0x0273
+#define WCD9335_CPE_SS_STATUS                            0x0274
+#define WCD9335_CPE_SS_CPE_OCD_CFG                       0x0275
+#define WCD9335_CPE_SS_SS_ERROR_INT_MASK                 0x0276
+#define WCD9335_CPE_SS_SS_ERROR_INT_STATUS               0x0277
+#define WCD9335_CPE_SS_SS_ERROR_INT_CLEAR                0x0278
+#define WCD9335_SOC_MAD_MAIN_CTL_1                       0x0281
+#define WCD9335_SOC_MAD_MAIN_CTL_2                       0x0282
+#define WCD9335_SOC_MAD_AUDIO_CTL_1                      0x0283
+#define WCD9335_SOC_MAD_AUDIO_CTL_2                      0x0284
+#define WCD9335_SOC_MAD_AUDIO_CTL_3                      0x0285
+#define WCD9335_SOC_MAD_AUDIO_CTL_4                      0x0286
+#define WCD9335_SOC_MAD_AUDIO_CTL_5                      0x0287
+#define WCD9335_SOC_MAD_AUDIO_CTL_6                      0x0288
+#define WCD9335_SOC_MAD_AUDIO_CTL_7                      0x0289
+#define WCD9335_SOC_MAD_AUDIO_CTL_8                      0x028a
+#define WCD9335_SOC_MAD_AUDIO_IIR_CTL_PTR                0x028b
+#define WCD9335_SOC_MAD_AUDIO_IIR_CTL_VAL                0x028c
+#define WCD9335_SOC_MAD_ULTR_CTL_1                       0x028d
+#define WCD9335_SOC_MAD_ULTR_CTL_2                       0x028e
+#define WCD9335_SOC_MAD_ULTR_CTL_3                       0x028f
+#define WCD9335_SOC_MAD_ULTR_CTL_4                       0x0290
+#define WCD9335_SOC_MAD_ULTR_CTL_5                       0x0291
+#define WCD9335_SOC_MAD_ULTR_CTL_6                       0x0292
+#define WCD9335_SOC_MAD_ULTR_CTL_7                       0x0293
+#define WCD9335_SOC_MAD_BEACON_CTL_1                     0x0294
+#define WCD9335_SOC_MAD_BEACON_CTL_2                     0x0295
+#define WCD9335_SOC_MAD_BEACON_CTL_3                     0x0296
+#define WCD9335_SOC_MAD_BEACON_CTL_4                     0x0297
+#define WCD9335_SOC_MAD_BEACON_CTL_5                     0x0298
+#define WCD9335_SOC_MAD_BEACON_CTL_6                     0x0299
+#define WCD9335_SOC_MAD_BEACON_CTL_7                     0x029a
+#define WCD9335_SOC_MAD_BEACON_CTL_8                     0x029b
+#define WCD9335_SOC_MAD_BEACON_IIR_CTL_PTR               0x029c
+#define WCD9335_SOC_MAD_BEACON_IIR_CTL_VAL               0x029d
+#define WCD9335_SOC_MAD_INP_SEL                          0x029e
+
+/* Page-6 Registers */
+#define WCD9335_PAGE6_PAGE_REGISTER                      0x0600
+#define WCD9335_ANA_BIAS                                 0x0601
+#define WCD9335_ANA_CLK_TOP                              0x0602
+#define WCD9335_ANA_RCO                                  0x0603
+#define WCD9335_ANA_BUCK_VOUT_A                          0x0604
+#define WCD9335_ANA_BUCK_VOUT_D                          0x0605
+#define WCD9335_ANA_BUCK_CTL                             0x0606
+#define WCD9335_ANA_BUCK_STATUS                          0x0607
+#define WCD9335_ANA_RX_SUPPLIES                          0x0608
+#define WCD9335_ANA_HPH                                  0x0609
+#define WCD9335_ANA_EAR                                  0x060a
+#define WCD9335_ANA_LO_1_2                               0x060b
+#define WCD9335_ANA_LO_3_4                               0x060c
+#define WCD9335_ANA_MAD_SETUP                            0x060d
+#define WCD9335_ANA_AMIC1                                0x060e
+#define WCD9335_ANA_AMIC2                                0x060f
+#define WCD9335_ANA_AMIC3                                0x0610
+#define WCD9335_ANA_AMIC4                                0x0611
+#define WCD9335_ANA_AMIC5                                0x0612
+#define WCD9335_ANA_AMIC6                                0x0613
+#define WCD9335_ANA_MBHC_MECH                            0x0614
+#define WCD9335_ANA_MBHC_ELECT                           0x0615
+#define WCD9335_ANA_MBHC_ZDET                            0x0616
+#define WCD9335_ANA_MBHC_RESULT_1                        0x0617
+#define WCD9335_ANA_MBHC_RESULT_2                        0x0618
+#define WCD9335_ANA_MBHC_RESULT_3                        0x0619
+#define WCD9335_ANA_MBHC_BTN0                            0x061a
+#define WCD9335_ANA_MBHC_BTN1                            0x061b
+#define WCD9335_ANA_MBHC_BTN2                            0x061c
+#define WCD9335_ANA_MBHC_BTN3                            0x061d
+#define WCD9335_ANA_MBHC_BTN4                            0x061e
+#define WCD9335_ANA_MBHC_BTN5                            0x061f
+#define WCD9335_ANA_MBHC_BTN6                            0x0620
+#define WCD9335_ANA_MBHC_BTN7                            0x0621
+#define WCD9335_ANA_MICB1                                0x0622
+#define WCD9335_ANA_MICB2                                0x0623
+#define WCD9335_ANA_MICB2_RAMP                           0x0624
+#define WCD9335_ANA_MICB3                                0x0625
+#define WCD9335_ANA_MICB4                                0x0626
+#define WCD9335_ANA_VBADC                                0x0627
+#define WCD9335_BIAS_CTL                                 0x0628
+#define WCD9335_BIAS_VBG_FINE_ADJ                        0x0629
+#define WCD9335_CLOCK_TEST_CTL                           0x062d
+#define WCD9335_RCO_CTRL_1                               0x062e
+#define WCD9335_RCO_CTRL_2                               0x062f
+#define WCD9335_RCO_CAL                                  0x0630
+#define WCD9335_RCO_CAL_1                                0x0631
+#define WCD9335_RCO_CAL_2                                0x0632
+#define WCD9335_RCO_TEST_CTRL                            0x0633
+#define WCD9335_RCO_CAL_OUT_1                            0x0634
+#define WCD9335_RCO_CAL_OUT_2                            0x0635
+#define WCD9335_RCO_CAL_OUT_3                            0x0636
+#define WCD9335_RCO_CAL_OUT_4                            0x0637
+#define WCD9335_RCO_CAL_OUT_5                            0x0638
+#define WCD9335_SIDO_SIDO_MODE_1                         0x063a
+#define WCD9335_SIDO_SIDO_MODE_2                         0x063b
+#define WCD9335_SIDO_SIDO_MODE_3                         0x063c
+#define WCD9335_SIDO_SIDO_MODE_4                         0x063d
+#define WCD9335_SIDO_SIDO_VCL_1                          0x063e
+#define WCD9335_SIDO_SIDO_VCL_2                          0x063f
+#define WCD9335_SIDO_SIDO_VCL_3                          0x0640
+#define WCD9335_SIDO_SIDO_CCL_1                          0x0641
+#define WCD9335_SIDO_SIDO_CCL_2                          0x0642
+#define WCD9335_SIDO_SIDO_CCL_3                          0x0643
+#define WCD9335_SIDO_SIDO_CCL_4                          0x0644
+#define WCD9335_SIDO_SIDO_CCL_5                          0x0645
+#define WCD9335_SIDO_SIDO_CCL_6                          0x0646
+#define WCD9335_SIDO_SIDO_CCL_7                          0x0647
+#define WCD9335_SIDO_SIDO_CCL_8                          0x0648
+#define WCD9335_SIDO_SIDO_CCL_9                          0x0649
+#define WCD9335_SIDO_SIDO_CCL_10                         0x064a
+#define WCD9335_SIDO_SIDO_FILTER_1                       0x064b
+#define WCD9335_SIDO_SIDO_FILTER_2                       0x064c
+#define WCD9335_SIDO_SIDO_DRIVER_1                       0x064d
+#define WCD9335_SIDO_SIDO_DRIVER_2                       0x064e
+#define WCD9335_SIDO_SIDO_DRIVER_3                       0x064f
+#define WCD9335_SIDO_SIDO_CAL_CODE_EXT_1                 0x0650
+#define WCD9335_SIDO_SIDO_CAL_CODE_EXT_2                 0x0651
+#define WCD9335_SIDO_SIDO_CAL_CODE_OUT_1                 0x0652
+#define WCD9335_SIDO_SIDO_CAL_CODE_OUT_2                 0x0653
+#define WCD9335_SIDO_SIDO_TEST_1                         0x0654
+#define WCD9335_SIDO_SIDO_TEST_2                         0x0655
+#define WCD9335_MBHC_CTL_1                               0x0656
+#define WCD9335_MBHC_CTL_2                               0x0657
+#define WCD9335_MBHC_PLUG_DETECT_CTL                     0x0658
+#define WCD9335_MBHC_ZDET_ANA_CTL                        0x0659
+#define WCD9335_MBHC_ZDET_RAMP_CTL                       0x065a
+#define WCD9335_MBHC_FSM_DEBUG                           0x065b /* v1.x */
+#define WCD9335_MBHC_FSM_STATUS                          0x065b /* v2.0 */
+#define WCD9335_MBHC_TEST_CTL                            0x065c
+#define WCD9335_VBADC_SUBBLOCK_EN                        0x065d
+#define WCD9335_VBADC_IBIAS_FE                           0x065e
+#define WCD9335_VBADC_BIAS_ADC                           0x065f
+#define WCD9335_VBADC_FE_CTRL                            0x0660
+#define WCD9335_VBADC_ADC_REF                            0x0661
+#define WCD9335_VBADC_ADC_IO                             0x0662
+#define WCD9335_VBADC_ADC_SAR                            0x0663
+#define WCD9335_VBADC_DEBUG                              0x0664
+#define WCD9335_VBADC_ADC_DOUTMSB                        0x0665
+#define WCD9335_VBADC_ADC_DOUTLSB                        0x0666
+#define WCD9335_LDOH_MODE                                0x0667
+#define WCD9335_LDOH_BIAS                                0x0668
+#define WCD9335_LDOH_STB_LOADS                           0x0669
+#define WCD9335_LDOH_SLOWRAMP                            0x066a
+#define WCD9335_MICB1_TEST_CTL_1                         0x066b
+#define WCD9335_MICB1_TEST_CTL_2                         0x066c
+#define WCD9335_MICB1_TEST_CTL_3                         0x066d
+#define WCD9335_MICB2_TEST_CTL_1                         0x066e
+#define WCD9335_MICB2_TEST_CTL_2                         0x066f
+#define WCD9335_MICB2_TEST_CTL_3                         0x0670
+#define WCD9335_MICB3_TEST_CTL_1                         0x0671
+#define WCD9335_MICB3_TEST_CTL_2                         0x0672
+#define WCD9335_MICB3_TEST_CTL_3                         0x0673
+#define WCD9335_MICB4_TEST_CTL_1                         0x0674
+#define WCD9335_MICB4_TEST_CTL_2                         0x0675
+#define WCD9335_MICB4_TEST_CTL_3                         0x0676
+#define WCD9335_TX_COM_ADC_VCM                           0x0677
+#define WCD9335_TX_COM_BIAS_ATEST                        0x0678
+#define WCD9335_TX_COM_ADC_INT1_IB                       0x0679
+#define WCD9335_TX_COM_ADC_INT2_IB                       0x067a
+#define WCD9335_TX_COM_TXFE_DIV_CTL                      0x067b
+#define WCD9335_TX_COM_TXFE_DIV_START                    0x067c
+#define WCD9335_TX_COM_TXFE_DIV_STOP_9P6M                0x067d
+#define WCD9335_TX_COM_TXFE_DIV_STOP_12P288M             0x067e
+#define WCD9335_TX_1_2_TEST_EN                           0x067f
+#define WCD9335_TX_1_2_ADC_IB                            0x0680
+#define WCD9335_TX_1_2_ATEST_REFCTL                      0x0681
+#define WCD9335_TX_1_2_TEST_CTL                          0x0682
+#define WCD9335_TX_1_2_TEST_BLK_EN                       0x0683
+#define WCD9335_TX_1_2_TXFE_CLKDIV                       0x0684
+#define WCD9335_TX_1_2_SAR1_ERR                          0x0685
+#define WCD9335_TX_1_2_SAR2_ERR                          0x0686
+#define WCD9335_TX_3_4_TEST_EN                           0x0687
+#define WCD9335_TX_3_4_ADC_IB                            0x0688
+#define WCD9335_TX_3_4_ATEST_REFCTL                      0x0689
+#define WCD9335_TX_3_4_TEST_CTL                          0x068a
+#define WCD9335_TX_3_4_TEST_BLK_EN                       0x068b
+#define WCD9335_TX_3_4_TXFE_CLKDIV                       0x068c
+#define WCD9335_TX_3_4_SAR1_ERR                          0x068d
+#define WCD9335_TX_3_4_SAR2_ERR                          0x068e
+#define WCD9335_TX_5_6_TEST_EN                           0x068f
+#define WCD9335_TX_5_6_ADC_IB                            0x0690
+#define WCD9335_TX_5_6_ATEST_REFCTL                      0x0691
+#define WCD9335_TX_5_6_TEST_CTL                          0x0692
+#define WCD9335_TX_5_6_TEST_BLK_EN                       0x0693
+#define WCD9335_TX_5_6_TXFE_CLKDIV                       0x0694
+#define WCD9335_TX_5_6_SAR1_ERR                          0x0695
+#define WCD9335_TX_5_6_SAR2_ERR                          0x0696
+#define WCD9335_CLASSH_MODE_1                            0x0697
+#define WCD9335_CLASSH_MODE_2                            0x0698
+#define WCD9335_CLASSH_MODE_3                            0x0699
+#define WCD9335_CLASSH_CTRL_VCL_1                        0x069a
+#define WCD9335_CLASSH_CTRL_VCL_2                        0x069b
+#define WCD9335_CLASSH_CTRL_CCL_1                        0x069c
+#define WCD9335_CLASSH_CTRL_CCL_2                        0x069d
+#define WCD9335_CLASSH_CTRL_CCL_3                        0x069e
+#define WCD9335_CLASSH_CTRL_CCL_4                        0x069f
+#define WCD9335_CLASSH_CTRL_CCL_5                        0x06a0
+#define WCD9335_CLASSH_BUCK_TMUX_A_D                     0x06a1
+#define WCD9335_CLASSH_BUCK_SW_DRV_CNTL                  0x06a2
+#define WCD9335_CLASSH_SPARE                             0x06a3
+#define WCD9335_FLYBACK_EN                               0x06a4
+#define WCD9335_FLYBACK_VNEG_CTRL_1                      0x06a5
+#define WCD9335_FLYBACK_VNEG_CTRL_2                      0x06a6
+#define WCD9335_FLYBACK_VNEG_CTRL_3                      0x06a7
+#define WCD9335_FLYBACK_VNEG_CTRL_4                      0x06a8
+#define WCD9335_FLYBACK_VNEG_CTRL_5                      0x06a9
+#define WCD9335_FLYBACK_VNEG_CTRL_6                      0x06aa
+#define WCD9335_FLYBACK_VNEG_CTRL_7                      0x06ab
+#define WCD9335_FLYBACK_VNEG_CTRL_8                      0x06ac
+#define WCD9335_FLYBACK_VNEG_CTRL_9                      0x06ad
+#define WCD9335_FLYBACK_VNEG_DAC_CTRL_1                  0x06ae
+#define WCD9335_FLYBACK_VNEG_DAC_CTRL_2                  0x06af
+#define WCD9335_FLYBACK_VNEG_DAC_CTRL_3                  0x06b0
+#define WCD9335_FLYBACK_VNEG_DAC_CTRL_4                  0x06b1 /* v1.x */
+#define WCD9335_FLYBACK_CTRL_1                           0x06b1 /* v2.0 */
+#define WCD9335_FLYBACK_TEST_CTL                         0x06b2
+#define WCD9335_RX_AUX_SW_CTL                            0x06b3
+#define WCD9335_RX_PA_AUX_IN_CONN                        0x06b4
+#define WCD9335_RX_TIMER_DIV                             0x06b5
+#define WCD9335_RX_OCP_CTL                               0x06b6
+#define WCD9335_RX_OCP_COUNT                             0x06b7
+#define WCD9335_RX_BIAS_EAR_DAC                          0x06b8
+#define WCD9335_RX_BIAS_EAR_AMP                          0x06b9
+#define WCD9335_RX_BIAS_HPH_LDO                          0x06ba
+#define WCD9335_RX_BIAS_HPH_PA                           0x06bb
+#define WCD9335_RX_BIAS_HPH_RDACBUFF_CNP2                0x06bc
+#define WCD9335_RX_BIAS_HPH_RDAC_LDO                     0x06bd
+#define WCD9335_RX_BIAS_HPH_CNP1                         0x06be
+#define WCD9335_RX_BIAS_HPH_LOWPOWER                     0x06bf
+#define WCD9335_RX_BIAS_DIFFLO_PA                        0x06c0
+#define WCD9335_RX_BIAS_DIFFLO_REF                       0x06c1
+#define WCD9335_RX_BIAS_DIFFLO_LDO                       0x06c2
+#define WCD9335_RX_BIAS_SELO_DAC_PA                      0x06c3
+#define WCD9335_RX_BIAS_BUCK_RST                         0x06c4
+#define WCD9335_RX_BIAS_BUCK_VREF_ERRAMP                 0x06c5
+#define WCD9335_RX_BIAS_FLYB_ERRAMP                      0x06c6
+#define WCD9335_RX_BIAS_FLYB_BUFF                        0x06c7
+#define WCD9335_RX_BIAS_FLYB_MID_RST                     0x06c8
+#define WCD9335_HPH_L_STATUS                             0x06c9
+#define WCD9335_HPH_R_STATUS                             0x06ca
+#define WCD9335_HPH_CNP_EN                               0x06cb
+#define WCD9335_HPH_CNP_WG_CTL                           0x06cc
+#define WCD9335_HPH_CNP_WG_TIME                          0x06cd
+#define WCD9335_HPH_OCP_CTL                              0x06ce
+#define WCD9335_HPH_AUTO_CHOP                            0x06cf
+#define WCD9335_HPH_CHOP_CTL                             0x06d0
+#define WCD9335_HPH_PA_CTL1                              0x06d1
+#define WCD9335_HPH_PA_CTL2                              0x06d2
+#define WCD9335_HPH_L_EN                                 0x06d3
+#define WCD9335_HPH_L_TEST                               0x06d4
+#define WCD9335_HPH_L_ATEST                              0x06d5
+#define WCD9335_HPH_R_EN                                 0x06d6
+#define WCD9335_HPH_R_TEST                               0x06d7
+#define WCD9335_HPH_R_ATEST                              0x06d8
+#define WCD9335_HPH_RDAC_CLK_CTL1                        0x06d9
+#define WCD9335_HPH_RDAC_CLK_CTL2                        0x06da
+#define WCD9335_HPH_RDAC_LDO_CTL                         0x06db
+#define WCD9335_HPH_RDAC_CHOP_CLK_LP_CTL                 0x06dc
+#define WCD9335_HPH_REFBUFF_UHQA_CTL                     0x06dd
+#define WCD9335_HPH_REFBUFF_LP_CTL                       0x06de
+#define WCD9335_HPH_L_DAC_CTL                            0x06df
+#define WCD9335_HPH_R_DAC_CTL                            0x06e0
+#define WCD9335_EAR_EN_REG                               0x06e1
+#define WCD9335_EAR_CMBUFF                               0x06e2
+#define WCD9335_EAR_ICTL                                 0x06e3
+#define WCD9335_EAR_EN_DBG_CTL                           0x06e4
+#define WCD9335_EAR_CNP                                  0x06e5
+#define WCD9335_EAR_DAC_CTL_ATEST                        0x06e6
+#define WCD9335_EAR_STATUS_REG                           0x06e7
+#define WCD9335_EAR_OUT_SHORT                            0x06e8
+#define WCD9335_DIFF_LO_MISC                             0x06e9
+#define WCD9335_DIFF_LO_LO2_COMPANDER                    0x06ea
+#define WCD9335_DIFF_LO_LO1_COMPANDER                    0x06eb
+#define WCD9335_DIFF_LO_COMMON                           0x06ec
+#define WCD9335_DIFF_LO_BYPASS_EN                        0x06ed
+#define WCD9335_DIFF_LO_CNP                              0x06ee
+#define WCD9335_DIFF_LO_CORE_OUT_PROG                    0x06ef
+#define WCD9335_DIFF_LO_LDO_OUT_PROG                     0x06f0
+#define WCD9335_DIFF_LO_COM_SWCAP_REFBUF_FREQ            0x06f1
+#define WCD9335_DIFF_LO_COM_PA_FREQ                      0x06f2
+#define WCD9335_DIFF_LO_RESERVED_REG                     0x06f3
+#define WCD9335_DIFF_LO_LO1_STATUS_1                     0x06f4
+#define WCD9335_DIFF_LO_LO1_STATUS_2                     0x06f5
+#define WCD9335_SE_LO_COM1                               0x06f6
+#define WCD9335_SE_LO_COM2                               0x06f7
+#define WCD9335_SE_LO_LO3_GAIN                           0x06f8
+#define WCD9335_SE_LO_LO3_CTRL                           0x06f9
+#define WCD9335_SE_LO_LO4_GAIN                           0x06fa
+#define WCD9335_SE_LO_LO4_CTRL                           0x06fb
+#define WCD9335_SE_LO_LO3_STATUS                         0x06fe
+#define WCD9335_SE_LO_LO4_STATUS                         0x06ff
+
+/* Page-10 Registers */
+#define WCD9335_PAGE10_PAGE_REGISTER                     0x0a00
+#define WCD9335_CDC_ANC0_CLK_RESET_CTL                   0x0a01
+#define WCD9335_CDC_ANC0_MODE_1_CTL                      0x0a02
+#define WCD9335_CDC_ANC0_MODE_2_CTL                      0x0a03
+#define WCD9335_CDC_ANC0_FF_SHIFT                        0x0a04
+#define WCD9335_CDC_ANC0_FB_SHIFT                        0x0a05
+#define WCD9335_CDC_ANC0_LPF_FF_A_CTL                    0x0a06
+#define WCD9335_CDC_ANC0_LPF_FF_B_CTL                    0x0a07
+#define WCD9335_CDC_ANC0_LPF_FB_CTL                      0x0a08
+#define WCD9335_CDC_ANC0_SMLPF_CTL                       0x0a09
+#define WCD9335_CDC_ANC0_DCFLT_SHIFT_CTL                 0x0a0a
+#define WCD9335_CDC_ANC0_IIR_ADAPT_CTL                   0x0a0b
+#define WCD9335_CDC_ANC0_IIR_COEFF_1_CTL                 0x0a0c
+#define WCD9335_CDC_ANC0_IIR_COEFF_2_CTL                 0x0a0d
+#define WCD9335_CDC_ANC0_FF_A_GAIN_CTL                   0x0a0e
+#define WCD9335_CDC_ANC0_FF_B_GAIN_CTL                   0x0a0f
+#define WCD9335_CDC_ANC0_FB_GAIN_CTL                     0x0a10
+#define WCD9335_CDC_ANC1_CLK_RESET_CTL                   0x0a19
+#define WCD9335_CDC_ANC1_MODE_1_CTL                      0x0a1a
+#define WCD9335_CDC_ANC1_MODE_2_CTL                      0x0a1b
+#define WCD9335_CDC_ANC1_FF_SHIFT                        0x0a1c
+#define WCD9335_CDC_ANC1_FB_SHIFT                        0x0a1d
+#define WCD9335_CDC_ANC1_LPF_FF_A_CTL                    0x0a1e
+#define WCD9335_CDC_ANC1_LPF_FF_B_CTL                    0x0a1f
+#define WCD9335_CDC_ANC1_LPF_FB_CTL                      0x0a20
+#define WCD9335_CDC_ANC1_SMLPF_CTL                       0x0a21
+#define WCD9335_CDC_ANC1_DCFLT_SHIFT_CTL                 0x0a22
+#define WCD9335_CDC_ANC1_IIR_ADAPT_CTL                   0x0a23
+#define WCD9335_CDC_ANC1_IIR_COEFF_1_CTL                 0x0a24
+#define WCD9335_CDC_ANC1_IIR_COEFF_2_CTL                 0x0a25
+#define WCD9335_CDC_ANC1_FF_A_GAIN_CTL                   0x0a26
+#define WCD9335_CDC_ANC1_FF_B_GAIN_CTL                   0x0a27
+#define WCD9335_CDC_ANC1_FB_GAIN_CTL                     0x0a28
+#define WCD9335_CDC_TX0_TX_PATH_CTL                      0x0a31
+#define WCD9335_CDC_TX0_TX_PATH_CFG0                     0x0a32
+#define WCD9335_CDC_TX0_TX_PATH_CFG1                     0x0a33
+#define WCD9335_CDC_TX0_TX_VOL_CTL                       0x0a34
+#define WCD9335_CDC_TX0_TX_PATH_192_CTL                  0x0a35
+#define WCD9335_CDC_TX0_TX_PATH_192_CFG                  0x0a36
+#define WCD9335_CDC_TX0_TX_PATH_SEC0                     0x0a37
+#define WCD9335_CDC_TX0_TX_PATH_SEC1                     0x0a38
+#define WCD9335_CDC_TX0_TX_PATH_SEC2                     0x0a39
+#define WCD9335_CDC_TX0_TX_PATH_SEC3                     0x0a3a
+#define WCD9335_CDC_TX0_TX_PATH_SEC4                     0x0a3b
+#define WCD9335_CDC_TX0_TX_PATH_SEC5                     0x0a3c
+#define WCD9335_CDC_TX0_TX_PATH_SEC6                     0x0a3d
+#define WCD9335_CDC_TX0_TX_PATH_SEC7                     0x0a3e
+#define WCD9335_CDC_TX1_TX_PATH_CTL                      0x0a41
+#define WCD9335_CDC_TX1_TX_PATH_CFG0                     0x0a42
+#define WCD9335_CDC_TX1_TX_PATH_CFG1                     0x0a43
+#define WCD9335_CDC_TX1_TX_VOL_CTL                       0x0a44
+#define WCD9335_CDC_TX1_TX_PATH_192_CTL                  0x0a45
+#define WCD9335_CDC_TX1_TX_PATH_192_CFG                  0x0a46
+#define WCD9335_CDC_TX1_TX_PATH_SEC0                     0x0a47
+#define WCD9335_CDC_TX1_TX_PATH_SEC1                     0x0a48
+#define WCD9335_CDC_TX1_TX_PATH_SEC2                     0x0a49
+#define WCD9335_CDC_TX1_TX_PATH_SEC3                     0x0a4a
+#define WCD9335_CDC_TX1_TX_PATH_SEC4                     0x0a4b
+#define WCD9335_CDC_TX1_TX_PATH_SEC5                     0x0a4c
+#define WCD9335_CDC_TX1_TX_PATH_SEC6                     0x0a4d
+#define WCD9335_CDC_TX2_TX_PATH_CTL                      0x0a51
+#define WCD9335_CDC_TX2_TX_PATH_CFG0                     0x0a52
+#define WCD9335_CDC_TX2_TX_PATH_CFG1                     0x0a53
+#define WCD9335_CDC_TX2_TX_VOL_CTL                       0x0a54
+#define WCD9335_CDC_TX2_TX_PATH_192_CTL                  0x0a55
+#define WCD9335_CDC_TX2_TX_PATH_192_CFG                  0x0a56
+#define WCD9335_CDC_TX2_TX_PATH_SEC0                     0x0a57
+#define WCD9335_CDC_TX2_TX_PATH_SEC1                     0x0a58
+#define WCD9335_CDC_TX2_TX_PATH_SEC2                     0x0a59
+#define WCD9335_CDC_TX2_TX_PATH_SEC3                     0x0a5a
+#define WCD9335_CDC_TX2_TX_PATH_SEC4                     0x0a5b
+#define WCD9335_CDC_TX2_TX_PATH_SEC5                     0x0a5c
+#define WCD9335_CDC_TX2_TX_PATH_SEC6                     0x0a5d
+#define WCD9335_CDC_TX3_TX_PATH_CTL                      0x0a61
+#define WCD9335_CDC_TX3_TX_PATH_CFG0                     0x0a62
+#define WCD9335_CDC_TX3_TX_PATH_CFG1                     0x0a63
+#define WCD9335_CDC_TX3_TX_VOL_CTL                       0x0a64
+#define WCD9335_CDC_TX3_TX_PATH_192_CTL                  0x0a65
+#define WCD9335_CDC_TX3_TX_PATH_192_CFG                  0x0a66
+#define WCD9335_CDC_TX3_TX_PATH_SEC0                     0x0a67
+#define WCD9335_CDC_TX3_TX_PATH_SEC1                     0x0a68
+#define WCD9335_CDC_TX3_TX_PATH_SEC2                     0x0a69
+#define WCD9335_CDC_TX3_TX_PATH_SEC3                     0x0a6a
+#define WCD9335_CDC_TX3_TX_PATH_SEC4                     0x0a6b
+#define WCD9335_CDC_TX3_TX_PATH_SEC5                     0x0a6c
+#define WCD9335_CDC_TX3_TX_PATH_SEC6                     0x0a6d
+#define WCD9335_CDC_TX4_TX_PATH_CTL                      0x0a71
+#define WCD9335_CDC_TX4_TX_PATH_CFG0                     0x0a72
+#define WCD9335_CDC_TX4_TX_PATH_CFG1                     0x0a73
+#define WCD9335_CDC_TX4_TX_VOL_CTL                       0x0a74
+#define WCD9335_CDC_TX4_TX_PATH_192_CTL                  0x0a75
+#define WCD9335_CDC_TX4_TX_PATH_192_CFG                  0x0a76
+#define WCD9335_CDC_TX4_TX_PATH_SEC0                     0x0a77
+#define WCD9335_CDC_TX4_TX_PATH_SEC1                     0x0a78
+#define WCD9335_CDC_TX4_TX_PATH_SEC2                     0x0a79
+#define WCD9335_CDC_TX4_TX_PATH_SEC3                     0x0a7a
+#define WCD9335_CDC_TX4_TX_PATH_SEC4                     0x0a7b
+#define WCD9335_CDC_TX4_TX_PATH_SEC5                     0x0a7c
+#define WCD9335_CDC_TX4_TX_PATH_SEC6                     0x0a7d
+#define WCD9335_CDC_TX5_TX_PATH_CTL                      0x0a81
+#define WCD9335_CDC_TX5_TX_PATH_CFG0                     0x0a82
+#define WCD9335_CDC_TX5_TX_PATH_CFG1                     0x0a83
+#define WCD9335_CDC_TX5_TX_VOL_CTL                       0x0a84
+#define WCD9335_CDC_TX5_TX_PATH_192_CTL                  0x0a85
+#define WCD9335_CDC_TX5_TX_PATH_192_CFG                  0x0a86
+#define WCD9335_CDC_TX5_TX_PATH_SEC0                     0x0a87
+#define WCD9335_CDC_TX5_TX_PATH_SEC1                     0x0a88
+#define WCD9335_CDC_TX5_TX_PATH_SEC2                     0x0a89
+#define WCD9335_CDC_TX5_TX_PATH_SEC3                     0x0a8a
+#define WCD9335_CDC_TX5_TX_PATH_SEC4                     0x0a8b
+#define WCD9335_CDC_TX5_TX_PATH_SEC5                     0x0a8c
+#define WCD9335_CDC_TX5_TX_PATH_SEC6                     0x0a8d
+#define WCD9335_CDC_TX6_TX_PATH_CTL                      0x0a91
+#define WCD9335_CDC_TX6_TX_PATH_CFG0                     0x0a92
+#define WCD9335_CDC_TX6_TX_PATH_CFG1                     0x0a93
+#define WCD9335_CDC_TX6_TX_VOL_CTL                       0x0a94
+#define WCD9335_CDC_TX6_TX_PATH_192_CTL                  0x0a95
+#define WCD9335_CDC_TX6_TX_PATH_192_CFG                  0x0a96
+#define WCD9335_CDC_TX6_TX_PATH_SEC0                     0x0a97
+#define WCD9335_CDC_TX6_TX_PATH_SEC1                     0x0a98
+#define WCD9335_CDC_TX6_TX_PATH_SEC2                     0x0a99
+#define WCD9335_CDC_TX6_TX_PATH_SEC3                     0x0a9a
+#define WCD9335_CDC_TX6_TX_PATH_SEC4                     0x0a9b
+#define WCD9335_CDC_TX6_TX_PATH_SEC5                     0x0a9c
+#define WCD9335_CDC_TX6_TX_PATH_SEC6                     0x0a9d
+#define WCD9335_CDC_TX7_TX_PATH_CTL                      0x0aa1
+#define WCD9335_CDC_TX7_TX_PATH_CFG0                     0x0aa2
+#define WCD9335_CDC_TX7_TX_PATH_CFG1                     0x0aa3
+#define WCD9335_CDC_TX7_TX_VOL_CTL                       0x0aa4
+#define WCD9335_CDC_TX7_TX_PATH_192_CTL                  0x0aa5
+#define WCD9335_CDC_TX7_TX_PATH_192_CFG                  0x0aa6
+#define WCD9335_CDC_TX7_TX_PATH_SEC0                     0x0aa7
+#define WCD9335_CDC_TX7_TX_PATH_SEC1                     0x0aa8
+#define WCD9335_CDC_TX7_TX_PATH_SEC2                     0x0aa9
+#define WCD9335_CDC_TX7_TX_PATH_SEC3                     0x0aaa
+#define WCD9335_CDC_TX7_TX_PATH_SEC4                     0x0aab
+#define WCD9335_CDC_TX7_TX_PATH_SEC5                     0x0aac
+#define WCD9335_CDC_TX7_TX_PATH_SEC6                     0x0aad
+#define WCD9335_CDC_TX8_TX_PATH_CTL                      0x0ab1
+#define WCD9335_CDC_TX8_TX_PATH_CFG0                     0x0ab2
+#define WCD9335_CDC_TX8_TX_PATH_CFG1                     0x0ab3
+#define WCD9335_CDC_TX8_TX_VOL_CTL                       0x0ab4
+#define WCD9335_CDC_TX8_TX_PATH_192_CTL                  0x0ab5
+#define WCD9335_CDC_TX8_TX_PATH_192_CFG                  0x0ab6
+#define WCD9335_CDC_TX8_TX_PATH_SEC0                     0x0ab7
+#define WCD9335_CDC_TX8_TX_PATH_SEC1                     0x0ab8
+#define WCD9335_CDC_TX8_TX_PATH_SEC2                     0x0ab9
+#define WCD9335_CDC_TX8_TX_PATH_SEC3                     0x0aba
+#define WCD9335_CDC_TX8_TX_PATH_SEC4                     0x0abb
+#define WCD9335_CDC_TX8_TX_PATH_SEC5                     0x0abc
+#define WCD9335_CDC_TX8_TX_PATH_SEC6                     0x0abd
+#define WCD9335_CDC_TX9_SPKR_PROT_PATH_CTL               0x0ac2
+#define WCD9335_CDC_TX9_SPKR_PROT_PATH_CFG0              0x0ac3
+#define WCD9335_CDC_TX10_SPKR_PROT_PATH_CTL              0x0ac6
+#define WCD9335_CDC_TX10_SPKR_PROT_PATH_CFG0             0x0ac7
+#define WCD9335_CDC_TX11_SPKR_PROT_PATH_CTL              0x0aca
+#define WCD9335_CDC_TX11_SPKR_PROT_PATH_CFG0             0x0acb
+#define WCD9335_CDC_TX12_SPKR_PROT_PATH_CTL              0x0ace
+#define WCD9335_CDC_TX12_SPKR_PROT_PATH_CFG0             0x0acf
+
+/* Page-11 Registers */
+#define WCD9335_PAGE11_PAGE_REGISTER                     0x0b00
+#define WCD9335_CDC_COMPANDER1_CTL0                      0x0b01
+#define WCD9335_CDC_COMPANDER1_CTL1                      0x0b02
+#define WCD9335_CDC_COMPANDER1_CTL2                      0x0b03
+#define WCD9335_CDC_COMPANDER1_CTL3                      0x0b04
+#define WCD9335_CDC_COMPANDER1_CTL4                      0x0b05
+#define WCD9335_CDC_COMPANDER1_CTL5                      0x0b06
+#define WCD9335_CDC_COMPANDER1_CTL6                      0x0b07
+#define WCD9335_CDC_COMPANDER1_CTL7                      0x0b08
+#define WCD9335_CDC_COMPANDER2_CTL0                      0x0b09
+#define WCD9335_CDC_COMPANDER2_CTL1                      0x0b0a
+#define WCD9335_CDC_COMPANDER2_CTL2                      0x0b0b
+#define WCD9335_CDC_COMPANDER2_CTL3                      0x0b0c
+#define WCD9335_CDC_COMPANDER2_CTL4                      0x0b0d
+#define WCD9335_CDC_COMPANDER2_CTL5                      0x0b0e
+#define WCD9335_CDC_COMPANDER2_CTL6                      0x0b0f
+#define WCD9335_CDC_COMPANDER2_CTL7                      0x0b10
+#define WCD9335_CDC_COMPANDER3_CTL0                      0x0b11
+#define WCD9335_CDC_COMPANDER3_CTL1                      0x0b12
+#define WCD9335_CDC_COMPANDER3_CTL2                      0x0b13
+#define WCD9335_CDC_COMPANDER3_CTL3                      0x0b14
+#define WCD9335_CDC_COMPANDER3_CTL4                      0x0b15
+#define WCD9335_CDC_COMPANDER3_CTL5                      0x0b16
+#define WCD9335_CDC_COMPANDER3_CTL6                      0x0b17
+#define WCD9335_CDC_COMPANDER3_CTL7                      0x0b18
+#define WCD9335_CDC_COMPANDER4_CTL0                      0x0b19
+#define WCD9335_CDC_COMPANDER4_CTL1                      0x0b1a
+#define WCD9335_CDC_COMPANDER4_CTL2                      0x0b1b
+#define WCD9335_CDC_COMPANDER4_CTL3                      0x0b1c
+#define WCD9335_CDC_COMPANDER4_CTL4                      0x0b1d
+#define WCD9335_CDC_COMPANDER4_CTL5                      0x0b1e
+#define WCD9335_CDC_COMPANDER4_CTL6                      0x0b1f
+#define WCD9335_CDC_COMPANDER4_CTL7                      0x0b20
+#define WCD9335_CDC_COMPANDER5_CTL0                      0x0b21
+#define WCD9335_CDC_COMPANDER5_CTL1                      0x0b22
+#define WCD9335_CDC_COMPANDER5_CTL2                      0x0b23
+#define WCD9335_CDC_COMPANDER5_CTL3                      0x0b24
+#define WCD9335_CDC_COMPANDER5_CTL4                      0x0b25
+#define WCD9335_CDC_COMPANDER5_CTL5                      0x0b26
+#define WCD9335_CDC_COMPANDER5_CTL6                      0x0b27
+#define WCD9335_CDC_COMPANDER5_CTL7                      0x0b28
+#define WCD9335_CDC_COMPANDER6_CTL0                      0x0b29
+#define WCD9335_CDC_COMPANDER6_CTL1                      0x0b2a
+#define WCD9335_CDC_COMPANDER6_CTL2                      0x0b2b
+#define WCD9335_CDC_COMPANDER6_CTL3                      0x0b2c
+#define WCD9335_CDC_COMPANDER6_CTL4                      0x0b2d
+#define WCD9335_CDC_COMPANDER6_CTL5                      0x0b2e
+#define WCD9335_CDC_COMPANDER6_CTL6                      0x0b2f
+#define WCD9335_CDC_COMPANDER6_CTL7                      0x0b30
+#define WCD9335_CDC_COMPANDER7_CTL0                      0x0b31
+#define WCD9335_CDC_COMPANDER7_CTL1                      0x0b32
+#define WCD9335_CDC_COMPANDER7_CTL2                      0x0b33
+#define WCD9335_CDC_COMPANDER7_CTL3                      0x0b34
+#define WCD9335_CDC_COMPANDER7_CTL4                      0x0b35
+#define WCD9335_CDC_COMPANDER7_CTL5                      0x0b36
+#define WCD9335_CDC_COMPANDER7_CTL6                      0x0b37
+#define WCD9335_CDC_COMPANDER7_CTL7                      0x0b38
+#define WCD9335_CDC_COMPANDER8_CTL0                      0x0b39
+#define WCD9335_CDC_COMPANDER8_CTL1                      0x0b3a
+#define WCD9335_CDC_COMPANDER8_CTL2                      0x0b3b
+#define WCD9335_CDC_COMPANDER8_CTL3                      0x0b3c
+#define WCD9335_CDC_COMPANDER8_CTL4                      0x0b3d
+#define WCD9335_CDC_COMPANDER8_CTL5                      0x0b3e
+#define WCD9335_CDC_COMPANDER8_CTL6                      0x0b3f
+#define WCD9335_CDC_COMPANDER8_CTL7                      0x0b40
+#define WCD9335_CDC_RX0_RX_PATH_CTL                      0x0b41
+#define WCD9335_CDC_RX0_RX_PATH_CFG0                     0x0b42
+#define WCD9335_CDC_RX0_RX_PATH_CFG1                     0x0b43
+#define WCD9335_CDC_RX0_RX_PATH_CFG2                     0x0b44
+#define WCD9335_CDC_RX0_RX_VOL_CTL                       0x0b45
+#define WCD9335_CDC_RX0_RX_PATH_MIX_CTL                  0x0b46
+#define WCD9335_CDC_RX0_RX_PATH_MIX_CFG                  0x0b47
+#define WCD9335_CDC_RX0_RX_VOL_MIX_CTL                   0x0b48
+#define WCD9335_CDC_RX0_RX_PATH_SEC0                     0x0b49
+#define WCD9335_CDC_RX0_RX_PATH_SEC1                     0x0b4a
+#define WCD9335_CDC_RX0_RX_PATH_SEC2                     0x0b4b
+#define WCD9335_CDC_RX0_RX_PATH_SEC3                     0x0b4c
+#define WCD9335_CDC_RX0_RX_PATH_SEC5                     0x0b4e
+#define WCD9335_CDC_RX0_RX_PATH_SEC6                     0x0b4f
+#define WCD9335_CDC_RX0_RX_PATH_SEC7                     0x0b50
+#define WCD9335_CDC_RX0_RX_PATH_MIX_SEC0                 0x0b51
+#define WCD9335_CDC_RX0_RX_PATH_MIX_SEC1                 0x0b52
+#define WCD9335_CDC_RX1_RX_PATH_CTL                      0x0b55
+#define WCD9335_CDC_RX1_RX_PATH_CFG0                     0x0b56
+#define WCD9335_CDC_RX1_RX_PATH_CFG1                     0x0b57
+#define WCD9335_CDC_RX1_RX_PATH_CFG2                     0x0b58
+#define WCD9335_CDC_RX1_RX_VOL_CTL                       0x0b59
+#define WCD9335_CDC_RX1_RX_PATH_MIX_CTL                  0x0b5a
+#define WCD9335_CDC_RX1_RX_PATH_MIX_CFG                  0x0b5b
+#define WCD9335_CDC_RX1_RX_VOL_MIX_CTL                   0x0b5c
+#define WCD9335_CDC_RX1_RX_PATH_SEC0                     0x0b5d
+#define WCD9335_CDC_RX1_RX_PATH_SEC1                     0x0b5e
+#define WCD9335_CDC_RX1_RX_PATH_SEC2                     0x0b5f
+#define WCD9335_CDC_RX1_RX_PATH_SEC3                     0x0b60
+#define WCD9335_CDC_RX1_RX_PATH_SEC4                     0x0b61
+#define WCD9335_CDC_RX1_RX_PATH_SEC5                     0x0b62
+#define WCD9335_CDC_RX1_RX_PATH_SEC6                     0x0b63
+#define WCD9335_CDC_RX1_RX_PATH_SEC7                     0x0b64
+#define WCD9335_CDC_RX1_RX_PATH_MIX_SEC0                 0x0b65
+#define WCD9335_CDC_RX1_RX_PATH_MIX_SEC1                 0x0b66
+#define WCD9335_CDC_RX2_RX_PATH_CTL                      0x0b69
+#define WCD9335_CDC_RX2_RX_PATH_CFG0                     0x0b6a
+#define WCD9335_CDC_RX2_RX_PATH_CFG1                     0x0b6b
+#define WCD9335_CDC_RX2_RX_PATH_CFG2                     0x0b6c
+#define WCD9335_CDC_RX2_RX_VOL_CTL                       0x0b6d
+#define WCD9335_CDC_RX2_RX_PATH_MIX_CTL                  0x0b6e
+#define WCD9335_CDC_RX2_RX_PATH_MIX_CFG                  0x0b6f
+#define WCD9335_CDC_RX2_RX_VOL_MIX_CTL                   0x0b70
+#define WCD9335_CDC_RX2_RX_PATH_SEC0                     0x0b71
+#define WCD9335_CDC_RX2_RX_PATH_SEC1                     0x0b72
+#define WCD9335_CDC_RX2_RX_PATH_SEC2                     0x0b73
+#define WCD9335_CDC_RX2_RX_PATH_SEC3                     0x0b74
+#define WCD9335_CDC_RX2_RX_PATH_SEC4                     0x0b75
+#define WCD9335_CDC_RX2_RX_PATH_SEC5                     0x0b76
+#define WCD9335_CDC_RX2_RX_PATH_SEC6                     0x0b77
+#define WCD9335_CDC_RX2_RX_PATH_SEC7                     0x0b78
+#define WCD9335_CDC_RX2_RX_PATH_MIX_SEC0                 0x0b79
+#define WCD9335_CDC_RX2_RX_PATH_MIX_SEC1                 0x0b7a
+#define WCD9335_CDC_RX3_RX_PATH_CTL                      0x0b7d
+#define WCD9335_CDC_RX3_RX_PATH_CFG0                     0x0b7e
+#define WCD9335_CDC_RX3_RX_PATH_CFG1                     0x0b7f
+#define WCD9335_CDC_RX3_RX_PATH_CFG2                     0x0b80
+#define WCD9335_CDC_RX3_RX_VOL_CTL                       0x0b81
+#define WCD9335_CDC_RX3_RX_PATH_MIX_CTL                  0x0b82
+#define WCD9335_CDC_RX3_RX_PATH_MIX_CFG                  0x0b83
+#define WCD9335_CDC_RX3_RX_VOL_MIX_CTL                   0x0b84
+#define WCD9335_CDC_RX3_RX_PATH_SEC0                     0x0b85
+#define WCD9335_CDC_RX3_RX_PATH_SEC1                     0x0b86
+#define WCD9335_CDC_RX3_RX_PATH_SEC2                     0x0b87
+#define WCD9335_CDC_RX3_RX_PATH_SEC3                     0x0b88
+#define WCD9335_CDC_RX3_RX_PATH_SEC5                     0x0b8a
+#define WCD9335_CDC_RX3_RX_PATH_SEC6                     0x0b8b
+#define WCD9335_CDC_RX3_RX_PATH_SEC7                     0x0b8c
+#define WCD9335_CDC_RX3_RX_PATH_MIX_SEC0                 0x0b8d
+#define WCD9335_CDC_RX3_RX_PATH_MIX_SEC1                 0x0b8e
+#define WCD9335_CDC_RX4_RX_PATH_CTL                      0x0b91
+#define WCD9335_CDC_RX4_RX_PATH_CFG0                     0x0b92
+#define WCD9335_CDC_RX4_RX_PATH_CFG1                     0x0b93
+#define WCD9335_CDC_RX4_RX_PATH_CFG2                     0x0b94
+#define WCD9335_CDC_RX4_RX_VOL_CTL                       0x0b95
+#define WCD9335_CDC_RX4_RX_PATH_MIX_CTL                  0x0b96
+#define WCD9335_CDC_RX4_RX_PATH_MIX_CFG                  0x0b97
+#define WCD9335_CDC_RX4_RX_VOL_MIX_CTL                   0x0b98
+#define WCD9335_CDC_RX4_RX_PATH_SEC0                     0x0b99
+#define WCD9335_CDC_RX4_RX_PATH_SEC1                     0x0b9a
+#define WCD9335_CDC_RX4_RX_PATH_SEC2                     0x0b9b
+#define WCD9335_CDC_RX4_RX_PATH_SEC3                     0x0b9c
+#define WCD9335_CDC_RX4_RX_PATH_SEC5                     0x0b9e
+#define WCD9335_CDC_RX4_RX_PATH_SEC6                     0x0b9f
+#define WCD9335_CDC_RX4_RX_PATH_SEC7                     0x0ba0
+#define WCD9335_CDC_RX4_RX_PATH_MIX_SEC0                 0x0ba1
+#define WCD9335_CDC_RX4_RX_PATH_MIX_SEC1                 0x0ba2
+#define WCD9335_CDC_RX5_RX_PATH_CTL                      0x0ba5
+#define WCD9335_CDC_RX5_RX_PATH_CFG0                     0x0ba6
+#define WCD9335_CDC_RX5_RX_PATH_CFG1                     0x0ba7
+#define WCD9335_CDC_RX5_RX_PATH_CFG2                     0x0ba8
+#define WCD9335_CDC_RX5_RX_VOL_CTL                       0x0ba9
+#define WCD9335_CDC_RX5_RX_PATH_MIX_CTL                  0x0baa
+#define WCD9335_CDC_RX5_RX_PATH_MIX_CFG                  0x0bab
+#define WCD9335_CDC_RX5_RX_VOL_MIX_CTL                   0x0bac
+#define WCD9335_CDC_RX5_RX_PATH_SEC0                     0x0bad
+#define WCD9335_CDC_RX5_RX_PATH_SEC1                     0x0bae
+#define WCD9335_CDC_RX5_RX_PATH_SEC2                     0x0baf
+#define WCD9335_CDC_RX5_RX_PATH_SEC3                     0x0bb0
+#define WCD9335_CDC_RX5_RX_PATH_SEC5                     0x0bb2
+#define WCD9335_CDC_RX5_RX_PATH_SEC6                     0x0bb3
+#define WCD9335_CDC_RX5_RX_PATH_SEC7                     0x0bb4
+#define WCD9335_CDC_RX5_RX_PATH_MIX_SEC0                 0x0bb5
+#define WCD9335_CDC_RX5_RX_PATH_MIX_SEC1                 0x0bb6
+#define WCD9335_CDC_RX6_RX_PATH_CTL                      0x0bb9
+#define WCD9335_CDC_RX6_RX_PATH_CFG0                     0x0bba
+#define WCD9335_CDC_RX6_RX_PATH_CFG1                     0x0bbb
+#define WCD9335_CDC_RX6_RX_PATH_CFG2                     0x0bbc
+#define WCD9335_CDC_RX6_RX_VOL_CTL                       0x0bbd
+#define WCD9335_CDC_RX6_RX_PATH_MIX_CTL                  0x0bbe
+#define WCD9335_CDC_RX6_RX_PATH_MIX_CFG                  0x0bbf
+#define WCD9335_CDC_RX6_RX_VOL_MIX_CTL                   0x0bc0
+#define WCD9335_CDC_RX6_RX_PATH_SEC0                     0x0bc1
+#define WCD9335_CDC_RX6_RX_PATH_SEC1                     0x0bc2
+#define WCD9335_CDC_RX6_RX_PATH_SEC2                     0x0bc3
+#define WCD9335_CDC_RX6_RX_PATH_SEC3                     0x0bc4
+#define WCD9335_CDC_RX6_RX_PATH_SEC5                     0x0bc6
+#define WCD9335_CDC_RX6_RX_PATH_SEC6                     0x0bc7
+#define WCD9335_CDC_RX6_RX_PATH_SEC7                     0x0bc8
+#define WCD9335_CDC_RX6_RX_PATH_MIX_SEC0                 0x0bc9
+#define WCD9335_CDC_RX6_RX_PATH_MIX_SEC1                 0x0bca
+#define WCD9335_CDC_RX7_RX_PATH_CTL                      0x0bcd
+#define WCD9335_CDC_RX7_RX_PATH_CFG0                     0x0bce
+#define WCD9335_CDC_RX7_RX_PATH_CFG1                     0x0bcf
+#define WCD9335_CDC_RX7_RX_PATH_CFG2                     0x0bd0
+#define WCD9335_CDC_RX7_RX_VOL_CTL                       0x0bd1
+#define WCD9335_CDC_RX7_RX_PATH_MIX_CTL                  0x0bd2
+#define WCD9335_CDC_RX7_RX_PATH_MIX_CFG                  0x0bd3
+#define WCD9335_CDC_RX7_RX_VOL_MIX_CTL                   0x0bd4
+#define WCD9335_CDC_RX7_RX_PATH_SEC0                     0x0bd5
+#define WCD9335_CDC_RX7_RX_PATH_SEC1                     0x0bd6
+#define WCD9335_CDC_RX7_RX_PATH_SEC2                     0x0bd7
+#define WCD9335_CDC_RX7_RX_PATH_SEC3                     0x0bd8
+#define WCD9335_CDC_RX7_RX_PATH_SEC5                     0x0bda
+#define WCD9335_CDC_RX7_RX_PATH_SEC6                     0x0bdb
+#define WCD9335_CDC_RX7_RX_PATH_SEC7                     0x0bdc
+#define WCD9335_CDC_RX7_RX_PATH_MIX_SEC0                 0x0bdd
+#define WCD9335_CDC_RX7_RX_PATH_MIX_SEC1                 0x0bde
+#define WCD9335_CDC_RX8_RX_PATH_CTL                      0x0be1
+#define WCD9335_CDC_RX8_RX_PATH_CFG0                     0x0be2
+#define WCD9335_CDC_RX8_RX_PATH_CFG1                     0x0be3
+#define WCD9335_CDC_RX8_RX_PATH_CFG2                     0x0be4
+#define WCD9335_CDC_RX8_RX_VOL_CTL                       0x0be5
+#define WCD9335_CDC_RX8_RX_PATH_MIX_CTL                  0x0be6
+#define WCD9335_CDC_RX8_RX_PATH_MIX_CFG                  0x0be7
+#define WCD9335_CDC_RX8_RX_VOL_MIX_CTL                   0x0be8
+#define WCD9335_CDC_RX8_RX_PATH_SEC0                     0x0be9
+#define WCD9335_CDC_RX8_RX_PATH_SEC1                     0x0bea
+#define WCD9335_CDC_RX8_RX_PATH_SEC2                     0x0beb
+#define WCD9335_CDC_RX8_RX_PATH_SEC3                     0x0bec
+#define WCD9335_CDC_RX8_RX_PATH_SEC5                     0x0bee
+#define WCD9335_CDC_RX8_RX_PATH_SEC6                     0x0bef
+#define WCD9335_CDC_RX8_RX_PATH_SEC7                     0x0bf0
+#define WCD9335_CDC_RX8_RX_PATH_MIX_SEC0                 0x0bf1
+#define WCD9335_CDC_RX8_RX_PATH_MIX_SEC1                 0x0bf2
+
+/* Page-12 Registers */
+#define WCD9335_PAGE12_PAGE_REGISTER                     0x0c00
+#define WCD9335_CDC_CLSH_CRC                             0x0c01
+#define WCD9335_CDC_CLSH_DLY_CTRL                        0x0c02
+#define WCD9335_CDC_CLSH_DECAY_CTRL                      0x0c03
+#define WCD9335_CDC_CLSH_HPH_V_PA                        0x0c04
+#define WCD9335_CDC_CLSH_EAR_V_PA                        0x0c05
+#define WCD9335_CDC_CLSH_HPH_V_HD                        0x0c06
+#define WCD9335_CDC_CLSH_EAR_V_HD                        0x0c07
+#define WCD9335_CDC_CLSH_K1_MSB                          0x0c08
+#define WCD9335_CDC_CLSH_K1_LSB                          0x0c09
+#define WCD9335_CDC_CLSH_K2_MSB                          0x0c0a
+#define WCD9335_CDC_CLSH_K2_LSB                          0x0c0b
+#define WCD9335_CDC_CLSH_IDLE_CTRL                       0x0c0c
+#define WCD9335_CDC_CLSH_IDLE_HPH                        0x0c0d
+#define WCD9335_CDC_CLSH_IDLE_EAR                        0x0c0e
+#define WCD9335_CDC_CLSH_TEST0                           0x0c0f
+#define WCD9335_CDC_CLSH_TEST1                           0x0c10
+#define WCD9335_CDC_CLSH_OVR_VREF                        0x0c11
+#define WCD9335_CDC_BOOST0_BOOST_PATH_CTL                0x0c19
+#define WCD9335_CDC_BOOST0_BOOST_CTL                     0x0c1a
+#define WCD9335_CDC_BOOST0_BOOST_CFG1                    0x0c1b
+#define WCD9335_CDC_BOOST0_BOOST_CFG2                    0x0c1c
+#define WCD9335_CDC_BOOST1_BOOST_PATH_CTL                0x0c21
+#define WCD9335_CDC_BOOST1_BOOST_CTL                     0x0c22
+#define WCD9335_CDC_BOOST1_BOOST_CFG1                    0x0c23
+#define WCD9335_CDC_BOOST1_BOOST_CFG2                    0x0c24
+#define WCD9335_SWR_AHB_BRIDGE_WR_DATA_0                 0x0c29
+#define WCD9335_SWR_AHB_BRIDGE_WR_DATA_1                 0x0c2a
+#define WCD9335_SWR_AHB_BRIDGE_WR_DATA_2                 0x0c2b
+#define WCD9335_SWR_AHB_BRIDGE_WR_DATA_3                 0x0c2c
+#define WCD9335_SWR_AHB_BRIDGE_WR_ADDR_0                 0x0c2d
+#define WCD9335_SWR_AHB_BRIDGE_WR_ADDR_1                 0x0c2e
+#define WCD9335_SWR_AHB_BRIDGE_WR_ADDR_2                 0x0c2f
+#define WCD9335_SWR_AHB_BRIDGE_WR_ADDR_3                 0x0c30
+#define WCD9335_SWR_AHB_BRIDGE_RD_ADDR_0                 0x0c31
+#define WCD9335_SWR_AHB_BRIDGE_RD_ADDR_1                 0x0c32
+#define WCD9335_SWR_AHB_BRIDGE_RD_ADDR_2                 0x0c33
+#define WCD9335_SWR_AHB_BRIDGE_RD_ADDR_3                 0x0c34
+#define WCD9335_SWR_AHB_BRIDGE_RD_DATA_0                 0x0c35
+#define WCD9335_SWR_AHB_BRIDGE_RD_DATA_1                 0x0c36
+#define WCD9335_SWR_AHB_BRIDGE_RD_DATA_2                 0x0c37
+#define WCD9335_SWR_AHB_BRIDGE_RD_DATA_3                 0x0c38
+#define WCD9335_SWR_AHB_BRIDGE_ACCESS_CFG                0x0c39
+#define WCD9335_SWR_AHB_BRIDGE_ACCESS_STATUS             0x0c3a
+#define WCD9335_CDC_VBAT_VBAT_PATH_CTL                   0x0c3d
+#define WCD9335_CDC_VBAT_VBAT_CFG                        0x0c3e
+#define WCD9335_CDC_VBAT_VBAT_ADC_CAL1                   0x0c3f
+#define WCD9335_CDC_VBAT_VBAT_ADC_CAL2                   0x0c40
+#define WCD9335_CDC_VBAT_VBAT_ADC_CAL3                   0x0c41
+#define WCD9335_CDC_VBAT_VBAT_PK_EST1                    0x0c42
+#define WCD9335_CDC_VBAT_VBAT_PK_EST2                    0x0c43
+#define WCD9335_CDC_VBAT_VBAT_PK_EST3                    0x0c44
+#define WCD9335_CDC_VBAT_VBAT_RF_PROC1                   0x0c45
+#define WCD9335_CDC_VBAT_VBAT_RF_PROC2                   0x0c46
+#define WCD9335_CDC_VBAT_VBAT_TAC1                       0x0c47
+#define WCD9335_CDC_VBAT_VBAT_TAC2                       0x0c48
+#define WCD9335_CDC_VBAT_VBAT_TAC3                       0x0c49
+#define WCD9335_CDC_VBAT_VBAT_TAC4                       0x0c4a
+#define WCD9335_CDC_VBAT_VBAT_GAIN_UPD1                  0x0c4b
+#define WCD9335_CDC_VBAT_VBAT_GAIN_UPD2                  0x0c4c
+#define WCD9335_CDC_VBAT_VBAT_GAIN_UPD3                  0x0c4d
+#define WCD9335_CDC_VBAT_VBAT_GAIN_UPD4                  0x0c4e
+#define WCD9335_CDC_VBAT_VBAT_DEBUG1                     0x0c4f
+#define WCD9335_CDC_VBAT_VBAT_GAIN_UPD_MON               0x0c50
+#define WCD9335_CDC_VBAT_VBAT_GAIN_MON_VAL               0x0c51
+#define WCD9335_SPLINE_SRC0_CLK_RST_CTL_0                0x0c55
+#define WCD9335_SPLINE_SRC0_STATUS                       0x0c56
+#define WCD9335_SPLINE_SRC1_CLK_RST_CTL_0                0x0c6d
+#define WCD9335_SPLINE_SRC1_STATUS                       0x0c6e
+#define WCD9335_SPLINE_SRC2_CLK_RST_CTL_0                0x0c85
+#define WCD9335_SPLINE_SRC2_STATUS                       0x0c86
+#define WCD9335_SPLINE_SRC3_CLK_RST_CTL_0                0x0c9d
+#define WCD9335_SPLINE_SRC3_STATUS                       0x0c9e
+#define WCD9335_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL        0x0cb5
+#define WCD9335_CDC_SIDETONE_SRC0_ST_SRC_PATH_CFG1       0x0cb6
+#define WCD9335_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL        0x0cb9
+#define WCD9335_CDC_SIDETONE_SRC1_ST_SRC_PATH_CFG1       0x0cba
+
+/* Page-13 Registers */
+#define WCD9335_PAGE13_PAGE_REGISTER                     0x0d00
+#define WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG0              0x0d01
+#define WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG1              0x0d02
+#define WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG0              0x0d03
+#define WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG1              0x0d04
+#define WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG0              0x0d05
+#define WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG1              0x0d06
+#define WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG0              0x0d07
+#define WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG1              0x0d08
+#define WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG0              0x0d09
+#define WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG1              0x0d0a
+#define WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG0              0x0d0b
+#define WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG1              0x0d0c
+#define WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG0              0x0d0d
+#define WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG1              0x0d0e
+#define WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG0              0x0d0f
+#define WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG1              0x0d10
+#define WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG0              0x0d11
+#define WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG1              0x0d12
+#define WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG0               0x0d13
+#define WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG1               0x0d14
+#define WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG2               0x0d15
+#define WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG3               0x0d16
+#define WCD9335_CDC_RX_INP_MUX_RX_MIX_CFG4               0x0d17
+#define WCD9335_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0         0x0d18
+#define WCD9335_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1         0x0d19
+#define WCD9335_CDC_RX_INP_MUX_ANC_CFG0                  0x0d1a
+#define WCD9335_CDC_RX_INP_MUX_SPLINE_SRC_CFG0           0x0d1b
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG0             0x0d1d
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG1             0x0d1e
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG0             0x0d1f
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG1             0x0d20
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG0             0x0d21
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG1             0x0d22
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG0             0x0d23
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG1             0x0d24
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX4_CFG0             0x0d25
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX5_CFG0             0x0d26
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX6_CFG0             0x0d27
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX7_CFG0             0x0d28
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX8_CFG0             0x0d29
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX10_CFG0            0x0d2b
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX11_CFG0            0x0d2c
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX12_CFG0            0x0d2d
+#define WCD9335_CDC_TX_INP_MUX_ADC_MUX13_CFG0            0x0d2e
+#define WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0   0x0d31
+#define WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1   0x0d32
+#define WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2   0x0d33
+#define WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3   0x0d34
+#define WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0   0x0d35
+#define WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1   0x0d36
+#define WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2   0x0d37
+#define WCD9335_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3   0x0d38
+#define WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0                0x0d3a
+#define WCD9335_CDC_IF_ROUTER_TX_MUX_CFG1                0x0d3b
+#define WCD9335_CDC_IF_ROUTER_TX_MUX_CFG2                0x0d3c
+#define WCD9335_CDC_IF_ROUTER_TX_MUX_CFG3                0x0d3d
+#define WCD9335_CDC_CLK_RST_CTRL_MCLK_CONTROL            0x0d41
+#define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_CONTROL          0x0d42
+#define WCD9335_CDC_CLK_RST_CTRL_SWR_CONTROL             0x0d43
+#define WCD9335_CDC_PROX_DETECT_PROX_CTL                 0x0d49
+#define WCD9335_CDC_PROX_DETECT_PROX_POLL_PERIOD0        0x0d4a
+#define WCD9335_CDC_PROX_DETECT_PROX_POLL_PERIOD1        0x0d4b
+#define WCD9335_CDC_PROX_DETECT_PROX_SIG_PATTERN_LSB     0x0d4c
+#define WCD9335_CDC_PROX_DETECT_PROX_SIG_PATTERN_MSB     0x0d4d
+#define WCD9335_CDC_PROX_DETECT_PROX_STATUS              0x0d4e
+#define WCD9335_CDC_PROX_DETECT_PROX_TEST_CTRL           0x0d4f
+#define WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB       0x0d50
+#define WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB       0x0d51
+#define WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB_RD    0x0d52
+#define WCD9335_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB_RD    0x0d53
+#define WCD9335_CDC_PROX_DETECT_PROX_CTL_REPEAT_PAT      0x0d54
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_PATH_CTL           0x0d55
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL        0x0d56
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL        0x0d57
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL        0x0d58
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL        0x0d59
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B5_CTL        0x0d5a
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B6_CTL        0x0d5b
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B7_CTL        0x0d5c
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B8_CTL        0x0d5d
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_CTL                0x0d5e
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL     0x0d5f
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL        0x0d60
+#define WCD9335_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL        0x0d61
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_PATH_CTL           0x0d65
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL        0x0d66
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL        0x0d67
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL        0x0d68
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL        0x0d69
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B5_CTL        0x0d6a
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B6_CTL        0x0d6b
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B7_CTL        0x0d6c
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B8_CTL        0x0d6d
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_CTL                0x0d6e
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL     0x0d6f
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_COEF_B1_CTL        0x0d70
+#define WCD9335_CDC_SIDETONE_IIR1_IIR_COEF_B2_CTL        0x0d71
+#define WCD9335_CDC_TOP_TOP_CFG0                         0x0d81
+#define WCD9335_CDC_TOP_TOP_CFG1                         0x0d82
+#define WCD9335_CDC_TOP_TOP_CFG2                         0x0d83
+#define WCD9335_CDC_TOP_TOP_CFG3                         0x0d84
+#define WCD9335_CDC_TOP_TOP_CFG4                         0x0d85
+#define WCD9335_CDC_TOP_TOP_CFG5                         0x0d86
+#define WCD9335_CDC_TOP_TOP_CFG6                         0x0d87
+#define WCD9335_CDC_TOP_TOP_CFG7                         0x0d88
+#define WCD9335_CDC_TOP_HPHL_COMP_WR_LSB                 0x0d89
+#define WCD9335_CDC_TOP_HPHL_COMP_WR_MSB                 0x0d8a
+#define WCD9335_CDC_TOP_HPHL_COMP_LUT                    0x0d8b
+#define WCD9335_CDC_TOP_HPHL_COMP_RD_LSB                 0x0d8c
+#define WCD9335_CDC_TOP_HPHL_COMP_RD_MSB                 0x0d8d
+#define WCD9335_CDC_TOP_HPHR_COMP_WR_LSB                 0x0d8e
+#define WCD9335_CDC_TOP_HPHR_COMP_WR_MSB                 0x0d8f
+#define WCD9335_CDC_TOP_HPHR_COMP_LUT                    0x0d90
+#define WCD9335_CDC_TOP_HPHR_COMP_RD_LSB                 0x0d91
+#define WCD9335_CDC_TOP_HPHR_COMP_RD_MSB                 0x0d92
+#define WCD9335_CDC_TOP_DIFFL_COMP_WR_LSB                0x0d93
+#define WCD9335_CDC_TOP_DIFFL_COMP_WR_MSB                0x0d94
+#define WCD9335_CDC_TOP_DIFFL_COMP_LUT                   0x0d95
+#define WCD9335_CDC_TOP_DIFFL_COMP_RD_LSB                0x0d96
+#define WCD9335_CDC_TOP_DIFFL_COMP_RD_MSB                0x0d97
+#define WCD9335_CDC_TOP_DIFFR_COMP_WR_LSB                0x0d98
+#define WCD9335_CDC_TOP_DIFFR_COMP_WR_MSB                0x0d99
+#define WCD9335_CDC_TOP_DIFFR_COMP_LUT                   0x0d9a
+#define WCD9335_CDC_TOP_DIFFR_COMP_RD_LSB                0x0d9b
+#define WCD9335_CDC_TOP_DIFFR_COMP_RD_MSB                0x0d9c
+
+/* Page-0x80 Registers */
+#define WCD9335_PAGE80_PAGE_REGISTER                     0x8000
+#define WCD9335_TLMM_BIST_MODE_PINCFG                    0x8001
+#define WCD9335_TLMM_RF_PA_ON_PINCFG                     0x8002
+#define WCD9335_TLMM_INTR1_PINCFG                        0x8003
+#define WCD9335_TLMM_INTR2_PINCFG                        0x8004
+#define WCD9335_TLMM_SWR_DATA_PINCFG                     0x8005
+#define WCD9335_TLMM_SWR_CLK_PINCFG                      0x8006
+#define WCD9335_TLMM_SLIMBUS_DATA2_PINCFG                0x8007
+#define WCD9335_TLMM_I2C_CLK_PINCFG                      0x8008
+#define WCD9335_TLMM_I2C_DATA_PINCFG                     0x8009
+#define WCD9335_TLMM_I2S_RX_SD0_PINCFG                   0x800a
+#define WCD9335_TLMM_I2S_RX_SD1_PINCFG                   0x800b
+#define WCD9335_TLMM_I2S_RX_SCK_PINCFG                   0x800c
+#define WCD9335_TLMM_I2S_RX_WS_PINCFG                    0x800d
+#define WCD9335_TLMM_I2S_TX_SD0_PINCFG                   0x800e
+#define WCD9335_TLMM_I2S_TX_SD1_PINCFG                   0x800f
+#define WCD9335_TLMM_I2S_TX_SCK_PINCFG                   0x8010
+#define WCD9335_TLMM_I2S_TX_WS_PINCFG                    0x8011
+#define WCD9335_TLMM_DMIC1_CLK_PINCFG                    0x8012
+#define WCD9335_TLMM_DMIC1_DATA_PINCFG                   0x8013
+#define WCD9335_TLMM_DMIC2_CLK_PINCFG                    0x8014
+#define WCD9335_TLMM_DMIC2_DATA_PINCFG                   0x8015
+#define WCD9335_TLMM_DMIC3_CLK_PINCFG                    0x8016
+#define WCD9335_TLMM_DMIC3_DATA_PINCFG                   0x8017
+#define WCD9335_TLMM_JTDI_PINCFG                         0x8018
+#define WCD9335_TLMM_JTDO_PINCFG                         0x8019
+#define WCD9335_TLMM_JTMS_PINCFG                         0x801a
+#define WCD9335_TLMM_JTCK_PINCFG                         0x801b
+#define WCD9335_TLMM_JTRST_PINCFG                        0x801c
+#define WCD9335_TEST_DEBUG_PIN_CTL_OE_0                  0x8031
+#define WCD9335_TEST_DEBUG_PIN_CTL_OE_1                  0x8032
+#define WCD9335_TEST_DEBUG_PIN_CTL_OE_2                  0x8033
+#define WCD9335_TEST_DEBUG_PIN_CTL_OE_3                  0x8034
+#define WCD9335_TEST_DEBUG_PIN_CTL_DATA_0                0x8035
+#define WCD9335_TEST_DEBUG_PIN_CTL_DATA_1                0x8036
+#define WCD9335_TEST_DEBUG_PIN_CTL_DATA_2                0x8037
+#define WCD9335_TEST_DEBUG_PIN_CTL_DATA_3                0x8038
+#define WCD9335_TEST_DEBUG_PAD_DRVCTL                    0x8039
+#define WCD9335_TEST_DEBUG_PIN_STATUS                    0x803a
+#define WCD9335_TEST_DEBUG_NPL_DLY_TEST_1                0x803b
+#define WCD9335_TEST_DEBUG_NPL_DLY_TEST_2                0x803c
+#define WCD9335_TEST_DEBUG_MEM_CTRL                      0x803d
+#define WCD9335_TEST_DEBUG_DEBUG_BUS_SEL                 0x8041
+#define WCD9335_TEST_DEBUG_DEBUG_JTAG                    0x8042
+#define WCD9335_TEST_DEBUG_DEBUG_EN_1                    0x8043
+#define WCD9335_TEST_DEBUG_DEBUG_EN_2                    0x8044
+#define WCD9335_TEST_DEBUG_DEBUG_EN_3                    0x8045
+#define WCD9335_MAX_REGISTER                             0x80FF
+
+/* SLIMBUS Slave Registers */
+#define TASHA_SLIM_PGD_PORT_INT_EN0                     (0x30)
+#define TASHA_SLIM_PGD_PORT_INT_STATUS_RX_0             (0x34)
+#define TASHA_SLIM_PGD_PORT_INT_STATUS_RX_1             (0x35)
+#define TASHA_SLIM_PGD_PORT_INT_STATUS_TX_0             (0x36)
+#define TASHA_SLIM_PGD_PORT_INT_STATUS_TX_1             (0x37)
+#define TASHA_SLIM_PGD_PORT_INT_CLR_RX_0                (0x38)
+#define TASHA_SLIM_PGD_PORT_INT_CLR_RX_1                (0x39)
+#define TASHA_SLIM_PGD_PORT_INT_CLR_TX_0                (0x3A)
+#define TASHA_SLIM_PGD_PORT_INT_CLR_TX_1                (0x3B)
+#define TASHA_SLIM_PGD_PORT_INT_RX_SOURCE0		(0x60)
+#define TASHA_SLIM_PGD_PORT_INT_TX_SOURCE0		(0x70)
+
+/* Macros for Packing Register Writes into a U32 */
+#define TASHA_PACKED_REG_SIZE sizeof(u32)
+
+#define TASHA_CODEC_PACK_ENTRY(reg, mask, val) ((val & 0xff)|\
+	((mask & 0xff) << 8)|((reg & 0xffff) << 16))
+#define TASHA_CODEC_UNPACK_ENTRY(packed, reg, mask, val) \
+	do { \
+		((reg) = ((packed >> 16) & (0xffff))); \
+		((mask) = ((packed >> 8) & (0xff))); \
+		((val) = ((packed) & (0xff))); \
+	} while (0)
+#endif

+ 56 - 0
include/linux/mfd/wcd934x/irq.h

@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __WCD934X_IRQ_H_
+#define __WCD934X_IRQ_H_
+
+enum {
+	/* INTR_REG 0 */
+	WCD934X_IRQ_MISC = 1,
+	WCD934X_IRQ_HPH_PA_OCPL_FAULT,
+	WCD934X_IRQ_HPH_PA_OCPR_FAULT,
+	WCD934X_IRQ_EAR_PA_OCP_FAULT,
+	WCD934X_IRQ_HPH_PA_CNPL_COMPLETE,
+	WCD934X_IRQ_HPH_PA_CNPR_COMPLETE,
+	WCD934X_IRQ_EAR_PA_CNP_COMPLETE,
+	/* INTR_REG 1 */
+	WCD934X_IRQ_MBHC_SW_DET,
+	WCD934X_IRQ_MBHC_ELECT_INS_REM_DET,
+	WCD934X_IRQ_MBHC_BUTTON_PRESS_DET,
+	WCD934X_IRQ_MBHC_BUTTON_RELEASE_DET,
+	WCD934X_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
+	WCD934X_IRQ_RESERVED_0,
+	WCD934X_IRQ_RESERVED_1,
+	WCD934X_IRQ_RESERVED_2,
+	/* INTR_REG 2 */
+	WCD934X_IRQ_LINE_PA1_CNP_COMPLETE,
+	WCD934X_IRQ_LINE_PA2_CNP_COMPLETE,
+	WCD934X_IRQ_SLNQ_ANALOG_ERROR,
+	WCD934X_IRQ_RESERVED_3,
+	WCD934X_IRQ_SOUNDWIRE,
+	WCD934X_IRQ_VDD_DIG_RAMP_COMPLETE,
+	WCD934X_IRQ_RCO_ERROR,
+	WCD934X_IRQ_CPE_ERROR,
+	/* INTR_REG 3 */
+	WCD934X_IRQ_MAD_AUDIO,
+	WCD934X_IRQ_MAD_BEACON,
+	WCD934X_IRQ_MAD_ULTRASOUND,
+	WCD934X_IRQ_VBAT_ATTACK,
+	WCD934X_IRQ_VBAT_RESTORE,
+	WCD934X_IRQ_CPE1_INTR,
+	WCD934X_IRQ_RESERVED_4,
+	WCD934X_IRQ_SLNQ_DIGITAL,
+	WCD934X_NUM_IRQS,
+};
+
+#endif

+ 1848 - 0
include/linux/mfd/wcd934x/registers.h

@@ -0,0 +1,1848 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _WCD934X_REGISTERS_H
+#define _WCD934X_REGISTERS_H
+
+#define WCD934X_PAGE_SIZE 256
+#define WCD934X_NUM_PAGES 256
+
+extern const u8 * const wcd934x_reg[WCD934X_NUM_PAGES];
+
+enum {
+	WCD934X_PAGE_0 = 0,
+	WCD934X_PAGE_1,
+	WCD934X_PAGE_2,
+	WCD934X_PAGE_4 = 4,
+	WCD934X_PAGE_5,
+	WCD934X_PAGE_6,
+	WCD934X_PAGE_7,
+	WCD934X_PAGE_10 = 0xA,
+	WCD934X_PAGE_11,
+	WCD934X_PAGE_12,
+	WCD934X_PAGE_13,
+	WCD934X_PAGE_14,
+	WCD934X_PAGE_15,
+	WCD934X_PAGE_0x50,
+	WCD934X_PAGE_0X80,
+};
+
+enum {
+	WCD934X_WRITE = 0,
+	WCD934X_READ,
+	WCD934X_READ_WRITE,
+};
+
+/* Page-0 Registers */
+#define WCD934X_PAGE0_PAGE_REGISTER                        0x0000
+#define WCD934X_CODEC_RPM_CLK_BYPASS                       0x0001
+#define WCD934X_CODEC_RPM_CLK_GATE                         0x0002
+#define WCD934X_CODEC_RPM_CLK_MCLK_CFG                     0x0003
+#define WCD934X_CODEC_RPM_CLK_MCLK2_CFG                    0x0004
+#define WCD934X_CODEC_RPM_I2S_DSD_CLK_SEL                  0x0005
+#define WCD934X_CODEC_RPM_RST_CTL                          0x0009
+#define WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL               0x0011
+#define WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0               0x0021
+#define WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE1               0x0022
+#define WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2               0x0023
+#define WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE3               0x0024
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_CTL                   0x0025
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_TEST0                 0x0026
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_TEST1                 0x0027
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT0              0x0029
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT1              0x002a
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT2              0x002b
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT3              0x002c
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT4              0x002d
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT5              0x002e
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT6              0x002f
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT7              0x0030
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT8              0x0031
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT9              0x0032
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT10             0x0033
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT11             0x0034
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT12             0x0035
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT13             0x0036
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14             0x0037
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15             0x0038
+#define WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS                0x0039
+#define WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_NONNEGO        0x003a
+#define WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_1              0x003b
+#define WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_2              0x003c
+#define WCD934X_CHIP_TIER_CTRL_I2C_SLAVE_ID_3              0x003d
+#define WCD934X_CHIP_TIER_CTRL_ANA_WAIT_STATE_CTL          0x003e
+#define WCD934X_CHIP_TIER_CTRL_SLNQ_WAIT_STATE_CTL         0x003f
+#define WCD934X_CHIP_TIER_CTRL_I2C_ACTIVE                  0x0040
+#define WCD934X_CHIP_TIER_CTRL_ALT_FUNC_EN                 0x0041
+#define WCD934X_CHIP_TIER_CTRL_GPIO_CTL_OE                 0x0042
+#define WCD934X_CHIP_TIER_CTRL_GPIO_CTL_DATA               0x0043
+#define WCD934X_DATA_HUB_RX0_CFG                           0x0051
+#define WCD934X_DATA_HUB_RX1_CFG                           0x0052
+#define WCD934X_DATA_HUB_RX2_CFG                           0x0053
+#define WCD934X_DATA_HUB_RX3_CFG                           0x0054
+#define WCD934X_DATA_HUB_RX4_CFG                           0x0055
+#define WCD934X_DATA_HUB_RX5_CFG                           0x0056
+#define WCD934X_DATA_HUB_RX6_CFG                           0x0057
+#define WCD934X_DATA_HUB_RX7_CFG                           0x0058
+#define WCD934X_DATA_HUB_SB_TX0_INP_CFG                    0x0061
+#define WCD934X_DATA_HUB_SB_TX1_INP_CFG                    0x0062
+#define WCD934X_DATA_HUB_SB_TX2_INP_CFG                    0x0063
+#define WCD934X_DATA_HUB_SB_TX3_INP_CFG                    0x0064
+#define WCD934X_DATA_HUB_SB_TX4_INP_CFG                    0x0065
+#define WCD934X_DATA_HUB_SB_TX5_INP_CFG                    0x0066
+#define WCD934X_DATA_HUB_SB_TX6_INP_CFG                    0x0067
+#define WCD934X_DATA_HUB_SB_TX7_INP_CFG                    0x0068
+#define WCD934X_DATA_HUB_SB_TX8_INP_CFG                    0x0069
+#define WCD934X_DATA_HUB_SB_TX9_INP_CFG                    0x006a
+#define WCD934X_DATA_HUB_SB_TX10_INP_CFG                   0x006b
+#define WCD934X_DATA_HUB_SB_TX11_INP_CFG                   0x006c
+#define WCD934X_DATA_HUB_SB_TX13_INP_CFG                   0x006e
+#define WCD934X_DATA_HUB_SB_TX14_INP_CFG                   0x006f
+#define WCD934X_DATA_HUB_SB_TX15_INP_CFG                   0x0070
+#define WCD934X_DATA_HUB_I2S_TX0_CFG                       0x0071
+#define WCD934X_DATA_HUB_I2S_TX1_0_CFG                     0x0073
+#define WCD934X_DATA_HUB_I2S_TX1_1_CFG                     0x0074
+#define WCD934X_DATA_HUB_I2S_0_CTL                         0x0081
+#define WCD934X_DATA_HUB_I2S_1_CTL                         0x0082
+#define WCD934X_DATA_HUB_I2S_2_CTL                         0x0083
+#define WCD934X_DATA_HUB_I2S_3_CTL                         0x0084
+#define WCD934X_DATA_HUB_I2S_CLKSRC_CTL                    0x0085
+#define WCD934X_DATA_HUB_I2S_COMMON_CTL                    0x0086
+#define WCD934X_DATA_HUB_I2S_0_TDM_CTL                     0x0087
+#define WCD934X_DATA_HUB_I2S_STATUS                        0x0088
+#define WCD934X_DMA_RDMA_CTL_0                             0x0091
+#define WCD934X_DMA_CH_2_3_CFG_RDMA_0                      0x0092
+#define WCD934X_DMA_CH_0_1_CFG_RDMA_0                      0x0093
+#define WCD934X_DMA_RDMA_CTL_1                             0x0094
+#define WCD934X_DMA_CH_2_3_CFG_RDMA_1                      0x0095
+#define WCD934X_DMA_CH_0_1_CFG_RDMA_1                      0x0096
+#define WCD934X_DMA_RDMA_CTL_2                             0x0097
+#define WCD934X_DMA_CH_2_3_CFG_RDMA_2                      0x0098
+#define WCD934X_DMA_CH_0_1_CFG_RDMA_2                      0x0099
+#define WCD934X_DMA_RDMA_CTL_3                             0x009A
+#define WCD934X_DMA_CH_2_3_CFG_RDMA_3                      0x009B
+#define WCD934X_DMA_CH_0_1_CFG_RDMA_3                      0x009C
+#define WCD934X_DMA_RDMA_CTL_4                             0x009D
+#define WCD934X_DMA_CH_2_3_CFG_RDMA_4                      0x009E
+#define WCD934X_DMA_CH_0_1_CFG_RDMA_4                      0x009F
+#define WCD934X_DMA_RDMA4_PRT_CFG                          0x00b1
+#define WCD934X_DMA_RDMA_SBTX0_7_CFG                       0x00b9
+#define WCD934X_DMA_RDMA_SBTX8_11_CFG                      0x00ba
+#define WCD934X_DMA_WDMA_CTL_0                             0x00c1
+#define WCD934X_DMA_CH_4_5_CFG_WDMA_0                      0x00c2
+#define WCD934X_DMA_CH_2_3_CFG_WDMA_0                      0x00c3
+#define WCD934X_DMA_CH_0_1_CFG_WDMA_0                      0x00c4
+#define WCD934X_DMA_WDMA_CTL_1                             0x00C6
+#define WCD934X_DMA_CH_4_5_CFG_WDMA_1                      0x00C7
+#define WCD934X_DMA_CH_2_3_CFG_WDMA_1                      0x00C8
+#define WCD934X_DMA_CH_0_1_CFG_WDMA_1                      0x00C9
+#define WCD934X_DMA_WDMA_CTL_2                             0x00CB
+#define WCD934X_DMA_CH_4_5_CFG_WDMA_2                      0x00CC
+#define WCD934X_DMA_CH_2_3_CFG_WDMA_2                      0x00CD
+#define WCD934X_DMA_CH_0_1_CFG_WDMA_2                      0x00CE
+#define WCD934X_DMA_WDMA_CTL_3                             0x00D0
+#define WCD934X_DMA_CH_4_5_CFG_WDMA_3                      0x00D1
+#define WCD934X_DMA_CH_2_3_CFG_WDMA_3                      0x00D2
+#define WCD934X_DMA_CH_0_1_CFG_WDMA_3                      0x00D3
+#define WCD934X_DMA_WDMA_CTL_4                             0x00D5
+#define WCD934X_DMA_CH_4_5_CFG_WDMA_4                      0x00D6
+#define WCD934X_DMA_CH_2_3_CFG_WDMA_4                      0x00D7
+#define WCD934X_DMA_CH_0_1_CFG_WDMA_4                      0x00D8
+#define WCD934X_DMA_WDMA0_PRT_CFG                          0x00E1
+#define WCD934X_DMA_WDMA3_PRT_CFG                          0x00E2
+#define WCD934X_DMA_WDMA4_PRT0_3_CFG                       0x00E3
+#define WCD934X_DMA_WDMA4_PRT4_7_CFG                       0x00E4
+#define WCD934X_PAGE1_PAGE_REGISTER                        0x0100
+#define WCD934X_CPE_FLL_USER_CTL_0                         0x0101
+#define WCD934X_CPE_FLL_USER_CTL_1                         0x0102
+#define WCD934X_CPE_FLL_USER_CTL_2                         0x0103
+#define WCD934X_CPE_FLL_USER_CTL_3                         0x0104
+#define WCD934X_CPE_FLL_USER_CTL_4                         0x0105
+#define WCD934X_CPE_FLL_USER_CTL_5                         0x0106
+#define WCD934X_CPE_FLL_USER_CTL_6                         0x0107
+#define WCD934X_CPE_FLL_USER_CTL_7                         0x0108
+#define WCD934X_CPE_FLL_USER_CTL_8                         0x0109
+#define WCD934X_CPE_FLL_USER_CTL_9                         0x010a
+#define WCD934X_CPE_FLL_L_VAL_CTL_0                        0x010b
+#define WCD934X_CPE_FLL_L_VAL_CTL_1                        0x010c
+#define WCD934X_CPE_FLL_DSM_FRAC_CTL_0                     0x010d
+#define WCD934X_CPE_FLL_DSM_FRAC_CTL_1                     0x010e
+#define WCD934X_CPE_FLL_CONFIG_CTL_0                       0x010f
+#define WCD934X_CPE_FLL_CONFIG_CTL_1                       0x0110
+#define WCD934X_CPE_FLL_CONFIG_CTL_2                       0x0111
+#define WCD934X_CPE_FLL_CONFIG_CTL_3                       0x0112
+#define WCD934X_CPE_FLL_CONFIG_CTL_4                       0x0113
+#define WCD934X_CPE_FLL_TEST_CTL_0                         0x0114
+#define WCD934X_CPE_FLL_TEST_CTL_1                         0x0115
+#define WCD934X_CPE_FLL_TEST_CTL_2                         0x0116
+#define WCD934X_CPE_FLL_TEST_CTL_3                         0x0117
+#define WCD934X_CPE_FLL_TEST_CTL_4                         0x0118
+#define WCD934X_CPE_FLL_TEST_CTL_5                         0x0119
+#define WCD934X_CPE_FLL_TEST_CTL_6                         0x011a
+#define WCD934X_CPE_FLL_TEST_CTL_7                         0x011b
+#define WCD934X_CPE_FLL_FREQ_CTL_0                         0x011c
+#define WCD934X_CPE_FLL_FREQ_CTL_1                         0x011d
+#define WCD934X_CPE_FLL_FREQ_CTL_2                         0x011e
+#define WCD934X_CPE_FLL_FREQ_CTL_3                         0x011f
+#define WCD934X_CPE_FLL_SSC_CTL_0                          0x0120
+#define WCD934X_CPE_FLL_SSC_CTL_1                          0x0121
+#define WCD934X_CPE_FLL_SSC_CTL_2                          0x0122
+#define WCD934X_CPE_FLL_SSC_CTL_3                          0x0123
+#define WCD934X_CPE_FLL_FLL_MODE                           0x0124
+#define WCD934X_CPE_FLL_STATUS_0                           0x0125
+#define WCD934X_CPE_FLL_STATUS_1                           0x0126
+#define WCD934X_CPE_FLL_STATUS_2                           0x0127
+#define WCD934X_CPE_FLL_STATUS_3                           0x0128
+#define WCD934X_I2S_FLL_USER_CTL_0                         0x0141
+#define WCD934X_I2S_FLL_USER_CTL_1                         0x0142
+#define WCD934X_I2S_FLL_USER_CTL_2                         0x0143
+#define WCD934X_I2S_FLL_USER_CTL_3                         0x0144
+#define WCD934X_I2S_FLL_USER_CTL_4                         0x0145
+#define WCD934X_I2S_FLL_USER_CTL_5                         0x0146
+#define WCD934X_I2S_FLL_USER_CTL_6                         0x0147
+#define WCD934X_I2S_FLL_USER_CTL_7                         0x0148
+#define WCD934X_I2S_FLL_USER_CTL_8                         0x0149
+#define WCD934X_I2S_FLL_USER_CTL_9                         0x014a
+#define WCD934X_I2S_FLL_L_VAL_CTL_0                        0x014b
+#define WCD934X_I2S_FLL_L_VAL_CTL_1                        0x014c
+#define WCD934X_I2S_FLL_DSM_FRAC_CTL_0                     0x014d
+#define WCD934X_I2S_FLL_DSM_FRAC_CTL_1                     0x014e
+#define WCD934X_I2S_FLL_CONFIG_CTL_0                       0x014f
+#define WCD934X_I2S_FLL_CONFIG_CTL_1                       0x0150
+#define WCD934X_I2S_FLL_CONFIG_CTL_2                       0x0151
+#define WCD934X_I2S_FLL_CONFIG_CTL_3                       0x0152
+#define WCD934X_I2S_FLL_CONFIG_CTL_4                       0x0153
+#define WCD934X_I2S_FLL_TEST_CTL_0                         0x0154
+#define WCD934X_I2S_FLL_TEST_CTL_1                         0x0155
+#define WCD934X_I2S_FLL_TEST_CTL_2                         0x0156
+#define WCD934X_I2S_FLL_TEST_CTL_3                         0x0157
+#define WCD934X_I2S_FLL_TEST_CTL_4                         0x0158
+#define WCD934X_I2S_FLL_TEST_CTL_5                         0x0159
+#define WCD934X_I2S_FLL_TEST_CTL_6                         0x015a
+#define WCD934X_I2S_FLL_TEST_CTL_7                         0x015b
+#define WCD934X_I2S_FLL_FREQ_CTL_0                         0x015c
+#define WCD934X_I2S_FLL_FREQ_CTL_1                         0x015d
+#define WCD934X_I2S_FLL_FREQ_CTL_2                         0x015e
+#define WCD934X_I2S_FLL_FREQ_CTL_3                         0x015f
+#define WCD934X_I2S_FLL_SSC_CTL_0                          0x0160
+#define WCD934X_I2S_FLL_SSC_CTL_1                          0x0161
+#define WCD934X_I2S_FLL_SSC_CTL_2                          0x0162
+#define WCD934X_I2S_FLL_SSC_CTL_3                          0x0163
+#define WCD934X_I2S_FLL_FLL_MODE                           0x0164
+#define WCD934X_I2S_FLL_STATUS_0                           0x0165
+#define WCD934X_I2S_FLL_STATUS_1                           0x0166
+#define WCD934X_I2S_FLL_STATUS_2                           0x0167
+#define WCD934X_I2S_FLL_STATUS_3                           0x0168
+#define WCD934X_SB_FLL_USER_CTL_0                          0x0181
+#define WCD934X_SB_FLL_USER_CTL_1                          0x0182
+#define WCD934X_SB_FLL_USER_CTL_2                          0x0183
+#define WCD934X_SB_FLL_USER_CTL_3                          0x0184
+#define WCD934X_SB_FLL_USER_CTL_4                          0x0185
+#define WCD934X_SB_FLL_USER_CTL_5                          0x0186
+#define WCD934X_SB_FLL_USER_CTL_6                          0x0187
+#define WCD934X_SB_FLL_USER_CTL_7                          0x0188
+#define WCD934X_SB_FLL_USER_CTL_8                          0x0189
+#define WCD934X_SB_FLL_USER_CTL_9                          0x018a
+#define WCD934X_SB_FLL_L_VAL_CTL_0                         0x018b
+#define WCD934X_SB_FLL_L_VAL_CTL_1                         0x018c
+#define WCD934X_SB_FLL_DSM_FRAC_CTL_0                      0x018d
+#define WCD934X_SB_FLL_DSM_FRAC_CTL_1                      0x018e
+#define WCD934X_SB_FLL_CONFIG_CTL_0                        0x018f
+#define WCD934X_SB_FLL_CONFIG_CTL_1                        0x0190
+#define WCD934X_SB_FLL_CONFIG_CTL_2                        0x0191
+#define WCD934X_SB_FLL_CONFIG_CTL_3                        0x0192
+#define WCD934X_SB_FLL_CONFIG_CTL_4                        0x0193
+#define WCD934X_SB_FLL_TEST_CTL_0                          0x0194
+#define WCD934X_SB_FLL_TEST_CTL_1                          0x0195
+#define WCD934X_SB_FLL_TEST_CTL_2                          0x0196
+#define WCD934X_SB_FLL_TEST_CTL_3                          0x0197
+#define WCD934X_SB_FLL_TEST_CTL_4                          0x0198
+#define WCD934X_SB_FLL_TEST_CTL_5                          0x0199
+#define WCD934X_SB_FLL_TEST_CTL_6                          0x019a
+#define WCD934X_SB_FLL_TEST_CTL_7                          0x019b
+#define WCD934X_SB_FLL_FREQ_CTL_0                          0x019c
+#define WCD934X_SB_FLL_FREQ_CTL_1                          0x019d
+#define WCD934X_SB_FLL_FREQ_CTL_2                          0x019e
+#define WCD934X_SB_FLL_FREQ_CTL_3                          0x019f
+#define WCD934X_SB_FLL_SSC_CTL_0                           0x01a0
+#define WCD934X_SB_FLL_SSC_CTL_1                           0x01a1
+#define WCD934X_SB_FLL_SSC_CTL_2                           0x01a2
+#define WCD934X_SB_FLL_SSC_CTL_3                           0x01a3
+#define WCD934X_SB_FLL_FLL_MODE                            0x01a4
+#define WCD934X_SB_FLL_STATUS_0                            0x01a5
+#define WCD934X_SB_FLL_STATUS_1                            0x01a6
+#define WCD934X_SB_FLL_STATUS_2                            0x01a7
+#define WCD934X_SB_FLL_STATUS_3                            0x01a8
+#define WCD934X_PAGE2_PAGE_REGISTER                        0x0200
+#define WCD934X_CPE_SS_CPE_CTL                             0x0201
+#define WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0                0x0202
+#define WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_1                0x0203
+#define WCD934X_CPE_SS_PWR_CPEFLL_CTL                      0x0204
+#define WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0            0x0205
+#define WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1            0x0206
+#define WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_OVERRIDE     0x0207
+#define WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0           0x0208
+#define WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1           0x0209
+#define WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2           0x020a
+#define WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3           0x020b
+#define WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_4           0x020c
+#define WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_5           0x020d
+#define WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN              0x020e
+#define WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL                 0x020f
+#define WCD934X_CPE_SS_SOC_SW_COLLAPSE_OVERRIDE_CTL        0x0210
+#define WCD934X_CPE_SS_SOC_SW_COLLAPSE_OVERRIDE_CTL1       0x0211
+#define WCD934X_CPE_SS_US_BUF_INT_PERIOD                   0x0212
+#define WCD934X_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD           0x0213
+#define WCD934X_CPE_SS_SVA_CFG                             0x0214
+#define WCD934X_CPE_SS_US_CFG                              0x0215
+#define WCD934X_CPE_SS_MAD_CTL                             0x0216
+#define WCD934X_CPE_SS_CPAR_CTL                            0x0217
+#define WCD934X_CPE_SS_DMIC0_CTL                           0x0218
+#define WCD934X_CPE_SS_DMIC1_CTL                           0x0219
+#define WCD934X_CPE_SS_DMIC2_CTL                           0x021a
+#define WCD934X_CPE_SS_DMIC_CFG                            0x021b
+#define WCD934X_CPE_SS_CPAR_CFG                            0x021c
+#define WCD934X_CPE_SS_WDOG_CFG                            0x021d
+#define WCD934X_CPE_SS_BACKUP_INT                          0x021e
+#define WCD934X_CPE_SS_STATUS                              0x021f
+#define WCD934X_CPE_SS_CPE_OCD_CFG                         0x0220
+#define WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A                0x0221
+#define WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B                0x0222
+#define WCD934X_CPE_SS_SS_ERROR_INT_MASK_1A                0x0223
+#define WCD934X_CPE_SS_SS_ERROR_INT_MASK_1B                0x0224
+#define WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0A              0x0225
+#define WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0B              0x0226
+#define WCD934X_CPE_SS_SS_ERROR_INT_STATUS_1A              0x0227
+#define WCD934X_CPE_SS_SS_ERROR_INT_STATUS_1B              0x0228
+#define WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_0A               0x0229
+#define WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_0B               0x022a
+#define WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_1A               0x022b
+#define WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_1B               0x022c
+#define WCD934X_SOC_MAD_MAIN_CTL_1                         0x0281
+#define WCD934X_SOC_MAD_MAIN_CTL_2                         0x0282
+#define WCD934X_SOC_MAD_AUDIO_CTL_1                        0x0283
+#define WCD934X_SOC_MAD_AUDIO_CTL_2                        0x0284
+#define WCD934X_SOC_MAD_AUDIO_CTL_3                        0x0285
+#define WCD934X_SOC_MAD_AUDIO_CTL_4                        0x0286
+#define WCD934X_SOC_MAD_AUDIO_CTL_5                        0x0287
+#define WCD934X_SOC_MAD_AUDIO_CTL_6                        0x0288
+#define WCD934X_SOC_MAD_AUDIO_CTL_7                        0x0289
+#define WCD934X_SOC_MAD_AUDIO_CTL_8                        0x028a
+#define WCD934X_SOC_MAD_AUDIO_IIR_CTL_PTR                  0x028b
+#define WCD934X_SOC_MAD_AUDIO_IIR_CTL_VAL                  0x028c
+#define WCD934X_SOC_MAD_ULTR_CTL_1                         0x028d
+#define WCD934X_SOC_MAD_ULTR_CTL_2                         0x028e
+#define WCD934X_SOC_MAD_ULTR_CTL_3                         0x028f
+#define WCD934X_SOC_MAD_ULTR_CTL_4                         0x0290
+#define WCD934X_SOC_MAD_ULTR_CTL_5                         0x0291
+#define WCD934X_SOC_MAD_ULTR_CTL_6                         0x0292
+#define WCD934X_SOC_MAD_ULTR_CTL_7                         0x0293
+#define WCD934X_SOC_MAD_BEACON_CTL_1                       0x0294
+#define WCD934X_SOC_MAD_BEACON_CTL_2                       0x0295
+#define WCD934X_SOC_MAD_BEACON_CTL_3                       0x0296
+#define WCD934X_SOC_MAD_BEACON_CTL_4                       0x0297
+#define WCD934X_SOC_MAD_BEACON_CTL_5                       0x0298
+#define WCD934X_SOC_MAD_BEACON_CTL_6                       0x0299
+#define WCD934X_SOC_MAD_BEACON_CTL_7                       0x029a
+#define WCD934X_SOC_MAD_BEACON_CTL_8                       0x029b
+#define WCD934X_SOC_MAD_BEACON_IIR_CTL_PTR                 0x029c
+#define WCD934X_SOC_MAD_BEACON_IIR_CTL_VAL                 0x029d
+#define WCD934X_SOC_MAD_INP_SEL                            0x029e
+#define WCD934X_PAGE4_PAGE_REGISTER                        0x0400
+#define WCD934X_INTR_CFG                                   0x0401
+#define WCD934X_INTR_CLR_COMMIT                            0x0402
+#define WCD934X_INTR_PIN1_MASK0                            0x0409
+#define WCD934X_INTR_PIN1_MASK1                            0x040a
+#define WCD934X_INTR_PIN1_MASK2                            0x040b
+#define WCD934X_INTR_PIN1_MASK3                            0x040c
+#define WCD934X_INTR_PIN1_STATUS0                          0x0411
+#define WCD934X_INTR_PIN1_STATUS1                          0x0412
+#define WCD934X_INTR_PIN1_STATUS2                          0x0413
+#define WCD934X_INTR_PIN1_STATUS3                          0x0414
+#define WCD934X_INTR_PIN1_CLEAR0                           0x0419
+#define WCD934X_INTR_PIN1_CLEAR1                           0x041a
+#define WCD934X_INTR_PIN1_CLEAR2                           0x041b
+#define WCD934X_INTR_PIN1_CLEAR3                           0x041c
+#define WCD934X_INTR_PIN2_MASK3                            0x0424
+#define WCD934X_INTR_PIN2_STATUS3                          0x042c
+#define WCD934X_INTR_PIN2_CLEAR3                           0x0434
+#define WCD934X_INTR_CPESS_SUMRY_MASK2                     0x043b
+#define WCD934X_INTR_CPESS_SUMRY_MASK3                     0x043c
+#define WCD934X_INTR_CPESS_SUMRY_STATUS2                   0x0443
+#define WCD934X_INTR_CPESS_SUMRY_STATUS3                   0x0444
+#define WCD934X_INTR_CPESS_SUMRY_CLEAR2                    0x044b
+#define WCD934X_INTR_CPESS_SUMRY_CLEAR3                    0x044c
+#define WCD934X_INTR_LEVEL0                                0x0461
+#define WCD934X_INTR_LEVEL1                                0x0462
+#define WCD934X_INTR_LEVEL2                                0x0463
+#define WCD934X_INTR_LEVEL3                                0x0464
+#define WCD934X_INTR_BYPASS0                               0x0469
+#define WCD934X_INTR_BYPASS1                               0x046a
+#define WCD934X_INTR_BYPASS2                               0x046b
+#define WCD934X_INTR_BYPASS3                               0x046c
+#define WCD934X_INTR_SET0                                  0x0471
+#define WCD934X_INTR_SET1                                  0x0472
+#define WCD934X_INTR_SET2                                  0x0473
+#define WCD934X_INTR_SET3                                  0x0474
+#define WCD934X_INTR_CODEC_MISC_MASK                       0x04b1
+#define WCD934X_INTR_CODEC_MISC_STATUS                     0x04b2
+#define WCD934X_INTR_CODEC_MISC_CLEAR                      0x04b3
+#define WCD934X_PAGE5_PAGE_REGISTER                        0x0500
+#define WCD934X_SLNQ_DIG_DEVICE                            0x0501
+#define WCD934X_SLNQ_DIG_REVISION                          0x0502
+#define WCD934X_SLNQ_DIG_H_COMMAND                         0x0511
+#define WCD934X_SLNQ_DIG_NUMBER_OF_BYTE_MSB                0x0512
+#define WCD934X_SLNQ_DIG_NUMBER_OF_BYTE_LSB                0x0513
+#define WCD934X_SLNQ_DIG_MASTER_ADDRESS_MSB                0x0514
+#define WCD934X_SLNQ_DIG_MASTER_ADDRESS_LSB                0x0515
+#define WCD934X_SLNQ_DIG_SLAVE_ADDRESS_MSB                 0x0516
+#define WCD934X_SLNQ_DIG_SLAVE_ADDRESS_LSB                 0x0517
+#define WCD934X_SLNQ_DIG_TIMER0_INTERRUPT_MSB              0x0518
+#define WCD934X_SLNQ_DIG_TIMER0_INTERRUPT_LSB              0x0519
+#define WCD934X_SLNQ_DIG_TIMER1_INTERRUPT_MSB              0x051a
+#define WCD934X_SLNQ_DIG_TIMER1_INTERRUPT_LSB              0x051b
+#define WCD934X_SLNQ_DIG_TIMER2_INTERRUPT_MSB              0x051c
+#define WCD934X_SLNQ_DIG_TIMER2_INTERRUPT_LSB              0x051d
+#define WCD934X_SLNQ_DIG_COMM_CTL                          0x0520
+#define WCD934X_SLNQ_DIG_FRAME_CTRL                        0x0542
+#define WCD934X_SLNQ_DIG_PDM_2ND_DATA_CH1_2                0x055c
+#define WCD934X_SLNQ_DIG_PDM_2ND_DATA_CH3_4                0x055d
+#define WCD934X_SLNQ_DIG_PDM_2ND_DATA_CH5                  0x055e
+#define WCD934X_SLNQ_DIG_SW_EVENT_RD                       0x0561
+#define WCD934X_SLNQ_DIG_SW_EVENT_CTRL                     0x0562
+#define WCD934X_SLNQ_DIG_PDM_SELECT_1                      0x0563
+#define WCD934X_SLNQ_DIG_PDM_SELECT_2                      0x0564
+#define WCD934X_SLNQ_DIG_PDM_SELECT_3                      0x0565
+#define WCD934X_SLNQ_DIG_PDM_SAMPLING_FREQ                 0x0566
+#define WCD934X_SLNQ_DIG_PDM_DC_CONVERSION_CTL             0x0569
+#define WCD934X_SLNQ_DIG_PDM_DC_CONVERSION_SEL             0x056a
+#define WCD934X_SLNQ_DIG_PDM_DC_CONV_CHA_MSB               0x056b
+#define WCD934X_SLNQ_DIG_PDM_DC_CONV_CHA_LSB               0x056c
+#define WCD934X_SLNQ_DIG_PDM_DC_CONV_CHB_MSB               0x056d
+#define WCD934X_SLNQ_DIG_PDM_DC_CONV_CHB_LSB               0x056e
+#define WCD934X_SLNQ_DIG_RAM_CNTRL                         0x0571
+#define WCD934X_SLNQ_DIG_SRAM_BANK                         0x0572
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_0                       0x0573
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_1                       0x0574
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_2                       0x0575
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_3                       0x0576
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_4                       0x0577
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_5                       0x0578
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_6                       0x0579
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_7                       0x057a
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_8                       0x057b
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_9                       0x057c
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_A                       0x057d
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_B                       0x057e
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_C                       0x057f
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_D                       0x0580
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_E                       0x0581
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_F                       0x0582
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_10                      0x0583
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_11                      0x0584
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_12                      0x0585
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_13                      0x0586
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_14                      0x0587
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_15                      0x0588
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_16                      0x0589
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_17                      0x058a
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_18                      0x058b
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_19                      0x058c
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_1A                      0x058d
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_1B                      0x058e
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_1C                      0x058f
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_1D                      0x0590
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_1E                      0x0591
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_1F                      0x0592
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_20                      0x0593
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_21                      0x0594
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_22                      0x0595
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_23                      0x0596
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_24                      0x0597
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_25                      0x0598
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_26                      0x0599
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_27                      0x059a
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_28                      0x059b
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_29                      0x059c
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_2A                      0x059d
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_2B                      0x059e
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_2C                      0x059f
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_2D                      0x05a0
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_2E                      0x05a1
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_2F                      0x05a2
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_30                      0x05a3
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_31                      0x05a4
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_32                      0x05a5
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_33                      0x05a6
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_34                      0x05a7
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_35                      0x05a8
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_36                      0x05a9
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_37                      0x05aa
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_38                      0x05ab
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_39                      0x05ac
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_3A                      0x05ad
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_3B                      0x05ae
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_3C                      0x05af
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_3D                      0x05b0
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_3E                      0x05b1
+#define WCD934X_SLNQ_DIG_SRAM_BYTE_3F                      0x05b2
+#define WCD934X_SLNQ_DIG_TOP_CTRL1                         0x05b3
+#define WCD934X_SLNQ_DIG_TOP_CTRL2                         0x05b4
+#define WCD934X_SLNQ_DIG_PDM_CTRL                          0x05b5
+#define WCD934X_SLNQ_DIG_PDM_MUTE_CTRL                     0x05b6
+#define WCD934X_SLNQ_DIG_DEC_BYPASS_CTRL                   0x05b7
+#define WCD934X_SLNQ_DIG_DEC_BYPASS_STATUS                 0x05b8
+#define WCD934X_SLNQ_DIG_DEC_BYPASS_FS                     0x05b9
+#define WCD934X_SLNQ_DIG_DEC_BYPASS_IN_SEL                 0x05ba
+#define WCD934X_SLNQ_DIG_GPOUT_ENABLE                      0x05bb
+#define WCD934X_SLNQ_DIG_GPOUT_VAL                         0x05bc
+#define WCD934X_SLNQ_DIG_ANA_INTERRUPT_MASK                0x05be
+#define WCD934X_SLNQ_DIG_ANA_INTERRUPT_STATUS              0x05bf
+#define WCD934X_SLNQ_DIG_ANA_INTERRUPT_CLR                 0x05c0
+#define WCD934X_SLNQ_DIG_IP_TESTING                        0x05c1
+#define WCD934X_SLNQ_DIG_INTERRUPT_CNTRL                   0x05e3
+#define WCD934X_SLNQ_DIG_INTERRUPT_CNT                     0x05e9
+#define WCD934X_SLNQ_DIG_INTERRUPT_CNT_MSB                 0x05eb
+#define WCD934X_SLNQ_DIG_INTERRUPT_CNT_LSB                 0x05ec
+#define WCD934X_SLNQ_DIG_INTERRUPT_MASK0                   0x05f1
+#define WCD934X_SLNQ_DIG_INTERRUPT_MASK1                   0x05f2
+#define WCD934X_SLNQ_DIG_INTERRUPT_MASK2                   0x05f3
+#define WCD934X_SLNQ_DIG_INTERRUPT_MASK3                   0x05f4
+#define WCD934X_SLNQ_DIG_INTERRUPT_MASK4                   0x05f5
+#define WCD934X_SLNQ_DIG_INTERRUPT_STATUS0                 0x05f6
+#define WCD934X_SLNQ_DIG_INTERRUPT_STATUS1                 0x05f7
+#define WCD934X_SLNQ_DIG_INTERRUPT_STATUS2                 0x05f8
+#define WCD934X_SLNQ_DIG_INTERRUPT_STATUS3                 0x05f9
+#define WCD934X_SLNQ_DIG_INTERRUPT_STATUS4                 0x05fa
+#define WCD934X_SLNQ_DIG_INTERRUPT_CLR0                    0x05fb
+#define WCD934X_SLNQ_DIG_INTERRUPT_CLR1                    0x05fc
+#define WCD934X_SLNQ_DIG_INTERRUPT_CLR2                    0x05fd
+#define WCD934X_SLNQ_DIG_INTERRUPT_CLR3                    0x05fe
+#define WCD934X_SLNQ_DIG_INTERRUPT_CLR4                    0x05ff
+#define WCD934X_ANA_PAGE_REGISTER                          0x0600
+#define WCD934X_ANA_BIAS                                   0x0601
+#define WCD934X_ANA_RCO                                    0x0603
+#define WCD934X_ANA_PAGE6_SPARE2                           0x0604
+#define WCD934X_ANA_PAGE6_SPARE3                           0x0605
+#define WCD934X_ANA_BUCK_CTL                               0x0606
+#define WCD934X_ANA_BUCK_STATUS                            0x0607
+#define WCD934X_ANA_RX_SUPPLIES                            0x0608
+#define WCD934X_ANA_HPH                                    0x0609
+#define WCD934X_ANA_EAR                                    0x060a
+#define WCD934X_ANA_LO_1_2                                 0x060b
+#define WCD934X_ANA_MAD_SETUP                              0x060d
+#define WCD934X_ANA_AMIC1                                  0x060e
+#define WCD934X_ANA_AMIC2                                  0x060f
+#define WCD934X_ANA_AMIC3                                  0x0610
+#define WCD934X_ANA_AMIC4                                  0x0611
+#define WCD934X_ANA_MBHC_MECH                              0x0614
+#define WCD934X_ANA_MBHC_ELECT                             0x0615
+#define WCD934X_ANA_MBHC_ZDET                              0x0616
+#define WCD934X_ANA_MBHC_RESULT_1                          0x0617
+#define WCD934X_ANA_MBHC_RESULT_2                          0x0618
+#define WCD934X_ANA_MBHC_RESULT_3                          0x0619
+#define WCD934X_ANA_MBHC_BTN0                              0x061a
+#define WCD934X_ANA_MBHC_BTN1                              0x061b
+#define WCD934X_ANA_MBHC_BTN2                              0x061c
+#define WCD934X_ANA_MBHC_BTN3                              0x061d
+#define WCD934X_ANA_MBHC_BTN4                              0x061e
+#define WCD934X_ANA_MBHC_BTN5                              0x061f
+#define WCD934X_ANA_MBHC_BTN6                              0x0620
+#define WCD934X_ANA_MBHC_BTN7                              0x0621
+#define WCD934X_ANA_MICB1                                  0x0622
+#define WCD934X_ANA_MICB2                                  0x0623
+#define WCD934X_ANA_MICB2_RAMP                             0x0624
+#define WCD934X_ANA_MICB3                                  0x0625
+#define WCD934X_ANA_MICB4                                  0x0626
+#define WCD934X_ANA_VBADC                                  0x0627
+#define WCD934X_BIAS_CTL                                   0x0628
+#define WCD934X_BIAS_VBG_FINE_ADJ                          0x0629
+#define WCD934X_RCO_CTRL_1                                 0x062e
+#define WCD934X_RCO_CTRL_2                                 0x062f
+#define WCD934X_RCO_CAL                                    0x0630
+#define WCD934X_RCO_CAL_1                                  0x0631
+#define WCD934X_RCO_CAL_2                                  0x0632
+#define WCD934X_RCO_TEST_CTRL                              0x0633
+#define WCD934X_RCO_CAL_OUT_1                              0x0634
+#define WCD934X_RCO_CAL_OUT_2                              0x0635
+#define WCD934X_RCO_CAL_OUT_3                              0x0636
+#define WCD934X_RCO_CAL_OUT_4                              0x0637
+#define WCD934X_RCO_CAL_OUT_5                              0x0638
+#define WCD934X_SIDO_MODE_1                                0x063a
+#define WCD934X_SIDO_MODE_2                                0x063b
+#define WCD934X_SIDO_MODE_3                                0x063c
+#define WCD934X_SIDO_MODE_4                                0x063d
+#define WCD934X_SIDO_VCL_1                                 0x063e
+#define WCD934X_SIDO_VCL_2                                 0x063f
+#define WCD934X_SIDO_VCL_3                                 0x0640
+#define WCD934X_SIDO_CCL_1                                 0x0641
+#define WCD934X_SIDO_CCL_2                                 0x0642
+#define WCD934X_SIDO_CCL_3                                 0x0643
+#define WCD934X_SIDO_CCL_4                                 0x0644
+#define WCD934X_SIDO_CCL_5                                 0x0645
+#define WCD934X_SIDO_CCL_6                                 0x0646
+#define WCD934X_SIDO_CCL_7                                 0x0647
+#define WCD934X_SIDO_CCL_8                                 0x0648
+#define WCD934X_SIDO_CCL_9                                 0x0649
+#define WCD934X_SIDO_CCL_10                                0x064a
+#define WCD934X_SIDO_FILTER_1                              0x064b
+#define WCD934X_SIDO_FILTER_2                              0x064c
+#define WCD934X_SIDO_DRIVER_1                              0x064d
+#define WCD934X_SIDO_DRIVER_2                              0x064e
+#define WCD934X_SIDO_DRIVER_3                              0x064f
+#define WCD934X_SIDO_CAL_CODE_EXT_1                        0x0650
+#define WCD934X_SIDO_CAL_CODE_EXT_2                        0x0651
+#define WCD934X_SIDO_CAL_CODE_OUT_1                        0x0652
+#define WCD934X_SIDO_CAL_CODE_OUT_2                        0x0653
+#define WCD934X_SIDO_TEST_1                                0x0654
+#define WCD934X_SIDO_TEST_2                                0x0655
+#define WCD934X_MBHC_CTL_CLK                               0x0656
+#define WCD934X_MBHC_CTL_ANA                               0x0657
+#define WCD934X_MBHC_CTL_SPARE_1                           0x0658
+#define WCD934X_MBHC_CTL_SPARE_2                           0x0659
+#define WCD934X_MBHC_CTL_BCS                               0x065a
+#define WCD934X_MBHC_STATUS_SPARE_1                        0x065b
+#define WCD934X_MBHC_TEST_CTL                              0x065c
+#define WCD934X_VBADC_SUBBLOCK_EN                          0x065d
+#define WCD934X_VBADC_IBIAS_FE                             0x065e
+#define WCD934X_VBADC_BIAS_ADC                             0x065f
+#define WCD934X_VBADC_FE_CTRL                              0x0660
+#define WCD934X_VBADC_ADC_REF                              0x0661
+#define WCD934X_VBADC_ADC_IO                               0x0662
+#define WCD934X_VBADC_ADC_SAR                              0x0663
+#define WCD934X_VBADC_DEBUG                                0x0664
+#define WCD934X_LDOH_MODE                                  0x0667
+#define WCD934X_LDOH_BIAS                                  0x0668
+#define WCD934X_LDOH_STB_LOADS                             0x0669
+#define WCD934X_LDOH_SLOWRAMP                              0x066a
+#define WCD934X_MICB1_TEST_CTL_1                           0x066b
+#define WCD934X_MICB1_TEST_CTL_2                           0x066c
+#define WCD934X_MICB1_TEST_CTL_3                           0x066d
+#define WCD934X_MICB2_TEST_CTL_1                           0x066e
+#define WCD934X_MICB2_TEST_CTL_2                           0x066f
+#define WCD934X_MICB2_TEST_CTL_3                           0x0670
+#define WCD934X_MICB3_TEST_CTL_1                           0x0671
+#define WCD934X_MICB3_TEST_CTL_2                           0x0672
+#define WCD934X_MICB3_TEST_CTL_3                           0x0673
+#define WCD934X_MICB4_TEST_CTL_1                           0x0674
+#define WCD934X_MICB4_TEST_CTL_2                           0x0675
+#define WCD934X_MICB4_TEST_CTL_3                           0x0676
+#define WCD934X_TX_COM_ADC_VCM                             0x0677
+#define WCD934X_TX_COM_BIAS_ATEST                          0x0678
+#define WCD934X_TX_COM_ADC_INT1_IB                         0x0679
+#define WCD934X_TX_COM_ADC_INT2_IB                         0x067a
+#define WCD934X_TX_COM_TXFE_DIV_CTL                        0x067b
+#define WCD934X_TX_COM_TXFE_DIV_START                      0x067c
+#define WCD934X_TX_COM_TXFE_DIV_STOP_9P6M                  0x067d
+#define WCD934X_TX_COM_TXFE_DIV_STOP_12P288M               0x067e
+#define WCD934X_TX_1_2_TEST_EN                             0x067f
+#define WCD934X_TX_1_2_ADC_IB                              0x0680
+#define WCD934X_TX_1_2_ATEST_REFCTL                        0x0681
+#define WCD934X_TX_1_2_TEST_CTL                            0x0682
+#define WCD934X_TX_1_2_TEST_BLK_EN                         0x0683
+#define WCD934X_TX_1_2_TXFE_CLKDIV                         0x0684
+#define WCD934X_TX_1_2_SAR1_ERR                            0x0685
+#define WCD934X_TX_1_2_SAR2_ERR                            0x0686
+#define WCD934X_TX_3_4_TEST_EN                             0x0687
+#define WCD934X_TX_3_4_ADC_IB                              0x0688
+#define WCD934X_TX_3_4_ATEST_REFCTL                        0x0689
+#define WCD934X_TX_3_4_TEST_CTL                            0x068a
+#define WCD934X_TX_3_4_TEST_BLK_EN                         0x068b
+#define WCD934X_TX_3_4_TXFE_CLKDIV                         0x068c
+#define WCD934X_TX_3_4_SAR1_ERR                            0x068d
+#define WCD934X_TX_3_4_SAR2_ERR                            0x068e
+#define WCD934X_CLASSH_MODE_1                              0x0697
+#define WCD934X_CLASSH_MODE_2                              0x0698
+#define WCD934X_CLASSH_MODE_3                              0x0699
+#define WCD934X_CLASSH_CTRL_VCL_1                          0x069a
+#define WCD934X_CLASSH_CTRL_VCL_2                          0x069b
+#define WCD934X_CLASSH_CTRL_CCL_1                          0x069c
+#define WCD934X_CLASSH_CTRL_CCL_2                          0x069d
+#define WCD934X_CLASSH_CTRL_CCL_3                          0x069e
+#define WCD934X_CLASSH_CTRL_CCL_4                          0x069f
+#define WCD934X_CLASSH_CTRL_CCL_5                          0x06a0
+#define WCD934X_CLASSH_BUCK_TMUX_A_D                       0x06a1
+#define WCD934X_CLASSH_BUCK_SW_DRV_CNTL                    0x06a2
+#define WCD934X_CLASSH_SPARE                               0x06a3
+#define WCD934X_FLYBACK_EN                                 0x06a4
+#define WCD934X_FLYBACK_VNEG_CTRL_1                        0x06a5
+#define WCD934X_FLYBACK_VNEG_CTRL_2                        0x06a6
+#define WCD934X_FLYBACK_VNEG_CTRL_3                        0x06a7
+#define WCD934X_FLYBACK_VNEG_CTRL_4                        0x06a8
+#define WCD934X_FLYBACK_VNEG_CTRL_5                        0x06a9
+#define WCD934X_FLYBACK_VNEG_CTRL_6                        0x06aa
+#define WCD934X_FLYBACK_VNEG_CTRL_7                        0x06ab
+#define WCD934X_FLYBACK_VNEG_CTRL_8                        0x06ac
+#define WCD934X_FLYBACK_VNEG_CTRL_9                        0x06ad
+#define WCD934X_FLYBACK_VNEGDAC_CTRL_1                     0x06ae
+#define WCD934X_FLYBACK_VNEGDAC_CTRL_2                     0x06af
+#define WCD934X_FLYBACK_VNEGDAC_CTRL_3                     0x06b0
+#define WCD934X_FLYBACK_CTRL_1                             0x06b1
+#define WCD934X_FLYBACK_TEST_CTL                           0x06b2
+#define WCD934X_RX_AUX_SW_CTL                              0x06b3
+#define WCD934X_RX_PA_AUX_IN_CONN                          0x06b4
+#define WCD934X_RX_TIMER_DIV                               0x06b5
+#define WCD934X_RX_OCP_CTL                                 0x06b6
+#define WCD934X_RX_OCP_COUNT                               0x06b7
+#define WCD934X_RX_BIAS_EAR_DAC                            0x06b8
+#define WCD934X_RX_BIAS_EAR_AMP                            0x06b9
+#define WCD934X_RX_BIAS_HPH_LDO                            0x06ba
+#define WCD934X_RX_BIAS_HPH_PA                             0x06bb
+#define WCD934X_RX_BIAS_HPH_RDACBUFF_CNP2                  0x06bc
+#define WCD934X_RX_BIAS_HPH_RDAC_LDO                       0x06bd
+#define WCD934X_RX_BIAS_HPH_CNP1                           0x06be
+#define WCD934X_RX_BIAS_HPH_LOWPOWER                       0x06bf
+#define WCD934X_RX_BIAS_DIFFLO_PA                          0x06c0
+#define WCD934X_RX_BIAS_DIFFLO_REF                         0x06c1
+#define WCD934X_RX_BIAS_DIFFLO_LDO                         0x06c2
+#define WCD934X_RX_BIAS_SELO_DAC_PA                        0x06c3
+#define WCD934X_RX_BIAS_BUCK_RST                           0x06c4
+#define WCD934X_RX_BIAS_BUCK_VREF_ERRAMP                   0x06c5
+#define WCD934X_RX_BIAS_FLYB_ERRAMP                        0x06c6
+#define WCD934X_RX_BIAS_FLYB_BUFF                          0x06c7
+#define WCD934X_RX_BIAS_FLYB_MID_RST                       0x06c8
+#define WCD934X_HPH_L_STATUS                               0x06c9
+#define WCD934X_HPH_R_STATUS                               0x06ca
+#define WCD934X_HPH_CNP_EN                                 0x06cb
+#define WCD934X_HPH_CNP_WG_CTL                             0x06cc
+#define WCD934X_HPH_CNP_WG_TIME                            0x06cd
+#define WCD934X_HPH_OCP_CTL                                0x06ce
+#define WCD934X_HPH_AUTO_CHOP                              0x06cf
+#define WCD934X_HPH_CHOP_CTL                               0x06d0
+#define WCD934X_HPH_PA_CTL1                                0x06d1
+#define WCD934X_HPH_PA_CTL2                                0x06d2
+#define WCD934X_HPH_L_EN                                   0x06d3
+#define WCD934X_HPH_L_TEST                                 0x06d4
+#define WCD934X_HPH_L_ATEST                                0x06d5
+#define WCD934X_HPH_R_EN                                   0x06d6
+#define WCD934X_HPH_R_TEST                                 0x06d7
+#define WCD934X_HPH_R_ATEST                                0x06d8
+#define WCD934X_HPH_RDAC_CLK_CTL1                          0x06d9
+#define WCD934X_HPH_RDAC_CLK_CTL2                          0x06da
+#define WCD934X_HPH_RDAC_LDO_CTL                           0x06db
+#define WCD934X_HPH_RDAC_CHOP_CLK_LP_CTL                   0x06dc
+#define WCD934X_HPH_REFBUFF_UHQA_CTL                       0x06dd
+#define WCD934X_HPH_REFBUFF_LP_CTL                         0x06de
+#define WCD934X_HPH_L_DAC_CTL                              0x06df
+#define WCD934X_HPH_R_DAC_CTL                              0x06e0
+#define WCD934X_EAR_EN_REG                                 0x06e1
+#define WCD934X_EAR_CMBUFF                                 0x06e2
+#define WCD934X_EAR_ICTL                                   0x06e3
+#define WCD934X_EAR_EN_DBG_CTL                             0x06e4
+#define WCD934X_EAR_CNP                                    0x06e5
+#define WCD934X_EAR_DAC_CTL_ATEST                          0x06e6
+#define WCD934X_EAR_STATUS_REG                             0x06e7
+#define WCD934X_EAR_EAR_MISC                               0x06e8
+#define WCD934X_DIFF_LO_MISC                               0x06e9
+#define WCD934X_DIFF_LO_LO2_COMPANDER                      0x06ea
+#define WCD934X_DIFF_LO_LO1_COMPANDER                      0x06eb
+#define WCD934X_DIFF_LO_COMMON                             0x06ec
+#define WCD934X_DIFF_LO_BYPASS_EN                          0x06ed
+#define WCD934X_DIFF_LO_CNP                                0x06ee
+#define WCD934X_DIFF_LO_CORE_OUT_PROG                      0x06ef
+#define WCD934X_DIFF_LO_LDO_OUT_PROG                       0x06f0
+#define WCD934X_DIFF_LO_COM_SWCAP_REFBUF_FREQ              0x06f1
+#define WCD934X_DIFF_LO_COM_PA_FREQ                        0x06f2
+#define WCD934X_DIFF_LO_RESERVED_REG                       0x06f3
+#define WCD934X_DIFF_LO_LO1_STATUS_1                       0x06f4
+#define WCD934X_DIFF_LO_LO1_STATUS_2                       0x06f5
+#define WCD934X_ANA_NEW_PAGE_REGISTER                      0x0700
+#define WCD934X_HPH_NEW_ANA_HPH2                           0x0701
+#define WCD934X_HPH_NEW_ANA_HPH3                           0x0702
+#define WCD934X_SLNQ_ANA_EN                                0x0703
+#define WCD934X_SLNQ_ANA_STATUS                            0x0704
+#define WCD934X_SLNQ_ANA_LDO_CONFIG                        0x0705
+#define WCD934X_SLNQ_ANA_LDO_OCP_CONFIG                    0x0706
+#define WCD934X_SLNQ_ANA_TX_LDO_CONFIG                     0x0707
+#define WCD934X_SLNQ_ANA_TX_DRV_CONFIG                     0x0708
+#define WCD934X_SLNQ_ANA_RX_CONFIG_1                       0x0709
+#define WCD934X_SLNQ_ANA_RX_CONFIG_2                       0x070a
+#define WCD934X_SLNQ_ANA_PLL_ENABLES                       0x070b
+#define WCD934X_SLNQ_ANA_PLL_PRESET                        0x070c
+#define WCD934X_SLNQ_ANA_PLL_STATUS                        0x070d
+#define WCD934X_CLK_SYS_PLL_ENABLES                        0x070e
+#define WCD934X_CLK_SYS_PLL_PRESET                         0x070f
+#define WCD934X_CLK_SYS_PLL_STATUS                         0x0710
+#define WCD934X_CLK_SYS_MCLK_PRG                           0x0711
+#define WCD934X_CLK_SYS_MCLK2_PRG1                         0x0712
+#define WCD934X_CLK_SYS_MCLK2_PRG2                         0x0713
+#define WCD934X_CLK_SYS_XO_PRG                             0x0714
+#define WCD934X_CLK_SYS_XO_CAP_XTP                         0x0715
+#define WCD934X_CLK_SYS_XO_CAP_XTM                         0x0716
+#define WCD934X_BOOST_BST_EN_DLY                           0x0718
+#define WCD934X_BOOST_CTRL_ILIM                            0x0719
+#define WCD934X_BOOST_VOUT_SETTING                         0x071a
+#define WCD934X_SIDO_NEW_VOUT_A_STARTUP                    0x071b
+#define WCD934X_SIDO_NEW_VOUT_D_STARTUP                    0x071c
+#define WCD934X_SIDO_NEW_VOUT_D_FREQ1                      0x071d
+#define WCD934X_SIDO_NEW_VOUT_D_FREQ2                      0x071e
+#define WCD934X_MBHC_NEW_ELECT_REM_CLAMP_CTL               0x071f
+#define WCD934X_MBHC_NEW_CTL_1                             0x0720
+#define WCD934X_MBHC_NEW_CTL_2                             0x0721
+#define WCD934X_MBHC_NEW_PLUG_DETECT_CTL                   0x0722
+#define WCD934X_MBHC_NEW_ZDET_ANA_CTL                      0x0723
+#define WCD934X_MBHC_NEW_ZDET_RAMP_CTL                     0x0724
+#define WCD934X_MBHC_NEW_FSM_STATUS                        0x0725
+#define WCD934X_MBHC_NEW_ADC_RESULT                        0x0726
+#define WCD934X_TX_NEW_AMIC_4_5_SEL                        0x0727
+#define WCD934X_VBADC_NEW_ADC_MODE                         0x072f
+#define WCD934X_VBADC_NEW_ADC_DOUTMSB                      0x0730
+#define WCD934X_VBADC_NEW_ADC_DOUTLSB                      0x0731
+#define WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL                  0x0732
+#define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL                   0x0733
+#define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L                 0x0733
+#define WCD934X_HPH_NEW_INT_RDAC_VREF_CTL                  0x0734
+#define WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL              0x0735
+#define WCD934X_HPH_NEW_INT_RDAC_MISC1                     0x0736
+#define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R                 0x0736
+#define WCD934X_HPH_NEW_INT_PA_MISC1                       0x0737
+#define WCD934X_HPH_NEW_INT_PA_MISC2                       0x0738
+#define WCD934X_HPH_NEW_INT_PA_RDAC_MISC                   0x0739
+#define WCD934X_HPH_NEW_INT_HPH_TIMER1                     0x073a
+#define WCD934X_HPH_NEW_INT_HPH_TIMER2                     0x073b
+#define WCD934X_HPH_NEW_INT_HPH_TIMER3                     0x073c
+#define WCD934X_HPH_NEW_INT_HPH_TIMER4                     0x073d
+#define WCD934X_HPH_NEW_INT_PA_RDAC_MISC2                  0x073e
+#define WCD934X_HPH_NEW_INT_PA_RDAC_MISC3                  0x073f
+#define WCD934X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI            0x0745
+#define WCD934X_RX_NEW_INT_HPH_RDAC_BIAS_ULP               0x0746
+#define WCD934X_RX_NEW_INT_HPH_RDAC_LDO_LP                 0x0747
+#define WCD934X_SLNQ_INT_ANA_INT_LDO_TEST                  0x074b
+#define WCD934X_SLNQ_INT_ANA_INT_LDO_DEBUG_1               0x074c
+#define WCD934X_SLNQ_INT_ANA_INT_LDO_DEBUG_2               0x074d
+#define WCD934X_SLNQ_INT_ANA_INT_TX_LDO_TEST               0x074e
+#define WCD934X_SLNQ_INT_ANA_INT_TX_DRV_TEST               0x074f
+#define WCD934X_SLNQ_INT_ANA_INT_RX_TEST                   0x0750
+#define WCD934X_SLNQ_INT_ANA_INT_RX_TEST_STATUS            0x0751
+#define WCD934X_SLNQ_INT_ANA_INT_RX_DEBUG_1                0x0752
+#define WCD934X_SLNQ_INT_ANA_INT_RX_DEBUG_2                0x0753
+#define WCD934X_SLNQ_INT_ANA_INT_CLK_CTRL                  0x0754
+#define WCD934X_SLNQ_INT_ANA_INT_RESERVED_1                0x0755
+#define WCD934X_SLNQ_INT_ANA_INT_RESERVED_2                0x0756
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_POST_DIV_REG0         0x0757
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_POST_DIV_REG1         0x0758
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_REF_DIV_REG0          0x0759
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_REF_DIV_REG1          0x075a
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_FILTER_REG0           0x075b
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_FILTER_REG1           0x075c
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_L_VAL                 0x075d
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_M_VAL                 0x075e
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_N_VAL                 0x075f
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_TEST_REG0             0x0760
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_PFD_CP_DSM_PROG       0x0761
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_VCO_PROG              0x0762
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_TEST_REG1             0x0763
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_LDO_LOCK_CFG          0x0764
+#define WCD934X_SLNQ_INT_ANA_INT_PLL_DIG_LOCK_DET_CFG      0x0765
+#define WCD934X_CLK_SYS_INT_POST_DIV_REG0                  0x076c
+#define WCD934X_CLK_SYS_INT_POST_DIV_REG1                  0x076d
+#define WCD934X_CLK_SYS_INT_REF_DIV_REG0                   0x076e
+#define WCD934X_CLK_SYS_INT_REF_DIV_REG1                   0x076f
+#define WCD934X_CLK_SYS_INT_FILTER_REG0                    0x0770
+#define WCD934X_CLK_SYS_INT_FILTER_REG1                    0x0771
+#define WCD934X_CLK_SYS_INT_PLL_L_VAL                      0x0772
+#define WCD934X_CLK_SYS_INT_PLL_M_VAL                      0x0773
+#define WCD934X_CLK_SYS_INT_PLL_N_VAL                      0x0774
+#define WCD934X_CLK_SYS_INT_TEST_REG0                      0x0775
+#define WCD934X_CLK_SYS_INT_PFD_CP_DSM_PROG                0x0776
+#define WCD934X_CLK_SYS_INT_VCO_PROG                       0x0777
+#define WCD934X_CLK_SYS_INT_TEST_REG1                      0x0778
+#define WCD934X_CLK_SYS_INT_LDO_LOCK_CFG                   0x0779
+#define WCD934X_CLK_SYS_INT_DIG_LOCK_DET_CFG               0x077a
+#define WCD934X_CLK_SYS_INT_CLK_TEST1                      0x077b
+#define WCD934X_CLK_SYS_INT_CLK_TEST2                      0x077c
+#define WCD934X_CLK_SYS_INT_CLK_TEST3                      0x077d
+#define WCD934X_CLK_SYS_INT_XO_TEST1                       0x077e
+#define WCD934X_CLK_SYS_INT_XO_TEST2                       0x077f
+#define WCD934X_BOOST_INT_VCOMP_HYST                       0x0787
+#define WCD934X_BOOST_INT_VLOOP_FILTER                     0x0788
+#define WCD934X_BOOST_INT_CTRL_IDELTA                      0x0789
+#define WCD934X_BOOST_INT_CTRL_ILIM_STARTUP                0x078a
+#define WCD934X_BOOST_INT_CTRL_MIN_ONTIME                  0x078b
+#define WCD934X_BOOST_INT_CTRL_MAX_ONTIME                  0x078c
+#define WCD934X_BOOST_INT_CTRL_TIMING                      0x078d
+#define WCD934X_BOOST_INT_TMUX_A_D                         0x078e
+#define WCD934X_BOOST_INT_SW_DRV_CNTL                      0x078f
+#define WCD934X_BOOST_INT_SPARE1                           0x0790
+#define WCD934X_BOOST_INT_SPARE2                           0x0791
+#define WCD934X_SIDO_NEW_INT_RAMP_STATUS                   0x0796
+#define WCD934X_SIDO_NEW_INT_SPARE_1                       0x0797
+#define WCD934X_SIDO_NEW_INT_DEBUG_VOUT_SETTING_A          0x0798
+#define WCD934X_SIDO_NEW_INT_DEBUG_VOUT_SETTING_D          0x0799
+#define WCD934X_SIDO_NEW_INT_RAMP_INC_WAIT                 0x079a
+#define WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_CTL             0x079b
+#define WCD934X_SIDO_NEW_INT_RAMP_IBLEED_CTL               0x079c
+#define WCD934X_SIDO_NEW_INT_DEBUG_CPROVR_TEST             0x079d
+#define WCD934X_SIDO_NEW_INT_RAMP_CTL_A                    0x079e
+#define WCD934X_SIDO_NEW_INT_RAMP_CTL_D                    0x079f
+#define WCD934X_SIDO_NEW_INT_RAMP_TIMEOUT_PERIOD           0x07a0
+#define WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_SETTING1        0x07a1
+#define WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_SETTING2        0x07a2
+#define WCD934X_SIDO_NEW_INT_DYNAMIC_IPEAK_SETTING3        0x07a3
+#define WCD934X_SIDO_NEW_INT_HIGH_ACCU_MODE_SEL1           0x07a4
+#define WCD934X_SIDO_NEW_INT_HIGH_ACCU_MODE_SEL2           0x07a5
+#define WCD934X_MBHC_NEW_INT_SLNQ_HPF                      0x07af
+#define WCD934X_MBHC_NEW_INT_SLNQ_REF                      0x07b0
+#define WCD934X_MBHC_NEW_INT_SLNQ_COMP                     0x07b1
+#define WCD934X_MBHC_NEW_INT_SPARE_2                       0x07b2
+#define WCD934X_PAGE10_PAGE_REGISTER                       0x0a00
+#define WCD934X_CDC_ANC0_CLK_RESET_CTL                     0x0a01
+#define WCD934X_CDC_ANC0_MODE_1_CTL                        0x0a02
+#define WCD934X_CDC_ANC0_MODE_2_CTL                        0x0a03
+#define WCD934X_CDC_ANC0_FF_SHIFT                          0x0a04
+#define WCD934X_CDC_ANC0_FB_SHIFT                          0x0a05
+#define WCD934X_CDC_ANC0_LPF_FF_A_CTL                      0x0a06
+#define WCD934X_CDC_ANC0_LPF_FF_B_CTL                      0x0a07
+#define WCD934X_CDC_ANC0_LPF_FB_CTL                        0x0a08
+#define WCD934X_CDC_ANC0_SMLPF_CTL                         0x0a09
+#define WCD934X_CDC_ANC0_DCFLT_SHIFT_CTL                   0x0a0a
+#define WCD934X_CDC_ANC0_IIR_ADAPT_CTL                     0x0a0b
+#define WCD934X_CDC_ANC0_IIR_COEFF_1_CTL                   0x0a0c
+#define WCD934X_CDC_ANC0_IIR_COEFF_2_CTL                   0x0a0d
+#define WCD934X_CDC_ANC0_FF_A_GAIN_CTL                     0x0a0e
+#define WCD934X_CDC_ANC0_FF_B_GAIN_CTL                     0x0a0f
+#define WCD934X_CDC_ANC0_FB_GAIN_CTL                       0x0a10
+#define WCD934X_CDC_ANC0_RC_COMMON_CTL                     0x0a11
+#define WCD934X_CDC_ANC0_FIFO_COMMON_CTL                   0x0a13
+#define WCD934X_CDC_ANC0_RC0_STATUS_FMIN_CNTR              0x0a14
+#define WCD934X_CDC_ANC0_RC1_STATUS_FMIN_CNTR              0x0a15
+#define WCD934X_CDC_ANC0_RC0_STATUS_FMAX_CNTR              0x0a16
+#define WCD934X_CDC_ANC0_RC1_STATUS_FMAX_CNTR              0x0a17
+#define WCD934X_CDC_ANC0_STATUS_FIFO                       0x0a18
+#define WCD934X_CDC_ANC1_CLK_RESET_CTL                     0x0a19
+#define WCD934X_CDC_ANC1_MODE_1_CTL                        0x0a1a
+#define WCD934X_CDC_ANC1_MODE_2_CTL                        0x0a1b
+#define WCD934X_CDC_ANC1_FF_SHIFT                          0x0a1c
+#define WCD934X_CDC_ANC1_FB_SHIFT                          0x0a1d
+#define WCD934X_CDC_ANC1_LPF_FF_A_CTL                      0x0a1e
+#define WCD934X_CDC_ANC1_LPF_FF_B_CTL                      0x0a1f
+#define WCD934X_CDC_ANC1_LPF_FB_CTL                        0x0a20
+#define WCD934X_CDC_ANC1_SMLPF_CTL                         0x0a21
+#define WCD934X_CDC_ANC1_DCFLT_SHIFT_CTL                   0x0a22
+#define WCD934X_CDC_ANC1_IIR_ADAPT_CTL                     0x0a23
+#define WCD934X_CDC_ANC1_IIR_COEFF_1_CTL                   0x0a24
+#define WCD934X_CDC_ANC1_IIR_COEFF_2_CTL                   0x0a25
+#define WCD934X_CDC_ANC1_FF_A_GAIN_CTL                     0x0a26
+#define WCD934X_CDC_ANC1_FF_B_GAIN_CTL                     0x0a27
+#define WCD934X_CDC_ANC1_FB_GAIN_CTL                       0x0a28
+#define WCD934X_CDC_ANC1_RC_COMMON_CTL                     0x0a29
+#define WCD934X_CDC_ANC1_FIFO_COMMON_CTL                   0x0a2b
+#define WCD934X_CDC_ANC1_RC0_STATUS_FMIN_CNTR              0x0a2c
+#define WCD934X_CDC_ANC1_RC1_STATUS_FMIN_CNTR              0x0a2d
+#define WCD934X_CDC_ANC1_RC0_STATUS_FMAX_CNTR              0x0a2e
+#define WCD934X_CDC_ANC1_RC1_STATUS_FMAX_CNTR              0x0a2f
+#define WCD934X_CDC_ANC1_STATUS_FIFO                       0x0a30
+#define WCD934X_CDC_TX0_TX_PATH_CTL                        0x0a31
+#define WCD934X_CDC_TX0_TX_PATH_CFG0                       0x0a32
+#define WCD934X_CDC_TX0_TX_PATH_CFG1                       0x0a33
+#define WCD934X_CDC_TX0_TX_VOL_CTL                         0x0a34
+#define WCD934X_CDC_TX0_TX_PATH_192_CTL                    0x0a35
+#define WCD934X_CDC_TX0_TX_PATH_192_CFG                    0x0a36
+#define WCD934X_CDC_TX0_TX_PATH_SEC0                       0x0a37
+#define WCD934X_CDC_TX0_TX_PATH_SEC1                       0x0a38
+#define WCD934X_CDC_TX0_TX_PATH_SEC2                       0x0a39
+#define WCD934X_CDC_TX0_TX_PATH_SEC3                       0x0a3a
+#define WCD934X_CDC_TX0_TX_PATH_SEC4                       0x0a3b
+#define WCD934X_CDC_TX0_TX_PATH_SEC5                       0x0a3c
+#define WCD934X_CDC_TX0_TX_PATH_SEC6                       0x0a3d
+#define WCD934X_CDC_TX0_TX_PATH_SEC7                       0x0a3e
+#define WCD934X_CDC_TX1_TX_PATH_CTL                        0x0a41
+#define WCD934X_CDC_TX1_TX_PATH_CFG0                       0x0a42
+#define WCD934X_CDC_TX1_TX_PATH_CFG1                       0x0a43
+#define WCD934X_CDC_TX1_TX_VOL_CTL                         0x0a44
+#define WCD934X_CDC_TX1_TX_PATH_192_CTL                    0x0a45
+#define WCD934X_CDC_TX1_TX_PATH_192_CFG                    0x0a46
+#define WCD934X_CDC_TX1_TX_PATH_SEC0                       0x0a47
+#define WCD934X_CDC_TX1_TX_PATH_SEC1                       0x0a48
+#define WCD934X_CDC_TX1_TX_PATH_SEC2                       0x0a49
+#define WCD934X_CDC_TX1_TX_PATH_SEC3                       0x0a4a
+#define WCD934X_CDC_TX1_TX_PATH_SEC4                       0x0a4b
+#define WCD934X_CDC_TX1_TX_PATH_SEC5                       0x0a4c
+#define WCD934X_CDC_TX1_TX_PATH_SEC6                       0x0a4d
+#define WCD934X_CDC_TX2_TX_PATH_CTL                        0x0a51
+#define WCD934X_CDC_TX2_TX_PATH_CFG0                       0x0a52
+#define WCD934X_CDC_TX2_TX_PATH_CFG1                       0x0a53
+#define WCD934X_CDC_TX2_TX_VOL_CTL                         0x0a54
+#define WCD934X_CDC_TX2_TX_PATH_192_CTL                    0x0a55
+#define WCD934X_CDC_TX2_TX_PATH_192_CFG                    0x0a56
+#define WCD934X_CDC_TX2_TX_PATH_SEC0                       0x0a57
+#define WCD934X_CDC_TX2_TX_PATH_SEC1                       0x0a58
+#define WCD934X_CDC_TX2_TX_PATH_SEC2                       0x0a59
+#define WCD934X_CDC_TX2_TX_PATH_SEC3                       0x0a5a
+#define WCD934X_CDC_TX2_TX_PATH_SEC4                       0x0a5b
+#define WCD934X_CDC_TX2_TX_PATH_SEC5                       0x0a5c
+#define WCD934X_CDC_TX2_TX_PATH_SEC6                       0x0a5d
+#define WCD934X_CDC_TX3_TX_PATH_CTL                        0x0a61
+#define WCD934X_CDC_TX3_TX_PATH_CFG0                       0x0a62
+#define WCD934X_CDC_TX3_TX_PATH_CFG1                       0x0a63
+#define WCD934X_CDC_TX3_TX_VOL_CTL                         0x0a64
+#define WCD934X_CDC_TX3_TX_PATH_192_CTL                    0x0a65
+#define WCD934X_CDC_TX3_TX_PATH_192_CFG                    0x0a66
+#define WCD934X_CDC_TX3_TX_PATH_SEC0                       0x0a67
+#define WCD934X_CDC_TX3_TX_PATH_SEC1                       0x0a68
+#define WCD934X_CDC_TX3_TX_PATH_SEC2                       0x0a69
+#define WCD934X_CDC_TX3_TX_PATH_SEC3                       0x0a6a
+#define WCD934X_CDC_TX3_TX_PATH_SEC4                       0x0a6b
+#define WCD934X_CDC_TX3_TX_PATH_SEC5                       0x0a6c
+#define WCD934X_CDC_TX3_TX_PATH_SEC6                       0x0a6d
+#define WCD934X_CDC_TX4_TX_PATH_CTL                        0x0a71
+#define WCD934X_CDC_TX4_TX_PATH_CFG0                       0x0a72
+#define WCD934X_CDC_TX4_TX_PATH_CFG1                       0x0a73
+#define WCD934X_CDC_TX4_TX_VOL_CTL                         0x0a74
+#define WCD934X_CDC_TX4_TX_PATH_192_CTL                    0x0a75
+#define WCD934X_CDC_TX4_TX_PATH_192_CFG                    0x0a76
+#define WCD934X_CDC_TX4_TX_PATH_SEC0                       0x0a77
+#define WCD934X_CDC_TX4_TX_PATH_SEC1                       0x0a78
+#define WCD934X_CDC_TX4_TX_PATH_SEC2                       0x0a79
+#define WCD934X_CDC_TX4_TX_PATH_SEC3                       0x0a7a
+#define WCD934X_CDC_TX4_TX_PATH_SEC4                       0x0a7b
+#define WCD934X_CDC_TX4_TX_PATH_SEC5                       0x0a7c
+#define WCD934X_CDC_TX4_TX_PATH_SEC6                       0x0a7d
+#define WCD934X_CDC_TX5_TX_PATH_CTL                        0x0a81
+#define WCD934X_CDC_TX5_TX_PATH_CFG0                       0x0a82
+#define WCD934X_CDC_TX5_TX_PATH_CFG1                       0x0a83
+#define WCD934X_CDC_TX5_TX_VOL_CTL                         0x0a84
+#define WCD934X_CDC_TX5_TX_PATH_192_CTL                    0x0a85
+#define WCD934X_CDC_TX5_TX_PATH_192_CFG                    0x0a86
+#define WCD934X_CDC_TX5_TX_PATH_SEC0                       0x0a87
+#define WCD934X_CDC_TX5_TX_PATH_SEC1                       0x0a88
+#define WCD934X_CDC_TX5_TX_PATH_SEC2                       0x0a89
+#define WCD934X_CDC_TX5_TX_PATH_SEC3                       0x0a8a
+#define WCD934X_CDC_TX5_TX_PATH_SEC4                       0x0a8b
+#define WCD934X_CDC_TX5_TX_PATH_SEC5                       0x0a8c
+#define WCD934X_CDC_TX5_TX_PATH_SEC6                       0x0a8d
+#define WCD934X_CDC_TX6_TX_PATH_CTL                        0x0a91
+#define WCD934X_CDC_TX6_TX_PATH_CFG0                       0x0a92
+#define WCD934X_CDC_TX6_TX_PATH_CFG1                       0x0a93
+#define WCD934X_CDC_TX6_TX_VOL_CTL                         0x0a94
+#define WCD934X_CDC_TX6_TX_PATH_192_CTL                    0x0a95
+#define WCD934X_CDC_TX6_TX_PATH_192_CFG                    0x0a96
+#define WCD934X_CDC_TX6_TX_PATH_SEC0                       0x0a97
+#define WCD934X_CDC_TX6_TX_PATH_SEC1                       0x0a98
+#define WCD934X_CDC_TX6_TX_PATH_SEC2                       0x0a99
+#define WCD934X_CDC_TX6_TX_PATH_SEC3                       0x0a9a
+#define WCD934X_CDC_TX6_TX_PATH_SEC4                       0x0a9b
+#define WCD934X_CDC_TX6_TX_PATH_SEC5                       0x0a9c
+#define WCD934X_CDC_TX6_TX_PATH_SEC6                       0x0a9d
+#define WCD934X_CDC_TX7_TX_PATH_CTL                        0x0aa1
+#define WCD934X_CDC_TX7_TX_PATH_CFG0                       0x0aa2
+#define WCD934X_CDC_TX7_TX_PATH_CFG1                       0x0aa3
+#define WCD934X_CDC_TX7_TX_VOL_CTL                         0x0aa4
+#define WCD934X_CDC_TX7_TX_PATH_192_CTL                    0x0aa5
+#define WCD934X_CDC_TX7_TX_PATH_192_CFG                    0x0aa6
+#define WCD934X_CDC_TX7_TX_PATH_SEC0                       0x0aa7
+#define WCD934X_CDC_TX7_TX_PATH_SEC1                       0x0aa8
+#define WCD934X_CDC_TX7_TX_PATH_SEC2                       0x0aa9
+#define WCD934X_CDC_TX7_TX_PATH_SEC3                       0x0aaa
+#define WCD934X_CDC_TX7_TX_PATH_SEC4                       0x0aab
+#define WCD934X_CDC_TX7_TX_PATH_SEC5                       0x0aac
+#define WCD934X_CDC_TX7_TX_PATH_SEC6                       0x0aad
+#define WCD934X_CDC_TX8_TX_PATH_CTL                        0x0ab1
+#define WCD934X_CDC_TX8_TX_PATH_CFG0                       0x0ab2
+#define WCD934X_CDC_TX8_TX_PATH_CFG1                       0x0ab3
+#define WCD934X_CDC_TX8_TX_VOL_CTL                         0x0ab4
+#define WCD934X_CDC_TX8_TX_PATH_192_CTL                    0x0ab5
+#define WCD934X_CDC_TX8_TX_PATH_192_CFG                    0x0ab6
+#define WCD934X_CDC_TX8_TX_PATH_SEC0                       0x0ab7
+#define WCD934X_CDC_TX8_TX_PATH_SEC1                       0x0ab8
+#define WCD934X_CDC_TX8_TX_PATH_SEC2                       0x0ab9
+#define WCD934X_CDC_TX8_TX_PATH_SEC3                       0x0aba
+#define WCD934X_CDC_TX8_TX_PATH_SEC4                       0x0abb
+#define WCD934X_CDC_TX8_TX_PATH_SEC5                       0x0abc
+#define WCD934X_CDC_TX8_TX_PATH_SEC6                       0x0abd
+#define WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL                 0x0ac2
+#define WCD934X_CDC_TX9_SPKR_PROT_PATH_CFG0                0x0ac3
+#define WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL                0x0ac6
+#define WCD934X_CDC_TX10_SPKR_PROT_PATH_CFG0               0x0ac7
+#define WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL                0x0aca
+#define WCD934X_CDC_TX11_SPKR_PROT_PATH_CFG0               0x0acb
+#define WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL                0x0ace
+#define WCD934X_CDC_TX12_SPKR_PROT_PATH_CFG0               0x0acf
+#define WCD934X_PAGE11_PAGE_REGISTER                       0x0b00
+#define WCD934X_CDC_COMPANDER1_CTL0                        0x0b01
+#define WCD934X_CDC_COMPANDER1_CTL1                        0x0b02
+#define WCD934X_CDC_COMPANDER1_CTL2                        0x0b03
+#define WCD934X_CDC_COMPANDER1_CTL3                        0x0b04
+#define WCD934X_CDC_COMPANDER1_CTL4                        0x0b05
+#define WCD934X_CDC_COMPANDER1_CTL5                        0x0b06
+#define WCD934X_CDC_COMPANDER1_CTL6                        0x0b07
+#define WCD934X_CDC_COMPANDER1_CTL7                        0x0b08
+#define WCD934X_CDC_COMPANDER2_CTL0                        0x0b09
+#define WCD934X_CDC_COMPANDER2_CTL1                        0x0b0a
+#define WCD934X_CDC_COMPANDER2_CTL2                        0x0b0b
+#define WCD934X_CDC_COMPANDER2_CTL3                        0x0b0c
+#define WCD934X_CDC_COMPANDER2_CTL4                        0x0b0d
+#define WCD934X_CDC_COMPANDER2_CTL5                        0x0b0e
+#define WCD934X_CDC_COMPANDER2_CTL6                        0x0b0f
+#define WCD934X_CDC_COMPANDER2_CTL7                        0x0b10
+#define WCD934X_CDC_COMPANDER3_CTL0                        0x0b11
+#define WCD934X_CDC_COMPANDER3_CTL1                        0x0b12
+#define WCD934X_CDC_COMPANDER3_CTL2                        0x0b13
+#define WCD934X_CDC_COMPANDER3_CTL3                        0x0b14
+#define WCD934X_CDC_COMPANDER3_CTL4                        0x0b15
+#define WCD934X_CDC_COMPANDER3_CTL5                        0x0b16
+#define WCD934X_CDC_COMPANDER3_CTL6                        0x0b17
+#define WCD934X_CDC_COMPANDER3_CTL7                        0x0b18
+#define WCD934X_CDC_COMPANDER4_CTL0                        0x0b19
+#define WCD934X_CDC_COMPANDER4_CTL1                        0x0b1a
+#define WCD934X_CDC_COMPANDER4_CTL2                        0x0b1b
+#define WCD934X_CDC_COMPANDER4_CTL3                        0x0b1c
+#define WCD934X_CDC_COMPANDER4_CTL4                        0x0b1d
+#define WCD934X_CDC_COMPANDER4_CTL5                        0x0b1e
+#define WCD934X_CDC_COMPANDER4_CTL6                        0x0b1f
+#define WCD934X_CDC_COMPANDER4_CTL7                        0x0b20
+#define WCD934X_CDC_COMPANDER7_CTL0                        0x0b31
+#define WCD934X_CDC_COMPANDER7_CTL1                        0x0b32
+#define WCD934X_CDC_COMPANDER7_CTL2                        0x0b33
+#define WCD934X_CDC_COMPANDER7_CTL3                        0x0b34
+#define WCD934X_CDC_COMPANDER7_CTL4                        0x0b35
+#define WCD934X_CDC_COMPANDER7_CTL5                        0x0b36
+#define WCD934X_CDC_COMPANDER7_CTL6                        0x0b37
+#define WCD934X_CDC_COMPANDER7_CTL7                        0x0b38
+#define WCD934X_CDC_COMPANDER8_CTL0                        0x0b39
+#define WCD934X_CDC_COMPANDER8_CTL1                        0x0b3a
+#define WCD934X_CDC_COMPANDER8_CTL2                        0x0b3b
+#define WCD934X_CDC_COMPANDER8_CTL3                        0x0b3c
+#define WCD934X_CDC_COMPANDER8_CTL4                        0x0b3d
+#define WCD934X_CDC_COMPANDER8_CTL5                        0x0b3e
+#define WCD934X_CDC_COMPANDER8_CTL6                        0x0b3f
+#define WCD934X_CDC_COMPANDER8_CTL7                        0x0b40
+#define WCD934X_CDC_RX0_RX_PATH_CTL                        0x0b41
+#define WCD934X_CDC_RX0_RX_PATH_CFG0                       0x0b42
+#define WCD934X_CDC_RX0_RX_PATH_CFG1                       0x0b43
+#define WCD934X_CDC_RX0_RX_PATH_CFG2                       0x0b44
+#define WCD934X_CDC_RX0_RX_VOL_CTL                         0x0b45
+#define WCD934X_CDC_RX0_RX_PATH_MIX_CTL                    0x0b46
+#define WCD934X_CDC_RX0_RX_PATH_MIX_CFG                    0x0b47
+#define WCD934X_CDC_RX0_RX_VOL_MIX_CTL                     0x0b48
+#define WCD934X_CDC_RX0_RX_PATH_SEC0                       0x0b49
+#define WCD934X_CDC_RX0_RX_PATH_SEC1                       0x0b4a
+#define WCD934X_CDC_RX0_RX_PATH_SEC2                       0x0b4b
+#define WCD934X_CDC_RX0_RX_PATH_SEC3                       0x0b4c
+#define WCD934X_CDC_RX0_RX_PATH_SEC5                       0x0b4e
+#define WCD934X_CDC_RX0_RX_PATH_SEC6                       0x0b4f
+#define WCD934X_CDC_RX0_RX_PATH_SEC7                       0x0b50
+#define WCD934X_CDC_RX0_RX_PATH_MIX_SEC0                   0x0b51
+#define WCD934X_CDC_RX0_RX_PATH_MIX_SEC1                   0x0b52
+#define WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL                 0x0b53
+#define WCD934X_CDC_RX1_RX_PATH_CTL                        0x0b55
+#define WCD934X_CDC_RX1_RX_PATH_CFG0                       0x0b56
+#define WCD934X_CDC_RX1_RX_PATH_CFG1                       0x0b57
+#define WCD934X_CDC_RX1_RX_PATH_CFG2                       0x0b58
+#define WCD934X_CDC_RX1_RX_VOL_CTL                         0x0b59
+#define WCD934X_CDC_RX1_RX_PATH_MIX_CTL                    0x0b5a
+#define WCD934X_CDC_RX1_RX_PATH_MIX_CFG                    0x0b5b
+#define WCD934X_CDC_RX1_RX_VOL_MIX_CTL                     0x0b5c
+#define WCD934X_CDC_RX1_RX_PATH_SEC0                       0x0b5d
+#define WCD934X_CDC_RX1_RX_PATH_SEC1                       0x0b5e
+#define WCD934X_CDC_RX1_RX_PATH_SEC2                       0x0b5f
+#define WCD934X_CDC_RX1_RX_PATH_SEC3                       0x0b60
+#define WCD934X_CDC_RX1_RX_PATH_SEC4                       0x0b61
+#define WCD934X_CDC_RX1_RX_PATH_SEC5                       0x0b62
+#define WCD934X_CDC_RX1_RX_PATH_SEC6                       0x0b63
+#define WCD934X_CDC_RX1_RX_PATH_SEC7                       0x0b64
+#define WCD934X_CDC_RX1_RX_PATH_MIX_SEC0                   0x0b65
+#define WCD934X_CDC_RX1_RX_PATH_MIX_SEC1                   0x0b66
+#define WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL                 0x0b67
+#define WCD934X_CDC_RX2_RX_PATH_CTL                        0x0b69
+#define WCD934X_CDC_RX2_RX_PATH_CFG0                       0x0b6a
+#define WCD934X_CDC_RX2_RX_PATH_CFG1                       0x0b6b
+#define WCD934X_CDC_RX2_RX_PATH_CFG2                       0x0b6c
+#define WCD934X_CDC_RX2_RX_VOL_CTL                         0x0b6d
+#define WCD934X_CDC_RX2_RX_PATH_MIX_CTL                    0x0b6e
+#define WCD934X_CDC_RX2_RX_PATH_MIX_CFG                    0x0b6f
+#define WCD934X_CDC_RX2_RX_VOL_MIX_CTL                     0x0b70
+#define WCD934X_CDC_RX2_RX_PATH_SEC0                       0x0b71
+#define WCD934X_CDC_RX2_RX_PATH_SEC1                       0x0b72
+#define WCD934X_CDC_RX2_RX_PATH_SEC2                       0x0b73
+#define WCD934X_CDC_RX2_RX_PATH_SEC3                       0x0b74
+#define WCD934X_CDC_RX2_RX_PATH_SEC4                       0x0b75
+#define WCD934X_CDC_RX2_RX_PATH_SEC5                       0x0b76
+#define WCD934X_CDC_RX2_RX_PATH_SEC6                       0x0b77
+#define WCD934X_CDC_RX2_RX_PATH_SEC7                       0x0b78
+#define WCD934X_CDC_RX2_RX_PATH_MIX_SEC0                   0x0b79
+#define WCD934X_CDC_RX2_RX_PATH_MIX_SEC1                   0x0b7a
+#define WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL                 0x0b7b
+#define WCD934X_CDC_RX3_RX_PATH_CTL                        0x0b7d
+#define WCD934X_CDC_RX3_RX_PATH_CFG0                       0x0b7e
+#define WCD934X_CDC_RX3_RX_PATH_CFG1                       0x0b7f
+#define WCD934X_CDC_RX3_RX_PATH_CFG2                       0x0b80
+#define WCD934X_CDC_RX3_RX_VOL_CTL                         0x0b81
+#define WCD934X_CDC_RX3_RX_PATH_MIX_CTL                    0x0b82
+#define WCD934X_CDC_RX3_RX_PATH_MIX_CFG                    0x0b83
+#define WCD934X_CDC_RX3_RX_VOL_MIX_CTL                     0x0b84
+#define WCD934X_CDC_RX3_RX_PATH_SEC0                       0x0b85
+#define WCD934X_CDC_RX3_RX_PATH_SEC1                       0x0b86
+#define WCD934X_CDC_RX3_RX_PATH_SEC2                       0x0b87
+#define WCD934X_CDC_RX3_RX_PATH_SEC3                       0x0b88
+#define WCD934X_CDC_RX3_RX_PATH_SEC5                       0x0b8a
+#define WCD934X_CDC_RX3_RX_PATH_SEC6                       0x0b8b
+#define WCD934X_CDC_RX3_RX_PATH_SEC7                       0x0b8c
+#define WCD934X_CDC_RX3_RX_PATH_MIX_SEC0                   0x0b8d
+#define WCD934X_CDC_RX3_RX_PATH_MIX_SEC1                   0x0b8e
+#define WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL                 0x0b8f
+#define WCD934X_CDC_RX4_RX_PATH_CTL                        0x0b91
+#define WCD934X_CDC_RX4_RX_PATH_CFG0                       0x0b92
+#define WCD934X_CDC_RX4_RX_PATH_CFG1                       0x0b93
+#define WCD934X_CDC_RX4_RX_PATH_CFG2                       0x0b94
+#define WCD934X_CDC_RX4_RX_VOL_CTL                         0x0b95
+#define WCD934X_CDC_RX4_RX_PATH_MIX_CTL                    0x0b96
+#define WCD934X_CDC_RX4_RX_PATH_MIX_CFG                    0x0b97
+#define WCD934X_CDC_RX4_RX_VOL_MIX_CTL                     0x0b98
+#define WCD934X_CDC_RX4_RX_PATH_SEC0                       0x0b99
+#define WCD934X_CDC_RX4_RX_PATH_SEC1                       0x0b9a
+#define WCD934X_CDC_RX4_RX_PATH_SEC2                       0x0b9b
+#define WCD934X_CDC_RX4_RX_PATH_SEC3                       0x0b9c
+#define WCD934X_CDC_RX4_RX_PATH_SEC5                       0x0b9e
+#define WCD934X_CDC_RX4_RX_PATH_SEC6                       0x0b9f
+#define WCD934X_CDC_RX4_RX_PATH_SEC7                       0x0ba0
+#define WCD934X_CDC_RX4_RX_PATH_MIX_SEC0                   0x0ba1
+#define WCD934X_CDC_RX4_RX_PATH_MIX_SEC1                   0x0ba2
+#define WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL                 0x0ba3
+#define WCD934X_CDC_RX7_RX_PATH_CTL                        0x0bcd
+#define WCD934X_CDC_RX7_RX_PATH_CFG0                       0x0bce
+#define WCD934X_CDC_RX7_RX_PATH_CFG1                       0x0bcf
+#define WCD934X_CDC_RX7_RX_PATH_CFG2                       0x0bd0
+#define WCD934X_CDC_RX7_RX_VOL_CTL                         0x0bd1
+#define WCD934X_CDC_RX7_RX_PATH_MIX_CTL                    0x0bd2
+#define WCD934X_CDC_RX7_RX_PATH_MIX_CFG                    0x0bd3
+#define WCD934X_CDC_RX7_RX_VOL_MIX_CTL                     0x0bd4
+#define WCD934X_CDC_RX7_RX_PATH_SEC0                       0x0bd5
+#define WCD934X_CDC_RX7_RX_PATH_SEC1                       0x0bd6
+#define WCD934X_CDC_RX7_RX_PATH_SEC2                       0x0bd7
+#define WCD934X_CDC_RX7_RX_PATH_SEC3                       0x0bd8
+#define WCD934X_CDC_RX7_RX_PATH_SEC5                       0x0bda
+#define WCD934X_CDC_RX7_RX_PATH_SEC6                       0x0bdb
+#define WCD934X_CDC_RX7_RX_PATH_SEC7                       0x0bdc
+#define WCD934X_CDC_RX7_RX_PATH_MIX_SEC0                   0x0bdd
+#define WCD934X_CDC_RX7_RX_PATH_MIX_SEC1                   0x0bde
+#define WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL                 0x0bdf
+#define WCD934X_CDC_RX8_RX_PATH_CTL                        0x0be1
+#define WCD934X_CDC_RX8_RX_PATH_CFG0                       0x0be2
+#define WCD934X_CDC_RX8_RX_PATH_CFG1                       0x0be3
+#define WCD934X_CDC_RX8_RX_PATH_CFG2                       0x0be4
+#define WCD934X_CDC_RX8_RX_VOL_CTL                         0x0be5
+#define WCD934X_CDC_RX8_RX_PATH_MIX_CTL                    0x0be6
+#define WCD934X_CDC_RX8_RX_PATH_MIX_CFG                    0x0be7
+#define WCD934X_CDC_RX8_RX_VOL_MIX_CTL                     0x0be8
+#define WCD934X_CDC_RX8_RX_PATH_SEC0                       0x0be9
+#define WCD934X_CDC_RX8_RX_PATH_SEC1                       0x0bea
+#define WCD934X_CDC_RX8_RX_PATH_SEC2                       0x0beb
+#define WCD934X_CDC_RX8_RX_PATH_SEC3                       0x0bec
+#define WCD934X_CDC_RX8_RX_PATH_SEC5                       0x0bee
+#define WCD934X_CDC_RX8_RX_PATH_SEC6                       0x0bef
+#define WCD934X_CDC_RX8_RX_PATH_SEC7                       0x0bf0
+#define WCD934X_CDC_RX8_RX_PATH_MIX_SEC0                   0x0bf1
+#define WCD934X_CDC_RX8_RX_PATH_MIX_SEC1                   0x0bf2
+#define WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL                 0x0bf3
+#define WCD934X_PAGE12_PAGE_REGISTER                       0x0c00
+#define WCD934X_CDC_CLSH_CRC                               0x0c01
+#define WCD934X_CDC_CLSH_DLY_CTRL                          0x0c02
+#define WCD934X_CDC_CLSH_DECAY_CTRL                        0x0c03
+#define WCD934X_CDC_CLSH_HPH_V_PA                          0x0c04
+#define WCD934X_CDC_CLSH_EAR_V_PA                          0x0c05
+#define WCD934X_CDC_CLSH_HPH_V_HD                          0x0c06
+#define WCD934X_CDC_CLSH_EAR_V_HD                          0x0c07
+#define WCD934X_CDC_CLSH_K1_MSB                            0x0c08
+#define WCD934X_CDC_CLSH_K1_LSB                            0x0c09
+#define WCD934X_CDC_CLSH_K2_MSB                            0x0c0a
+#define WCD934X_CDC_CLSH_K2_LSB                            0x0c0b
+#define WCD934X_CDC_CLSH_IDLE_CTRL                         0x0c0c
+#define WCD934X_CDC_CLSH_IDLE_HPH                          0x0c0d
+#define WCD934X_CDC_CLSH_IDLE_EAR                          0x0c0e
+#define WCD934X_CDC_CLSH_TEST0                             0x0c0f
+#define WCD934X_CDC_CLSH_TEST1                             0x0c10
+#define WCD934X_CDC_CLSH_OVR_VREF                          0x0c11
+#define WCD934X_CDC_BOOST0_BOOST_PATH_CTL                  0x0c19
+#define WCD934X_CDC_BOOST0_BOOST_CTL                       0x0c1a
+#define WCD934X_CDC_BOOST0_BOOST_CFG1                      0x0c1b
+#define WCD934X_CDC_BOOST0_BOOST_CFG2                      0x0c1c
+#define WCD934X_CDC_BOOST1_BOOST_PATH_CTL                  0x0c21
+#define WCD934X_CDC_BOOST1_BOOST_CTL                       0x0c22
+#define WCD934X_CDC_BOOST1_BOOST_CFG1                      0x0c23
+#define WCD934X_CDC_BOOST1_BOOST_CFG2                      0x0c24
+#define WCD934X_CDC_VBAT_VBAT_PATH_CTL                     0x0c3d
+#define WCD934X_CDC_VBAT_VBAT_CFG                          0x0c3e
+#define WCD934X_CDC_VBAT_VBAT_ADC_CAL1                     0x0c3f
+#define WCD934X_CDC_VBAT_VBAT_ADC_CAL2                     0x0c40
+#define WCD934X_CDC_VBAT_VBAT_ADC_CAL3                     0x0c41
+#define WCD934X_CDC_VBAT_VBAT_PK_EST1                      0x0c42
+#define WCD934X_CDC_VBAT_VBAT_PK_EST2                      0x0c43
+#define WCD934X_CDC_VBAT_VBAT_PK_EST3                      0x0c44
+#define WCD934X_CDC_VBAT_VBAT_RF_PROC1                     0x0c45
+#define WCD934X_CDC_VBAT_VBAT_RF_PROC2                     0x0c46
+#define WCD934X_CDC_VBAT_VBAT_TAC1                         0x0c47
+#define WCD934X_CDC_VBAT_VBAT_TAC2                         0x0c48
+#define WCD934X_CDC_VBAT_VBAT_TAC3                         0x0c49
+#define WCD934X_CDC_VBAT_VBAT_TAC4                         0x0c4a
+#define WCD934X_CDC_VBAT_VBAT_GAIN_UPD1                    0x0c4b
+#define WCD934X_CDC_VBAT_VBAT_GAIN_UPD2                    0x0c4c
+#define WCD934X_CDC_VBAT_VBAT_GAIN_UPD3                    0x0c4d
+#define WCD934X_CDC_VBAT_VBAT_GAIN_UPD4                    0x0c4e
+#define WCD934X_CDC_VBAT_VBAT_DEBUG1                       0x0c4f
+#define WCD934X_CDC_VBAT_VBAT_GAIN_UPD_MON                 0x0c50
+#define WCD934X_CDC_VBAT_VBAT_GAIN_MON_VAL                 0x0c51
+#define WCD934X_CDC_VBAT_VBAT_BAN                          0x0c52
+#define WCD934X_MIXING_ASRC0_CLK_RST_CTL                   0x0c55
+#define WCD934X_MIXING_ASRC0_CTL0                          0x0c56
+#define WCD934X_MIXING_ASRC0_CTL1                          0x0c57
+#define WCD934X_MIXING_ASRC0_FIFO_CTL                      0x0c58
+#define WCD934X_MIXING_ASRC0_STATUS_FMIN_CNTR_LSB          0x0c59
+#define WCD934X_MIXING_ASRC0_STATUS_FMIN_CNTR_MSB          0x0c5a
+#define WCD934X_MIXING_ASRC0_STATUS_FMAX_CNTR_LSB          0x0c5b
+#define WCD934X_MIXING_ASRC0_STATUS_FMAX_CNTR_MSB          0x0c5c
+#define WCD934X_MIXING_ASRC0_STATUS_FIFO                   0x0c5d
+#define WCD934X_MIXING_ASRC1_CLK_RST_CTL                   0x0c61
+#define WCD934X_MIXING_ASRC1_CTL0                          0x0c62
+#define WCD934X_MIXING_ASRC1_CTL1                          0x0c63
+#define WCD934X_MIXING_ASRC1_FIFO_CTL                      0x0c64
+#define WCD934X_MIXING_ASRC1_STATUS_FMIN_CNTR_LSB          0x0c65
+#define WCD934X_MIXING_ASRC1_STATUS_FMIN_CNTR_MSB          0x0c66
+#define WCD934X_MIXING_ASRC1_STATUS_FMAX_CNTR_LSB          0x0c67
+#define WCD934X_MIXING_ASRC1_STATUS_FMAX_CNTR_MSB          0x0c68
+#define WCD934X_MIXING_ASRC1_STATUS_FIFO                   0x0c69
+#define WCD934X_MIXING_ASRC2_CLK_RST_CTL                   0x0c6d
+#define WCD934X_MIXING_ASRC2_CTL0                          0x0c6e
+#define WCD934X_MIXING_ASRC2_CTL1                          0x0c6f
+#define WCD934X_MIXING_ASRC2_FIFO_CTL                      0x0c70
+#define WCD934X_MIXING_ASRC2_STATUS_FMIN_CNTR_LSB          0x0c71
+#define WCD934X_MIXING_ASRC2_STATUS_FMIN_CNTR_MSB          0x0c72
+#define WCD934X_MIXING_ASRC2_STATUS_FMAX_CNTR_LSB          0x0c73
+#define WCD934X_MIXING_ASRC2_STATUS_FMAX_CNTR_MSB          0x0c74
+#define WCD934X_MIXING_ASRC2_STATUS_FIFO                   0x0c75
+#define WCD934X_MIXING_ASRC3_CLK_RST_CTL                   0x0c79
+#define WCD934X_MIXING_ASRC3_CTL0                          0x0c7a
+#define WCD934X_MIXING_ASRC3_CTL1                          0x0c7b
+#define WCD934X_MIXING_ASRC3_FIFO_CTL                      0x0c7c
+#define WCD934X_MIXING_ASRC3_STATUS_FMIN_CNTR_LSB          0x0c7d
+#define WCD934X_MIXING_ASRC3_STATUS_FMIN_CNTR_MSB          0x0c7e
+#define WCD934X_MIXING_ASRC3_STATUS_FMAX_CNTR_LSB          0x0c7f
+#define WCD934X_MIXING_ASRC3_STATUS_FMAX_CNTR_MSB          0x0c80
+#define WCD934X_MIXING_ASRC3_STATUS_FIFO                   0x0c81
+#define WCD934X_SWR_AHB_BRIDGE_WR_DATA_0                   0x0c85
+#define WCD934X_SWR_AHB_BRIDGE_WR_DATA_1                   0x0c86
+#define WCD934X_SWR_AHB_BRIDGE_WR_DATA_2                   0x0c87
+#define WCD934X_SWR_AHB_BRIDGE_WR_DATA_3                   0x0c88
+#define WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0                   0x0c89
+#define WCD934X_SWR_AHB_BRIDGE_WR_ADDR_1                   0x0c8a
+#define WCD934X_SWR_AHB_BRIDGE_WR_ADDR_2                   0x0c8b
+#define WCD934X_SWR_AHB_BRIDGE_WR_ADDR_3                   0x0c8c
+#define WCD934X_SWR_AHB_BRIDGE_RD_ADDR_0                   0x0c8d
+#define WCD934X_SWR_AHB_BRIDGE_RD_ADDR_1                   0x0c8e
+#define WCD934X_SWR_AHB_BRIDGE_RD_ADDR_2                   0x0c8f
+#define WCD934X_SWR_AHB_BRIDGE_RD_ADDR_3                   0x0c90
+#define WCD934X_SWR_AHB_BRIDGE_RD_DATA_0                   0x0c91
+#define WCD934X_SWR_AHB_BRIDGE_RD_DATA_1                   0x0c92
+#define WCD934X_SWR_AHB_BRIDGE_RD_DATA_2                   0x0c93
+#define WCD934X_SWR_AHB_BRIDGE_RD_DATA_3                   0x0c94
+#define WCD934X_SWR_AHB_BRIDGE_ACCESS_CFG                  0x0c95
+#define WCD934X_SWR_AHB_BRIDGE_ACCESS_STATUS               0x0c96
+#define WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL          0x0cb5
+#define WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CFG1         0x0cb6
+#define WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL          0x0cb9
+#define WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CFG1         0x0cba
+#define WCD934X_SIDETONE_ASRC0_CLK_RST_CTL                 0x0cbd
+#define WCD934X_SIDETONE_ASRC0_CTL0                        0x0cbe
+#define WCD934X_SIDETONE_ASRC0_CTL1                        0x0cbf
+#define WCD934X_SIDETONE_ASRC0_FIFO_CTL                    0x0cc0
+#define WCD934X_SIDETONE_ASRC0_STATUS_FMIN_CNTR_LSB        0x0cc1
+#define WCD934X_SIDETONE_ASRC0_STATUS_FMIN_CNTR_MSB        0x0cc2
+#define WCD934X_SIDETONE_ASRC0_STATUS_FMAX_CNTR_LSB        0x0cc3
+#define WCD934X_SIDETONE_ASRC0_STATUS_FMAX_CNTR_MSB        0x0cc4
+#define WCD934X_SIDETONE_ASRC0_STATUS_FIFO                 0x0cc5
+#define WCD934X_SIDETONE_ASRC1_CLK_RST_CTL                 0x0cc9
+#define WCD934X_SIDETONE_ASRC1_CTL0                        0x0cca
+#define WCD934X_SIDETONE_ASRC1_CTL1                        0x0ccb
+#define WCD934X_SIDETONE_ASRC1_FIFO_CTL                    0x0ccc
+#define WCD934X_SIDETONE_ASRC1_STATUS_FMIN_CNTR_LSB        0x0ccd
+#define WCD934X_SIDETONE_ASRC1_STATUS_FMIN_CNTR_MSB        0x0cce
+#define WCD934X_SIDETONE_ASRC1_STATUS_FMAX_CNTR_LSB        0x0ccf
+#define WCD934X_SIDETONE_ASRC1_STATUS_FMAX_CNTR_MSB        0x0cd0
+#define WCD934X_SIDETONE_ASRC1_STATUS_FIFO                 0x0cd1
+#define WCD934X_EC_REF_HQ0_EC_REF_HQ_PATH_CTL              0x0cd5
+#define WCD934X_EC_REF_HQ0_EC_REF_HQ_CFG0                  0x0cd6
+#define WCD934X_EC_REF_HQ1_EC_REF_HQ_PATH_CTL              0x0cdd
+#define WCD934X_EC_REF_HQ1_EC_REF_HQ_CFG0                  0x0cde
+#define WCD934X_EC_ASRC0_CLK_RST_CTL                       0x0ce5
+#define WCD934X_EC_ASRC0_CTL0                              0x0ce6
+#define WCD934X_EC_ASRC0_CTL1                              0x0ce7
+#define WCD934X_EC_ASRC0_FIFO_CTL                          0x0ce8
+#define WCD934X_EC_ASRC0_STATUS_FMIN_CNTR_LSB              0x0ce9
+#define WCD934X_EC_ASRC0_STATUS_FMIN_CNTR_MSB              0x0cea
+#define WCD934X_EC_ASRC0_STATUS_FMAX_CNTR_LSB              0x0ceb
+#define WCD934X_EC_ASRC0_STATUS_FMAX_CNTR_MSB              0x0cec
+#define WCD934X_EC_ASRC0_STATUS_FIFO                       0x0ced
+#define WCD934X_EC_ASRC1_CLK_RST_CTL                       0x0cf1
+#define WCD934X_EC_ASRC1_CTL0                              0x0cf2
+#define WCD934X_EC_ASRC1_CTL1                              0x0cf3
+#define WCD934X_EC_ASRC1_FIFO_CTL                          0x0cf4
+#define WCD934X_EC_ASRC1_STATUS_FMIN_CNTR_LSB              0x0cf5
+#define WCD934X_EC_ASRC1_STATUS_FMIN_CNTR_MSB              0x0cf6
+#define WCD934X_EC_ASRC1_STATUS_FMAX_CNTR_LSB              0x0cf7
+#define WCD934X_EC_ASRC1_STATUS_FMAX_CNTR_MSB              0x0cf8
+#define WCD934X_EC_ASRC1_STATUS_FIFO                       0x0cf9
+#define WCD934X_PAGE13_PAGE_REGISTER                       0x0d00
+#define WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0                0x0d01
+#define WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1                0x0d02
+#define WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0                0x0d03
+#define WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1                0x0d04
+#define WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0                0x0d05
+#define WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1                0x0d06
+#define WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0                0x0d07
+#define WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1                0x0d08
+#define WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0                0x0d09
+#define WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1                0x0d0a
+#define WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0                0x0d0f
+#define WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1                0x0d10
+#define WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0                0x0d11
+#define WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1                0x0d12
+#define WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG0                 0x0d13
+#define WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG1                 0x0d14
+#define WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG2                 0x0d15
+#define WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG3                 0x0d16
+#define WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG4                 0x0d17
+#define WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0           0x0d18
+#define WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1           0x0d19
+#define WCD934X_CDC_RX_INP_MUX_ANC_CFG0                    0x0d1a
+#define WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0            0x0d1b
+#define WCD934X_CDC_RX_INP_MUX_EC_REF_HQ_CFG0              0x0d1c
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0               0x0d1d
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1               0x0d1e
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0               0x0d1f
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1               0x0d20
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0               0x0d21
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1               0x0d22
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0               0x0d23
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1               0x0d25
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0               0x0d26
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0               0x0d27
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0               0x0d28
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0               0x0d29
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0               0x0d2a
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX10_CFG0              0x0d2b
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX11_CFG0              0x0d2c
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX12_CFG0              0x0d2d
+#define WCD934X_CDC_TX_INP_MUX_ADC_MUX13_CFG0              0x0d2e
+#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0     0x0d31
+#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1     0x0d32
+#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2     0x0d33
+#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3     0x0d34
+#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0     0x0d35
+#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1     0x0d36
+#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2     0x0d37
+#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3     0x0d38
+#define WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0                  0x0d3a
+#define WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1                  0x0d3b
+#define WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2                  0x0d3c
+#define WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3                  0x0d3d
+#define WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL              0x0d41
+#define WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL            0x0d42
+#define WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL               0x0d43
+#define WCD934X_CDC_CLK_RST_CTRL_DSD_CONTROL               0x0d44
+#define WCD934X_CDC_CLK_RST_CTRL_ASRC_SHARE_CONTROL        0x0d45
+#define WCD934X_CDC_CLK_RST_CTRL_GFM_CONTROL               0x0d46
+#define WCD934X_CDC_PROX_DETECT_PROX_CTL                   0x0d49
+#define WCD934X_CDC_PROX_DETECT_PROX_POLL_PERIOD0          0x0d4a
+#define WCD934X_CDC_PROX_DETECT_PROX_POLL_PERIOD1          0x0d4b
+#define WCD934X_CDC_PROX_DETECT_PROX_SIG_PATTERN_LSB       0x0d4c
+#define WCD934X_CDC_PROX_DETECT_PROX_SIG_PATTERN_MSB       0x0d4d
+#define WCD934X_CDC_PROX_DETECT_PROX_STATUS                0x0d4e
+#define WCD934X_CDC_PROX_DETECT_PROX_TEST_CTRL             0x0d4f
+#define WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB         0x0d50
+#define WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB         0x0d51
+#define WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_LSB_RD      0x0d52
+#define WCD934X_CDC_PROX_DETECT_PROX_TEST_BUFF_MSB_RD      0x0d53
+#define WCD934X_CDC_PROX_DETECT_PROX_CTL_REPEAT_PAT        0x0d54
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_PATH_CTL             0x0d55
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL          0x0d56
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL          0x0d57
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL          0x0d58
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL          0x0d59
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B5_CTL          0x0d5a
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B6_CTL          0x0d5b
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B7_CTL          0x0d5c
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B8_CTL          0x0d5d
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_CTL                  0x0d5e
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL       0x0d5f
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL          0x0d60
+#define WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL          0x0d61
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_PATH_CTL             0x0d65
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL          0x0d66
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL          0x0d67
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL          0x0d68
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL          0x0d69
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B5_CTL          0x0d6a
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B6_CTL          0x0d6b
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B7_CTL          0x0d6c
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B8_CTL          0x0d6d
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_CTL                  0x0d6e
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL       0x0d6f
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_COEF_B1_CTL          0x0d70
+#define WCD934X_CDC_SIDETONE_IIR1_IIR_COEF_B2_CTL          0x0d71
+#define WCD934X_CDC_TOP_TOP_CFG0                           0x0d81
+#define WCD934X_CDC_TOP_TOP_CFG1                           0x0d82
+#define WCD934X_CDC_TOP_TOP_CFG7                           0x0d88
+#define WCD934X_CDC_TOP_HPHL_COMP_WR_LSB                   0x0d89
+#define WCD934X_CDC_TOP_HPHL_COMP_WR_MSB                   0x0d8a
+#define WCD934X_CDC_TOP_HPHL_COMP_LUT                      0x0d8b
+#define WCD934X_CDC_TOP_HPHL_COMP_RD_LSB                   0x0d8c
+#define WCD934X_CDC_TOP_HPHL_COMP_RD_MSB                   0x0d8d
+#define WCD934X_CDC_TOP_HPHR_COMP_WR_LSB                   0x0d8e
+#define WCD934X_CDC_TOP_HPHR_COMP_WR_MSB                   0x0d8f
+#define WCD934X_CDC_TOP_HPHR_COMP_LUT                      0x0d90
+#define WCD934X_CDC_TOP_HPHR_COMP_RD_LSB                   0x0d91
+#define WCD934X_CDC_TOP_HPHR_COMP_RD_MSB                   0x0d92
+#define WCD934X_CDC_TOP_DIFFL_COMP_WR_LSB                  0x0d93
+#define WCD934X_CDC_TOP_DIFFL_COMP_WR_MSB                  0x0d94
+#define WCD934X_CDC_TOP_DIFFL_COMP_LUT                     0x0d95
+#define WCD934X_CDC_TOP_DIFFL_COMP_RD_LSB                  0x0d96
+#define WCD934X_CDC_TOP_DIFFL_COMP_RD_MSB                  0x0d97
+#define WCD934X_CDC_TOP_DIFFR_COMP_WR_LSB                  0x0d98
+#define WCD934X_CDC_TOP_DIFFR_COMP_WR_MSB                  0x0d99
+#define WCD934X_CDC_TOP_DIFFR_COMP_LUT                     0x0d9a
+#define WCD934X_CDC_TOP_DIFFR_COMP_RD_LSB                  0x0d9b
+#define WCD934X_CDC_TOP_DIFFR_COMP_RD_MSB                  0x0d9c
+#define WCD934X_CDC_DSD0_PATH_CTL                          0x0db1
+#define WCD934X_CDC_DSD0_CFG0                              0x0db2
+#define WCD934X_CDC_DSD0_CFG1                              0x0db3
+#define WCD934X_CDC_DSD0_CFG2                              0x0db4
+#define WCD934X_CDC_DSD0_CFG3                              0x0db5
+#define WCD934X_CDC_DSD0_CFG4                              0x0db6
+#define WCD934X_CDC_DSD0_CFG5                              0x0db7
+#define WCD934X_CDC_DSD1_PATH_CTL                          0x0dc1
+#define WCD934X_CDC_DSD1_CFG0                              0x0dc2
+#define WCD934X_CDC_DSD1_CFG1                              0x0dc3
+#define WCD934X_CDC_DSD1_CFG2                              0x0dc4
+#define WCD934X_CDC_DSD1_CFG3                              0x0dc5
+#define WCD934X_CDC_DSD1_CFG4                              0x0dc6
+#define WCD934X_CDC_DSD1_CFG5                              0x0dc7
+#define WCD934X_CDC_RX_IDLE_DET_PATH_CTL                   0x0dd1
+#define WCD934X_CDC_RX_IDLE_DET_CFG0                       0x0dd2
+#define WCD934X_CDC_RX_IDLE_DET_CFG1                       0x0dd3
+#define WCD934X_CDC_RX_IDLE_DET_CFG2                       0x0dd4
+#define WCD934X_CDC_RX_IDLE_DET_CFG3                       0x0dd5
+#define WCD934X_PAGE14_PAGE_REGISTER                       0x0e00
+#define WCD934X_CDC_RATE_EST0_RE_CLK_RST_CTL               0x0e01
+#define WCD934X_CDC_RATE_EST0_RE_CTL                       0x0e02
+#define WCD934X_CDC_RATE_EST0_RE_PULSE_SUPR_CTL            0x0e03
+#define WCD934X_CDC_RATE_EST0_RE_TIMER                     0x0e04
+#define WCD934X_CDC_RATE_EST0_RE_BW_SW                     0x0e05
+#define WCD934X_CDC_RATE_EST0_RE_THRESH                    0x0e06
+#define WCD934X_CDC_RATE_EST0_RE_STATUS                    0x0e07
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_CTRL                 0x0e09
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_TIMER2               0x0e0c
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW1           0x0e0d
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW2           0x0e0e
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW3           0x0e0f
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW4           0x0e10
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_OFFSET_BW5           0x0e11
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW1            0x0e12
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW2            0x0e13
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW3            0x0e14
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW4            0x0e15
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_LIMIT_BW5            0x0e16
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW1          0x0e17
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW2          0x0e18
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW3          0x0e19
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW4          0x0e1a
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_LIMITD1_BW5          0x0e1b
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW1             0x0e1c
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW2             0x0e1d
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW3             0x0e1e
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW4             0x0e1f
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_HYST_BW5             0x0e20
+#define WCD934X_CDC_RATE_EST0_RE_RMAX_DIAG                 0x0e21
+#define WCD934X_CDC_RATE_EST0_RE_RMIN_DIAG                 0x0e22
+#define WCD934X_CDC_RATE_EST0_RE_PH_DET                    0x0e23
+#define WCD934X_CDC_RATE_EST0_RE_DIAG_CLR                  0x0e24
+#define WCD934X_CDC_RATE_EST0_RE_MB_SW_STATE               0x0e25
+#define WCD934X_CDC_RATE_EST0_RE_MAST_DIAG_STATE           0x0e26
+#define WCD934X_CDC_RATE_EST0_RE_RATE_OUT_7_0              0x0e27
+#define WCD934X_CDC_RATE_EST0_RE_RATE_OUT_15_8             0x0e28
+#define WCD934X_CDC_RATE_EST0_RE_RATE_OUT_23_16            0x0e29
+#define WCD934X_CDC_RATE_EST0_RE_RATE_OUT_31_24            0x0e2a
+#define WCD934X_CDC_RATE_EST0_RE_RATE_OUT_39_32            0x0e2b
+#define WCD934X_CDC_RATE_EST0_RE_RATE_OUT_40_43            0x0e2c
+#define WCD934X_CDC_RATE_EST1_RE_CLK_RST_CTL               0x0e31
+#define WCD934X_CDC_RATE_EST1_RE_CTL                       0x0e32
+#define WCD934X_CDC_RATE_EST1_RE_PULSE_SUPR_CTL            0x0e33
+#define WCD934X_CDC_RATE_EST1_RE_TIMER                     0x0e34
+#define WCD934X_CDC_RATE_EST1_RE_BW_SW                     0x0e35
+#define WCD934X_CDC_RATE_EST1_RE_THRESH                    0x0e36
+#define WCD934X_CDC_RATE_EST1_RE_STATUS                    0x0e37
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_CTRL                 0x0e39
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_TIMER2               0x0e3c
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW1           0x0e3d
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW2           0x0e3e
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW3           0x0e3f
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW4           0x0e40
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_OFFSET_BW5           0x0e41
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW1            0x0e42
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW2            0x0e43
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW3            0x0e44
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW4            0x0e45
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_LIMIT_BW5            0x0e46
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW1          0x0e47
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW2          0x0e48
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW3          0x0e49
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW4          0x0e4a
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_LIMITD1_BW5          0x0e4b
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW1             0x0e4c
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW2             0x0e4d
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW3             0x0e4e
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW4             0x0e4f
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_HYST_BW5             0x0e50
+#define WCD934X_CDC_RATE_EST1_RE_RMAX_DIAG                 0x0e51
+#define WCD934X_CDC_RATE_EST1_RE_RMIN_DIAG                 0x0e52
+#define WCD934X_CDC_RATE_EST1_RE_PH_DET                    0x0e53
+#define WCD934X_CDC_RATE_EST1_RE_DIAG_CLR                  0x0e54
+#define WCD934X_CDC_RATE_EST1_RE_MB_SW_STATE               0x0e55
+#define WCD934X_CDC_RATE_EST1_RE_MAST_DIAG_STATE           0x0e56
+#define WCD934X_CDC_RATE_EST1_RE_RATE_OUT_7_0              0x0e57
+#define WCD934X_CDC_RATE_EST1_RE_RATE_OUT_15_8             0x0e58
+#define WCD934X_CDC_RATE_EST1_RE_RATE_OUT_23_16            0x0e59
+#define WCD934X_CDC_RATE_EST1_RE_RATE_OUT_31_24            0x0e5a
+#define WCD934X_CDC_RATE_EST1_RE_RATE_OUT_39_32            0x0e5b
+#define WCD934X_CDC_RATE_EST1_RE_RATE_OUT_40_43            0x0e5c
+#define WCD934X_CDC_RATE_EST2_RE_CLK_RST_CTL               0x0e61
+#define WCD934X_CDC_RATE_EST2_RE_CTL                       0x0e62
+#define WCD934X_CDC_RATE_EST2_RE_PULSE_SUPR_CTL            0x0e63
+#define WCD934X_CDC_RATE_EST2_RE_TIMER                     0x0e64
+#define WCD934X_CDC_RATE_EST2_RE_BW_SW                     0x0e65
+#define WCD934X_CDC_RATE_EST2_RE_THRESH                    0x0e66
+#define WCD934X_CDC_RATE_EST2_RE_STATUS                    0x0e67
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_CTRL                 0x0e69
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_TIMER2               0x0e6c
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW1           0x0e6d
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW2           0x0e6e
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW3           0x0e6f
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW4           0x0e70
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_OFFSET_BW5           0x0e71
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW1            0x0e72
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW2            0x0e73
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW3            0x0e74
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW4            0x0e75
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_LIMIT_BW5            0x0e76
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW1          0x0e77
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW2          0x0e78
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW3          0x0e79
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW4          0x0e7a
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_LIMITD1_BW5          0x0e7b
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW1             0x0e7c
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW2             0x0e7d
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW3             0x0e7e
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW4             0x0e7f
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_HYST_BW5             0x0e80
+#define WCD934X_CDC_RATE_EST2_RE_RMAX_DIAG                 0x0e81
+#define WCD934X_CDC_RATE_EST2_RE_RMIN_DIAG                 0x0e82
+#define WCD934X_CDC_RATE_EST2_RE_PH_DET                    0x0e83
+#define WCD934X_CDC_RATE_EST2_RE_DIAG_CLR                  0x0e84
+#define WCD934X_CDC_RATE_EST2_RE_MB_SW_STATE               0x0e85
+#define WCD934X_CDC_RATE_EST2_RE_MAST_DIAG_STATE           0x0e86
+#define WCD934X_CDC_RATE_EST2_RE_RATE_OUT_7_0              0x0e87
+#define WCD934X_CDC_RATE_EST2_RE_RATE_OUT_15_8             0x0e88
+#define WCD934X_CDC_RATE_EST2_RE_RATE_OUT_23_16            0x0e89
+#define WCD934X_CDC_RATE_EST2_RE_RATE_OUT_31_24            0x0e8a
+#define WCD934X_CDC_RATE_EST2_RE_RATE_OUT_39_32            0x0e8b
+#define WCD934X_CDC_RATE_EST2_RE_RATE_OUT_40_43            0x0e8c
+#define WCD934X_CDC_RATE_EST3_RE_CLK_RST_CTL               0x0e91
+#define WCD934X_CDC_RATE_EST3_RE_CTL                       0x0e92
+#define WCD934X_CDC_RATE_EST3_RE_PULSE_SUPR_CTL            0x0e93
+#define WCD934X_CDC_RATE_EST3_RE_TIMER                     0x0e94
+#define WCD934X_CDC_RATE_EST3_RE_BW_SW                     0x0e95
+#define WCD934X_CDC_RATE_EST3_RE_THRESH                    0x0e96
+#define WCD934X_CDC_RATE_EST3_RE_STATUS                    0x0e97
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_CTRL                 0x0e99
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_TIMER2               0x0e9c
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW1           0x0e9d
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW2           0x0e9e
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW3           0x0e9f
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW4           0x0ea0
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_OFFSET_BW5           0x0ea1
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW1            0x0ea2
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW2            0x0ea3
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW3            0x0ea4
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW4            0x0ea5
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_LIMIT_BW5            0x0ea6
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW1          0x0ea7
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW2          0x0ea8
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW3          0x0ea9
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW4          0x0eaa
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_LIMITD1_BW5          0x0eab
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW1             0x0eac
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW2             0x0ead
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW3             0x0eae
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW4             0x0eaf
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_HYST_BW5             0x0eb0
+#define WCD934X_CDC_RATE_EST3_RE_RMAX_DIAG                 0x0eb1
+#define WCD934X_CDC_RATE_EST3_RE_RMIN_DIAG                 0x0eb2
+#define WCD934X_CDC_RATE_EST3_RE_PH_DET                    0x0eb3
+#define WCD934X_CDC_RATE_EST3_RE_DIAG_CLR                  0x0eb4
+#define WCD934X_CDC_RATE_EST3_RE_MB_SW_STATE               0x0eb5
+#define WCD934X_CDC_RATE_EST3_RE_MAST_DIAG_STATE           0x0eb6
+#define WCD934X_CDC_RATE_EST3_RE_RATE_OUT_7_0              0x0eb7
+#define WCD934X_CDC_RATE_EST3_RE_RATE_OUT_15_8             0x0eb8
+#define WCD934X_CDC_RATE_EST3_RE_RATE_OUT_23_16            0x0eb9
+#define WCD934X_CDC_RATE_EST3_RE_RATE_OUT_31_24            0x0eba
+#define WCD934X_CDC_RATE_EST3_RE_RATE_OUT_39_32            0x0ebb
+#define WCD934X_CDC_RATE_EST3_RE_RATE_OUT_40_43            0x0ebc
+#define WCD934X_PAGE15_PAGE_REGISTER                       0x0f00
+#define WCD934X_SPLINE_SRC0_CLK_RST_CTL_0                  0x0f01
+#define WCD934X_SPLINE_SRC0_STATUS                         0x0f02
+#define WCD934X_SPLINE_SRC1_CLK_RST_CTL_0                  0x0f19
+#define WCD934X_SPLINE_SRC1_STATUS                         0x0f1a
+#define WCD934X_SPLINE_SRC2_CLK_RST_CTL_0                  0x0f31
+#define WCD934X_SPLINE_SRC2_STATUS                         0x0f32
+#define WCD934X_SPLINE_SRC3_CLK_RST_CTL_0                  0x0f49
+#define WCD934X_SPLINE_SRC3_STATUS                         0x0f4a
+#define WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG0                  0x0fa1
+#define WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG1                  0x0fa2
+#define WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG2                  0x0fa3
+#define WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG3                  0x0fa4
+#define WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG0                  0x0fa5
+#define WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG1                  0x0fa6
+#define WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG2                  0x0fa7
+#define WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG3                  0x0fa8
+#define WCD934X_CDC_DEBUG_SPLINE_SRC_DEBUG_CFG0            0x0fa9
+#define WCD934X_CDC_DEBUG_SPLINE_SRC_DEBUG_CFG1            0x0faa
+#define WCD934X_CDC_DEBUG_RC_RE_ASRC_DEBUG_CFG0            0x0fab
+#define WCD934X_CDC_DEBUG_ANC0_RC0_FIFO_CTL                0x0fac
+#define WCD934X_CDC_DEBUG_ANC0_RC1_FIFO_CTL                0x0fad
+#define WCD934X_CDC_DEBUG_ANC1_RC0_FIFO_CTL                0x0fae
+#define WCD934X_CDC_DEBUG_ANC1_RC1_FIFO_CTL                0x0faf
+#define WCD934X_CDC_DEBUG_ANC_RC_RST_DBG_CNTR              0x0fb0
+#define WCD934X_PAGE80_PAGE_REGISTER                       0x5000
+#define WCD934X_CODEC_CPR_WR_DATA_0                        0x5001
+#define WCD934X_CODEC_CPR_WR_DATA_1                        0x5002
+#define WCD934X_CODEC_CPR_WR_DATA_2                        0x5003
+#define WCD934X_CODEC_CPR_WR_DATA_3                        0x5004
+#define WCD934X_CODEC_CPR_WR_ADDR_0                        0x5005
+#define WCD934X_CODEC_CPR_WR_ADDR_1                        0x5006
+#define WCD934X_CODEC_CPR_WR_ADDR_2                        0x5007
+#define WCD934X_CODEC_CPR_WR_ADDR_3                        0x5008
+#define WCD934X_CODEC_CPR_RD_ADDR_0                        0x5009
+#define WCD934X_CODEC_CPR_RD_ADDR_1                        0x500a
+#define WCD934X_CODEC_CPR_RD_ADDR_2                        0x500b
+#define WCD934X_CODEC_CPR_RD_ADDR_3                        0x500c
+#define WCD934X_CODEC_CPR_RD_DATA_0                        0x500d
+#define WCD934X_CODEC_CPR_RD_DATA_1                        0x500e
+#define WCD934X_CODEC_CPR_RD_DATA_2                        0x500f
+#define WCD934X_CODEC_CPR_RD_DATA_3                        0x5010
+#define WCD934X_CODEC_CPR_ACCESS_CFG                       0x5011
+#define WCD934X_CODEC_CPR_ACCESS_STATUS                    0x5012
+#define WCD934X_CODEC_CPR_NOM_CX_VDD                       0x5021
+#define WCD934X_CODEC_CPR_SVS_CX_VDD                       0x5022
+#define WCD934X_CODEC_CPR_SVS2_CX_VDD                      0x5023
+#define WCD934X_CODEC_CPR_NOM_MX_VDD                       0x5024
+#define WCD934X_CODEC_CPR_SVS_MX_VDD                       0x5025
+#define WCD934X_CODEC_CPR_SVS2_MX_VDD                      0x5026
+#define WCD934X_CODEC_CPR_SVS2_MIN_CX_VDD                  0x5027
+#define WCD934X_CODEC_CPR_MAX_SVS2_STEP                    0x5028
+#define WCD934X_CODEC_CPR_CTL                              0x5029
+#define WCD934X_CODEC_CPR_SW_MODECHNG_STATUS               0x502a
+#define WCD934X_CODEC_CPR_SW_MODECHNG_START                0x502b
+#define WCD934X_CODEC_CPR_CPR_STATUS                       0x502c
+#define WCD934X_PAGE128_PAGE_REGISTER                      0x8000
+#define WCD934X_TLMM_BIST_MODE_PINCFG                      0x8001
+#define WCD934X_TLMM_RF_PA_ON_PINCFG                       0x8002
+#define WCD934X_TLMM_INTR1_PINCFG                          0x8003
+#define WCD934X_TLMM_INTR2_PINCFG                          0x8004
+#define WCD934X_TLMM_SWR_DATA_PINCFG                       0x8005
+#define WCD934X_TLMM_SWR_CLK_PINCFG                        0x8006
+#define WCD934X_TLMM_I2S_2_SCK_PINCFG                      0x8007
+#define WCD934X_TLMM_SLIMBUS_DATA1_PINCFG                  0x8008
+#define WCD934X_TLMM_SLIMBUS_DATA2_PINCFG                  0x8009
+#define WCD934X_TLMM_SLIMBUS_CLK_PINCFG                    0x800a
+#define WCD934X_TLMM_I2C_CLK_PINCFG                        0x800b
+#define WCD934X_TLMM_I2C_DATA_PINCFG                       0x800c
+#define WCD934X_TLMM_I2S_0_RX_PINCFG                       0x800d
+#define WCD934X_TLMM_I2S_0_TX_PINCFG                       0x800e
+#define WCD934X_TLMM_I2S_0_SCK_PINCFG                      0x800f
+#define WCD934X_TLMM_I2S_0_WS_PINCFG                       0x8010
+#define WCD934X_TLMM_I2S_1_RX_PINCFG                       0x8011
+#define WCD934X_TLMM_I2S_1_TX_PINCFG                       0x8012
+#define WCD934X_TLMM_I2S_1_SCK_PINCFG                      0x8013
+#define WCD934X_TLMM_I2S_1_WS_PINCFG                       0x8014
+#define WCD934X_TLMM_DMIC1_CLK_PINCFG                      0x8015
+#define WCD934X_TLMM_DMIC1_DATA_PINCFG                     0x8016
+#define WCD934X_TLMM_DMIC2_CLK_PINCFG                      0x8017
+#define WCD934X_TLMM_DMIC2_DATA_PINCFG                     0x8018
+#define WCD934X_TLMM_DMIC3_CLK_PINCFG                      0x8019
+#define WCD934X_TLMM_DMIC3_DATA_PINCFG                     0x801a
+#define WCD934X_TLMM_JTCK_PINCFG                           0x801b
+#define WCD934X_TLMM_GPIO1_PINCFG                          0x801c
+#define WCD934X_TLMM_GPIO2_PINCFG                          0x801d
+#define WCD934X_TLMM_GPIO3_PINCFG                          0x801e
+#define WCD934X_TLMM_GPIO4_PINCFG                          0x801f
+#define WCD934X_TLMM_SPI_S_CSN_PINCFG                      0x8020
+#define WCD934X_TLMM_SPI_S_CLK_PINCFG                      0x8021
+#define WCD934X_TLMM_SPI_S_DOUT_PINCFG                     0x8022
+#define WCD934X_TLMM_SPI_S_DIN_PINCFG                      0x8023
+#define WCD934X_TLMM_BA_N_PINCFG                           0x8024
+#define WCD934X_TLMM_GPIO0_PINCFG                          0x8025
+#define WCD934X_TLMM_I2S_2_RX_PINCFG                       0x8026
+#define WCD934X_TLMM_I2S_2_WS_PINCFG                       0x8027
+#define WCD934X_TEST_DEBUG_PIN_CTL_OE_0                    0x8031
+#define WCD934X_TEST_DEBUG_PIN_CTL_OE_1                    0x8032
+#define WCD934X_TEST_DEBUG_PIN_CTL_OE_2                    0x8033
+#define WCD934X_TEST_DEBUG_PIN_CTL_OE_3                    0x8034
+#define WCD934X_TEST_DEBUG_PIN_CTL_OE_4                    0x8035
+#define WCD934X_TEST_DEBUG_PIN_CTL_DATA_0                  0x8036
+#define WCD934X_TEST_DEBUG_PIN_CTL_DATA_1                  0x8037
+#define WCD934X_TEST_DEBUG_PIN_CTL_DATA_2                  0x8038
+#define WCD934X_TEST_DEBUG_PIN_CTL_DATA_3                  0x8039
+#define WCD934X_TEST_DEBUG_PIN_CTL_DATA_4                  0x803a
+#define WCD934X_TEST_DEBUG_PAD_DRVCTL_0                    0x803b
+#define WCD934X_TEST_DEBUG_PAD_DRVCTL_1                    0x803c
+#define WCD934X_TEST_DEBUG_PIN_STATUS                      0x803d
+#define WCD934X_TEST_DEBUG_NPL_DLY_TEST_1                  0x803e
+#define WCD934X_TEST_DEBUG_NPL_DLY_TEST_2                  0x803f
+#define WCD934X_TEST_DEBUG_MEM_CTRL                        0x8040
+#define WCD934X_TEST_DEBUG_DEBUG_BUS_SEL                   0x8041
+#define WCD934X_TEST_DEBUG_DEBUG_JTAG                      0x8042
+#define WCD934X_TEST_DEBUG_DEBUG_EN_1                      0x8043
+#define WCD934X_TEST_DEBUG_DEBUG_EN_2                      0x8044
+#define WCD934X_TEST_DEBUG_DEBUG_EN_3                      0x8045
+#define WCD934X_TEST_DEBUG_DEBUG_EN_4                      0x8046
+#define WCD934X_TEST_DEBUG_DEBUG_EN_5                      0x8047
+#define WCD934X_TEST_DEBUG_ANA_DTEST_DIR                   0x804a
+#define WCD934X_TEST_DEBUG_PAD_INP_DISABLE_0               0x804b
+#define WCD934X_TEST_DEBUG_PAD_INP_DISABLE_1               0x804c
+#define WCD934X_TEST_DEBUG_PAD_INP_DISABLE_2               0x804d
+#define WCD934X_TEST_DEBUG_PAD_INP_DISABLE_3               0x804e
+#define WCD934X_TEST_DEBUG_PAD_INP_DISABLE_4               0x804f
+#define WCD934X_TEST_DEBUG_SYSMEM_CTRL                     0x8050
+#define WCD934X_TEST_DEBUG_SOC_SW_PWR_SEQ_DELAY            0x8051
+#define WCD934X_TEST_DEBUG_LVAL_NOM_LOW                    0x8052
+#define WCD934X_TEST_DEBUG_LVAL_NOM_HIGH                   0x8053
+#define WCD934X_TEST_DEBUG_LVAL_SVS_SVS2_LOW               0x8054
+#define WCD934X_TEST_DEBUG_LVAL_SVS_SVS2_HIGH              0x8055
+#define WCD934X_TEST_DEBUG_SPI_SLAVE_CHAR                  0x8056
+#define WCD934X_TEST_DEBUG_CODEC_DIAGS                     0x8057
+#define WCD934X_MAX_REGISTER                               0x80FF
+
+/* SLIMBUS Slave Registers */
+#define WCD934X_SLIM_PGD_PORT_INT_RX_EN0                     (0x30)
+#define WCD934X_SLIM_PGD_PORT_INT_TX_EN0                     (0x32)
+#define WCD934X_SLIM_PGD_PORT_INT_STATUS_RX_0                (0x34)
+#define WCD934X_SLIM_PGD_PORT_INT_STATUS_RX_1                (0x35)
+#define WCD934X_SLIM_PGD_PORT_INT_STATUS_TX_0                (0x36)
+#define WCD934X_SLIM_PGD_PORT_INT_STATUS_TX_1                (0x37)
+#define WCD934X_SLIM_PGD_PORT_INT_CLR_RX_0                   (0x38)
+#define WCD934X_SLIM_PGD_PORT_INT_CLR_RX_1                   (0x39)
+#define WCD934X_SLIM_PGD_PORT_INT_CLR_TX_0                   (0x3A)
+#define WCD934X_SLIM_PGD_PORT_INT_CLR_TX_1                   (0x3B)
+#define WCD934X_SLIM_PGD_PORT_INT_RX_SOURCE0                 (0x60)
+#define WCD934X_SLIM_PGD_PORT_INT_TX_SOURCE0                 (0x70)
+
+#endif

+ 440 - 0
include/linux/mfd/wcd9xxx/core.h

@@ -0,0 +1,440 @@
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __MFD_TABLA_CORE_H__
+#define __MFD_TABLA_CORE_H__
+
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/of_irq.h>
+#include <linux/interrupt.h>
+#include <linux/pm_qos.h>
+
+#define WCD9XXX_MAX_IRQ_REGS 4
+#define WCD9XXX_MAX_NUM_IRQS (WCD9XXX_MAX_IRQ_REGS * 8)
+#define WCD9XXX_SLIM_NUM_PORT_REG 3
+#define TABLA_VERSION_1_0	0
+#define TABLA_VERSION_1_1	1
+#define TABLA_VERSION_2_0	2
+#define TABLA_IS_1_X(ver) \
+	(((ver == TABLA_VERSION_1_0) || (ver == TABLA_VERSION_1_1)) ? 1 : 0)
+#define TABLA_IS_2_0(ver) ((ver == TABLA_VERSION_2_0) ? 1 : 0)
+
+#define WCD9XXX_SUPPLY_BUCK_NAME "cdc-vdd-buck"
+
+#define SITAR_VERSION_1P0 0
+#define SITAR_VERSION_1P1 1
+#define SITAR_IS_1P0(ver) \
+	((ver == SITAR_VERSION_1P0) ? 1 : 0)
+#define SITAR_IS_1P1(ver) \
+	((ver == SITAR_VERSION_1P1) ? 1 : 0)
+
+#define TAIKO_VERSION_1_0	1
+#define TAIKO_IS_1_0(ver) \
+	((ver == TAIKO_VERSION_1_0) ? 1 : 0)
+
+#define TAPAN_VERSION_1_0	0
+#define TAPAN_IS_1_0(ver) \
+	((ver == TAPAN_VERSION_1_0) ? 1 : 0)
+
+#define TOMTOM_VERSION_1_0	1
+#define TOMTOM_IS_1_0(ver) \
+	((ver == TOMTOM_VERSION_1_0) ? 1 : 0)
+
+#define TASHA_VERSION_1_0     0
+#define TASHA_VERSION_1_1     1
+#define TASHA_VERSION_2_0     2
+
+#define TASHA_IS_1_0(wcd) \
+	((wcd->type == WCD9335 || wcd->type == WCD9326) ? \
+	((wcd->version == TASHA_VERSION_1_0) ? 1 : 0) : 0)
+
+#define TASHA_IS_1_1(wcd) \
+	((wcd->type == WCD9335 || wcd->type == WCD9326) ? \
+	((wcd->version == TASHA_VERSION_1_1) ? 1 : 0) : 0)
+
+#define TASHA_IS_2_0(wcd) \
+	((wcd->type == WCD9335 || wcd->type == WCD9326) ? \
+	((wcd->version == TASHA_VERSION_2_0) ? 1 : 0) : 0)
+
+/*
+ * As fine version info cannot be retrieved before tavil probe.
+ * Define three coarse versions for possible future use before tavil probe.
+ */
+#define TAVIL_VERSION_1_0             0
+#define TAVIL_VERSION_1_1             1
+#define TAVIL_VERSION_WCD9340_1_0     2
+#define TAVIL_VERSION_WCD9341_1_0     3
+#define TAVIL_VERSION_WCD9340_1_1     4
+#define TAVIL_VERSION_WCD9341_1_1     5
+
+#define TAVIL_IS_1_0(wcd) \
+	((wcd->type == WCD934X) ? \
+	 ((wcd->version == TAVIL_VERSION_1_0 || \
+	   wcd->version == TAVIL_VERSION_WCD9340_1_0 || \
+	   wcd->version == TAVIL_VERSION_WCD9341_1_0) ? 1 : 0) : 0)
+#define TAVIL_IS_1_1(wcd) \
+	((wcd->type == WCD934X) ? \
+	 ((wcd->version == TAVIL_VERSION_1_1 || \
+	   wcd->version == TAVIL_VERSION_WCD9340_1_1 || \
+	   wcd->version == TAVIL_VERSION_WCD9341_1_1) ? 1 : 0) : 0)
+#define TAVIL_IS_WCD9340_1_0(wcd) \
+	((wcd->type == WCD934X) ? \
+	 ((wcd->version == TAVIL_VERSION_WCD9340_1_0) ? 1 : 0) : 0)
+#define TAVIL_IS_WCD9341_1_0(wcd) \
+	((wcd->type == WCD934X) ? \
+	 ((wcd->version == TAVIL_VERSION_WCD9341_1_0) ? 1 : 0) : 0)
+#define TAVIL_IS_WCD9340_1_1(wcd) \
+	((wcd->type == WCD934X) ? \
+	 ((wcd->version == TAVIL_VERSION_WCD9340_1_1) ? 1 : 0) : 0)
+#define TAVIL_IS_WCD9341_1_1(wcd) \
+	((wcd->type == WCD934X) ? \
+	 ((wcd->version == TAVIL_VERSION_WCD9341_1_1) ? 1 : 0) : 0)
+
+#define IS_CODEC_TYPE(wcd, wcdtype) \
+	((wcd->type == wcdtype) ? true : false)
+#define IS_CODEC_VERSION(wcd, wcdversion) \
+	((wcd->version == wcdversion) ? true : false)
+
+enum {
+	CDC_V_1_0,
+	CDC_V_1_1,
+	CDC_V_2_0,
+};
+
+enum codec_variant {
+	WCD9XXX,
+	WCD9330,
+	WCD9335,
+	WCD9326,
+	WCD934X,
+};
+
+enum wcd9xxx_slim_slave_addr_type {
+	WCD9XXX_SLIM_SLAVE_ADDR_TYPE_0,
+	WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1,
+};
+
+enum wcd9xxx_pm_state {
+	WCD9XXX_PM_SLEEPABLE,
+	WCD9XXX_PM_AWAKE,
+	WCD9XXX_PM_ASLEEP,
+};
+
+enum {
+	WCD9XXX_INTR_STATUS_BASE = 0,
+	WCD9XXX_INTR_CLEAR_BASE,
+	WCD9XXX_INTR_MASK_BASE,
+	WCD9XXX_INTR_LEVEL_BASE,
+	WCD9XXX_INTR_CLR_COMMIT,
+	WCD9XXX_INTR_REG_MAX,
+};
+
+enum wcd9xxx_intf_status {
+	WCD9XXX_INTERFACE_TYPE_PROBING,
+	WCD9XXX_INTERFACE_TYPE_SLIMBUS,
+	WCD9XXX_INTERFACE_TYPE_I2C,
+};
+
+enum {
+	/* INTR_REG 0 */
+	WCD9XXX_IRQ_SLIMBUS = 0,
+	WCD9XXX_IRQ_MBHC_REMOVAL,
+	WCD9XXX_IRQ_MBHC_SHORT_TERM,
+	WCD9XXX_IRQ_MBHC_PRESS,
+	WCD9XXX_IRQ_MBHC_RELEASE,
+	WCD9XXX_IRQ_MBHC_POTENTIAL,
+	WCD9XXX_IRQ_MBHC_INSERTION,
+	WCD9XXX_IRQ_BG_PRECHARGE,
+	/* INTR_REG 1 */
+	WCD9XXX_IRQ_PA1_STARTUP,
+	WCD9XXX_IRQ_PA2_STARTUP,
+	WCD9XXX_IRQ_PA3_STARTUP,
+	WCD9XXX_IRQ_PA4_STARTUP,
+	WCD9306_IRQ_HPH_PA_OCPR_FAULT = WCD9XXX_IRQ_PA4_STARTUP,
+	WCD9XXX_IRQ_PA5_STARTUP,
+	WCD9XXX_IRQ_MICBIAS1_PRECHARGE,
+	WCD9306_IRQ_HPH_PA_OCPL_FAULT = WCD9XXX_IRQ_MICBIAS1_PRECHARGE,
+	WCD9XXX_IRQ_MICBIAS2_PRECHARGE,
+	WCD9XXX_IRQ_MICBIAS3_PRECHARGE,
+	/* INTR_REG 2 */
+	WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
+	WCD9XXX_IRQ_HPH_PA_OCPR_FAULT,
+	WCD9XXX_IRQ_EAR_PA_OCPL_FAULT,
+	WCD9XXX_IRQ_HPH_L_PA_STARTUP,
+	WCD9XXX_IRQ_HPH_R_PA_STARTUP,
+	WCD9320_IRQ_EAR_PA_STARTUP,
+	WCD9306_IRQ_MBHC_JACK_SWITCH = WCD9320_IRQ_EAR_PA_STARTUP,
+	WCD9310_NUM_IRQS,
+	WCD9XXX_IRQ_RESERVED_0 = WCD9310_NUM_IRQS,
+	WCD9XXX_IRQ_RESERVED_1,
+	WCD9330_IRQ_SVASS_ERR_EXCEPTION = WCD9310_NUM_IRQS,
+	WCD9330_IRQ_MBHC_JACK_SWITCH,
+	/* INTR_REG 3 */
+	WCD9XXX_IRQ_MAD_AUDIO,
+	WCD9XXX_IRQ_MAD_ULTRASOUND,
+	WCD9XXX_IRQ_MAD_BEACON,
+	WCD9XXX_IRQ_SPEAKER_CLIPPING,
+	WCD9320_IRQ_MBHC_JACK_SWITCH,
+	WCD9306_NUM_IRQS,
+	WCD9XXX_IRQ_VBAT_MONITOR_ATTACK = WCD9306_NUM_IRQS,
+	WCD9XXX_IRQ_VBAT_MONITOR_RELEASE,
+	WCD9XXX_NUM_IRQS,
+	/* WCD9330 INTR1_REG 3*/
+	WCD9330_IRQ_SVASS_ENGINE = WCD9XXX_IRQ_MAD_AUDIO,
+	WCD9330_IRQ_MAD_AUDIO,
+	WCD9330_IRQ_MAD_ULTRASOUND,
+	WCD9330_IRQ_MAD_BEACON,
+	WCD9330_IRQ_SPEAKER1_CLIPPING,
+	WCD9330_IRQ_SPEAKER2_CLIPPING,
+	WCD9330_IRQ_VBAT_MONITOR_ATTACK,
+	WCD9330_IRQ_VBAT_MONITOR_RELEASE,
+	WCD9330_NUM_IRQS,
+	WCD9XXX_IRQ_RESERVED_2 = WCD9330_NUM_IRQS,
+};
+
+enum {
+	TABLA_NUM_IRQS = WCD9310_NUM_IRQS,
+	SITAR_NUM_IRQS = WCD9310_NUM_IRQS,
+	TAIKO_NUM_IRQS = WCD9XXX_NUM_IRQS,
+	TAPAN_NUM_IRQS = WCD9306_NUM_IRQS,
+	TOMTOM_NUM_IRQS = WCD9330_NUM_IRQS,
+};
+
+struct intr_data {
+	int intr_num;
+	bool clear_first;
+};
+
+struct wcd9xxx_core_resource {
+	struct mutex irq_lock;
+	struct mutex nested_irq_lock;
+
+	enum wcd9xxx_pm_state pm_state;
+	struct mutex pm_lock;
+	/* pm_wq notifies change of pm_state */
+	wait_queue_head_t pm_wq;
+	struct pm_qos_request pm_qos_req;
+	int wlock_holders;
+
+
+	/* holds the table of interrupts per codec */
+	const struct intr_data *intr_table;
+	int intr_table_size;
+	unsigned int irq_base;
+	unsigned int irq;
+	u8 irq_masks_cur[WCD9XXX_MAX_IRQ_REGS];
+	u8 irq_masks_cache[WCD9XXX_MAX_IRQ_REGS];
+	bool irq_level_high[WCD9XXX_MAX_NUM_IRQS];
+	int num_irqs;
+	int num_irq_regs;
+	u16 intr_reg[WCD9XXX_INTR_REG_MAX];
+	struct regmap *wcd_core_regmap;
+
+	/* Pointer to parent container data structure */
+	void *parent;
+
+	struct device *dev;
+	struct irq_domain *domain;
+};
+
+/*
+ * data structure for Slimbus and I2S channel.
+ * Some of fields are only used in smilbus mode
+ */
+struct wcd9xxx_ch {
+	u32 sph;		/* share channel handle - slimbus only	*/
+	u32 ch_num;		/*
+				 * vitrual channel number, such as 128 -144.
+				 * apply for slimbus only
+				 */
+	u16 ch_h;		/* chanel handle - slimbus only */
+	u16 port;		/*
+				 * tabla port for RX and TX
+				 * such as 0-9 for TX and 10 -16 for RX
+				 * apply for both i2s and slimbus
+				 */
+	u16 shift;		/*
+				 * shift bit for RX and TX
+				 * apply for both i2s and slimbus
+				 */
+	struct list_head list;	/*
+				 * channel link list
+				 * apply for both i2s and slimbus
+				 */
+};
+
+struct wcd9xxx_codec_dai_data {
+	u32 rate;				/* sample rate          */
+	u32 bit_width;				/* sit width 16,24,32   */
+	struct list_head wcd9xxx_ch_list;	/* channel list         */
+	u16 grph;				/* slimbus group handle */
+	unsigned long ch_mask;
+	wait_queue_head_t dai_wait;
+	bool bus_down_in_recovery;
+};
+
+#define WCD9XXX_CH(xport, xshift) \
+	{.port = xport, .shift = xshift}
+
+enum wcd9xxx_chipid_major {
+	TABLA_MAJOR = cpu_to_le16(0x100),
+	SITAR_MAJOR = cpu_to_le16(0x101),
+	TAIKO_MAJOR = cpu_to_le16(0x102),
+	TAPAN_MAJOR = cpu_to_le16(0x103),
+	TOMTOM_MAJOR = cpu_to_le16(0x105),
+	TASHA_MAJOR = cpu_to_le16(0x0),
+	TASHA2P0_MAJOR = cpu_to_le16(0x107),
+	TAVIL_MAJOR = cpu_to_le16(0x108),
+};
+
+enum codec_power_states {
+	WCD_REGION_POWER_COLLAPSE_REMOVE,
+	WCD_REGION_POWER_COLLAPSE_BEGIN,
+	WCD_REGION_POWER_DOWN,
+};
+
+enum wcd_power_regions {
+	WCD9XXX_DIG_CORE_REGION_1,
+	WCD9XXX_MAX_PWR_REGIONS,
+};
+
+struct wcd9xxx_codec_type {
+	u16 id_major;
+	u16 id_minor;
+	struct mfd_cell *dev;
+	int size;
+	int num_irqs;
+	int version; /* -1 to retrieve version from chip version register */
+	enum wcd9xxx_slim_slave_addr_type slim_slave_type;
+	u16 i2c_chip_status;
+	const struct intr_data *intr_tbl;
+	int intr_tbl_size;
+	u16 intr_reg[WCD9XXX_INTR_REG_MAX];
+};
+
+struct wcd9xxx_power_region {
+	enum codec_power_states power_state;
+	u16 pwr_collapse_reg_min;
+	u16 pwr_collapse_reg_max;
+};
+
+struct wcd9xxx {
+	struct device *dev;
+	struct slim_device *slim;
+	struct slim_device *slim_slave;
+	struct mutex io_lock;
+	struct mutex xfer_lock;
+	struct mutex reset_lock;
+	u8 version;
+
+	int reset_gpio;
+	struct device_node *wcd_rst_np;
+
+	int (*read_dev)(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			int bytes, void *dest, bool interface_reg);
+	int (*write_dev)(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			int bytes, void *src, bool interface_reg);
+	int (*multi_reg_write)(struct wcd9xxx *wcd9xxx, const void *data,
+			       size_t count);
+	int (*dev_down)(struct wcd9xxx *wcd9xxx);
+	int (*post_reset)(struct wcd9xxx *wcd9xxx);
+
+	void *ssr_priv;
+	bool dev_up;
+
+	u32 num_of_supplies;
+	struct regulator_bulk_data *supplies;
+
+	struct wcd9xxx_core_resource core_res;
+
+	u16 id_minor;
+	u16 id_major;
+
+	/* Slimbus or I2S port */
+	u32 num_rx_port;
+	u32 num_tx_port;
+	struct wcd9xxx_ch *rx_chs;
+	struct wcd9xxx_ch *tx_chs;
+	u32 mclk_rate;
+	enum codec_variant type;
+	struct regmap *regmap;
+
+	struct wcd9xxx_codec_type *codec_type;
+	bool prev_pg_valid;
+	u8 prev_pg;
+	u8 avoid_cdc_rstlow;
+	struct wcd9xxx_power_region *wcd9xxx_pwr[WCD9XXX_MAX_PWR_REGIONS];
+};
+
+struct wcd9xxx_reg_val {
+	unsigned short reg; /* register address */
+	u8 *buf;            /* buffer to be written to reg. addr */
+	int bytes;          /* number of bytes to be written */
+};
+
+int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
+int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+		u8 val);
+int wcd9xxx_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
+int wcd9xxx_slim_write_repeat(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			     int bytes, void *src);
+int wcd9xxx_slim_reserve_bw(struct wcd9xxx *wcd9xxx,
+			    u32 bw_ops, bool commit);
+int wcd9xxx_set_power_state(struct wcd9xxx *wcd9xxx, enum codec_power_states,
+			    enum wcd_power_regions);
+int wcd9xxx_get_current_power_state(struct wcd9xxx *wcd9xxx,
+				    enum wcd_power_regions);
+
+int wcd9xxx_page_write(struct wcd9xxx *wcd9xxx, unsigned short *reg);
+
+int wcd9xxx_slim_bulk_write(struct wcd9xxx *wcd9xxx,
+			    struct wcd9xxx_reg_val *bulk_reg,
+			    unsigned int size, bool interface);
+
+extern int wcd9xxx_core_res_init(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res,
+	int num_irqs, int num_irq_regs, struct regmap *wcd_regmap);
+
+extern void wcd9xxx_core_res_deinit(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res);
+
+extern int wcd9xxx_core_res_suspend(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res,
+	pm_message_t pmesg);
+
+extern int wcd9xxx_core_res_resume(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res);
+
+extern int wcd9xxx_core_irq_init(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res);
+
+extern int wcd9xxx_assign_irq(struct wcd9xxx_core_resource *wcd9xxx_core_res,
+			      unsigned int irq,
+			      unsigned int irq_base);
+
+extern enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void);
+extern void wcd9xxx_set_intf_type(enum wcd9xxx_intf_status);
+
+extern enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(
+			struct wcd9xxx_core_resource *wcd9xxx_core_res,
+			enum wcd9xxx_pm_state o,
+			enum wcd9xxx_pm_state n);
+static inline int __init wcd9xxx_irq_of_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	return 0;
+}
+
+int wcd9xxx_init(void);
+void wcd9xxx_exit(void);
+#endif

+ 197 - 0
include/linux/mfd/wcd9xxx/pdata.h

@@ -0,0 +1,197 @@
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __MFD_WCD9XXX_PDATA_H__
+
+#define __MFD_WCD9XXX_PDATA_H__
+
+#include <linux/slimbus/slimbus.h>
+#include <linux/mfd/msm-cdc-supply.h>
+
+#define MICBIAS_EXT_BYP_CAP 0x00
+#define MICBIAS_NO_EXT_BYP_CAP 0x01
+
+#define SITAR_LDOH_1P95_V 0x0
+#define SITAR_LDOH_2P35_V 0x1
+#define SITAR_LDOH_2P75_V 0x2
+#define SITAR_LDOH_2P85_V 0x3
+
+#define SITAR_CFILT1_SEL 0x0
+#define SITAR_CFILT2_SEL 0x1
+#define SITAR_CFILT3_SEL 0x2
+
+#define WCD9XXX_LDOH_1P95_V 0x0
+#define WCD9XXX_LDOH_2P35_V 0x1
+#define WCD9XXX_LDOH_2P75_V 0x2
+#define WCD9XXX_LDOH_2P85_V 0x3
+#define WCD9XXX_LDOH_3P0_V 0x3
+
+#define TABLA_LDOH_1P95_V 0x0
+#define TABLA_LDOH_2P35_V 0x1
+#define TABLA_LDOH_2P75_V 0x2
+#define TABLA_LDOH_2P85_V 0x3
+
+#define TABLA_CFILT1_SEL 0x0
+#define TABLA_CFILT2_SEL 0x1
+#define TABLA_CFILT3_SEL 0x2
+
+#define MAX_AMIC_CHANNEL 7
+
+#define TABLA_OCP_300_MA 0x0
+#define TABLA_OCP_350_MA 0x2
+#define TABLA_OCP_365_MA 0x3
+#define TABLA_OCP_150_MA 0x4
+#define TABLA_OCP_190_MA 0x6
+#define TABLA_OCP_220_MA 0x7
+
+#define TABLA_DCYCLE_255  0x0
+#define TABLA_DCYCLE_511  0x1
+#define TABLA_DCYCLE_767  0x2
+#define TABLA_DCYCLE_1023 0x3
+#define TABLA_DCYCLE_1279 0x4
+#define TABLA_DCYCLE_1535 0x5
+#define TABLA_DCYCLE_1791 0x6
+#define TABLA_DCYCLE_2047 0x7
+#define TABLA_DCYCLE_2303 0x8
+#define TABLA_DCYCLE_2559 0x9
+#define TABLA_DCYCLE_2815 0xA
+#define TABLA_DCYCLE_3071 0xB
+#define TABLA_DCYCLE_3327 0xC
+#define TABLA_DCYCLE_3583 0xD
+#define TABLA_DCYCLE_3839 0xE
+#define TABLA_DCYCLE_4095 0xF
+
+#define WCD9XXX_MCLK_CLK_12P288MHZ 12288000
+#define WCD9XXX_MCLK_CLK_9P6HZ 9600000
+
+/* Only valid for 9.6 MHz mclk */
+#define WCD9XXX_DMIC_SAMPLE_RATE_600KHZ 600000
+#define WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ 2400000
+#define WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ 3200000
+#define WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ 4800000
+
+/* Only valid for 12.288 MHz mclk */
+#define WCD9XXX_DMIC_SAMPLE_RATE_768KHZ 768000
+#define WCD9XXX_DMIC_SAMPLE_RATE_2P048MHZ 2048000
+#define WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ 3072000
+#define WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ 4096000
+#define WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ 6144000
+
+#define WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED 0
+
+#define WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED 0
+
+struct wcd9xxx_amic {
+	/*legacy mode, txfe_enable and txfe_buff take 7 input
+	 * each bit represent the channel / TXFE number
+	 * and numbered as below
+	 * bit 0 = channel 1 / TXFE1_ENABLE / TXFE1_BUFF
+	 * bit 1 = channel 2 / TXFE2_ENABLE / TXFE2_BUFF
+	 * ...
+	 * bit 7 = channel 7 / TXFE7_ENABLE / TXFE7_BUFF
+	 */
+	u8 legacy_mode:MAX_AMIC_CHANNEL;
+	u8 txfe_enable:MAX_AMIC_CHANNEL;
+	u8 txfe_buff:MAX_AMIC_CHANNEL;
+	u8 use_pdata:MAX_AMIC_CHANNEL;
+};
+
+/* Each micbias can be assigned to one of three cfilters
+ * Vbatt_min >= .15V + ldoh_v
+ * ldoh_v >= .15v + cfiltx_mv
+ * If ldoh_v = 1.95 160 mv < cfiltx_mv < 1800 mv
+ * If ldoh_v = 2.35 200 mv < cfiltx_mv < 2200 mv
+ * If ldoh_v = 2.75 240 mv < cfiltx_mv < 2600 mv
+ * If ldoh_v = 2.85 250 mv < cfiltx_mv < 2700 mv
+ */
+
+struct wcd9xxx_micbias_setting {
+	u8 ldoh_v;
+	u32 cfilt1_mv; /* in mv */
+	u32 cfilt2_mv; /* in mv */
+	u32 cfilt3_mv; /* in mv */
+	u32 micb1_mv;
+	u32 micb2_mv;
+	u32 micb3_mv;
+	u32 micb4_mv;
+	/* Different WCD9xxx series codecs may not
+	 * have 4 mic biases. If a codec has fewer
+	 * mic biases, some of these properties will
+	 * not be used.
+	 */
+	u8 bias1_cfilt_sel;
+	u8 bias2_cfilt_sel;
+	u8 bias3_cfilt_sel;
+	u8 bias4_cfilt_sel;
+	u8 bias1_cap_mode;
+	u8 bias2_cap_mode;
+	u8 bias3_cap_mode;
+	u8 bias4_cap_mode;
+	bool bias2_is_headset_only;
+};
+
+struct wcd9xxx_ocp_setting {
+	unsigned int	use_pdata:1; /* 0 - use sys default as recommended */
+	unsigned int	num_attempts:4; /* up to 15 attempts */
+	unsigned int	run_time:4; /* in duty cycle */
+	unsigned int	wait_time:4; /* in duty cycle */
+	unsigned int	hph_ocp_limit:3; /* Headphone OCP current limit */
+};
+
+#define WCD9XXX_MAX_REGULATOR	9
+/*
+ *      format : TABLA_<POWER_SUPPLY_PIN_NAME>_CUR_MAX
+ *
+ *      <POWER_SUPPLY_PIN_NAME> from Tabla objective spec
+ */
+
+#define  WCD9XXX_CDC_VDDA_CP_CUR_MAX      500000
+#define  WCD9XXX_CDC_VDDA_RX_CUR_MAX      20000
+#define  WCD9XXX_CDC_VDDA_TX_CUR_MAX      20000
+#define  WCD9XXX_VDDIO_CDC_CUR_MAX        5000
+
+#define  WCD9XXX_VDDD_CDC_D_CUR_MAX       5000
+#define  WCD9XXX_VDDD_CDC_A_CUR_MAX       5000
+
+#define WCD9XXX_VDD_SPKDRV_NAME "cdc-vdd-spkdrv"
+#define WCD9XXX_VDD_SPKDRV2_NAME "cdc-vdd-spkdrv-2"
+
+struct wcd9xxx_regulator {
+	const char *name;
+	int min_uV;
+	int max_uV;
+	int optimum_uA;
+	bool ondemand;
+	struct regulator *regulator;
+};
+
+struct wcd9xxx_pdata {
+	int irq;
+	int irq_base;
+	int num_irqs;
+	int reset_gpio;
+	struct device_node *wcd_rst_np;
+	struct wcd9xxx_amic amic_settings;
+	struct slim_device slimbus_slave_device;
+	struct wcd9xxx_micbias_setting micbias;
+	struct wcd9xxx_ocp_setting ocp;
+	struct cdc_regulator *regulator;
+	int num_supplies;
+	u32 mclk_rate;
+	u32 dmic_sample_rate;
+	u32 mad_dmic_sample_rate;
+	u32 ecpp_dmic_sample_rate;
+	u32 dmic_clk_drv;
+	u16 use_pinctrl;
+};
+
+#endif

+ 37 - 0
include/linux/mfd/wcd9xxx/wcd9xxx-irq.h

@@ -0,0 +1,37 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/types.h>
+#include <linux/mfd/wcd9xxx/core.h>
+
+#ifndef __MFD_WCD9XXX_IRQ_H
+#define __MFD_WCD9XXX_IRQ_H
+bool wcd9xxx_lock_sleep(struct wcd9xxx_core_resource *wcd9xxx_res);
+void wcd9xxx_unlock_sleep(struct wcd9xxx_core_resource *wcd9xxx_res);
+void wcd9xxx_nested_irq_lock(struct wcd9xxx_core_resource *wcd9xxx_res);
+void wcd9xxx_nested_irq_unlock(struct wcd9xxx_core_resource *wcd9xxx_res);
+int wcd9xxx_request_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq,
+			irq_handler_t handler, const char *name, void *data);
+
+void wcd9xxx_free_irq(struct wcd9xxx_core_resource *wcd9xxx_res,
+			int irq, void *data);
+void wcd9xxx_enable_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq);
+void wcd9xxx_disable_irq(struct wcd9xxx_core_resource *wcd9xxx_res,
+			int irq);
+void wcd9xxx_disable_irq_sync(struct wcd9xxx_core_resource *wcd9xxx_res,
+			int irq);
+
+int wcd9xxx_irq_init(struct wcd9xxx_core_resource *wcd9xxx_res);
+void wcd9xxx_irq_exit(struct wcd9xxx_core_resource *wcd9xxx_res);
+int wcd9xxx_irq_drv_init(void);
+void wcd9xxx_irq_drv_exit(void);
+#endif

+ 119 - 0
include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h

@@ -0,0 +1,119 @@
+/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __WCD9310_SLIMSLAVE_H_
+#define __WCD9310_SLIMSLAVE_H_
+
+#include <linux/slimbus/slimbus.h>
+#include <linux/mfd/wcd9xxx/core.h>
+
+
+/*
+ *  client is expected to give port ids in the range of
+ *  1-10 for pre Taiko Tx ports and 1-16 for Taiko
+ *  1-7 for pre Taiko Rx ports and 1-16 for Tako,
+ *  we need to add offset for getting the absolute slave
+ *  port id before configuring the HW
+ */
+#define TABLA_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS 10
+#define TAIKO_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS 16
+
+#define SLIM_MAX_TX_PORTS TAIKO_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS
+
+#define TABLA_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS \
+	TABLA_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS
+#define TAIKO_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS \
+	TAIKO_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS
+
+#define TABLA_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS 7
+#define TAIKO_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS 13
+
+#define SLIM_MAX_RX_PORTS TAIKO_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS
+
+#define SLIM_MAX_REG_ADDR (0x180 + 4 * (SLIM_MAX_RX_PORTS))
+
+#define TABLA_SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID \
+	TABLA_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS
+#define TAIKO_SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID \
+	TAIKO_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS
+
+#define TABLA_SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID 16
+#define TAIKO_SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID 31
+
+#define TABLA_SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID 9
+#define TAIKO_SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID 15
+
+/* below details are taken from SLIMBUS slave SWI */
+#define SB_PGD_PORT_BASE 0x000
+
+#define SB_PGD_PORT_CFG_BYTE_ADDR(offset, port_num) \
+		(SB_PGD_PORT_BASE + offset + (1 * port_num))
+
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_0(port_num) \
+		(SB_PGD_PORT_BASE + 0x100 + 4*port_num)
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_0_START_PORT_ID   0
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_0_END_PORT_ID     7
+
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_1(port_num) \
+		(SB_PGD_PORT_BASE + 0x101 + 4*port_num)
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID   8
+
+#define SB_PGD_RX_PORT_MULTI_CHANNEL_0(offset, port_num) \
+		(SB_PGD_PORT_BASE + offset + (4 * port_num))
+
+/* slave port water mark level
+ *   (0: 6bytes, 1: 9bytes, 2: 12 bytes, 3: 15 bytes)
+ */
+#define SLAVE_PORT_WATER_MARK_6BYTES  0
+#define SLAVE_PORT_WATER_MARK_9BYTES  1
+#define SLAVE_PORT_WATER_MARK_12BYTES 2
+#define SLAVE_PORT_WATER_MARK_15BYTES 3
+#define SLAVE_PORT_WATER_MARK_SHIFT 1
+#define SLAVE_PORT_ENABLE           1
+#define SLAVE_PORT_DISABLE          0
+#define WATER_MARK_VAL \
+	((SLAVE_PORT_WATER_MARK_12BYTES << SLAVE_PORT_WATER_MARK_SHIFT) | \
+	 (SLAVE_PORT_ENABLE))
+#define BASE_CH_NUM 128
+
+
+int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx,
+			   u8 wcd9xxx_pgd_la,
+			   unsigned int tx_num, unsigned int *tx_slot,
+			   unsigned int rx_num, unsigned int *rx_slot);
+
+int wcd9xxx_deinit_slimslave(struct wcd9xxx *wcd9xxx);
+
+int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx,
+			    struct list_head *wcd9xxx_ch_list,
+			    unsigned int rate, unsigned int bit_width,
+			    u16 *grph);
+int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx,
+			    struct list_head *wcd9xxx_ch_list,
+			    unsigned int rate, unsigned int bit_width,
+				u16 *grph);
+int wcd9xxx_close_slim_sch_rx(struct wcd9xxx *wcd9xxx,
+			      struct list_head *wcd9xxx_ch_list, u16 grph);
+int wcd9xxx_close_slim_sch_tx(struct wcd9xxx *wcd9xxx,
+			      struct list_head *wcd9xxx_ch_list, u16 grph);
+int wcd9xxx_get_channel(struct wcd9xxx *wcd9xxx,
+			unsigned int *rx_ch,
+			unsigned int *tx_ch);
+int wcd9xxx_get_slave_port(unsigned int ch_num);
+int wcd9xxx_disconnect_port(struct wcd9xxx *wcd9xxx,
+			    struct list_head *wcd9xxx_ch_list, u16 grph);
+int wcd9xxx_rx_vport_validation(u32 port_id,
+				struct list_head *codec_dai_list);
+int wcd9xxx_tx_vport_validation(u32 vtable, u32 port_id,
+				struct wcd9xxx_codec_dai_data *codec_dai,
+				u32 num_codec_dais);
+#endif /* __WCD9310_SLIMSLAVE_H_ */

+ 40 - 0
include/linux/mfd/wcd9xxx/wcd9xxx-utils.h

@@ -0,0 +1,40 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __WCD9XXX_UTILS_H__
+#define __WCD9XXX_UTILS_H__
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <linux/mfd/wcd9xxx/core.h>
+
+struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev);
+int wcd9xxx_bringup(struct device *dev);
+int wcd9xxx_bringdown(struct device *dev);
+struct regmap *wcd9xxx_regmap_init(struct device *dev,
+				   const struct regmap_config *config);
+int wcd9xxx_reset(struct device *dev);
+int wcd9xxx_reset_low(struct device *dev);
+int wcd9xxx_get_codec_info(struct device *dev);
+
+typedef int (*codec_bringup_fn)(struct wcd9xxx *);
+typedef int (*codec_bringdown_fn)(struct wcd9xxx *);
+typedef int (*codec_type_fn)(struct wcd9xxx *,
+			     struct wcd9xxx_codec_type *);
+
+codec_bringdown_fn wcd9xxx_bringdown_fn(int type);
+codec_bringup_fn wcd9xxx_bringup_fn(int type);
+codec_type_fn wcd9xxx_get_codec_info_fn(int type);
+
+#endif

+ 190 - 0
include/linux/qdsp6v2/apr.h

@@ -0,0 +1,190 @@
+/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+#ifndef __APR_H_
+#define __APR_H_
+
+#include <linux/mutex.h>
+#include <soc/qcom/subsystem_notif.h>
+
+enum apr_subsys_state {
+	APR_SUBSYS_DOWN,
+	APR_SUBSYS_UP,
+	APR_SUBSYS_LOADED,
+};
+
+struct apr_q6 {
+	void *pil;
+	atomic_t q6_state;
+	atomic_t modem_state;
+	struct mutex lock;
+};
+
+struct apr_hdr {
+	uint16_t hdr_field;
+	uint16_t pkt_size;
+	uint8_t src_svc;
+	uint8_t src_domain;
+	uint16_t src_port;
+	uint8_t dest_svc;
+	uint8_t dest_domain;
+	uint16_t dest_port;
+	uint32_t token;
+	uint32_t opcode;
+};
+
+#define APR_HDR_LEN(hdr_len) ((hdr_len)/4)
+#define APR_PKT_SIZE(hdr_len, payload_len) ((hdr_len) + (payload_len))
+#define APR_HDR_FIELD(msg_type, hdr_len, ver)\
+	(((msg_type & 0x3) << 8) | ((hdr_len & 0xF) << 4) | (ver & 0xF))
+
+#define APR_HDR_SIZE sizeof(struct apr_hdr)
+
+/* Version */
+#define APR_PKT_VER		0x0
+
+/* Command and Response Types */
+#define APR_MSG_TYPE_EVENT	0x0
+#define APR_MSG_TYPE_CMD_RSP	0x1
+#define APR_MSG_TYPE_SEQ_CMD	0x2
+#define APR_MSG_TYPE_NSEQ_CMD	0x3
+#define APR_MSG_TYPE_MAX	0x04
+
+/* APR Basic Response Message */
+#define APR_BASIC_RSP_RESULT 0x000110E8
+#define APR_RSP_ACCEPTED     0x000100BE
+
+/* Domain IDs */
+#define APR_DOMAIN_SIM	0x1
+#define APR_DOMAIN_PC		0x2
+#define APR_DOMAIN_MODEM	0x3
+#define APR_DOMAIN_ADSP	0x4
+#define APR_DOMAIN_APPS	0x5
+#define APR_DOMAIN_MAX	0x6
+
+/* ADSP service IDs */
+#define APR_SVC_TEST_CLIENT     0x2
+#define APR_SVC_ADSP_CORE	0x3
+#define APR_SVC_AFE		0x4
+#define APR_SVC_VSM		0x5
+#define APR_SVC_VPM		0x6
+#define APR_SVC_ASM		0x7
+#define APR_SVC_ADM		0x8
+#define APR_SVC_ADSP_MVM	0x09
+#define APR_SVC_ADSP_CVS	0x0A
+#define APR_SVC_ADSP_CVP	0x0B
+#define APR_SVC_USM		0x0C
+#define APR_SVC_LSM		0x0D
+#define APR_SVC_VIDC		0x16
+#define APR_SVC_MAX		0x17
+
+/* Modem Service IDs */
+#define APR_SVC_MVS		0x3
+#define APR_SVC_MVM		0x4
+#define APR_SVC_CVS		0x5
+#define APR_SVC_CVP		0x6
+#define APR_SVC_SRD		0x7
+
+/* APR Port IDs */
+#define APR_MAX_PORTS		0x80
+
+#define APR_NAME_MAX		0x40
+
+#define RESET_EVENTS		0x000130D7
+
+#define LPASS_RESTART_EVENT	0x1000
+#define LPASS_RESTART_READY	0x1001
+
+struct apr_client_data {
+	uint16_t reset_event;
+	uint16_t reset_proc;
+	uint16_t payload_size;
+	uint16_t hdr_len;
+	uint16_t msg_type;
+	uint16_t src;
+	uint16_t dest_svc;
+	uint16_t src_port;
+	uint16_t dest_port;
+	uint32_t token;
+	uint32_t opcode;
+	void *payload;
+};
+
+typedef int32_t (*apr_fn)(struct apr_client_data *data, void *priv);
+
+struct apr_svc {
+	uint16_t id;
+	uint16_t dest_id;
+	uint16_t client_id;
+	uint16_t dest_domain;
+	uint8_t rvd;
+	uint8_t port_cnt;
+	uint8_t svc_cnt;
+	uint8_t need_reset;
+	apr_fn port_fn[APR_MAX_PORTS];
+	void *port_priv[APR_MAX_PORTS];
+	apr_fn fn;
+	void *priv;
+	struct mutex m_lock;
+	spinlock_t w_lock;
+	uint8_t pkt_owner;
+};
+
+struct apr_client {
+	uint8_t id;
+	uint8_t svc_cnt;
+	uint8_t rvd;
+	struct mutex m_lock;
+	struct apr_svc_ch_dev *handle;
+	struct apr_svc svc[APR_SVC_MAX];
+};
+
+struct apr_rx_intents {
+	int num_of_intents;
+	uint32_t size;
+};
+
+struct apr_pkt_cfg {
+	uint8_t pkt_owner;
+	struct apr_rx_intents intents;
+};
+
+int apr_load_adsp_image(void);
+struct apr_client *apr_get_client(int dest_id, int client_id);
+int apr_wait_for_device_up(int dest_id);
+int apr_get_svc(const char *svc_name, int dest_id, int *client_id,
+		int *svc_idx, int *svc_id);
+void apr_cb_func(void *buf, int len, void *priv);
+struct apr_svc *apr_register(char *dest, char *svc_name, apr_fn svc_fn,
+					uint32_t src_port, void *priv);
+inline int apr_fill_hdr(void *handle, uint32_t *buf, uint16_t src_port,
+			uint16_t msg_type, uint16_t dest_port,
+			uint32_t token, uint32_t opcode, uint16_t len);
+
+int apr_send_pkt(void *handle, uint32_t *buf);
+int apr_deregister(void *handle);
+void subsys_notif_register(char *client_name, int domain,
+			   struct notifier_block *nb);
+int apr_get_dest_id(char *dest);
+uint16_t apr_get_data_src(struct apr_hdr *hdr);
+void change_q6_state(int state);
+void q6audio_dsp_not_responding(void);
+void apr_reset(void *handle);
+enum apr_subsys_state apr_get_subsys_state(void);
+enum apr_subsys_state apr_get_modem_state(void);
+void apr_set_modem_state(enum apr_subsys_state state);
+enum apr_subsys_state apr_get_q6_state(void);
+int apr_set_q6_state(enum apr_subsys_state state);
+void apr_set_subsys_state(void);
+const char *apr_get_lpass_subsys_name(void);
+uint16_t apr_get_reset_domain(uint16_t proc);
+#endif

+ 90 - 0
include/linux/qdsp6v2/apr_tal.h

@@ -0,0 +1,90 @@
+/* Copyright (c) 2010-2011, 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+#ifndef __APR_TAL_H_
+#define __APR_TAL_H_
+
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/uaccess.h>
+
+/* APR Client IDs */
+#define APR_CLIENT_AUDIO	0x0
+#define APR_CLIENT_VOICE	0x1
+#define APR_CLIENT_MAX		0x2
+
+#define APR_DL_SMD    0
+#define APR_DL_MAX    1
+
+#define APR_DEST_MODEM 0
+#define APR_DEST_QDSP6 1
+#define APR_DEST_MAX   2
+
+#if defined(CONFIG_MSM_QDSP6_APRV2_GLINK) || \
+	defined(CONFIG_MSM_QDSP6_APRV3_GLINK)
+#define APR_MAX_BUF			512
+#else
+#define APR_MAX_BUF			8092
+#endif
+
+#define APR_DEFAULT_NUM_OF_INTENTS 20
+
+#define APR_OPEN_TIMEOUT_MS 5000
+
+enum {
+	/* If client sets the pkt_owner to APR_PKT_OWNER_DRIVER, APR
+	 * driver will allocate a buffer, where the user packet is
+	 * copied into, for each and every single Tx transmission.
+	 * The buffer is thereafter passed to underlying link layer
+	 * and freed upon the notification received from the link layer
+	 * that the packet has been consumed.
+	 */
+	APR_PKT_OWNER_DRIVER,
+	/* If client sets the pkt_owner to APR_PKT_OWNER_CLIENT, APR
+	 * will pass the user packet memory address directly to underlying
+	 * link layer. In this case it is the client's responsibility to
+	 * make sure the packet is intact until being notified that the
+	 * packet has been consumed.
+	 */
+	APR_PKT_OWNER_CLIENT,
+};
+
+struct apr_pkt_priv {
+	/* This property is only applicable for APR over Glink.
+	 * It is ignored in APR over SMD cases.
+	 */
+	uint8_t pkt_owner;
+};
+
+typedef void (*apr_svc_cb_fn)(void *buf, int len, void *priv);
+struct apr_svc_ch_dev *apr_tal_open(uint32_t svc, uint32_t dest,
+			uint32_t dl, apr_svc_cb_fn func, void *priv);
+int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
+		struct apr_pkt_priv *pkt_priv, int len);
+int apr_tal_close(struct apr_svc_ch_dev *apr_ch);
+int apr_tal_rx_intents_config(struct apr_svc_ch_dev *apr_ch,
+		int num_of_intents, uint32_t size);
+
+
+struct apr_svc_ch_dev {
+	void               *handle;
+	spinlock_t         w_lock;
+	spinlock_t         r_lock;
+	struct mutex       m_lock;
+	apr_svc_cb_fn      func;
+	wait_queue_head_t  wait;
+	void               *priv;
+	unsigned int       channel_state;
+	bool               if_remote_intent_ready;
+};
+
+#endif

Some files were not shown because too many files changed in this diff