From ffbea912b0e22b7888ae9db00850c6375e0379ca Mon Sep 17 00:00:00 2001
From: "Thanh Thai. Nguyen" <thanh.nguyen.zc@renesas.com>
Date: Mon, 19 Jul 2021 08:44:32 +0700
Subject: [PATCH 1/2] Add-ADSP-sound-driver-source

---
 include/adsp_drv/xf-adsp-drv-ext.h |   58 +
 sound/soc/adsp/Kconfig             |   14 +
 sound/soc/adsp/Makefile            |    3 +
 sound/soc/adsp/xf-adsp-alsa.c      | 3960 ++++++++++++++++++++++++++++
 sound/soc/adsp/xf-adsp-alsa.c.orig | 3949 +++++++++++++++++++++++++++
 sound/soc/adsp/xf-adsp-base.c      | 2259 ++++++++++++++++
 sound/soc/adsp/xf-adsp-base.h      |  275 ++
 sound/soc/adsp/xf-adsp-config.h    |  604 +++++
 8 files changed, 11122 insertions(+)
 create mode 100644 include/adsp_drv/xf-adsp-drv-ext.h
 create mode 100644 sound/soc/adsp/Kconfig
 create mode 100644 sound/soc/adsp/Makefile
 create mode 100644 sound/soc/adsp/xf-adsp-alsa.c
 create mode 100644 sound/soc/adsp/xf-adsp-alsa.c.orig
 create mode 100644 sound/soc/adsp/xf-adsp-base.c
 create mode 100644 sound/soc/adsp/xf-adsp-base.h
 create mode 100644 sound/soc/adsp/xf-adsp-config.h

diff --git a/include/adsp_drv/xf-adsp-drv-ext.h b/include/adsp_drv/xf-adsp-drv-ext.h
new file mode 100644
index 0000000..6c3dbc0
--- /dev/null
+++ b/include/adsp_drv/xf-adsp-drv-ext.h
@@ -0,0 +1,58 @@
+/*****************************************************************************
+ * \file       xf-adsp-driver-ext.h
+ * \brief      Header file for ADSP driver extension part
+ * \addtogroup ADSP Driver
+ ******************************************************************************
+ * \date       Oct. 21, 2017
+ * \author     Renesas Electronics Corporation
+ ******************************************************************************
+ * \par        Copyright
+ *
+ * Copyright(c) 2016 Renesas Electoronics Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __XF_ADSP_DRV_EXT_H
+#define __XF_ADSP_DRV_EXT_H
+
+/***********************************************************
+ * Extension client APIs
+ * ********************************************************/
+
+struct xf_adsp_base_cmd {
+	/* register new client for ADSP base control */
+	int (*client_register)(void **private_data);
+	/* unregister client */
+	int (*client_unregister)(void *private_data);
+	/* get data from proxy */
+	int (*recv)(void *private_data, void *buf);
+	/* send data to proxy */
+	int (*send)(void *private_data, void *buf);
+	/* wait the valid message in the response queue */
+	int (*poll)(void *private_data, int *condition);
+};
+
+/* create ADSP base control data */
+int xf_adsp_base_create(struct xf_adsp_base_cmd *cmd);
+
+/* destroy ADSP base control data */
+int xf_adsp_base_destroy(void);
+
+#endif
diff --git a/sound/soc/adsp/Kconfig b/sound/soc/adsp/Kconfig
new file mode 100644
index 0000000..605261f
--- /dev/null
+++ b/sound/soc/adsp/Kconfig
@@ -0,0 +1,14 @@
+## SoC for ADSP driver configuration
+menu "ASoC ADSP driver"
+
+config SND_SOC_ADSP
+    tristate "SoC Audio for R-Car ADSP"
+    select SND_SIMPLE_CARD
+    select SND_SIMPLE_SCU_CARD
+    select SND_AUDIO_GRAPH_CARD
+    select SND_AUDIO_GRAPH_SCU_CARD
+    default y
+    help
+      This option enables ALSA ADSP sound supports ADSP module
+
+endmenu
diff --git a/sound/soc/adsp/Makefile b/sound/soc/adsp/Makefile
new file mode 100644
index 0000000..8277fdb
--- /dev/null
+++ b/sound/soc/adsp/Makefile
@@ -0,0 +1,3 @@
+## Makefile for SoC ADSP driver
+snd-soc-adsp-objs	:= xf-adsp-alsa.o xf-adsp-base.o
+obj-$(CONFIG_SND_SOC_ADSP)	+= snd-soc-adsp.o
diff --git a/sound/soc/adsp/xf-adsp-alsa.c b/sound/soc/adsp/xf-adsp-alsa.c
new file mode 100644
index 0000000..cdac9db
--- /dev/null
+++ b/sound/soc/adsp/xf-adsp-alsa.c
@@ -0,0 +1,3960 @@
+/** ***************************************************************************
+ * \file	 xf-adsp-alsa.c
+ * \brief	 Source file for ADSP ALSA Driver
+ * \addtogroup	 ADSP Driver
+ ******************************************************************************
+ * \date	 May. 31, 2021
+ * \author	 Renesas Electronics Corporation
+ ******************************************************************************
+ * \par		Copyright
+ *
+ * Copyright(c) 2021 Renesas Electoronics Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/sched/signal.h>
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/pcm-indirect.h>
+#include <linux/time.h>
+
+#include "xf-adsp-base.h"
+
+/* Name of Volume control for playback */
+#define PLAYBACK_VOLUME_CTR_NAME	"PlaybackVolume"
+
+/* Name of Volume control for capture */
+#define CAPTURE_VOLUME_CTR_NAME		"CaptureVolume"
+
+/* Name of Sample Rate control for playback */
+#define PLAYBACK_OUT_RATE_CTR_NAME	"PlaybackOutRate"
+
+/* Name of Output Channel control for playback */
+#define PLAYBACK_OUT_CHANNEL_CTR_NAME	"PlaybackOutChannel"
+
+/* Name of Sample Rate control for capture */
+#define CAPTURE_IN_RATE_CTR_NAME	"CaptureInRate"
+
+/* Name of Equalizer parameters control for playback */
+#define PLAYBACK_EQZ_CTR_NAME		"PlaybackEQZControl"
+
+/* Name of Equalizer parameters control for capture */
+#define CAPTURE_EQZ_CTR_NAME		"CaptureEQZControl"
+
+/* Name of Equalizer Switch control for playback */
+#define PLAYBACK_EQZ_SWITCH_CTR_NAME	"PlaybackEQZSwitch"
+
+/* Name of Equalizer Switch control for capture */
+#define CAPTURE_EQZ_SWITCH_CTR_NAME	"CaptureEQZSwitch"
+
+/* Name of Volume control for TDM playback */
+#define TDM_PLAYBACK_VOLUME_CTR_NAME	"TDMPlaybackVolume"
+
+/* Name of Volume control for TDM capture */
+#define TDM_CAPTURE_VOLUME_CTR_NAME	"TDMCaptureVolume"
+
+/* Name of Sample Rate control for TDM playback */
+#define TDM_PLAYBACK_OUT_RATE_CTR_NAME	"TDMPlaybackOutRate"
+
+/* Name of Sample Rate control for TDM capture */
+#define TDM_CAPTURE_IN_RATE_CTR_NAME	"TDMCaptureInRate"
+
+/* Prefix of Playback control name */
+#define PREFIX_OF_PLAYBACK_CTR_NAME	PLAYBACK_VOLUME_CTR_NAME[0]
+
+/* Prefix of Capture control name */
+#define PREFIX_OF_CAPTURE_CTR_NAME	CAPTURE_VOLUME_CTR_NAME[0]
+
+/* Prefix of TDM control name */
+#define PREFIX_OF_TDM_CTR_NAME		TDM_PLAYBACK_VOLUME_CTR_NAME[0]
+
+/* Prefix of TDM playback */
+#define TDM_PLAYBACK			TDM_PLAYBACK_VOLUME_CTR_NAME[3]
+
+/* Prefix of TDM record */
+#define TDM_CAPTURE			TDM_CAPTURE_VOLUME_CTR_NAME[3]
+
+/* Number of control for playback & capture */
+#define RDR_CONTROL_NUM		(9)
+
+/* Number of controls for TDM */
+#define TDM_CONTROL_NUM		(4)
+
+/* Indicate playback stream */
+#define DIRECT_PLAYBACK		(0)
+
+/* Indicate capture stream */
+#define DIRECT_CAPTURE		(1)
+
+/* Indicate stream number */
+#define DIRECT_NUM		(2)
+
+/* Supported frame size for playback/record function in driver */
+#define FRAME_SIZE		(1024)
+
+/* Supported frame size for TDM playback/record function in driver */
+#define TDM_FRAME_SIZE		(1024)
+
+/* Supported sample rate in driver */
+#define SND_ADSP_SAMPLE_RATES	(SNDRV_PCM_RATE_32000 | \
+				 SNDRV_PCM_RATE_44100 | \
+				 SNDRV_PCM_RATE_48000)
+
+/* Supported PCM width in driver */
+#define SND_ADSP_PCM_WIDTHS	(SNDRV_PCM_FMTBIT_S16_LE | \
+				 SNDRV_PCM_FMTBIT_S24_LE)
+
+/* Macro to control DAI index */
+/* DAI 0 index for playback/record functions of stereo/mono formats */
+#define RDR_DAI_IDX0		(0)
+
+/* DAI 1 index for playback/record functions of stereo/mono formats */
+#define RDR_DAI_IDX1		(1)
+
+/* DAI 2 index for playback/record functions of stereo/mono formats */
+#define RDR_DAI_IDX2		(2)
+
+/* DAI 3 index for playback/record functions of stereo/mono formats */
+#define RDR_DAI_IDX3		(3)
+
+/* DAI 4 index for playback/record functions of TDM formats */
+#define TDM_DAI_IDX		(4)
+
+/* Maximum number of DAI supported by driver */
+#define MAX_DAI_IDX		(5)
+
+/* Renderer/Capture software information */
+/* Minimum channel number supported */
+#define MIN_CHANNEL		(1)
+
+/* Maximum channel number supported */
+#define MAX_CHANNEL		(2)
+
+/* Minimum buffer size in byte */
+#define MIN_BUF_SIZE		(FRAME_SIZE * MIN_CHANNEL * 2)
+
+/* Maximum buffer size in byte */
+#define MAX_BUF_SIZE		(FRAME_SIZE * MAX_CHANNEL * 4)
+
+/* Minimum numbers of period in the buffer */
+#define MIN_PERIOD		(1)
+
+/* Maximum numbers of period in the buffer */
+#define MAX_PERIOD		(4)
+
+/* Maximun numbers of bytes in ALSA buffer */
+#define MAX_BUFFER_BYTES	(MAX_PERIOD * MAX_BUF_SIZE)
+
+/* TDM software information */
+/*< Minimum channel number supported in TDM plugin */
+#define TDM_MIN_CHANNEL		(6)
+
+/* Maximum channel number supported in TDM plugin */
+#define TDM_MAX_CHANNEL		(8)
+
+/* Minimum buffer size in byte for TDM format */
+#define TDM_MIN_BUF_SIZE	(TDM_FRAME_SIZE * TDM_MIN_CHANNEL * 2)
+
+/* Maximum buffer size in byte for TDM format */
+#define TDM_MAX_BUF_SIZE	(TDM_FRAME_SIZE * TDM_MAX_CHANNEL * 4)
+
+/* Minimum numbers of period in the buffer for TDM format */
+#define TDM_MIN_PERIOD		(1)
+
+/* Maximum numbers of period in the buffer for TDM format  */
+#define TDM_MAX_PERIOD		(4)
+
+/* Maximum numbers of bytes in ALSA buffer for TDM format */
+#define TDM_MAX_BUFFER_BYTES	(TDM_MAX_PERIOD * TDM_MAX_BUF_SIZE)
+
+/* Volume scale used when user set */
+#define VOLUME_SCALE		(100)
+
+/* Maximum element in Equalizer parameter control */
+#define MAX_EQZ_PARAM_NUMBER	(55)
+
+/* Equalizer control is disabled */
+#define EQZ_OFF			(0)
+
+/* Equalizer control is enabled */
+#define EQZ_ON			(1)
+
+/* Component status */
+/* Handle state is NULL */
+#define XF_HANDLE_NULL		(0)
+
+/* Handle state is CREATED after creating handle successfully */
+#define XF_HANDLE_CREATED	BIT(0)
+
+/* Handle state is READY after finishing handle init */
+#define XF_HANDLE_READY		BIT(1)
+
+/* channels */
+/* Mono stream */
+#define MONAURAL		(1)
+
+/* Stereo stream */
+#define STEREO			(2)
+
+/* define number of bytes in a sample of 24 bits format types */
+/* store 24 bits data in 4 bytes LE */
+#define FMTBIT_S24_LE_BYTES_PER_SAMPLE		(4)
+
+/* store 24 bits data in 3 bytes LE */
+#define FMTBIT_S24_3LE_BYTES_PER_SAMPLE		(3)
+
+/* helper macro to get bytes per sample number */
+#define BYTES_PER_SAMPLE(fmt)   (FMTBIT_##fmt##_BYTES_PER_SAMPLE)
+
+/* check component is created */
+#define COMPONENT_IS_CREATED(n)	(((n & XF_HANDLE_CREATED) != 0) ? TRUE : FALSE)
+
+/* check component is ready */
+#define COMPONENT_IS_READY(n)	(((n & XF_HANDLE_READY) != 0) ? TRUE : FALSE)
+
+/* indicator of stream order */
+#define MIX_UNUSED			(0)
+#define FIRST_RUN			(2)
+#define SECOND_RUN			(1)
+
+/* check MIX usage */
+#define MIX_ENABLED(mix_ctl)	((mix_ctl == SECOND_RUN) ? TRUE : FALSE)
+
+/*******************************************************************
+ * base structures for ADSP ALSA driver
+ * ****************************************************************/
+
+/** \struct snd_adsp_control
+ *  \brief  Structure stores parameters from user
+ */
+struct snd_adsp_control {
+	/* Volume rate for playback/record */
+	int	   vol_rate[DIRECT_NUM][MAX_DAI_IDX - 1];
+
+	/* Volume rate for TDM playback/TDM record */
+	int	   tdm_vol_rate[DIRECT_NUM];
+
+	/* Out sample rate with Renderer, in sample rate with Capture */
+	int	   sample_rate[DIRECT_NUM][MAX_DAI_IDX - 1];
+
+	/* Out sample rate for TDM Renderer, in sample rate for TDM Capture */
+	int	   tdm_sample_rate[DIRECT_NUM];
+
+	/* Output channel of playback */
+	int	   rdr_out_ch[MAX_DAI_IDX - 1];
+
+	/* Equalizer parameters */
+	struct xf_adsp_equalizer_params eqz_params[DIRECT_NUM][MAX_DAI_IDX - 1];
+
+	/* Equalizer switch */
+	int	   eqz_switch[DIRECT_NUM][MAX_DAI_IDX - 1];
+
+	/* Indicator of MIX usage */
+	int	   mix_usage;
+};
+
+/** \struct snd_adsp_base_info
+ *  \brief  Structure stores some base information of a stream
+ */
+struct snd_adsp_base_info {
+	/* high resolution timer data */
+	struct hrtimer			hrtimer;
+
+	/* kernel time value in nanosecond */
+	ktime_t				ktime;
+
+	/* save interrupt state before getting lock */
+	unsigned long			flag;
+
+	/* high resolution timer state */
+	int				hrt_state;
+
+	/* target handle id of ALSA driver */
+	int				handle_id;
+
+	/* data buffer */
+	char				*buffer[XF_BUF_POOL_SIZE];
+
+	/* size of each allocated data buffer */
+	int				buf_bytes;
+
+	/* data index of buffer */
+	int				buf_idx;
+
+	/* queue index of buffer */
+	int				buf_queue;
+
+	/* HW index in bytes */
+	int				hw_idx;
+
+	/* number of bytes in a period */
+	int				period_bytes;
+
+	/* substream runtime object */
+	struct snd_pcm_substream	*substream;
+
+	/* indirect PCM data transfer */
+	struct snd_pcm_indirect		pcm_indirect;
+
+	/* spinlock data */
+	spinlock_t			lock;
+
+	/* runtime error indicator */
+	int				runtime_err;
+};
+
+/** \struct snd_adsp_playback
+ *  \brief  Structure stores data for playback function
+ */
+struct snd_adsp_playback {
+	/* base information of stream */
+	struct snd_adsp_base_info	base;
+
+	/* Renderer component data */
+	struct xf_adsp_renderer		*renderer;
+
+	/* Equalizer component data */
+	struct xf_adsp_equalizer	*equalizer;
+
+	/* Renderer component state */
+	int				rdr_state;
+
+	/* Equalizer component state */
+	int				eqz_state;
+};
+
+/** \struct snd_adsp_record
+ *  \brief  Structure stores data for record function
+ */
+struct snd_adsp_record {
+	/* base information of stream */
+	struct snd_adsp_base_info	base;
+
+	/* Capture component data */
+	struct xf_adsp_capture		*capture;
+
+	/* Equalizer component data */
+	struct xf_adsp_equalizer	*equalizer;
+
+	/* Capture component state */
+	int				cap_state;
+
+	/* Equalizer component state */
+	int				eqz_state;
+};
+
+/** \struct snd_adsp_tdm_playback
+ *  \brief  Structure stores data for TDM playback function
+ */
+struct snd_adsp_tdm_playback {
+	/* base information of stream */
+	struct snd_adsp_base_info	base;
+
+	/* TDM Renderer component data */
+	struct xf_adsp_tdm_renderer	*tdm_renderer;
+
+	/* TDM Renderer component state */
+	int				state;
+};
+
+/** \struct snd_adsp_tdm_record
+ *  \brief  Structure stores data for TDM record function
+ */
+struct snd_adsp_tdm_record {
+	/* base information of stream */
+	struct snd_adsp_base_info	base;
+
+	/* TDM Capture component data */
+	struct xf_adsp_tdm_capture	*tdm_capture;
+
+	/* TDM Capture component state */
+	int				state;
+};
+
+/** \struct snd_adsp_card
+ *  \brief  Structure stores data for ALSA sound card
+ */
+struct snd_adsp_card {
+	/* playback data */
+	struct snd_adsp_playback	*playback[MAX_DAI_IDX - 1];
+
+	/* record data */
+	struct snd_adsp_record		*record[MAX_DAI_IDX - 1];
+
+	/* TDM playback data */
+	struct snd_adsp_tdm_playback	*tdm_playback;
+
+	/* TDM record data */
+	struct snd_adsp_tdm_record	*tdm_record;
+
+	/* Structure contains params information for control */
+	struct snd_adsp_control		ctr_if;
+};
+
+/** HW configuration of ALSA ADSP card for Renderer/Capture */
+static struct snd_pcm_hardware snd_pcm_adsp_hw = {
+	.info		= (SNDRV_PCM_INFO_INTERLEAVED  /* PRQA S 1053 14 */
+			 | SNDRV_PCM_INFO_RESUME
+			 | SNDRV_PCM_INFO_BLOCK_TRANSFER
+			 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
+	.formats	   = SND_ADSP_PCM_WIDTHS,
+	.rates		   = SND_ADSP_SAMPLE_RATES,
+	.rate_min	   = 32000,
+	.rate_max	   = 48000,
+	.channels_min	   = MIN_CHANNEL,
+	.channels_max	   = MAX_CHANNEL,
+
+	/* maximum buffer size in bytes */
+	.buffer_bytes_max  = MAX_BUFFER_BYTES,
+
+	/* minimum size of the periods (frame) in bytes */
+	.period_bytes_min  = MIN_BUF_SIZE,
+
+	/* maximum size of the periods (frame) in bytes */
+	.period_bytes_max  = MAX_BUF_SIZE,
+
+	/* minimum periods (frames) in a buffer */
+	.periods_min	   = MIN_PERIOD,
+
+	/* maximum periods (frames) in a buffer */
+	.periods_max	   = MAX_PERIOD,
+};
+
+/* HW configuration of ALSA ADSP card for TDM */
+static struct snd_pcm_hardware snd_pcm_adsp_tdm_hw = {
+	.info		  = (SNDRV_PCM_INFO_INTERLEAVED  /* PRQA S 1053 14 */
+			   | SNDRV_PCM_INFO_RESUME
+			   | SNDRV_PCM_INFO_BLOCK_TRANSFER
+			   | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
+	.formats	  = SND_ADSP_PCM_WIDTHS,
+	.rates		  = SND_ADSP_SAMPLE_RATES,
+	.rate_min	  = 32000,
+	.rate_max	  = 48000,
+	.channels_min	  = TDM_MIN_CHANNEL,
+	.channels_max	  = TDM_MAX_CHANNEL,
+
+	/* maximum buffer size in bytes */
+	.buffer_bytes_max = TDM_MAX_BUFFER_BYTES,
+
+	/* minimum size of the periods (frame) in bytes */
+	.period_bytes_min = TDM_MIN_BUF_SIZE,
+
+	/* maximum size of the periods (frame) in bytes */
+	.period_bytes_max = TDM_MAX_BUF_SIZE,
+
+	/* minimum periods (frames) in a buffer */
+	.periods_min	  = TDM_MIN_PERIOD,
+
+	/* maximum periods (frames) in a buffer */
+	.periods_max	  = TDM_MAX_PERIOD,
+};
+
+/*******************************************************************
+ * function declaration
+ * ****************************************************************/
+
+static int
+snd_adsp_rdr_empty_buf_done(void *data, int opcode, int length, char *buffer);
+static int
+snd_adsp_rdr_fill_buf_done(void *data, int opcode, int length, char *buffer);
+static int
+snd_adsp_cap_empty_buf_done(void *data, int opcode, int length, char *buffer);
+static int
+snd_adsp_cap_fill_buf_done(void *data, int opcode, int length, char *buffer);
+static int
+snd_adsp_get_dai_id_from_substream(struct snd_pcm_substream *substream);
+static void *
+snd_adsp_get_drvdata_from_substream(struct snd_pcm_substream *substream);
+static struct snd_adsp_base_info *
+snd_adsp_get_base_from_substream(struct snd_pcm_substream *substream);
+static struct snd_adsp_base_info *
+snd_adsp_get_base_from_hrt(struct hrtimer *hrt);
+static enum hrtimer_restart snd_adsp_hrtimer_func(struct hrtimer *hrt);
+static int snd_adsp_playback_init(struct snd_adsp_playback **data,
+				  int eqz_flag,
+				  struct snd_pcm_substream *substream);
+static int snd_adsp_record_init(struct snd_adsp_record **data,
+				int eqz_flag,
+				struct snd_pcm_substream *substream);
+static int snd_adsp_playback_prepare(struct snd_adsp_playback *playback,
+				     struct snd_pcm_substream *substream);
+static int snd_adsp_record_prepare(struct snd_adsp_record *record,
+				   struct snd_pcm_substream *substream);
+static int snd_adsp_playback_deinit(struct snd_adsp_playback *playback);
+static int snd_adsp_record_deinit(struct snd_adsp_record *record);
+static int snd_adsp_tdm_playback_init(struct snd_adsp_tdm_playback **data,
+				      struct snd_pcm_substream *substream);
+static int snd_adsp_tdm_record_init(struct snd_adsp_tdm_record **data,
+				    struct snd_pcm_substream *substream);
+static int
+snd_adsp_tdm_playback_prepare(struct snd_adsp_tdm_playback *tdm_playback,
+			      struct snd_pcm_substream *substream);
+static int snd_adsp_tdm_record_prepare(struct snd_adsp_tdm_record *tdm_record,
+				       struct snd_pcm_substream *substream);
+static int
+snd_adsp_tdm_playback_deinit(struct snd_adsp_tdm_playback *tdm_playback);
+static int snd_adsp_tdm_record_deinit(struct snd_adsp_tdm_record *tdm_record);
+static int snd_adsp_pcm_open(struct snd_soc_component *component,
+					struct snd_pcm_substream *substream);
+static int snd_adsp_pcm_close(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream);
+static int snd_adsp_pcm_hw_params(struct snd_soc_component *component,
+				struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *hw_params);
+static int snd_adsp_pcm_hw_free(struct snd_soc_component *component,
+					struct snd_pcm_substream *substream);
+static int snd_adsp_pcm_prepare(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream);
+static int snd_adsp_pcm_trigger(struct snd_soc_component *component,
+							struct snd_pcm_substream *substream, int idx);
+static snd_pcm_uframes_t
+snd_adsp_pcm_pointer(struct snd_soc_component *component,
+				struct snd_pcm_substream *substream);
+static int snd_adsp_pcm_ack(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream);
+static void snd_adsp_pcm_transfer(struct snd_pcm_substream *substream,
+				  struct snd_pcm_indirect *rec, size_t bytes);
+static int snd_adsp_control_volume_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo);
+static int snd_adsp_control_volume_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol);
+static int snd_adsp_control_volume_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol);
+static int snd_adsp_control_eqz_get(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol);
+static int snd_adsp_control_eqz_info(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo);
+static int snd_adsp_control_eqz_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol);
+static int
+snd_adsp_control_eqz_switch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol);
+static int
+snd_adsp_control_eqz_switch_info(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_info *uinfo);
+static int
+snd_adsp_control_sample_rate_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol);
+static int
+snd_adsp_control_sample_rate_info(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo);
+static int
+snd_adsp_control_sample_rate_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol);
+static int
+snd_adsp_control_eqz_switch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol);
+static void snd_adsp_get_eqz_params_from_control(
+				struct xf_adsp_equalizer_params *eqz_params,
+				struct xf_adsp_equalizer_params *eqz_ctr_params,
+				bool flag);
+static int snd_adsp_pcm_new(struct snd_soc_component *component,
+				struct snd_soc_pcm_runtime *runtime);
+static int snd_adsp_probe(struct platform_device *pdev);
+static int snd_adsp_remove(struct platform_device *pdev);
+
+/*******************************************************************
+ * callback function of ADSP control interface
+ * ****************************************************************/
+/** **************************************************************************
+ *  \brief	event handler callback to notify error from ADSP
+ *
+ *  \param[in]	data		Pointer to ADSP ALSA sound card
+ *  \retval	0		Success
+ *****************************************************************************/
+static int snd_adsp_event_handler(void *data)
+{
+	struct snd_adsp_base_info *base = (struct snd_adsp_base_info *)data;
+
+	if (base)
+		base->runtime_err = TRUE;
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 empty buf done callback for playback/TDM playback functions
+ *
+ *  \param[in]	  data		Pointer to ADSP ALSA sound card
+ *  \param[in]	  opcode	Opcode of message
+ *  \param[in]	  length	Length of data buffer
+ *  \param[in]	  buffer	Pointer to data buffer
+ *  \retval	  0		Success
+ *****************************************************************************/
+static int
+snd_adsp_rdr_empty_buf_done(void *data, int opcode, int length, char *buffer)
+{
+	struct snd_adsp_base_info *base = (struct snd_adsp_base_info *)data;
+
+	if (base) {
+		spin_lock_irqsave(&base->lock, base->flag);
+
+		base->buf_queue++;
+		base->hw_idx += length; /* increase the DMA buffer index */
+
+		spin_unlock_irqrestore(&base->lock, base->flag);
+	}
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 fill buf done callback for playback/TDM playback functions
+ *
+ *  \param[in]	  data		Pointer to ADSP ALSA sound card
+ *  \param[in]	  opcode	Opcode of message
+ *  \param[in]	  length	Length of data buffer
+ *  \param[in]	  buffer	Pointer to data buffer
+ *  \retval	  0		Success
+ *****************************************************************************/
+static int
+snd_adsp_rdr_fill_buf_done(void *data, int opcode, int length, char *buffer)
+{
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 empty buf done callback for record/TDM record functions
+ *
+ *  \param[in]	  data		Pointer to ADSP ALSA sound card
+ *  \param[in]	  opcode	Opcode of message
+ *  \param[in]	  length	Length of data buffer
+ *  \param[in]	  buffer	Pointer to data buffer
+ *  \retval	  0		Success
+ *****************************************************************************/
+static int
+snd_adsp_cap_empty_buf_done(void *data, int opcode, int length, char *buffer)
+{
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 fill buf done callback for record/TDM record functions
+ *
+ *  \param[in]	  data		Pointer to ADSP ALSA sound card
+ *  \param[in]	  opcode	Opcode of message
+ *  \param[in]	  length	Length of data buffer
+ *  \param[in]	  buffer	Pointer to data buffer
+ * \retval	  0		Success
+ *****************************************************************************/
+static int
+snd_adsp_cap_fill_buf_done(void *data, int opcode, int length, char *buffer)
+{
+	struct snd_adsp_base_info *base = (struct snd_adsp_base_info *)data;
+
+	if (base) {
+		spin_lock_irqsave(&base->lock, base->flag);
+
+		base->buf_queue++;
+		base->hw_idx += length; /* increase the DMA buffer index */
+
+		spin_unlock_irqrestore(&base->lock, base->flag);
+	}
+
+	return 0;
+}
+
+/** callback functions for playback/TDM playback */
+static struct xf_callback_func rdr_callbacks =	/* PRQA S 3218 */
+{
+	.empty_buf_done = &snd_adsp_rdr_empty_buf_done,	/* PRQA S 1053 2 */
+	.fill_buf_done = &snd_adsp_rdr_fill_buf_done,
+	.event_handler = &snd_adsp_event_handler
+};
+
+/** callback functions for record/TDM record */
+static struct xf_callback_func cap_callbacks =	/* PRQA S 3218 */
+{
+	.empty_buf_done = &snd_adsp_cap_empty_buf_done,	/* PRQA S 1053 2 */
+	.fill_buf_done = &snd_adsp_cap_fill_buf_done,
+	.event_handler = &snd_adsp_event_handler
+};
+
+/*******************************************************************
+ * helper functions to get some internal data
+ * ****************************************************************/
+
+/** **************************************************************************
+ *  \brief	Get current index of CPU DAI from runtime data of substream
+ *
+ *  \param[in]	  substream	Pointer to PCM stream data
+ *  \retval	  id		Index of current CPU DAI
+ *****************************************************************************/
+static int
+snd_adsp_get_dai_id_from_substream(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd;
+
+	rtd = asoc_substream_to_rtd(substream);
+	return asoc_rtd_to_cpu(rtd, 0)->id;
+}
+
+/** **************************************************************************
+ *  \brief	Get ADSP ALSA driver's data from runtime data of substream
+ *
+ *  \param[in]	substream	Pointer to PCM stream data
+ *  \retval	pointer		Pointer to driver's data
+ *****************************************************************************/
+static void *
+snd_adsp_get_drvdata_from_substream(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd;
+
+	rtd = asoc_substream_to_rtd(substream);
+	return snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
+}
+
+/** **************************************************************************
+ *  \brief   Get base's data of playback/record from runtime data of substream
+ *
+ *  \param[in]	substream	Pointer to PCM stream data
+ *  \retval	pointer		Pointer to playback/record's base data
+ *****************************************************************************/
+static struct snd_adsp_base_info *
+snd_adsp_get_base_from_substream(struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_card *adsp_card;
+	struct snd_adsp_base_info *base;
+	int dai_idx;
+
+	adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+
+	/* get DAI index of substream */
+	dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+
+	/* get base data of the substream */
+	if (dai_idx == RDR_DAI_IDX0 || dai_idx == RDR_DAI_IDX1 ||
+	    dai_idx == RDR_DAI_IDX2 || dai_idx == RDR_DAI_IDX3) {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			base = !adsp_card->playback[dai_idx] ?
+				NULL : &adsp_card->playback[dai_idx]->base;
+		} else {
+			base = !adsp_card->record[dai_idx] ?
+				NULL : &adsp_card->record[dai_idx]->base;
+		}
+	} else {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			base = !adsp_card->tdm_playback ?
+				NULL : &adsp_card->tdm_playback->base;
+		} else {
+			base = !adsp_card->tdm_record ?
+				NULL : &adsp_card->tdm_record->base;
+		}
+	}
+
+	return base;
+}
+
+/** ***************************************************************************
+ *  \brief    Get playback/record/TDM playback/TDM record's base data
+ *	      from hr timer data
+ *
+ *  \param[in]	hrt		Pointer to hr timer data
+ *  \retval	pointer		Pointer to playback/record's base data
+ *****************************************************************************/
+static struct snd_adsp_base_info *
+snd_adsp_get_base_from_hrt(struct hrtimer *hrt)
+{
+	return (struct snd_adsp_base_info *)hrt;
+}
+
+/*****************************************************************************
+ * hrtimer interrupt function
+ * ***************************************************************************/
+
+/** **************************************************************************
+ *  \brief	Interrupt function of high resolution timer
+ *
+ *  \param[in]	hrt		Pointer to hr timer data
+ *  \retval	HRTIMER_RESTART Restart the timer after expire time
+ *****************************************************************************/
+static enum hrtimer_restart snd_adsp_hrtimer_func(struct hrtimer *hrt)
+{
+	struct snd_adsp_base_info *base = snd_adsp_get_base_from_hrt(hrt);
+
+	spin_lock_irqsave(&base->lock, base->flag);
+	if (base->hw_idx != 0) {
+		spin_unlock_irqrestore(&base->lock, base->flag);
+		/* update PCM status for the next period */
+		snd_pcm_period_elapsed(base->substream);
+	} else {
+		spin_unlock_irqrestore(&base->lock, base->flag);
+	}
+
+	hrtimer_forward_now(hrt, base->ktime);
+
+	return HRTIMER_RESTART;
+}
+
+/*****************************************************************************
+ * internal functions to manage playback and record functions
+ * ***************************************************************************/
+
+/** **************************************************************************
+ *  \brief	Initialize playback data
+ *
+ *  \param[out]	  playback_data		Pointer to store playback data
+ *  \param[in]	  eqz_flag		Flag to indicate equalizer usage
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	  EINVAL		Failed to initialize playback data
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int snd_adsp_playback_init(struct snd_adsp_playback **playback_data,
+				  int eqz_flag,
+				  struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_playback *playback;
+
+	/* allocate memory for playback data */
+	playback = kmalloc(sizeof(*playback), GFP_KERNEL);
+	if (!playback)
+		return -EINVAL;
+
+	/* init params */
+	memset(playback, 0, sizeof(struct snd_adsp_playback));
+
+	/* save the playback data */
+	*playback_data = playback;
+
+	/* set handle state as NULL state */
+	playback->rdr_state = XF_HANDLE_NULL;
+	playback->eqz_state = XF_HANDLE_NULL;
+	playback->base.hrt_state = XF_HANDLE_NULL;
+
+	/* register renderer component */
+	if (xf_adsp_renderer_create(&playback->renderer,
+				    &rdr_callbacks,
+				    (void *)&playback->base) < 0)
+		return -EINVAL;
+
+	/* mark renderer component created */
+	playback->rdr_state = XF_HANDLE_CREATED;
+
+	/* set target handle ID as renderer ID */
+	playback->base.handle_id = playback->renderer->handle_id;
+
+	if (eqz_flag == EQZ_ON) {
+		/* create equalizer component when equalizer is used */
+		if (xf_adsp_equalizer_create(&playback->equalizer,
+					     &rdr_callbacks,
+					     (void *)&playback->base) < 0)
+			return -EINVAL;
+
+		/* mark equalizer component created */
+		playback->eqz_state = XF_HANDLE_CREATED;
+
+		/* set target handle ID as equalizer ID */
+		playback->base.handle_id = playback->equalizer->handle_id;
+	}
+
+	/* init lock */
+	spin_lock_init(&playback->base.lock);
+
+	/* save the substream data */
+	playback->base.substream = substream;
+
+	/* init high resolution timer for updating hw status */
+	hrtimer_init(&playback->base.hrtimer,
+		     CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+
+	/* PRQA S 0563 1 */
+	playback->base.hrtimer.function = &snd_adsp_hrtimer_func;
+	playback->base.hrt_state = XF_HANDLE_CREATED;
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Initialize record data
+ *
+ *  \param[out]	 record_data	Pointer to store record data
+ *  \param[in]	 eqz_flag	Flag to indicate equalizer usage
+ *  \param[in]	 substream	Pointer to substream data
+ *  \retval	-EINVAL		Failed to initialize record data
+ *  \retval	 0		Success
+ *****************************************************************************/
+static int snd_adsp_record_init(struct snd_adsp_record **record_data,
+				int eqz_flag,
+				struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_record *record;
+
+	/* allocate memory for record data */
+	record = kmalloc(sizeof(*record), GFP_KERNEL);
+	if (!record)
+		return -EINVAL;
+
+	/* init params */
+	memset(record, 0, sizeof(struct snd_adsp_record));
+
+	/* save the record data */
+	*record_data = record;
+
+	/* set handle state as NULL state */
+	record->cap_state = XF_HANDLE_NULL;
+	record->eqz_state = XF_HANDLE_NULL;
+	record->base.hrt_state = XF_HANDLE_NULL;
+
+	/* register capture component */
+	if (xf_adsp_capture_create(&record->capture,
+				   &cap_callbacks,
+				   (void *)&record->base) < 0)
+		return -EINVAL;
+
+	/* mark capture component created */
+	record->cap_state = XF_HANDLE_CREATED;
+
+	/* set target handle ID as capture ID */
+	record->base.handle_id = record->capture->handle_id;
+
+	/* create equalizer component in case of it being used */
+	if (eqz_flag == EQZ_ON) {
+		if (xf_adsp_equalizer_create(&record->equalizer,
+					     &cap_callbacks,
+					     (void *)&record->base) < 0)
+			return -EINVAL;
+
+		/* mark equalizer component created */
+		record->eqz_state = XF_HANDLE_CREATED;
+
+		/* set target handle ID as equalizer ID */
+		record->base.handle_id = record->equalizer->handle_id;
+	}
+
+	/* init lock */
+	spin_lock_init(&record->base.lock);
+
+	/* save the substream data */
+	record->base.substream = substream;
+
+	/* init high resolution timer for updating hw status */
+	hrtimer_init(&record->base.hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+
+	/* PRQA S 0563 1 */
+	record->base.hrtimer.function = &snd_adsp_hrtimer_func;
+	record->base.hrt_state = XF_HANDLE_CREATED;
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Prepare playback function
+ *
+ *  \param[out]	  playback		Pointer to playback data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	 -EINVAL		Failed to prepare playback function
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int snd_adsp_playback_prepare(struct snd_adsp_playback *playback,
+				     struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_card *adsp_card;
+	int dai_idx, pcm_width, ch, fs, frame_size, vol_rate, hw_buffer_size;
+	int out_rate;
+	struct snd_adsp_control *ctr_if;
+	struct snd_pcm_runtime *runtime;
+	struct xf_adsp_renderer *renderer;
+	struct xf_adsp_equalizer *equalizer;
+	struct snd_adsp_base_info *base;
+	int i;
+
+	adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+	dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+	ctr_if = &adsp_card->ctr_if;
+	runtime = substream->runtime;
+	renderer = playback->renderer;
+	equalizer = playback->equalizer;
+	base = &playback->base;
+
+	/* runtime parameter */
+	fs = runtime->rate;
+	ch = runtime->channels;
+	pcm_width = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 24;
+	frame_size = runtime->period_size;
+	vol_rate = ctr_if->vol_rate[DIRECT_PLAYBACK][dai_idx];
+	out_rate = ctr_if->sample_rate[DIRECT_PLAYBACK][dai_idx];
+	hw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+	/* get number of bytes in a period */
+	base->period_bytes = snd_pcm_lib_period_bytes(substream);
+
+	if (pcm_width == 16)
+		base->buf_bytes = base->period_bytes;
+	else
+		base->buf_bytes = (base->period_bytes *
+			BYTES_PER_SAMPLE(S24_3LE)) / BYTES_PER_SAMPLE(S24_LE);
+
+	/* pcm indirect configuration */
+	base->pcm_indirect.hw_buffer_size = hw_buffer_size;
+	base->pcm_indirect.sw_buffer_size = base->pcm_indirect.hw_buffer_size;
+
+	/* it should equal to a period size in bytes */
+	base->pcm_indirect.hw_queue_size = base->period_bytes;
+
+	/* set parameters when Renderer is not ready */
+	if (COMPONENT_IS_READY(playback->rdr_state) == FALSE) {
+		struct xf_adsp_renderer_params *params = &renderer->params;
+
+		/* apply renderer parameters */
+		params->in_rate = fs;
+		params->channel = ch;
+		params->pcm_width = pcm_width;
+		params->frame_size = frame_size;
+
+		if (ctr_if->mix_usage == SECOND_RUN)
+			params->mix_ctrl = ctr_if->mix_usage;
+		else
+			params->mix_ctrl = MIX_UNUSED;
+
+		/* set flow as ADSP->PDMA0->SRC0->PDMA1->SSI0 */
+		params->dev1 = SRC0;
+		params->dev2 = SSI00;
+		params->dma1 = PDMA_CH00;
+		params->dma2 = PDMA_CH01;
+
+		/* when MIX is enabled, change to DMAC transfer type to save */
+		/* hw FIFO */
+		if (MIX_ENABLED(params->mix_ctrl) == TRUE)
+			params->dma1 = ADMAC_CH01;
+
+		/* set volume rate if it is set by user or default value */
+		/* is 100% */
+		if (vol_rate >= 0)
+			params->vol_rate = vol_rate;
+		else
+			params->vol_rate = (1 << 20);
+
+		/* set output channel if it is set by user */
+		if (ctr_if->rdr_out_ch[dai_idx] >= MONAURAL)
+			params->out_channel = ctr_if->rdr_out_ch[dai_idx];
+		else
+			params->out_channel = params->channel;
+
+		/* set sample rate output if it is set by user */
+		if (out_rate >= 0)
+			params->out_rate = out_rate;
+
+		/* set parameters to ADSP Renderer plugin */
+		if (xf_adsp_renderer_set_params(renderer) != 0)
+			return -EINVAL;
+
+		/* allocate buffer pool to prepare the execution */
+		renderer->buf_pool = xf_adsp_allocate_mem_pool(
+				XF_BUF_POOL_SIZE, base->buf_bytes);
+
+		if (IS_ERR(renderer->buf_pool))	/* PRQA S 306*/
+			return -EINVAL;
+
+		for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+			base->buffer[i] = xf_adsp_get_data_from_pool(
+					renderer->buf_pool, i);
+
+			base->buf_queue++;
+			memset(base->buffer[i], 0, base->buf_bytes);
+		}
+
+		/* mark Renderer ready */
+		playback->rdr_state |= XF_HANDLE_READY;
+
+		/* set parameters for Equalizer if it is used */
+		if (COMPONENT_IS_CREATED(playback->eqz_state) == TRUE) {
+			/* apply Equalizer parameter setting */
+			equalizer->params.channel = ch;
+			equalizer->params.pcm_width = pcm_width;
+			equalizer->params.rate = fs;
+
+			/* get equalizer parameters from control interface */
+			/* data */
+			snd_adsp_get_eqz_params_from_control(
+				&equalizer->params,
+				&ctr_if->eqz_params[DIRECT_PLAYBACK][dai_idx],
+				true);
+
+			/* set parameters to Equalizer plugin */
+			if (xf_adsp_equalizer_set_params(equalizer) != 0)
+				return -EINVAL;
+
+			/* route Equalizer to Renderer */
+			if (xf_adsp_route(equalizer->handle_id,
+					  renderer->handle_id,
+					  XF_BUF_POOL_SIZE,
+					  base->buf_bytes) != 0)
+				return -EINVAL;
+
+			/* mark Equalizer ready */
+			playback->eqz_state |= XF_HANDLE_READY;
+
+			/* prepare data before start PCM */
+			/* PRQA S 2462 1 */ /* PRQA S 2463 1 */
+			for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+				/* send buffer to plugin to kick */
+				/* init-processing */
+				if (xf_adsp_empty_this_buffer(
+							base->handle_id,
+							base->buffer[i],
+							base->buf_bytes) != 0)
+					return -EINVAL;
+
+				spin_lock_irqsave(&base->lock, base->flag);
+				base->buf_queue--;
+				spin_unlock_irqrestore(&base->lock, base->flag);
+			}
+		} else {
+			/* send zero buffer to plugin to kick */
+			/* init-processing */
+			if (xf_adsp_empty_this_buffer(base->handle_id,
+						      base->buffer[0],
+						      base->buf_bytes) != 0)
+				return -EINVAL;
+
+			spin_lock_irqsave(&base->lock, base->flag);
+			base->buf_queue--;
+			spin_unlock_irqrestore(&base->lock, base->flag);
+		}
+
+		/* wait until all the buffer have been consummed */
+		while (base->buf_queue != XF_BUF_POOL_SIZE) {
+			schedule_timeout_interruptible(2);
+			if (signal_pending(current))
+				break;
+
+			/* check the error from initialization */
+			if (base->runtime_err)
+				return -EINVAL;
+		}
+
+		/* reset HW index */
+		base->hw_idx = 0;
+	}
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Prepare record function
+ *
+ *  \param[out]	  record		Pointer to record data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	 -EINVAL		Failed to prepare record function
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int snd_adsp_record_prepare(struct snd_adsp_record *record,
+				   struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_card *adsp_card;
+	int dai_idx, pcm_width, ch, fs, frame_size, vol_rate, in_rate;
+	int hw_buffer_size, hw_queue_size;
+	struct snd_adsp_control *ctr_if;
+	struct snd_pcm_runtime *runtime;
+	struct xf_adsp_capture *capture;
+	struct xf_adsp_equalizer *equalizer;
+	struct snd_adsp_base_info *base;
+	int i;
+
+	adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+	dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+	ctr_if = &adsp_card->ctr_if;
+	runtime = substream->runtime;
+	capture = record->capture;
+	equalizer = record->equalizer;
+	base = &record->base;
+
+	/* runtime parameter */
+	fs = runtime->rate;
+	ch = runtime->channels;
+	pcm_width = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 24;
+	frame_size = runtime->period_size;
+	vol_rate = ctr_if->vol_rate[DIRECT_CAPTURE][dai_idx];
+	in_rate = ctr_if->sample_rate[DIRECT_CAPTURE][dai_idx];
+	hw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+	/* total size of allocated buffers */
+	hw_queue_size = base->period_bytes * XF_BUF_POOL_SIZE;
+
+	/* get number of bytes in a period */
+	base->period_bytes = snd_pcm_lib_period_bytes(substream);
+
+	if (pcm_width == 16)
+		base->buf_bytes = base->period_bytes;
+	else
+		base->buf_bytes = ((base->period_bytes *
+			BYTES_PER_SAMPLE(S24_3LE)) / BYTES_PER_SAMPLE(S24_LE));
+
+	/* pcm indirect configuration */
+	base->pcm_indirect.hw_buffer_size = hw_buffer_size;
+	base->pcm_indirect.sw_buffer_size = base->pcm_indirect.hw_buffer_size;
+	base->pcm_indirect.hw_queue_size = hw_queue_size;
+
+	/* prepare parameters to set to Capture plugin when it is not yet */
+	/* ready */
+	if (COMPONENT_IS_READY(record->cap_state) == FALSE) {
+		struct xf_adsp_capture_params *params = &capture->params;
+
+		/* apply capture parameters */
+		params->out_rate = fs;
+		params->channel = ch;
+		params->pcm_width = pcm_width;
+		params->frame_size = frame_size;
+
+		params->dev1 = SRC0;
+		params->dev2 = SSI10;
+		params->dma1 = PDMA_CH00;
+		params->dma2 = PDMA_CH01;
+
+		/* set volume rate if it is set by user or default volume as */
+		/* 100% */
+		if (vol_rate >= 0)
+			params->vol_rate = vol_rate;
+		else
+			params->vol_rate = (1 << 20);
+
+		/* set sample rate input if it is set by user */
+		if (in_rate >= 0)
+			params->in_rate = in_rate;
+
+		/* allocate buffer pool to prepare the execution */
+		capture->buf_pool = xf_adsp_allocate_mem_pool(
+				XF_BUF_POOL_SIZE, base->buf_bytes);
+
+		if (IS_ERR(capture->buf_pool))		 /* PRQA S 306 */
+			return -EINVAL;
+
+		for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+			base->buffer[i] = xf_adsp_get_data_from_pool(
+					capture->buf_pool, i);
+
+			base->buf_queue++;
+		}
+
+		/* set parameters to ADSP Capture plugin */
+		if (xf_adsp_capture_set_params(capture) != 0)
+			return -EINVAL;
+
+		/* mark Capture ready */
+		record->cap_state |= XF_HANDLE_READY;
+
+		/* set parameters for Equalizer if it's used */
+		if (COMPONENT_IS_CREATED(record->eqz_state) == TRUE) {
+			/* apply Equalizer parameter setting */
+			equalizer->params.channel = ch;
+			equalizer->params.pcm_width = pcm_width;
+			equalizer->params.rate = fs;
+
+			/* get equalizer parameter from control interface */
+			/* data */
+			snd_adsp_get_eqz_params_from_control(
+				&equalizer->params,
+				&ctr_if->eqz_params[DIRECT_CAPTURE][dai_idx],
+				true);
+
+			/* set parameters to Equalizer plugin */
+			if (xf_adsp_equalizer_set_params(equalizer) != 0)
+				return -EINVAL;
+
+			/* route Capture to Equalizer */
+			if (xf_adsp_route(capture->handle_id,
+					  equalizer->handle_id,
+					  XF_BUF_POOL_SIZE,
+					  base->buf_bytes) != 0)
+				return -EINVAL;
+
+			/* mark Equalizer ready */
+			record->eqz_state |= XF_HANDLE_READY;
+		}
+
+		/* kick init process by sending a zero buffer length */
+		xf_adsp_fill_this_buffer(base->handle_id, base->buffer[0], 0);
+
+		spin_lock_irqsave(&base->lock, base->flag);
+		base->buf_queue--;
+		spin_unlock_irqrestore(&base->lock, base->flag);
+
+		/* wait until finishing initialization */
+		while (base->buf_queue != XF_BUF_POOL_SIZE) {
+			schedule_timeout_interruptible(2);
+			if (signal_pending(current))
+				break;
+
+			/* check the error from initialization */
+			if (base->runtime_err)
+				return -EINVAL;
+		}
+
+		if (COMPONENT_IS_CREATED(record->eqz_state) == TRUE) {
+			/* PRQA S 2462 1 */ /* PRQA S 2463 1 */
+			for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+				/* send buffer to plugin */
+				if (xf_adsp_fill_this_buffer(
+						base->handle_id,
+						base->buffer[i],
+						base->buf_bytes) != 0)
+					return -EINVAL;
+
+				spin_lock_irqsave(&base->lock, base->flag);
+				base->buf_queue--;
+				spin_unlock_irqrestore(&base->lock, base->flag);
+			}
+
+			/* wait until all the buffer have been responsed */
+			while (base->buf_queue != XF_BUF_POOL_SIZE) {
+				schedule_timeout_interruptible(2);
+				if (signal_pending(current))
+					break;
+
+				/* check the error from initialization */
+				if (base->runtime_err)
+					return -EINVAL;
+			}
+		}
+
+		/* reset hw data position */
+		base->hw_idx = 0;
+	}
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Deinitialize playback function
+ *
+ *  \param[out]	playback	Pointer to playback data
+ *  \retval	-EINVAL		Failed to deinitialize playback function
+ *  \retval	0		Success
+ *****************************************************************************/
+static int snd_adsp_playback_deinit(struct snd_adsp_playback *playback)
+{
+	int ret = 0;
+
+	/* perform de-initialization if playback has been created already */
+	if (playback) {
+		/* perform completion process */
+		if (COMPONENT_IS_CREATED(playback->rdr_state) == TRUE) {
+			/* send buffer with zero length to plugin for */
+			/* completion process *//* PRQA S 3200 2 */
+			xf_adsp_empty_this_buffer(playback->base.handle_id,
+						  NULL, 0);
+
+			/* free buffer pool */ /* PRQA S 3200 1 */
+			xf_adsp_free_mem_pool(playback->renderer->buf_pool);
+
+			/* destroy Renderer */
+			if (xf_adsp_renderer_destroy(playback->renderer) != 0)
+				ret = -EINVAL;
+
+			playback->renderer = NULL;
+		}
+
+		/* destroy Equalizer if it is used */
+		if (COMPONENT_IS_CREATED(playback->eqz_state) == TRUE) {
+			if (xf_adsp_equalizer_destroy(playback->equalizer))
+				ret = -EINVAL;
+
+			playback->equalizer = NULL;
+		}
+
+		/* canncel timer interrupt */
+		if (COMPONENT_IS_CREATED(playback->base.hrt_state) == TRUE)
+			hrtimer_cancel(&playback->base.hrtimer);
+
+		/* free playback data */
+		kfree(playback);
+	}
+
+	return ret;
+}
+
+/** **************************************************************************
+ *  \brief	Deinitialize record function
+ *
+ *  \param[out]	 record		Pointer to record data
+ *  \retval	 -EINVAL	Failed to deinitialize record function
+ *  \retval	 0		Success
+ *****************************************************************************/
+static int snd_adsp_record_deinit(struct snd_adsp_record *record)
+{
+	int ret = 0;
+
+	/* perform de-initialization if record has been created already */
+	if (!record)
+		return ret;
+
+	/* perform completion process */
+	if (COMPONENT_IS_CREATED(record->cap_state) == TRUE) {
+		/* send buffer with zero length to plugin for */
+		/* completion process *//* PRQA S 3200 2 */
+		xf_adsp_empty_this_buffer(record->base.handle_id, NULL, 0);
+
+		/* free buffer pool */ /* PRQA S 3200 1 */
+		xf_adsp_free_mem_pool(record->capture->buf_pool);
+
+		if (xf_adsp_capture_destroy(record->capture))
+			ret = -EINVAL;
+
+		record->capture = NULL;
+	}
+
+	/* destroy Equalizer if it is used */
+	if (COMPONENT_IS_CREATED(record->eqz_state) == TRUE) {
+		if (xf_adsp_equalizer_destroy(record->equalizer) != 0)
+			ret = -EINVAL;
+
+		record->equalizer = NULL;
+	}
+
+	/* canncel timer interrupt */
+	if (COMPONENT_IS_CREATED(record->base.hrt_state) == TRUE)
+		hrtimer_cancel(&record->base.hrtimer);
+
+	/* free record data */
+	kfree(record);
+
+	return ret;
+}
+
+/*****************************************************************************
+ * internal functions to manage TDM playback and TDM record functions
+ * ***************************************************************************/
+
+/** **************************************************************************
+ *  \brief	Initialize TDM playback data
+ *
+ *  \param[out]	tdm_playback_data	Pointer to store TDM playback data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	  -EINVAL		Failed to initialize TDM playback data
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int
+snd_adsp_tdm_playback_init(struct snd_adsp_tdm_playback **tdm_playback_data,
+			   struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_tdm_playback *tdm_playback;
+
+	/* allocate memory for TDM playback data */
+	tdm_playback = kmalloc(sizeof(*tdm_playback), GFP_KERNEL);
+
+	if (!tdm_playback)
+		return -EINVAL;
+
+	/* init params */
+	memset(tdm_playback, 0, sizeof(struct snd_adsp_tdm_playback));
+
+	/* save the TDM playback data */
+	*tdm_playback_data = tdm_playback;
+
+	/* set handle state as NULL state */
+	tdm_playback->state = XF_HANDLE_NULL;
+	tdm_playback->base.hrt_state = XF_HANDLE_NULL;
+
+	/* register TDM renderer component */
+	if (xf_adsp_tdm_renderer_create(&tdm_playback->tdm_renderer,
+					&rdr_callbacks,
+					(void *)&tdm_playback->base) < 0)
+		return -EINVAL;
+
+	/* mark TDM renderer component created */
+	tdm_playback->state = XF_HANDLE_CREATED;
+
+	/* set target handle ID as TDM renderer ID */
+	tdm_playback->base.handle_id = tdm_playback->tdm_renderer->handle_id;
+
+	/* init lock */
+	spin_lock_init(&tdm_playback->base.lock);
+
+	/* save the substream data */
+	tdm_playback->base.substream = substream;
+
+	/* init high resolution timer for updating hw status */
+	hrtimer_init(&tdm_playback->base.hrtimer,
+		     CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+
+	/* PRQA S 0563 1 */
+	tdm_playback->base.hrtimer.function = &snd_adsp_hrtimer_func;
+	tdm_playback->base.hrt_state = XF_HANDLE_CREATED;
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Initialize TDM record data
+ *
+ *  \param[out]	  tdm_record_data	Pointer to store TDM record data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	  -EINVAL		Failed to initialize TDM record data
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int
+snd_adsp_tdm_record_init(struct snd_adsp_tdm_record **tdm_record_data,
+			 struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_tdm_record *tdm_record;
+
+	/* allocate memory for TDM record data */
+	tdm_record = kmalloc(sizeof(*tdm_record), GFP_KERNEL);
+	if (!tdm_record)
+		return -EINVAL;
+
+	/* init params */
+	memset(tdm_record, 0, sizeof(struct snd_adsp_tdm_record));
+
+	/* save the TDM record data */
+	*tdm_record_data = tdm_record;
+
+	/* set handle state as NULL state */
+	tdm_record->state = XF_HANDLE_NULL;
+	tdm_record->base.hrt_state = XF_HANDLE_NULL;
+
+	/* register TDM Capture component */
+	if (xf_adsp_tdm_capture_create(&tdm_record->tdm_capture,
+				       &cap_callbacks,
+				       (void *)&tdm_record->base) != 0)
+		return -EINVAL;
+
+	/* mark TDM capture component created */
+	tdm_record->state = XF_HANDLE_CREATED;
+
+	/* set target handle ID as TDM capture ID */
+	tdm_record->base.handle_id = tdm_record->tdm_capture->handle_id;
+
+	/* init lock */
+	spin_lock_init(&tdm_record->base.lock);
+
+	/* save the substream data */
+	tdm_record->base.substream = substream;
+
+	/* init high resolution timer for updating hw status */
+	hrtimer_init(&tdm_record->base.hrtimer,
+		     CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+
+	/* PRQA S 0563 1 */
+	tdm_record->base.hrtimer.function = &snd_adsp_hrtimer_func;
+	tdm_record->base.hrt_state = XF_HANDLE_CREATED;
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Prepare TDM playback function
+ *
+ *  \param[out]	  tdm_playback		Pointer to TDM playback data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	  -EINVAL		Failed to prepare TDM playback function
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int
+snd_adsp_tdm_playback_prepare(struct snd_adsp_tdm_playback *tdm_playback,
+			      struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_card *adsp_card;
+	struct snd_adsp_control *ctr_if;
+	struct snd_pcm_runtime *runtime;
+	struct xf_adsp_tdm_renderer *tdm_renderer;
+	struct snd_adsp_base_info *base;
+	int i;
+	int pcm_width, ch_mode, fs, frame_size, hw_buffer_size;
+
+	adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+	ctr_if = &adsp_card->ctr_if;
+	runtime = substream->runtime;
+	tdm_renderer = tdm_playback->tdm_renderer;
+	base = &tdm_playback->base;
+
+	/* runtime parameter */
+	fs = runtime->rate;
+	pcm_width = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 24;
+	frame_size = runtime->period_size;
+
+	ch_mode = (runtime->channels == 8) ?
+		XA_TDM_RDR_CHANNEL_MODE_1X8 : XA_TDM_RDR_CHANNEL_MODE_1X6;
+
+	hw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+	/* get number of bytes in a period */
+	base->period_bytes = snd_pcm_lib_period_bytes(substream);
+
+	if (pcm_width == 16)
+		base->buf_bytes = base->period_bytes;
+	else
+		base->buf_bytes = ((base->period_bytes *
+			BYTES_PER_SAMPLE(S24_3LE)) / BYTES_PER_SAMPLE(S24_LE));
+
+	/* pcm indirect configuration */
+	base->pcm_indirect.hw_buffer_size = hw_buffer_size;
+	base->pcm_indirect.sw_buffer_size = base->pcm_indirect.hw_buffer_size;
+
+	/* it should equal to a period size in bytes */
+	base->pcm_indirect.hw_queue_size = base->period_bytes;
+
+	/* prepare parameters to set to TDM playback as it is not ready */
+	if (COMPONENT_IS_READY(tdm_playback->state) == FALSE) {
+		struct xf_adsp_tdm_renderer_params *params;
+
+		params = &tdm_renderer->params;
+
+		/* apply renderer parameters */
+		params->in_rate = fs;
+		params->ch_mode = ch_mode;
+		params->pcm_width = pcm_width;
+		params->frame_size = frame_size;
+
+		/* setting Audio device indexes */
+		params->dma1 = ADMAC_CH00; /* use DMAC for transfer data */
+		params->dma2 = PDMA_CH03;
+		params->dev1 = SRC1;
+		params->dev2 = SSI30;  /* set SSI index to SSI30 */
+
+		/* set volume rate if it is set by user or default value as */
+		/* 100% */
+		params->vol_rate = (ctr_if->tdm_vol_rate[DIRECT_PLAYBACK] >= 0)
+			? ctr_if->tdm_vol_rate[DIRECT_PLAYBACK] : (1 << 20);
+
+		/* set output sampling rate if it is set by user */
+		if (ctr_if->tdm_sample_rate[DIRECT_PLAYBACK] >= 0)
+			params->out_rate =
+				ctr_if->tdm_sample_rate[DIRECT_PLAYBACK];
+
+		/* set parameters to ADSP TDM Renderer plugin */
+		if (xf_adsp_tdm_renderer_set_params(tdm_renderer) != 0)
+			return -EINVAL;
+
+		/* allocate buffer pool to prepare the execution */
+		tdm_renderer->buf_pool = xf_adsp_allocate_mem_pool(
+				XF_BUF_POOL_SIZE, base->buf_bytes);
+
+		if (IS_ERR(tdm_renderer->buf_pool))	/* PRQA S 306*/
+			return -EINVAL;
+
+		for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+			base->buffer[i] = xf_adsp_get_data_from_pool(
+					tdm_renderer->buf_pool, i);
+
+			base->buf_queue++;
+		}
+
+		/* mark TDM Renderer created */
+		tdm_playback->state |= XF_HANDLE_READY;
+
+		/* send zero buffer to plugin to kick init-processing */
+		memset(base->buffer[0], 0, base->buf_bytes);
+
+		if (xf_adsp_empty_this_buffer(base->handle_id, base->buffer[0],
+					      base->buf_bytes) != 0)
+			return -EINVAL;
+
+		spin_lock_irqsave(&base->lock, base->flag);
+		base->buf_queue--;
+		spin_unlock_irqrestore(&base->lock, base->flag);
+
+		/* wait until all the buffer have been consummed */
+		while (base->buf_queue != XF_BUF_POOL_SIZE) {
+			schedule_timeout_interruptible(2);
+			if (signal_pending(current))
+				break;
+
+			/* check the error from initialization */
+			if (base->runtime_err)
+				return -EINVAL;
+		}
+
+		/* reset HW index */
+		base->hw_idx = 0;
+	}
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Prepare TDM record function
+ *
+ *  \param[out]	  tdm_record		Pointer to TDM record data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	  -EINVAL		Failed to prepare TDM record function
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int snd_adsp_tdm_record_prepare(struct snd_adsp_tdm_record *tdm_record,
+				       struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_card *adsp_card =
+		snd_adsp_get_drvdata_from_substream(substream);
+	struct snd_adsp_control *ctr_if = &adsp_card->ctr_if;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct xf_adsp_tdm_capture *tdm_capture = tdm_record->tdm_capture;
+	struct snd_adsp_base_info *base = &tdm_record->base;
+	int i;
+	int pcm_width, ch_mode, fs, frame_size;
+
+	/* runtime parameter */
+	fs = runtime->rate;
+
+	ch_mode = (runtime->channels == 8) ?
+		XA_TDM_RDR_CHANNEL_MODE_1X8 : XA_TDM_RDR_CHANNEL_MODE_1X6;
+
+	pcm_width = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 24;
+	frame_size = runtime->period_size;
+
+	/* get number of bytes in a period */
+	base->period_bytes = snd_pcm_lib_period_bytes(substream);
+	base->buf_bytes = (pcm_width == 16) ?
+			   base->period_bytes : ((base->period_bytes *
+						BYTES_PER_SAMPLE(S24_3LE)) /
+						BYTES_PER_SAMPLE(S24_LE));
+
+	/* pcm indirect configuration */
+	base->pcm_indirect.hw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	base->pcm_indirect.sw_buffer_size = base->pcm_indirect.hw_buffer_size;
+
+	/* total size of allocated buffers */
+	base->pcm_indirect.hw_queue_size = base->period_bytes *
+					   XF_BUF_POOL_SIZE;
+
+	/* prepare parameters to set to TDM Capture as it is not yet ready */
+	if (COMPONENT_IS_READY(tdm_record->state) == FALSE) {
+		struct xf_adsp_tdm_capture_params *params;
+
+		params = &tdm_capture->params;
+
+		/* apply capture parameters */
+		params->out_rate = fs;
+		params->ch_mode = ch_mode;
+		params->pcm_width = pcm_width;
+		params->frame_size = frame_size;
+
+		/* setting Audio device indexes */
+		params->dma1 = PDMA_CH00;
+		params->dma2 = PDMA_CH01;
+		params->dev1 = SRC0;
+		params->dev2 = SSI40;  /* set input device is SSI40 */
+
+		/* set volume rate if it is set by user or default value as */
+		/* 100% */
+		params->vol_rate = (ctr_if->tdm_vol_rate[DIRECT_CAPTURE] >= 0)
+			? ctr_if->tdm_vol_rate[DIRECT_CAPTURE] : (1 << 20);
+
+		/* set input rate if it is set by user */
+		if (ctr_if->tdm_sample_rate[DIRECT_CAPTURE] >= 0) {
+			params->in_rate =
+				ctr_if->tdm_sample_rate[DIRECT_CAPTURE];
+		}
+
+		/* allocate buffer pool to prepare the execution */
+		tdm_capture->buf_pool = xf_adsp_allocate_mem_pool(
+				XF_BUF_POOL_SIZE, base->buf_bytes);
+
+		if (IS_ERR(tdm_capture->buf_pool))	/* PRQA S 306 */
+			return -EINVAL;
+
+		for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+			base->buffer[i] = xf_adsp_get_data_from_pool(
+					tdm_capture->buf_pool, i);
+
+			base->buf_queue++;
+		}
+
+		/* set parameters to ADSP TDM Capture plugin */
+		if (xf_adsp_tdm_capture_set_params(tdm_capture) != 0)
+			return -EINVAL;
+
+		/* mark TDM Capture ready */
+		tdm_record->state |= XF_HANDLE_READY;
+
+		/* kick init process by sending a zero buffer length */
+		xf_adsp_fill_this_buffer(base->handle_id, base->buffer[0], 0);
+
+		spin_lock_irqsave(&base->lock, base->flag);
+		base->buf_queue--;
+		spin_unlock_irqrestore(&base->lock, base->flag);
+
+		/* wait until finishing initialization */
+		while (base->buf_queue != XF_BUF_POOL_SIZE) {
+			schedule_timeout_interruptible(2);
+			if (signal_pending(current))
+				break;
+
+			/* check the error from initialization */
+			if (base->runtime_err)
+				return -EINVAL;
+		}
+
+		/* reset hw data position */
+		base->hw_idx = 0;
+	}
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Deinitialize TDM playback function
+ *
+ *  \param[out]	  tdm_playback	Pointer to TDM playback data
+ *  \retval	  -EINVAL	Failed to deinitialize TDM playback function
+ *  \retval	  0		Success
+ *****************************************************************************/
+static int
+snd_adsp_tdm_playback_deinit(struct snd_adsp_tdm_playback *tdm_playback)
+{
+	int ret = 0;
+
+	/* perform de-initialization if TDM playback has been created */
+	if (!tdm_playback)
+		return ret;
+
+	/* perform completion process */
+	if (COMPONENT_IS_CREATED(tdm_playback->state) == TRUE) {
+		/* send buffer with zero length to plugin for */
+		/* completion process */
+		/* PRQA S 3200 2 */
+		xf_adsp_empty_this_buffer(tdm_playback->base.handle_id,
+					  NULL, 0);
+
+		/* free buffer pool *//* PRQA S 3200 2 */
+		xf_adsp_free_mem_pool(tdm_playback->tdm_renderer->buf_pool);
+
+		/* destroy TDM Renderer component */
+		if (xf_adsp_tdm_renderer_destroy(
+				tdm_playback->tdm_renderer) != 0)
+			ret = -EINVAL;
+
+		tdm_playback->tdm_renderer = NULL;
+	}
+
+	/* canncel timer interrupt */
+	if (COMPONENT_IS_CREATED(tdm_playback->base.hrt_state) == TRUE)
+		hrtimer_cancel(&tdm_playback->base.hrtimer);
+
+	/* free playback data */
+	kfree(tdm_playback);
+
+	return ret;
+}
+
+/** **************************************************************************
+ *  \brief	Deinitialize TDM record function
+ *
+ *  \param[out]	 tdm_record	Pointer to TDM record data
+ *  \retval	 -EINVAL	Failed to deinitialize TDM record function
+ *  \retval	 0		Success
+ *****************************************************************************/
+static int snd_adsp_tdm_record_deinit(struct snd_adsp_tdm_record *tdm_record)
+{
+	int ret = 0;
+
+	/* perform de-initialization if TDM record has been created already */
+	if (!tdm_record)
+		return ret;
+
+	/* perform completion process */
+	if (COMPONENT_IS_CREATED(tdm_record->state) == TRUE) {
+		/* send buffer with zero length to plugin for */
+		/* completion process */
+		/* PRQA S 3200 2 */
+		xf_adsp_empty_this_buffer(tdm_record->base.handle_id, NULL, 0);
+
+		/* free buffer pool *//* PRQA S 3200 2 */
+		xf_adsp_free_mem_pool(tdm_record->tdm_capture->buf_pool);
+
+		/* destroy TDM Capture component */
+		if (xf_adsp_tdm_capture_destroy(tdm_record->tdm_capture) != 0)
+			ret = -EINVAL;
+
+		tdm_record->tdm_capture = NULL;
+	}
+
+	/* canncel timer interrupt */
+	if (COMPONENT_IS_CREATED(tdm_record->base.hrt_state) == TRUE)
+		hrtimer_cancel(&tdm_record->base.hrtimer);
+
+	/* free record data */
+	kfree(tdm_record);
+
+	return ret;
+}
+
+/*****************************************************************************
+ * callback functions of ADSP ALSA driver
+ * ***************************************************************************/
+
+/** **************************************************************************
+ *  \brief	 Open a playback/TDM playback or record/TDM record stream
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Error
+ *****************************************************************************/
+static int snd_adsp_pcm_open(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream)
+{
+	/* get ADSP soundcard and CPU DAI index */
+	struct snd_adsp_card *adsp_card;
+	int dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+	struct snd_adsp_control *ctr_if;
+
+	adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+	ctr_if = &adsp_card->ctr_if;
+
+	if (dai_idx == RDR_DAI_IDX0 || dai_idx == RDR_DAI_IDX1 ||
+	    dai_idx == RDR_DAI_IDX2 || dai_idx == RDR_DAI_IDX3) {
+		/* register data for playback/record functions */
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			/* perform playback initialization */
+			if (snd_adsp_playback_init(
+				   &adsp_card->playback[dai_idx],
+				   ctr_if->eqz_switch[DIRECT_PLAYBACK][dai_idx],
+				   substream) < 0) {
+				/* perform playback de-initialization when */
+				/* the initialization fails */
+				snd_adsp_playback_deinit(
+						adsp_card->playback[dai_idx]);
+
+				adsp_card->playback[dai_idx] = NULL;
+				return -EINVAL;
+			}
+		} else {
+			/* perform record initialization */
+			if (snd_adsp_record_init(
+				    &adsp_card->record[dai_idx],
+				    ctr_if->eqz_switch[DIRECT_CAPTURE][dai_idx],
+				    substream) < 0) {
+				/* perform record de-initialization when the */
+				/* initialization fails */
+				snd_adsp_record_deinit(
+						adsp_card->record[dai_idx]);
+
+				adsp_card->record[dai_idx] = NULL;
+				return -EINVAL;
+			}
+		}
+
+		/* save the hardware parameters */
+		snd_soc_set_runtime_hwparams(substream, &snd_pcm_adsp_hw);
+
+		/* each period has a frame size */
+		snd_pcm_hw_constraint_single(substream->runtime,
+					     SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+					     FRAME_SIZE);
+	} else {
+		/* register data for TDM playback/record functions */
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			/* perform TDM playback initialization */
+			if (snd_adsp_tdm_playback_init(
+						&adsp_card->tdm_playback,
+						substream) < 0) {
+				/* perform TDM playback de-initialization */
+				/* when the initialization fails */
+				snd_adsp_tdm_playback_deinit(
+						adsp_card->tdm_playback);
+
+				adsp_card->tdm_playback = NULL;
+				return -EINVAL;
+			}
+		} else {
+			/* perform TDM record initialization */
+			if (snd_adsp_tdm_record_init(&adsp_card->tdm_record,
+						     substream) < 0) {
+				/* perform TDM record de-initialization */
+				/* when the initialization fails */
+				snd_adsp_tdm_record_deinit(
+						adsp_card->tdm_record);
+
+				adsp_card->tdm_record = NULL;
+				return -EINVAL;
+			}
+		}
+
+		/* save the hardware parameters */
+		snd_soc_set_runtime_hwparams(substream, &snd_pcm_adsp_tdm_hw);
+
+		/* each period has a frame size */
+		snd_pcm_hw_constraint_single(substream->runtime,
+					     SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+					     TDM_FRAME_SIZE);
+	}
+
+	snd_pcm_hw_constraint_integer(substream->runtime,
+				      SNDRV_PCM_HW_PARAM_PERIODS);
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Close a playback/TDM playback or record/TDM record stream
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Error
+ *****************************************************************************/
+static int snd_adsp_pcm_close(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream)
+{
+	/* get ADSP soundcard and CPU DAI index */
+	struct snd_adsp_card *adsp_card =
+		snd_adsp_get_drvdata_from_substream(substream);
+	int dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+	int err = 0;
+
+	if (dai_idx == RDR_DAI_IDX0 || dai_idx == RDR_DAI_IDX1 ||
+	    dai_idx == RDR_DAI_IDX2 || dai_idx == RDR_DAI_IDX3) {
+		/* destroy Renderer/Capture or Equalizer (if used) */
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			if (snd_adsp_playback_deinit(
+					adsp_card->playback[dai_idx]) < 0)
+				err = -EINVAL;
+
+			adsp_card->playback[dai_idx] = NULL;
+		} else {
+			if (snd_adsp_record_deinit(
+					adsp_card->record[dai_idx]) < 0)
+				err = -EINVAL;
+
+			adsp_card->record[dai_idx] = NULL;
+		}
+	} else {
+		/* destroy TDM Renderer/TDM Capture */
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			if (snd_adsp_tdm_playback_deinit(
+					adsp_card->tdm_playback) < 0)
+				err = -EINVAL;
+
+			adsp_card->tdm_playback = NULL;
+		} else {
+			if (snd_adsp_tdm_record_deinit(
+					adsp_card->tdm_record) < 0)
+				err = -EINVAL;
+
+			adsp_card->tdm_record = NULL;
+		}
+	}
+
+	return err;
+}
+
+/** **************************************************************************
+ *  \brief	Allocate ALSA buffer and calculate expire time of hr timer
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-ENOMEM			Cannot allocate ALSA buffer
+ *****************************************************************************/
+static int snd_adsp_pcm_hw_params(struct snd_soc_component *component,
+				struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *hw_params)
+{
+	struct snd_adsp_base_info *base;
+	int err = 0;
+
+	base = snd_adsp_get_base_from_substream(substream);
+
+	/* set expire time of hrtimer, this value should be time for */
+	/* transfer a frame */
+	base->ktime = ns_to_ktime((1000000000 / params_rate(hw_params)) *
+				  params_period_size(hw_params));
+
+	err = snd_pcm_lib_malloc_pages(substream,
+				       params_buffer_bytes(hw_params));
+
+	/* reset DMA buffer area */
+	memset(substream->runtime->dma_area, 0, substream->runtime->dma_bytes);
+
+	return err;
+}
+
+/** **************************************************************************
+ *  \brief	 Free the allocated ALSA buffer
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Cannot deallocate buffer
+ *****************************************************************************/
+static int snd_adsp_pcm_hw_free(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream)
+{
+	return snd_pcm_lib_free_pages(substream);
+}
+
+/** **************************************************************************
+ *  \brief	 Prepare playback/TDM playback or record/TDM record function
+ *		   before transferring data
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval		 0		Success
+ *  \retval		 -EINVAL	Error
+ *****************************************************************************/
+static int snd_adsp_pcm_prepare(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream)
+{
+	/* get ADSP soundcard and CPU DAI index */
+	struct snd_adsp_card *
+		adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+	int dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+	int err = 0;
+
+	if (dai_idx == RDR_DAI_IDX0 || dai_idx == RDR_DAI_IDX1 ||
+	    dai_idx == RDR_DAI_IDX2 || dai_idx == RDR_DAI_IDX3) {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			/* get playback prepared to execute */
+			err = snd_adsp_playback_prepare(
+				adsp_card->playback[dai_idx], substream);
+		else
+			/* get record prepared to execute */
+			err = snd_adsp_record_prepare(
+				adsp_card->record[dai_idx], substream);
+	} else {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			/* get TDM playback prepared to execute */
+			err = snd_adsp_tdm_playback_prepare(
+				adsp_card->tdm_playback, substream);
+		else
+			/* get TDM record prepared to execute */
+			err = snd_adsp_tdm_record_prepare(
+				adsp_card->tdm_record, substream);
+	}
+
+	return err;
+}
+
+/** **************************************************************************
+ *  \brief	 Trigger playback/TDM playback or record/TDM record stream
+ *		   to go to next phase
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Error
+ *****************************************************************************/
+static int snd_adsp_pcm_trigger(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream, int idx)
+{
+	struct snd_adsp_base_info *
+		base = snd_adsp_get_base_from_substream(substream);
+
+	switch (idx) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		/* start high-resolution timer */
+		hrtimer_start(&base->hrtimer, base->ktime, HRTIMER_MODE_REL);
+
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+			int buf_queue = 0;
+
+			/* get current available buffer */
+			spin_lock_irqsave(&base->lock, base->flag);
+			buf_queue = base->buf_queue;
+			spin_unlock_irqrestore(&base->lock, base->flag);
+
+			/* send all available buffer to plugin to */
+			/* get data */
+			for (; buf_queue > 0; buf_queue--) {
+				if (xf_adsp_fill_this_buffer(
+						base->handle_id,
+						base->buffer[base->buf_idx],
+						base->buf_bytes) != 0)
+					return -EINVAL;
+
+				spin_lock_irqsave(&base->lock, base->flag);
+				base->buf_queue--;
+				spin_unlock_irqrestore(&base->lock, base->flag);
+
+				base->buf_idx++;
+
+				if (base->buf_idx >= XF_BUF_POOL_SIZE)
+					base->buf_idx = 0;
+			}
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Return HW data position
+ *
+ *  \param[in]	  component		Pointer to component of driver
+ *  \param[in]	  substream		Pointer to substream object
+ *  \retval	  position		HW data position
+ *****************************************************************************/
+static snd_pcm_uframes_t
+snd_adsp_pcm_pointer(struct snd_soc_component *component,
+				struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_base_info *
+		base = snd_adsp_get_base_from_substream(substream);
+	unsigned int hw_idx, hw_buffer_size;
+	snd_pcm_uframes_t pointer;
+
+	/* convert hw index to correct as submitted bytes */
+	spin_lock_irqsave(&base->lock, base->flag);
+	hw_idx = (base->hw_idx / base->buf_bytes) * base->period_bytes;
+	spin_unlock_irqrestore(&base->lock, base->flag);
+
+	hw_buffer_size = base->pcm_indirect.hw_buffer_size;
+
+	if (hw_idx >= hw_buffer_size) {
+		spin_lock_irqsave(&base->lock, base->flag);
+
+		base->hw_idx -= (hw_buffer_size / base->period_bytes) *
+							base->buf_bytes;
+
+		spin_unlock_irqrestore(&base->lock, base->flag);
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		pointer = snd_pcm_indirect_playback_pointer(substream,
+							    &base->pcm_indirect,
+							    hw_idx);
+	else
+		pointer = snd_pcm_indirect_capture_pointer(substream,
+							   &base->pcm_indirect,
+							   hw_idx);
+
+	return pointer;
+}
+
+/** **************************************************************************
+ *  \brief	  Call read/write process to transfer data
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Error
+ *****************************************************************************/
+static int snd_adsp_pcm_ack(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_base_info *
+		base = snd_adsp_get_base_from_substream(substream);
+
+	if (base->runtime_err)
+		return -EINVAL;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_pcm_indirect_playback_transfer(substream,
+						   &base->pcm_indirect,
+						   snd_adsp_pcm_transfer);
+	else
+		snd_pcm_indirect_capture_transfer(substream,
+						  &base->pcm_indirect,
+						  snd_adsp_pcm_transfer);
+
+	return 0;
+}
+
+/** ***************************************************************************
+ *  \brief	  Copy data from source buffer to destination buffer
+ *
+ *  \params[in]	 dst		Destination buffer pointer
+ *  \params[out] src		Source buffer pointer
+ *  \params[in]	 dst_size	Destination buffer size in byte
+ *  \params[in]	 src_size	Source buffer size in byte
+ *  \retval	 None
+ *****************************************************************************/
+static inline void
+snd_adsp_copy_data(void *dst, void *src, int dst_size, int src_size)
+{
+	unsigned char *data_dst = dst;
+	unsigned char *data_src = src;
+	int i;
+
+	if (dst_size == src_size) {
+		/* src and dst bufs are same size, does not need to convert */
+		memcpy(data_dst, data_src, dst_size);
+
+	} else if (dst_size < src_size) {
+		for (i = 0; i < (dst_size - BYTES_PER_SAMPLE(S24_3LE));
+				i += BYTES_PER_SAMPLE(S24_3LE)) {
+			*(u32 *)data_dst = *(u32 *)data_src;
+
+			data_dst += BYTES_PER_SAMPLE(S24_3LE);
+			data_src += BYTES_PER_SAMPLE(S24_LE);
+		}
+
+		/* copy a S24_3LE sample from S24_LE sample */
+		data_dst[0] = data_src[0];
+		data_dst[1] = data_src[1];
+		data_dst[2] = data_src[2];
+
+	} else {
+		unsigned int tmp;
+
+		for (i = 0; i < (dst_size - BYTES_PER_SAMPLE(S24_LE));
+				i += BYTES_PER_SAMPLE(S24_LE)) {
+			tmp = *(u32 *)data_src;
+			*(u32 *)data_dst = tmp & 0x0FFFFFF;
+
+			data_dst += BYTES_PER_SAMPLE(S24_LE);
+			data_src += BYTES_PER_SAMPLE(S24_3LE);
+		}
+
+		/* copy a S24_LE sample from S24_3LE sample */
+		data_dst[0] = data_src[0];
+		data_dst[1] = data_src[1];
+		data_dst[2] = data_src[2];
+		data_dst[3] = 0;
+	}
+}
+
+/** **************************************************************************
+ *  \brief	  Transfer data process between ALSA buffer and ADSP buffer
+ *
+ *  \param[in]	  substream		Pointer to substream object
+ *  \param[in]	  rec			Pointer to indirect PCM data
+ *  \param[in]	  bytes			Number of byte need to be transferred
+ *  \retval	  None
+ *****************************************************************************/
+static void snd_adsp_pcm_transfer(struct snd_pcm_substream *substream,
+				  struct snd_pcm_indirect *rec,
+				  size_t bytes)
+{
+	struct snd_adsp_base_info *
+		base = snd_adsp_get_base_from_substream(substream);
+	int direct = substream->stream;
+	int trans_bytes = bytes;
+	int buf_bytes, period_bytes;
+	void *dma_buf, *data_buff;
+
+	/* get the DMA buffer pointer */
+	dma_buf = (void *)(substream->runtime->dma_area + rec->sw_data);
+
+	/* get information from base */
+	buf_bytes = base->buf_bytes;
+	period_bytes = base->period_bytes;
+
+	/* make sure the available buffer and transfer size - TBD */
+	while (trans_bytes > 0) {
+		spin_lock_irqsave(&base->lock, base->flag);
+		if (base->buf_queue > 0 && trans_bytes >= period_bytes) {
+			base->buf_queue--;
+			spin_unlock_irqrestore(&base->lock, base->flag);
+
+			/* get the buffer pointer from stream */
+			data_buff = base->buffer[base->buf_idx];
+
+			if (direct == SNDRV_PCM_STREAM_PLAYBACK) {
+				/* copy data from user *//* PRQA S 3200 2 */
+				snd_adsp_copy_data(data_buff, dma_buf,
+						   buf_bytes, period_bytes);
+
+				/* send buffer to plugin */
+				if (xf_adsp_empty_this_buffer(base->handle_id,
+							      data_buff,
+							      buf_bytes) < 0)
+					base->runtime_err = TRUE;
+			} else {
+				/* copy data to user *//* PRQA S 3200 2 */
+				snd_adsp_copy_data(dma_buf, data_buff,
+						   period_bytes, buf_bytes);
+
+				/* send buffer to plugin */
+				if (xf_adsp_fill_this_buffer(base->handle_id,
+							     data_buff,
+							     buf_bytes) < 0)
+					base->runtime_err = TRUE;
+			}
+
+			base->buf_idx++;
+			if (base->buf_idx >= XF_BUF_POOL_SIZE)
+				base->buf_idx = 0;
+		} else {
+			spin_unlock_irqrestore(&base->lock, base->flag);
+			break;
+		}
+
+		trans_bytes -= period_bytes;
+	}
+}
+
+/** **************************************************************************
+ *  \brief	 Get info of Volume control
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  uinfo		Pointer to info structure of volume control
+ *  \retval		 0	Success
+ *****************************************************************************/
+static int snd_adsp_control_volume_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = -1;
+	uinfo->value.integer.max = 799;
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Get volume value
+ *
+ *  \param[in]	kcontrol		Pointer to control instance
+ *  \param[in]	ucontrol		Pointer to volume value
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Error
+ *****************************************************************************/
+static int snd_adsp_control_volume_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	struct snd_adsp_control *ctr_if = &adsp_card->ctr_if;
+	int handle_state, handle_id;
+	int volume, cmd_idx, direction;
+	unsigned int index;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* set handle state as NULL state */
+	handle_state = XF_HANDLE_NULL;
+	handle_id = -1;
+
+	/* determine command index, direction, handle state, handle ID */
+	if (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) {
+		cmd_idx = XA_RDR_CONFIG_PARAM_VOLUME_RATE;
+		direction = DIRECT_PLAYBACK;
+
+		if (adsp_card->playback[index]) {
+			handle_state = adsp_card->playback[index]->rdr_state;
+
+			handle_id =
+				adsp_card->playback[index]->renderer->handle_id;
+		}
+	} else if (kcontrol->id.name[0] == PREFIX_OF_CAPTURE_CTR_NAME) {
+		cmd_idx = XA_CAP_CONFIG_PARAM_VOLUME_RATE;
+		direction = DIRECT_CAPTURE;
+
+		if (adsp_card->record[index]) {
+			handle_state = adsp_card->record[index]->cap_state;
+
+			handle_id =
+				adsp_card->record[index]->capture->handle_id;
+		}
+	} else {
+		if (kcontrol->id.name[3] == TDM_PLAYBACK) {
+			cmd_idx = XA_TDM_RDR_CONFIG_PARAM_VOLUME_RATE;
+			direction = DIRECT_PLAYBACK;
+
+			if (adsp_card->tdm_playback) {
+				handle_state = adsp_card->tdm_playback->state;
+
+				handle_id =
+			       adsp_card->tdm_playback->tdm_renderer->handle_id;
+			}
+		} else {
+			cmd_idx = XA_TDM_CAP_CONFIG_PARAM_VOLUME_RATE;
+			direction = DIRECT_CAPTURE;
+
+			if (adsp_card->tdm_record) {
+				handle_state = adsp_card->tdm_record->state;
+
+				handle_id =
+				  adsp_card->tdm_record->tdm_capture->handle_id;
+			}
+		}
+	}
+
+	/* get the volume's value */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		/* get the volume's value from the plugin */
+		if (xf_adsp_get_param(handle_id, cmd_idx, &volume) != 0)
+			return -EINVAL;
+
+		/* check the value after getting it and adjust it */
+		ucontrol->value.integer.value[0] = (volume == 0xFFFFFFFF) ?
+					(-1) : (volume * VOLUME_SCALE) >> 20;
+	} else {
+		if (kcontrol->id.name[0] != PREFIX_OF_TDM_CTR_NAME)
+			ucontrol->value.integer.value[0] =
+					(ctr_if->vol_rate[direction][index] *
+					 VOLUME_SCALE) >> 20;
+		else
+			ucontrol->value.integer.value[0] =
+					(ctr_if->tdm_vol_rate[direction] *
+					 VOLUME_SCALE) >> 20;
+	}
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Set volume value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to volume value
+ *  \retval	  1		Volume change
+ *  \retval	  0		Volume does not change
+ *  \retval	  -EINVAL	Error
+ *****************************************************************************/
+/* PRQA S 3673 1*/
+static int
+snd_adsp_control_volume_put(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	struct snd_adsp_control *ctr_if = &adsp_card->ctr_if;
+	int volume;
+	int ret;
+	int handle_state, handle_id, cmd_idx, volume_get;
+	int direction;
+	unsigned int index;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* set handle state as NULL state and handle ID */
+	handle_state = XF_HANDLE_NULL;
+	handle_id = -1;
+
+	/* get the value to set */
+	if (ucontrol->value.integer.value[0] == -1) {
+		volume = 0xFFFFFFFF;
+	} else {
+		/* round up the value if needed */
+		volume = (ucontrol->value.integer.value[0] * (1 << 20)) /
+			  VOLUME_SCALE;
+
+		if ((ucontrol->value.integer.value[0] * (1 << 20)) >
+		    (VOLUME_SCALE * volume))
+			volume += 1;
+	}
+
+	/* determine command index, direction, handle state, handle ID */
+	if (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) {
+		cmd_idx = XA_RDR_CONFIG_PARAM_VOLUME_RATE;
+		direction = DIRECT_PLAYBACK;
+
+		if (adsp_card->playback[index]) {
+			handle_state = adsp_card->playback[index]->rdr_state;
+
+			handle_id =
+				adsp_card->playback[index]->renderer->handle_id;
+		}
+	} else if (kcontrol->id.name[0] == PREFIX_OF_CAPTURE_CTR_NAME) {
+		cmd_idx = XA_CAP_CONFIG_PARAM_VOLUME_RATE;
+		direction = DIRECT_CAPTURE;
+
+		if (adsp_card->record[index]) {
+			handle_state = adsp_card->record[index]->cap_state;
+
+			handle_id =
+				adsp_card->record[index]->capture->handle_id;
+		}
+	} else {
+		if (kcontrol->id.name[3] == TDM_PLAYBACK) {
+			cmd_idx = XA_TDM_RDR_CONFIG_PARAM_VOLUME_RATE;
+			direction = DIRECT_PLAYBACK;
+
+			if (adsp_card->tdm_playback) {
+				handle_state = adsp_card->tdm_playback->state;
+
+				handle_id =
+			       adsp_card->tdm_playback->tdm_renderer->handle_id;
+			}
+		} else {
+			cmd_idx = XA_TDM_CAP_CONFIG_PARAM_VOLUME_RATE;
+			direction = DIRECT_CAPTURE;
+
+			if (adsp_card->tdm_record) {
+				handle_state = adsp_card->tdm_record->state;
+
+				handle_id =
+				  adsp_card->tdm_record->tdm_capture->handle_id;
+			}
+		}
+	}
+
+	/* set volume to plugin */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		/* TDM does not support set volume in runtime state */
+		if (kcontrol->id.name[0] == PREFIX_OF_TDM_CTR_NAME)
+			return -EINVAL;
+
+		/* apply set volume value to ADSP from user setting */
+		if (xf_adsp_set_param(handle_id, cmd_idx, volume) != 0)
+			return -EINVAL;
+
+		/* get volume from ADSP after setting to confirm */
+		if (xf_adsp_get_param(handle_id, cmd_idx, &volume_get) != 0)
+			return -EINVAL;
+
+		/* check if the value has changed */
+		ret = (volume_get == volume) ? 1 : 0;
+	} else {
+		if (kcontrol->id.name[0] != PREFIX_OF_TDM_CTR_NAME)
+			ctr_if->vol_rate[direction][index] = volume;
+		else
+			ctr_if->tdm_vol_rate[direction] = volume;
+
+		ret = 1;
+	}
+
+	return ret;
+}
+
+/** **************************************************************************
+ *  \brief	 Get info of Sample Rate Converter control
+ *
+ *  \param[in]	kcontrol	Pointer to control instance
+ *  \param[in]	uinfo		Pointer to info structure of sample rate
+ *				converter control
+ *  \retval	0		Success
+ *****************************************************************************/
+static int snd_adsp_control_sample_rate_info(struct snd_kcontrol *kcontrol,
+					     struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = -1;
+	uinfo->value.integer.max = 48000;
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Get sample rate value
+ *
+ *  \param[in]	kcontrol	Pointer to control instance
+ *  \param[in]	ucontrol	Pointer to sample rate value
+ *  \retval	0		Success
+ *  \retval	-EINVAL		Error
+ *****************************************************************************/
+static int snd_adsp_control_sample_rate_get(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int *rate;
+	int handle_id, handle_state, cmd_idx, direction;
+	unsigned int index;
+
+	rate = (int *)&ucontrol->value.integer.value[0]; /* PRQA S 310 */
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* set handle state as NULL state and handle ID */
+	handle_state = XF_HANDLE_NULL;
+	handle_id = -1;
+
+	/* determine command, direction, handle state, handle ID */
+	if (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) {
+		cmd_idx = XA_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+		direction = DIRECT_PLAYBACK;
+
+		if (adsp_card->playback[index]) {
+			handle_state = adsp_card->playback[index]->rdr_state;
+
+			handle_id =
+				adsp_card->playback[index]->renderer->handle_id;
+		}
+	} else if (kcontrol->id.name[0] == PREFIX_OF_CAPTURE_CTR_NAME) {
+		cmd_idx = XA_CAP_CONFIG_PARAM_SAMPLE_RATE;
+		direction = DIRECT_CAPTURE;
+
+		if (adsp_card->record[index]) {
+			handle_state = adsp_card->record[index]->cap_state;
+
+			handle_id =
+				adsp_card->record[index]->capture->handle_id;
+		}
+	} else {
+		if (kcontrol->id.name[3] == TDM_PLAYBACK) {
+			cmd_idx = XA_TDM_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+			direction = DIRECT_PLAYBACK;
+
+			if (adsp_card->tdm_playback) {
+				handle_state = adsp_card->tdm_playback->state;
+
+				handle_id =
+			       adsp_card->tdm_playback->tdm_renderer->handle_id;
+			}
+		} else {
+			cmd_idx = XA_TDM_CAP_CONFIG_PARAM_IN_SAMPLE_RATE;
+			direction = DIRECT_CAPTURE;
+
+			if (adsp_card->tdm_record) {
+				handle_state = adsp_card->tdm_record->state;
+
+				handle_id =
+				  adsp_card->tdm_record->tdm_capture->handle_id;
+			}
+		}
+	}
+
+	/* get parameter from plugin */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		if (xf_adsp_get_param(handle_id, cmd_idx, rate) != 0)
+			return -EINVAL;
+	} else {
+		if (kcontrol->id.name[0] != PREFIX_OF_TDM_CTR_NAME)
+			*rate = adsp_card->ctr_if.sample_rate[direction][index];
+		else
+			*rate = adsp_card->ctr_if.tdm_sample_rate[direction];
+	}
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Set sample rate value
+ *
+ *  \param[in]	kcontrol	Pointer to control instance
+ *  \param[in]	ucontrol	Pointer to sample rate value
+ *  \retval	1		Sample rate change
+ *  \retval	0		Sample rate does not change
+ *  \retval	-EINVAL		Error
+ *****************************************************************************/
+/* PRQA S 3673 1 */
+static int
+snd_adsp_control_sample_rate_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	unsigned int index;
+	int rate;
+	int handle_state, cmd_idx, direction;
+	int ret = 1;
+
+	rate = (int)ucontrol->value.integer.value[0];
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* set handle state as NULL state */
+	handle_state = XF_HANDLE_NULL;
+
+	/* determine command, direction and handle state */
+	if (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) {
+		cmd_idx = XA_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+		direction = DIRECT_PLAYBACK;
+
+		if (adsp_card->playback[index])
+			handle_state = adsp_card->playback[index]->rdr_state;
+
+	} else if (kcontrol->id.name[0] == PREFIX_OF_CAPTURE_CTR_NAME) {
+		cmd_idx = XA_CAP_CONFIG_PARAM_SAMPLE_RATE;
+		direction = DIRECT_CAPTURE;
+
+		if (adsp_card->record[index])
+			handle_state = adsp_card->record[index]->cap_state;
+
+	} else {
+		if (kcontrol->id.name[3] == TDM_PLAYBACK) {
+			cmd_idx = XA_TDM_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+			direction = DIRECT_PLAYBACK;
+
+			if (adsp_card->tdm_playback)
+				handle_state = adsp_card->tdm_playback->state;
+
+		} else {
+			cmd_idx = XA_TDM_CAP_CONFIG_PARAM_IN_SAMPLE_RATE;
+			direction = DIRECT_CAPTURE;
+
+			if (adsp_card->tdm_record)
+				handle_state = adsp_card->tdm_record->state;
+		}
+	}
+
+	/* get the value to set */
+	if (COMPONENT_IS_READY(handle_state) == TRUE)
+		return -EINVAL;
+
+	if (kcontrol->id.name[0] != PREFIX_OF_TDM_CTR_NAME)
+		adsp_card->ctr_if.sample_rate[direction][index] = rate;
+	else
+		adsp_card->ctr_if.tdm_sample_rate[direction] = rate;
+
+	ret = 1;
+
+	return ret;
+}
+
+/** **************************************************************************
+ *  \brief	 Get info of Equalizer control
+ *
+ *  \param[in]	kcontrol	Pointer to control instance
+ *  \param[in]	uinfo		Pointer to info structure of Equalizer control
+ *  \retval	0		Success
+ *****************************************************************************/
+static int snd_adsp_control_eqz_info(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = MAX_EQZ_PARAM_NUMBER;
+	uinfo->value.integer.min = -1;
+	uinfo->value.integer.max = 0x7fffffff;
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Get equalizer parameters value
+ *
+ *  \param[in]	  kcontrol		Pointer to control instance
+ *  \param[in]	  ucontrol		Pointer to equalizer parameters value
+ *  \retval	  0			Success
+ *  \retval	  -EINVAL		Error
+ *****************************************************************************/
+static int snd_adsp_control_eqz_get(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int handle_state, direction;
+	int i, j, filter_index;
+	unsigned int index;
+	struct xf_adsp_equalizer *equalizer;
+	struct xf_adsp_equalizer_params *eqz_params;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* determin direction of stream */
+	direction = (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) ?
+					     DIRECT_PLAYBACK : DIRECT_CAPTURE;
+
+	/* set handle state as NULL state, handle ID, equalizer pointer */
+	handle_state = XF_HANDLE_NULL;
+	equalizer = NULL;
+
+	/* get component's state */
+	if (direction == DIRECT_PLAYBACK) {
+		if (adsp_card->playback[index]) {
+			handle_state = adsp_card->playback[index]->eqz_state;
+			equalizer = adsp_card->playback[index]->equalizer;
+		}
+	} else {
+		if (adsp_card->record[index]) {
+			handle_state = adsp_card->record[index]->eqz_state;
+			equalizer = adsp_card->record[index]->equalizer;
+		}
+	}
+
+	/* perform parameters' values getting */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		/* get equalizer's parameters */
+		if (xf_adsp_equalizer_get_params(equalizer) != 0)
+			return -EINVAL;
+
+		eqz_params = &equalizer->params;
+	} else {
+		eqz_params = &adsp_card->ctr_if.eqz_params[direction][index];
+	}
+
+	/* get equalizer type: PARAMETRIC or GRAPHIC */
+	ucontrol->value.integer.value[0] = eqz_params->eqz_type;
+
+	/* get parameters' value from Equalizer plugin */
+	if (eqz_params->eqz_type == XA_REL_EQZ_TYPE_PARAMETRIC) {
+		for (i = 0, filter_index = 1;
+		     filter_index <= XA_REL_EQZ_FILTER_NUM;
+		     i++, filter_index++) {
+			/* get filter index */
+			ucontrol->value.integer.value[(i * 6) + 1] =
+				filter_index;
+
+			/* get frequency centre */
+			ucontrol->value.integer.value[(i * 6) + 2] =
+				eqz_params->p_coef.fc[i];
+
+			/* get bandwidth */
+			ucontrol->value.integer.value[(i * 6) + 3] =
+				eqz_params->p_coef.band_width[i];
+
+			/* get filter type */
+			ucontrol->value.integer.value[(i * 6) + 4] =
+				eqz_params->p_coef.type[i];
+
+			/* get gain base */
+			ucontrol->value.integer.value[(i * 6) + 5] =
+				eqz_params->p_coef.gain_base[i];
+
+			/* get gain */
+			ucontrol->value.integer.value[(i * 6) + 6] =
+				eqz_params->p_coef.gain[i];
+		}
+	} else {
+		for (i = 0, filter_index = 1;
+		     filter_index <= XA_REL_EQZ_GRAPHIC_BAND_NUM;
+		     i++, filter_index++) {
+			/* get band index */
+			ucontrol->value.integer.value[(i * 2) + 1] =
+				filter_index;
+
+			/* get graphic gain */
+			ucontrol->value.integer.value[(i * 2) + 2] =
+				eqz_params->g_coef.gain_g[i];
+		}
+
+		j = (i * 2) + 1;
+
+		/* make the rest of values silent */
+		while (j < MAX_EQZ_PARAM_NUMBER) {
+			ucontrol->value.integer.value[j] = -1;
+			j++;
+		}
+	}
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Set equalizer parameters value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to equalizer parameters value
+ *  \retval	  1		Equalizer parameters change
+ *  \retval	  0		Equalizer parameters does not change
+ *  \retval	 -EINVAL	Error
+ *****************************************************************************/
+/* PRQA S 3673 1*/
+static int snd_adsp_control_eqz_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int handle_state, direction, filter_idx;
+	int i;
+	int index;
+	struct xf_adsp_equalizer_params *eqz_params = NULL;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* determine the direction */
+	direction = (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) ?
+					     DIRECT_PLAYBACK : DIRECT_CAPTURE;
+
+	/* set handle state as NULL state */
+	handle_state = XF_HANDLE_NULL;
+
+	/* get the handle state */
+	if (direction == DIRECT_PLAYBACK) {
+		if (adsp_card->playback[index])
+			handle_state = adsp_card->playback[index]->eqz_state;
+	} else {
+		if (adsp_card->record[index])
+			handle_state = adsp_card->record[index]->eqz_state;
+	}
+
+	/* perform equalizer's parameters setting */
+	if (COMPONENT_IS_READY(handle_state) == TRUE)
+		return -EINVAL;
+
+	/* PRQA S 310 1*/
+	eqz_params = &adsp_card->ctr_if.eqz_params[direction][index];
+
+	i = 0;
+	/* PRQA S 3440 1*/
+	eqz_params->eqz_type = ucontrol->value.integer.value[i];
+	i++;
+	filter_idx = 0;
+
+	if (eqz_params->eqz_type == XA_REL_EQZ_TYPE_PARAMETRIC) {
+		while (i < MAX_EQZ_PARAM_NUMBER) {
+			/* get index filter */
+			/* PRQA S 3440*/
+			filter_idx = ucontrol->value.integer.value[i];
+			i++;
+
+			/* valid index filter is range */
+			/* (1 to XA_REL_EQZ_FILTER_NUM) */
+			if (filter_idx >= 1 &&
+			    filter_idx <= XA_REL_EQZ_FILTER_NUM) {
+					/* PRQA S 3440 5*/
+				eqz_params->p_coef.fc[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+
+				i++;
+				eqz_params->p_coef.band_width[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+
+				i++;
+				eqz_params->p_coef.type[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+
+				i++;
+				eqz_params->p_coef.gain_base[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+
+				i++;
+				eqz_params->p_coef.gain[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+
+				i++;
+			}
+			/* index filter = -1 means that user */
+			/* does not set this filter */
+			else if (filter_idx == -1 || filter_idx == 0) {
+				i += 5;
+			} else {
+				return -EINVAL;
+			}
+		}
+	} else if (eqz_params->eqz_type == XA_REL_EQZ_TYPE_GRAPHIC) {
+		while (i < ((XA_REL_EQZ_GRAPHIC_BAND_NUM * 2) + 1)) {
+			/*get index filter */
+			/* PRQA S 3440 */
+			filter_idx = ucontrol->value.integer.value[i++];
+
+			if (filter_idx >= 1 &&
+			    filter_idx <= XA_REL_EQZ_GRAPHIC_BAND_NUM) {
+				eqz_params->g_coef.gain_g[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+				i++;
+
+			} else if (filter_idx == -1 || filter_idx == 0) {
+				i += 1;
+			} else {
+				return -EINVAL;
+			}
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	return 1;
+}
+
+/** **************************************************************************
+ *  \brief	 Get info of Equalizer Switch control
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  uinfo		Pointer to info structure of Equalizer
+ *				Switch control
+ *  \retval	  0		Success
+ *****************************************************************************/
+static int snd_adsp_control_eqz_switch_info(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Get equalizer switch value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to equalizer switch value
+ *  \retval	  0		Success
+ *  \retval	  -EINVAL	Error
+ *****************************************************************************/
+static int
+snd_adsp_control_eqz_switch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int direction;
+	unsigned int index;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* determine the direction */
+	direction = (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) ?
+					     DIRECT_PLAYBACK : DIRECT_CAPTURE;
+
+	/* get the Equalizer switch status */
+	ucontrol->value.integer.value[0] =
+		adsp_card->ctr_if.eqz_switch[direction][index];
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Set equalizer switch value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to equalizer switch value
+ *  \retval	  1		Equalizer switch change
+ *  \retval	  0		Equalizer switch does not change
+ *  \retval	 -EINVAL	Error
+ *****************************************************************************/
+/* PRQA S 3673 1 */
+static int
+snd_adsp_control_eqz_switch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int eqz_switch;
+	int handle_state, direction;
+	unsigned int index;
+	int ret = 0;
+
+	eqz_switch = ucontrol->value.integer.value[0];
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* determine the direction */
+	direction = (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) ?
+		     DIRECT_PLAYBACK : DIRECT_CAPTURE;
+
+	/* set handle state as NULL state */
+	handle_state = XF_HANDLE_NULL;
+
+	/* determine handle state */
+	if (direction == DIRECT_PLAYBACK) {
+		if (adsp_card->playback[index])
+			handle_state = adsp_card->playback[index]->rdr_state;
+	} else {
+		if (adsp_card->record[index])
+			handle_state = adsp_card->record[index]->cap_state;
+	}
+
+	/* set the status of Equalizer */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		/* runtime setting is not supported */
+		ret = -EINVAL;
+	} else {
+		adsp_card->ctr_if.eqz_switch[direction][index] = eqz_switch;
+		ret = 1;
+	}
+
+	return ret;
+}
+
+/** **************************************************************************
+ *  \brief	 Get info of Renderer output channel
+ *
+ *  \param[in]	  kcontrol Pointer to control instance
+ *  \param[in]	  uinfo	   Pointer to info structure of Renderer output channel
+ *  \retval	  0	   Success
+ *****************************************************************************/
+static int
+snd_adsp_control_rdr_out_channel_info(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = MONAURAL;
+	uinfo->value.integer.max = STEREO;
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Get Renderer output channel's value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to Renderer output channel value
+ *  \retval	  0		Success
+ *  \retval	 -EINVAL	Error
+ *****************************************************************************/
+static int
+snd_adsp_control_rdr_out_channel_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int rdr_out_ch;
+	unsigned int index;
+	int handle_state, handle_id;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	handle_state = XF_HANDLE_NULL;
+	handle_id = -1;
+
+	/* determine handle state and handle ID */
+	if (adsp_card->playback[index]) {
+		handle_state = adsp_card->playback[index]->rdr_state;
+		handle_id = adsp_card->playback[index]->renderer->handle_id;
+	}
+
+	/* get Renderer output channel's value */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		/* get Renderer output channel's value from Renderer plugin */
+		if (xf_adsp_get_param(handle_id,
+				      XA_RDR_CONFIG_PARAM_OUT_CHANNELS,
+				      &rdr_out_ch) != 0) {
+			return -EINVAL;
+		}
+
+		ucontrol->value.integer.value[0] = rdr_out_ch;
+	} else {
+		ucontrol->value.integer.value[0] =
+		adsp_card->ctr_if.rdr_out_ch[index];
+	}
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Set Renderer output channel's value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to Renderer output channel value
+ *  \retval	  1		Success
+ *  \retval	  -EINVAL	Error
+ *****************************************************************************/
+static int
+snd_adsp_control_rdr_out_channel_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	unsigned int index;
+	int handle_state;
+	int ret = 1;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	handle_state = XF_HANDLE_NULL;
+
+	/* determine handle state and handle ID */
+	if (adsp_card->playback[index])
+		handle_state = adsp_card->playback[index]->rdr_state;
+
+	/* get Renderer output channel's value */
+	if (COMPONENT_IS_READY(handle_state) == TRUE)
+		/* not support runtime setting */
+		ret = -EINVAL;
+	else
+		adsp_card->ctr_if.rdr_out_ch[index] =
+			ucontrol->value.integer.value[0];
+
+	return ret;
+}
+
+/** control interface for playback's volume rate */
+/* PRQA S 3218 */
+static struct snd_kcontrol_new
+snd_adsp_playback_volume_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = PLAYBACK_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = PLAYBACK_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = PLAYBACK_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = PLAYBACK_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	}
+};
+
+/** control interface for Capture's volume rate */
+/* PRQA S 3218 1*/
+static struct snd_kcontrol_new
+snd_adsp_capture_volume_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = CAPTURE_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = CAPTURE_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = CAPTURE_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = CAPTURE_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	}
+};
+
+/** control interface for playback's output sample rate */
+/* PRQA S 3218 1*/
+static struct snd_kcontrol_new
+snd_adsp_playback_sample_rate_out_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = PLAYBACK_OUT_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = PLAYBACK_OUT_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = PLAYBACK_OUT_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = PLAYBACK_OUT_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	}
+};
+
+/** control interface for Capture's input sample rate */
+/* PRQA S 3218 */
+static struct snd_kcontrol_new
+snd_adsp_capture_sample_rate_in_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = CAPTURE_IN_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = CAPTURE_IN_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = CAPTURE_IN_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = CAPTURE_IN_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	}
+};
+
+/** control interface for Equalizer parameters in playback */
+/* PRQA S 3218 1*/
+static struct snd_kcontrol_new
+snd_adsp_playback_equalizer_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = PLAYBACK_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = PLAYBACK_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = PLAYBACK_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = PLAYBACK_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	}
+};
+
+/** control interface for Equalizer parameters in record */
+/* PRQA S 3218 */
+static struct snd_kcontrol_new
+snd_adsp_capture_equalizer_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = CAPTURE_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = CAPTURE_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = CAPTURE_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = CAPTURE_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	}
+};
+
+/** control interface for Equalizer usage in playback */
+/* PRQA S 3218 */
+static struct snd_kcontrol_new
+snd_adsp_playback_equalizer_switch_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = PLAYBACK_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = PLAYBACK_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = PLAYBACK_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = PLAYBACK_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	}
+};
+
+/** control interface for Equalizer usage in record */
+/* PRQA S 3218 1*/
+static struct snd_kcontrol_new
+snd_adsp_capture_equalizer_switch_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = CAPTURE_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = CAPTURE_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = CAPTURE_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = CAPTURE_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	}
+};
+
+/** control interface for playback's output channel */
+static struct snd_kcontrol_new
+snd_adsp_playback_out_channel_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = PLAYBACK_OUT_CHANNEL_CTR_NAME,
+		.info = &snd_adsp_control_rdr_out_channel_info,
+		.get = &snd_adsp_control_rdr_out_channel_get,
+		.put = &snd_adsp_control_rdr_out_channel_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.index = RDR_DAI_IDX1,
+		.name = PLAYBACK_OUT_CHANNEL_CTR_NAME,
+		.info = &snd_adsp_control_rdr_out_channel_info,
+		.get = &snd_adsp_control_rdr_out_channel_get,
+		.put = &snd_adsp_control_rdr_out_channel_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.index = RDR_DAI_IDX2,
+		.name = PLAYBACK_OUT_CHANNEL_CTR_NAME,
+		.info = &snd_adsp_control_rdr_out_channel_info,
+		.get = &snd_adsp_control_rdr_out_channel_get,
+		.put = &snd_adsp_control_rdr_out_channel_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.index = RDR_DAI_IDX3,
+		.name = PLAYBACK_OUT_CHANNEL_CTR_NAME,
+		.info = &snd_adsp_control_rdr_out_channel_info,
+		.get = &snd_adsp_control_rdr_out_channel_get,
+		.put = &snd_adsp_control_rdr_out_channel_put
+	}
+};
+
+/** control interface for TDM playback's volume rate */
+static struct snd_kcontrol_new snd_adsp_tdm_playback_volume_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		/* PRQA S 1053 5 */
+	.name = TDM_PLAYBACK_VOLUME_CTR_NAME,
+	.info = &snd_adsp_control_volume_info,
+	.get = &snd_adsp_control_volume_get,
+	.put = &snd_adsp_control_volume_put
+};
+
+/** control interface for TDM capture's volume rate */
+static struct snd_kcontrol_new snd_adsp_tdm_capture_volume_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		/* PRQA S 1053 5 */
+	.name = TDM_CAPTURE_VOLUME_CTR_NAME,
+	.info = &snd_adsp_control_volume_info,
+	.get = &snd_adsp_control_volume_get,
+	.put = &snd_adsp_control_volume_put
+};
+
+/** control interface for TDM playback's output sample rate */
+static struct snd_kcontrol_new snd_adsp_tdm_playback_sample_rate_out_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		/* PRQA S 1053 5 */
+	.name = TDM_PLAYBACK_OUT_RATE_CTR_NAME,
+	.info = &snd_adsp_control_sample_rate_info,
+	.get = &snd_adsp_control_sample_rate_get,
+	.put = &snd_adsp_control_sample_rate_put
+};
+
+/** control interface for TDM capture's input sample rate */
+static struct snd_kcontrol_new snd_adsp_tdm_capture_sample_rate_in_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		/* PRQA S 1053 5 */
+	.name = TDM_CAPTURE_IN_RATE_CTR_NAME,
+	.info = &snd_adsp_control_sample_rate_info,
+	.get = &snd_adsp_control_sample_rate_get,
+	.put = &snd_adsp_control_sample_rate_put
+};
+
+
+/*******************************************************************
+ * Internal functions
+ * ****************************************************************/
+
+/** **************************************************************************
+ *  \brief	 Process information get from control structure
+ *
+ *  \param[in]	  eqz_params	 Equalizer parameters object
+ *  \param[in]	  eqz_ctr_params Equalizer parameters stored in control object
+ *  \param[in]	  flag		 Indicate playback or capture stream
+ *****************************************************************************/
+static void snd_adsp_get_eqz_params_from_control(
+		struct xf_adsp_equalizer_params *eqz_params,
+		struct xf_adsp_equalizer_params *eqz_ctr_params, bool flag)
+{
+	int filter_idx;
+
+	if (flag) {
+		if (eqz_ctr_params->eqz_type >= 0)
+			eqz_params->eqz_type = eqz_ctr_params->eqz_type;
+
+		for (filter_idx = 0; filter_idx < XA_REL_EQZ_FILTER_NUM;
+		     filter_idx++) {
+			if (eqz_ctr_params->p_coef.fc[filter_idx] >= 0)
+				eqz_params->p_coef.fc[filter_idx] =
+				  eqz_ctr_params->p_coef.fc[filter_idx];
+
+			if (eqz_ctr_params->p_coef.band_width[filter_idx] >= 0)
+				eqz_params->p_coef.band_width[filter_idx] =
+				eqz_ctr_params->p_coef.band_width[filter_idx];
+
+			if (eqz_ctr_params->p_coef.type[filter_idx] >= 0)
+				eqz_params->p_coef.type[filter_idx] =
+				  eqz_ctr_params->p_coef.type[filter_idx];
+
+			if (eqz_ctr_params->p_coef.gain_base[filter_idx] >= 0)
+				eqz_params->p_coef.gain_base[filter_idx] =
+				  eqz_ctr_params->p_coef.gain_base[filter_idx];
+
+			if (eqz_ctr_params->p_coef.gain[filter_idx] >= 0)
+				eqz_params->p_coef.gain[filter_idx] =
+				  eqz_ctr_params->p_coef.gain[filter_idx];
+		}
+		for (filter_idx = 0; filter_idx < XA_REL_EQZ_GRAPHIC_BAND_NUM;
+		     filter_idx++) {
+			if (eqz_ctr_params->g_coef.gain_g[filter_idx] >= 0)
+				eqz_params->g_coef.gain_g[filter_idx] =
+				  eqz_ctr_params->g_coef.gain_g[filter_idx];
+		}
+	} else {
+		memcpy(eqz_ctr_params, eqz_params, sizeof(*eqz_params));
+	}
+}
+
+/*******************************************************************
+ * ALSA ADSP Platform driver interface
+ * ****************************************************************/
+
+/** ****************************************************************************
+ *  \brief	 Register control interface and preallocate ALSA buffer
+ *
+ *  \param[in]	  component	Pointer to component of driver
+ *  \param[in]	  runtime	Pointer to runtime PCM data
+ *  \retval	  0		Success
+ *  \retval	 -EINVAL	Cannot register control interface
+ ******************************************************************************/
+static int snd_adsp_pcm_new(struct snd_soc_component *component,
+					struct snd_soc_pcm_runtime *runtime)
+{
+	int i = 0, err = 0;
+	int id;
+	struct snd_card *card;
+	struct snd_adsp_card *adsp_card;
+	int alsa_buf_sz = 0;
+
+	/* get sound card data */
+	card = runtime->card->snd_card;
+
+	/* get driver data */
+	adsp_card = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(runtime, 0));
+
+	/* get the ID of CPU DAI */
+	id = asoc_rtd_to_cpu(runtime, 0)->id;
+
+	/* register control interfaces */
+	if (id == RDR_DAI_IDX0 || id == RDR_DAI_IDX1 ||
+	    id == RDR_DAI_IDX2 || id == RDR_DAI_IDX3) {
+		struct snd_kcontrol *kctl[RDR_CONTROL_NUM];
+		void *rdr_ctr[RDR_CONTROL_NUM] = {
+			&snd_adsp_playback_volume_control[id], /* PRQA S 1031 */
+			&snd_adsp_capture_volume_control[id],
+			&snd_adsp_playback_sample_rate_out_control[id],
+			&snd_adsp_capture_sample_rate_in_control[id],
+			&snd_adsp_playback_equalizer_control[id],
+			&snd_adsp_capture_equalizer_control[id],
+			&snd_adsp_playback_equalizer_switch_control[id],
+			&snd_adsp_capture_equalizer_switch_control[id],
+			&snd_adsp_playback_out_channel_control[id]
+		};
+
+		/* add basic control instance */
+		for (i = 0; i < RDR_CONTROL_NUM; i++) {
+			kctl[i] = snd_ctl_new1(rdr_ctr[i], adsp_card);
+			err = snd_ctl_add(card, kctl[i]);
+			if (err < 0)
+				return -EINVAL;
+		}
+
+		/* assign ALSA buffer size */
+		alsa_buf_sz = MAX_BUFFER_BYTES;
+
+		/* enable MIX feature from the 2nd playback/record stream */
+		if (adsp_card->ctr_if.mix_usage == MIX_UNUSED)
+			adsp_card->ctr_if.mix_usage = FIRST_RUN;
+		else if (adsp_card->ctr_if.mix_usage == FIRST_RUN)
+			adsp_card->ctr_if.mix_usage = SECOND_RUN;
+
+	} else {
+		struct snd_kcontrol *kctl[TDM_CONTROL_NUM];
+		void *tdm_ctr[TDM_CONTROL_NUM] = {
+			&snd_adsp_tdm_playback_volume_control,
+			&snd_adsp_tdm_playback_sample_rate_out_control,
+			&snd_adsp_tdm_capture_volume_control,
+			&snd_adsp_tdm_capture_sample_rate_in_control
+		};
+
+		/* add basic control instances */
+		if (asoc_rtd_to_codec(runtime, 0)->id == 0) {
+			/* playback */
+			for (i = 0; i < 2; i++) {
+				kctl[i] = snd_ctl_new1(tdm_ctr[i], adsp_card);
+				err = snd_ctl_add(card, kctl[i]);
+				if (err < 0)
+					return -EINVAL;
+			}
+		} else {
+			/* capture */
+			for (i = 2; i < TDM_CONTROL_NUM; i++) {
+				kctl[i] = snd_ctl_new1(tdm_ctr[i], adsp_card);
+				err = snd_ctl_add(card, kctl[i]);
+				if (err < 0)
+					return -EINVAL;
+			}
+		}
+
+		/* assign ALSA buffer size */
+		alsa_buf_sz = TDM_MAX_BUFFER_BYTES;
+	}
+
+	snd_pcm_lib_preallocate_pages_for_all(runtime->pcm,
+			SNDRV_DMA_TYPE_CONTINUOUS,
+			snd_dma_continuous_data(GFP_KERNEL),
+			alsa_buf_sz, alsa_buf_sz);
+	return 0;
+}
+
+/* ****************************************************************************
+ * ALSA ADSP DAI register
+ * ***************************************************************************/
+
+/** callback function of component driver */
+static const struct snd_soc_component_driver snd_adsp_soc_component = {
+	.pcm_construct	= &snd_adsp_pcm_new,
+	.open = &snd_adsp_pcm_open,
+	.close = &snd_adsp_pcm_close,
+	.hw_params = &snd_adsp_pcm_hw_params,
+	.hw_free = &snd_adsp_pcm_hw_free,
+	.prepare = &snd_adsp_pcm_prepare,
+	.trigger = &snd_adsp_pcm_trigger,
+	.pointer = &snd_adsp_pcm_pointer,
+	.ack = &snd_adsp_pcm_ack,
+	.name = "snd_adsp",
+};
+
+/** DAI information of ADSP ALSA driver */
+static struct snd_soc_dai_driver snd_adsp_dai[MAX_DAI_IDX] = {
+	{
+		/* PRQA S 1053 */
+		.id			= RDR_DAI_IDX0,
+		.name			= "adsp-dai.0",
+		.playback.stream_name   = "Playback0",
+		.capture.stream_name	= "Capture0",
+	},
+	{
+		.id			= RDR_DAI_IDX1,
+		.name			= "adsp-dai.1",
+		.playback.stream_name   = "Playback1",
+		.capture.stream_name	= "Capture1",
+	},
+	{
+		.id			= RDR_DAI_IDX2,
+		.name			= "adsp-dai.2",
+		.playback.stream_name   = "Playback2",
+		.capture.stream_name	= "Capture2",
+	},
+	{
+		.id			= RDR_DAI_IDX3,
+		.name			= "adsp-dai.3",
+		.playback.stream_name   = "Playback3",
+		.capture.stream_name	= "Capture3",
+	},
+	{
+		.id			= TDM_DAI_IDX,
+		.name			= "adsp-tdm-dai",
+		.playback.stream_name   = "TDM Playback",
+		.capture.stream_name	= "TDM Capture",
+	}
+};
+
+/** ***************************************************************************
+ *  \brief	 Register platform driver and ADSP ALSA sound card
+ *
+ *  \param[in]	  pdev		Pointer to platform driver data
+ *  \retval	  0		Success
+ *  \retval	 -ENOMEM	Cannot allocate driver's data
+ *  \retval	 -EINVAL	Cannot register platform driver or sound card
+ ****************************************************************************/
+static int snd_adsp_probe(struct platform_device *pdev)
+{
+	struct snd_adsp_card *adsp_card;
+	int i;
+
+	/* allocate a card data structure */
+	adsp_card = kmalloc(sizeof(*adsp_card), GFP_KERNEL);
+	if (!adsp_card)
+		return -ENOMEM;
+
+	/* init parameters */
+	memset(adsp_card, 0, sizeof(*adsp_card)); /* PRQA S 3200 */
+
+	/* PRQA S 3200 1*/
+	memset(&adsp_card->ctr_if, -1, sizeof(struct snd_adsp_control));
+
+	/* disable Equalizer for all streams */
+	for (i = 0; i < (MAX_DAI_IDX - 1); i++) {
+		adsp_card->ctr_if.eqz_switch[DIRECT_CAPTURE][i] = 0;
+		adsp_card->ctr_if.eqz_switch[DIRECT_PLAYBACK][i] = 0;
+	}
+
+	/* disable MIX function for all */
+	adsp_card->ctr_if.mix_usage = MIX_UNUSED;
+
+	/* save driver data */
+	dev_set_drvdata(&pdev->dev, adsp_card);
+
+	/* fill format information of sound DAI driver for Rdr/Cap function */
+	for (i = 0; i < (MAX_DAI_IDX - 1); i++) {
+		snd_adsp_dai[i].playback.rates = SND_ADSP_SAMPLE_RATES;
+		snd_adsp_dai[i].playback.formats = SND_ADSP_PCM_WIDTHS;
+		snd_adsp_dai[i].playback.channels_min = MIN_CHANNEL;
+		snd_adsp_dai[i].playback.channels_max = MAX_CHANNEL;
+
+		snd_adsp_dai[i].capture.rates = SND_ADSP_SAMPLE_RATES;
+		snd_adsp_dai[i].capture.formats = SND_ADSP_PCM_WIDTHS;
+		snd_adsp_dai[i].capture.channels_min = MIN_CHANNEL;
+		snd_adsp_dai[i].capture.channels_max = MAX_CHANNEL;
+	}
+
+	/* fill format information of sound DAI driver for TDM function */
+	snd_adsp_dai[i].playback.rates = SND_ADSP_SAMPLE_RATES;
+	snd_adsp_dai[i].playback.formats = SND_ADSP_PCM_WIDTHS;
+	snd_adsp_dai[i].playback.channels_min = TDM_MIN_CHANNEL;
+	snd_adsp_dai[i].playback.channels_max = TDM_MAX_CHANNEL;
+
+	snd_adsp_dai[i].capture.rates = SND_ADSP_SAMPLE_RATES;
+	snd_adsp_dai[i].capture.formats = SND_ADSP_PCM_WIDTHS;
+	snd_adsp_dai[i].capture.channels_min = TDM_MIN_CHANNEL;
+	snd_adsp_dai[i].capture.channels_max = TDM_MAX_CHANNEL;
+
+	/*
+	 *	asoc register
+	 */
+	if (devm_snd_soc_register_component(&pdev->dev, &snd_adsp_soc_component,
+			snd_adsp_dai, ARRAY_SIZE(snd_adsp_dai)) < 0) {
+		dev_err(&pdev->dev, "failed to register component\n");
+		return -EINVAL;
+	}
+
+	dev_info(&pdev->dev, "probed\n");
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Unregister platform driver and ADSP ALSA sound card
+ *
+ *  \param[in]	pdev		Pointer platform driver data
+ *  \retval	0		Success
+ *  \retval	-EINVAL		Invalid driver's data
+ *****************************************************************************/
+static int snd_adsp_remove(struct platform_device *pdev)
+{
+	/* get ADSP sound card data */
+	struct snd_adsp_card *adsp_card = dev_get_drvdata(&pdev->dev);
+
+	if (!adsp_card)
+		return -ENODEV;
+
+	/* release the ADSP sound card */
+	kfree(adsp_card);
+
+	/* success */
+	return 0;
+}
+
+/** ADSP ALSA driver information */
+static const struct of_device_id snd_adsp_id[] = {
+	{ .compatible = "renesas,rcar_adsp_sound_gen3", },  /* PRQA S 1053 */
+};
+MODULE_DEVICE_TABLE(of, snd_adsp_id);
+
+/** platform driver of ADSP ALSA sound card */
+static struct platform_driver snd_adsp_driver = {
+	.driver	= {		 /* PRQA S 1053 */
+		.name	= "rcar_adsp_sound",
+		.of_match_table = snd_adsp_id,
+	},
+	.probe		= snd_adsp_probe,
+	.remove		= snd_adsp_remove,
+};
+module_platform_driver(snd_adsp_driver);		/* PRQA S 0651 */
+
+MODULE_AUTHOR("Renesas AudioDSP");
+MODULE_DESCRIPTION("Platform driver for ADSP");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ADSP-PCM-AUDIO");
diff --git a/sound/soc/adsp/xf-adsp-alsa.c.orig b/sound/soc/adsp/xf-adsp-alsa.c.orig
new file mode 100644
index 0000000..a445916
--- /dev/null
+++ b/sound/soc/adsp/xf-adsp-alsa.c.orig
@@ -0,0 +1,3949 @@
+/** ***************************************************************************
+ * \file	 xf-adsp-alsa.c
+ * \brief	 Source file for ADSP ALSA Driver
+ * \addtogroup	 ADSP Driver
+ ******************************************************************************
+ * \date	 May. 31, 2021
+ * \author	 Renesas Electronics Corporation
+ ******************************************************************************
+ * \par		Copyright
+ *
+ * Copyright(c) 2021 Renesas Electoronics Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/sched/signal.h>
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/pcm-indirect.h>
+#include <linux/time.h>
+
+#include "xf-adsp-base.h"
+
+/* Name of Volume control for playback */
+#define PLAYBACK_VOLUME_CTR_NAME	"PlaybackVolume"
+
+/* Name of Volume control for capture */
+#define CAPTURE_VOLUME_CTR_NAME		"CaptureVolume"
+
+/* Name of Sample Rate control for playback */
+#define PLAYBACK_OUT_RATE_CTR_NAME	"PlaybackOutRate"
+
+/* Name of Output Channel control for playback */
+#define PLAYBACK_OUT_CHANNEL_CTR_NAME	"PlaybackOutChannel"
+
+/* Name of Sample Rate control for capture */
+#define CAPTURE_IN_RATE_CTR_NAME	"CaptureInRate"
+
+/* Name of Equalizer parameters control for playback */
+#define PLAYBACK_EQZ_CTR_NAME		"PlaybackEQZControl"
+
+/* Name of Equalizer parameters control for capture */
+#define CAPTURE_EQZ_CTR_NAME		"CaptureEQZControl"
+
+/* Name of Equalizer Switch control for playback */
+#define PLAYBACK_EQZ_SWITCH_CTR_NAME	"PlaybackEQZSwitch"
+
+/* Name of Equalizer Switch control for capture */
+#define CAPTURE_EQZ_SWITCH_CTR_NAME	"CaptureEQZSwitch"
+
+/* Name of Volume control for TDM playback */
+#define TDM_PLAYBACK_VOLUME_CTR_NAME	"TDMPlaybackVolume"
+
+/* Name of Volume control for TDM capture */
+#define TDM_CAPTURE_VOLUME_CTR_NAME	"TDMCaptureVolume"
+
+/* Name of Sample Rate control for TDM playback */
+#define TDM_PLAYBACK_OUT_RATE_CTR_NAME	"TDMPlaybackOutRate"
+
+/* Name of Sample Rate control for TDM capture */
+#define TDM_CAPTURE_IN_RATE_CTR_NAME	"TDMCaptureInRate"
+
+/* Prefix of Playback control name */
+#define PREFIX_OF_PLAYBACK_CTR_NAME	PLAYBACK_VOLUME_CTR_NAME[0]
+
+/* Prefix of Capture control name */
+#define PREFIX_OF_CAPTURE_CTR_NAME	CAPTURE_VOLUME_CTR_NAME[0]
+
+/* Prefix of TDM control name */
+#define PREFIX_OF_TDM_CTR_NAME		TDM_PLAYBACK_VOLUME_CTR_NAME[0]
+
+/* Prefix of TDM playback */
+#define TDM_PLAYBACK			TDM_PLAYBACK_VOLUME_CTR_NAME[3]
+
+/* Prefix of TDM record */
+#define TDM_CAPTURE			TDM_CAPTURE_VOLUME_CTR_NAME[3]
+
+/* Number of control for playback & capture */
+#define RDR_CONTROL_NUM		(9)
+
+/* Number of controls for TDM */
+#define TDM_CONTROL_NUM		(4)
+
+/* Indicate playback stream */
+#define DIRECT_PLAYBACK		(0)
+
+/* Indicate capture stream */
+#define DIRECT_CAPTURE		(1)
+
+/* Indicate stream number */
+#define DIRECT_NUM		(2)
+
+/* Supported frame size for playback/record function in driver */
+#define FRAME_SIZE		(1024)
+
+/* Supported frame size for TDM playback/record function in driver */
+#define TDM_FRAME_SIZE		(1024)
+
+/* Supported sample rate in driver */
+#define SND_ADSP_SAMPLE_RATES	(SNDRV_PCM_RATE_32000 | \
+				 SNDRV_PCM_RATE_44100 | \
+				 SNDRV_PCM_RATE_48000)
+
+/* Supported PCM width in driver */
+#define SND_ADSP_PCM_WIDTHS	(SNDRV_PCM_FMTBIT_S16_LE | \
+				 SNDRV_PCM_FMTBIT_S24_LE)
+
+/* Macro to control DAI index */
+/* DAI 0 index for playback/record functions of stereo/mono formats */
+#define RDR_DAI_IDX0		(0)
+
+/* DAI 1 index for playback/record functions of stereo/mono formats */
+#define RDR_DAI_IDX1		(1)
+
+/* DAI 2 index for playback/record functions of stereo/mono formats */
+#define RDR_DAI_IDX2		(2)
+
+/* DAI 3 index for playback/record functions of stereo/mono formats */
+#define RDR_DAI_IDX3		(3)
+
+/* DAI 4 index for playback/record functions of TDM formats */
+#define TDM_DAI_IDX		(4)
+
+/* Maximum number of DAI supported by driver */
+#define MAX_DAI_IDX		(5)
+
+/* Renderer/Capture software information */
+/* Minimum channel number supported */
+#define MIN_CHANNEL		(1)
+
+/* Maximum channel number supported */
+#define MAX_CHANNEL		(2)
+
+/* Minimum buffer size in byte */
+#define MIN_BUF_SIZE		(FRAME_SIZE * MIN_CHANNEL * 2)
+
+/* Maximum buffer size in byte */
+#define MAX_BUF_SIZE		(FRAME_SIZE * MAX_CHANNEL * 4)
+
+/* Minimum numbers of period in the buffer */
+#define MIN_PERIOD		(1)
+
+/* Maximum numbers of period in the buffer */
+#define MAX_PERIOD		(4)
+
+/* Maximun numbers of bytes in ALSA buffer */
+#define MAX_BUFFER_BYTES	(MAX_PERIOD * MAX_BUF_SIZE)
+
+/* TDM software information */
+/*< Minimum channel number supported in TDM plugin */
+#define TDM_MIN_CHANNEL		(6)
+
+/* Maximum channel number supported in TDM plugin */
+#define TDM_MAX_CHANNEL		(8)
+
+/* Minimum buffer size in byte for TDM format */
+#define TDM_MIN_BUF_SIZE	(TDM_FRAME_SIZE * TDM_MIN_CHANNEL * 2)
+
+/* Maximum buffer size in byte for TDM format */
+#define TDM_MAX_BUF_SIZE	(TDM_FRAME_SIZE * TDM_MAX_CHANNEL * 4)
+
+/* Minimum numbers of period in the buffer for TDM format */
+#define TDM_MIN_PERIOD		(1)
+
+/* Maximum numbers of period in the buffer for TDM format  */
+#define TDM_MAX_PERIOD		(4)
+
+/* Maximum numbers of bytes in ALSA buffer for TDM format */
+#define TDM_MAX_BUFFER_BYTES	(TDM_MAX_PERIOD * TDM_MAX_BUF_SIZE)
+
+/* Volume scale used when user set */
+#define VOLUME_SCALE		(100)
+
+/* Maximum element in Equalizer parameter control */
+#define MAX_EQZ_PARAM_NUMBER	(55)
+
+/* Equalizer control is disabled */
+#define EQZ_OFF			(0)
+
+/* Equalizer control is enabled */
+#define EQZ_ON			(1)
+
+/* Component status */
+/* Handle state is NULL */
+#define XF_HANDLE_NULL		(0)
+
+/* Handle state is CREATED after creating handle successfully */
+#define XF_HANDLE_CREATED	BIT(0)
+
+/* Handle state is READY after finishing handle init */
+#define XF_HANDLE_READY		BIT(1)
+
+/* channels */
+/* Mono stream */
+#define MONAURAL		(1)
+
+/* Stereo stream */
+#define STEREO			(2)
+
+/* define number of bytes in a sample of 24 bits format types */
+/* store 24 bits data in 4 bytes LE */
+#define FMTBIT_S24_LE_BYTES_PER_SAMPLE		(4)
+
+/* store 24 bits data in 3 bytes LE */
+#define FMTBIT_S24_3LE_BYTES_PER_SAMPLE		(3)
+
+/* helper macro to get bytes per sample number */
+#define BYTES_PER_SAMPLE(fmt)   (FMTBIT_##fmt##_BYTES_PER_SAMPLE)
+
+/* check component is created */
+#define COMPONENT_IS_CREATED(n)	(((n & XF_HANDLE_CREATED) != 0) ? TRUE : FALSE)
+
+/* check component is ready */
+#define COMPONENT_IS_READY(n)	(((n & XF_HANDLE_READY) != 0) ? TRUE : FALSE)
+
+/* indicator of stream order */
+#define MIX_UNUSED			(0)
+#define FIRST_RUN			(2)
+#define SECOND_RUN			(1)
+
+/* check MIX usage */
+#define MIX_ENABLED(mix_ctl)	((mix_ctl == SECOND_RUN) ? TRUE : FALSE)
+
+/*******************************************************************
+ * base structures for ADSP ALSA driver
+ * ****************************************************************/
+
+/** \struct snd_adsp_control
+ *  \brief  Structure stores parameters from user
+ */
+struct snd_adsp_control {
+	/* Volume rate for playback/record */
+	int	   vol_rate[DIRECT_NUM][MAX_DAI_IDX - 1];
+
+	/* Volume rate for TDM playback/TDM record */
+	int	   tdm_vol_rate[DIRECT_NUM];
+
+	/* Out sample rate with Renderer, in sample rate with Capture */
+	int	   sample_rate[DIRECT_NUM][MAX_DAI_IDX - 1];
+
+	/* Out sample rate for TDM Renderer, in sample rate for TDM Capture */
+	int	   tdm_sample_rate[DIRECT_NUM];
+
+	/* Output channel of playback */
+	int	   rdr_out_ch[MAX_DAI_IDX - 1];
+
+	/* Equalizer parameters */
+	struct xf_adsp_equalizer_params eqz_params[DIRECT_NUM][MAX_DAI_IDX - 1];
+
+	/* Equalizer switch */
+	int	   eqz_switch[DIRECT_NUM][MAX_DAI_IDX - 1];
+
+	/* Indicator of MIX usage */
+	int	   mix_usage;
+};
+
+/** \struct snd_adsp_base_info
+ *  \brief  Structure stores some base information of a stream
+ */
+struct snd_adsp_base_info {
+	/* high resolution timer data */
+	struct hrtimer			hrtimer;
+
+	/* kernel time value in nanosecond */
+	ktime_t				ktime;
+
+	/* save interrupt state before getting lock */
+	unsigned long			flag;
+
+	/* high resolution timer state */
+	int				hrt_state;
+
+	/* target handle id of ALSA driver */
+	int				handle_id;
+
+	/* data buffer */
+	char				*buffer[XF_BUF_POOL_SIZE];
+
+	/* size of each allocated data buffer */
+	int				buf_bytes;
+
+	/* data index of buffer */
+	int				buf_idx;
+
+	/* queue index of buffer */
+	int				buf_queue;
+
+	/* HW index in bytes */
+	int				hw_idx;
+
+	/* number of bytes in a period */
+	int				period_bytes;
+
+	/* substream runtime object */
+	struct snd_pcm_substream	*substream;
+
+	/* indirect PCM data transfer */
+	struct snd_pcm_indirect		pcm_indirect;
+
+	/* spinlock data */
+	spinlock_t			lock;
+
+	/* runtime error indicator */
+	int				runtime_err;
+};
+
+/** \struct snd_adsp_playback
+ *  \brief  Structure stores data for playback function
+ */
+struct snd_adsp_playback {
+	/* base information of stream */
+	struct snd_adsp_base_info	base;
+
+	/* Renderer component data */
+	struct xf_adsp_renderer		*renderer;
+
+	/* Equalizer component data */
+	struct xf_adsp_equalizer	*equalizer;
+
+	/* Renderer component state */
+	int				rdr_state;
+
+	/* Equalizer component state */
+	int				eqz_state;
+};
+
+/** \struct snd_adsp_record
+ *  \brief  Structure stores data for record function
+ */
+struct snd_adsp_record {
+	/* base information of stream */
+	struct snd_adsp_base_info	base;
+
+	/* Capture component data */
+	struct xf_adsp_capture		*capture;
+
+	/* Equalizer component data */
+	struct xf_adsp_equalizer	*equalizer;
+
+	/* Capture component state */
+	int				cap_state;
+
+	/* Equalizer component state */
+	int				eqz_state;
+};
+
+/** \struct snd_adsp_tdm_playback
+ *  \brief  Structure stores data for TDM playback function
+ */
+struct snd_adsp_tdm_playback {
+	/* base information of stream */
+	struct snd_adsp_base_info	base;
+
+	/* TDM Renderer component data */
+	struct xf_adsp_tdm_renderer	*tdm_renderer;
+
+	/* TDM Renderer component state */
+	int				state;
+};
+
+/** \struct snd_adsp_tdm_record
+ *  \brief  Structure stores data for TDM record function
+ */
+struct snd_adsp_tdm_record {
+	/* base information of stream */
+	struct snd_adsp_base_info	base;
+
+	/* TDM Capture component data */
+	struct xf_adsp_tdm_capture	*tdm_capture;
+
+	/* TDM Capture component state */
+	int				state;
+};
+
+/** \struct snd_adsp_card
+ *  \brief  Structure stores data for ALSA sound card
+ */
+struct snd_adsp_card {
+	/* playback data */
+	struct snd_adsp_playback	*playback[MAX_DAI_IDX - 1];
+
+	/* record data */
+	struct snd_adsp_record		*record[MAX_DAI_IDX - 1];
+
+	/* TDM playback data */
+	struct snd_adsp_tdm_playback	*tdm_playback;
+
+	/* TDM record data */
+	struct snd_adsp_tdm_record	*tdm_record;
+
+	/* Structure contains params information for control */
+	struct snd_adsp_control		ctr_if;
+};
+
+/** HW configuration of ALSA ADSP card for Renderer/Capture */
+static struct snd_pcm_hardware snd_pcm_adsp_hw = {
+	.info		= (SNDRV_PCM_INFO_INTERLEAVED  /* PRQA S 1053 14 */
+			 | SNDRV_PCM_INFO_RESUME
+			 | SNDRV_PCM_INFO_BLOCK_TRANSFER
+			 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
+	.formats	   = SND_ADSP_PCM_WIDTHS,
+	.rates		   = SND_ADSP_SAMPLE_RATES,
+	.rate_min	   = 32000,
+	.rate_max	   = 48000,
+	.channels_min	   = MIN_CHANNEL,
+	.channels_max	   = MAX_CHANNEL,
+
+	/* maximum buffer size in bytes */
+	.buffer_bytes_max  = MAX_BUFFER_BYTES,
+
+	/* minimum size of the periods (frame) in bytes */
+	.period_bytes_min  = MIN_BUF_SIZE,
+
+	/* maximum size of the periods (frame) in bytes */
+	.period_bytes_max  = MAX_BUF_SIZE,
+
+	/* minimum periods (frames) in a buffer */
+	.periods_min	   = MIN_PERIOD,
+
+	/* maximum periods (frames) in a buffer */
+	.periods_max	   = MAX_PERIOD,
+};
+
+/* HW configuration of ALSA ADSP card for TDM */
+static struct snd_pcm_hardware snd_pcm_adsp_tdm_hw = {
+	.info		  = (SNDRV_PCM_INFO_INTERLEAVED  /* PRQA S 1053 14 */
+			   | SNDRV_PCM_INFO_RESUME
+			   | SNDRV_PCM_INFO_BLOCK_TRANSFER
+			   | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
+	.formats	  = SND_ADSP_PCM_WIDTHS,
+	.rates		  = SND_ADSP_SAMPLE_RATES,
+	.rate_min	  = 32000,
+	.rate_max	  = 48000,
+	.channels_min	  = TDM_MIN_CHANNEL,
+	.channels_max	  = TDM_MAX_CHANNEL,
+
+	/* maximum buffer size in bytes */
+	.buffer_bytes_max = TDM_MAX_BUFFER_BYTES,
+
+	/* minimum size of the periods (frame) in bytes */
+	.period_bytes_min = TDM_MIN_BUF_SIZE,
+
+	/* maximum size of the periods (frame) in bytes */
+	.period_bytes_max = TDM_MAX_BUF_SIZE,
+
+	/* minimum periods (frames) in a buffer */
+	.periods_min	  = TDM_MIN_PERIOD,
+
+	/* maximum periods (frames) in a buffer */
+	.periods_max	  = TDM_MAX_PERIOD,
+};
+
+/*******************************************************************
+ * function declaration
+ * ****************************************************************/
+
+static int
+snd_adsp_rdr_empty_buf_done(void *data, int opcode, int length, char *buffer);
+static int
+snd_adsp_rdr_fill_buf_done(void *data, int opcode, int length, char *buffer);
+static int
+snd_adsp_cap_empty_buf_done(void *data, int opcode, int length, char *buffer);
+static int
+snd_adsp_cap_fill_buf_done(void *data, int opcode, int length, char *buffer);
+static int
+snd_adsp_get_dai_id_from_substream(struct snd_pcm_substream *substream);
+static void *
+snd_adsp_get_drvdata_from_substream(struct snd_pcm_substream *substream);
+static struct snd_adsp_base_info *
+snd_adsp_get_base_from_substream(struct snd_pcm_substream *substream);
+static struct snd_adsp_base_info *
+snd_adsp_get_base_from_hrt(struct hrtimer *hrt);
+static enum hrtimer_restart snd_adsp_hrtimer_func(struct hrtimer *hrt);
+static int snd_adsp_playback_init(struct snd_adsp_playback **data,
+				  int eqz_flag,
+				  struct snd_pcm_substream *substream);
+static int snd_adsp_record_init(struct snd_adsp_record **data,
+				int eqz_flag,
+				struct snd_pcm_substream *substream);
+static int snd_adsp_playback_prepare(struct snd_adsp_playback *playback,
+				     struct snd_pcm_substream *substream);
+static int snd_adsp_record_prepare(struct snd_adsp_record *record,
+				   struct snd_pcm_substream *substream);
+static int snd_adsp_playback_deinit(struct snd_adsp_playback *playback);
+static int snd_adsp_record_deinit(struct snd_adsp_record *record);
+static int snd_adsp_tdm_playback_init(struct snd_adsp_tdm_playback **data,
+				      struct snd_pcm_substream *substream);
+static int snd_adsp_tdm_record_init(struct snd_adsp_tdm_record **data,
+				    struct snd_pcm_substream *substream);
+static int
+snd_adsp_tdm_playback_prepare(struct snd_adsp_tdm_playback *tdm_playback,
+			      struct snd_pcm_substream *substream);
+static int snd_adsp_tdm_record_prepare(struct snd_adsp_tdm_record *tdm_record,
+				       struct snd_pcm_substream *substream);
+static int
+snd_adsp_tdm_playback_deinit(struct snd_adsp_tdm_playback *tdm_playback);
+static int snd_adsp_tdm_record_deinit(struct snd_adsp_tdm_record *tdm_record);
+static int snd_adsp_pcm_open(struct snd_soc_component *component,
+					struct snd_pcm_substream *substream);
+static int snd_adsp_pcm_close(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream);
+static int snd_adsp_pcm_hw_params(struct snd_soc_component *component,
+				struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *hw_params);
+static int snd_adsp_pcm_hw_free(struct snd_soc_component *component,
+					struct snd_pcm_substream *substream);
+static int snd_adsp_pcm_prepare(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream);
+static int snd_adsp_pcm_trigger(struct snd_soc_component *component,
+							struct snd_pcm_substream *substream, int idx);
+static snd_pcm_uframes_t
+snd_adsp_pcm_pointer(struct snd_soc_component *component,
+				struct snd_pcm_substream *substream);
+static int snd_adsp_pcm_ack(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream);
+static void snd_adsp_pcm_transfer(struct snd_pcm_substream *substream,
+				  struct snd_pcm_indirect *rec, size_t bytes);
+static int snd_adsp_control_volume_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo);
+static int snd_adsp_control_volume_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol);
+static int snd_adsp_control_volume_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol);
+static int snd_adsp_control_eqz_get(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol);
+static int snd_adsp_control_eqz_info(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo);
+static int snd_adsp_control_eqz_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol);
+static int
+snd_adsp_control_eqz_switch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol);
+static int
+snd_adsp_control_eqz_switch_info(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_info *uinfo);
+static int
+snd_adsp_control_sample_rate_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol);
+static int
+snd_adsp_control_sample_rate_info(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo);
+static int
+snd_adsp_control_sample_rate_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol);
+static int
+snd_adsp_control_eqz_switch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol);
+static void snd_adsp_get_eqz_params_from_control(
+				struct xf_adsp_equalizer_params *eqz_params,
+				struct xf_adsp_equalizer_params *eqz_ctr_params,
+				bool flag);
+static int snd_adsp_pcm_new(struct snd_soc_component *component,
+				struct snd_soc_pcm_runtime *runtime);
+static int snd_adsp_probe(struct platform_device *pdev);
+static int snd_adsp_remove(struct platform_device *pdev);
+
+/*******************************************************************
+ * callback function of ADSP control interface
+ * ****************************************************************/
+/** **************************************************************************
+ *  \brief	event handler callback to notify error from ADSP
+ *
+ *  \param[in]	data		Pointer to ADSP ALSA sound card
+ *  \retval	0		Success
+ *****************************************************************************/
+static int snd_adsp_event_handler(void *data)
+{
+	struct snd_adsp_base_info *base = (struct snd_adsp_base_info *)data;
+
+	if (base)
+		base->runtime_err = TRUE;
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 empty buf done callback for playback/TDM playback functions
+ *
+ *  \param[in]	  data		Pointer to ADSP ALSA sound card
+ *  \param[in]	  opcode	Opcode of message
+ *  \param[in]	  length	Length of data buffer
+ *  \param[in]	  buffer	Pointer to data buffer
+ *  \retval	  0		Success
+ *****************************************************************************/
+static int
+snd_adsp_rdr_empty_buf_done(void *data, int opcode, int length, char *buffer)
+{
+	struct snd_adsp_base_info *base = (struct snd_adsp_base_info *)data;
+
+	if (base) {
+		spin_lock_irqsave(&base->lock, base->flag);
+
+		base->buf_queue++;
+		base->hw_idx += length; /* increase the DMA buffer index */
+
+		spin_unlock_irqrestore(&base->lock, base->flag);
+	}
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 fill buf done callback for playback/TDM playback functions
+ *
+ *  \param[in]	  data		Pointer to ADSP ALSA sound card
+ *  \param[in]	  opcode	Opcode of message
+ *  \param[in]	  length	Length of data buffer
+ *  \param[in]	  buffer	Pointer to data buffer
+ *  \retval	  0		Success
+ *****************************************************************************/
+static int
+snd_adsp_rdr_fill_buf_done(void *data, int opcode, int length, char *buffer)
+{
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 empty buf done callback for record/TDM record functions
+ *
+ *  \param[in]	  data		Pointer to ADSP ALSA sound card
+ *  \param[in]	  opcode	Opcode of message
+ *  \param[in]	  length	Length of data buffer
+ *  \param[in]	  buffer	Pointer to data buffer
+ *  \retval	  0		Success
+ *****************************************************************************/
+static int
+snd_adsp_cap_empty_buf_done(void *data, int opcode, int length, char *buffer)
+{
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 fill buf done callback for record/TDM record functions
+ *
+ *  \param[in]	  data		Pointer to ADSP ALSA sound card
+ *  \param[in]	  opcode	Opcode of message
+ *  \param[in]	  length	Length of data buffer
+ *  \param[in]	  buffer	Pointer to data buffer
+ * \retval	  0		Success
+ *****************************************************************************/
+static int
+snd_adsp_cap_fill_buf_done(void *data, int opcode, int length, char *buffer)
+{
+	struct snd_adsp_base_info *base = (struct snd_adsp_base_info *)data;
+
+	if (base) {
+		spin_lock_irqsave(&base->lock, base->flag);
+
+		base->buf_queue++;
+		base->hw_idx += length; /* increase the DMA buffer index */
+
+		spin_unlock_irqrestore(&base->lock, base->flag);
+	}
+
+	return 0;
+}
+
+/** callback functions for playback/TDM playback */
+static struct xf_callback_func rdr_callbacks =	/* PRQA S 3218 */
+{
+	.empty_buf_done = &snd_adsp_rdr_empty_buf_done,	/* PRQA S 1053 2 */
+	.fill_buf_done = &snd_adsp_rdr_fill_buf_done,
+	.event_handler = &snd_adsp_event_handler
+};
+
+/** callback functions for record/TDM record */
+static struct xf_callback_func cap_callbacks =	/* PRQA S 3218 */
+{
+	.empty_buf_done = &snd_adsp_cap_empty_buf_done,	/* PRQA S 1053 2 */
+	.fill_buf_done = &snd_adsp_cap_fill_buf_done,
+	.event_handler = &snd_adsp_event_handler
+};
+
+/*******************************************************************
+ * helper functions to get some internal data
+ * ****************************************************************/
+
+/** **************************************************************************
+ *  \brief	Get current index of CPU DAI from runtime data of substream
+ *
+ *  \param[in]	  substream	Pointer to PCM stream data
+ *  \retval	  id		Index of current CPU DAI
+ *****************************************************************************/
+static int
+snd_adsp_get_dai_id_from_substream(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd;
+
+	rtd = asoc_substream_to_rtd(substream);
+	return asoc_rtd_to_cpu(rtd, 0)->id;
+}
+
+/** **************************************************************************
+ *  \brief	Get ADSP ALSA driver's data from runtime data of substream
+ *
+ *  \param[in]	substream	Pointer to PCM stream data
+ *  \retval	pointer		Pointer to driver's data
+ *****************************************************************************/
+static void *
+snd_adsp_get_drvdata_from_substream(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd;
+
+	rtd = asoc_substream_to_rtd(substream);
+	return snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
+}
+
+/** **************************************************************************
+ *  \brief   Get base's data of playback/record from runtime data of substream
+ *
+ *  \param[in]	substream	Pointer to PCM stream data
+ *  \retval	pointer		Pointer to playback/record's base data
+ *****************************************************************************/
+static struct snd_adsp_base_info *
+snd_adsp_get_base_from_substream(struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_card *adsp_card;
+	struct snd_adsp_base_info *base;
+	int dai_idx;
+
+	adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+
+	/* get DAI index of substream */
+	dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+
+	/* get base data of the substream */
+	if (dai_idx == RDR_DAI_IDX0 || dai_idx == RDR_DAI_IDX1 ||
+	    dai_idx == RDR_DAI_IDX2 || dai_idx == RDR_DAI_IDX3) {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			base = !adsp_card->playback[dai_idx] ?
+				NULL : &adsp_card->playback[dai_idx]->base;
+		} else {
+			base = !adsp_card->record[dai_idx] ?
+				NULL : &adsp_card->record[dai_idx]->base;
+		}
+	} else {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			base = !adsp_card->tdm_playback ?
+				NULL : &adsp_card->tdm_playback->base;
+		} else {
+			base = !adsp_card->tdm_record ?
+				NULL : &adsp_card->tdm_record->base;
+		}
+	}
+
+	return base;
+}
+
+/** ***************************************************************************
+ *  \brief    Get playback/record/TDM playback/TDM record's base data
+ *	      from hr timer data
+ *
+ *  \param[in]	hrt		Pointer to hr timer data
+ *  \retval	pointer		Pointer to playback/record's base data
+ *****************************************************************************/
+static struct snd_adsp_base_info *
+snd_adsp_get_base_from_hrt(struct hrtimer *hrt)
+{
+	return (struct snd_adsp_base_info *)hrt;
+}
+
+/*****************************************************************************
+ * hrtimer interrupt function
+ * ***************************************************************************/
+
+/** **************************************************************************
+ *  \brief	Interrupt function of high resolution timer
+ *
+ *  \param[in]	hrt		Pointer to hr timer data
+ *  \retval	HRTIMER_RESTART Restart the timer after expire time
+ *****************************************************************************/
+static enum hrtimer_restart snd_adsp_hrtimer_func(struct hrtimer *hrt)
+{
+	struct snd_adsp_base_info *base = snd_adsp_get_base_from_hrt(hrt);
+
+	spin_lock_irqsave(&base->lock, base->flag);
+	if (base->hw_idx != 0) {
+		spin_unlock_irqrestore(&base->lock, base->flag);
+		/* update PCM status for the next period */
+		snd_pcm_period_elapsed(base->substream);
+	} else {
+		spin_unlock_irqrestore(&base->lock, base->flag);
+	}
+
+	hrtimer_forward_now(hrt, base->ktime);
+
+	return HRTIMER_RESTART;
+}
+
+/*****************************************************************************
+ * internal functions to manage playback and record functions
+ * ***************************************************************************/
+
+/** **************************************************************************
+ *  \brief	Initialize playback data
+ *
+ *  \param[out]	  playback_data		Pointer to store playback data
+ *  \param[in]	  eqz_flag		Flag to indicate equalizer usage
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	  EINVAL		Failed to initialize playback data
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int snd_adsp_playback_init(struct snd_adsp_playback **playback_data,
+				  int eqz_flag,
+				  struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_playback *playback;
+
+	/* allocate memory for playback data */
+	playback = kmalloc(sizeof(*playback), GFP_KERNEL);
+	if (!playback)
+		return -EINVAL;
+
+	/* init params */
+	memset(playback, 0, sizeof(struct snd_adsp_playback));
+
+	/* save the playback data */
+	*playback_data = playback;
+
+	/* set handle state as NULL state */
+	playback->rdr_state = XF_HANDLE_NULL;
+	playback->eqz_state = XF_HANDLE_NULL;
+	playback->base.hrt_state = XF_HANDLE_NULL;
+
+	/* register renderer component */
+	if (xf_adsp_renderer_create(&playback->renderer,
+				    &rdr_callbacks,
+				    (void *)&playback->base) < 0)
+		return -EINVAL;
+
+	/* mark renderer component created */
+	playback->rdr_state = XF_HANDLE_CREATED;
+
+	/* set target handle ID as renderer ID */
+	playback->base.handle_id = playback->renderer->handle_id;
+
+	if (eqz_flag == EQZ_ON) {
+		/* create equalizer component when equalizer is used */
+		if (xf_adsp_equalizer_create(&playback->equalizer,
+					     &rdr_callbacks,
+					     (void *)&playback->base) < 0)
+			return -EINVAL;
+
+		/* mark equalizer component created */
+		playback->eqz_state = XF_HANDLE_CREATED;
+
+		/* set target handle ID as equalizer ID */
+		playback->base.handle_id = playback->equalizer->handle_id;
+	}
+
+	/* init lock */
+	spin_lock_init(&playback->base.lock);
+
+	/* save the substream data */
+	playback->base.substream = substream;
+
+	/* init high resolution timer for updating hw status */
+	hrtimer_init(&playback->base.hrtimer,
+		     CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+
+	/* PRQA S 0563 1 */
+	playback->base.hrtimer.function = &snd_adsp_hrtimer_func;
+	playback->base.hrt_state = XF_HANDLE_CREATED;
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Initialize record data
+ *
+ *  \param[out]	 record_data	Pointer to store record data
+ *  \param[in]	 eqz_flag	Flag to indicate equalizer usage
+ *  \param[in]	 substream	Pointer to substream data
+ *  \retval	-EINVAL		Failed to initialize record data
+ *  \retval	 0		Success
+ *****************************************************************************/
+static int snd_adsp_record_init(struct snd_adsp_record **record_data,
+				int eqz_flag,
+				struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_record *record;
+
+	/* allocate memory for record data */
+	record = kmalloc(sizeof(*record), GFP_KERNEL);
+	if (!record)
+		return -EINVAL;
+
+	/* init params */
+	memset(record, 0, sizeof(struct snd_adsp_record));
+
+	/* save the record data */
+	*record_data = record;
+
+	/* set handle state as NULL state */
+	record->cap_state = XF_HANDLE_NULL;
+	record->eqz_state = XF_HANDLE_NULL;
+	record->base.hrt_state = XF_HANDLE_NULL;
+
+	/* register capture component */
+	if (xf_adsp_capture_create(&record->capture,
+				   &cap_callbacks,
+				   (void *)&record->base) < 0)
+		return -EINVAL;
+
+	/* mark capture component created */
+	record->cap_state = XF_HANDLE_CREATED;
+
+	/* set target handle ID as capture ID */
+	record->base.handle_id = record->capture->handle_id;
+
+	/* create equalizer component in case of it being used */
+	if (eqz_flag == EQZ_ON) {
+		if (xf_adsp_equalizer_create(&record->equalizer,
+					     &cap_callbacks,
+					     (void *)&record->base) < 0)
+			return -EINVAL;
+
+		/* mark equalizer component created */
+		record->eqz_state = XF_HANDLE_CREATED;
+
+		/* set target handle ID as equalizer ID */
+		record->base.handle_id = record->equalizer->handle_id;
+	}
+
+	/* init lock */
+	spin_lock_init(&record->base.lock);
+
+	/* save the substream data */
+	record->base.substream = substream;
+
+	/* init high resolution timer for updating hw status */
+	hrtimer_init(&record->base.hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+
+	/* PRQA S 0563 1 */
+	record->base.hrtimer.function = &snd_adsp_hrtimer_func;
+	record->base.hrt_state = XF_HANDLE_CREATED;
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Prepare playback function
+ *
+ *  \param[out]	  playback		Pointer to playback data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	 -EINVAL		Failed to prepare playback function
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int snd_adsp_playback_prepare(struct snd_adsp_playback *playback,
+				     struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_card *adsp_card;
+	int dai_idx, pcm_width, ch, fs, frame_size, vol_rate, hw_buffer_size;
+	int out_rate;
+	struct snd_adsp_control *ctr_if;
+	struct snd_pcm_runtime *runtime;
+	struct xf_adsp_renderer *renderer;
+	struct xf_adsp_equalizer *equalizer;
+	struct snd_adsp_base_info *base;
+	int i;
+
+	adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+	dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+	ctr_if = &adsp_card->ctr_if;
+	runtime = substream->runtime;
+	renderer = playback->renderer;
+	equalizer = playback->equalizer;
+	base = &playback->base;
+
+	/* runtime parameter */
+	fs = runtime->rate;
+	ch = runtime->channels;
+	pcm_width = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 24;
+	frame_size = runtime->period_size;
+	vol_rate = ctr_if->vol_rate[DIRECT_PLAYBACK][dai_idx];
+	out_rate = ctr_if->sample_rate[DIRECT_PLAYBACK][dai_idx];
+	hw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+	/* get number of bytes in a period */
+	base->period_bytes = snd_pcm_lib_period_bytes(substream);
+
+	if (pcm_width == 16)
+		base->buf_bytes = base->period_bytes;
+	else
+		base->buf_bytes = (base->period_bytes *
+			BYTES_PER_SAMPLE(S24_3LE)) / BYTES_PER_SAMPLE(S24_LE);
+
+	/* pcm indirect configuration */
+	base->pcm_indirect.hw_buffer_size = hw_buffer_size;
+	base->pcm_indirect.sw_buffer_size = base->pcm_indirect.hw_buffer_size;
+
+	/* it should equal to a period size in bytes */
+	base->pcm_indirect.hw_queue_size = base->period_bytes;
+
+	/* set parameters when Renderer is not ready */
+	if (COMPONENT_IS_READY(playback->rdr_state) == FALSE) {
+		struct xf_adsp_renderer_params *params = &renderer->params;
+
+		/* apply renderer parameters */
+		params->in_rate = fs;
+		params->channel = ch;
+		params->pcm_width = pcm_width;
+		params->frame_size = frame_size;
+
+		if (ctr_if->mix_usage == SECOND_RUN)
+			params->mix_ctrl = ctr_if->mix_usage;
+		else
+			params->mix_ctrl = MIX_UNUSED;
+
+		/* set flow as ADSP->PDMA0->SRC0->PDMA1->SSI0 */
+		params->dev1 = SRC0;
+		params->dev2 = SSI00;
+		params->dma1 = PDMA_CH00;
+		params->dma2 = PDMA_CH01;
+
+		/* when MIX is enabled, change to DMAC transfer type to save */
+		/* hw FIFO */
+		if (MIX_ENABLED(params->mix_ctrl) == TRUE)
+			params->dma1 = ADMAC_CH01;
+
+		/* set volume rate if it is set by user or default value */
+		/* is 100% */
+		if (vol_rate >= 0)
+			params->vol_rate = vol_rate;
+		else
+			params->vol_rate = (1 << 20);
+
+		/* set output channel if it is set by user */
+		if (ctr_if->rdr_out_ch[dai_idx] >= MONAURAL)
+			params->out_channel = ctr_if->rdr_out_ch[dai_idx];
+		else
+			params->out_channel = params->channel;
+
+		/* set sample rate output if it is set by user */
+		if (out_rate >= 0)
+			params->out_rate = out_rate;
+
+		/* set parameters to ADSP Renderer plugin */
+		if (xf_adsp_renderer_set_params(renderer) != 0)
+			return -EINVAL;
+
+		/* allocate buffer pool to prepare the execution */
+		renderer->buf_pool = xf_adsp_allocate_mem_pool(
+				XF_BUF_POOL_SIZE, base->buf_bytes);
+
+		if (IS_ERR(renderer->buf_pool))	/* PRQA S 306*/
+			return -EINVAL;
+
+		for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+			base->buffer[i] = xf_adsp_get_data_from_pool(
+					renderer->buf_pool, i);
+
+			base->buf_queue++;
+			memset(base->buffer[i], 0, base->buf_bytes);
+		}
+
+		/* mark Renderer ready */
+		playback->rdr_state |= XF_HANDLE_READY;
+
+		/* set parameters for Equalizer if it is used */
+		if (COMPONENT_IS_CREATED(playback->eqz_state) == TRUE) {
+			/* apply Equalizer parameter setting */
+			equalizer->params.channel = ch;
+			equalizer->params.pcm_width = pcm_width;
+			equalizer->params.rate = fs;
+
+			/* get equalizer parameters from control interface */
+			/* data */
+			snd_adsp_get_eqz_params_from_control(
+				&equalizer->params,
+				&ctr_if->eqz_params[DIRECT_PLAYBACK][dai_idx],
+				true);
+
+			/* set parameters to Equalizer plugin */
+			if (xf_adsp_equalizer_set_params(equalizer) != 0)
+				return -EINVAL;
+
+			/* route Equalizer to Renderer */
+			if (xf_adsp_route(equalizer->handle_id,
+					  renderer->handle_id,
+					  XF_BUF_POOL_SIZE,
+					  base->buf_bytes) != 0)
+				return -EINVAL;
+
+			/* mark Equalizer ready */
+			playback->eqz_state |= XF_HANDLE_READY;
+
+			/* prepare data before start PCM */
+			/* PRQA S 2462 1 */ /* PRQA S 2463 1 */
+			for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+				/* send buffer to plugin to kick */
+				/* init-processing */
+				if (xf_adsp_empty_this_buffer(
+							base->handle_id,
+							base->buffer[i],
+							base->buf_bytes) != 0)
+					return -EINVAL;
+
+				spin_lock_irqsave(&base->lock, base->flag);
+				base->buf_queue--;
+				spin_unlock_irqrestore(&base->lock, base->flag);
+			}
+		} else {
+			/* send zero buffer to plugin to kick */
+			/* init-processing */
+			if (xf_adsp_empty_this_buffer(base->handle_id,
+						      base->buffer[0],
+						      base->buf_bytes) != 0)
+				return -EINVAL;
+
+			spin_lock_irqsave(&base->lock, base->flag);
+			base->buf_queue--;
+			spin_unlock_irqrestore(&base->lock, base->flag);
+		}
+
+		/* wait until all the buffer have been consummed */
+		while (base->buf_queue != XF_BUF_POOL_SIZE) {
+			schedule_timeout_interruptible(2);
+			if (signal_pending(current))
+				break;
+
+			/* check the error from initialization */
+			if (base->runtime_err)
+				return -EINVAL;
+		}
+
+		/* reset HW index */
+		base->hw_idx = 0;
+	}
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Prepare record function
+ *
+ *  \param[out]	  record		Pointer to record data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	 -EINVAL		Failed to prepare record function
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int snd_adsp_record_prepare(struct snd_adsp_record *record,
+				   struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_card *adsp_card;
+	int dai_idx, pcm_width, ch, fs, frame_size, vol_rate, in_rate;
+	int hw_buffer_size, hw_queue_size;
+	struct snd_adsp_control *ctr_if;
+	struct snd_pcm_runtime *runtime;
+	struct xf_adsp_capture *capture;
+	struct xf_adsp_equalizer *equalizer;
+	struct snd_adsp_base_info *base;
+	int i;
+
+	adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+	dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+	ctr_if = &adsp_card->ctr_if;
+	runtime = substream->runtime;
+	capture = record->capture;
+	equalizer = record->equalizer;
+	base = &record->base;
+
+	/* runtime parameter */
+	fs = runtime->rate;
+	ch = runtime->channels;
+	pcm_width = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 24;
+	frame_size = runtime->period_size;
+	vol_rate = ctr_if->vol_rate[DIRECT_CAPTURE][dai_idx];
+	in_rate = ctr_if->sample_rate[DIRECT_CAPTURE][dai_idx];
+	hw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+	/* total size of allocated buffers */
+	hw_queue_size = base->period_bytes * XF_BUF_POOL_SIZE;
+
+	/* get number of bytes in a period */
+	base->period_bytes = snd_pcm_lib_period_bytes(substream);
+
+	if (pcm_width == 16)
+		base->buf_bytes = base->period_bytes;
+	else
+		base->buf_bytes = ((base->period_bytes *
+			BYTES_PER_SAMPLE(S24_3LE)) / BYTES_PER_SAMPLE(S24_LE));
+
+	/* pcm indirect configuration */
+	base->pcm_indirect.hw_buffer_size = hw_buffer_size;
+	base->pcm_indirect.sw_buffer_size = base->pcm_indirect.hw_buffer_size;
+	base->pcm_indirect.hw_queue_size = hw_queue_size;
+
+	/* prepare parameters to set to Capture plugin when it is not yet */
+	/* ready */
+	if (COMPONENT_IS_READY(record->cap_state) == FALSE) {
+		struct xf_adsp_capture_params *params = &capture->params;
+
+		/* apply capture parameters */
+		params->out_rate = fs;
+		params->channel = ch;
+		params->pcm_width = pcm_width;
+		params->frame_size = frame_size;
+
+		params->dev1 = SRC0;
+		params->dev2 = SSI10;
+		params->dma1 = PDMA_CH00;
+		params->dma2 = PDMA_CH01;
+
+		/* set volume rate if it is set by user or default volume as */
+		/* 100% */
+		if (vol_rate >= 0)
+			params->vol_rate = vol_rate;
+		else
+			params->vol_rate = (1 << 20);
+
+		/* set sample rate input if it is set by user */
+		if (in_rate >= 0)
+			params->in_rate = in_rate;
+
+		/* allocate buffer pool to prepare the execution */
+		capture->buf_pool = xf_adsp_allocate_mem_pool(
+				XF_BUF_POOL_SIZE, base->buf_bytes);
+
+		if (IS_ERR(capture->buf_pool))		 /* PRQA S 306 */
+			return -EINVAL;
+
+		for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+			base->buffer[i] = xf_adsp_get_data_from_pool(
+					capture->buf_pool, i);
+
+			base->buf_queue++;
+		}
+
+		/* set parameters to ADSP Capture plugin */
+		if (xf_adsp_capture_set_params(capture) != 0)
+			return -EINVAL;
+
+		/* mark Capture ready */
+		record->cap_state |= XF_HANDLE_READY;
+
+		/* set parameters for Equalizer if it's used */
+		if (COMPONENT_IS_CREATED(record->eqz_state) == TRUE) {
+			/* apply Equalizer parameter setting */
+			equalizer->params.channel = ch;
+			equalizer->params.pcm_width = pcm_width;
+			equalizer->params.rate = fs;
+
+			/* get equalizer parameter from control interface */
+			/* data */
+			snd_adsp_get_eqz_params_from_control(
+				&equalizer->params,
+				&ctr_if->eqz_params[DIRECT_CAPTURE][dai_idx],
+				true);
+
+			/* set parameters to Equalizer plugin */
+			if (xf_adsp_equalizer_set_params(equalizer) != 0)
+				return -EINVAL;
+
+			/* route Capture to Equalizer */
+			if (xf_adsp_route(capture->handle_id,
+					  equalizer->handle_id,
+					  XF_BUF_POOL_SIZE,
+					  base->buf_bytes) != 0)
+				return -EINVAL;
+
+			/* mark Equalizer ready */
+			record->eqz_state |= XF_HANDLE_READY;
+		}
+
+		/* kick init process by sending a zero buffer length */
+		xf_adsp_fill_this_buffer(base->handle_id, base->buffer[0], 0);
+
+		spin_lock_irqsave(&base->lock, base->flag);
+		base->buf_queue--;
+		spin_unlock_irqrestore(&base->lock, base->flag);
+
+		/* wait until finishing initialization */
+		while (base->buf_queue != XF_BUF_POOL_SIZE) {
+			schedule_timeout_interruptible(2);
+			if (signal_pending(current))
+				break;
+
+			/* check the error from initialization */
+			if (base->runtime_err)
+				return -EINVAL;
+		}
+
+		if (COMPONENT_IS_CREATED(record->eqz_state) == TRUE) {
+			/* PRQA S 2462 1 */ /* PRQA S 2463 1 */
+			for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+				/* send buffer to plugin */
+				if (xf_adsp_fill_this_buffer(
+						base->handle_id,
+						base->buffer[i],
+						base->buf_bytes) != 0)
+					return -EINVAL;
+
+				spin_lock_irqsave(&base->lock, base->flag);
+				base->buf_queue--;
+				spin_unlock_irqrestore(&base->lock, base->flag);
+			}
+
+			/* wait until all the buffer have been responsed */
+			while (base->buf_queue != XF_BUF_POOL_SIZE) {
+				schedule_timeout_interruptible(2);
+				if (signal_pending(current))
+					break;
+
+				/* check the error from initialization */
+				if (base->runtime_err)
+					return -EINVAL;
+			}
+		}
+
+		/* reset hw data position */
+		base->hw_idx = 0;
+	}
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Deinitialize playback function
+ *
+ *  \param[out]	playback	Pointer to playback data
+ *  \retval	-EINVAL		Failed to deinitialize playback function
+ *  \retval	0		Success
+ *****************************************************************************/
+static int snd_adsp_playback_deinit(struct snd_adsp_playback *playback)
+{
+	int ret = 0;
+
+	/* perform de-initialization if playback has been created already */
+	if (playback) {
+		/* perform completion process */
+		if (COMPONENT_IS_CREATED(playback->rdr_state) == TRUE) {
+			/* send buffer with zero length to plugin for */
+			/* completion process *//* PRQA S 3200 2 */
+			xf_adsp_empty_this_buffer(playback->base.handle_id,
+						  NULL, 0);
+
+			/* free buffer pool */ /* PRQA S 3200 1 */
+			xf_adsp_free_mem_pool(playback->renderer->buf_pool);
+
+			/* destroy Renderer */
+			if (xf_adsp_renderer_destroy(playback->renderer) != 0)
+				ret = -EINVAL;
+
+			playback->renderer = NULL;
+		}
+
+		/* destroy Equalizer if it is used */
+		if (COMPONENT_IS_CREATED(playback->eqz_state) == TRUE) {
+			if (xf_adsp_equalizer_destroy(playback->equalizer))
+				ret = -EINVAL;
+
+			playback->equalizer = NULL;
+		}
+
+		/* canncel timer interrupt */
+		if (COMPONENT_IS_CREATED(playback->base.hrt_state) == TRUE)
+			hrtimer_cancel(&playback->base.hrtimer);
+
+		/* free playback data */
+		kfree(playback);
+	}
+
+	return ret;
+}
+
+/** **************************************************************************
+ *  \brief	Deinitialize record function
+ *
+ *  \param[out]	 record		Pointer to record data
+ *  \retval	 -EINVAL	Failed to deinitialize record function
+ *  \retval	 0		Success
+ *****************************************************************************/
+static int snd_adsp_record_deinit(struct snd_adsp_record *record)
+{
+	int ret = 0;
+
+	/* perform de-initialization if record has been created already */
+	if (!record)
+		return ret;
+
+	/* perform completion process */
+	if (COMPONENT_IS_CREATED(record->cap_state) == TRUE) {
+		/* send buffer with zero length to plugin for */
+		/* completion process *//* PRQA S 3200 2 */
+		xf_adsp_empty_this_buffer(record->base.handle_id, NULL, 0);
+
+		/* free buffer pool */ /* PRQA S 3200 1 */
+		xf_adsp_free_mem_pool(record->capture->buf_pool);
+
+		if (xf_adsp_capture_destroy(record->capture))
+			ret = -EINVAL;
+
+		record->capture = NULL;
+	}
+
+	/* destroy Equalizer if it is used */
+	if (COMPONENT_IS_CREATED(record->eqz_state) == TRUE) {
+		if (xf_adsp_equalizer_destroy(record->equalizer) != 0)
+			ret = -EINVAL;
+
+		record->equalizer = NULL;
+	}
+
+	/* canncel timer interrupt */
+	if (COMPONENT_IS_CREATED(record->base.hrt_state) == TRUE)
+		hrtimer_cancel(&record->base.hrtimer);
+
+	/* free record data */
+	kfree(record);
+
+	return ret;
+}
+
+/*****************************************************************************
+ * internal functions to manage TDM playback and TDM record functions
+ * ***************************************************************************/
+
+/** **************************************************************************
+ *  \brief	Initialize TDM playback data
+ *
+ *  \param[out]	tdm_playback_data	Pointer to store TDM playback data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	  -EINVAL		Failed to initialize TDM playback data
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int
+snd_adsp_tdm_playback_init(struct snd_adsp_tdm_playback **tdm_playback_data,
+			   struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_tdm_playback *tdm_playback;
+
+	/* allocate memory for TDM playback data */
+	tdm_playback = kmalloc(sizeof(*tdm_playback), GFP_KERNEL);
+
+	if (!tdm_playback)
+		return -EINVAL;
+
+	/* init params */
+	memset(tdm_playback, 0, sizeof(struct snd_adsp_tdm_playback));
+
+	/* save the TDM playback data */
+	*tdm_playback_data = tdm_playback;
+
+	/* set handle state as NULL state */
+	tdm_playback->state = XF_HANDLE_NULL;
+	tdm_playback->base.hrt_state = XF_HANDLE_NULL;
+
+	/* register TDM renderer component */
+	if (xf_adsp_tdm_renderer_create(&tdm_playback->tdm_renderer,
+					&rdr_callbacks,
+					(void *)&tdm_playback->base) < 0)
+		return -EINVAL;
+
+	/* mark TDM renderer component created */
+	tdm_playback->state = XF_HANDLE_CREATED;
+
+	/* set target handle ID as TDM renderer ID */
+	tdm_playback->base.handle_id = tdm_playback->tdm_renderer->handle_id;
+
+	/* init lock */
+	spin_lock_init(&tdm_playback->base.lock);
+
+	/* save the substream data */
+	tdm_playback->base.substream = substream;
+
+	/* init high resolution timer for updating hw status */
+	hrtimer_init(&tdm_playback->base.hrtimer,
+		     CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+
+	/* PRQA S 0563 1 */
+	tdm_playback->base.hrtimer.function = &snd_adsp_hrtimer_func;
+	tdm_playback->base.hrt_state = XF_HANDLE_CREATED;
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Initialize TDM record data
+ *
+ *  \param[out]	  tdm_record_data	Pointer to store TDM record data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	  -EINVAL		Failed to initialize TDM record data
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int
+snd_adsp_tdm_record_init(struct snd_adsp_tdm_record **tdm_record_data,
+			 struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_tdm_record *tdm_record;
+
+	/* allocate memory for TDM record data */
+	tdm_record = kmalloc(sizeof(*tdm_record), GFP_KERNEL);
+	if (!tdm_record)
+		return -EINVAL;
+
+	/* init params */
+	memset(tdm_record, 0, sizeof(struct snd_adsp_tdm_record));
+
+	/* save the TDM record data */
+	*tdm_record_data = tdm_record;
+
+	/* set handle state as NULL state */
+	tdm_record->state = XF_HANDLE_NULL;
+	tdm_record->base.hrt_state = XF_HANDLE_NULL;
+
+	/* register TDM Capture component */
+	if (xf_adsp_tdm_capture_create(&tdm_record->tdm_capture,
+				       &cap_callbacks,
+				       (void *)&tdm_record->base) != 0)
+		return -EINVAL;
+
+	/* mark TDM capture component created */
+	tdm_record->state = XF_HANDLE_CREATED;
+
+	/* set target handle ID as TDM capture ID */
+	tdm_record->base.handle_id = tdm_record->tdm_capture->handle_id;
+
+	/* init lock */
+	spin_lock_init(&tdm_record->base.lock);
+
+	/* save the substream data */
+	tdm_record->base.substream = substream;
+
+	/* init high resolution timer for updating hw status */
+	hrtimer_init(&tdm_record->base.hrtimer,
+		     CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+
+	/* PRQA S 0563 1 */
+	tdm_record->base.hrtimer.function = &snd_adsp_hrtimer_func;
+	tdm_record->base.hrt_state = XF_HANDLE_CREATED;
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Prepare TDM playback function
+ *
+ *  \param[out]	  tdm_playback		Pointer to TDM playback data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	  -EINVAL		Failed to prepare TDM playback function
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int
+snd_adsp_tdm_playback_prepare(struct snd_adsp_tdm_playback *tdm_playback,
+			      struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_card *adsp_card;
+	struct snd_adsp_control *ctr_if;
+	struct snd_pcm_runtime *runtime;
+	struct xf_adsp_tdm_renderer *tdm_renderer;
+	struct snd_adsp_base_info *base;
+	int i;
+	int pcm_width, ch_mode, fs, frame_size, hw_buffer_size;
+
+	adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+	ctr_if = &adsp_card->ctr_if;
+	runtime = substream->runtime;
+	tdm_renderer = tdm_playback->tdm_renderer;
+	base = &tdm_playback->base;
+
+	/* runtime parameter */
+	fs = runtime->rate;
+	pcm_width = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 24;
+	frame_size = runtime->period_size;
+
+	ch_mode = (runtime->channels == 8) ?
+		XA_TDM_RDR_CHANNEL_MODE_1X8 : XA_TDM_RDR_CHANNEL_MODE_1X6;
+
+	hw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+	/* get number of bytes in a period */
+	base->period_bytes = snd_pcm_lib_period_bytes(substream);
+
+	if (pcm_width == 16)
+		base->buf_bytes = base->period_bytes;
+	else
+		base->buf_bytes = ((base->period_bytes *
+			BYTES_PER_SAMPLE(S24_3LE)) / BYTES_PER_SAMPLE(S24_LE));
+
+	/* pcm indirect configuration */
+	base->pcm_indirect.hw_buffer_size = hw_buffer_size;
+	base->pcm_indirect.sw_buffer_size = base->pcm_indirect.hw_buffer_size;
+
+	/* it should equal to a period size in bytes */
+	base->pcm_indirect.hw_queue_size = base->period_bytes;
+
+	/* prepare parameters to set to TDM playback as it is not ready */
+	if (COMPONENT_IS_READY(tdm_playback->state) == FALSE) {
+		struct xf_adsp_tdm_renderer_params *params;
+
+		params = &tdm_renderer->params;
+
+		/* apply renderer parameters */
+		params->in_rate = fs;
+		params->ch_mode = ch_mode;
+		params->pcm_width = pcm_width;
+		params->frame_size = frame_size;
+
+		/* setting Audio device indexes */
+		params->dma1 = ADMAC_CH00; /* use DMAC for transfer data */
+		params->dma2 = PDMA_CH03;
+		params->dev1 = SRC1;
+		params->dev2 = SSI30;  /* set SSI index to SSI30 */
+
+		/* set volume rate if it is set by user or default value as */
+		/* 100% */
+		params->vol_rate = (ctr_if->tdm_vol_rate[DIRECT_PLAYBACK] >= 0)
+			? ctr_if->tdm_vol_rate[DIRECT_PLAYBACK] : (1 << 20);
+
+		/* set output sampling rate if it is set by user */
+		if (ctr_if->tdm_sample_rate[DIRECT_PLAYBACK] >= 0)
+			params->out_rate =
+				ctr_if->tdm_sample_rate[DIRECT_PLAYBACK];
+
+		/* set parameters to ADSP TDM Renderer plugin */
+		if (xf_adsp_tdm_renderer_set_params(tdm_renderer) != 0)
+			return -EINVAL;
+
+		/* allocate buffer pool to prepare the execution */
+		tdm_renderer->buf_pool = xf_adsp_allocate_mem_pool(
+				XF_BUF_POOL_SIZE, base->buf_bytes);
+
+		if (IS_ERR(tdm_renderer->buf_pool))	/* PRQA S 306*/
+			return -EINVAL;
+
+		for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+			base->buffer[i] = xf_adsp_get_data_from_pool(
+					tdm_renderer->buf_pool, i);
+
+			base->buf_queue++;
+		}
+
+		/* mark TDM Renderer created */
+		tdm_playback->state |= XF_HANDLE_READY;
+
+		/* send zero buffer to plugin to kick init-processing */
+		memset(base->buffer[0], 0, base->buf_bytes);
+
+		if (xf_adsp_empty_this_buffer(base->handle_id, base->buffer[0],
+					      base->buf_bytes) != 0)
+			return -EINVAL;
+
+		spin_lock_irqsave(&base->lock, base->flag);
+		base->buf_queue--;
+		spin_unlock_irqrestore(&base->lock, base->flag);
+
+		/* wait until all the buffer have been consummed */
+		while (base->buf_queue != XF_BUF_POOL_SIZE) {
+			schedule_timeout_interruptible(2);
+			if (signal_pending(current))
+				break;
+
+			/* check the error from initialization */
+			if (base->runtime_err)
+				return -EINVAL;
+		}
+
+		/* reset HW index */
+		base->hw_idx = 0;
+	}
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Prepare TDM record function
+ *
+ *  \param[out]	  tdm_record		Pointer to TDM record data
+ *  \param[in]	  substream		Pointer to substream data
+ *  \retval	  -EINVAL		Failed to prepare TDM record function
+ *  \retval	  0			Success
+ *****************************************************************************/
+static int snd_adsp_tdm_record_prepare(struct snd_adsp_tdm_record *tdm_record,
+				       struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_card *adsp_card =
+		snd_adsp_get_drvdata_from_substream(substream);
+	struct snd_adsp_control *ctr_if = &adsp_card->ctr_if;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct xf_adsp_tdm_capture *tdm_capture = tdm_record->tdm_capture;
+	struct snd_adsp_base_info *base = &tdm_record->base;
+	int i;
+	int pcm_width, ch_mode, fs, frame_size;
+
+	/* runtime parameter */
+	fs = runtime->rate;
+
+	ch_mode = (runtime->channels == 8) ?
+		XA_TDM_RDR_CHANNEL_MODE_1X8 : XA_TDM_RDR_CHANNEL_MODE_1X6;
+
+	pcm_width = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 24;
+	frame_size = runtime->period_size;
+
+	/* get number of bytes in a period */
+	base->period_bytes = snd_pcm_lib_period_bytes(substream);
+	base->buf_bytes = (pcm_width == 16) ?
+			   base->period_bytes : ((base->period_bytes *
+						BYTES_PER_SAMPLE(S24_3LE)) /
+						BYTES_PER_SAMPLE(S24_LE));
+
+	/* pcm indirect configuration */
+	base->pcm_indirect.hw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	base->pcm_indirect.sw_buffer_size = base->pcm_indirect.hw_buffer_size;
+
+	/* total size of allocated buffers */
+	base->pcm_indirect.hw_queue_size = base->period_bytes *
+					   XF_BUF_POOL_SIZE;
+
+	/* prepare parameters to set to TDM Capture as it is not yet ready */
+	if (COMPONENT_IS_READY(tdm_record->state) == FALSE) {
+		struct xf_adsp_tdm_capture_params *params;
+
+		params = &tdm_capture->params;
+
+		/* apply capture parameters */
+		params->out_rate = fs;
+		params->ch_mode = ch_mode;
+		params->pcm_width = pcm_width;
+		params->frame_size = frame_size;
+
+		/* setting Audio device indexes */
+		params->dma1 = PDMA_CH00;
+		params->dma2 = PDMA_CH01;
+		params->dev1 = SRC0;
+		params->dev2 = SSI40;  /* set input device is SSI40 */
+
+		/* set volume rate if it is set by user or default value as */
+		/* 100% */
+		params->vol_rate = (ctr_if->tdm_vol_rate[DIRECT_CAPTURE] >= 0)
+			? ctr_if->tdm_vol_rate[DIRECT_CAPTURE] : (1 << 20);
+
+		/* set input rate if it is set by user */
+		if (ctr_if->tdm_sample_rate[DIRECT_CAPTURE] >= 0) {
+			params->in_rate =
+				ctr_if->tdm_sample_rate[DIRECT_CAPTURE];
+		}
+
+		/* allocate buffer pool to prepare the execution */
+		tdm_capture->buf_pool = xf_adsp_allocate_mem_pool(
+				XF_BUF_POOL_SIZE, base->buf_bytes);
+
+		if (IS_ERR(tdm_capture->buf_pool))	/* PRQA S 306 */
+			return -EINVAL;
+
+		for (i = 0; i < XF_BUF_POOL_SIZE; i++) {
+			base->buffer[i] = xf_adsp_get_data_from_pool(
+					tdm_capture->buf_pool, i);
+
+			base->buf_queue++;
+		}
+
+		/* set parameters to ADSP TDM Capture plugin */
+		if (xf_adsp_tdm_capture_set_params(tdm_capture) != 0)
+			return -EINVAL;
+
+		/* mark TDM Capture ready */
+		tdm_record->state |= XF_HANDLE_READY;
+
+		/* kick init process by sending a zero buffer length */
+		xf_adsp_fill_this_buffer(base->handle_id, base->buffer[0], 0);
+
+		spin_lock_irqsave(&base->lock, base->flag);
+		base->buf_queue--;
+		spin_unlock_irqrestore(&base->lock, base->flag);
+
+		/* wait until finishing initialization */
+		while (base->buf_queue != XF_BUF_POOL_SIZE) {
+			schedule_timeout_interruptible(2);
+			if (signal_pending(current))
+				break;
+
+			/* check the error from initialization */
+			if (base->runtime_err)
+				return -EINVAL;
+		}
+
+		/* reset hw data position */
+		base->hw_idx = 0;
+	}
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	Deinitialize TDM playback function
+ *
+ *  \param[out]	  tdm_playback	Pointer to TDM playback data
+ *  \retval	  -EINVAL	Failed to deinitialize TDM playback function
+ *  \retval	  0		Success
+ *****************************************************************************/
+static int
+snd_adsp_tdm_playback_deinit(struct snd_adsp_tdm_playback *tdm_playback)
+{
+	int ret = 0;
+
+	/* perform de-initialization if TDM playback has been created */
+	if (!tdm_playback)
+		return ret;
+
+	/* perform completion process */
+	if (COMPONENT_IS_CREATED(tdm_playback->state) == TRUE) {
+		/* send buffer with zero length to plugin for */
+		/* completion process */
+		/* PRQA S 3200 2 */
+		xf_adsp_empty_this_buffer(tdm_playback->base.handle_id,
+					  NULL, 0);
+
+		/* free buffer pool *//* PRQA S 3200 2 */
+		xf_adsp_free_mem_pool(tdm_playback->tdm_renderer->buf_pool);
+
+		/* destroy TDM Renderer component */
+		if (xf_adsp_tdm_renderer_destroy(
+				tdm_playback->tdm_renderer) != 0)
+			ret = -EINVAL;
+
+		tdm_playback->tdm_renderer = NULL;
+	}
+
+	/* canncel timer interrupt */
+	if (COMPONENT_IS_CREATED(tdm_playback->base.hrt_state) == TRUE)
+		hrtimer_cancel(&tdm_playback->base.hrtimer);
+
+	/* free playback data */
+	kfree(tdm_playback);
+
+	return ret;
+}
+
+/** **************************************************************************
+ *  \brief	Deinitialize TDM record function
+ *
+ *  \param[out]	 tdm_record	Pointer to TDM record data
+ *  \retval	 -EINVAL	Failed to deinitialize TDM record function
+ *  \retval	 0		Success
+ *****************************************************************************/
+static int snd_adsp_tdm_record_deinit(struct snd_adsp_tdm_record *tdm_record)
+{
+	int ret = 0;
+
+	/* perform de-initialization if TDM record has been created already */
+	if (!tdm_record)
+		return ret;
+
+	/* perform completion process */
+	if (COMPONENT_IS_CREATED(tdm_record->state) == TRUE) {
+		/* send buffer with zero length to plugin for */
+		/* completion process */
+		/* PRQA S 3200 2 */
+		xf_adsp_empty_this_buffer(tdm_record->base.handle_id, NULL, 0);
+
+		/* free buffer pool *//* PRQA S 3200 2 */
+		xf_adsp_free_mem_pool(tdm_record->tdm_capture->buf_pool);
+
+		/* destroy TDM Capture component */
+		if (xf_adsp_tdm_capture_destroy(tdm_record->tdm_capture) != 0)
+			ret = -EINVAL;
+
+		tdm_record->tdm_capture = NULL;
+	}
+
+	/* canncel timer interrupt */
+	if (COMPONENT_IS_CREATED(tdm_record->base.hrt_state) == TRUE)
+		hrtimer_cancel(&tdm_record->base.hrtimer);
+
+	/* free record data */
+	kfree(tdm_record);
+
+	return ret;
+}
+
+/*****************************************************************************
+ * callback functions of ADSP ALSA driver
+ * ***************************************************************************/
+
+/** **************************************************************************
+ *  \brief	 Open a playback/TDM playback or record/TDM record stream
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Error
+ *****************************************************************************/
+static int snd_adsp_pcm_open(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream)
+{
+	/* get ADSP soundcard and CPU DAI index */
+	struct snd_adsp_card *adsp_card;
+	int dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+	struct snd_adsp_control *ctr_if;
+
+	adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+	ctr_if = &adsp_card->ctr_if;
+
+	if (dai_idx == RDR_DAI_IDX0 || dai_idx == RDR_DAI_IDX1 ||
+	    dai_idx == RDR_DAI_IDX2 || dai_idx == RDR_DAI_IDX3) {
+		/* register data for playback/record functions */
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			/* perform playback initialization */
+			if (snd_adsp_playback_init(
+				   &adsp_card->playback[dai_idx],
+				   ctr_if->eqz_switch[DIRECT_PLAYBACK][dai_idx],
+				   substream) < 0) {
+				/* perform playback de-initialization when */
+				/* the initialization fails */
+				snd_adsp_playback_deinit(
+						adsp_card->playback[dai_idx]);
+
+				adsp_card->playback[dai_idx] = NULL;
+				return -EINVAL;
+			}
+		} else {
+			/* perform record initialization */
+			if (snd_adsp_record_init(
+				    &adsp_card->record[dai_idx],
+				    ctr_if->eqz_switch[DIRECT_CAPTURE][dai_idx],
+				    substream) < 0) {
+				/* perform record de-initialization when the */
+				/* initialization fails */
+				snd_adsp_record_deinit(
+						adsp_card->record[dai_idx]);
+
+				adsp_card->record[dai_idx] = NULL;
+				return -EINVAL;
+			}
+		}
+
+		/* save the hardware parameters */
+		snd_soc_set_runtime_hwparams(substream, &snd_pcm_adsp_hw);
+
+		/* each period has a frame size */
+		snd_pcm_hw_constraint_single(substream->runtime,
+					     SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+					     FRAME_SIZE);
+	} else {
+		/* register data for TDM playback/record functions */
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			/* perform TDM playback initialization */
+			if (snd_adsp_tdm_playback_init(
+						&adsp_card->tdm_playback,
+						substream) < 0) {
+				/* perform TDM playback de-initialization */
+				/* when the initialization fails */
+				snd_adsp_tdm_playback_deinit(
+						adsp_card->tdm_playback);
+
+				adsp_card->tdm_playback = NULL;
+				return -EINVAL;
+			}
+		} else {
+			/* perform TDM record initialization */
+			if (snd_adsp_tdm_record_init(&adsp_card->tdm_record,
+						     substream) < 0) {
+				/* perform TDM record de-initialization */
+				/* when the initialization fails */
+				snd_adsp_tdm_record_deinit(
+						adsp_card->tdm_record);
+
+				adsp_card->tdm_record = NULL;
+				return -EINVAL;
+			}
+		}
+
+		/* save the hardware parameters */
+		snd_soc_set_runtime_hwparams(substream, &snd_pcm_adsp_tdm_hw);
+
+		/* each period has a frame size */
+		snd_pcm_hw_constraint_single(substream->runtime,
+					     SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+					     TDM_FRAME_SIZE);
+	}
+
+	snd_pcm_hw_constraint_integer(substream->runtime,
+				      SNDRV_PCM_HW_PARAM_PERIODS);
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Close a playback/TDM playback or record/TDM record stream
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Error
+ *****************************************************************************/
+static int snd_adsp_pcm_close(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream)
+{
+	/* get ADSP soundcard and CPU DAI index */
+	struct snd_adsp_card *adsp_card =
+		snd_adsp_get_drvdata_from_substream(substream);
+	int dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+	int err = 0;
+
+	if (dai_idx == RDR_DAI_IDX0 || dai_idx == RDR_DAI_IDX1 ||
+	    dai_idx == RDR_DAI_IDX2 || dai_idx == RDR_DAI_IDX3) {
+		/* destroy Renderer/Capture or Equalizer (if used) */
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			if (snd_adsp_playback_deinit(
+					adsp_card->playback[dai_idx]) < 0)
+				err = -EINVAL;
+
+			adsp_card->playback[dai_idx] = NULL;
+		} else {
+			if (snd_adsp_record_deinit(
+					adsp_card->record[dai_idx]) < 0)
+				err = -EINVAL;
+
+			adsp_card->record[dai_idx] = NULL;
+		}
+	} else {
+		/* destroy TDM Renderer/TDM Capture */
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			if (snd_adsp_tdm_playback_deinit(
+					adsp_card->tdm_playback) < 0)
+				err = -EINVAL;
+
+			adsp_card->tdm_playback = NULL;
+		} else {
+			if (snd_adsp_tdm_record_deinit(
+					adsp_card->tdm_record) < 0)
+				err = -EINVAL;
+
+			adsp_card->tdm_record = NULL;
+		}
+	}
+
+	return err;
+}
+
+/** **************************************************************************
+ *  \brief	Allocate ALSA buffer and calculate expire time of hr timer
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-ENOMEM			Cannot allocate ALSA buffer
+ *****************************************************************************/
+static int snd_adsp_pcm_hw_params(struct snd_soc_component *component,
+				struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *hw_params)
+{
+	struct snd_adsp_base_info *base;
+	int err = 0;
+
+	base = snd_adsp_get_base_from_substream(substream);
+
+	/* set expire time of hrtimer, this value should be time for */
+	/* transfer a frame */
+	base->ktime = ns_to_ktime((1000000000 / params_rate(hw_params)) *
+				  params_period_size(hw_params));
+
+	err = snd_pcm_lib_malloc_pages(substream,
+				       params_buffer_bytes(hw_params));
+
+	/* reset DMA buffer area */
+	memset(substream->runtime->dma_area, 0, substream->runtime->dma_bytes);
+
+	return err;
+}
+
+/** **************************************************************************
+ *  \brief	 Free the allocated ALSA buffer
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Cannot deallocate buffer
+ *****************************************************************************/
+static int snd_adsp_pcm_hw_free(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream)
+{
+	return snd_pcm_lib_free_pages(substream);
+}
+
+/** **************************************************************************
+ *  \brief	 Prepare playback/TDM playback or record/TDM record function
+ *		   before transferring data
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval		 0		Success
+ *  \retval		 -EINVAL	Error
+ *****************************************************************************/
+static int snd_adsp_pcm_prepare(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream)
+{
+	/* get ADSP soundcard and CPU DAI index */
+	struct snd_adsp_card *
+		adsp_card = snd_adsp_get_drvdata_from_substream(substream);
+	int dai_idx = snd_adsp_get_dai_id_from_substream(substream);
+	int err = 0;
+
+	if (dai_idx == RDR_DAI_IDX0 || dai_idx == RDR_DAI_IDX1 ||
+	    dai_idx == RDR_DAI_IDX2 || dai_idx == RDR_DAI_IDX3) {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			/* get playback prepared to execute */
+			err = snd_adsp_playback_prepare(
+				adsp_card->playback[dai_idx], substream);
+		else
+			/* get record prepared to execute */
+			err = snd_adsp_record_prepare(
+				adsp_card->record[dai_idx], substream);
+	} else {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			/* get TDM playback prepared to execute */
+			err = snd_adsp_tdm_playback_prepare(
+				adsp_card->tdm_playback, substream);
+		else
+			/* get TDM record prepared to execute */
+			err = snd_adsp_tdm_record_prepare(
+				adsp_card->tdm_record, substream);
+	}
+
+	return err;
+}
+
+/** **************************************************************************
+ *  \brief	 Trigger playback/TDM playback or record/TDM record stream
+ *		   to go to next phase
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Error
+ *****************************************************************************/
+static int snd_adsp_pcm_trigger(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream, int idx)
+{
+	struct snd_adsp_base_info *
+		base = snd_adsp_get_base_from_substream(substream);
+
+	switch (idx) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		/* start high-resolution timer */
+		hrtimer_start(&base->hrtimer, base->ktime, HRTIMER_MODE_REL);
+
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+			int buf_queue = 0;
+
+			/* get current available buffer */
+			spin_lock_irqsave(&base->lock, base->flag);
+			buf_queue = base->buf_queue;
+			spin_unlock_irqrestore(&base->lock, base->flag);
+
+			/* send all available buffer to plugin to */
+			/* get data */
+			for (; buf_queue > 0; buf_queue--) {
+				if (xf_adsp_fill_this_buffer(
+						base->handle_id,
+						base->buffer[base->buf_idx],
+						base->buf_bytes) != 0)
+					return -EINVAL;
+
+				spin_lock_irqsave(&base->lock, base->flag);
+				base->buf_queue--;
+				spin_unlock_irqrestore(&base->lock, base->flag);
+
+				base->buf_idx++;
+
+				if (base->buf_idx >= XF_BUF_POOL_SIZE)
+					base->buf_idx = 0;
+			}
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Return HW data position
+ *
+ *  \param[in]	  component		Pointer to component of driver
+ *  \param[in]	  substream		Pointer to substream object
+ *  \retval	  position		HW data position
+ *****************************************************************************/
+static snd_pcm_uframes_t
+snd_adsp_pcm_pointer(struct snd_soc_component *component,
+				struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_base_info *
+		base = snd_adsp_get_base_from_substream(substream);
+	unsigned int hw_idx, hw_buffer_size;
+	snd_pcm_uframes_t pointer;
+
+	/* convert hw index to correct as submitted bytes */
+	spin_lock_irqsave(&base->lock, base->flag);
+	hw_idx = (base->hw_idx / base->buf_bytes) * base->period_bytes;
+	spin_unlock_irqrestore(&base->lock, base->flag);
+
+	hw_buffer_size = base->pcm_indirect.hw_buffer_size;
+
+	if (hw_idx >= hw_buffer_size) {
+		spin_lock_irqsave(&base->lock, base->flag);
+
+		base->hw_idx -= (hw_buffer_size / base->period_bytes) *
+							base->buf_bytes;
+
+		spin_unlock_irqrestore(&base->lock, base->flag);
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		pointer = snd_pcm_indirect_playback_pointer(substream,
+							    &base->pcm_indirect,
+							    hw_idx);
+	else
+		pointer = snd_pcm_indirect_capture_pointer(substream,
+							   &base->pcm_indirect,
+							   hw_idx);
+
+	return pointer;
+}
+
+/** **************************************************************************
+ *  \brief	  Call read/write process to transfer data
+ *
+ *  \param[in]	component		Pointer to component of driver
+ *  \param[in]	substream		Pointer to substream object
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Error
+ *****************************************************************************/
+static int snd_adsp_pcm_ack(struct snd_soc_component *component,
+						struct snd_pcm_substream *substream)
+{
+	struct snd_adsp_base_info *
+		base = snd_adsp_get_base_from_substream(substream);
+
+	if (base->runtime_err)
+		return -EINVAL;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_pcm_indirect_playback_transfer(substream,
+						   &base->pcm_indirect,
+						   snd_adsp_pcm_transfer);
+	else
+		snd_pcm_indirect_capture_transfer(substream,
+						  &base->pcm_indirect,
+						  snd_adsp_pcm_transfer);
+
+	return 0;
+}
+
+/** ***************************************************************************
+ *  \brief	  Copy data from source buffer to destination buffer
+ *
+ *  \params[in]	 dst		Destination buffer pointer
+ *  \params[out] src		Source buffer pointer
+ *  \params[in]	 dst_size	Destination buffer size in byte
+ *  \params[in]	 src_size	Source buffer size in byte
+ *  \retval	 None
+ *****************************************************************************/
+static inline void
+snd_adsp_copy_data(void *dst, void *src, int dst_size, int src_size)
+{
+	unsigned char *data_dst = dst;
+	unsigned char *data_src = src;
+	int i;
+
+	if (dst_size == src_size) {
+		/* src and dst bufs are same size, does not need to convert */
+		memcpy(data_dst, data_src, dst_size);
+
+	} else if (dst_size < src_size) {
+		for (i = 0; i < (dst_size - BYTES_PER_SAMPLE(S24_3LE));
+				i += BYTES_PER_SAMPLE(S24_3LE)) {
+			*(u32 *)data_dst = *(u32 *)data_src;
+
+			data_dst += BYTES_PER_SAMPLE(S24_3LE);
+			data_src += BYTES_PER_SAMPLE(S24_LE);
+		}
+
+		/* copy a S24_3LE sample from S24_LE sample */
+		data_dst[0] = data_src[0];
+		data_dst[1] = data_src[1];
+		data_dst[2] = data_src[2];
+
+	} else {
+		unsigned int tmp;
+
+		for (i = 0; i < (dst_size - BYTES_PER_SAMPLE(S24_LE));
+				i += BYTES_PER_SAMPLE(S24_LE)) {
+			tmp = *(u32 *)data_src;
+			*(u32 *)data_dst = tmp & 0x0FFFFFF;
+
+			data_dst += BYTES_PER_SAMPLE(S24_LE);
+			data_src += BYTES_PER_SAMPLE(S24_3LE);
+		}
+
+		/* copy a S24_LE sample from S24_3LE sample */
+		data_dst[0] = data_src[0];
+		data_dst[1] = data_src[1];
+		data_dst[2] = data_src[2];
+		data_dst[3] = 0;
+	}
+}
+
+/** **************************************************************************
+ *  \brief	  Transfer data process between ALSA buffer and ADSP buffer
+ *
+ *  \param[in]	  substream		Pointer to substream object
+ *  \param[in]	  rec			Pointer to indirect PCM data
+ *  \param[in]	  bytes			Number of byte need to be transferred
+ *  \retval	  None
+ *****************************************************************************/
+static void snd_adsp_pcm_transfer(struct snd_pcm_substream *substream,
+				  struct snd_pcm_indirect *rec,
+				  size_t bytes)
+{
+	struct snd_adsp_base_info *
+		base = snd_adsp_get_base_from_substream(substream);
+	int direct = substream->stream;
+	int trans_bytes = bytes;
+	int buf_bytes, period_bytes;
+	void *dma_buf, *data_buff;
+
+	/* get the DMA buffer pointer */
+	dma_buf = (void *)(substream->runtime->dma_area + rec->sw_data);
+
+	/* get information from base */
+	buf_bytes = base->buf_bytes;
+	period_bytes = base->period_bytes;
+
+	/* make sure the available buffer and transfer size - TBD */
+	while (trans_bytes > 0) {
+		spin_lock_irqsave(&base->lock, base->flag);
+		if (base->buf_queue > 0 && trans_bytes >= period_bytes) {
+			base->buf_queue--;
+			spin_unlock_irqrestore(&base->lock, base->flag);
+
+			/* get the buffer pointer from stream */
+			data_buff = base->buffer[base->buf_idx];
+
+			if (direct == SNDRV_PCM_STREAM_PLAYBACK) {
+				/* copy data from user *//* PRQA S 3200 2 */
+				snd_adsp_copy_data(data_buff, dma_buf,
+						   buf_bytes, period_bytes);
+
+				/* send buffer to plugin */
+				if (xf_adsp_empty_this_buffer(base->handle_id,
+							      data_buff,
+							      buf_bytes) < 0)
+					base->runtime_err = TRUE;
+			} else {
+				/* copy data to user *//* PRQA S 3200 2 */
+				snd_adsp_copy_data(dma_buf, data_buff,
+						   period_bytes, buf_bytes);
+
+				/* send buffer to plugin */
+				if (xf_adsp_fill_this_buffer(base->handle_id,
+							     data_buff,
+							     buf_bytes) < 0)
+					base->runtime_err = TRUE;
+			}
+
+			base->buf_idx++;
+			if (base->buf_idx >= XF_BUF_POOL_SIZE)
+				base->buf_idx = 0;
+		} else {
+			spin_unlock_irqrestore(&base->lock, base->flag);
+			break;
+		}
+
+		trans_bytes -= period_bytes;
+	}
+}
+
+/** **************************************************************************
+ *  \brief	 Get info of Volume control
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  uinfo		Pointer to info structure of volume control
+ *  \retval		 0	Success
+ *****************************************************************************/
+static int snd_adsp_control_volume_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = -1;
+	uinfo->value.integer.max = 799;
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Get volume value
+ *
+ *  \param[in]	kcontrol		Pointer to control instance
+ *  \param[in]	ucontrol		Pointer to volume value
+ *  \retval	0			Success
+ *  \retval	-EINVAL			Error
+ *****************************************************************************/
+static int snd_adsp_control_volume_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	struct snd_adsp_control *ctr_if = &adsp_card->ctr_if;
+	int handle_state, handle_id;
+	int volume, cmd_idx, direction;
+	unsigned int index;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* set handle state as NULL state */
+	handle_state = XF_HANDLE_NULL;
+	handle_id = -1;
+
+	/* determine command index, direction, handle state, handle ID */
+	if (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) {
+		cmd_idx = XA_RDR_CONFIG_PARAM_VOLUME_RATE;
+		direction = DIRECT_PLAYBACK;
+
+		if (adsp_card->playback[index]) {
+			handle_state = adsp_card->playback[index]->rdr_state;
+
+			handle_id =
+				adsp_card->playback[index]->renderer->handle_id;
+		}
+	} else if (kcontrol->id.name[0] == PREFIX_OF_CAPTURE_CTR_NAME) {
+		cmd_idx = XA_CAP_CONFIG_PARAM_VOLUME_RATE;
+		direction = DIRECT_CAPTURE;
+
+		if (adsp_card->record[index]) {
+			handle_state = adsp_card->record[index]->cap_state;
+
+			handle_id =
+				adsp_card->record[index]->capture->handle_id;
+		}
+	} else {
+		if (kcontrol->id.name[3] == TDM_PLAYBACK) {
+			cmd_idx = XA_TDM_RDR_CONFIG_PARAM_VOLUME_RATE;
+			direction = DIRECT_PLAYBACK;
+
+			if (adsp_card->tdm_playback) {
+				handle_state = adsp_card->tdm_playback->state;
+
+				handle_id =
+			       adsp_card->tdm_playback->tdm_renderer->handle_id;
+			}
+		} else {
+			cmd_idx = XA_TDM_CAP_CONFIG_PARAM_VOLUME_RATE;
+			direction = DIRECT_CAPTURE;
+
+			if (adsp_card->tdm_record) {
+				handle_state = adsp_card->tdm_record->state;
+
+				handle_id =
+				  adsp_card->tdm_record->tdm_capture->handle_id;
+			}
+		}
+	}
+
+	/* get the volume's value */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		/* get the volume's value from the plugin */
+		if (xf_adsp_get_param(handle_id, cmd_idx, &volume) != 0)
+			return -EINVAL;
+
+		/* check the value after getting it and adjust it */
+		ucontrol->value.integer.value[0] = (volume == 0xFFFFFFFF) ?
+					(-1) : (volume * VOLUME_SCALE) >> 20;
+	} else {
+		if (kcontrol->id.name[0] != PREFIX_OF_TDM_CTR_NAME)
+			ucontrol->value.integer.value[0] =
+					(ctr_if->vol_rate[direction][index] *
+					 VOLUME_SCALE) >> 20;
+		else
+			ucontrol->value.integer.value[0] =
+					(ctr_if->tdm_vol_rate[direction] *
+					 VOLUME_SCALE) >> 20;
+	}
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Set volume value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to volume value
+ *  \retval	  1		Volume change
+ *  \retval	  0		Volume does not change
+ *  \retval	  -EINVAL	Error
+ *****************************************************************************/
+/* PRQA S 3673 1*/
+static int
+snd_adsp_control_volume_put(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	struct snd_adsp_control *ctr_if = &adsp_card->ctr_if;
+	int volume;
+	int ret;
+	int handle_state, handle_id, cmd_idx, volume_get;
+	int direction;
+	unsigned int index;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* set handle state as NULL state and handle ID */
+	handle_state = XF_HANDLE_NULL;
+	handle_id = -1;
+
+	/* get the value to set */
+	if (ucontrol->value.integer.value[0] == -1) {
+		volume = 0xFFFFFFFF;
+	} else {
+		/* round up the value if needed */
+		volume = (ucontrol->value.integer.value[0] * (1 << 20)) /
+			  VOLUME_SCALE;
+
+		if ((ucontrol->value.integer.value[0] * (1 << 20)) >
+		    (VOLUME_SCALE * volume))
+			volume += 1;
+	}
+
+	/* determine command index, direction, handle state, handle ID */
+	if (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) {
+		cmd_idx = XA_RDR_CONFIG_PARAM_VOLUME_RATE;
+		direction = DIRECT_PLAYBACK;
+
+		if (adsp_card->playback[index]) {
+			handle_state = adsp_card->playback[index]->rdr_state;
+
+			handle_id =
+				adsp_card->playback[index]->renderer->handle_id;
+		}
+	} else if (kcontrol->id.name[0] == PREFIX_OF_CAPTURE_CTR_NAME) {
+		cmd_idx = XA_CAP_CONFIG_PARAM_VOLUME_RATE;
+		direction = DIRECT_CAPTURE;
+
+		if (adsp_card->record[index]) {
+			handle_state = adsp_card->record[index]->cap_state;
+
+			handle_id =
+				adsp_card->record[index]->capture->handle_id;
+		}
+	} else {
+		if (kcontrol->id.name[3] == TDM_PLAYBACK) {
+			cmd_idx = XA_TDM_RDR_CONFIG_PARAM_VOLUME_RATE;
+			direction = DIRECT_PLAYBACK;
+
+			if (adsp_card->tdm_playback) {
+				handle_state = adsp_card->tdm_playback->state;
+
+				handle_id =
+			       adsp_card->tdm_playback->tdm_renderer->handle_id;
+			}
+		} else {
+			cmd_idx = XA_TDM_CAP_CONFIG_PARAM_VOLUME_RATE;
+			direction = DIRECT_CAPTURE;
+
+			if (adsp_card->tdm_record) {
+				handle_state = adsp_card->tdm_record->state;
+
+				handle_id =
+				  adsp_card->tdm_record->tdm_capture->handle_id;
+			}
+		}
+	}
+
+	/* set volume to plugin */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		/* TDM does not support set volume in runtime state */
+		if (kcontrol->id.name[0] == PREFIX_OF_TDM_CTR_NAME)
+			return -EINVAL;
+
+		/* apply set volume value to ADSP from user setting */
+		if (xf_adsp_set_param(handle_id, cmd_idx, volume) != 0)
+			return -EINVAL;
+
+		/* get volume from ADSP after setting to confirm */
+		if (xf_adsp_get_param(handle_id, cmd_idx, &volume_get) != 0)
+			return -EINVAL;
+
+		/* check if the value has changed */
+		ret = (volume_get == volume) ? 1 : 0;
+	} else {
+		if (kcontrol->id.name[0] != PREFIX_OF_TDM_CTR_NAME)
+			ctr_if->vol_rate[direction][index] = volume;
+		else
+			ctr_if->tdm_vol_rate[direction] = volume;
+
+		ret = 1;
+	}
+
+	return ret;
+}
+
+/** **************************************************************************
+ *  \brief	 Get info of Sample Rate Converter control
+ *
+ *  \param[in]	kcontrol	Pointer to control instance
+ *  \param[in]	uinfo		Pointer to info structure of sample rate
+ *				converter control
+ *  \retval	0		Success
+ *****************************************************************************/
+static int snd_adsp_control_sample_rate_info(struct snd_kcontrol *kcontrol,
+					     struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = -1;
+	uinfo->value.integer.max = 48000;
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Get sample rate value
+ *
+ *  \param[in]	kcontrol	Pointer to control instance
+ *  \param[in]	ucontrol	Pointer to sample rate value
+ *  \retval	0		Success
+ *  \retval	-EINVAL		Error
+ *****************************************************************************/
+static int snd_adsp_control_sample_rate_get(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int *rate;
+	int handle_id, handle_state, cmd_idx, direction;
+	unsigned int index;
+
+	rate = (int *)&ucontrol->value.integer.value[0]; /* PRQA S 310 */
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* set handle state as NULL state and handle ID */
+	handle_state = XF_HANDLE_NULL;
+	handle_id = -1;
+
+	/* determine command, direction, handle state, handle ID */
+	if (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) {
+		cmd_idx = XA_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+		direction = DIRECT_PLAYBACK;
+
+		if (adsp_card->playback[index]) {
+			handle_state = adsp_card->playback[index]->rdr_state;
+
+			handle_id =
+				adsp_card->playback[index]->renderer->handle_id;
+		}
+	} else if (kcontrol->id.name[0] == PREFIX_OF_CAPTURE_CTR_NAME) {
+		cmd_idx = XA_CAP_CONFIG_PARAM_SAMPLE_RATE;
+		direction = DIRECT_CAPTURE;
+
+		if (adsp_card->record[index]) {
+			handle_state = adsp_card->record[index]->cap_state;
+
+			handle_id =
+				adsp_card->record[index]->capture->handle_id;
+		}
+	} else {
+		if (kcontrol->id.name[3] == TDM_PLAYBACK) {
+			cmd_idx = XA_TDM_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+			direction = DIRECT_PLAYBACK;
+
+			if (adsp_card->tdm_playback) {
+				handle_state = adsp_card->tdm_playback->state;
+
+				handle_id =
+			       adsp_card->tdm_playback->tdm_renderer->handle_id;
+			}
+		} else {
+			cmd_idx = XA_TDM_CAP_CONFIG_PARAM_IN_SAMPLE_RATE;
+			direction = DIRECT_CAPTURE;
+
+			if (adsp_card->tdm_record) {
+				handle_state = adsp_card->tdm_record->state;
+
+				handle_id =
+				  adsp_card->tdm_record->tdm_capture->handle_id;
+			}
+		}
+	}
+
+	/* get parameter from plugin */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		if (xf_adsp_get_param(handle_id, cmd_idx, rate) != 0)
+			return -EINVAL;
+	} else {
+		if (kcontrol->id.name[0] != PREFIX_OF_TDM_CTR_NAME)
+			*rate = adsp_card->ctr_if.sample_rate[direction][index];
+		else
+			*rate = adsp_card->ctr_if.tdm_sample_rate[direction];
+	}
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Set sample rate value
+ *
+ *  \param[in]	kcontrol	Pointer to control instance
+ *  \param[in]	ucontrol	Pointer to sample rate value
+ *  \retval	1		Sample rate change
+ *  \retval	0		Sample rate does not change
+ *  \retval	-EINVAL		Error
+ *****************************************************************************/
+/* PRQA S 3673 1 */
+static int
+snd_adsp_control_sample_rate_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	unsigned int index;
+	int rate;
+	int handle_state, cmd_idx, direction;
+	int ret = 1;
+
+	rate = (int)ucontrol->value.integer.value[0];
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* set handle state as NULL state */
+	handle_state = XF_HANDLE_NULL;
+
+	/* determine command, direction and handle state */
+	if (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) {
+		cmd_idx = XA_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+		direction = DIRECT_PLAYBACK;
+
+		if (adsp_card->playback[index])
+			handle_state = adsp_card->playback[index]->rdr_state;
+
+	} else if (kcontrol->id.name[0] == PREFIX_OF_CAPTURE_CTR_NAME) {
+		cmd_idx = XA_CAP_CONFIG_PARAM_SAMPLE_RATE;
+		direction = DIRECT_CAPTURE;
+
+		if (adsp_card->record[index])
+			handle_state = adsp_card->record[index]->cap_state;
+
+	} else {
+		if (kcontrol->id.name[3] == TDM_PLAYBACK) {
+			cmd_idx = XA_TDM_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+			direction = DIRECT_PLAYBACK;
+
+			if (adsp_card->tdm_playback)
+				handle_state = adsp_card->tdm_playback->state;
+
+		} else {
+			cmd_idx = XA_TDM_CAP_CONFIG_PARAM_IN_SAMPLE_RATE;
+			direction = DIRECT_CAPTURE;
+
+			if (adsp_card->tdm_record)
+				handle_state = adsp_card->tdm_record->state;
+		}
+	}
+
+	/* get the value to set */
+	if (COMPONENT_IS_READY(handle_state) == TRUE)
+		return -EINVAL;
+
+	if (kcontrol->id.name[0] != PREFIX_OF_TDM_CTR_NAME)
+		adsp_card->ctr_if.sample_rate[direction][index] = rate;
+	else
+		adsp_card->ctr_if.tdm_sample_rate[direction] = rate;
+
+	ret = 1;
+
+	return ret;
+}
+
+/** **************************************************************************
+ *  \brief	 Get info of Equalizer control
+ *
+ *  \param[in]	kcontrol	Pointer to control instance
+ *  \param[in]	uinfo		Pointer to info structure of Equalizer control
+ *  \retval	0		Success
+ *****************************************************************************/
+static int snd_adsp_control_eqz_info(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = MAX_EQZ_PARAM_NUMBER;
+	uinfo->value.integer.min = -1;
+	uinfo->value.integer.max = 0x7fffffff;
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Get equalizer parameters value
+ *
+ *  \param[in]	  kcontrol		Pointer to control instance
+ *  \param[in]	  ucontrol		Pointer to equalizer parameters value
+ *  \retval	  0			Success
+ *  \retval	  -EINVAL		Error
+ *****************************************************************************/
+static int snd_adsp_control_eqz_get(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int handle_state, direction;
+	int i, j, filter_index;
+	unsigned int index;
+	struct xf_adsp_equalizer *equalizer;
+	struct xf_adsp_equalizer_params *eqz_params;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* determin direction of stream */
+	direction = (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) ?
+					     DIRECT_PLAYBACK : DIRECT_CAPTURE;
+
+	/* set handle state as NULL state, handle ID, equalizer pointer */
+	handle_state = XF_HANDLE_NULL;
+	equalizer = NULL;
+
+	/* get component's state */
+	if (direction == DIRECT_PLAYBACK) {
+		if (adsp_card->playback[index]) {
+			handle_state = adsp_card->playback[index]->eqz_state;
+			equalizer = adsp_card->playback[index]->equalizer;
+		}
+	} else {
+		if (adsp_card->record[index]) {
+			handle_state = adsp_card->record[index]->eqz_state;
+			equalizer = adsp_card->record[index]->equalizer;
+		}
+	}
+
+	/* perform parameters' values getting */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		/* get equalizer's parameters */
+		if (xf_adsp_equalizer_get_params(equalizer) != 0)
+			return -EINVAL;
+
+		eqz_params = &equalizer->params;
+	} else {
+		eqz_params = &adsp_card->ctr_if.eqz_params[direction][index];
+	}
+
+	/* get equalizer type: PARAMETRIC or GRAPHIC */
+	ucontrol->value.integer.value[0] = eqz_params->eqz_type;
+
+	/* get parameters' value from Equalizer plugin */
+	if (eqz_params->eqz_type == XA_REL_EQZ_TYPE_PARAMETRIC) {
+		for (i = 0, filter_index = 1;
+		     filter_index <= XA_REL_EQZ_FILTER_NUM;
+		     i++, filter_index++) {
+			/* get filter index */
+			ucontrol->value.integer.value[(i * 6) + 1] =
+				filter_index;
+
+			/* get frequency centre */
+			ucontrol->value.integer.value[(i * 6) + 2] =
+				eqz_params->p_coef.fc[i];
+
+			/* get bandwidth */
+			ucontrol->value.integer.value[(i * 6) + 3] =
+				eqz_params->p_coef.band_width[i];
+
+			/* get filter type */
+			ucontrol->value.integer.value[(i * 6) + 4] =
+				eqz_params->p_coef.type[i];
+
+			/* get gain base */
+			ucontrol->value.integer.value[(i * 6) + 5] =
+				eqz_params->p_coef.gain_base[i];
+
+			/* get gain */
+			ucontrol->value.integer.value[(i * 6) + 6] =
+				eqz_params->p_coef.gain[i];
+		}
+	} else {
+		for (i = 0, filter_index = 1;
+		     filter_index <= XA_REL_EQZ_GRAPHIC_BAND_NUM;
+		     i++, filter_index++) {
+			/* get band index */
+			ucontrol->value.integer.value[(i * 2) + 1] =
+				filter_index;
+
+			/* get graphic gain */
+			ucontrol->value.integer.value[(i * 2) + 2] =
+				eqz_params->g_coef.gain_g[i];
+		}
+
+		j = (i * 2) + 1;
+
+		/* make the rest of values silent */
+		while (j < MAX_EQZ_PARAM_NUMBER) {
+			ucontrol->value.integer.value[j] = -1;
+			j++;
+		}
+	}
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Set equalizer parameters value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to equalizer parameters value
+ *  \retval	  1		Equalizer parameters change
+ *  \retval	  0		Equalizer parameters does not change
+ *  \retval	 -EINVAL	Error
+ *****************************************************************************/
+/* PRQA S 3673 1*/
+static int snd_adsp_control_eqz_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int handle_state, direction, filter_idx;
+	int i;
+	int index;
+	struct xf_adsp_equalizer_params *eqz_params = NULL;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* determine the direction */
+	direction = (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) ?
+					     DIRECT_PLAYBACK : DIRECT_CAPTURE;
+
+	/* set handle state as NULL state */
+	handle_state = XF_HANDLE_NULL;
+
+	/* get the handle state */
+	if (direction == DIRECT_PLAYBACK) {
+		if (adsp_card->playback[index])
+			handle_state = adsp_card->playback[index]->eqz_state;
+	} else {
+		if (adsp_card->record[index])
+			handle_state = adsp_card->record[index]->eqz_state;
+	}
+
+	/* perform equalizer's parameters setting */
+	if (COMPONENT_IS_READY(handle_state) == TRUE)
+		return -EINVAL;
+
+	/* PRQA S 310 1*/
+	eqz_params = &adsp_card->ctr_if.eqz_params[direction][index];
+
+	i = 0;
+	/* PRQA S 3440 1*/
+	eqz_params->eqz_type = ucontrol->value.integer.value[i];
+	i++;
+	filter_idx = 0;
+
+	if (eqz_params->eqz_type == XA_REL_EQZ_TYPE_PARAMETRIC) {
+		while (i < MAX_EQZ_PARAM_NUMBER) {
+			/* get index filter */
+			/* PRQA S 3440*/
+			filter_idx = ucontrol->value.integer.value[i];
+			i++;
+
+			/* valid index filter is range */
+			/* (1 to XA_REL_EQZ_FILTER_NUM) */
+			if (filter_idx >= 1 &&
+			    filter_idx <= XA_REL_EQZ_FILTER_NUM) {
+					/* PRQA S 3440 5*/
+				eqz_params->p_coef.fc[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+
+				i++;
+				eqz_params->p_coef.band_width[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+
+				i++;
+				eqz_params->p_coef.type[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+
+				i++;
+				eqz_params->p_coef.gain_base[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+
+				i++;
+				eqz_params->p_coef.gain[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+
+				i++;
+			}
+			/* index filter = -1 means that user */
+			/* does not set this filter */
+			else if (filter_idx == -1 || filter_idx == 0) {
+				i += 5;
+			} else {
+				return -EINVAL;
+			}
+		}
+	} else if (eqz_params->eqz_type == XA_REL_EQZ_TYPE_GRAPHIC) {
+		while (i < ((XA_REL_EQZ_GRAPHIC_BAND_NUM * 2) + 1)) {
+			/*get index filter */
+			/* PRQA S 3440 */
+			filter_idx = ucontrol->value.integer.value[i++];
+
+			if (filter_idx >= 1 &&
+			    filter_idx <= XA_REL_EQZ_GRAPHIC_BAND_NUM) {
+				eqz_params->g_coef.gain_g[filter_idx - 1] =
+					ucontrol->value.integer.value[i];
+				i++;
+
+			} else if (filter_idx == -1 || filter_idx == 0) {
+				i += 1;
+			} else {
+				return -EINVAL;
+			}
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	return 1;
+}
+
+/** **************************************************************************
+ *  \brief	 Get info of Equalizer Switch control
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  uinfo		Pointer to info structure of Equalizer
+ *				Switch control
+ *  \retval	  0		Success
+ *****************************************************************************/
+static int snd_adsp_control_eqz_switch_info(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Get equalizer switch value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to equalizer switch value
+ *  \retval	  0		Success
+ *  \retval	  -EINVAL	Error
+ *****************************************************************************/
+static int
+snd_adsp_control_eqz_switch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int direction;
+	unsigned int index;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* determine the direction */
+	direction = (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) ?
+					     DIRECT_PLAYBACK : DIRECT_CAPTURE;
+
+	/* get the Equalizer switch status */
+	ucontrol->value.integer.value[0] =
+		adsp_card->ctr_if.eqz_switch[direction][index];
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Set equalizer switch value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to equalizer switch value
+ *  \retval	  1		Equalizer switch change
+ *  \retval	  0		Equalizer switch does not change
+ *  \retval	 -EINVAL	Error
+ *****************************************************************************/
+/* PRQA S 3673 1 */
+static int
+snd_adsp_control_eqz_switch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int eqz_switch;
+	int handle_state, direction;
+	unsigned int index;
+	int ret = 0;
+
+	eqz_switch = ucontrol->value.integer.value[0];
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	/* determine the direction */
+	direction = (kcontrol->id.name[0] == PREFIX_OF_PLAYBACK_CTR_NAME) ?
+		     DIRECT_PLAYBACK : DIRECT_CAPTURE;
+
+	/* set handle state as NULL state */
+	handle_state = XF_HANDLE_NULL;
+
+	/* determine handle state */
+	if (direction == DIRECT_PLAYBACK) {
+		if (adsp_card->playback[index])
+			handle_state = adsp_card->playback[index]->rdr_state;
+	} else {
+		if (adsp_card->record[index])
+			handle_state = adsp_card->record[index]->cap_state;
+	}
+
+	/* set the status of Equalizer */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		/* runtime setting is not supported */
+		ret = -EINVAL;
+	} else {
+		adsp_card->ctr_if.eqz_switch[direction][index] = eqz_switch;
+		ret = 1;
+	}
+
+	return ret;
+}
+
+/** **************************************************************************
+ *  \brief	 Get info of Renderer output channel
+ *
+ *  \param[in]	  kcontrol Pointer to control instance
+ *  \param[in]	  uinfo	   Pointer to info structure of Renderer output channel
+ *  \retval	  0	   Success
+ *****************************************************************************/
+static int
+snd_adsp_control_rdr_out_channel_info(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = MONAURAL;
+	uinfo->value.integer.max = STEREO;
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Get Renderer output channel's value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to Renderer output channel value
+ *  \retval	  0		Success
+ *  \retval	 -EINVAL	Error
+ *****************************************************************************/
+static int
+snd_adsp_control_rdr_out_channel_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	int rdr_out_ch;
+	unsigned int index;
+	int handle_state, handle_id;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	handle_state = XF_HANDLE_NULL;
+	handle_id = -1;
+
+	/* determine handle state and handle ID */
+	if (adsp_card->playback[index]) {
+		handle_state = adsp_card->playback[index]->rdr_state;
+		handle_id = adsp_card->playback[index]->renderer->handle_id;
+	}
+
+	/* get Renderer output channel's value */
+	if (COMPONENT_IS_READY(handle_state) == TRUE) {
+		/* get Renderer output channel's value from Renderer plugin */
+		if (xf_adsp_get_param(handle_id,
+				      XA_RDR_CONFIG_PARAM_OUT_CHANNELS,
+				      &rdr_out_ch) != 0) {
+			return -EINVAL;
+		}
+
+		ucontrol->value.integer.value[0] = rdr_out_ch;
+	} else {
+		ucontrol->value.integer.value[0] =
+		adsp_card->ctr_if.rdr_out_ch[index];
+	}
+
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Set Renderer output channel's value
+ *
+ *  \param[in]	  kcontrol	Pointer to control instance
+ *  \param[in]	  ucontrol	Pointer to Renderer output channel value
+ *  \retval	  1		Success
+ *  \retval	  -EINVAL	Error
+ *****************************************************************************/
+static int
+snd_adsp_control_rdr_out_channel_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_adsp_card *adsp_card = snd_kcontrol_chip(kcontrol);
+	unsigned int index;
+	int handle_state;
+	int ret = 1;
+
+	/* get the index */
+	index = kcontrol->id.index;
+
+	handle_state = XF_HANDLE_NULL;
+
+	/* determine handle state and handle ID */
+	if (adsp_card->playback[index])
+		handle_state = adsp_card->playback[index]->rdr_state;
+
+	/* get Renderer output channel's value */
+	if (COMPONENT_IS_READY(handle_state) == TRUE)
+		/* not support runtime setting */
+		ret = -EINVAL;
+	else
+		adsp_card->ctr_if.rdr_out_ch[index] =
+			ucontrol->value.integer.value[0];
+
+	return ret;
+}
+
+/** control interface for playback's volume rate */
+/* PRQA S 3218 */
+static struct snd_kcontrol_new
+snd_adsp_playback_volume_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = PLAYBACK_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = PLAYBACK_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = PLAYBACK_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = PLAYBACK_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	}
+};
+
+/** control interface for Capture's volume rate */
+/* PRQA S 3218 1*/
+static struct snd_kcontrol_new
+snd_adsp_capture_volume_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = CAPTURE_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = CAPTURE_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = CAPTURE_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = CAPTURE_VOLUME_CTR_NAME,
+		.info = &snd_adsp_control_volume_info,
+		.get = &snd_adsp_control_volume_get,
+		.put = &snd_adsp_control_volume_put
+	}
+};
+
+/** control interface for playback's output sample rate */
+/* PRQA S 3218 1*/
+static struct snd_kcontrol_new
+snd_adsp_playback_sample_rate_out_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = PLAYBACK_OUT_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = PLAYBACK_OUT_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = PLAYBACK_OUT_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = PLAYBACK_OUT_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	}
+};
+
+/** control interface for Capture's input sample rate */
+/* PRQA S 3218 */
+static struct snd_kcontrol_new
+snd_adsp_capture_sample_rate_in_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = CAPTURE_IN_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = CAPTURE_IN_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = CAPTURE_IN_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = CAPTURE_IN_RATE_CTR_NAME,
+		.info = &snd_adsp_control_sample_rate_info,
+		.get = &snd_adsp_control_sample_rate_get,
+		.put = &snd_adsp_control_sample_rate_put
+	}
+};
+
+/** control interface for Equalizer parameters in playback */
+/* PRQA S 3218 1*/
+static struct snd_kcontrol_new
+snd_adsp_playback_equalizer_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = PLAYBACK_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = PLAYBACK_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = PLAYBACK_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = PLAYBACK_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	}
+};
+
+/** control interface for Equalizer parameters in record */
+/* PRQA S 3218 */
+static struct snd_kcontrol_new
+snd_adsp_capture_equalizer_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = CAPTURE_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = CAPTURE_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = CAPTURE_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = CAPTURE_EQZ_CTR_NAME,
+		.info = &snd_adsp_control_eqz_info,
+		.get = &snd_adsp_control_eqz_get,
+		.put = &snd_adsp_control_eqz_put
+	}
+};
+
+/** control interface for Equalizer usage in playback */
+/* PRQA S 3218 */
+static struct snd_kcontrol_new
+snd_adsp_playback_equalizer_switch_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = PLAYBACK_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = PLAYBACK_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = PLAYBACK_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = PLAYBACK_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	}
+};
+
+/** control interface for Equalizer usage in record */
+/* PRQA S 3218 1*/
+static struct snd_kcontrol_new
+snd_adsp_capture_equalizer_switch_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = CAPTURE_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX1,
+		.name = CAPTURE_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX2,
+		.name = CAPTURE_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX3,
+		.name = CAPTURE_EQZ_SWITCH_CTR_NAME,
+		.info = &snd_adsp_control_eqz_switch_info,
+		.get = &snd_adsp_control_eqz_switch_get,
+		.put = &snd_adsp_control_eqz_switch_put
+	}
+};
+
+/** control interface for playback's output channel */
+static struct snd_kcontrol_new
+snd_adsp_playback_out_channel_control[MAX_DAI_IDX - 1] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	/* PRQA S 1053 5 */
+		.index = RDR_DAI_IDX0,
+		.name = PLAYBACK_OUT_CHANNEL_CTR_NAME,
+		.info = &snd_adsp_control_rdr_out_channel_info,
+		.get = &snd_adsp_control_rdr_out_channel_get,
+		.put = &snd_adsp_control_rdr_out_channel_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.index = RDR_DAI_IDX1,
+		.name = PLAYBACK_OUT_CHANNEL_CTR_NAME,
+		.info = &snd_adsp_control_rdr_out_channel_info,
+		.get = &snd_adsp_control_rdr_out_channel_get,
+		.put = &snd_adsp_control_rdr_out_channel_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.index = RDR_DAI_IDX2,
+		.name = PLAYBACK_OUT_CHANNEL_CTR_NAME,
+		.info = &snd_adsp_control_rdr_out_channel_info,
+		.get = &snd_adsp_control_rdr_out_channel_get,
+		.put = &snd_adsp_control_rdr_out_channel_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.index = RDR_DAI_IDX3,
+		.name = PLAYBACK_OUT_CHANNEL_CTR_NAME,
+		.info = &snd_adsp_control_rdr_out_channel_info,
+		.get = &snd_adsp_control_rdr_out_channel_get,
+		.put = &snd_adsp_control_rdr_out_channel_put
+	}
+};
+
+/** control interface for TDM playback's volume rate */
+static struct snd_kcontrol_new snd_adsp_tdm_playback_volume_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		/* PRQA S 1053 5 */
+	.name = TDM_PLAYBACK_VOLUME_CTR_NAME,
+	.info = &snd_adsp_control_volume_info,
+	.get = &snd_adsp_control_volume_get,
+	.put = &snd_adsp_control_volume_put
+};
+
+/** control interface for TDM capture's volume rate */
+static struct snd_kcontrol_new snd_adsp_tdm_capture_volume_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		/* PRQA S 1053 5 */
+	.name = TDM_CAPTURE_VOLUME_CTR_NAME,
+	.info = &snd_adsp_control_volume_info,
+	.get = &snd_adsp_control_volume_get,
+	.put = &snd_adsp_control_volume_put
+};
+
+/** control interface for TDM playback's output sample rate */
+static struct snd_kcontrol_new snd_adsp_tdm_playback_sample_rate_out_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		/* PRQA S 1053 5 */
+	.name = TDM_PLAYBACK_OUT_RATE_CTR_NAME,
+	.info = &snd_adsp_control_sample_rate_info,
+	.get = &snd_adsp_control_sample_rate_get,
+	.put = &snd_adsp_control_sample_rate_put
+};
+
+/** control interface for TDM capture's input sample rate */
+static struct snd_kcontrol_new snd_adsp_tdm_capture_sample_rate_in_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		/* PRQA S 1053 5 */
+	.name = TDM_CAPTURE_IN_RATE_CTR_NAME,
+	.info = &snd_adsp_control_sample_rate_info,
+	.get = &snd_adsp_control_sample_rate_get,
+	.put = &snd_adsp_control_sample_rate_put
+};
+
+
+/*******************************************************************
+ * Internal functions
+ * ****************************************************************/
+
+/** **************************************************************************
+ *  \brief	 Process information get from control structure
+ *
+ *  \param[in]	  eqz_params	 Equalizer parameters object
+ *  \param[in]	  eqz_ctr_params Equalizer parameters stored in control object
+ *  \param[in]	  flag		 Indicate playback or capture stream
+ *****************************************************************************/
+static void snd_adsp_get_eqz_params_from_control(
+		struct xf_adsp_equalizer_params *eqz_params,
+		struct xf_adsp_equalizer_params *eqz_ctr_params, bool flag)
+{
+	int filter_idx;
+
+	if (flag) {
+		if (eqz_ctr_params->eqz_type >= 0)
+			eqz_params->eqz_type = eqz_ctr_params->eqz_type;
+
+		for (filter_idx = 0; filter_idx < XA_REL_EQZ_FILTER_NUM;
+		     filter_idx++) {
+			if (eqz_ctr_params->p_coef.fc[filter_idx] >= 0)
+				eqz_params->p_coef.fc[filter_idx] =
+				  eqz_ctr_params->p_coef.fc[filter_idx];
+
+			if (eqz_ctr_params->p_coef.band_width[filter_idx] >= 0)
+				eqz_params->p_coef.band_width[filter_idx] =
+				eqz_ctr_params->p_coef.band_width[filter_idx];
+
+			if (eqz_ctr_params->p_coef.type[filter_idx] >= 0)
+				eqz_params->p_coef.type[filter_idx] =
+				  eqz_ctr_params->p_coef.type[filter_idx];
+
+			if (eqz_ctr_params->p_coef.gain_base[filter_idx] >= 0)
+				eqz_params->p_coef.gain_base[filter_idx] =
+				  eqz_ctr_params->p_coef.gain_base[filter_idx];
+
+			if (eqz_ctr_params->p_coef.gain[filter_idx] >= 0)
+				eqz_params->p_coef.gain[filter_idx] =
+				  eqz_ctr_params->p_coef.gain[filter_idx];
+		}
+		for (filter_idx = 0; filter_idx < XA_REL_EQZ_GRAPHIC_BAND_NUM;
+		     filter_idx++) {
+			if (eqz_ctr_params->g_coef.gain_g[filter_idx] >= 0)
+				eqz_params->g_coef.gain_g[filter_idx] =
+				  eqz_ctr_params->g_coef.gain_g[filter_idx];
+		}
+	} else {
+		memcpy(eqz_ctr_params, eqz_params, sizeof(*eqz_params));
+	}
+}
+
+/*******************************************************************
+ * ALSA ADSP Platform driver interface
+ * ****************************************************************/
+
+/** ****************************************************************************
+ *  \brief	 Register control interface and preallocate ALSA buffer
+ *
+ *  \param[in]	  component	Pointer to component of driver
+ *  \param[in]	  runtime	Pointer to runtime PCM data
+ *  \retval	  0		Success
+ *  \retval	 -EINVAL	Cannot register control interface
+ ******************************************************************************/
+static int snd_adsp_pcm_new(struct snd_soc_component *component,
+					struct snd_soc_pcm_runtime *runtime)
+{
+	int i = 0, err = 0;
+	int id;
+	struct snd_card *card;
+	struct snd_adsp_card *adsp_card;
+	int alsa_buf_sz = 0;
+
+	/* get sound card data */
+	card = runtime->card->snd_card;
+
+	/* get driver data */
+	adsp_card = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(runtime, 0));
+
+	/* get the ID of CPU DAI */
+	id = asoc_rtd_to_cpu(runtime, 0)->id;
+
+	/* register control interfaces */
+	if (id == RDR_DAI_IDX0 || id == RDR_DAI_IDX1 ||
+	    id == RDR_DAI_IDX2 || id == RDR_DAI_IDX3) {
+		struct snd_kcontrol *kctl[RDR_CONTROL_NUM];
+		void *rdr_ctr[RDR_CONTROL_NUM] = {
+			&snd_adsp_playback_volume_control[id], /* PRQA S 1031 */
+			&snd_adsp_capture_volume_control[id],
+			&snd_adsp_playback_sample_rate_out_control[id],
+			&snd_adsp_capture_sample_rate_in_control[id],
+			&snd_adsp_playback_equalizer_control[id],
+			&snd_adsp_capture_equalizer_control[id],
+			&snd_adsp_playback_equalizer_switch_control[id],
+			&snd_adsp_capture_equalizer_switch_control[id],
+			&snd_adsp_playback_out_channel_control[id]
+		};
+
+		/* add basic control instance */
+		for (i = 0; i < RDR_CONTROL_NUM; i++) {
+			kctl[i] = snd_ctl_new1(rdr_ctr[i], adsp_card);
+			err = snd_ctl_add(card, kctl[i]);
+			if (err < 0)
+				return -EINVAL;
+		}
+
+		/* assign ALSA buffer size */
+		alsa_buf_sz = MAX_BUFFER_BYTES;
+
+		/* enable MIX feature from the 2nd playback/record stream */
+		if (adsp_card->ctr_if.mix_usage == MIX_UNUSED)
+			adsp_card->ctr_if.mix_usage = FIRST_RUN;
+		else if (adsp_card->ctr_if.mix_usage == FIRST_RUN)
+			adsp_card->ctr_if.mix_usage = SECOND_RUN;
+
+	} else {
+		struct snd_kcontrol *kctl[TDM_CONTROL_NUM];
+		void *tdm_ctr[TDM_CONTROL_NUM] = {
+			&snd_adsp_tdm_playback_volume_control,
+			&snd_adsp_tdm_playback_sample_rate_out_control,
+			&snd_adsp_tdm_capture_volume_control,
+			&snd_adsp_tdm_capture_sample_rate_in_control
+		};
+
+		/* add basic control instances */
+		for (i = 0; i < TDM_CONTROL_NUM; i++) {
+			kctl[i] = snd_ctl_new1(tdm_ctr[i], adsp_card);
+			err = snd_ctl_add(card, kctl[i]);
+			if (err < 0)
+				return -EINVAL;
+		}
+
+		/* assign ALSA buffer size */
+		alsa_buf_sz = TDM_MAX_BUFFER_BYTES;
+	}
+
+	snd_pcm_lib_preallocate_pages_for_all(runtime->pcm,
+			SNDRV_DMA_TYPE_CONTINUOUS,
+			snd_dma_continuous_data(GFP_KERNEL),
+			alsa_buf_sz, alsa_buf_sz);
+	return 0;
+}
+
+/* ****************************************************************************
+ * ALSA ADSP DAI register
+ * ***************************************************************************/
+
+/** callback function of component driver */
+static const struct snd_soc_component_driver snd_adsp_soc_component = {
+	.pcm_construct	= &snd_adsp_pcm_new,
+	.open = &snd_adsp_pcm_open,
+	.close = &snd_adsp_pcm_close,
+	.hw_params = &snd_adsp_pcm_hw_params,
+	.hw_free = &snd_adsp_pcm_hw_free,
+	.prepare = &snd_adsp_pcm_prepare,
+	.trigger = &snd_adsp_pcm_trigger,
+	.pointer = &snd_adsp_pcm_pointer,
+	.ack = &snd_adsp_pcm_ack,
+	.name = "snd_adsp",
+};
+
+/** DAI information of ADSP ALSA driver */
+static struct snd_soc_dai_driver snd_adsp_dai[MAX_DAI_IDX] = {
+	{
+		/* PRQA S 1053 */
+		.id			= RDR_DAI_IDX0,
+		.name			= "adsp-dai.0",
+		.playback.stream_name   = "Playback0",
+		.capture.stream_name	= "Capture0",
+	},
+	{
+		.id			= RDR_DAI_IDX1,
+		.name			= "adsp-dai.1",
+		.playback.stream_name   = "Playback1",
+		.capture.stream_name	= "Capture1",
+	},
+	{
+		.id			= RDR_DAI_IDX2,
+		.name			= "adsp-dai.2",
+		.playback.stream_name   = "Playback2",
+		.capture.stream_name	= "Capture2",
+	},
+	{
+		.id			= RDR_DAI_IDX3,
+		.name			= "adsp-dai.3",
+		.playback.stream_name   = "Playback3",
+		.capture.stream_name	= "Capture3",
+	},
+	{
+		.id			= TDM_DAI_IDX,
+		.name			= "adsp-tdm-dai",
+		.playback.stream_name   = "TDM Playback",
+		.capture.stream_name	= "TDM Capture",
+	}
+};
+
+/** ***************************************************************************
+ *  \brief	 Register platform driver and ADSP ALSA sound card
+ *
+ *  \param[in]	  pdev		Pointer to platform driver data
+ *  \retval	  0		Success
+ *  \retval	 -ENOMEM	Cannot allocate driver's data
+ *  \retval	 -EINVAL	Cannot register platform driver or sound card
+ ****************************************************************************/
+static int snd_adsp_probe(struct platform_device *pdev)
+{
+	struct snd_adsp_card *adsp_card;
+	int i;
+
+	/* allocate a card data structure */
+	adsp_card = kmalloc(sizeof(*adsp_card), GFP_KERNEL);
+	if (!adsp_card)
+		return -ENOMEM;
+
+	/* init parameters */
+	memset(adsp_card, 0, sizeof(*adsp_card)); /* PRQA S 3200 */
+
+	/* PRQA S 3200 1*/
+	memset(&adsp_card->ctr_if, -1, sizeof(struct snd_adsp_control));
+
+	/* disable Equalizer for all streams */
+	for (i = 0; i < (MAX_DAI_IDX - 1); i++) {
+		adsp_card->ctr_if.eqz_switch[DIRECT_CAPTURE][i] = 0;
+		adsp_card->ctr_if.eqz_switch[DIRECT_PLAYBACK][i] = 0;
+	}
+
+	/* disable MIX function for all */
+	adsp_card->ctr_if.mix_usage = MIX_UNUSED;
+
+	/* save driver data */
+	dev_set_drvdata(&pdev->dev, adsp_card);
+
+	/* fill format information of sound DAI driver for Rdr/Cap function */
+	for (i = 0; i < (MAX_DAI_IDX - 1); i++) {
+		snd_adsp_dai[i].playback.rates = SND_ADSP_SAMPLE_RATES;
+		snd_adsp_dai[i].playback.formats = SND_ADSP_PCM_WIDTHS;
+		snd_adsp_dai[i].playback.channels_min = MIN_CHANNEL;
+		snd_adsp_dai[i].playback.channels_max = MAX_CHANNEL;
+
+		snd_adsp_dai[i].capture.rates = SND_ADSP_SAMPLE_RATES;
+		snd_adsp_dai[i].capture.formats = SND_ADSP_PCM_WIDTHS;
+		snd_adsp_dai[i].capture.channels_min = MIN_CHANNEL;
+		snd_adsp_dai[i].capture.channels_max = MAX_CHANNEL;
+	}
+
+	/* fill format information of sound DAI driver for TDM function */
+	snd_adsp_dai[i].playback.rates = SND_ADSP_SAMPLE_RATES;
+	snd_adsp_dai[i].playback.formats = SND_ADSP_PCM_WIDTHS;
+	snd_adsp_dai[i].playback.channels_min = TDM_MIN_CHANNEL;
+	snd_adsp_dai[i].playback.channels_max = TDM_MAX_CHANNEL;
+
+	snd_adsp_dai[i].capture.rates = SND_ADSP_SAMPLE_RATES;
+	snd_adsp_dai[i].capture.formats = SND_ADSP_PCM_WIDTHS;
+	snd_adsp_dai[i].capture.channels_min = TDM_MIN_CHANNEL;
+	snd_adsp_dai[i].capture.channels_max = TDM_MAX_CHANNEL;
+
+	/*
+	 *	asoc register
+	 */
+	if (devm_snd_soc_register_component(&pdev->dev, &snd_adsp_soc_component,
+			snd_adsp_dai, ARRAY_SIZE(snd_adsp_dai)) < 0) {
+		dev_err(&pdev->dev, "failed to register component\n");
+		return -EINVAL;
+	}
+
+	dev_info(&pdev->dev, "probed\n");
+
+	/* success */
+	return 0;
+}
+
+/** **************************************************************************
+ *  \brief	 Unregister platform driver and ADSP ALSA sound card
+ *
+ *  \param[in]	pdev		Pointer platform driver data
+ *  \retval	0		Success
+ *  \retval	-EINVAL		Invalid driver's data
+ *****************************************************************************/
+static int snd_adsp_remove(struct platform_device *pdev)
+{
+	/* get ADSP sound card data */
+	struct snd_adsp_card *adsp_card = dev_get_drvdata(&pdev->dev);
+
+	if (!adsp_card)
+		return -ENODEV;
+
+	/* release the ADSP sound card */
+	kfree(adsp_card);
+
+	/* success */
+	return 0;
+}
+
+/** ADSP ALSA driver information */
+static const struct of_device_id snd_adsp_id[] = {
+	{ .compatible = "renesas,rcar_adsp_sound_gen3", },  /* PRQA S 1053 */
+};
+MODULE_DEVICE_TABLE(of, snd_adsp_id);
+
+/** platform driver of ADSP ALSA sound card */
+static struct platform_driver snd_adsp_driver = {
+	.driver	= {		 /* PRQA S 1053 */
+		.name	= "rcar_adsp_sound",
+		.of_match_table = snd_adsp_id,
+	},
+	.probe		= snd_adsp_probe,
+	.remove		= snd_adsp_remove,
+};
+module_platform_driver(snd_adsp_driver);		/* PRQA S 0651 */
+
+MODULE_AUTHOR("Renesas AudioDSP");
+MODULE_DESCRIPTION("Platform driver for ADSP");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ADSP-PCM-AUDIO");
diff --git a/sound/soc/adsp/xf-adsp-base.c b/sound/soc/adsp/xf-adsp-base.c
new file mode 100644
index 0000000..3ad9445
--- /dev/null
+++ b/sound/soc/adsp/xf-adsp-base.c
@@ -0,0 +1,2259 @@
+/** ***************************************************************************
+ *\file		xf-adsp-base.c
+ *\brief	Source file for ADSP Base Control layer
+ *\addtogroup	ADSP Driver
+ ******************************************************************************
+ *\date		Oct. 21, 2017
+ *\author	Renesas Electronics Corporation
+ ******************************************************************************
+ *\par		Copyright
+ *
+ * Copyright(c) 2016 Renesas Electoronics Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+
+#include "xf-adsp-base.h"
+
+#define XF_AUX_POOL_SIZE	(16)	/**< size of auxiliary pool*/
+#define XF_AUX_POOL_MSG_LENGTH	(256)	/**< size of auxiliary buffer   */
+
+#define XF_PROXY_ALIGN		(64)	/**< proxy alignment		*/
+
+/** \def XF_ALIGNED(size)
+ *  Get properly aligned buffer length
+ */
+#define XF_ALIGNED(size)\
+((((size) + XF_PROXY_ALIGN) - 1) & ~(XF_PROXY_ALIGN - 1)) /* PRQA S 3453 */
+
+#ifndef offset_of
+/** \def offset_of(type, member)
+ *  Return the offset of member in type structuer in byte
+ */
+#define offset_of(type, member)  \
+	((int)(long int)&(((const type *)(0))->member))	/* PRQA S 3453 */
+#endif
+
+/*************************************************
+ * Variable and and function declaration
+ * **********************************************/
+
+/** ADSP base control data */
+static struct xf_adsp_base *base;
+
+/* function declaration */
+static int xf_adsp_base_register_handle(void *private_data,
+					struct xf_callback_func *cb,
+					int comp_id);
+static inline struct xf_handle *xf_adsp_base_get_handle(int handle_id);
+static int xf_adsp_base_free_handle(int handle_id);
+static void xf_adsp_base_init_handle(void);
+static int xf_adsp_base_get_valid_handle(void);
+static int xf_send_and_receive(struct xf_message *msg);
+static int xf_response_thread(void *data);
+static void xf_buffer_put(struct xf_buffer *buffer);
+static u32 xf_buffer_length(struct xf_buffer *b);
+static struct xf_buffer *xf_buffer_get(struct xf_pool *pool);
+static void *xf_buffer_data(struct xf_buffer *b);
+static int xf_adsp_unregister(int comp_id);
+static int xf_adsp_register(char *name, int *comp_id);
+
+/*************************************************
+ * Helper function to process pool data
+ * **********************************************/
+
+/** ***********************************************************
+ *  \brief get buffer from given pool
+ *
+ *  \param[in]  pool	Data pool address
+ *  \retval	b	Pointer to buffer address in pool
+ **************************************************************/
+static struct xf_buffer *xf_buffer_get(struct xf_pool *pool)
+{
+	struct xf_buffer *b;
+
+	b = pool->free;
+	if (b) {
+		pool->free = b->link.next;
+		b->link.pool = pool;
+	}
+	return b;
+}
+
+/***********************************************************
+ *\brief return buffer back to pool
+ *
+ *\param[in]  buffer  Pointer to the buffer data
+ ************************************************************/
+static void xf_buffer_put(struct xf_buffer *buffer)
+{
+	struct xf_pool *pool = buffer->link.pool;
+
+	buffer->link.next = pool->free;
+	pool->free = buffer;
+}
+
+/***********************************************************
+ *\brief get the address of the given buffer data
+ *
+ *\param[in]	b		Pointer to the buffer data
+ *\retval	address		Address of buffer data
+ ************************************************************/
+static void *xf_buffer_data(struct xf_buffer *b)
+{
+	return b->address;
+}
+
+/************************************************************
+ *\brief get the length of the given buffer data
+ *
+ *\param[in]	b		Pointer to the buffer data
+ *\retval	length		Size of buffer data
+ ************************************************************/
+static u32 xf_buffer_length(struct xf_buffer *b)  /* PRQA S 3673 */
+{
+	return b->link.pool->length;
+}
+
+/************************************************************
+ *\brief set data to the given command message
+ *
+ *\param[out] m		Pointer to the command message
+ *\param[in]  id	Message ID
+ *\param[in]  opcode	Message opcode
+ *\param[in]  length	Message length
+ *\param[in]  buf	Pointer to the buffer data
+ *\param[in]  next	Pointer to the next message
+ *\retval     m		Pointer to the command message
+ ************************************************************/
+static inline struct xf_message *
+xf_create_msg(struct xf_message *m, u32 id, u32 opcode, u32 length, void *buf,
+	      struct xf_message *next)
+{
+	if (m) {
+		m->id = id;
+		m->opcode = opcode;
+		m->length = length;
+		m->buffer = buf;
+		m->next = next;
+	}
+
+	return m;
+}
+
+/*****************************************************************
+ *\brief synchronous send and wait for response message from proxy
+ *
+ *\param[in]	msg		Pointer to the command message
+ *\retval	0		Success
+ *\retval	-EINVAL		Failed
+ ****************************************************************/
+static int xf_send_and_receive(struct xf_message *msg)
+{
+	int err;
+	int opcode = msg->opcode;
+
+	/* reset the base flag */
+	spin_lock(&base->lock);
+	base->base_flag = FALSE;
+	spin_unlock(&base->lock);
+
+	err = base->cmd.send(base->client, (void *)msg);
+	if (err != 0)
+		return err;
+
+	/* sleep and wait for the response wake up event */
+	if (wait_event_interruptible(base->base_wait,
+				     base->base_flag || base->err_flag)) {
+		return -EINVAL;
+	}
+
+	if (base->err_flag != 0) {
+		spin_lock(&base->lock);
+		base->err_flag = FALSE;
+		spin_unlock(&base->lock);
+		return -EINVAL;
+	}
+
+	/* save the response message */
+	/* PRQA S 3200 */
+	memcpy(msg, &base->base_msg, sizeof(struct xf_message));
+
+	/* check if the reponsed message is right */
+	if (msg->opcode != opcode)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*************************************************************
+ *\brief send a message to proxy
+ *
+ *\param[in]	msg		Pointer to the command message
+ *\retval	0		Success
+ *\retval	-EINVAL		Failed
+ **************************************************************/
+static inline int xf_send(struct xf_message *msg)
+{
+	return base->cmd.send(base->client, (void *)msg);
+}
+
+/** ***********************************************************
+ *\brief receive message from proxy
+ *
+ *\param[in]	msg		Pointer to store the response message
+ *\retval	0		Success
+ *\retval	-EINVAL		Failed
+ **************************************************************/
+static inline int xf_receive(struct xf_message *msg)
+{
+	/* do not wait here */
+	return base->cmd.recv(base->client, (void *)msg);
+}
+
+/** ***********************************************************
+ *\brief thread for receive response data
+ **************************************************************/
+static int xf_response_thread(void *data)
+{
+	struct xf_message msg;
+	struct xf_handle *handle;
+	int id;
+
+	/* set polling to wait the response message */
+	spin_lock(&base->lock);
+	base->wait_flag = FALSE;
+	spin_unlock(&base->lock);
+
+	while (!kthread_should_stop()) {
+		if (base->cmd.poll(base->client, &base->wait_flag) != 0)
+			continue;
+
+		if (xf_receive(&msg) != 0)
+			continue;
+
+		/* get the handle id */
+		id = XF_AP_CLIENT(msg.id);
+
+		/* check the destination of the response message */
+		if (id == 0) {
+			/* message is from base control */
+			/* PRQA S 3200 1*/
+			memcpy(&base->base_msg, &msg,
+			       sizeof(struct xf_message));
+
+			spin_lock(&base->lock);
+			base->base_flag = TRUE;
+			spin_unlock(&base->lock);
+
+			wake_up(&base->base_wait);
+			continue;
+		}
+
+		/* get handle data */
+		handle = xf_adsp_base_get_handle(id);
+
+		if (handle == 0)
+			continue;
+
+		switch (msg.opcode) {
+		case XF_EMPTY_THIS_BUFFER:	/* PRQA S 0594 */
+			handle->cb->empty_buf_done(handle->private_data,
+						   msg.opcode,
+						   msg.length,
+						   msg.buffer);
+			break;
+		case XF_FILL_THIS_BUFFER:	/* PRQA S 0594 */
+			handle->cb->fill_buf_done(handle->private_data,
+						  msg.opcode,
+						  msg.length,
+						  msg.buffer);
+			break;
+		case XF_SET_PARAM:		/* PRQA S 0594 4 */
+		case XF_GET_PARAM:
+		case XF_ROUTE:
+		case XF_UNROUTE:
+			/* message is from base control */
+			memcpy(&base->base_msg, &msg,
+			       sizeof(struct xf_message)); /* PRQA S 3200 */
+
+			spin_lock(&base->lock);
+			base->base_flag = TRUE;
+			spin_unlock(&base->lock);
+
+			wake_up(&base->base_wait);
+			break;
+		default:
+			/* error has occurred */
+			handle->cb->event_handler(handle->private_data);
+
+			xf_adsp_base_free_handle(id); /* PRQA S 3200 */
+
+			spin_lock(&base->lock);
+			base->err_flag = TRUE;
+			spin_unlock(&base->lock);
+
+			wake_up(&base->base_wait);
+			break;
+		}
+	}
+
+	pr_info("ADSP base thread was exited\n");
+
+	do_exit(0);
+	return 0;
+}
+
+/*************************************************************
+ *	\brief register component to ADSP
+ *
+ *	\param[in]    name      Name string of component
+ *	\param[out]   comp_id   Store the registered component ID
+ *	\retval	      0         Success
+ *	\retval	      -EINVAL   Failed
+ **************************************************************/
+static int xf_adsp_register(char *name, int *comp_id)	/* PRQA S 3673 */
+{
+	struct xf_message msg;
+	struct xf_buffer *b = xf_buffer_get(base->aux_pool);
+	int err = 0;
+
+	msg.id = __XF_MSG_ID(__XF_AP_PROXY(0), __XF_DSP_PROXY(0));
+	msg.opcode = XF_REGISTER;
+	msg.length = strlen(name) + 1;
+	msg.buffer = xf_buffer_data(b);
+
+	/* copy identify name of ADSP component */
+	if (msg.length <= xf_buffer_length(b))
+		strncpy(msg.buffer, name, msg.length);	/* PRQA S 3200 */
+	else
+		strncpy(msg.buffer, name, xf_buffer_length(b));/* PRQA S 3200 */
+
+	err = xf_send_and_receive(&msg);
+	if (err != 0)
+		goto exit;		/* PRQA S 2001 */
+
+	/* save the registered component ID */
+	*comp_id = XF_MSG_SRC(msg.id);
+
+exit:
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** ***********************************************************
+ * \brief unregister component from ADSP
+ * \param[in]	comp_id		Registered component ID
+ * \retval	0		Success
+ * \retval	-EINVAL		Failed
+ **************************************************************/
+static int xf_adsp_unregister(int comp_id)
+{
+	struct xf_message msg;
+
+	xf_create_msg(&msg, __XF_MSG_ID(__XF_AP_PROXY(0), comp_id),
+		      XF_UNREGISTER, 0, NULL, NULL);	/* PRQA S 3200 */
+
+	return xf_send_and_receive(&msg);
+}
+
+/***************************************************************
+ * APIs for ADSP component helper
+ * ************************************************************/
+/** ***********************************************************
+ * \brief allocate memory pool from shared memory
+ * \param[in]   pool_size	Number of buffer need to allocate
+ * \param[in]   buf_length	Size of each buffer in bytes
+ * \retval	pool		Pointer to allocated pool
+ * \retval	-EINVAL		Invalid base data
+ * \retval	-ENOMEM		Out of memory resource
+ **************************************************************/
+struct xf_pool *xf_adsp_allocate_mem_pool(int pool_size, int buf_length)
+{
+	void *data;
+	u32 number;
+	struct xf_buffer *b;
+	struct xf_message msg;
+	struct xf_pool *pool;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base)
+		return ERR_PTR(-EINVAL);	/* PRQA S 0306 */
+
+	xf_create_msg(&msg, __XF_MSG_ID(__XF_AP_PROXY(0), __XF_DSP_PROXY(0)),
+		      XF_ALLOC,
+		      buf_length * pool_size, NULL, NULL); /* PRQA S 3200 */
+
+	err = xf_send_and_receive(&msg);
+	if (err != 0)
+		return ERR_PTR(-ENOMEM);		/* PRQA S 0306 */
+
+	/* PRQA S 0306 1 */
+	pool = kmalloc(offset_of(struct xf_pool, buffer) +
+		       (pool_size * sizeof(struct xf_buffer)), GFP_KERNEL);
+
+	if (!pool)
+		return ERR_PTR(-ENOMEM);	/* PRQA S 0306 */
+
+	pool->length = buf_length;
+	pool->number = pool_size;
+	pool->p = msg.buffer;
+
+	number = pool_size;
+	for (pool->free = b = &pool->buffer[0], data = pool->p;
+	     number > 0; number--, b++) {	/* PRQA S 2462,3418,0489 */
+		/* set address of the buffer */
+		b->address = data;
+
+		/* fill buffer into free list */
+		if (number == 1)
+			b->link.next = NULL;
+		else
+			b->link.next = b + 1;		/* PRQA S 0489 */
+
+		/* advance data pointer in contigous buffer */
+		data += buf_length;		/* PRQA S 0550 */
+	}
+
+	return pool;
+}
+
+/** ***********************************************************
+ *\brief return memory to shared memory
+ *\param[in]	pool	Data pool address
+ *\retval	0	Success
+ *\retval	-EINVAL Invalid base or pool data
+ **************************************************************/
+int xf_adsp_free_mem_pool(struct xf_pool *pool)
+{
+	struct xf_message msg;
+
+	/* check the sane ADSP base pool data*/
+	if (!base || !pool)
+		return -EINVAL;
+
+	xf_create_msg(&msg, __XF_MSG_ID(__XF_AP_PROXY(0), __XF_DSP_PROXY(0)),
+		      XF_FREE, pool->number * pool->length,
+		      pool->p, NULL);		/* PRQA S 3200 */
+
+	xf_send_and_receive(&msg);		/* PRQA S 3200 */
+
+	kfree(pool);
+
+	return 0;
+}
+
+/** ***********************************************************
+ *\brief get buffer from given pool
+ *
+ *\param[in]	pool	Data pool address
+ *\param[in]	index   Buffer index
+ *\retval	b	Pointer to buffer address in pool
+ *\retval	-EINVAL Invalid pool or index
+ **************************************************************/
+char *xf_adsp_get_data_from_pool(struct xf_pool *pool, int index)
+{
+	struct xf_buffer *buf[XF_BUF_POOL_SIZE] = {0};
+	char *data;
+	int i;
+
+	/* check the sane pool data*/
+	if (!pool)
+		return ERR_PTR(-EINVAL);		/* PRQA S 306 */
+
+	/* check the index is valid */
+	if (index > (pool->number - 1))
+		return ERR_PTR(-EINVAL);		/* PRQA S 306 */
+
+	/* get buffer from pool */
+	for (i = 0; i <= index; i++)
+		buf[i] = xf_buffer_get(pool);
+
+	/* get data from buffer */
+	data = xf_buffer_data(buf[index]);
+
+	/* return buffer to pool */
+	for (i = index; i >= 0; i--)
+		xf_buffer_put(buf[i]);
+
+	return data;
+}
+
+/** ***********************************************************
+ *\brief  send empty this buffer command to ADSP framework
+ *
+ *\param[in]	handle_id	ID of the registered handle
+ *\param[in]	buffer		Pointer to data buffer
+ *\param[in]	length		Size of buffer in bytes
+ *\retval	0		Success
+ *\retval	-EINVAL		Failed
+ **************************************************************/
+int xf_adsp_empty_this_buffer(int handle_id, char *buffer, int length)
+{
+	struct xf_message msg;
+	struct xf_handle *handle;
+
+	/* check the sane ADSP base data */
+	if (!base)
+		return -EINVAL;
+
+	handle = xf_adsp_base_get_handle(handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	/* submit message to port 0 of component */
+	/* PRQA S 3200 2 */
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_EMPTY_THIS_BUFFER, length, buffer, NULL);
+
+	xf_send(&msg);		/* PRQA S 3200 */
+
+	return 0;
+}
+
+/** ***********************************************************
+ *\brief  send fill this buffer command to ADSP framework
+ *
+ *\param[in]	handle_id	ID of the registered handle
+ *\param[in]	buffer		Pointer to data buffer
+ *\param[in]	length		Size of buffer in bytes
+ *\retval	0		Success
+ *\retval	-EINVAL		Failed
+ **************************************************************/
+int xf_adsp_fill_this_buffer(int handle_id, char *buffer, int length)
+{
+	struct xf_message msg;
+	struct xf_handle *handle;
+
+	/* check the sane ADSP base data */
+	if (!base)
+		return -EINVAL;
+
+	handle = xf_adsp_base_get_handle(handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	/* submit message to port 1 of component */
+	/* PRQA S 3200 2 */
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 1)),
+		      XF_FILL_THIS_BUFFER, length, buffer, NULL);
+
+	xf_send(&msg);		/* PRQA S 3200 */
+
+	return 0;
+}
+
+/** ***********************************************************
+ *\brief route data between two registered ADSP plugins
+ *
+ *\param[in]	src_handle_id	Handle ID of source plugin
+ *\param[in]	dst_handle_id	Handle ID of sink plugin
+ *\param[in]	buf_cnt		Number of buffer in tunnel
+ *\param[in]	buf_size	Size of each buffer in tunnel
+ *\retval	0		Success
+ *\retval	-EINVAL		Failed
+ **************************************************************/
+int
+xf_adsp_route(int src_handle_id, int dst_handle_id, int buf_cnt, int buf_size)
+{
+	struct xf_route_port_msg *route_msg;
+	struct xf_message msg;
+	struct xf_buffer *b;
+	struct xf_handle *dst_handle, *src_handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base)
+		return -EINVAL;
+
+	/* get handle data */
+	dst_handle = xf_adsp_base_get_handle(dst_handle_id);
+	src_handle = xf_adsp_base_get_handle(src_handle_id);
+
+	if (!dst_handle || !src_handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+	route_msg = xf_buffer_data(b);
+
+	/* route information */
+	route_msg->dst = __XF_PORT_SPEC2(dst_handle->comp_id, 0);
+	route_msg->alloc_align = 4;
+	route_msg->alloc_number = buf_cnt;
+	route_msg->alloc_size = buf_size;
+
+	/* PRQA S 3200 2*/
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, src_handle_id),
+				  __XF_PORT_SPEC2(src_handle->comp_id, 1)),
+		      XF_ROUTE, sizeof(*route_msg), route_msg, NULL);
+
+	err = xf_send_and_receive(&msg);
+
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief set a single parameter
+ *
+ *\param[in]	handle_id	ID of registered handle
+ *\param[in]	index		Sub-command index of parameter
+ *\param[in]	value		the setting value
+ *\retval	0		Success
+ *\retval	-EINVAL		Failed
+ **************************************************************/
+int xf_adsp_set_param(int handle_id, int index, int value)
+{
+	struct xf_message msg;
+	struct xf_buffer *b;
+	struct xf_set_param_msg *msg_params;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base)
+		return -EINVAL;
+
+	handle = xf_adsp_base_get_handle(handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+	msg_params = xf_buffer_data(b);
+
+	msg_params->item[0].id = index;
+	msg_params->item[0].value = value;
+
+	/* PRQA S 3200 2 */
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_SET_PARAM, XF_SET_PARAM_CMD_LEN(1), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief get a single parameter
+ *
+ *\param[in]	handle_id	ID of registered handle
+ *\param[in]	index		Sub-command index of parameter
+ *\param[out]	value		Store the getting value
+ *\retval	0		Success
+ *\retval	-EINVAL		Failed
+ **************************************************************/
+int xf_adsp_get_param(int handle_id, int index, int *value)
+{
+	struct xf_message msg;
+	struct xf_buffer *b;
+	union xf_get_param_msg *msg_params;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base and value data */
+	if (!base || !value)
+		return -EINVAL;
+
+	handle = xf_adsp_base_get_handle(handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+	msg_params = xf_buffer_data(b);
+
+	msg_params->c.id[0] = index;
+
+	/* PRQA S 3200 2 */
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_GET_PARAM, XF_GET_PARAM_CMD_LEN(1), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+	if (err != 0)
+		goto exit;		/* PRQA S 2001 */
+
+	/* save the received parameters */
+	*value = msg_params->r.value[0];
+
+exit:
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/***************************************************
+ * APIs for ADSP base control
+ * ************************************************/
+
+/** ***********************************************************
+ *\brief initialize ADSP base's instance
+ *
+ *\retval 0	  Success
+ *\retval -EINVAL ADSP base's instance has been initialized
+ *\retval -ENOMEM Cannot allocate memory for ADSP base
+ *\retval -EBUSY  Cannot register client to proxy
+ **************************************************************/
+int xf_adsp_base_create(struct xf_adsp_base_cmd *cmd)
+{
+	int err = 0;
+
+	if (base != 0)
+		return -EINVAL;
+
+	if (!cmd || !cmd->recv || !cmd->send || !cmd->poll ||
+	    !cmd->client_register || !cmd->client_unregister)
+		return -EINVAL;
+
+	base = kmalloc(sizeof(*base), GFP_KERNEL);
+	if (!base)
+		return -ENOMEM;
+
+	memset(base, 0, sizeof(struct xf_adsp_base));	/* PRQA S 3200 */
+
+	/* store the proxy command */
+	memcpy(&base->cmd, cmd, sizeof(struct xf_adsp_base_cmd));
+
+	/* create client to connect from proxy driver */
+	err = base->cmd.client_register(&base->client);
+	if (err != 0)
+		goto err3;		/* PRQA S 2001 */
+
+	/* initialize waiting queue */
+	init_waitqueue_head(&base->base_wait);
+
+	/* initialize handle */
+	xf_adsp_base_init_handle();
+
+	/* create thread to get the responsed message from proxy */
+	base->rsp_thread = kthread_run(&xf_response_thread,
+				       (void *)base, "adsp base");
+
+	if (base->rsp_thread != 0) {
+		pr_info("ADSP base thread has been started.\n");
+	} else {
+		pr_info("Failed in create base thread\n");
+		err = -ENOMEM;
+		goto err2;		/* PRQA S 2001 */
+	}
+
+	/* allocate auxiliary pool for component usage */
+	base->aux_pool = xf_adsp_allocate_mem_pool(
+					XF_AUX_POOL_SIZE,
+					XF_ALIGNED(XF_AUX_POOL_MSG_LENGTH));
+
+	if (IS_ERR(base->aux_pool)) {		/* PRQA S 306 */
+		err = -ENOMEM;
+		goto err1;		/* PRQA S 2001 */
+	}
+
+	pr_info("ADSP base was created\n");
+	return 0;
+
+err1:
+	/* cancel the waitting queue */
+	spin_lock(&base->lock);
+	base->wait_flag = TRUE;
+	spin_unlock(&base->lock);
+
+	/* stop thread inadvance */
+	kthread_stop(base->rsp_thread);
+
+err2:
+	base->cmd.client_unregister(base->client);
+
+err3:
+	kfree(base);
+	base = NULL;
+
+	return err;
+}
+EXPORT_SYMBOL(xf_adsp_base_create);		/* PRQA S 0651 */
+
+/** ***********************************************************
+ *\brief deinitialize ADSP base's instance
+ *
+ *\retval	 0	   Success
+ *\retval	 -EINVAL Invalid ADSP base's instance
+ **************************************************************/
+int xf_adsp_base_destroy(void)
+{
+	/* check the sane ADSP base data */
+	if (!base)
+		return -EINVAL;
+
+	/* free auxiliary pool to shared memory */
+	xf_adsp_free_mem_pool(base->aux_pool);		/* PRQA S 3200 */
+
+	/* cancel wait the response message, go to stop process */
+	spin_lock(&base->lock);
+	base->wait_flag = TRUE;
+	spin_unlock(&base->lock);
+
+	/* stop response thread */
+	kthread_stop(base->rsp_thread);
+
+	/* unregister client */
+	base->cmd.client_unregister(base->client);
+
+	kfree(base);
+	base = NULL;
+
+	pr_info("ADSP base was destroyed\n");
+	return 0;
+}
+EXPORT_SYMBOL(xf_adsp_base_destroy);		/* PRQA S 0651 */
+
+/** ***********************************************************
+ *	\brief initialize handle instance
+ **************************************************************/
+static inline void xf_adsp_base_init_handle(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_HANDLE; i++)
+		base->handle[i] = NULL;
+}
+
+/** ***********************************************************
+ *\brief get the next available handle ID for register
+ *
+ *\retval -1		Unavailable handle ID
+ *\retval 0 to 255	Available handle ID
+ **************************************************************/
+static inline int xf_adsp_base_get_valid_handle(void)
+{
+	int id = -1;
+	int i;
+
+	for (i = 0; i < MAX_HANDLE; i++) {
+		/* get the id of the first available handler */
+		if (!base->handle[i]) {
+			id = i;
+			break;
+		}
+	}
+
+	return id;
+}
+
+/** ***********************************************************
+ *\brief register a handle instance for component usage
+ *
+ *\param[in]	 private_data	Private data of this component
+ *\param[in]	 cb		Callback function
+ *\param[in]	 comp_id	ID of register component
+ *\retval	 id		ID of registered handle
+ *\retval	 -EINVAL	Cannot get the handle instance
+ *\retval	 -ENOMEM	Cannot allocate handle memory
+ **************************************************************/
+static int xf_adsp_base_register_handle(void *private_data,
+					struct xf_callback_func *cb,
+					int comp_id)
+{
+	struct xf_handle *handle;
+	int id;
+
+	/* get the next handle id */
+	id = xf_adsp_base_get_valid_handle();
+
+	/* check available handle in base */
+	if (id < 0)
+		return -EINVAL;
+
+	/* allocate handle data */
+	handle = kmalloc(sizeof(*handle), GFP_KERNEL);
+	if (!handle)
+		return -ENOMEM;
+
+	/* save handle data */
+	handle->private_data = private_data;
+	handle->cb = cb;
+	handle->comp_id = comp_id;
+
+	/* save the hanle data */
+	base->handle[id] = handle;
+
+	/* return the id numbering in base handle */
+	return (id + 1);
+}
+
+/** ***********************************************************
+ *\brief  get handle instance from handle ID
+ *
+ *\param[in]	 handle_id	ID of registered handle
+ *\retval	 handle		Pointer to handle instance
+ **************************************************************/
+static inline struct xf_handle *xf_adsp_base_get_handle(int handle_id)
+{
+	return base->handle[handle_id - 1];
+}
+
+/** ***********************************************************
+ *\brief free the registered handle instance
+ *
+ *\param[in]	handle_id	ID of registered handle
+ *\retval	0		Success
+ *\retval	-EINVAL		Invalid handle ID
+ **************************************************************/
+static int xf_adsp_base_free_handle(int handle_id)
+{
+	if (handle_id < 1 || handle_id > MAX_HANDLE)
+		return -EINVAL;
+
+	kfree(base->handle[handle_id - 1]);
+	base->handle[handle_id - 1] = NULL;
+
+	return 0;
+}
+
+/***********************************************************************
+ * APIs for Renderer component
+ * ********************************************************************/
+
+/** ***********************************************************
+ *\brief  set ADSP Renderer parameters
+ *
+ *\param[in]	renderer	Pointer to Renderer component
+ *\retval	0		Success
+ *\retval	-EINVAL		Failed
+ **************************************************************/
+int xf_adsp_renderer_set_params(struct xf_adsp_renderer *renderer)
+{
+	struct xf_message msg;
+	struct xf_set_param_msg *msg_params;
+	struct xf_adsp_renderer_params *params;
+	struct xf_buffer *b;
+	int i;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base || !renderer)
+		return -EINVAL;
+
+	params = &renderer->params;
+
+	/* get Renderer's handle data */
+	handle = xf_adsp_base_get_handle(renderer->handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+
+	msg_params = xf_buffer_data(b);
+
+	i = 0;
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_SAMPLE_RATE;
+	msg_params->item[i++].value = params->in_rate;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_CHANNELS;
+	msg_params->item[i++].value = params->channel;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_PCM_WIDTH;
+	msg_params->item[i++].value = params->pcm_width;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_FRAME_SIZE;
+	msg_params->item[i++].value = params->frame_size;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_OUTPUT1;
+	msg_params->item[i++].value = params->dev1;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_OUTPUT2;
+	msg_params->item[i++].value = params->dev2;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_DMACHANNEL1;
+	msg_params->item[i++].value = params->dma1;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_DMACHANNEL2;
+	msg_params->item[i++].value = params->dma2;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+	msg_params->item[i++].value = params->out_rate;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_VOLUME_RATE;
+	msg_params->item[i++].value = params->vol_rate;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_OUT_CHANNELS;
+	msg_params->item[i++].value = params->out_channel;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_MIX_CONTROL;
+	msg_params->item[i++].value = params->mix_ctrl;
+
+	msg_params->item[i].id = XA_RDR_CONFIG_PARAM_STATE;
+	msg_params->item[i++].value = params->state;
+
+	/* PRQA S 3200 2*/
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, renderer->handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_SET_PARAM, XF_SET_PARAM_CMD_LEN(i), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief  get ADSP Renderer parameters
+ *
+ *\param[in]	renderer	Pointer to Renderer component
+ *\retval	0		Success
+ *\retval	-EINVAL		Failed
+ **************************************************************/
+/* PRQA S 1505 */
+int xf_adsp_renderer_get_params(struct xf_adsp_renderer *renderer)
+{
+	struct xf_adsp_renderer_params *rdr_params;
+	struct xf_message msg;
+	struct xf_buffer *b;
+	union xf_get_param_msg *msg_params;
+	int i;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base || !renderer)
+		return -EINVAL;
+
+	rdr_params = &renderer->params;
+
+	/* get Renderer's handle data */
+	handle = xf_adsp_base_get_handle(renderer->handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+	msg_params = xf_buffer_data(b);
+
+	i = 0;
+	/* PRQA S 3440 13 1*/
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_SAMPLE_RATE;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_CHANNELS;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_PCM_WIDTH;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_FRAME_SIZE;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_OUTPUT1;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_OUTPUT2;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_DMACHANNEL1;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_DMACHANNEL2;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_VOLUME_RATE;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_OUT_CHANNELS;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_MIX_CONTROL;
+	msg_params->c.id[i++] = XA_RDR_CONFIG_PARAM_STATE;
+
+	/* PRQA S 3200 2*/
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, renderer->handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_GET_PARAM, XF_GET_PARAM_CMD_LEN(i), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+	if (err != 0)
+		goto exit;		/* PRQA S 2001 */
+
+	/* save the received parameters */
+	i = 0;
+	rdr_params->in_rate = msg_params->r.value[i++];	/* PRQA S 3440 13 */
+	rdr_params->channel = msg_params->r.value[i++];
+	rdr_params->pcm_width = msg_params->r.value[i++];
+	rdr_params->frame_size = msg_params->r.value[i++];
+	rdr_params->dev1 = msg_params->r.value[i++];
+	rdr_params->dev2 = msg_params->r.value[i++];
+	rdr_params->dma1 = msg_params->r.value[i++];
+	rdr_params->dma2 = msg_params->r.value[i++];
+	rdr_params->out_rate = msg_params->r.value[i++];
+	rdr_params->vol_rate = msg_params->r.value[i++];
+	rdr_params->out_channel = msg_params->r.value[i++];
+	rdr_params->mix_ctrl = msg_params->r.value[i++];
+	rdr_params->state = msg_params->r.value[i++];
+
+exit:
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** **************************************************************************
+ *\brief  create Renderer component
+ *
+ *\param[in,out]  renderer	Pointer to the registered component
+ *\param[in]	  cb		Callback function
+ *\param[in]	  private_data	Private data
+ *\retval	  0		Success
+ *\retval	 -EINVAL	Invalid base instance or register fail
+ *\retval	 -ENOMEM	Cannot allocate Renderer instance
+ *****************************************************************************/
+int xf_adsp_renderer_create(struct xf_adsp_renderer **renderer,
+			    struct xf_callback_func *cb, void *private_data)
+{
+	struct xf_adsp_renderer *rdr;
+	int err;
+	int comp_id;
+
+	/* check the sane ADSP base data */
+	if (!base)
+		return -EINVAL;
+
+	rdr = kmalloc(sizeof(*rdr), GFP_KERNEL);
+	if (!rdr)
+		return -ENOMEM;
+
+	memset(rdr, 0, sizeof(struct xf_adsp_renderer)); /* PRQA S 3200 */
+
+	/* register renderer component */
+	err = xf_adsp_register("renderer", &comp_id);
+	if (err != 0)
+		goto err2;		/* PRQA S 2001 */
+
+	/* register Renderer to ADSP base control */
+	rdr->handle_id = xf_adsp_base_register_handle(private_data,
+						      cb, comp_id);
+
+	if (rdr->handle_id <= 0) {
+		err = -EINVAL;
+		goto err1;		/* PRQA S 2001 */
+	}
+
+	/* get the default parameter from Renderer plugin */
+	err = xf_adsp_renderer_get_params(rdr);
+	if (err != 0)
+		goto err1;		/* PRQA S 2001 */
+
+	/* save renderer compoent data */
+	*renderer = rdr;
+
+	return 0;
+
+err1:
+	xf_adsp_unregister(comp_id);		/* PRQA S 3200 */
+
+err2:
+	kfree(rdr);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief  deinitialize ADSP Renderer component
+ *
+ *\param[in]	 renderer	Pointer to Renderer component
+ *\retval	 0		Success
+ *\retval	 -EINVAL	Invalid base or Renderer data
+ **************************************************************/
+/* PRQA S 3673 */
+int xf_adsp_renderer_destroy(struct xf_adsp_renderer *renderer)
+{
+	struct xf_handle *handle;
+	int handle_id;
+
+	/* check the sane ADSP base data */
+	if (!base || !renderer)
+		return -EINVAL;
+
+	handle_id = renderer->handle_id;
+
+	handle = xf_adsp_base_get_handle(handle_id);
+	if (!handle)
+		goto exit;		/* PRQA S 2001 */
+
+	/* unregister component */
+	xf_adsp_unregister(handle->comp_id);		/* PRQA S 3200 */
+
+	/* free handle data from base control */
+	xf_adsp_base_free_handle(handle_id);		/* PRQA S 3200 */
+
+exit:
+	kfree(renderer);
+
+	return 0;
+}
+
+/***********************************************************************
+ * APIs for Capture component
+ * ********************************************************************/
+
+/** ***********************************************************
+ *\brief  set ADSP Capture parameters
+ *
+ *\param[in]	 capture	 Pointer to Capture component
+ *\retval	 0		 Success
+ *\retval	 -EINVAL	 Failed
+ **************************************************************/
+int xf_adsp_capture_set_params(struct xf_adsp_capture *capture)
+{
+	struct xf_message msg;
+	struct xf_set_param_msg *msg_params;
+	struct xf_adsp_capture_params *params;
+	struct xf_buffer *b;
+	int i;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base || !capture)
+		return -EINVAL;
+
+	params = &capture->params;
+
+	/* get Capture's handle data */
+	handle = xf_adsp_base_get_handle(capture->handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+
+	msg_params = xf_buffer_data(b);
+
+	i = 0;
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_SAMPLE_RATE;
+	msg_params->item[i++].value = params->in_rate;
+
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_CHANNELS;
+	msg_params->item[i++].value = params->channel;
+
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_PCM_WIDTH;
+	msg_params->item[i++].value = params->pcm_width;
+
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_FRAME_SIZE;
+	msg_params->item[i++].value = params->frame_size;
+
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_INPUT1;
+	msg_params->item[i++].value = params->dev1;
+
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_INPUT2;
+	msg_params->item[i++].value = params->dev2;
+
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_DMACHANNEL1;
+	msg_params->item[i++].value = params->dma1;
+
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_DMACHANNEL2;
+	msg_params->item[i++].value = params->dma2;
+
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_OUT_SAMPLE_RATE;
+	msg_params->item[i++].value = params->out_rate;
+
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_VOLUME_RATE;
+	msg_params->item[i++].value = params->vol_rate;
+
+	msg_params->item[i].id = XA_CAP_CONFIG_PARAM_STATE;
+	msg_params->item[i++].value = params->state;
+
+	/* PRQA S 3200 2 */
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, capture->handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_SET_PARAM, XF_SET_PARAM_CMD_LEN(i), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief  get ADSP Capture parameters
+ *
+ *\param[in]	 capture	 Pointer to Capture component
+ *\retval	 0		 Success
+ *\retval	 -EINVAL	 Failed
+ **************************************************************/
+/* PRQA S 1505 */
+int xf_adsp_capture_get_params(struct xf_adsp_capture *capture)
+{
+	struct xf_adsp_capture_params *cap_params;
+	struct xf_message msg;
+	struct xf_buffer *b;
+	union xf_get_param_msg *msg_params;
+	int i;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base || !capture)
+		return -EINVAL;
+
+	cap_params = &capture->params;
+
+	/* get Capture's handle data */
+	handle = xf_adsp_base_get_handle(capture->handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+	msg_params = xf_buffer_data(b);
+
+	i = 0;
+	/* PRQA S 3440 11 1*/
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_SAMPLE_RATE;
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_CHANNELS;
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_PCM_WIDTH;
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_FRAME_SIZE;
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_INPUT1;
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_INPUT2;
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_DMACHANNEL1;
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_DMACHANNEL2;
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_OUT_SAMPLE_RATE;
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_VOLUME_RATE;
+	msg_params->c.id[i++] = XA_CAP_CONFIG_PARAM_STATE;
+
+	/* PRQA S 3200 2 */
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, capture->handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_GET_PARAM, XF_GET_PARAM_CMD_LEN(i), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+	if (err != 0)
+		goto exit;		/* PRQA S 2001 */
+
+	/* save the received parameters */
+	i = 0;
+	cap_params->in_rate = msg_params->r.value[i++];	/* PRQA S 3440 11 */
+	cap_params->channel = msg_params->r.value[i++];
+	cap_params->pcm_width = msg_params->r.value[i++];
+	cap_params->frame_size = msg_params->r.value[i++];
+	cap_params->dev1 = msg_params->r.value[i++];
+	cap_params->dev2 = msg_params->r.value[i++];
+	cap_params->dma1 = msg_params->r.value[i++];
+	cap_params->dma2 = msg_params->r.value[i++];
+	cap_params->out_rate = msg_params->r.value[i++];
+	cap_params->vol_rate = msg_params->r.value[i++];
+	cap_params->state = msg_params->r.value[i++];
+
+exit:
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** **************************************************************************
+ *\brief  create Capture component
+ *
+ *\param[in,out]  capture	 Pointer to the registered component
+ *\param[in]	  cb		 Callback function
+ *\param[in]	  private_data	 Private data
+ *\retval	  0		 Success
+ *\retval	  -EINVAL	 Invalid base instance or register fail
+ *\retval	  -ENOMEM	 Cannot allocate Capture instance
+ *****************************************************************************/
+int xf_adsp_capture_create(struct xf_adsp_capture **capture,
+			   struct xf_callback_func *cb, void *private_data)
+{
+	struct xf_adsp_capture *cap;
+	int err;
+	int comp_id;
+
+	/* check the sane ADSP base data */
+	if (!base)
+		return -EINVAL;
+
+	cap = kmalloc(sizeof(*cap), GFP_KERNEL);
+	if (!cap)
+		return -ENOMEM;
+
+	memset(cap, 0, sizeof(struct xf_adsp_capture));	/* PRQA S 3200 */
+
+	/* register capture component */
+	err = xf_adsp_register("capture", &comp_id);
+	if (err != 0)
+		goto err2;		/* PRQA S 2001 */
+
+	/* register capture to ADSP base control */
+	cap->handle_id = xf_adsp_base_register_handle(private_data,
+						      cb, comp_id);
+
+	if (cap->handle_id <= 0) {
+		err = -EINVAL;
+		goto err1;		/* PRQA S 2001 */
+	}
+
+	/* get the default parameter from capture plugin */
+	err = xf_adsp_capture_get_params(cap);
+	if (err != 0)
+		goto err1;		/* PRQA S 2001 */
+
+	/* save capture compoent data */
+	*capture = cap;
+
+	return 0;
+
+err1:
+	xf_adsp_unregister(comp_id);	/* PRQA S 3200 */
+
+err2:
+	kfree(cap);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief  deinitialize ADSP Capture component
+ *
+ *\param[in]	 capture	 Pointer to Capture component
+ *\retval	 0		 Success
+ *\retval	 -EINVAL	 Invalid base or Capture data
+ **************************************************************/
+int xf_adsp_capture_destroy(struct xf_adsp_capture *capture) /* PRQA S 3673 */
+{
+	struct xf_handle *handle;
+	int handle_id;
+
+	/* check the sane ADSP base data */
+	if (!base || !capture)
+		return -EINVAL;
+
+	handle_id = capture->handle_id;
+
+	handle = xf_adsp_base_get_handle(handle_id);
+	if (!handle)
+		goto exit;		/* PRQA S 2001 */
+
+	/* unregister component */
+	xf_adsp_unregister(handle->comp_id);	/* PRQA S 3200 */
+
+	/* free handle data from base control */
+	xf_adsp_base_free_handle(handle_id);	/* PRQA S 3200 */
+
+exit:
+	kfree(capture);
+
+	return 0;
+}
+
+/***********************************************************************
+ * APIs for Equalizer component
+ * ********************************************************************/
+
+/** ***********************************************************
+ *\brief  set ADSP Equalizer parameters
+ *
+ *\param[in]	 equalizer	 Pointer to Equalizer component
+ *\retval	 0		 Success
+ *\retval	 -EINVAL	 Failed
+ **************************************************************/
+int xf_adsp_equalizer_set_params(struct xf_adsp_equalizer *equalizer)
+{
+	struct xf_message msg;
+	struct xf_set_param_msg *msg_params;
+	struct xf_adsp_equalizer_params    *params;
+	struct xf_buffer    *b;
+	int i, n;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base || !equalizer)
+		return -EINVAL;
+
+	params = &equalizer->params;
+
+	/* get Equalizer's handle data */
+	handle = xf_adsp_base_get_handle(equalizer->handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+
+	msg_params = xf_buffer_data(b);
+
+	i = 0;
+	msg_params->item[i].id = XA_EQZ_CONFIG_PARAM_COEF_FS;
+	msg_params->item[i++].value = params->rate;
+
+	msg_params->item[i].id = XA_EQZ_CONFIG_PARAM_CH;
+	msg_params->item[i++].value = params->channel;
+
+	msg_params->item[i].id = XA_EQZ_CONFIG_PARAM_PCM_WIDTH;
+	msg_params->item[i++].value = params->pcm_width;
+
+	msg_params->item[i].id = XA_EQZ_CONFIG_PARAM_EQZ_TYPE;
+	msg_params->item[i++].value = params->eqz_type;
+
+	if (params->eqz_type == XA_REL_EQZ_TYPE_PARAMETRIC) {
+		struct xf_equalizer_parametric_coef *coef = &params->p_coef;
+
+		for (n = 0; n < XA_REL_EQZ_FILTER_NUM; n++) {
+			msg_params->item[i].id =
+				XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_TYPE + n;
+			msg_params->item[i++].value = coef->type[n];
+
+			msg_params->item[i].id =
+				XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_FC + n;
+			msg_params->item[i++].value = coef->fc[n];
+
+			msg_params->item[i].id =
+				XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_BW + n;
+			msg_params->item[i++].value = coef->band_width[n];
+
+			msg_params->item[i].id =
+				XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_GA + n;
+			msg_params->item[i++].value = coef->gain[n];
+
+			msg_params->item[i].id =
+				XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_BA + n;
+			msg_params->item[i++].value = coef->gain_base[n];
+		}
+	} else {
+		struct xf_equalizer_graphic_coef *coef = &params->g_coef;
+
+		for (n = 0; n < XA_REL_EQZ_GRAPHIC_BAND_NUM; n++) {
+			msg_params->item[i].id =
+				XA_EQZ_CONFIG_PARAM_BAND_0_GCOEF_GA + n;
+			msg_params->item[i++].value = coef->gain_g[n];
+		}
+	}
+
+	/* PRQA S 3200 2 */
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, equalizer->handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_SET_PARAM, XF_SET_PARAM_CMD_LEN(i), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief  get ADSP Equalizer parameters
+ *
+ *\param[in]	 equalizer	 Pointer to Equalizer component
+ *\retval	 0		 Success
+ *\retval	 -EINVAL	 Failed
+ **************************************************************/
+/* PRQA S 1505 1*/
+int xf_adsp_equalizer_get_params(struct xf_adsp_equalizer *equalizer)
+{
+	struct xf_adsp_equalizer_params *eqz_params;
+	struct xf_message msg;
+	struct xf_buffer *b;
+	union xf_get_param_msg *msg_params;
+	int i, n;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base || !equalizer)
+		return -EINVAL;
+
+	eqz_params = &equalizer->params;
+
+	/* get Equalizer's handle data */
+	handle = xf_adsp_base_get_handle(equalizer->handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+	msg_params = xf_buffer_data(b);
+
+	i = 0;
+	msg_params->c.id[i++] = XA_EQZ_CONFIG_PARAM_COEF_FS; /* PRQA S 3440 4 */
+	msg_params->c.id[i++] = XA_EQZ_CONFIG_PARAM_CH;
+	msg_params->c.id[i++] = XA_EQZ_CONFIG_PARAM_PCM_WIDTH;
+	msg_params->c.id[i++] = XA_EQZ_CONFIG_PARAM_EQZ_TYPE;
+
+	for (n = 0; n < XA_REL_EQZ_FILTER_NUM; n++) {
+		/* PRQA S 3440 5 */
+		msg_params->c.id[i++] =
+			XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_TYPE + n;
+
+		msg_params->c.id[i++] =
+			XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_FC + n;
+
+		msg_params->c.id[i++] =
+			XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_BW + n;
+
+		msg_params->c.id[i++] =
+			XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_GA + n;
+
+		msg_params->c.id[i++] =
+			XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_BA + n;
+	}
+
+	for (n = 0; n < XA_REL_EQZ_GRAPHIC_BAND_NUM; n++)
+		/* PRQA S 3440 1 */
+		msg_params->c.id[i++] = XA_EQZ_CONFIG_PARAM_BAND_0_GCOEF_GA + n;
+
+	/* PRQA S 3200 2 */
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, equalizer->handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_GET_PARAM, XF_GET_PARAM_CMD_LEN(i), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+	if (err != 0)
+		goto exit;		/* PRQA S 2001 */
+
+	/* save the received parameters */
+	i = 0;
+	eqz_params->rate = msg_params->r.value[i++];	/* PRQA S 3440 4 */
+	eqz_params->channel = msg_params->r.value[i++];
+	eqz_params->pcm_width = msg_params->r.value[i++];
+	eqz_params->eqz_type = msg_params->r.value[i++];
+
+	for (n = 0; n < XA_REL_EQZ_FILTER_NUM; n++) {
+		/* PRQA S 3440 5 */
+		eqz_params->p_coef.type[n] = msg_params->r.value[i++];
+		eqz_params->p_coef.fc[n] = msg_params->r.value[i++];
+		eqz_params->p_coef.band_width[n] = msg_params->r.value[i++];
+		eqz_params->p_coef.gain[n] = msg_params->r.value[i++];
+		eqz_params->p_coef.gain_base[n] = msg_params->r.value[i++];
+	}
+
+	for (n = 0; n < XA_REL_EQZ_GRAPHIC_BAND_NUM; n++) {
+		/* PRQA S 3440 1 */
+		eqz_params->g_coef.gain_g[n] = msg_params->r.value[i++];
+	}
+
+exit:
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** **************************************************************************
+ *\brief  create Equalizer component
+ *
+ *\param[in,out]  equalizer	 Pointer to the registered component
+ *\param[in]	  cb		 Callback function
+ *\param[in]	  private_data	 Private data
+ *\retval	  0		 Success
+ *\retval	  -EINVAL	 Invalid base instance or register fail
+ *\retval	  -ENOMEM	 Cannot allocate Equalier instance
+ *****************************************************************************/
+int xf_adsp_equalizer_create(struct xf_adsp_equalizer **equalizer,
+			     struct xf_callback_func *cb, void *private_data)
+{
+	struct xf_adsp_equalizer *eqz;
+	int err;
+	int comp_id;
+
+	/* check the sane ADSP base data */
+	if (!base)
+		return -EINVAL;
+
+	eqz = kmalloc(sizeof(*eqz), GFP_KERNEL);
+	if (!eqz)
+		return -ENOMEM;
+
+	memset(eqz, 0, sizeof(struct xf_adsp_equalizer)); /* PRQA S 3200 */
+
+	/* register equalizer component */
+	err = xf_adsp_register("equalizer", &comp_id);
+	if (err != 0)
+		goto err2;			/* PRQA S 2001 */
+
+	/* register equalizer to ADSP base control */
+	eqz->handle_id = xf_adsp_base_register_handle(private_data,
+						      cb, comp_id);
+
+	if (eqz->handle_id <= 0) {
+		err = -EINVAL;
+		goto err1;			/* PRQA S 2001 */
+	}
+
+	/* get the default parameter from equalizer plugin */
+	err = xf_adsp_equalizer_get_params(eqz);
+	if (err != 0)
+		goto err1;			/* PRQA S 2001 */
+
+	/* save equalizer compoent data */
+	*equalizer = eqz;
+
+	return 0;
+
+err1:
+	xf_adsp_unregister(comp_id);		/* PRQA S 3200 */
+
+err2:
+	kfree(eqz);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief  deinitialize ADSP Equalizer component
+ *
+ *\param[in]	 equalizer	 Pointer to Equalizer component
+ *\retval	 0		 Success
+ *\retval	 -EINVAL	 Invalid base or Equalizer data
+ **************************************************************/
+/* PRQA S 3673 */
+int xf_adsp_equalizer_destroy(struct xf_adsp_equalizer *equalizer)
+{
+	struct xf_handle *handle;
+	int handle_id;
+
+	/* check the sane ADSP base and Equalizer data */
+	if (!base || !equalizer)
+		return -EINVAL;
+
+	handle_id = equalizer->handle_id;
+
+	handle = xf_adsp_base_get_handle(handle_id);
+	if (!handle)
+		goto exit;		/* PRQA S 2001 */
+
+	/* unregister component */
+	xf_adsp_unregister(handle->comp_id);	/* PRQA S 3200 */
+
+	/* free handle data from base control */
+	xf_adsp_base_free_handle(handle_id);	/* PRQA S 3200 */
+
+exit:
+	kfree(equalizer);
+
+	return 0;
+}
+
+/***********************************************************************
+ * APIs for TDM Renderer component
+ * ********************************************************************/
+
+/** ***********************************************************
+ *\brief  set ADSP TDM Renderer parameters
+ *
+ *\param[in]	 tdm_renderer	Pointer to TDM Renderer component
+ *\retval	 0		Success
+ *\retval	 -EINVAL	Failed
+ **************************************************************/
+int xf_adsp_tdm_renderer_set_params(struct xf_adsp_tdm_renderer *tdm_renderer)
+{
+	struct xf_message msg;
+	struct xf_set_param_msg *msg_params;
+	struct xf_adsp_tdm_renderer_params *params;
+	struct xf_buffer *b;
+	int i;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base || !tdm_renderer)
+		return -EINVAL;
+
+	params = &tdm_renderer->params;
+
+	/* get TDM Renderer's handle data */
+	handle = xf_adsp_base_get_handle(tdm_renderer->handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+
+	msg_params = xf_buffer_data(b);
+
+	i = 0;
+	msg_params->item[i].id = XA_TDM_RDR_CONFIG_PARAM_IN_SAMPLE_RATE;
+	msg_params->item[i++].value = params->in_rate;
+
+	msg_params->item[i].id = XA_TDM_RDR_CONFIG_PARAM_CHANNEL_MODE;
+	msg_params->item[i++].value = params->ch_mode;
+
+	msg_params->item[i].id = XA_TDM_RDR_CONFIG_PARAM_PCM_WIDTH;
+	msg_params->item[i++].value = params->pcm_width;
+
+	msg_params->item[i].id = XA_TDM_RDR_CONFIG_PARAM_FRAME_SIZE;
+	msg_params->item[i++].value = params->frame_size;
+
+	msg_params->item[i].id = XA_TDM_RDR_CONFIG_PARAM_OUTPUT1;
+	msg_params->item[i++].value = params->dev1;
+
+	msg_params->item[i].id = XA_TDM_RDR_CONFIG_PARAM_OUTPUT2;
+	msg_params->item[i++].value = params->dev2;
+
+	msg_params->item[i].id = XA_TDM_RDR_CONFIG_PARAM_DMACHANNEL1;
+	msg_params->item[i++].value = params->dma1;
+
+	msg_params->item[i].id = XA_TDM_RDR_CONFIG_PARAM_DMACHANNEL2;
+	msg_params->item[i++].value = params->dma2;
+
+	msg_params->item[i].id = XA_TDM_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+	msg_params->item[i++].value = params->out_rate;
+
+	msg_params->item[i].id = XA_TDM_RDR_CONFIG_PARAM_VOLUME_RATE;
+	msg_params->item[i++].value = params->vol_rate;
+
+	/* PRQA S 3200 2*/
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, tdm_renderer->handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_SET_PARAM, XF_SET_PARAM_CMD_LEN(i), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief  get ADSP TDM Renderer parameters
+ *
+ *\param[in]	 tdm_renderer	Pointer to TDM Renderer component
+ *\retval	 0		Success
+ *\retval	 -EINVAL	Failed
+ **************************************************************/
+/* PRQA S 1505 1*/
+int xf_adsp_tdm_renderer_get_params(struct xf_adsp_tdm_renderer *tdm_renderer)
+{
+	struct xf_adsp_tdm_renderer_params *params;
+	struct xf_message msg;
+	struct xf_buffer *b;
+	union xf_get_param_msg *msg_params;
+	int i;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base || !tdm_renderer)
+		return -EINVAL;
+
+	params = &tdm_renderer->params;
+
+	/* get TDM Renderer's handle data */
+	handle = xf_adsp_base_get_handle(tdm_renderer->handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+	msg_params = xf_buffer_data(b);
+
+	i = 0;
+	/* PRQA S 3440 13 1*/
+	msg_params->c.id[i++] = XA_TDM_RDR_CONFIG_PARAM_IN_SAMPLE_RATE;
+	msg_params->c.id[i++] = XA_TDM_RDR_CONFIG_PARAM_CHANNEL_MODE;
+	msg_params->c.id[i++] = XA_TDM_RDR_CONFIG_PARAM_PCM_WIDTH;
+	msg_params->c.id[i++] = XA_TDM_RDR_CONFIG_PARAM_FRAME_SIZE;
+	msg_params->c.id[i++] = XA_TDM_RDR_CONFIG_PARAM_OUTPUT1;
+	msg_params->c.id[i++] = XA_TDM_RDR_CONFIG_PARAM_OUTPUT2;
+	msg_params->c.id[i++] = XA_TDM_RDR_CONFIG_PARAM_DMACHANNEL1;
+	msg_params->c.id[i++] = XA_TDM_RDR_CONFIG_PARAM_DMACHANNEL2;
+	msg_params->c.id[i++] = XA_TDM_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE;
+	msg_params->c.id[i++] = XA_TDM_RDR_CONFIG_PARAM_VOLUME_RATE;
+
+	/* PRQA S 3200 2*/
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, tdm_renderer->handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_GET_PARAM, XF_GET_PARAM_CMD_LEN(i), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+	if (err != 0)
+		goto exit;		/* PRQA S 2001 */
+
+	/* save the received parameters */
+	i = 0;
+	params->in_rate = msg_params->r.value[i++];	/* PRQA S 3440 13 */
+	params->ch_mode = msg_params->r.value[i++];
+	params->pcm_width = msg_params->r.value[i++];
+	params->frame_size = msg_params->r.value[i++];
+	params->dev1 = msg_params->r.value[i++];
+	params->dev2 = msg_params->r.value[i++];
+	params->dma1 = msg_params->r.value[i++];
+	params->dma2 = msg_params->r.value[i++];
+	params->out_rate = msg_params->r.value[i++];
+	params->vol_rate = msg_params->r.value[i++];
+
+exit:
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** **************************************************************************
+ *\brief  create TDM Renderer component
+ *
+ *\param[in,out]  tdm_renderer	 Pointer to the registered component
+ *\param[in]	  cb		 Callback function
+ *\param[in]	  private_data	 Private data
+ *\retval	  0		 Success
+ *\retval	  -EINVAL	 Invalid base instance or register fail
+ *\retval	  -ENOMEM	 Cannot allocate Renderer instance
+ *****************************************************************************/
+int xf_adsp_tdm_renderer_create(struct xf_adsp_tdm_renderer **tdm_renderer,
+				struct xf_callback_func *cb,
+				void *private_data)
+{
+	struct xf_adsp_tdm_renderer *tdm_rdr;
+	int err;
+	int comp_id;
+
+	/* check the sane ADSP base data */
+	if (!base)
+		return -EINVAL;
+
+	tdm_rdr = kmalloc(sizeof(*tdm_rdr), GFP_KERNEL);
+	if (!tdm_rdr)
+		return -ENOMEM;
+
+	/* PRQA S 3200 */
+	memset(tdm_rdr, 0, sizeof(struct xf_adsp_tdm_renderer));
+
+	/* register TDM Renderer component */
+	err = xf_adsp_register("tdm-renderer", &comp_id);
+	if (err != 0)
+		goto err2;		/* PRQA S 2001 */
+
+	/* register TDM Renderer to ADSP base control */
+	tdm_rdr->handle_id = xf_adsp_base_register_handle(private_data,
+							  cb, comp_id);
+
+	if (tdm_rdr->handle_id <= 0) {
+		err = -EINVAL;
+		goto err1;		/* PRQA S 2001 */
+	}
+
+	/* get the default parameter from plugin */
+	err = xf_adsp_tdm_renderer_get_params(tdm_rdr);
+	if (err != 0)
+		goto err1;		/* PRQA S 2001 */
+
+	/* save compoent data */
+	*tdm_renderer = tdm_rdr;
+
+	return 0;
+
+err1:
+	xf_adsp_unregister(comp_id);		/* PRQA S 3200 */
+
+err2:
+	kfree(tdm_rdr);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief  deinitialize ADSP TDM Renderer component
+ *
+ *\param[in]	 tdm_renderer	Pointer to TDM Renderer component
+ *\retval	 0		Success
+ *\retval	 -EINVAL	Invalid base or Renderer data
+ **************************************************************/
+/* PRQA S 3673 1*/
+int xf_adsp_tdm_renderer_destroy(struct xf_adsp_tdm_renderer *tdm_renderer)
+{
+	struct xf_handle *handle;
+	int handle_id;
+
+	/* check the sane ADSP base data */
+	if (!base || !tdm_renderer)
+		return -EINVAL;
+
+	handle_id = tdm_renderer->handle_id;
+
+	handle = xf_adsp_base_get_handle(handle_id);
+	if (!handle)
+		goto exit;		/* PRQA S 2001 */
+
+	/* unregister component */
+	xf_adsp_unregister(handle->comp_id);		/* PRQA S 3200 */
+
+	/* free handle data from base control */
+	xf_adsp_base_free_handle(handle_id);		/* PRQA S 3200 */
+
+exit:
+	kfree(tdm_renderer);
+
+	return 0;
+}
+
+/***********************************************************************
+ * APIs for TDM Capture component
+ * ********************************************************************/
+
+/** ***********************************************************
+ *\brief  set ADSP TDM Capture parameters
+ *
+ *\param[in]	 tdm_capture	Pointer to TDM Capture component
+ *\retval	 0		Success
+ *\retval	 -EINVAL	Failed
+ **************************************************************/
+int xf_adsp_tdm_capture_set_params(struct xf_adsp_tdm_capture *tdm_capture)
+{
+	struct xf_message msg;
+	struct xf_set_param_msg *msg_params;
+	struct xf_adsp_tdm_capture_params *params;
+	struct xf_buffer *b;
+	int i;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base || !tdm_capture)
+		return -EINVAL;
+
+	params = &tdm_capture->params;
+
+	/* get TDM Capture's handle data */
+	handle = xf_adsp_base_get_handle(tdm_capture->handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+
+	msg_params = xf_buffer_data(b);
+
+	i = 0;
+	msg_params->item[i].id = XA_TDM_CAP_CONFIG_PARAM_IN_SAMPLE_RATE;
+	msg_params->item[i++].value = params->in_rate;
+
+	msg_params->item[i].id = XA_TDM_CAP_CONFIG_PARAM_CHANNEL_MODE;
+	msg_params->item[i++].value = params->ch_mode;
+
+	msg_params->item[i].id = XA_TDM_CAP_CONFIG_PARAM_PCM_WIDTH;
+	msg_params->item[i++].value = params->pcm_width;
+
+	msg_params->item[i].id = XA_TDM_CAP_CONFIG_PARAM_FRAME_SIZE;
+	msg_params->item[i++].value = params->frame_size;
+
+	msg_params->item[i].id = XA_TDM_CAP_CONFIG_PARAM_INPUT1;
+	msg_params->item[i++].value = params->dev1;
+
+	msg_params->item[i].id = XA_TDM_CAP_CONFIG_PARAM_INPUT2;
+	msg_params->item[i++].value = params->dev2;
+
+	msg_params->item[i].id = XA_TDM_CAP_CONFIG_PARAM_DMACHANNEL1;
+	msg_params->item[i++].value = params->dma1;
+
+	msg_params->item[i].id = XA_TDM_CAP_CONFIG_PARAM_DMACHANNEL2;
+	msg_params->item[i++].value = params->dma2;
+
+	msg_params->item[i].id = XA_TDM_CAP_CONFIG_PARAM_OUT_SAMPLE_RATE;
+	msg_params->item[i++].value = params->out_rate;
+
+	msg_params->item[i].id = XA_TDM_CAP_CONFIG_PARAM_VOLUME_RATE;
+	msg_params->item[i++].value = params->vol_rate;
+
+	/* PRQA S 3200 2*/
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, tdm_capture->handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_SET_PARAM, XF_SET_PARAM_CMD_LEN(i), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief  get ADSP TDM Capture parameters
+ *
+ *\param[in]	 tdm_capture	Pointer to TDM Capture component
+ *\retval	 0		Success
+ *\retval	 -EINVAL	Failed
+ **************************************************************/
+/* PRQA S 1505 1*/
+int xf_adsp_tdm_capture_get_params(struct xf_adsp_tdm_capture *tdm_capture)
+{
+	struct xf_adsp_tdm_capture_params *params;
+	struct xf_message msg;
+	struct xf_buffer *b;
+	union xf_get_param_msg *msg_params;
+	int i;
+	struct xf_handle *handle;
+	int err = 0;
+
+	/* check the sane ADSP base data */
+	if (!base || !tdm_capture)
+		return -EINVAL;
+
+	params = &tdm_capture->params;
+
+	/* get TDM Capture's handle data */
+	handle = xf_adsp_base_get_handle(tdm_capture->handle_id);
+	if (!handle)
+		return -EINVAL;
+
+	b = xf_buffer_get(base->aux_pool);
+	msg_params = xf_buffer_data(b);
+
+	i = 0;
+	/* PRQA S 3440 13 1*/
+	msg_params->c.id[i++] = XA_TDM_CAP_CONFIG_PARAM_IN_SAMPLE_RATE;
+	msg_params->c.id[i++] = XA_TDM_CAP_CONFIG_PARAM_CHANNEL_MODE;
+	msg_params->c.id[i++] = XA_TDM_CAP_CONFIG_PARAM_PCM_WIDTH;
+	msg_params->c.id[i++] = XA_TDM_CAP_CONFIG_PARAM_FRAME_SIZE;
+	msg_params->c.id[i++] = XA_TDM_CAP_CONFIG_PARAM_INPUT1;
+	msg_params->c.id[i++] = XA_TDM_CAP_CONFIG_PARAM_INPUT2;
+	msg_params->c.id[i++] = XA_TDM_CAP_CONFIG_PARAM_DMACHANNEL1;
+	msg_params->c.id[i++] = XA_TDM_CAP_CONFIG_PARAM_DMACHANNEL2;
+	msg_params->c.id[i++] = XA_TDM_CAP_CONFIG_PARAM_OUT_SAMPLE_RATE;
+	msg_params->c.id[i++] = XA_TDM_CAP_CONFIG_PARAM_VOLUME_RATE;
+
+	/* PRQA S 3200 2*/
+	xf_create_msg(&msg,
+		      __XF_MSG_ID(__XF_AP_CLIENT(0, tdm_capture->handle_id),
+				  __XF_PORT_SPEC2(handle->comp_id, 0)),
+		      XF_GET_PARAM, XF_GET_PARAM_CMD_LEN(i), msg_params, NULL);
+
+	err = xf_send_and_receive(&msg);
+	if (err != 0)
+		goto exit;		/* PRQA S 2001 */
+
+	/* save the received parameters */
+	i = 0;
+	params->in_rate = msg_params->r.value[i++];	/* PRQA S 3440 13 */
+	params->ch_mode = msg_params->r.value[i++];
+	params->pcm_width = msg_params->r.value[i++];
+	params->frame_size = msg_params->r.value[i++];
+	params->dev1 = msg_params->r.value[i++];
+	params->dev2 = msg_params->r.value[i++];
+	params->dma1 = msg_params->r.value[i++];
+	params->dma2 = msg_params->r.value[i++];
+	params->out_rate = msg_params->r.value[i++];
+	params->vol_rate = msg_params->r.value[i++];
+
+exit:
+	/* return msg to pool */
+	xf_buffer_put(b);
+
+	return err;
+}
+
+/** **************************************************************************
+ *\brief  create TDM Capture component
+ *
+ *\param[in,out]  tdm_capture	 Pointer to the registered component
+ *\param[in]	  cb		 Callback function
+ *\param[in]	  private_data	 Private data
+ *\retval	  0		 Success
+ *\retval	  -EINVAL	 Invalid base instance or register fail
+ *\retval	  -ENOMEM	 Cannot allocate Renderer instance
+ *****************************************************************************/
+int xf_adsp_tdm_capture_create(struct xf_adsp_tdm_capture **tdm_capture,
+			       struct xf_callback_func *cb, void *private_data)
+{
+	struct xf_adsp_tdm_capture *tdm_cap;
+	int err;
+	int comp_id;
+
+	/* check the sane ADSP base data */
+	if (!base)
+		return -EINVAL;
+
+	tdm_cap = kmalloc(sizeof(*tdm_cap), GFP_KERNEL);
+	if (!tdm_cap)
+		return -ENOMEM;
+
+	/* PRQA S 3200 */
+	memset(tdm_cap, 0, sizeof(struct xf_adsp_tdm_capture));
+
+	/* register TDM Capture component */
+	err = xf_adsp_register("tdm-capture", &comp_id);
+	if (err != 0)
+		goto err2;		/* PRQA S 2001 */
+
+	/* register TDM Capture to ADSP base control */
+	tdm_cap->handle_id = xf_adsp_base_register_handle(private_data,
+							  cb, comp_id);
+
+	if (tdm_cap->handle_id <= 0) {
+		err = -EINVAL;
+		goto err1;		/* PRQA S 2001 */
+	}
+
+	/* get the default parameter from plugin */
+	err = xf_adsp_tdm_capture_get_params(tdm_cap);
+	if (err != 0)
+		goto err1;		/* PRQA S 2001 */
+
+	/* save compoent data */
+	*tdm_capture = tdm_cap;
+
+	return 0;
+
+err1:
+	xf_adsp_unregister(comp_id);		/* PRQA S 3200 */
+
+err2:
+	kfree(tdm_cap);
+
+	return err;
+}
+
+/** ***********************************************************
+ *\brief  deinitialize ADSP TDM Capture component
+ *
+ *\param[in]	 tdm_capture	 Pointer to TDM Capture component
+ *\retval	 0		 Success
+ *\retval	 -EINVAL	 Invalid base or Renderer data
+ **************************************************************/
+/* PRQA S 3673 */
+int xf_adsp_tdm_capture_destroy(struct xf_adsp_tdm_capture *tdm_capture)
+{
+	struct xf_handle *handle;
+	int handle_id;
+
+	/* check the sane ADSP base data */
+	if (!base || !tdm_capture)
+		return -EINVAL;
+
+	handle_id = tdm_capture->handle_id;
+
+	handle = xf_adsp_base_get_handle(handle_id);
+	if (!handle)
+		goto exit;		/* PRQA S 2001 */
+
+	/* unregister component */
+	xf_adsp_unregister(handle->comp_id);		/* PRQA S 3200 */
+
+	/* free handle data from base control */
+	xf_adsp_base_free_handle(handle_id);		/* PRQA S 3200 */
+
+exit:
+	kfree(tdm_capture);
+
+	return 0;
+}
diff --git a/sound/soc/adsp/xf-adsp-base.h b/sound/soc/adsp/xf-adsp-base.h
new file mode 100644
index 0000000..27eb084
--- /dev/null
+++ b/sound/soc/adsp/xf-adsp-base.h
@@ -0,0 +1,275 @@
+/** *************************************************************************
+ *\file		xf-adsp-base.h
+ *\brief	Header file for ADSP Base Control layer
+ *\addtogroup	ADSP Driver
+ ****************************************************************************
+ *\date		Oct. 21, 2017
+ *\author	Renesas Electronics Corporation
+ ****************************************************************************
+ *\par		Copyright
+ *
+ * Copyright(c) 2016 Renesas Electoronics Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __XF_ADSP_BASE_H
+#define __XF_ADSP_BASE_H
+
+#include "xf-adsp-config.h"
+#include <adsp_drv/xf-adsp-drv-ext.h>
+
+#define XF_BUF_POOL_SIZE	(4)	 /**< number of buffer in a data pool */
+
+/**< maximum number of DSP component can be registered */
+#define MAX_HANDLE		(256)
+
+/* define boolean */
+#define TRUE			(1)
+#define FALSE			(0)
+
+/** \struct xf_callback_func
+ *  \brief  callback function for ADSP's response message
+ */
+struct xf_callback_func {
+	/** callback for empty buffer done message */
+	int (*empty_buf_done)(void *data, int opcode, int length, char *buffer);
+
+	/** callback for fill buffer done message */
+	int (*fill_buf_done)(void *data, int opcode, int length, char *buffer);
+
+	/** callback for event handler */
+	int (*event_handler)(void *data);
+};
+
+/** \struct xf_adsp_renderer_params
+ *  \brief  parameter structure for Renderer component
+ */
+struct xf_adsp_renderer_params {
+	int	 channel;	/**< channel number		*/
+	int	 pcm_width;	/**< PCM width			*/
+	int	 frame_size;	/**< frame size			*/
+	int	 in_rate;	/**< input sampling rate	*/
+	int	 out_rate;	/**< output sampling rate	*/
+	int	 vol_rate;	/**< volume rate		*/
+	int	 dev1;		/**< 1st device index		*/
+	int	 dev2;		/**< 2nd device index		*/
+	int	 dma1;		/**< 1st DMA index		*/
+	int	 dma2;		/**< 2nd DMA index		*/
+	int	 out_channel;	/**< output channels		*/
+	int	 mix_ctrl;	/**< mix control flag		*/
+	int	 state;		/**< operation state		*/
+};
+
+/** \struct xf_adsp_renderer
+ *  \brief  Renderer component structure
+ */
+struct xf_adsp_renderer {
+	struct xf_adsp_renderer_params   params; /**< parameter structure*/
+	struct xf_pool   *buf_pool;  /**< buffer pool for data transfer  */
+	int		 handle_id;  /**< ID of registered handle*/
+};
+
+/** \struct xf_adsp_capture_params
+ *\brief  parameter structure of Capture component
+ */
+struct xf_adsp_capture_params {
+	int	 channel;	/**< channel number		*/
+	int	 pcm_width;	/**< PCM width			*/
+	int	 frame_size;	/**< frame size			*/
+	int	 in_rate;	/**< input sampling rate	*/
+	int	 out_rate;	/**< output sampling rate	*/
+	int	 vol_rate;	/**< volume rate		*/
+	int	 dev1;		/**< 1st device index		*/
+	int	 dev2;		/**< 2nd device index		*/
+	int	 dma1;		/**< 1st DMA index		*/
+	int	 dma2;		/**< 2nd DMA index		*/
+	int	 state;		/**< operation state		*/
+};
+
+/** \struct xf_adsp_capture
+ *  \brief  Capture component structure
+ */
+struct xf_adsp_capture {
+	struct xf_adsp_capture_params	params;	 /**< parameter structuer*/
+	struct xf_pool   *buf_pool;  /**< buffer pool for data transfer  */
+	int		 handle_id;  /**< ID of registered handle*/
+};
+
+/** \struct xf_equalizer_parametric_coef
+ *\brief  Parametric Equalizer type's parameters
+ */
+struct xf_equalizer_parametric_coef {
+	int  type[XA_REL_EQZ_FILTER_NUM];		/**< Filter type */
+	int  fc[XA_REL_EQZ_FILTER_NUM];	  /**< Filter center frequency */
+	int  gain[XA_REL_EQZ_FILTER_NUM];	/**< Filter gain */
+	int  band_width[XA_REL_EQZ_FILTER_NUM];  /**< Filter band width	  */
+	int  gain_base[XA_REL_EQZ_FILTER_NUM];   /**< Filter base gain	  */
+};
+
+/** \struct xf_equalizer_graphic_coef
+ *  \brief  Graphic Equalizer type's parameters
+ */
+struct xf_equalizer_graphic_coef {
+	int  gain_g[XA_REL_EQZ_GRAPHIC_BAND_NUM];/**< Graphic equalizer gain */
+};
+
+/** \struct xf_adsp_equalizer_params
+ *\brief  Equalizer parameters
+ */
+struct xf_adsp_equalizer_params {
+	int		 channel;	/**< channel number	 */
+	int		 pcm_width;	/**< PCM width		 */
+	int		 rate;		/**< sampling rate	 */
+	int		 eqz_type;	/**< Equalizer type	 */
+	struct xf_equalizer_parametric_coef  p_coef; /**< Parametric params */
+	struct xf_equalizer_graphic_coef g_coef; /**< Graphic params */
+};
+
+/** \struct xf_adsp_equalizer
+ *  \brief  Equalizer component's structure
+ */
+struct xf_adsp_equalizer {
+	struct xf_adsp_equalizer_params   params;/**< Equalizer parameters   */
+	struct xf_pool	  *buf_pool;  /**< buffer pool for transfer data  */
+	int		  handle_id; /**< ID of registered handle	*/
+};
+
+/** \struct xf_adsp_tdm_renderer_params
+ *  \brief  parameter structure for TDM Renderer component
+ */
+struct xf_adsp_tdm_renderer_params {
+	int		 ch_mode;	/**< channel mode		*/
+	int		 pcm_width;	/**< PCM width			*/
+	int		 frame_size;	/**< frame size			*/
+	int		 in_rate;	/**< input sampling rate	*/
+	int		 out_rate;	/**< output sampling rate	*/
+	int		 vol_rate;	/**< volume rate		*/
+	int		 dev1;		/**< 1st device index		*/
+	int		 dev2;		/**< 2nd device index		*/
+	int		 dma1;		/**< 1st DMA index		*/
+	int		 dma2;		/**< 2nd DMA index		*/
+};
+
+/** \struct xf_adsp_tdm_renderer
+ *  \brief  TDM Renderer component structure
+ */
+struct xf_adsp_tdm_renderer {
+	struct xf_adsp_tdm_renderer_params   params; /**< parameter structure*/
+	struct xf_pool	  *buf_pool;  /**< buffer pool for data transfer  */
+	int	 handle_id;  /**< ID of registered handle	*/
+};
+
+/** \struct xf_adsp_tdm_capture_params
+ *  \brief  parameter structure for TDM Capture component
+ */
+struct xf_adsp_tdm_capture_params {
+	int	 ch_mode;	/**< channel mode		*/
+	int	 pcm_width;	/**< PCM width			*/
+	int	 frame_size;	/**< frame size			*/
+	int	 in_rate;	/**< input sampling rate	*/
+	int	 out_rate;	/**< output sampling rate	*/
+	int	 vol_rate;	/**< volume rate		*/
+	int	 dev1;		/**< 1st device index		*/
+	int	 dev2;		/**< 2nd device index		*/
+	int	 dma1;		/**< 1st DMA index		*/
+	int	 dma2;		/**< 2nd DMA index		*/
+};
+
+/** \struct xf_adsp_tdm_capture
+ *  \brief  TDM Capture component structure
+ */
+struct xf_adsp_tdm_capture {
+	struct xf_adsp_tdm_capture_params  params; /**< parameter structure*/
+	struct xf_pool	   *buf_pool;  /**< buffer pool for data transfer  */
+	int	 handle_id;  /**< ID of registered handle*/
+};
+
+/** \struct xf_handle
+ *  \brief Handle struct for each ADSP component
+ */
+struct xf_handle {
+	int	 comp_id;/**< ADSP component ID	  */
+	struct xf_callback_func  *cb;/**< callback functions	 */
+	void	*private_data;  /**< private data for callback functions*/
+};
+
+/** \struct xf_adsp_base
+ *  \brief Base component structure
+ */
+struct xf_adsp_base {
+	struct xf_adsp_base_cmd  cmd; /**< proxy commands	 */
+	void	*client; /**< client data which registered to proxy  */
+	struct xf_pool	 *aux_pool;  /**< auxiliary buffer pool data	 */
+	struct xf_handle *handle[MAX_HANDLE];	/**< handler data   */
+	struct task_struct *rsp_thread;/**< thread for response message*/
+	wait_queue_head_t base_wait;	 /**< ADSP base's waiting queue	 */
+	struct xf_message base_msg;   /**< ADSP base's response message   */
+	int base_flag;  /**< flag to control its waiting queue  */
+	int err_flag;  /**< flag to indicate a error from plugins */
+	int wait_flag;  /**< flag to control the polling waiting*/
+	spinlock_t lock; /**< spinlock data */
+};
+
+struct xf_pool *xf_adsp_allocate_mem_pool(int pool_size, int buf_length);
+int xf_adsp_free_mem_pool(struct xf_pool *pool);
+char *xf_adsp_get_data_from_pool(struct xf_pool *pool, int index);
+
+int xf_adsp_empty_this_buffer(int handle_id, char *buffer, int length);
+int xf_adsp_fill_this_buffer(int handle_id, char *buffer, int length);
+
+int xf_adsp_route(int src_handle_id, int dst_handle_id
+		 , int buf_cnt, int buf_size);
+
+int xf_adsp_set_param(int handle_id, int index, int value);
+int xf_adsp_get_param(int handle_id, int index, int *value);
+
+int xf_adsp_renderer_create(struct xf_adsp_renderer **renderer,
+			    struct xf_callback_func *cb, void *private_data);
+int xf_adsp_renderer_destroy(struct xf_adsp_renderer *renderer);
+int xf_adsp_renderer_set_params(struct xf_adsp_renderer *renderer);
+int xf_adsp_renderer_get_params(struct xf_adsp_renderer *renderer);
+
+int xf_adsp_capture_create(struct xf_adsp_capture **capture,
+			   struct xf_callback_func *cb, void *private_data);
+int xf_adsp_capture_destroy(struct xf_adsp_capture *capture);
+int xf_adsp_capture_set_params(struct xf_adsp_capture *capture);
+int xf_adsp_capture_get_params(struct xf_adsp_capture *capture);
+
+int xf_adsp_equalizer_create(struct xf_adsp_equalizer **equalizer,
+			     struct xf_callback_func *cb, void *private_data);
+int xf_adsp_equalizer_destroy(struct xf_adsp_equalizer *equalizer);
+int xf_adsp_equalizer_set_params(struct xf_adsp_equalizer *equalizer);
+int xf_adsp_equalizer_get_params(struct xf_adsp_equalizer *equalizer);
+
+int xf_adsp_tdm_renderer_create(struct xf_adsp_tdm_renderer **tdm_renderer,
+				struct xf_callback_func *cb,
+				void *private_data);
+int xf_adsp_tdm_renderer_destroy(struct xf_adsp_tdm_renderer *tdm_renderer);
+int xf_adsp_tdm_renderer_set_params(struct xf_adsp_tdm_renderer *tdm_renderer);
+int xf_adsp_tdm_renderer_get_params(struct xf_adsp_tdm_renderer *tdm_renderer);
+
+int xf_adsp_tdm_capture_create(struct xf_adsp_tdm_capture **tdm_capture,
+			       struct xf_callback_func *cb,
+			       void *private_data);
+int xf_adsp_tdm_capture_destroy(struct xf_adsp_tdm_capture *tdm_capture);
+int xf_adsp_tdm_capture_set_params(struct xf_adsp_tdm_capture *tdm_capture);
+int xf_adsp_tdm_capture_get_params(struct xf_adsp_tdm_capture *tdm_capture);
+
+#endif
diff --git a/sound/soc/adsp/xf-adsp-config.h b/sound/soc/adsp/xf-adsp-config.h
new file mode 100644
index 0000000..818a46a
--- /dev/null
+++ b/sound/soc/adsp/xf-adsp-config.h
@@ -0,0 +1,604 @@
+/** ****************************************************************************
+ *\file		xf-adsp-config.h
+ *\brief	Header file for ADSP configuration
+ *\addtogroup	ADSP Driver
+ *******************************************************************************
+ *\date		Oct. 21, 2017
+ *\author	Renesas Electronics Corporation
+ *******************************************************************************
+ *\par		Copyright
+ *
+ * Copyright(c) 2016 Renesas Electoronics Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __XF_ADSP_CONFIG_H
+#define __XF_ADSP_CONFIG_H
+
+/* Equalizer definition */
+#define XA_REL_EQZ_FILTER_NUM		(9) /**< number of filter */
+#define XA_REL_EQZ_GRAPHIC_BAND_NUM	(5) /**< number of graphic band */
+
+struct xf_buffer {
+	void			*address;
+	union {						/* PRQA S 750 3 */
+		struct xf_buffer *next;
+		struct xf_pool   *pool;
+	} link;
+};
+
+struct xf_pool {
+	/* length of individual buffer in a pool */
+	u32			length;
+
+	/* number of buffer in a pool */
+	u32			number;
+
+	/* pointer to pool memory */
+	void			*p;
+
+	/* pointer to first free buffer in a pool */
+	struct xf_buffer	*free;
+
+	/* individual buffer */
+	struct xf_buffer	buffer[0];		/* PRQA S 1037 */
+};
+
+struct xf_message {
+	/* pointer to the next item in the list */
+	struct xf_message	*next;
+
+	/* shmem session_id */
+	u32			id;
+
+	/* operation code */
+	u32			opcode;
+
+	/* length of attached message buffer */
+	u32			length;
+
+	/* message buffer */
+	void			*buffer;
+};
+
+/*******************************************************************************
+ * XF_GET_PARAM message
+ ******************************************************************************/
+
+/* ...message body (command/response) */
+union xf_get_param_msg {			/* PRQA S 750 18 */
+	/* ...command structure */
+	struct {
+		/* ...array of parameters requested */
+		u32		id[0];	/* PRQA S 1037 */
+
+	}   __attribute__((__packed__)) c;
+
+	/* ...response structure */
+	struct {
+		/* ...array of parameters values */
+		u32		value[0];/* PRQA S 1037 */
+
+	}   __attribute__((__packed__)) r;
+
+};
+
+/* ...length of the XF_GET_PARAM command/response */
+/* PRQA S 3453 2 */
+#define XF_GET_PARAM_CMD_LEN(params)	(sizeof(u32) * (params))
+#define XF_GET_PARAM_RSP_LEN(params)	(sizeof(u32) * (params))
+
+/*******************************************************************************
+ * XF_SET_PARAM message
+ ******************************************************************************/
+
+/* ...component initialization parameter */
+struct xf_set_param_item {
+	/* ...index of parameter passed to SET_CONFIG_PARAM call */
+	u32				 id;
+
+	/* ...value of parameter */
+	u32				 value;
+
+}   __attribute__ ((__packed__));
+
+/* ...message body (no response message? - tbd) */
+struct xf_set_param_msg {
+	/* ...command message */
+	struct xf_set_param_item	 item[0];	/* PRQA S 1037 */
+
+}   __attribute__ ((__packed__));
+
+/* ...length of the command message */
+/* PRQA S 3453 */
+#define XF_SET_PARAM_CMD_LEN(params) \
+	(sizeof(struct xf_set_param_item) * (params))
+
+/*******************************************************************************
+ * XF_ROUTE definition
+ ******************************************************************************/
+
+/* ...port routing command */
+struct xf_route_port_msg {
+	/* ...source port specification */
+	u32				 src;
+
+	/* ...destination port specification */
+	u32				 dst;
+
+	/* ...number of buffers to allocate */
+	u32				 alloc_number;
+
+	/* ...length of buffer to allocate */
+	u32				 alloc_size;
+
+	/* ...alignment restriction for a buffer */
+	u32				 alloc_align;
+
+}	__attribute__((__packed__));
+
+/*******************************************************************************
+ * XF_UNROUTE definition
+ ******************************************************************************/
+
+/* ...port unrouting command */
+struct xf_unroute_port_msg {
+	/* ...source port specification */
+	u32				 src;
+
+	/* ...destination port specification */
+	u32				 dst;
+
+}	__attribute__((__packed__));
+
+/* ...Capture states  */
+enum xa_capture_state {
+	XA_CAP_STATE_RUN	= 0,
+	XA_CAP_STATE_IDLE	= 1,
+	XA_CAP_STATE_PAUSE	= 2
+};
+
+/* ...Renderer states  */
+enum xa_renderer_state {
+	XA_RDR_STATE_RUN	= 0,
+	XA_RDR_STATE_IDLE	= 1,
+	XA_RDR_STATE_PAUSE	= 2
+};
+
+/*******************************************************************************
+ * Message routing composition - move somewhere else - tbd
+ ******************************************************************************/
+
+/* ...adjust IPC client of message going from user-space */
+#define XF_MSG_AP_FROM_USER(id, client) \
+	(((id) & ~(0xF << 2)) | ((client) << 2))
+
+/* ...wipe out IPC client from message going to user-space */
+#define XF_MSG_AP_TO_USER(id)		   \
+	((id) & ~(0xF << 18))
+
+/* ...port specification (12 bits) */
+#define __XF_PORT_SPEC(core, id, port)  ((core) | ((id) << 2) | ((port) << 8))
+#define __XF_PORT_SPEC2(id, port)	((id) | ((port) << 8))
+#define XF_PORT_CORE(spec)		((spec) & 0x3)
+#define XF_PORT_CLIENT(spec)		(((spec) >> 2) & 0x3F)
+#define XF_PORT_ID(spec)		(((spec) >> 8) & 0xF)
+
+/* ...message id contains source and destination ports specification */
+#define __XF_MSG_ID(src, dst)	(((src) & 0xFFFF) | (((dst) & 0xFFFF) << 16))
+#define XF_MSG_SRC(id)			(((id) >> 0) & 0xFFFF)
+#define XF_MSG_SRC_CORE(id)		(((id) >> 0) & 0x3)
+#define XF_MSG_SRC_CLIENT(id)		(((id) >> 2) & 0x3F)
+#define XF_MSG_SRC_PORT(id)		(((id) >> 8) & 0xF)
+#define XF_MSG_SRC_PROXY(id)		(((id) >> 15) & 0x1)
+#define XF_MSG_DST(id)			(((id) >> 16) & 0xFFFF)
+#define XF_MSG_DST_CORE(id)		(((id) >> 16) & 0x3)
+#define XF_MSG_DST_CLIENT(id)		(((id) >> 18) & 0x3F)
+#define XF_MSG_DST_PORT(id)		(((id) >> 24) & 0xF)
+#define XF_MSG_DST_PROXY(id)		(((id) >> 31) & 0x1)
+
+/* ...special treatment of AP-proxy destination field */
+#define XF_AP_IPC_CLIENT(id)		(((id) >> 18) & 0xF)
+#define XF_AP_CLIENT(id)		(((id) >> 22) & 0x1FF)
+#define __XF_AP_PROXY(core)		((core) | 0x8000)
+#define __XF_DSP_PROXY(core)		((core) | 0x8000)
+#define __XF_AP_CLIENT(core, client)	((core) | ((client) << 6) | 0x8000)
+
+/*******************************************************************************
+ * Opcode composition
+ ******************************************************************************/
+
+/* ...opcode composition with command/response data tags */
+#define __XF_OPCODE(c, r, op)	(((c) << 31) | ((r) << 30) | ((op) & 0x3F))
+
+/* ...accessors */
+#define XF_OPCODE_CDATA(opcode)		((opcode) & (1 << 31))
+#define XF_OPCODE_RDATA(opcode)		((opcode) & (1 << 30))
+#define XF_OPCODE_TYPE(opcode)		((opcode) & (0x3F))
+
+/*******************************************************************************
+ * Opcode types
+ ******************************************************************************/
+
+/* ...unregister client */
+#define XF_UNREGISTER			__XF_OPCODE(0, 0, 0)
+
+/* ...register client at proxy */
+#define XF_REGISTER			__XF_OPCODE(1, 0, 1)
+
+/* ...port routing command */
+#define XF_ROUTE			__XF_OPCODE(1, 0, 2)
+
+/* ...port unrouting command */
+#define XF_UNROUTE			__XF_OPCODE(1, 0, 3)
+
+/* ...shared buffer allocation */
+#define XF_ALLOC			__XF_OPCODE(0, 0, 4)
+
+/* ...shared buffer freeing */
+#define XF_FREE				__XF_OPCODE(0, 0, 5)
+
+/* ...set component parameters */
+#define XF_SET_PARAM			__XF_OPCODE(1, 0, 6)
+
+/* ...get component parameters */
+#define XF_GET_PARAM			__XF_OPCODE(1, 1, 7)
+
+/* ...input buffer reception */
+#define XF_EMPTY_THIS_BUFFER		__XF_OPCODE(1, 0, 8)
+
+/* ...output buffer reception */
+#define XF_FILL_THIS_BUFFER		__XF_OPCODE(0, 1, 9)
+
+/* ...flush specific port */
+#define XF_FLUSH			__XF_OPCODE(0, 0, 10)
+
+/* ...start component operation */
+#define XF_START			__XF_OPCODE(0, 0, 11)
+
+/* ...stop component operation */
+#define XF_STOP				__XF_OPCODE(0, 0, 12)
+
+/* ...pause component operation */
+#define XF_PAUSE			__XF_OPCODE(0, 0, 13)
+
+/* ...resume component operation */
+#define XF_RESUME			__XF_OPCODE(0, 0, 14)
+
+/* ...total amount of supported decoder commands */
+#define __XF_OP_NUM			(15)
+
+/*************************************************
+ * Renderer - specific configuration parameters
+ * **********************************************/
+
+enum xa_config_param_renderer {
+	XA_RDR_CONFIG_PARAM_STATE		= 0,
+	XA_RDR_CONFIG_PARAM_PCM_WIDTH		= 1,
+	XA_RDR_CONFIG_PARAM_CHANNELS		= 2,
+	XA_RDR_CONFIG_PARAM_SAMPLE_RATE		= 3,
+	XA_RDR_CONFIG_PARAM_FRAME_SIZE		= 4,
+	XA_RDR_CONFIG_PARAM_OUTPUT1		= 5,
+	XA_RDR_CONFIG_PARAM_DMACHANNEL1		= 6,
+	XA_RDR_CONFIG_PARAM_OUTPUT2		= 7,
+	XA_RDR_CONFIG_PARAM_DMACHANNEL2		= 8,
+	XA_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE	= 9,
+	XA_RDR_CONFIG_PARAM_VOLUME_RATE		= 10,
+	XA_RDR_CONFIG_PARAM_OUT_CHANNELS	= 11,
+	XA_RDR_CONFIG_PARAM_MIX_CONTROL		= 12,
+	XA_RDR_CONFIG_PARAM_NUM			= 13
+};
+
+/*************************************************
+ * Capture - specific configuration parameters
+ * **********************************************/
+
+enum xa_config_param_capture {
+	XA_CAP_CONFIG_PARAM_CB			= 0,
+	XA_CAP_CONFIG_PARAM_STATE		= 1,
+	XA_CAP_CONFIG_PARAM_PCM_WIDTH		= 2,
+	XA_CAP_CONFIG_PARAM_CHANNELS		= 3,
+	XA_CAP_CONFIG_PARAM_SAMPLE_RATE		= 4,
+	XA_CAP_CONFIG_PARAM_FRAME_SIZE		= 5,
+	XA_CAP_CONFIG_PARAM_INPUT1		= 6,
+	XA_CAP_CONFIG_PARAM_DMACHANNEL1		= 7,
+	XA_CAP_CONFIG_PARAM_INPUT2		= 8,
+	XA_CAP_CONFIG_PARAM_DMACHANNEL2		= 9,
+	XA_CAP_CONFIG_PARAM_OUT_SAMPLE_RATE	= 10,
+	XA_CAP_CONFIG_PARAM_VOLUME_RATE		= 11,
+	XA_CAP_CONFIG_PARAM_NUM			= 12
+};
+
+/*************************************************
+ * Equalizer - specific configuration parameters
+ * **********************************************/
+
+enum xa_rel_eqz_filter_type {
+	XA_REL_EQZ_TYPE_THROUGH = 0,
+	XA_REL_EQZ_TYPE_PEAK	= 1,
+	XA_REL_EQZ_TYPE_BASS	= 2,
+	XA_REL_EQZ_TYPE_TREBLE	= 3
+};
+
+enum xa_rel_eqz_type {
+	XA_REL_EQZ_TYPE_PARAMETRIC	= 0,
+	XA_REL_EQZ_TYPE_GRAPHIC		= 1
+};
+
+/*****************************************************************************/
+/* Additional subcommand indices */
+/*****************************************************************************/
+
+enum xa_add_cmd_type_generic {
+	/* XA_API_CMD_SET_CONFIG_PARAM indices */
+	XA_EQZ_CONFIG_PARAM_COEF_FS			= 0x0000,
+	XA_EQZ_CONFIG_PARAM_PCM_WIDTH			= 0x0001,
+	XA_EQZ_CONFIG_PARAM_CH				= 0x0002,
+	XA_EQZ_CONFIG_PARAM_EQZ_TYPE			= 0x0003,
+
+	XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_FC	= 0x0010,
+	XA_EQZ_CONFIG_PARAM_FILTER_1_COEF_FC	= 0x0011,
+	XA_EQZ_CONFIG_PARAM_FILTER_2_COEF_FC	= 0x0012,
+	XA_EQZ_CONFIG_PARAM_FILTER_3_COEF_FC	= 0x0013,
+	XA_EQZ_CONFIG_PARAM_FILTER_4_COEF_FC	= 0x0014,
+	XA_EQZ_CONFIG_PARAM_FILTER_5_COEF_FC	= 0x0015,
+	XA_EQZ_CONFIG_PARAM_FILTER_6_COEF_FC	= 0x0016,
+	XA_EQZ_CONFIG_PARAM_FILTER_7_COEF_FC	= 0x0017,
+	XA_EQZ_CONFIG_PARAM_FILTER_8_COEF_FC	= 0x0018,
+
+	XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_TYPE	= 0x0020,
+	XA_EQZ_CONFIG_PARAM_FILTER_1_COEF_TYPE	= 0x0021,
+	XA_EQZ_CONFIG_PARAM_FILTER_2_COEF_TYPE	= 0x0022,
+	XA_EQZ_CONFIG_PARAM_FILTER_3_COEF_TYPE	= 0x0023,
+	XA_EQZ_CONFIG_PARAM_FILTER_4_COEF_TYPE	= 0x0024,
+	XA_EQZ_CONFIG_PARAM_FILTER_5_COEF_TYPE	= 0x0025,
+	XA_EQZ_CONFIG_PARAM_FILTER_6_COEF_TYPE	= 0x0026,
+	XA_EQZ_CONFIG_PARAM_FILTER_7_COEF_TYPE	= 0x0027,
+	XA_EQZ_CONFIG_PARAM_FILTER_8_COEF_TYPE	= 0x0028,
+
+	XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_BW	= 0x0030,
+	XA_EQZ_CONFIG_PARAM_FILTER_1_COEF_BW	= 0x0031,
+	XA_EQZ_CONFIG_PARAM_FILTER_2_COEF_BW	= 0x0032,
+	XA_EQZ_CONFIG_PARAM_FILTER_3_COEF_BW	= 0x0033,
+	XA_EQZ_CONFIG_PARAM_FILTER_4_COEF_BW	= 0x0034,
+	XA_EQZ_CONFIG_PARAM_FILTER_5_COEF_BW	= 0x0035,
+	XA_EQZ_CONFIG_PARAM_FILTER_6_COEF_BW	= 0x0036,
+	XA_EQZ_CONFIG_PARAM_FILTER_7_COEF_BW	= 0x0037,
+	XA_EQZ_CONFIG_PARAM_FILTER_8_COEF_BW	= 0x0038,
+
+	XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_GA	= 0x0040,
+	XA_EQZ_CONFIG_PARAM_FILTER_1_COEF_GA	= 0x0041,
+	XA_EQZ_CONFIG_PARAM_FILTER_2_COEF_GA	= 0x0042,
+	XA_EQZ_CONFIG_PARAM_FILTER_3_COEF_GA	= 0x0043,
+	XA_EQZ_CONFIG_PARAM_FILTER_4_COEF_GA	= 0x0044,
+	XA_EQZ_CONFIG_PARAM_FILTER_5_COEF_GA	= 0x0045,
+	XA_EQZ_CONFIG_PARAM_FILTER_6_COEF_GA	= 0x0046,
+	XA_EQZ_CONFIG_PARAM_FILTER_7_COEF_GA	= 0x0047,
+	XA_EQZ_CONFIG_PARAM_FILTER_8_COEF_GA	= 0x0048,
+
+	XA_EQZ_CONFIG_PARAM_FILTER_0_COEF_BA	= 0x0050,
+	XA_EQZ_CONFIG_PARAM_FILTER_1_COEF_BA	= 0x0051,
+	XA_EQZ_CONFIG_PARAM_FILTER_2_COEF_BA	= 0x0052,
+	XA_EQZ_CONFIG_PARAM_FILTER_3_COEF_BA	= 0x0053,
+	XA_EQZ_CONFIG_PARAM_FILTER_4_COEF_BA	= 0x0054,
+	XA_EQZ_CONFIG_PARAM_FILTER_5_COEF_BA	= 0x0055,
+	XA_EQZ_CONFIG_PARAM_FILTER_6_COEF_BA	= 0x0056,
+	XA_EQZ_CONFIG_PARAM_FILTER_7_COEF_BA	= 0x0057,
+	XA_EQZ_CONFIG_PARAM_FILTER_8_COEF_BA	= 0x0058,
+
+	XA_EQZ_CONFIG_PARAM_BAND_0_GCOEF_GA	= 0x0060,
+	XA_EQZ_CONFIG_PARAM_BAND_1_GCOEF_GA	= 0x0061,
+	XA_EQZ_CONFIG_PARAM_BAND_2_GCOEF_GA	= 0x0062,
+	XA_EQZ_CONFIG_PARAM_BAND_3_GCOEF_GA	= 0x0063,
+	XA_EQZ_CONFIG_PARAM_BAND_4_GCOEF_GA	= 0x0064
+};
+
+/* ...tdm-renderer-specific configuration parameters */
+enum xa_config_param_tdm_renderer {
+	XA_TDM_RDR_CONFIG_PARAM_PCM_WIDTH	= 0,
+	XA_TDM_RDR_CONFIG_PARAM_CHANNEL_MODE	= 1,
+	XA_TDM_RDR_CONFIG_PARAM_IN_SAMPLE_RATE  = 2,
+	XA_TDM_RDR_CONFIG_PARAM_FRAME_SIZE	= 3,
+	XA_TDM_RDR_CONFIG_PARAM_OUTPUT1		= 4,
+	XA_TDM_RDR_CONFIG_PARAM_DMACHANNEL1	= 5,
+	XA_TDM_RDR_CONFIG_PARAM_OUTPUT2		= 6,
+	XA_TDM_RDR_CONFIG_PARAM_DMACHANNEL2	= 7,
+	XA_TDM_RDR_CONFIG_PARAM_OUT_SAMPLE_RATE = 8,
+	XA_TDM_RDR_CONFIG_PARAM_VOLUME_RATE	= 9
+};
+
+enum xa_rel_tdm_renderer_channel_mode {
+	XA_TDM_RDR_CHANNEL_MODE_2X4 = 0, /**< 4 stereo TDM data	   */
+	XA_TDM_RDR_CHANNEL_MODE_1X8 = 1, /**< 1 eight-channel TDM data*/
+	/**< 1 six-channels plus 1 two-channels TDM data */
+	XA_TDM_RDR_CHANNEL_MODE_6_2 = 2,
+	XA_TDM_RDR_CHANNEL_MODE_2X3 = 3, /**< 3 stereo TDM data	   */
+	XA_TDM_RDR_CHANNEL_MODE_1X6 = 4	 /**< 1 six-channel TDM data  */
+};
+
+/* ...TDM Capture-specific configuration parameters */
+enum xa_config_param_tdm_capture {
+	XA_TDM_CAP_CONFIG_PARAM_PCM_WIDTH	= 0,
+	XA_TDM_CAP_CONFIG_PARAM_CHANNEL_MODE	= 1,
+	XA_TDM_CAP_CONFIG_PARAM_IN_SAMPLE_RATE  = 2,
+	XA_TDM_CAP_CONFIG_PARAM_FRAME_SIZE	= 3,
+	XA_TDM_CAP_CONFIG_PARAM_INPUT1		= 4,
+	XA_TDM_CAP_CONFIG_PARAM_DMACHANNEL1	= 5,
+	XA_TDM_CAP_CONFIG_PARAM_INPUT2		= 6,
+	XA_TDM_CAP_CONFIG_PARAM_DMACHANNEL2	= 7,
+	XA_TDM_CAP_CONFIG_PARAM_OUT_SAMPLE_RATE = 8,
+	XA_TDM_CAP_CONFIG_PARAM_VOLUME_RATE	= 9
+};
+
+enum xa_rel_tdm_capture_channel_mode {
+	XA_TDM_CAP_CHANNEL_MODE_2X4 = 0, /**< 4 stereo TDM data  */
+	XA_TDM_CAP_CHANNEL_MODE_1X8 = 1, /**< 1 eight-channel TDM data*/
+	/**< 1 six-channels plus 1 two-channels TDM data */
+	XA_TDM_CAP_CHANNEL_MODE_6_2 = 2,
+	XA_TDM_CAP_CHANNEL_MODE_2X3 = 3, /**< 3 stereo TDM data	   */
+	XA_TDM_CAP_CHANNEL_MODE_1X6 = 4	 /**< 1 six-channel TDM data  */
+};
+
+/*****************************************************************************/
+/* HW supported	 */
+/*****************************************************************************/
+/* ...SSI modules supported by HW */
+enum ssi_module {
+	SSI00		= 0,
+	SSI01		= 1,
+	SSI02		= 2,
+	SSI03		= 3,
+	SSI04		= 4,
+	SSI05		= 5,
+	SSI06		= 6,
+	SSI07		= 7,
+	SSI10		= 10,
+	SSI11		= 11,
+	SSI12		= 12,
+	SSI13		= 13,
+	SSI14		= 14,
+	SSI15		= 15,
+	SSI16		= 16,
+	SSI17		= 17,
+	SSI20		= 20,
+	SSI21		= 21,
+	SSI22		= 22,
+	SSI23		= 23,
+	SSI24		= 24,
+	SSI25		= 25,
+	SSI26		= 26,
+	SSI27		= 27,
+	SSI30		= 30,
+	SSI31		= 31,
+	SSI32		= 32,
+	SSI33		= 33,
+	SSI34		= 34,
+	SSI35		= 35,
+	SSI36		= 36,
+	SSI37		= 37,
+	SSI40		= 40,
+	SSI41		= 41,
+	SSI42		= 42,
+	SSI43		= 43,
+	SSI44		= 44,
+	SSI45		= 45,
+	SSI46		= 46,
+	SSI47		= 47,
+	SSI5		= 50,
+	SSI6		= 60,
+	SSI7		= 70,
+	SSI8		= 80,
+	SSI90		= 90,
+	SSI91		= 91,
+	SSI92		= 92,
+	SSI93		= 93,
+	SSI94		= 94,
+	SSI95		= 95,
+	SSI96		= 96,
+	SSI97		= 97
+};
+
+/* ...SRC modules supported by HW */
+enum src_module {
+	SRC0	= 110,			  /* SRC0 */
+	SRC1	= 111,			  /* SRC1 */
+	SRC2	= 112,			  /* SRC2 */
+	SRC3	= 113,			  /* SRC3 */
+	SRC4	= 114,			  /* SRC4 */
+	SRC5	= 115,			  /* SRC5 */
+	SRC6	= 116,			  /* SRC6 */
+	SRC7	= 117,			  /* SRC7 */
+	SRC8	= 118,			  /* SRC8 */
+	SRC9	= 119,			  /* SRC9 */
+	SRCMAX  = 120			   /* Maximum number of SRC modules */
+};
+
+/* ...PDMA supported by HW */
+enum {
+	PDMA_CH00 = 0,
+	PDMA_CH01 = 1,
+	PDMA_CH02 = 2,
+	PDMA_CH03 = 3,
+	PDMA_CH04 = 4,
+	PDMA_CH05 = 5,
+	PDMA_CH06 = 6,
+	PDMA_CH07 = 7,
+	PDMA_CH08 = 8,
+	PDMA_CH09 = 9,
+	PDMA_CH10 = 10,
+	PDMA_CH11 = 11,
+	PDMA_CH12 = 12,
+	PDMA_CH13 = 13,
+	PDMA_CH14 = 14,
+	PDMA_CH15 = 15,
+	PDMA_CH16 = 16,
+	PDMA_CH17 = 17,
+	PDMA_CH18 = 18,
+	PDMA_CH19 = 19,
+	PDMA_CH20 = 20,
+	PDMA_CH21 = 21,
+	PDMA_CH22 = 22,
+	PDMA_CH23 = 23,
+	PDMA_CH24 = 24,
+	PDMA_CH25 = 25,
+	PDMA_CH26 = 26,
+	PDMA_CH27 = 27,
+	PDMA_CH28 = 28,
+	PDMA_CHMAX = 29
+};
+
+/* ...DMAC supported by HW */
+enum {
+	ADMAC_CH00 = PDMA_CHMAX + 0,
+	ADMAC_CH01 = PDMA_CHMAX + 1,
+	ADMAC_CH02 = PDMA_CHMAX + 2,
+	ADMAC_CH03 = PDMA_CHMAX + 3,
+	ADMAC_CH04 = PDMA_CHMAX + 4,
+	ADMAC_CH05 = PDMA_CHMAX + 5,
+	ADMAC_CH06 = PDMA_CHMAX + 6,
+	ADMAC_CH07 = PDMA_CHMAX + 7,
+	ADMAC_CH08 = PDMA_CHMAX + 8,
+	ADMAC_CH09 = PDMA_CHMAX + 9,
+	ADMAC_CH10 = PDMA_CHMAX + 10,
+	ADMAC_CH11 = PDMA_CHMAX + 11,
+	ADMAC_CH12 = PDMA_CHMAX + 12,
+	ADMAC_CH13 = PDMA_CHMAX + 13,
+	ADMAC_CH14 = PDMA_CHMAX + 14,
+	ADMAC_CH15 = PDMA_CHMAX + 15,
+	ADMAC_CH16 = PDMA_CHMAX + 16,
+	ADMAC_CH17 = PDMA_CHMAX + 17,
+	ADMAC_CH18 = PDMA_CHMAX + 18,
+	ADMAC_CH19 = PDMA_CHMAX + 19,
+	ADMAC_CH20 = PDMA_CHMAX + 20,
+	ADMAC_CH21 = PDMA_CHMAX + 21,
+	ADMAC_CH22 = PDMA_CHMAX + 22,
+	ADMAC_CH23 = PDMA_CHMAX + 23,
+	ADMAC_CH24 = PDMA_CHMAX + 24,
+	ADMAC_CH25 = PDMA_CHMAX + 25,
+	ADMAC_CH26 = PDMA_CHMAX + 26,
+	ADMAC_CH27 = PDMA_CHMAX + 27,
+	ADMAC_CH28 = PDMA_CHMAX + 28,
+	ADMAC_CH29 = PDMA_CHMAX + 29,
+	ADMAC_CH30 = PDMA_CHMAX + 30,
+	ADMAC_CH31 = PDMA_CHMAX + 31,
+	ADMAC_CHMAX = PDMA_CHMAX + 32
+};
+
+#endif
-- 
2.17.1

