diff --git a/drivers/gpu/drm/amd/dal/dc/audio/Makefile b/drivers/gpu/drm/amd/dal/dc/audio/Makefile
new file mode 100644
index 000000000000..0999372cecf0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the 'audio' sub-component of DAL.
+# It provides the control and status of HW adapter resources,
+# that are global for the ASIC and sharable between pipes.
+
+AUDIO = audio_base.o hw_ctx_audio.o
+
+AMD_DAL_AUDIO = $(addprefix $(AMDDALPATH)/dc/audio/,$(AUDIO))
+
+AMD_DAL_FILES += $(AMD_DAL_AUDIO)
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+AUDIO_DCE11 = audio_dce110.o hw_ctx_audio_dce110.o
+
+AMD_DAL_AUDIO_DCE11 = $(addprefix $(AMDDALPATH)/dc/audio/dce110/,$(AUDIO_DCE11))
+
+AMD_DAL_FILES += $(AMD_DAL_AUDIO_DCE11)
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/audio.h b/drivers/gpu/drm/amd/dal/dc/audio/audio.h
new file mode 100644
index 000000000000..ad2dc18ef37b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/audio.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AUDIO_H__
+#define __DAL_AUDIO_H__
+
+#include "include/audio_interface.h"
+#include "hw_ctx_audio.h"
+#include "include/link_service_types.h"
+
+/***** only for hook functions  *****/
+/**
+ *which will be overwritten by derived audio object.
+ *audio hw context object is independent object
+ */
+
+struct audio;
+
+struct audio_funcs {
+	/*
+	 *get_object_id
+	 *get_object_type
+	 *enumerate_input_signals
+	 *enumerate_output_signals
+	 *is_input_signal_supported
+	 *is_output_signal_supported
+	 *set_object_properties
+	 *get_object_properties
+	 */
+
+	void (*destroy)(struct audio **audio);
+	/*power_up
+	 *power_down
+	 *release_hw_base
+	 */
+
+	/* setup audio */
+	enum audio_result (*setup)(
+		struct audio *audio,
+		struct audio_output *output,
+		struct audio_info *info);
+
+	enum audio_result (*enable_output)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	enum audio_result (*disable_output)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	/*enable_azalia_audio_jack_presence
+	 * disable_azalia_audio_jack_presence
+	 */
+
+	enum audio_result (*unmute)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	enum audio_result (*mute)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	/* SW initialization that cannot be done in constructor. This will
+	 * be done is audio_power_up but is not in audio_interface. It is only
+	 * called by power_up
+	 */
+	enum audio_result (*initialize)(
+		struct audio *audio);
+
+	/* enable channel splitting mapping */
+	void (*enable_channel_splitting_mapping)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal,
+		const struct audio_channel_associate_info *audio_mapping,
+		bool enable);
+
+	/* get current multi channel split. */
+	enum audio_result (*get_channel_splitting_mapping)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		struct audio_channel_associate_info *audio_mapping);
+
+	/* set payload value for the unsolicited response */
+	void (*set_unsolicited_response_payload)(
+		struct audio *audio,
+		enum audio_payload payload);
+
+	/* Update audio wall clock source */
+	void (*setup_audio_wall_dto)(
+		struct audio *audio,
+		enum signal_type signal,
+		const struct audio_crtc_info *crtc_info,
+		const struct audio_pll_info *pll_info);
+
+	/* options and features supported by Audio */
+	struct audio_feature_support (*get_supported_features)(
+		struct audio *audio);
+
+	/*
+	 *check_audio_bandwidth
+	 *write_reg
+	 *read_reg
+	 *enable_gtc_embedding_with_group
+	 *disable_gtc_embedding
+	 *register_interrupt
+	 *unregister_interrupt
+	 *process_interrupt
+	 *create_hw_ctx
+	 *getHwCtx
+	 *setHwCtx
+	 *handle_interrupt
+	 */
+};
+
+struct audio {
+	/* hook functions. they will be overwritten by specific ASIC */
+	const struct audio_funcs *funcs;
+	/* TODO: static struct audio_funcs funcs;*/
+
+	/*external structures - get service from external*/
+	struct graphics_object_id id;
+	struct adapter_service *adapter_service;
+	/* audio HW context */
+	struct hw_ctx_audio *hw_ctx;
+	struct dc_context *ctx;
+	/* audio supports input and output signals */
+	uint32_t input_signals;
+	uint32_t output_signals;
+};
+
+/* - functions defined by audio.h will be used by audio component only.
+ *   but audio.c also implements some function defined by dal\include
+ */
+
+/* graphics_object_base implemention
+ * 1.input_signals and output_signals are moved
+ * into audio object.
+ *
+ * 2.Get the Graphics Object ID
+ *
+ * Outside audio:
+ * use dal_graphics_object_id_get_audio_id
+ * Within audio:
+ *	use audio->go_base.id
+ *
+ * 3. Get the Graphics Object Type
+ *
+ *  use object_id.type
+ *  not function implemented.
+ * 4. Common Graphics Object Properties
+ * use object id ->go_properties.multi_path
+ * not function implemented.
+ */
+
+bool dal_audio_construct_base(
+	struct audio *audio,
+	const struct audio_init_data *init_data);
+
+void dal_audio_destruct_base(
+	struct audio *audio);
+
+void dal_audio_release_hw_base(
+	struct audio *audio);
+
+#endif  /* __DAL_AUDIO__ */
+
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c b/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
new file mode 100644
index 000000000000..bfd6725d9b91
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "audio.h"
+#include "hw_ctx_audio.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/audio_dce110.h"
+#include "dce110/hw_ctx_audio_dce110.h"
+#endif
+
+/***** static function : only used within audio.c *****/
+
+/* stub for hook functions */
+static void destroy(
+	struct audio **audio)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+static enum audio_result setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result initialize(
+	struct audio *audio)
+{
+	/*DCE specific, must be implemented in derived. Implemeentaion of
+	 *initialize will create audio hw context. create_hw_ctx
+	 */
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static void enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* get current multi channel split. */
+static enum audio_result get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+/* set payload value for the unsolicited response */
+static void set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* update audio wall clock source */
+static void setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+static struct audio_feature_support get_supported_features(struct audio *audio)
+{
+	/*DCE specific, must be implemented in derived*/
+	struct audio_feature_support features;
+
+	dm_memset(&features, 0, sizeof(features));
+
+	features.ENGINE_DIGA = 1;
+	features.ENGINE_DIGB = 1;
+
+	return features;
+}
+
+static const struct audio_funcs audio_funcs = {
+	.destroy = destroy,
+	.setup = setup,
+	.enable_output = enable_output,
+	.disable_output = disable_output,
+	.unmute = unmute,
+	.mute = mute,
+	.initialize = initialize,
+	.enable_channel_splitting_mapping =
+		enable_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.setup_audio_wall_dto = setup_audio_wall_dto,
+	.get_supported_features = get_supported_features,
+};
+
+/***** SCOPE : declare in audio.h. use within dal-audio. *****/
+
+bool dal_audio_construct_base(
+	struct audio *audio,
+	const struct audio_init_data *init_data)
+{
+	enum signal_type signals = SIGNAL_TYPE_HDMI_TYPE_A;
+
+	ASSERT(init_data->as != NULL);
+
+	/* base hook functions */
+	audio->funcs = &audio_funcs;
+
+	/*setup pointers to get service from dal service compoenents*/
+	audio->adapter_service = init_data->as;
+
+	audio->ctx = init_data->ctx;
+
+	/* save audio endpoint number to identify object creating */
+	audio->id = init_data->audio_stream_id;
+
+	/* Fill supported signals. !!! be aware that android definition is
+	 * already shift to vector.
+	 */
+	signals |= SIGNAL_TYPE_DISPLAY_PORT;
+	signals |= SIGNAL_TYPE_DISPLAY_PORT_MST;
+	signals |= SIGNAL_TYPE_EDP;
+	signals |= SIGNAL_TYPE_DISPLAY_PORT;
+	signals |= SIGNAL_TYPE_WIRELESS;
+
+	/* Audio supports same set for input and output signals */
+	audio->input_signals = signals;
+	audio->output_signals = signals;
+
+	return true;
+}
+
+/* except hw_ctx, no other hw need reset. so do nothing */
+void dal_audio_destruct_base(
+	struct audio *audio)
+{
+}
+
+/* Enumerate Graphics Object supported Input/Output Signal Types */
+uint32_t dal_audio_enumerate_input_signals(
+	struct audio *audio)
+{
+	return audio->input_signals;
+}
+
+uint32_t dal_audio_enumerate_output_signals(
+	struct audio *audio)
+{
+	return audio->output_signals;
+}
+
+/*  Check if signal supported by GraphicsObject  */
+bool dal_audio_is_input_signal_supported(
+	struct audio *audio,
+	enum signal_type signal)
+{
+	return (signal & audio->output_signals) != 0;
+}
+
+bool dal_audio_is_output_signal_supported(
+	struct audio *audio,
+	enum signal_type signal)
+{
+	return (signal & audio->input_signals) != 0;
+}
+
+/***** SCOPE : declare in dal\include  *****/
+
+/* audio object creator triage. memory allocate and release will be
+ * done within dal_audio_create_dcexx
+ */
+struct audio *dal_audio_create(
+	const struct audio_init_data *init_data)
+{
+	struct adapter_service *as;
+
+	if (init_data->as == NULL)
+		return NULL;
+
+	as = init_data->as;
+	switch (dal_adapter_service_get_dce_version(as)) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dal_audio_create_dce110(init_data);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dal_audio_create_dce110(init_data);
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	return NULL;
+}
+
+/* audio object creator triage.
+ * memory for "struct audio   dal_audio_create_dce8x" allocate
+ * will happens within dal_audio_dce8x. memory allocate is done
+ * with dal_audio_create_dce8x. memory release is initiated by
+ * dal_audio_destroy. It will call hook function which will finially
+ * used destroy() of dal_audio_dce8x. therefore, no memroy allocate
+ *and release happen physcially at audio base object.
+ */
+void dal_audio_destroy(
+	struct audio **audio)
+{
+	if (!audio || !*audio) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*audio)->funcs->destroy(audio);
+
+	*audio = NULL;
+}
+
+const struct graphics_object_id dal_audio_get_graphics_object_id(
+	const struct audio *audio)
+{
+	return audio->id;
+}
+
+/* enable azalia audio endpoint. This function call hw_ctx directly
+ *not overwitten at audio level.
+ */
+enum audio_result dal_audio_enable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id)
+{
+	audio->hw_ctx->funcs->enable_azalia_audio(audio->hw_ctx, engine_id);
+	return AUDIO_RESULT_OK;
+}
+
+/* disable azalia audio endpoint. This function call hw_ctx directly
+ *not overwitten at audio level.
+ */
+enum audio_result dal_audio_disable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id)
+{
+	audio->hw_ctx->funcs->disable_azalia_audio(audio->hw_ctx, engine_id);
+	return AUDIO_RESULT_OK;
+}
+
+/* get audio bandwidth information. This function call hw_ctx directly
+ *not overwitten at audio level.
+ */
+void dal_audio_check_audio_bandwidth(
+	struct audio *audio,
+	const struct audio_crtc_info *info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates)
+{
+	dal_hw_ctx_audio_check_audio_bandwidth(
+		audio->hw_ctx, info, channel_count, signal, sample_rates);
+}
+
+/* DP Audio register write access. This function call hw_ctx directly
+ * not overwitten at audio level.
+ */
+
+/*assign GTC group and enable GTC value embedding*/
+void dal_audio_enable_gtc_embedding_with_group(
+	struct audio *audio,
+	uint32_t group_num,
+	uint32_t audio_latency)
+{
+	audio->hw_ctx->funcs->enable_gtc_embedding_with_group(
+		audio->hw_ctx, group_num, audio_latency);
+}
+
+/* disable GTC value embedding */
+void dal_audio_disable_gtc_embedding(
+	struct audio *audio)
+{
+	audio->hw_ctx->funcs->disable_gtc_embedding(audio->hw_ctx);
+}
+
+/* perform power up sequence (boot up, resume, recovery) */
+enum audio_result dal_audio_power_up(
+	struct audio *audio)
+{
+	return audio->funcs->initialize(audio);
+}
+
+/* perform power down (shut down, stand by) */
+enum audio_result dal_audio_power_down(
+	struct audio *audio)
+{
+	return AUDIO_RESULT_OK;
+}
+
+/* setup audio */
+enum audio_result dal_audio_setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info)
+{
+	return audio->funcs->setup(audio, output, info);
+}
+
+/* enable audio */
+enum audio_result dal_audio_enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->enable_output(audio, engine_id, signal);
+}
+
+/* disable audio */
+enum audio_result dal_audio_disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->disable_output(audio, engine_id, signal);
+}
+
+/* unmute audio */
+enum audio_result dal_audio_unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->unmute(audio, engine_id, signal);
+}
+
+/* mute audio */
+enum audio_result dal_audio_mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->mute(audio, engine_id, signal);
+}
+
+/* Enable multi channel split */
+void dal_audio_enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	audio->funcs->enable_channel_splitting_mapping(
+		audio, engine_id, signal, audio_mapping, enable);
+}
+
+/* get current multi channel split. */
+enum audio_result dal_audio_get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	return audio->funcs->get_channel_splitting_mapping(
+		audio, engine_id, audio_mapping);
+}
+
+/* set payload value for the unsolicited response */
+void dal_audio_set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload)
+{
+	audio->funcs->set_unsolicited_response_payload(audio, payload);
+}
+
+/* update audio wall clock source */
+void dal_audio_setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	audio->funcs->setup_audio_wall_dto(audio, signal, crtc_info, pll_info);
+}
+
+struct audio_feature_support dal_audio_get_supported_features(
+	struct audio *audio)
+{
+	return audio->funcs->get_supported_features(audio);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
new file mode 100644
index 000000000000..1aa0c1e61b32
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "audio_dce110.h"
+
+/***** static functions  *****/
+
+static void destruct(struct audio_dce110 *audio)
+{
+	/*release memory allocated for hw_ctx -- allocated is initiated
+	 *by audio_dce110 power_up
+	 *audio->base->hw_ctx = NULL is done within hw-ctx->destroy
+	 */
+	if (audio->base.hw_ctx)
+		audio->base.hw_ctx->funcs->destroy(&(audio->base.hw_ctx));
+
+	/* reset base_audio_block */
+	dal_audio_destruct_base(&audio->base);
+}
+
+static void destroy(struct audio **ptr)
+{
+	struct audio_dce110 *audio = NULL;
+
+	audio = container_of(*ptr, struct audio_dce110, base);
+
+	destruct(audio);
+
+	/* release memory allocated for audio_dce110*/
+	dm_free((*ptr)->ctx, audio);
+	*ptr = NULL;
+}
+
+
+/* The inital call of hook function comes from audio object level.
+ *The passing object handle "struct audio *audio" point to base object
+ *already.There is not need to get base object from audio_dce110.
+ */
+
+/**
+* setup
+*
+* @brief
+*  setup Audio HW block, to be called by dal_audio_setup
+*
+*/
+static enum audio_result setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info)
+{
+	switch (output->signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		/*setup HDMI audio engine*/
+		audio->hw_ctx->funcs->enable_afmt_clock(
+			audio->hw_ctx,
+			output->engine_id,
+			true);
+		audio->hw_ctx->funcs->setup_hdmi_audio(
+			audio->hw_ctx, output->engine_id, &output->crtc_info);
+
+		audio->hw_ctx->funcs->setup_azalia(
+			audio->hw_ctx,
+			output->engine_id,
+			output->signal,
+			&output->crtc_info,
+			&output->pll_info,
+			info);
+		break;
+
+	case SIGNAL_TYPE_WIRELESS:
+		/* setup Azalia block for Wireless Display - This
+			is different than for wired
+			displays because there is no
+			DIG to program.*/
+		/*TODO:
+		audio->hw_ctx->funcs->setup_azalia_for_vce(
+			audio->hw_ctx,
+			audio->signal,
+			audio->crtc_info,
+			info);
+		*/
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		/* setup DP audio engine will be done at enable output */
+
+		/* setup Azalia block*/
+		audio->hw_ctx->funcs->setup_azalia(
+			audio->hw_ctx,
+			output->engine_id,
+			output->signal,
+			&output->crtc_info,
+			&output->pll_info,
+			info);
+
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* enable_output
+*
+* @brief
+*  enable Audio HW block, to be called by dal_audio_enable_output
+*/
+static enum audio_result enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/* enable audio output */
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP: {
+			/* enable AFMT clock before enable audio*/
+			audio->hw_ctx->funcs->enable_afmt_clock(
+				audio->hw_ctx, engine_id, true);
+			/* setup DP audio engine */
+			audio->hw_ctx->funcs->setup_dp_audio(
+				audio->hw_ctx, engine_id);
+			/* enabl DP audio packets will be done at unblank */
+			audio->hw_ctx->funcs->enable_dp_audio(
+				audio->hw_ctx, engine_id);
+		}
+		break;
+	case SIGNAL_TYPE_WIRELESS:
+		/* route audio to VCE block */
+		audio->hw_ctx->funcs->setup_vce_audio(audio->hw_ctx);
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* disable_output
+*
+* @brief
+*  disable Audio HW block, to be called by dal_audio_disable_output
+*
+*/
+static enum audio_result disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_WIRELESS:
+		/* disable HDMI audio */
+		audio->hw_ctx->
+			funcs->disable_azalia_audio(
+					audio->hw_ctx, engine_id);
+		audio->hw_ctx->
+			funcs->enable_afmt_clock(
+					audio->hw_ctx, engine_id,
+					false);
+
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP: {
+			/* disable DP audio */
+			audio->hw_ctx->funcs->disable_dp_audio(
+				audio->hw_ctx, engine_id);
+			audio->hw_ctx->funcs->disable_azalia_audio(
+				audio->hw_ctx, engine_id);
+			audio->hw_ctx->funcs->enable_afmt_clock(
+				audio->hw_ctx, engine_id, false);
+		}
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* unmute
+*
+* @brief
+*  unmute audio, to be called by dal_audio_unmute
+*
+*/
+static enum audio_result unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		/* unmute Azalia audio */
+		audio->hw_ctx->funcs->unmute_azalia_audio(
+				audio->hw_ctx, engine_id);
+		break;
+	case SIGNAL_TYPE_WIRELESS:
+		/*Do nothing for wireless display*/
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* mute
+*
+* @brief
+*  mute audio, to be called  by dal_audio_nmute
+*
+*/
+static enum audio_result mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		/* mute Azalia audio */
+		audio->hw_ctx->funcs->mute_azalia_audio(
+				audio->hw_ctx, engine_id);
+		break;
+	case SIGNAL_TYPE_WIRELESS:
+		/*Do nothing for wireless display*/
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* initialize
+*
+* @brief
+*  Perform SW initialization - create audio hw context. Then do HW
+*  initialization. this function is called at dal_audio_power_up.
+*
+*/
+static enum audio_result initialize(
+	struct audio *audio)
+{
+	uint8_t audio_endpoint_enum_id = 0;
+
+	audio_endpoint_enum_id = audio->id.enum_id;
+
+	/* HW CTX already create*/
+	if (audio->hw_ctx != NULL)
+		return AUDIO_RESULT_OK;
+
+	audio->hw_ctx = dal_hw_ctx_audio_dce110_create(
+			audio->ctx,
+			audio_endpoint_enum_id);
+
+	if (audio->hw_ctx == NULL)
+		return AUDIO_RESULT_ERROR;
+
+	/* override HW default settings */
+	audio->hw_ctx->funcs->hw_initialize(audio->hw_ctx);
+
+	return AUDIO_RESULT_OK;
+}
+
+/* enable multi channel split */
+static void enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	audio->hw_ctx->funcs->setup_channel_splitting_mapping(
+		audio->hw_ctx,
+		engine_id,
+		signal,
+		audio_mapping, enable);
+}
+
+/* get current multi channel split. */
+static enum audio_result get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	if (audio->hw_ctx->funcs->get_channel_splitting_mapping(
+		audio->hw_ctx, engine_id, audio_mapping)) {
+		return AUDIO_RESULT_OK;
+	} else {
+		return AUDIO_RESULT_ERROR;
+	}
+}
+
+/**
+* set_unsolicited_response_payload
+*
+* @brief
+*  Set payload value for the unsolicited response
+*/
+static void set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload)
+{
+	audio->hw_ctx->funcs->set_unsolicited_response_payload(
+			audio->hw_ctx, payload);
+}
+
+/**
+* setup_audio_wall_dto
+*
+* @brief
+*  Update audio source clock from hardware context.
+*
+*/
+static void setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	audio->hw_ctx->funcs->setup_audio_wall_dto(
+		audio->hw_ctx, signal, crtc_info, pll_info);
+}
+
+/**
+* get_supported_features
+*
+* @brief
+*  options and features supported by Audio
+*  returns supported engines, signals.
+*  features are reported for HW audio/Azalia block rather then Audio object
+*  itself the difference for DCE6.x is that MultiStream Audio is now supported
+*
+*/
+static struct audio_feature_support get_supported_features(struct audio *audio)
+{
+	struct audio_feature_support afs = {0};
+
+	afs.ENGINE_DIGA = 1;
+	afs.ENGINE_DIGB = 1;
+	afs.ENGINE_DIGC = 1;
+	afs.MULTISTREAM_AUDIO = 1;
+
+	return afs;
+}
+
+static const struct audio_funcs funcs = {
+	.destroy = destroy,
+	.setup = setup,
+	.enable_output = enable_output,
+	.disable_output = disable_output,
+	.unmute = unmute,
+	.mute = mute,
+	.initialize = initialize,
+	.enable_channel_splitting_mapping =
+		enable_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.setup_audio_wall_dto = setup_audio_wall_dto,
+	.get_supported_features = get_supported_features,
+};
+
+static bool construct(
+	struct audio_dce110 *audio,
+	const struct audio_init_data *init_data)
+{
+	struct audio *base = &audio->base;
+
+	/* base audio construct*/
+	if (!dal_audio_construct_base(base, init_data))
+		return false;
+
+	/*vtable methods*/
+	base->funcs = &funcs;
+	return true;
+}
+
+
+/* --- audio scope functions  --- */
+
+struct audio *dal_audio_create_dce110(
+	const struct audio_init_data *init_data)
+{
+	/*allocate memory for audio_dce110 */
+	struct audio_dce110 *audio = dm_alloc(init_data->ctx, sizeof(*audio));
+
+	if (audio == NULL) {
+		ASSERT_CRITICAL(audio);
+		return NULL;
+	}
+	/*pointer to base_audio_block of audio_dce110 ==> audio base object */
+	if (construct(audio, init_data))
+		return &audio->base;
+
+	dal_logger_write(
+		init_data->ctx->logger,
+		LOG_MAJOR_ERROR,
+		LOG_MINOR_COMPONENT_AUDIO,
+		"Failed to create audio object for DCE11\n");
+
+	 /*release memory allocated if fail */
+	dm_free(init_data->ctx, audio);
+	return NULL;
+}
+
+/* Do not need expose construct_dce110 and destruct_dce110 becuase there is
+ *derived object after dce110
+ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
new file mode 100644
index 000000000000..e5ff823368b3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_AUDIO_DCE_110_H__
+#define __DAL_AUDIO_DCE_110_H__
+
+#include "audio/audio.h"
+#include "audio/hw_ctx_audio.h"
+#include "audio/dce110/hw_ctx_audio_dce110.h"
+
+
+
+struct audio_dce110 {
+	struct audio base;
+	/* dce-specific members are following */
+	/* none */
+};
+
+struct audio *dal_audio_create_dce110(const struct audio_init_data *init_data);
+
+#endif   /*__DAL_AUDIO_DCE_110_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
new file mode 100644
index 000000000000..f24b964bdd8d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
@@ -0,0 +1,1930 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+#include "../hw_ctx_audio.h"
+#include "hw_ctx_audio_dce110.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#define FROM_BASE(ptr) \
+	container_of((ptr), struct hw_ctx_audio_dce110, base)
+
+#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000
+#define DP_AUDIO_DTO_MODULE_WITHOUT_SS 360
+#define DP_AUDIO_DTO_PHASE_WITHOUT_SS 24
+
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUDIO_FRONT_END 0
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__REGISTER_PROGRAMMABLE 2
+
+#define FIRST_AUDIO_STREAM_ID 1
+
+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_AUDIO, \
+			"Audio:%s()\n", __func__)
+
+static const uint32_t engine_offset[] = {
+	0,
+	mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL,
+	mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL,
+	mmDIG3_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL
+};
+
+static void destruct(
+	struct hw_ctx_audio_dce110 *hw_ctx_dce110)
+{
+	dal_audio_destruct_hw_ctx_audio(&hw_ctx_dce110->base);
+}
+
+static void destroy(
+	struct hw_ctx_audio **ptr)
+{
+	struct hw_ctx_audio_dce110 *hw_ctx_dce110;
+
+	hw_ctx_dce110 = container_of(
+		*ptr, struct hw_ctx_audio_dce110, base);
+
+	destruct(hw_ctx_dce110);
+	/* release memory allocated for struct hw_ctx_audio_dce110 */
+	dm_free((*ptr)->ctx, hw_ctx_dce110);
+
+	*ptr = NULL;
+}
+
+/* ---  helpers --- */
+static void write_indirect_azalia_reg(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t reg_index,
+	uint32_t reg_data)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+	/* AZALIA_F0_CODEC_ENDPOINT_INDEX  endpoint index  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index;
+
+		set_reg_field_value(value, reg_index,
+			AZALIA_F0_CODEC_ENDPOINT_INDEX,
+			AZALIA_ENDPOINT_REG_INDEX);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AZALIA_F0_CODEC_ENDPOINT_DATA  endpoint data  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data;
+
+		value = 0;
+		set_reg_field_value(value, reg_data,
+			AZALIA_F0_CODEC_ENDPOINT_DATA,
+			AZALIA_ENDPOINT_REG_DATA);
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	dal_logger_write(
+		hw_ctx->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_AUDIO,
+		"AUDIO:write_indirect_azalia_reg: index: %u  data: %u\n",
+		reg_index, reg_data);
+}
+
+static uint32_t read_indirect_azalia_reg(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t reg_index)
+{
+	uint32_t ret_val = 0;
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+
+	/* AZALIA_F0_CODEC_ENDPOINT_INDEX  endpoint index  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index;
+
+		set_reg_field_value(value, reg_index,
+			AZALIA_F0_CODEC_ENDPOINT_INDEX,
+			AZALIA_ENDPOINT_REG_INDEX);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AZALIA_F0_CODEC_ENDPOINT_DATA  endpoint data  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		ret_val = value;
+	}
+
+	dal_logger_write(
+		hw_ctx->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_AUDIO,
+		"AUDIO:read_indirect_azalia_reg: index: %u  data: %u\n",
+		reg_index, ret_val);
+
+	return ret_val;
+}
+
+/* expose/not expose HBR capability to Audio driver */
+static void set_high_bit_rate_capable(
+	const struct hw_ctx_audio *hw_ctx,
+	bool capable)
+{
+	uint32_t value = 0;
+
+	/* set high bit rate audio capable*/
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR);
+
+	set_reg_field_value(value, capable,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR,
+		HBR_CAPABLE);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR,
+		value);
+}
+
+/* set HBR channnel count *
+static void set_hbr_channel_count(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t hbr_channel_count)
+{
+	uint32_t value = 0;
+
+	if (hbr_channel_count > 7)
+		return;
+
+	value = dal_read_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL);
+
+	set_reg_field_value(value, hbr_channel_count,
+		AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL,
+		HBR_CHANNEL_COUNT);
+
+	dal_write_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, value);
+
+}
+
+*set compressed audio channel count *
+static void set_compressed_audio_channel_count(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t compressed_audio_ch_count)
+{
+	uint32_t value = 0;
+	if (compressed_audio_ch_count > 7)
+		return;
+
+	value = dal_read_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL);
+
+	set_reg_field_value(value, compressed_audio_ch_count,
+		AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL,
+		COMPRESSED_CHANNEL_COUNT);
+
+	dal_write_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL,
+		value);
+
+}
+*/
+/* set video latency in in ms/2+1 */
+static void set_video_latency(
+	const struct hw_ctx_audio *hw_ctx,
+	int latency_in_ms)
+{
+	uint32_t value = 0;
+
+	if ((latency_in_ms < 0) || (latency_in_ms > 255))
+		return;
+
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC);
+
+	set_reg_field_value(value, latency_in_ms,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		VIDEO_LIPSYNC);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		value);
+
+}
+
+/* set audio latency in in ms/2+1 */
+static void set_audio_latency(
+	const struct hw_ctx_audio *hw_ctx,
+	int latency_in_ms)
+{
+	uint32_t value = 0;
+
+	if (latency_in_ms < 0)
+		latency_in_ms = 0;
+
+	if (latency_in_ms > 255)
+		latency_in_ms = 255;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC);
+
+	set_reg_field_value(value, latency_in_ms,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		AUDIO_LIPSYNC);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		value);
+
+}
+
+/* enable HW/SW Sync */
+/*static void enable_hw_sw_sync(
+	const struct hw_ctx_audio *hw_ctx)
+{
+		union AZALIA_CYCLIC_BUFFER_SYNC value;
+
+	value = dal_read_reg(mmAZALIA_CYCLIC_BUFFER_SYNC);
+	value.bits.CYCLIC_BUFFER_SYNC_ENABLE = 1;
+	dal_write_reg(mmAZALIA_CYCLIC_BUFFER_SYNC, value);
+}*/
+
+/* disable HW/SW Sync */
+/*static void disable_hw_sw_sync(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	union AZALIA_CYCLIC_BUFFER_SYNC value;
+
+	value = dal_read_reg(
+		mmAZALIA_CYCLIC_BUFFER_SYNC);
+	value.bits.CYCLIC_BUFFER_SYNC_ENABLE = 0;
+	dal_write_reg(
+		mmAZALIA_CYCLIC_BUFFER_SYNC, value);
+}*/
+
+/* update hardware with software's current position in cyclic buffer */
+/*static void update_sw_write_ptr(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t offset)
+{
+		union AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER value;
+
+	value = dal_read_reg(
+		mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER);
+	value.bits.APPLICATION_POSITION_IN_CYCLIC_BUFFER = offset;
+	dal_write_reg(
+		mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER,
+		value);
+}*/
+
+/* update Audio/Video association */
+/*static void update_av_association(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	uint32_t displayId)
+{
+
+}*/
+
+/* ---  hook functions --- */
+static bool get_azalia_clock_info_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct azalia_clock_info *azalia_clock_info);
+
+static bool get_azalia_clock_info_dp(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t requested_pixel_clock_in_khz,
+	const struct audio_pll_info *pll_info,
+	struct azalia_clock_info *azalia_clock_info);
+
+static void setup_audio_wall_dto(
+	const struct hw_ctx_audio *hw_ctx,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	struct azalia_clock_info clock_info = { 0 };
+
+	uint32_t value = dm_read_reg(hw_ctx->ctx, mmDCCG_AUDIO_DTO_SOURCE);
+
+	/* TODO: GraphicsObject\inc\GraphicsObjectDefs.hpp(131):
+	 *inline bool isHdmiSignal(SignalType signal)
+	 *if (Signals::isHdmiSignal(signal))
+	 */
+	if (dc_is_hdmi_signal(signal)) {
+		/*DTO0 Programming goal:
+		-generate 24MHz, 128*Fs from 24MHz
+		-use DTO0 when an active HDMI port is connected
+		(optionally a DP is connected) */
+
+		/* calculate DTO settings */
+		get_azalia_clock_info_hdmi(
+			hw_ctx,
+			crtc_info->requested_pixel_clock,
+			crtc_info->calculated_pixel_clock,
+			&clock_info);
+
+		/* On TN/SI, Program DTO source select and DTO select before
+		programming DTO modulo and DTO phase. These bits must be
+		programmed first, otherwise there will be no HDMI audio at boot
+		up. This is a HW sequence change (different from old ASICs).
+		Caution when changing this programming sequence.
+
+		HDMI enabled, using DTO0
+		program master CRTC for DTO0 */
+		{
+			set_reg_field_value(value,
+				pll_info->dto_source - DTO_SOURCE_ID0,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO0_SOURCE_SEL);
+
+			set_reg_field_value(value,
+				0,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO_SEL);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO_SOURCE, value);
+		}
+
+		/* module */
+		{
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_MODULE);
+			set_reg_field_value(value,
+				clock_info.audio_dto_module,
+				DCCG_AUDIO_DTO0_MODULE,
+				DCCG_AUDIO_DTO0_MODULE);
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_MODULE, value);
+		}
+
+		/* phase */
+		{
+			value = 0;
+
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_PHASE);
+			set_reg_field_value(value,
+				clock_info.audio_dto_phase,
+				DCCG_AUDIO_DTO0_PHASE,
+				DCCG_AUDIO_DTO0_PHASE);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_PHASE, value);
+		}
+
+	} else {
+		/*DTO1 Programming goal:
+		-generate 24MHz, 512*Fs, 128*Fs from 24MHz
+		-default is to used DTO1, and switch to DTO0 when an audio
+		master HDMI port is connected
+		-use as default for DP
+
+		calculate DTO settings */
+		get_azalia_clock_info_dp(
+			hw_ctx,
+			crtc_info->requested_pixel_clock,
+			pll_info,
+			&clock_info);
+
+		/* Program DTO select before programming DTO modulo and DTO
+		phase. default to use DTO1 */
+
+		{
+			set_reg_field_value(value, 1,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO_SEL);
+			/*dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value)*/
+
+			/* Select 512fs for DP TODO: web register definition
+			does not match register header file
+			set_reg_field_value(value, 1,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO2_USE_512FBR_DTO);
+			*/
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO_SOURCE, value);
+		}
+
+		/* module */
+		{
+			value = 0;
+
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_MODULE);
+
+			set_reg_field_value(value,
+				clock_info.audio_dto_module,
+				DCCG_AUDIO_DTO1_MODULE,
+				DCCG_AUDIO_DTO1_MODULE);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_MODULE, value);
+		}
+
+		/* phase */
+		{
+			value = 0;
+
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_PHASE);
+
+			set_reg_field_value(value,
+				clock_info.audio_dto_phase,
+				DCCG_AUDIO_DTO1_PHASE,
+				DCCG_AUDIO_DTO1_PHASE);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_PHASE, value);
+		}
+
+		/* DAL2 code separate DCCG_AUDIO_DTO_SEL and
+		DCCG_AUDIO_DTO2_USE_512FBR_DTO programming into two different
+		location. merge together should not hurt */
+		/*value.bits.DCCG_AUDIO_DTO2_USE_512FBR_DTO = 1;
+		dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value);*/
+	}
+}
+
+/* setup HDMI audio */
+static void setup_hdmi_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	const struct audio_crtc_info *crtc_info)
+{
+	struct audio_clock_info audio_clock_info = {0};
+	uint32_t max_packets_per_line;
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* For now still do calculation, although this field is ignored when
+	above HDMI_PACKET_GEN_VERSION set to 1 */
+	max_packets_per_line =
+		dal_audio_hw_ctx_calc_max_audio_packets_per_line(
+			hw_ctx,
+			crtc_info);
+
+	/* HDMI_AUDIO_PACKET_CONTROL */
+	{
+		addr =
+			mmHDMI_AUDIO_PACKET_CONTROL + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, max_packets_per_line,
+			HDMI_AUDIO_PACKET_CONTROL,
+			HDMI_AUDIO_PACKETS_PER_LINE);
+		/* still apply RS600's default setting which is 1. */
+		set_reg_field_value(value, 1,
+			HDMI_AUDIO_PACKET_CONTROL,
+			HDMI_AUDIO_DELAY_EN);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_AUDIO_PACKET_CONTROL */
+	{
+		addr = mmAFMT_AUDIO_PACKET_CONTROL + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 1,
+			AFMT_AUDIO_PACKET_CONTROL,
+			AFMT_60958_CS_UPDATE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_AUDIO_PACKET_CONTROL2 */
+	{
+		addr = mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 0,
+				AFMT_AUDIO_PACKET_CONTROL2,
+				AFMT_AUDIO_LAYOUT_OVRD);
+
+		/*Register field changed.*/
+		set_reg_field_value(value, 0,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_60958_OSF_OVRD);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* HDMI_ACR_PACKET_CONTROL */
+	{
+		addr = mmHDMI_ACR_PACKET_CONTROL + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 1,
+			HDMI_ACR_PACKET_CONTROL,
+			HDMI_ACR_AUTO_SEND);
+
+		/* Set HDMI_ACR_SOURCE to 0, to use hardwre
+		 *  computed CTS values.*/
+		set_reg_field_value(value, 0,
+			HDMI_ACR_PACKET_CONTROL,
+			HDMI_ACR_SOURCE);
+
+		/* For now clear HDMI_ACR_AUDIO_PRIORITY =>ACR packet has
+		higher priority over Audio Sample */
+		set_reg_field_value(value, 0,
+			HDMI_ACR_PACKET_CONTROL,
+			HDMI_ACR_AUDIO_PRIORITY);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* Program audio clock sample/regeneration parameters */
+	if (dal_audio_hw_ctx_get_audio_clock_info(
+		hw_ctx,
+		crtc_info->color_depth,
+		crtc_info->requested_pixel_clock,
+		crtc_info->calculated_pixel_clock,
+		&audio_clock_info)) {
+
+		/* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */
+		{
+			addr = mmHDMI_ACR_32_0 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+
+			set_reg_field_value(value, audio_clock_info.cts_32khz,
+				HDMI_ACR_32_0,
+				HDMI_ACR_CTS_32);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */
+		{
+			addr = mmHDMI_ACR_32_1 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.n_32khz,
+				HDMI_ACR_32_1,
+				HDMI_ACR_N_32);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */
+		{
+			addr = mmHDMI_ACR_44_0 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.cts_44khz,
+				HDMI_ACR_44_0,
+				HDMI_ACR_CTS_44);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */
+		{
+			addr = mmHDMI_ACR_44_1 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.n_44khz,
+				HDMI_ACR_44_1,
+				HDMI_ACR_N_44);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */
+		{
+			addr = mmHDMI_ACR_48_0 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.cts_48khz,
+				HDMI_ACR_48_0,
+				HDMI_ACR_CTS_48);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */
+		{
+			addr = mmHDMI_ACR_48_1 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.n_48khz,
+				HDMI_ACR_48_1,
+				HDMI_ACR_N_48);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* Video driver cannot know in advance which sample rate will
+		be used by HD Audio driver
+		HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is
+		programmed below in interruppt callback */
+	} /* if */
+
+	/* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK &
+	AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */
+	{
+		addr = mmAFMT_60958_0 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 1,
+			AFMT_60958_0,
+			AFMT_60958_CS_CHANNEL_NUMBER_L);
+
+		 /*HW default */
+		set_reg_field_value(value, 0,
+			AFMT_60958_0,
+			AFMT_60958_CS_CLOCK_ACCURACY);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */
+	{
+		addr = mmAFMT_60958_1 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 2,
+			AFMT_60958_1,
+			AFMT_60958_CS_CHANNEL_NUMBER_R);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/*AFMT_60958_2 now keep this settings until
+	 *  Programming guide comes out*/
+	{
+		addr = mmAFMT_60958_2 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 3,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_2);
+
+		set_reg_field_value(value, 4,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_3);
+
+		set_reg_field_value(value, 5,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_4);
+
+		set_reg_field_value(value, 6,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_5);
+
+		set_reg_field_value(value, 7,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_6);
+
+		set_reg_field_value(value, 8,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_7);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+}
+
+ /* setup DP audio */
+static void setup_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/* --- DP Audio packet configurations --- */
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* ATP Configuration */
+	{
+		addr = mmDP_SEC_AUD_N + engine_offset[engine_id];
+
+		set_reg_field_value(value,
+			DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT,
+			DP_SEC_AUD_N,
+			DP_SEC_AUD_N);
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* Async/auto-calc timestamp mode */
+	{
+		addr = mmDP_SEC_TIMESTAMP +
+			engine_offset[engine_id];
+
+		value = 0;
+
+		set_reg_field_value(value,
+			DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC,
+			DP_SEC_TIMESTAMP,
+			DP_SEC_TIMESTAMP_MODE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* --- The following are the registers
+	 *  copied from the SetupHDMI --- */
+
+
+	/* AFMT_AUDIO_PACKET_CONTROL */
+	{
+		addr = mmAFMT_AUDIO_PACKET_CONTROL +
+			engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value,
+			1,
+			AFMT_AUDIO_PACKET_CONTROL,
+			AFMT_60958_CS_UPDATE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_AUDIO_PACKET_CONTROL2 */
+	{
+		addr =
+			mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value,
+			0,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_AUDIO_LAYOUT_OVRD);
+
+		set_reg_field_value(value,
+			0,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_60958_OSF_OVRD);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_INFOFRAME_CONTROL0 */
+	{
+		addr =
+			mmAFMT_INFOFRAME_CONTROL0 + engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value,
+			1,
+			AFMT_INFOFRAME_CONTROL0,
+			AFMT_AUDIO_INFO_UPDATE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */
+	{
+		addr = mmAFMT_60958_0 + engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value,
+			0,
+			AFMT_60958_0,
+			AFMT_60958_CS_CLOCK_ACCURACY);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+}
+
+ /* setup VCE audio */
+static void setup_vce_audio(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	struct dc_context *ctx = hw_ctx->ctx;
+
+	NOT_IMPLEMENTED();
+
+	/*TODO:
+	const uint32_t addr = mmDOUT_DCE_VCE_CONTROL;
+	uint32_t value = 0;
+
+	value = dal_read_reg(hw_ctx->ctx,
+			addr);
+
+	set_reg_field_value(value,
+		FROM_BASE(hw_ctx)->azalia_stream_id - 1,
+		DOUT_DCE_VCE_CONTROL,
+		DC_VCE_AUDIO_STREAM_SELECT);
+
+	dal_write_reg(hw_ctx->ctx,
+			addr, value);*/
+}
+
+static void enable_afmt_clock(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	bool enable_flag)
+{
+	uint32_t engine_offs = engine_offset[engine_id];
+	uint32_t value;
+	uint32_t count = 0;
+	uint32_t enable = enable_flag ? 1:0;
+
+	/* Enable Audio packets*/
+	value = dm_read_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs);
+
+	/*enable AFMT clock*/
+	set_reg_field_value(value, enable,
+		AFMT_CNTL, AFMT_AUDIO_CLOCK_EN);
+	dm_write_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs, value);
+
+	/*wait for AFMT clock to turn on,
+	 * the expectation is that this
+	 * should complete in 1-2 reads)
+	 */
+	do {
+		/* Wait for 1us between subsequent register reads.*/
+		dm_delay_in_microseconds(hw_ctx->ctx, 1);
+		value = dm_read_reg(hw_ctx->ctx,
+				mmAFMT_CNTL + engine_offs);
+	} while (get_reg_field_value(value,
+				AFMT_CNTL, AFMT_AUDIO_CLOCK_ON) !=
+						enable && count++ < 10);
+}
+
+/* enable Azalia audio */
+static void enable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	uint32_t value;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
+
+	if (get_reg_field_value(value,
+			AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+			AUDIO_ENABLED) != 1)
+		set_reg_field_value(value, 1,
+			AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+			AUDIO_ENABLED);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+		value);
+}
+
+/* disable Azalia audio */
+static void disable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	uint32_t value;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
+
+	set_reg_field_value(value, 0,
+		AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+		AUDIO_ENABLED);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+		value);
+}
+
+/* enable DP audio */
+static void enable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id];
+
+	uint32_t value;
+
+	/* Enable Audio packets */
+	value = dm_read_reg(hw_ctx->ctx, addr);
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_ASP_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+
+	/* Program the ATP and AIP next */
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_ATP_ENABLE);
+
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_AIP_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+
+	/* Program STREAM_ENABLE after all the other enables. */
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_STREAM_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+/* disable DP audio */
+static void disable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id];
+
+	uint32_t value;
+
+	/* Disable Audio packets */
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_ASP_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_ATP_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_AIP_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_ACM_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_STREAM_ENABLE);
+
+	/* This register shared with encoder info frame. Therefore we need to
+	keep master enabled if at least on of the fields is not 0 */
+	if (value != 0)
+		set_reg_field_value(value, 1,
+			DP_SEC_CNTL,
+			DP_SEC_STREAM_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+static void configure_azalia(
+	const struct hw_ctx_audio *hw_ctx,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_info *audio_info)
+{
+	uint32_t speakers = audio_info->flags.info.ALLSPEAKERS;
+	uint32_t value;
+	uint32_t field = 0;
+	enum audio_format_code audio_format_code;
+	uint32_t format_index;
+	uint32_t index;
+	bool is_ac3_supported = false;
+	bool is_audio_format_supported = false;
+	union audio_sample_rates sample_rate;
+	uint32_t strlen = 0;
+
+	/* Speaker Allocation */
+	/*
+	uint32_t value;
+	uint32_t field = 0;*/
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
+
+	set_reg_field_value(value,
+		speakers,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		SPEAKER_ALLOCATION);
+
+	/* LFE_PLAYBACK_LEVEL = LFEPBL
+	 * LFEPBL = 0 : Unknown or refer to other information
+	 * LFEPBL = 1 : 0dB playback
+	 * LFEPBL = 2 : +10dB playback
+	 * LFE_BL = 3 : Reserved
+	 */
+	set_reg_field_value(value,
+		0,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		LFE_PLAYBACK_LEVEL);
+
+	set_reg_field_value(value,
+		0,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		HDMI_CONNECTION);
+
+	set_reg_field_value(value,
+		0,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		DP_CONNECTION);
+
+	field = get_reg_field_value(value,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			EXTRA_CONNECTION_INFO);
+
+	field &= ~0x1;
+
+	set_reg_field_value(value,
+		field,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		EXTRA_CONNECTION_INFO);
+
+	/* set audio for output signal */
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		set_reg_field_value(value,
+			1,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			HDMI_CONNECTION);
+
+		break;
+	case SIGNAL_TYPE_WIRELESS: {
+		/*LSB used for "is wireless" flag */
+		field = 0;
+		field = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		EXTRA_CONNECTION_INFO);
+		field |= 0x1;
+		set_reg_field_value(value,
+			field,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			EXTRA_CONNECTION_INFO);
+
+		set_reg_field_value(value,
+			1,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			HDMI_CONNECTION);
+
+		}
+		break;
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		set_reg_field_value(value,
+			1,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			DP_CONNECTION);
+
+		break;
+	default:
+		break;
+	}
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		value);
+
+	/* Wireless Display identification */
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION);
+
+	set_reg_field_value(value,
+		signal == SIGNAL_TYPE_WIRELESS ? 1 : 0,
+		AZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION,
+		WIRELESS_DISPLAY_IDENTIFICATION);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION,
+		value);
+
+	/*  Audio Descriptors   */
+	/* pass through all formats */
+	for (format_index = 0; format_index < AUDIO_FORMAT_CODE_COUNT;
+			format_index++) {
+		audio_format_code =
+			(AUDIO_FORMAT_CODE_FIRST + format_index);
+
+		/* those are unsupported, skip programming */
+		if (audio_format_code == AUDIO_FORMAT_CODE_1BITAUDIO ||
+			audio_format_code == AUDIO_FORMAT_CODE_DST)
+			continue;
+
+		value = 0;
+
+		/* check if supported */
+		is_audio_format_supported =
+			dal_audio_hw_ctx_is_audio_format_supported(
+				hw_ctx,
+				audio_info,
+				audio_format_code, &index);
+
+		if (is_audio_format_supported) {
+			const struct audio_mode *audio_mode =
+					&audio_info->modes[index];
+			union audio_sample_rates sample_rates =
+					audio_mode->sample_rates;
+			uint8_t byte2 = audio_mode->max_bit_rate;
+
+			/* adjust specific properties */
+			switch (audio_format_code) {
+			case AUDIO_FORMAT_CODE_LINEARPCM: {
+				dal_hw_ctx_audio_check_audio_bandwidth(
+					hw_ctx,
+					crtc_info,
+					audio_mode->channel_count,
+					signal,
+					&sample_rates);
+
+				byte2 = audio_mode->sample_size;
+
+				set_reg_field_value(value,
+				sample_rates.all,
+		AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+				SUPPORTED_FREQUENCIES_STEREO);
+
+				}
+				break;
+			case AUDIO_FORMAT_CODE_AC3:
+				is_ac3_supported = true;
+				break;
+			case AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS:
+			case AUDIO_FORMAT_CODE_DTS_HD:
+			case AUDIO_FORMAT_CODE_MAT_MLP:
+			case AUDIO_FORMAT_CODE_DST:
+			case AUDIO_FORMAT_CODE_WMAPRO:
+				byte2 = audio_mode->vendor_specific;
+				break;
+			default:
+				break;
+			}
+
+			/* fill audio format data */
+			set_reg_field_value(value,
+			audio_mode->channel_count - 1,
+			AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+			MAX_CHANNELS);
+
+			set_reg_field_value(value,
+			sample_rates.all,
+			AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+			SUPPORTED_FREQUENCIES);
+
+			set_reg_field_value(value,
+			byte2,
+			AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+			DESCRIPTOR_BYTE_2);
+
+		} /* if */
+
+		write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 +
+		format_index,
+		value);
+	} /* for */
+
+	if (is_ac3_supported)
+		dm_write_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS,
+		0x05);
+
+	/* check for 192khz/8-Ch support for HBR requirements */
+	sample_rate.all = 0;
+	sample_rate.rate.RATE_192 = 1;
+	dal_hw_ctx_audio_check_audio_bandwidth(
+		hw_ctx,
+		crtc_info,
+		8,
+		signal,
+		&sample_rate);
+
+	set_high_bit_rate_capable(hw_ctx, sample_rate.rate.RATE_192);
+
+	/* Audio and Video Lipsync */
+	set_video_latency(hw_ctx, audio_info->video_latency);
+	set_audio_latency(hw_ctx, audio_info->audio_latency);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->manufacture_id,
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
+		MANUFACTURER_ID);
+
+	set_reg_field_value(value, audio_info->product_id,
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
+		PRODUCT_ID);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
+		value);
+
+
+	value = 0;
+
+	/*get display name string length */
+	while (audio_info->display_name[strlen++] != '\0') {
+		if (strlen >=
+		MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS)
+			break;
+		}
+	set_reg_field_value(value, strlen,
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1,
+		SINK_DESCRIPTION_LEN);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1,
+		value);
+
+
+	/*
+	*write the port ID:
+	*PORT_ID0 = display index
+	*PORT_ID1 = 16bit BDF
+	*(format MSB->LSB: 8bit Bus, 5bit Device, 3bit Function)
+	*/
+
+	value = 0;
+
+	set_reg_field_value(value, audio_info->port_id[0],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2,
+		PORT_ID0);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2,
+		value);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->port_id[1],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3,
+		PORT_ID1);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3,
+		value);
+
+	/*write the 18 char monitor string */
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[0],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION0);
+
+	set_reg_field_value(value, audio_info->display_name[1],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION1);
+
+	set_reg_field_value(value, audio_info->display_name[2],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION2);
+
+	set_reg_field_value(value, audio_info->display_name[3],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION3);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		value);
+
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[4],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION4);
+
+	set_reg_field_value(value, audio_info->display_name[5],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION5);
+
+	set_reg_field_value(value, audio_info->display_name[6],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION6);
+
+	set_reg_field_value(value, audio_info->display_name[7],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION7);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		value);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[8],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION8);
+
+	set_reg_field_value(value, audio_info->display_name[9],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION9);
+
+	set_reg_field_value(value, audio_info->display_name[10],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION10);
+
+	set_reg_field_value(value, audio_info->display_name[11],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION11);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		value);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[12],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION12);
+
+	set_reg_field_value(value, audio_info->display_name[13],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION13);
+
+	set_reg_field_value(value, audio_info->display_name[14],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION14);
+
+	set_reg_field_value(value, audio_info->display_name[15],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION15);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		value);
+
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[16],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
+		DESCRIPTION16);
+
+	set_reg_field_value(value, audio_info->display_name[17],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
+		DESCRIPTION17);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
+		value);
+
+}
+
+/* setup Azalia HW block */
+static void setup_azalia(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info,
+	const struct audio_info *audio_info)
+{
+	uint32_t speakers = 0;
+	uint32_t channels = 0;
+
+	if (audio_info == NULL)
+		/* This should not happen.it does so we don't get BSOD*/
+		return;
+
+	speakers = audio_info->flags.info.ALLSPEAKERS;
+	channels = dal_audio_hw_ctx_speakers_to_channels(
+		hw_ctx,
+		audio_info->flags.speaker_flags).all;
+
+	/* setup the audio stream source select (audio -> dig mapping) */
+	{
+		const uint32_t addr =
+			mmAFMT_AUDIO_SRC_CONTROL + engine_offset[engine_id];
+
+		uint32_t value = 0;
+		/*convert one-based index to zero-based */
+		set_reg_field_value(value,
+			FROM_BASE(hw_ctx)->azalia_stream_id - 1,
+			AFMT_AUDIO_SRC_CONTROL,
+			AFMT_AUDIO_SRC_SELECT);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* Channel allocation */
+	{
+		const uint32_t addr =
+			mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id];
+		uint32_t value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value,
+			channels,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_AUDIO_CHANNEL_ENABLE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	configure_azalia(hw_ctx, signal, crtc_info, audio_info);
+}
+
+/* unmute audio */
+static void unmute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL +
+		engine_offset[engine_id];
+
+	uint32_t value = 0;
+
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	set_reg_field_value(value, 1,
+		AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+/* mute audio */
+static void mute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL +
+		engine_offset[engine_id];
+
+	uint32_t value = 0;
+
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	set_reg_field_value(value, 0,
+		AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+/* enable channel splitting mapping */
+static void setup_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	uint32_t value = 0;
+
+	if ((audio_mapping == NULL || audio_mapping->u32all == 0) && enable)
+		return;
+
+
+	value = audio_mapping->u32all;
+
+	if (enable == false)
+		/*0xFFFFFFFF;*/
+		value = MULTI_CHANNEL_SPLIT_NO_ASSO_INFO;
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO,
+		value);
+}
+
+/* get current channel spliting */
+static bool get_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	uint32_t value = 0;
+
+	if (audio_mapping == NULL)
+		return false;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO);
+
+	/*0xFFFFFFFF*/
+	if (get_reg_field_value(value,
+			AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO,
+			ASSOCIATION_INFO) !=
+			MULTI_CHANNEL_SPLIT_NO_ASSO_INFO) {
+		uint32_t multi_channel01_enable = 0;
+		uint32_t multi_channel23_enable = 0;
+		uint32_t multi_channel45_enable = 0;
+		uint32_t multi_channel67_enable = 0;
+		/* get the one we set.*/
+		audio_mapping->u32all = value;
+
+		/* check each enable status*/
+		value = read_indirect_azalia_reg(
+			hw_ctx,
+			ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE);
+
+		multi_channel01_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL01_ENABLE);
+
+		multi_channel23_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL23_ENABLE);
+
+		multi_channel45_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL45_ENABLE);
+
+		multi_channel67_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL67_ENABLE);
+
+		if (multi_channel01_enable == 0 &&
+			multi_channel23_enable == 0 &&
+			multi_channel45_enable == 0 &&
+			multi_channel67_enable == 0)
+			dal_logger_write(hw_ctx->ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_COMPONENT_AUDIO,
+				"Audio driver did not enable multi-channel\n");
+
+		return true;
+	}
+
+	return false;
+}
+
+/* set the payload value for the unsolicited response */
+static void set_unsolicited_response_payload(
+	const struct hw_ctx_audio *hw_ctx,
+	enum audio_payload payload)
+{
+	/* set the payload value for the unsolicited response
+	 Jack presence is not required to be enabled */
+	uint32_t value = 0;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE);
+
+	set_reg_field_value(value, payload,
+		AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE,
+		UNSOLICITED_RESPONSE_PAYLOAD);
+
+	set_reg_field_value(value, 1,
+		AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE,
+		UNSOLICITED_RESPONSE_FORCE);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE,
+		value);
+}
+
+/* initialize HW state */
+static void hw_initialize(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	uint32_t stream_id = FROM_BASE(hw_ctx)->azalia_stream_id;
+	uint32_t addr;
+
+	/* we only need to program the following registers once, so we only do
+	it for the first audio stream.*/
+	if (stream_id != FIRST_AUDIO_STREAM_ID)
+		return;
+
+	/* Suport R5 - 32khz
+	 * Suport R6 - 44.1khz
+	 * Suport R7 - 48khz
+	 */
+	addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES;
+	{
+		uint32_t value;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 0x70,
+		AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES,
+		AUDIO_RATE_CAPABILITIES);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/*Keep alive bit to verify HW block in BU. */
+	addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES;
+	{
+		uint32_t value;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 1,
+		AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES,
+		CLKSTOP);
+
+		set_reg_field_value(value, 1,
+		AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES,
+		EPSS);
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+}
+
+/* Assign GTC group and enable GTC value embedding */
+static void enable_gtc_embedding_with_group(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t group_num,
+	uint32_t audio_latency)
+{
+	/*need to replace the static number with variable */
+	if (group_num <= 6) {
+		uint32_t value = read_indirect_azalia_reg(
+			hw_ctx,
+			ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING);
+
+		set_reg_field_value(
+			value,
+			group_num,
+			AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+			PRESENTATION_TIME_EMBEDDING_GROUP);
+
+		set_reg_field_value(
+			value,
+			1,
+			AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+			PRESENTATION_TIME_EMBEDDING_ENABLE);
+
+		write_indirect_azalia_reg(
+			hw_ctx,
+			ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+			value);
+
+		/*update audio latency to LIPSYNC*/
+		set_audio_latency(hw_ctx, audio_latency);
+	} else {
+		dal_logger_write(
+			hw_ctx->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_COMPONENT_AUDIO,
+			"GTC group number %d is too big",
+			group_num);
+	}
+}
+
+ /* Disable GTC value embedding */
+static void disable_gtc_embedding(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	uint32_t value = 0;
+
+	value = read_indirect_azalia_reg(
+	hw_ctx,
+	ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING);
+
+	set_reg_field_value(value, 0,
+	AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+	PRESENTATION_TIME_EMBEDDING_ENABLE);
+
+	set_reg_field_value(value, 0,
+	AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+	PRESENTATION_TIME_EMBEDDING_GROUP);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+		value);
+}
+
+/* search pixel clock value for Azalia HDMI Audio */
+static bool get_azalia_clock_info_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	if (azalia_clock_info == NULL)
+		return false;
+
+	/* audio_dto_phase= 24 * 10,000;
+	 *   24MHz in [100Hz] units */
+	azalia_clock_info->audio_dto_phase =
+			24 * 10000;
+
+	/* audio_dto_module = PCLKFrequency * 10,000;
+	 *  [khz] -> [100Hz] */
+	azalia_clock_info->audio_dto_module =
+			actual_pixel_clock_in_khz * 10;
+
+	return true;
+}
+
+/* search pixel clock value for Azalia DP Audio */
+static bool get_azalia_clock_info_dp(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t requested_pixel_clock_in_khz,
+	const struct audio_pll_info *pll_info,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	if (pll_info == NULL || azalia_clock_info == NULL)
+		return false;
+
+	/* Reported dpDtoSourceClockInkhz value for
+	 * DCE8 already adjusted for SS, do not need any
+	 * adjustment here anymore
+	 */
+
+	/*audio_dto_phase = 24 * 10,000;
+	 * 24MHz in [100Hz] units */
+	azalia_clock_info->audio_dto_phase = 24 * 10000;
+
+	/*audio_dto_module = dpDtoSourceClockInkhz * 10,000;
+	 *  [khz] ->[100Hz] */
+	azalia_clock_info->audio_dto_module =
+		pll_info->dp_dto_source_clock_in_khz * 10;
+
+	return true;
+}
+
+static const struct hw_ctx_audio_funcs funcs = {
+	.destroy = destroy,
+	.setup_audio_wall_dto =
+		setup_audio_wall_dto,
+	.setup_hdmi_audio =
+		setup_hdmi_audio,
+	.setup_dp_audio = setup_dp_audio,
+	.setup_vce_audio = setup_vce_audio,
+	.enable_azalia_audio =
+		enable_azalia_audio,
+	.disable_azalia_audio =
+		disable_azalia_audio,
+	.enable_dp_audio =
+		enable_dp_audio,
+	.disable_dp_audio =
+		disable_dp_audio,
+	.setup_azalia =
+		setup_azalia,
+	.disable_az_clock_gating = NULL,
+	.unmute_azalia_audio =
+		unmute_azalia_audio,
+	.mute_azalia_audio =
+		mute_azalia_audio,
+	.setup_channel_splitting_mapping =
+		setup_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.hw_initialize =
+		hw_initialize,
+	.enable_gtc_embedding_with_group =
+		enable_gtc_embedding_with_group,
+	.disable_gtc_embedding =
+		disable_gtc_embedding,
+	.get_azalia_clock_info_hdmi =
+		get_azalia_clock_info_hdmi,
+	.get_azalia_clock_info_dp =
+		get_azalia_clock_info_dp,
+	.enable_afmt_clock = enable_afmt_clock
+};
+
+static bool construct(
+	struct hw_ctx_audio_dce110 *hw_ctx,
+	uint8_t azalia_stream_id,
+	struct dc_context *ctx)
+{
+	struct hw_ctx_audio *base = &hw_ctx->base;
+
+	if (!dal_audio_construct_hw_ctx_audio(base))
+		return false;
+
+	base->funcs = &funcs;
+
+	/* save audio endpoint or dig front for current dce110 audio object */
+	hw_ctx->azalia_stream_id = azalia_stream_id;
+	hw_ctx->base.ctx = ctx;
+
+	/* azalia audio endpoints register offsets. azalia is associated with
+	DIG front. save AUDIO register offset */
+	switch (azalia_stream_id) {
+	case 1: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	case 2: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	case 3: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	case 4: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	default:
+		dal_logger_write(
+			hw_ctx->base.ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_AUDIO,
+			"Invalid Azalia stream ID!");
+		break;
+	}
+
+	return true;
+}
+
+/* audio_dce110 is derived from audio directly, not via dce80  */
+struct hw_ctx_audio *dal_hw_ctx_audio_dce110_create(
+	struct dc_context *ctx,
+	uint32_t azalia_stream_id)
+{
+	/* allocate memory for struc hw_ctx_audio_dce110 */
+	struct hw_ctx_audio_dce110 *hw_ctx_dce110 =
+			dm_alloc(ctx, sizeof(struct hw_ctx_audio_dce110));
+
+	if (!hw_ctx_dce110) {
+		ASSERT_CRITICAL(hw_ctx_dce110);
+		return NULL;
+	}
+
+	/*return pointer to hw_ctx_audio back to caller  -- audio object */
+	if (construct(
+			hw_ctx_dce110, azalia_stream_id, ctx))
+		return &hw_ctx_dce110->base;
+
+	dal_logger_write(
+		ctx->logger,
+		LOG_MAJOR_ERROR,
+		LOG_MINOR_COMPONENT_AUDIO,
+		"Failed to create hw_ctx_audio for DCE11\n");
+
+
+	dm_free(ctx, hw_ctx_dce110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
new file mode 100644
index 000000000000..1ad3826aeb9f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_AUDIO_DCE110_H__
+#define __DAL_HW_CTX_AUDIO_DCE110_H__
+
+#include "audio/hw_ctx_audio.h"
+
+struct hw_ctx_audio_dce110 {
+	struct hw_ctx_audio base;
+
+	/* azalia stream id 1 based indexing, corresponding to audio GO enumId*/
+	uint32_t azalia_stream_id;
+
+	/* azalia stream endpoint register offsets */
+	struct azalia_reg_offsets az_mm_reg_offsets;
+
+	/* audio encoder block MM register offset -- associate with DIG FRONT */
+};
+
+struct hw_ctx_audio *dal_hw_ctx_audio_dce110_create(
+	struct dc_context *ctx,
+	uint32_t azalia_stream_id);
+
+#endif  /* __DAL_HW_CTX_AUDIO_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
new file mode 100644
index 000000000000..58207f53bff1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
@@ -0,0 +1,771 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "hw_ctx_audio.h"
+
+/* 25.2MHz/1.001*/
+/* 25.2MHz/1.001*/
+/* 25.2MHz*/
+/* 27MHz */
+/* 27MHz*1.001*/
+/* 27MHz*1.001*/
+/* 54MHz*/
+/* 54MHz*1.001*/
+/* 74.25MHz/1.001*/
+/* 74.25MHz*/
+/* 148.5MHz/1.001*/
+/* 148.5MHz*/
+
+static const struct audio_clock_info audio_clock_info_table[12] = {
+	{2517, 4576, 28125, 7007, 31250, 6864, 28125},
+	{2518, 4576, 28125, 7007, 31250, 6864, 28125},
+	{2520, 4096, 25200, 6272, 28000, 6144, 25200},
+	{2700, 4096, 27000, 6272, 30000, 6144, 27000},
+	{2702, 4096, 27027, 6272, 30030, 6144, 27027},
+	{2703, 4096, 27027, 6272, 30030, 6144, 27027},
+	{5400, 4096, 54000, 6272, 60000, 6144, 54000},
+	{5405, 4096, 54054, 6272, 60060, 6144, 54054},
+	{7417, 11648, 210937, 17836, 234375, 11648, 140625},
+	{7425, 4096, 74250, 6272, 82500, 6144, 74250},
+	{14835, 11648, 421875, 8918, 234375, 5824, 140625},
+	{14850, 4096, 148500, 6272, 165000, 6144, 148500}
+};
+
+static const struct audio_clock_info audio_clock_info_table_36bpc[12] = {
+	{2517, 9152, 84375, 7007, 48875, 9152, 56250},
+	{2518, 9152, 84375, 7007, 48875, 9152, 56250},
+	{2520, 4096, 37800, 6272, 42000, 6144, 37800},
+	{2700, 4096, 40500, 6272, 45000, 6144, 40500},
+	{2702, 8192, 81081, 6272, 45045, 8192, 54054},
+	{2703, 8192, 81081, 6272, 45045, 8192, 54054},
+	{5400, 4096, 81000, 6272, 90000, 6144, 81000},
+	{5405, 4096, 81081, 6272, 90090, 6144, 81081},
+	{7417, 11648, 316406, 17836, 351562, 11648, 210937},
+	{7425, 4096, 111375, 6272, 123750, 6144, 111375},
+	{14835, 11648, 632812, 17836, 703125, 11648, 421875},
+	{14850, 4096, 222750, 6272, 247500, 6144, 222750}
+};
+
+static const struct audio_clock_info audio_clock_info_table_48bpc[12] = {
+	{2517, 4576, 56250, 7007, 62500, 6864, 56250},
+	{2518, 4576, 56250, 7007, 62500, 6864, 56250},
+	{2520, 4096, 50400, 6272, 56000, 6144, 50400},
+	{2700, 4096, 54000, 6272, 60000, 6144, 54000},
+	{2702, 4096, 54054, 6267, 60060, 8192, 54054},
+	{2703, 4096, 54054, 6272, 60060, 8192, 54054},
+	{5400, 4096, 108000, 6272, 120000, 6144, 108000},
+	{5405, 4096, 108108, 6272, 120120, 6144, 108108},
+	{7417, 11648, 421875, 17836, 468750, 11648, 281250},
+	{7425, 4096, 148500, 6272, 165000, 6144, 148500},
+	{14835, 11648, 843750, 8918, 468750, 11648, 281250},
+	{14850, 4096, 297000, 6272, 330000, 6144, 297000}
+};
+
+
+/***** static function *****/
+
+/*
+ * except of HW context create function, caller will access other functions of
+ * hw ctx via handle hw_ctx. Memory allocation for struct hw_ctx_audio_dce8x
+ * will happen in hw_ctx_audio_dce8x. Memory allocation is done with
+ * dal_audio_create_hw_ctx_audio_dce8x. Memory release is done by caller
+ * via hw_ctx->functions.destroy(). It will finally use destroy() of
+ * hw_ctx_audio_dce8x. Therefore, no memory allocate and release happen
+ * physically at hw ctx base object.
+ */
+static void destroy(
+	struct hw_ctx_audio **ptr)
+{
+	/* Attention!
+	 * You must override this method in derived class */
+}
+
+static void setup_audio_wall_dto(
+	const struct hw_ctx_audio *hw_ctx,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* setup HDMI audio */
+static void setup_hdmi_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	const struct audio_crtc_info *crtc_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+ /* setup DP audio */
+static void setup_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+ /* setup VCE audio */
+static void setup_vce_audio(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* enable Azalia audio */
+static void enable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* disable Azalia audio */
+static void disable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* enable DP audio */
+static void enable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* disable DP audio */
+static void disable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* setup Azalia HW block */
+static void setup_azalia(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info,
+	const struct audio_info *audio_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* unmute audio */
+static void unmute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* mute audio */
+static void mute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* enable channel splitting mapping */
+static void setup_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* get current channel spliting */
+static bool get_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+/* set the payload value for the unsolicited response */
+static void set_unsolicited_response_payload(
+	const struct hw_ctx_audio *hw_ctx,
+	enum audio_payload payload)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* initialize HW state */
+static void hw_initialize(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* Assign GTC group and enable GTC value embedding */
+static void enable_gtc_embedding_with_group(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t groupNum,
+	uint32_t audioLatency)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* Disable GTC value embedding */
+static void disable_gtc_embedding(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* Disable Azalia Clock Gating Feature */
+static void disable_az_clock_gating(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* search pixel clock value for Azalia HDMI Audio */
+static bool get_azalia_clock_info_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+/* search pixel clock value for Azalia DP Audio */
+static bool get_azalia_clock_info_dp(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t requested_pixel_clock_in_khz,
+	const struct audio_pll_info *pll_info,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+
+
+
+
+
+
+
+
+/*****SCOPE : within audio hw context dal-audio-hw-ctx *****/
+
+
+/* check whether specified sample rates can fit into a given timing */
+void dal_hw_ctx_audio_check_audio_bandwidth(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		dal_audio_hw_ctx_check_audio_bandwidth_hdmi(
+			hw_ctx, crtc_info, channel_count, sample_rates);
+		break;
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+		dal_audio_hw_ctx_check_audio_bandwidth_dpsst(
+			hw_ctx, crtc_info, channel_count, sample_rates);
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		dal_audio_hw_ctx_check_audio_bandwidth_dpmst(
+			hw_ctx,  crtc_info, channel_count, sample_rates);
+		break;
+	default:
+		break;
+	}
+}
+
+/*For HDMI, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates)
+{
+	uint32_t samples;
+	uint32_t  h_blank;
+	bool limit_freq_to_48_khz = false;
+	bool limit_freq_to_88_2_khz = false;
+	bool limit_freq_to_96_khz = false;
+	bool limit_freq_to_174_4_khz = false;
+
+	/* For two channels supported return whatever sink support,unmodified*/
+	if (channel_count > 2) {
+
+		/* Based on HDMI spec 1.3 Table 7.5 */
+		if ((crtc_info->requested_pixel_clock <= 27000) &&
+		(crtc_info->v_active <= 576) &&
+		!(crtc_info->interlaced) &&
+		!(crtc_info->pixel_repetition == 2 ||
+		crtc_info->pixel_repetition == 4)) {
+			limit_freq_to_48_khz = true;
+
+		} else if ((crtc_info->requested_pixel_clock <= 27000) &&
+				(crtc_info->v_active <= 576) &&
+				(crtc_info->interlaced) &&
+				(crtc_info->pixel_repetition == 2)) {
+			limit_freq_to_88_2_khz = true;
+
+		} else if ((crtc_info->requested_pixel_clock <= 54000) &&
+				(crtc_info->v_active <= 576) &&
+				!(crtc_info->interlaced)) {
+			limit_freq_to_174_4_khz = true;
+		}
+	}
+
+	/* Also do some calculation for the available Audio Bandwidth for the
+	 * 8 ch (i.e. for the Layout 1 => ch > 2)
+	 */
+	h_blank = crtc_info->h_total - crtc_info->h_active;
+
+	if (crtc_info->pixel_repetition)
+		h_blank *= crtc_info->pixel_repetition;
+
+	/*based on HDMI spec 1.3 Table 7.5 */
+	h_blank -= 58;
+	/*for Control Period */
+	h_blank -= 16;
+
+	samples = h_blank * 10;
+	/* Number of Audio Packets (multiplied by 10) per Line (for 8 ch number
+	 * of Audio samples per line multiplied by 10 - Layout 1)
+	 */
+	 samples /= 32;
+	 samples *= crtc_info->v_active;
+	 /*Number of samples multiplied by 10, per second */
+	 samples *= crtc_info->refresh_rate;
+	 /*Number of Audio samples per second */
+	 samples /= 10;
+
+	 /* @todo do it after deep color is implemented
+	  * 8xx - deep color bandwidth scaling
+	  * Extra bandwidth is avaliable in deep color b/c link runs faster than
+	  * pixel rate. This has the effect of allowing more tmds characters to
+	  * be transmitted during blank
+	  */
+
+	switch (crtc_info->color_depth) {
+	case COLOR_DEPTH_888:
+		samples *= 4;
+		break;
+	case COLOR_DEPTH_101010:
+		samples *= 5;
+		break;
+	case COLOR_DEPTH_121212:
+		samples *= 6;
+		break;
+	default:
+		samples *= 4;
+		break;
+	}
+
+	samples /= 4;
+
+	/*check limitation*/
+	if (samples < 88200)
+		limit_freq_to_48_khz = true;
+	else if (samples < 96000)
+		limit_freq_to_88_2_khz = true;
+	else if (samples < 176400)
+		limit_freq_to_96_khz = true;
+	else if (samples < 192000)
+		limit_freq_to_174_4_khz = true;
+
+	if (sample_rates != NULL) {
+		/* limit frequencies */
+		if (limit_freq_to_174_4_khz)
+			sample_rates->rate.RATE_192 = 0;
+
+		if (limit_freq_to_96_khz) {
+			sample_rates->rate.RATE_192 = 0;
+			sample_rates->rate.RATE_176_4 = 0;
+		}
+		if (limit_freq_to_88_2_khz) {
+			sample_rates->rate.RATE_192 = 0;
+			sample_rates->rate.RATE_176_4 = 0;
+			sample_rates->rate.RATE_96 = 0;
+		}
+		if (limit_freq_to_48_khz) {
+			sample_rates->rate.RATE_192 = 0;
+			sample_rates->rate.RATE_176_4 = 0;
+			sample_rates->rate.RATE_96 = 0;
+			sample_rates->rate.RATE_88_2 = 0;
+		}
+	}
+}
+
+/*For DP SST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpsst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates)
+{
+	/* do nothing */
+}
+
+/*For DP MST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpmst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates)
+{
+	/* do nothing  */
+}
+
+/* calculate max number of Audio packets per line */
+uint32_t dal_audio_hw_ctx_calc_max_audio_packets_per_line(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info)
+{
+	uint32_t max_packets_per_line;
+
+	max_packets_per_line =
+		crtc_info->h_total - crtc_info->h_active;
+
+	if (crtc_info->pixel_repetition)
+		max_packets_per_line *= crtc_info->pixel_repetition;
+
+	/* for other hdmi features */
+	max_packets_per_line -= 58;
+	/* for Control Period */
+	max_packets_per_line -= 16;
+	/* Number of Audio Packets per Line */
+	max_packets_per_line /= 32;
+
+	return max_packets_per_line;
+}
+
+/**
+* speakersToChannels
+*
+* @brief
+*  translate speakers to channels
+*
+*  FL  - Front Left
+*  FR  - Front Right
+*  RL  - Rear Left
+*  RR  - Rear Right
+*  RC  - Rear Center
+*  FC  - Front Center
+*  FLC - Front Left Center
+*  FRC - Front Right Center
+*  RLC - Rear Left Center
+*  RRC - Rear Right Center
+*  LFE - Low Freq Effect
+*
+*               FC
+*          FLC      FRC
+*    FL                    FR
+*
+*                    LFE
+*              ()
+*
+*
+*    RL                    RR
+*          RLC      RRC
+*               RC
+*
+*             ch  8   7   6   5   4   3   2   1
+* 0b00000011      -   -   -   -   -   -   FR  FL
+* 0b00000111      -   -   -   -   -   LFE FR  FL
+* 0b00001011      -   -   -   -   FC  -   FR  FL
+* 0b00001111      -   -   -   -   FC  LFE FR  FL
+* 0b00010011      -   -   -   RC  -   -   FR  FL
+* 0b00010111      -   -   -   RC  -   LFE FR  FL
+* 0b00011011      -   -   -   RC  FC  -   FR  FL
+* 0b00011111      -   -   -   RC  FC  LFE FR  FL
+* 0b00110011      -   -   RR  RL  -   -   FR  FL
+* 0b00110111      -   -   RR  RL  -   LFE FR  FL
+* 0b00111011      -   -   RR  RL  FC  -   FR  FL
+* 0b00111111      -   -   RR  RL  FC  LFE FR  FL
+* 0b01110011      -   RC  RR  RL  -   -   FR  FL
+* 0b01110111      -   RC  RR  RL  -   LFE FR  FL
+* 0b01111011      -   RC  RR  RL  FC  -   FR  FL
+* 0b01111111      -   RC  RR  RL  FC  LFE FR  FL
+* 0b11110011      RRC RLC RR  RL  -   -   FR  FL
+* 0b11110111      RRC RLC RR  RL  -   LFE FR  FL
+* 0b11111011      RRC RLC RR  RL  FC  -   FR  FL
+* 0b11111111      RRC RLC RR  RL  FC  LFE FR  FL
+* 0b11000011      FRC FLC -   -   -   -   FR  FL
+* 0b11000111      FRC FLC -   -   -   LFE FR  FL
+* 0b11001011      FRC FLC -   -   FC  -   FR  FL
+* 0b11001111      FRC FLC -   -   FC  LFE FR  FL
+* 0b11010011      FRC FLC -   RC  -   -   FR  FL
+* 0b11010111      FRC FLC -   RC  -   LFE FR  FL
+* 0b11011011      FRC FLC -   RC  FC  -   FR  FL
+* 0b11011111      FRC FLC -   RC  FC  LFE FR  FL
+* 0b11110011      FRC FLC RR  RL  -   -   FR  FL
+* 0b11110111      FRC FLC RR  RL  -   LFE FR  FL
+* 0b11111011      FRC FLC RR  RL  FC  -   FR  FL
+* 0b11111111      FRC FLC RR  RL  FC  LFE FR  FL
+*
+* @param
+*  speakers - speaker information as it comes from CEA audio block
+*/
+/* translate speakers to channels */
+union audio_cea_channels dal_audio_hw_ctx_speakers_to_channels(
+	const struct hw_ctx_audio *hw_ctx,
+	struct audio_speaker_flags speaker_flags)
+{
+	union audio_cea_channels cea_channels = {0};
+
+	/* these are one to one */
+	cea_channels.channels.FL = speaker_flags.FL_FR;
+	cea_channels.channels.FR = speaker_flags.FL_FR;
+	cea_channels.channels.LFE = speaker_flags.LFE;
+	cea_channels.channels.FC = speaker_flags.FC;
+
+	/* if Rear Left and Right exist move RC speaker to channel 7
+	 * otherwise to channel 5
+	 */
+	if (speaker_flags.RL_RR) {
+		cea_channels.channels.RL_RC = speaker_flags.RL_RR;
+		cea_channels.channels.RR = speaker_flags.RL_RR;
+		cea_channels.channels.RC_RLC_FLC = speaker_flags.RC;
+	} else {
+		cea_channels.channels.RL_RC = speaker_flags.RC;
+	}
+
+	/* FRONT Left Right Center and REAR Left Right Center are exclusive */
+	if (speaker_flags.FLC_FRC) {
+		cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC;
+		cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC;
+	} else {
+		cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC;
+		cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC;
+	}
+
+	return cea_channels;
+}
+
+/* check whether specified audio format supported */
+bool dal_audio_hw_ctx_is_audio_format_supported(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_info *audio_info,
+	enum audio_format_code audio_format_code,
+	uint32_t *format_index)
+{
+	uint32_t index;
+	uint32_t max_channe_index = 0;
+	bool found = false;
+
+	if (audio_info == NULL)
+		return found;
+
+	/* pass through whole array */
+	for (index = 0; index < audio_info->mode_count; index++) {
+		if (audio_info->modes[index].format_code == audio_format_code) {
+			if (found) {
+				/* format has multiply entries, choose one with
+				 *  highst number of channels */
+				if (audio_info->modes[index].channel_count >
+		audio_info->modes[max_channe_index].channel_count) {
+					max_channe_index = index;
+				}
+			} else {
+				/* format found, save it's index */
+				found = true;
+				max_channe_index = index;
+			}
+		}
+	}
+
+	/* return index */
+	if (found && format_index != NULL)
+		*format_index = max_channe_index;
+
+	return found;
+}
+
+/* search pixel clock value for HDMI */
+bool dal_audio_hw_ctx_get_audio_clock_info(
+	const struct hw_ctx_audio *hw_ctx,
+	enum dc_color_depth color_depth,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct audio_clock_info *audio_clock_info)
+{
+	const struct audio_clock_info *clock_info;
+	uint32_t index;
+	uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_in_khz / 10;
+	uint32_t audio_array_size;
+
+	if (audio_clock_info == NULL)
+		return false; /* should not happen */
+
+	switch (color_depth) {
+	case COLOR_DEPTH_161616:
+		clock_info = audio_clock_info_table_48bpc;
+		audio_array_size = ARRAY_SIZE(
+				audio_clock_info_table_48bpc);
+		break;
+	case COLOR_DEPTH_121212:
+		clock_info = audio_clock_info_table_36bpc;
+		audio_array_size = ARRAY_SIZE(
+				audio_clock_info_table_36bpc);
+		break;
+	default:
+		clock_info = audio_clock_info_table;
+		audio_array_size = ARRAY_SIZE(
+				audio_clock_info_table);
+		break;
+	}
+
+	if (clock_info != NULL) {
+		/* search for exact pixel clock in table */
+		for (index = 0; index < audio_array_size; index++) {
+			if (clock_info[index].pixel_clock_in_10khz >
+				crtc_pixel_clock_in_10khz)
+				break;  /* not match */
+			else if (clock_info[index].pixel_clock_in_10khz ==
+					crtc_pixel_clock_in_10khz) {
+				/* match found */
+				if (audio_clock_info != NULL) {
+					*audio_clock_info = clock_info[index];
+					return true;
+				}
+			}
+		}
+	}
+
+
+	/* not found */
+	if (actual_pixel_clock_in_khz == 0)
+		actual_pixel_clock_in_khz = crtc_pixel_clock_in_khz;
+
+	/* See HDMI spec  the table entry under
+	 *  pixel clock of "Other". */
+	audio_clock_info->pixel_clock_in_10khz =
+			actual_pixel_clock_in_khz / 10;
+	audio_clock_info->cts_32khz = actual_pixel_clock_in_khz;
+	audio_clock_info->cts_44khz = actual_pixel_clock_in_khz;
+	audio_clock_info->cts_48khz = actual_pixel_clock_in_khz;
+
+	audio_clock_info->n_32khz = 4096;
+	audio_clock_info->n_44khz = 6272;
+	audio_clock_info->n_48khz = 6144;
+
+	return true;
+}
+
+static const struct hw_ctx_audio_funcs funcs = {
+	.destroy = destroy,
+	.setup_audio_wall_dto =
+		setup_audio_wall_dto,
+	.setup_hdmi_audio =
+		setup_hdmi_audio,
+	.setup_dp_audio = setup_dp_audio,
+	.setup_vce_audio = setup_vce_audio,
+	.enable_azalia_audio =
+		enable_azalia_audio,
+	.disable_azalia_audio =
+		disable_azalia_audio,
+	.enable_dp_audio =
+		enable_dp_audio,
+	.disable_dp_audio =
+		disable_dp_audio,
+	.setup_azalia =
+		setup_azalia,
+	.disable_az_clock_gating =
+		disable_az_clock_gating,
+	.unmute_azalia_audio =
+		unmute_azalia_audio,
+	.mute_azalia_audio =
+		mute_azalia_audio,
+	.setup_channel_splitting_mapping =
+		setup_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.hw_initialize =
+		hw_initialize,
+	.enable_gtc_embedding_with_group =
+		enable_gtc_embedding_with_group,
+	.disable_gtc_embedding =
+		disable_gtc_embedding,
+	.get_azalia_clock_info_hdmi =
+		get_azalia_clock_info_hdmi,
+	.get_azalia_clock_info_dp =
+		get_azalia_clock_info_dp,
+};
+/* --- object creator, destroy, construct, destruct --- */
+
+bool dal_audio_construct_hw_ctx_audio(
+	struct hw_ctx_audio *ctx)
+{
+	ctx->funcs = &funcs;
+
+	/* internal variables */
+
+	return true;
+}
+
+void dal_audio_destruct_hw_ctx_audio(
+	struct hw_ctx_audio *ctx)
+{
+	/* nothing to do */
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
new file mode 100644
index 000000000000..8ab2e5851f91
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_AUDIO_H__
+#define __DAL_HW_CTX_AUDIO_H__
+
+#include "include/audio_interface.h"
+#include "include/link_service_types.h"
+
+struct hw_ctx_audio;
+
+
+struct azalia_reg_offsets {
+	uint32_t azf0endpointx_azalia_f0_codec_endpoint_index;
+	uint32_t azf0endpointx_azalia_f0_codec_endpoint_data;
+};
+
+/***** hook functions *****/
+
+struct hw_ctx_audio_funcs {
+
+	/* functions for hw_ctx creation */
+	void (*destroy)(
+		struct hw_ctx_audio **ptr);
+
+	/***** from dal2 hwcontextaudio.hpp *****/
+
+	void (*setup_audio_wall_dto)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum signal_type signal,
+		const struct audio_crtc_info *crtc_info,
+		const struct audio_pll_info *pll_info);
+
+	/* MM register access  read_register  write_register */
+
+	/***** from dal2 hwcontextaudio_hal.hpp *****/
+
+	/* setup HDMI audio */
+	void (*setup_hdmi_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		const struct audio_crtc_info *crtc_info);
+
+	/* setup DP audio */
+	void (*setup_dp_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* setup VCE audio */
+	void (*setup_vce_audio)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* enable Azalia audio */
+	void (*enable_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* disable Azalia audio */
+	void (*disable_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* enable DP audio */
+	void (*enable_dp_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* disable DP audio */
+	void (*disable_dp_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* setup Azalia HW block */
+	void (*setup_azalia)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		enum signal_type signal,
+		const struct audio_crtc_info *crtc_info,
+		const struct audio_pll_info *pll_info,
+		const struct audio_info *audio_info);
+
+	/* unmute audio */
+	void (*unmute_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* mute audio */
+	void (*mute_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* enable channel splitting mapping */
+	void (*setup_channel_splitting_mapping)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		enum signal_type signal,
+		const struct audio_channel_associate_info *audio_mapping,
+		bool enable);
+
+	/* get current channel spliting */
+	bool (*get_channel_splitting_mapping)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		struct audio_channel_associate_info *audio_mapping);
+
+	/* set the payload value for the unsolicited response */
+	void (*set_unsolicited_response_payload)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum audio_payload payload);
+
+	/* initialize HW state */
+	void (*hw_initialize)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* check_audio_bandwidth */
+
+	/* Assign GTC group and enable GTC value embedding */
+	void (*enable_gtc_embedding_with_group)(
+		const struct hw_ctx_audio *hw_ctx,
+		uint32_t groupNum,
+		uint32_t audioLatency);
+
+	/* Disable GTC value embedding */
+	void (*disable_gtc_embedding)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* Disable Azalia Clock Gating Feature */
+	void (*disable_az_clock_gating)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* ~~~~  protected: ~~~~*/
+
+	/* calc_max_audio_packets_per_line */
+	/* speakers_to_channels */
+	/* is_audio_format_supported */
+	/* get_audio_clock_info */
+
+	/* search pixel clock value for Azalia HDMI Audio */
+	bool (*get_azalia_clock_info_hdmi)(
+		const struct hw_ctx_audio *hw_ctx,
+		uint32_t crtc_pixel_clock_in_khz,
+		uint32_t actual_pixel_clock_in_khz,
+		struct azalia_clock_info *azalia_clock_info);
+
+	/* search pixel clock value for Azalia DP Audio */
+	bool (*get_azalia_clock_info_dp)(
+		const struct hw_ctx_audio *hw_ctx,
+		uint32_t requested_pixel_clock_in_khz,
+		const struct audio_pll_info *pll_info,
+		struct azalia_clock_info *azalia_clock_info);
+
+	void (*enable_afmt_clock)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		bool enable);
+
+	/* @@@@   private:  @@@@  */
+
+	/* check_audio_bandwidth_hdmi  */
+	/* check_audio_bandwidth_dpsst */
+	/* check_audio_bandwidth_dpmst */
+
+};
+
+
+struct hw_ctx_audio {
+	const struct hw_ctx_audio_funcs *funcs;
+	struct dc_context *ctx;
+
+	/*audio_clock_infoTable[12];
+	 *audio_clock_infoTable_36bpc[12];
+	 *audio_clock_infoTable_48bpc[12];
+	 *used by hw_ctx_audio.c file only. Will declare as static array
+	 *azaliaclockinfoTable[12]  -- not used
+	 *BusNumberMask;   BusNumberShift; DeviceNumberMask;
+	 *not used by dce6 and after
+	 */
+};
+
+
+
+/* --- object construct, destruct --- */
+
+/*
+ *called by derived audio object for specific ASIC. In case no derived object,
+ *these two functions do not need exposed.
+ */
+bool dal_audio_construct_hw_ctx_audio(
+	struct hw_ctx_audio *hw_ctx);
+
+void dal_audio_destruct_hw_ctx_audio(
+	struct hw_ctx_audio *hw_ctx);
+
+/*
+ *creator of audio HW context will be implemented by specific ASIC object only.
+ *Top base or interface object does not have implementation of creator.
+ */
+
+
+/* --- functions called by audio hw context itself --- */
+
+/* MM register access */
+/*read_register  - dal_read_reg */
+/*write_register - dal_write_reg*/
+
+
+/*check whether specified sample rates can fit into a given timing */
+void dal_hw_ctx_audio_check_audio_bandwidth(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates);
+
+/*For HDMI, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates);
+
+/*For DPSST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpsst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates);
+
+/*For DPMST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpmst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates);
+
+/* calculate max number of Audio packets per line */
+uint32_t dal_audio_hw_ctx_calc_max_audio_packets_per_line(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info);
+
+/* translate speakers to channels */
+union audio_cea_channels dal_audio_hw_ctx_speakers_to_channels(
+	const struct hw_ctx_audio *hw_ctx,
+	struct audio_speaker_flags speaker_flags);
+
+/* check whether specified audio format supported */
+bool dal_audio_hw_ctx_is_audio_format_supported(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_info *audio_info,
+	enum audio_format_code audio_format_code,
+	uint32_t *format_index);
+
+/* search pixel clock value for HDMI */
+bool dal_audio_hw_ctx_get_audio_clock_info(
+	const struct hw_ctx_audio *hw_ctx,
+	enum dc_color_depth color_depth,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct audio_clock_info *audio_clock_info);
+
+
+#endif  /* __DAL_HW_CTX_AUDIO_H__ */
+
