All of lore.kernel.org
 help / color / mirror / Atom feed
From: Harry Wentland <harry.wentland@amd.com>
To: dri-devel@lists.freedesktop.org
Subject: [PATCH v2 08/26] drm/amd/dal: I2C Aux Manager
Date: Tue, 16 Feb 2016 17:27:48 -0500	[thread overview]
Message-ID: <cfa0de41e13f5afb8e1368ea127b6bbe7c568e9a.1455660367.git.harry.wentland@amd.com> (raw)
In-Reply-To: <cover.1455660366.git.harry.wentland@amd.com>

Implements low-level communication layer over I2C and Aux lines using
GPIO handles.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile         |  33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c     | 567 ++++++++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h     | 119 +++
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c   | 788 +++++++++++++++++
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h   |  56 ++
 .../i2caux/dce110/i2c_generic_hw_engine_dce110.h   |  25 +
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c    | 954 +++++++++++++++++++++
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h    |  58 ++
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c    | 172 ++++
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h    |  43 +
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c   | 266 ++++++
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h   |  39 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.c    | 112 +++
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.h    |  33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h         | 129 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c    |  67 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c     | 121 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h     | 113 +++
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c  | 286 ++++++
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h  |  77 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c  | 246 ++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h  |  80 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c  | 614 +++++++++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h  |  81 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c         | 529 ++++++++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h         | 123 +++
 26 files changed, 5731 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h

diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile b/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
new file mode 100644
index 000000000000..390d83d649f5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
@@ -0,0 +1,33 @@
+#
+# Makefile for the 'i2c' sub-component of DAL.
+# It provides the control and status of HW i2c engine of the adapter.
+
+I2CAUX = aux_engine.o engine_base.o i2caux.o i2c_engine.o \
+	 i2c_generic_hw_engine.o i2c_hw_engine.o i2c_sw_engine.o
+
+AMD_DAL_I2CAUX = $(addprefix $(AMDDALPATH)/dc/i2caux/,$(I2CAUX))
+
+AMD_DAL_FILES += $(AMD_DAL_I2CAUX)
+
+
+###############################################################################
+# DCE 11x family
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+I2CAUX_DCE110 = i2caux_dce110.o i2c_sw_engine_dce110.o i2c_hw_engine_dce110.o \
+	aux_engine_dce110.o
+
+AMD_DAL_I2CAUX_DCE110 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce110/,$(I2CAUX_DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_I2CAUX_DCE110)
+endif
+
+###############################################################################
+# Diagnostics on FPGA
+###############################################################################
+I2CAUX_DIAG = i2caux_diag.o
+
+AMD_DAL_I2CAUX_DIAG = $(addprefix $(AMDDALPATH)/dc/i2caux/diagnostics/,$(I2CAUX_DIAG))
+
+AMD_DAL_FILES += $(AMD_DAL_I2CAUX_DIAG)
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
new file mode 100644
index 000000000000..7042d10ee7dc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
@@ -0,0 +1,567 @@
+/*
+ * 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "aux_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "include/link_service_types.h"
+
+/*
+ * This unit
+ */
+
+enum {
+	AUX_INVALID_REPLY_RETRY_COUNTER = 1,
+	AUX_TIMED_OUT_RETRY_COUNTER = 2,
+	AUX_DEFER_RETRY_COUNTER = 6
+};
+
+#define FROM_ENGINE(ptr) \
+	container_of((ptr), struct aux_engine, base)
+
+enum i2caux_engine_type dal_aux_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_AUX;
+}
+
+bool dal_aux_engine_acquire(
+	struct engine *engine,
+	struct ddc *ddc)
+{
+	struct aux_engine *aux_engine = FROM_ENGINE(engine);
+
+	enum gpio_result result;
+
+	result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
+		GPIO_DDC_CONFIG_TYPE_MODE_AUX);
+
+	if (result != GPIO_RESULT_OK)
+		return false;
+
+	if (!aux_engine->funcs->acquire_engine(aux_engine)) {
+		dal_ddc_close(ddc);
+		return false;
+	}
+
+	engine->ddc = ddc;
+
+	return true;
+}
+
+struct read_command_context {
+	uint8_t *buffer;
+	uint8_t current_read_length;
+	uint32_t offset;
+	enum i2caux_transaction_status status;
+
+	struct aux_request_transaction_data request;
+	struct aux_reply_transaction_data reply;
+
+	uint8_t returned_byte;
+
+	uint32_t timed_out_retry_aux;
+	uint32_t invalid_reply_retry_aux;
+	uint32_t defer_retry_aux;
+	uint32_t defer_retry_i2c;
+	uint32_t invalid_reply_retry_aux_on_ack;
+
+	bool transaction_complete;
+	bool operation_succeeded;
+};
+
+static void process_read_reply(
+	struct aux_engine *engine,
+	struct read_command_context *ctx)
+{
+	engine->funcs->process_channel_reply(engine, &ctx->reply);
+
+	switch (ctx->reply.status) {
+	case AUX_TRANSACTION_REPLY_AUX_ACK:
+		ctx->defer_retry_aux = 0;
+		if (ctx->returned_byte > ctx->current_read_length) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else if (ctx->returned_byte < ctx->current_read_length) {
+			ctx->current_read_length -= ctx->returned_byte;
+
+			ctx->offset += ctx->returned_byte;
+
+			++ctx->invalid_reply_retry_aux_on_ack;
+
+			if (ctx->invalid_reply_retry_aux_on_ack >
+				AUX_INVALID_REPLY_RETRY_COUNTER) {
+				ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+				ctx->operation_succeeded = false;
+			}
+		} else {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+			ctx->transaction_complete = true;
+			ctx->operation_succeeded = true;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_NACK:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+		ctx->operation_succeeded = false;
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_DEFER:
+		++ctx->defer_retry_aux;
+
+		if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_I2C_DEFER:
+		ctx->defer_retry_aux = 0;
+
+		++ctx->defer_retry_i2c;
+
+		if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static void process_read_request(
+	struct aux_engine *engine,
+	struct read_command_context *ctx)
+{
+	enum aux_channel_operation_result operation_result;
+
+	engine->funcs->submit_channel_request(engine, &ctx->request);
+
+	operation_result = engine->funcs->get_channel_status(
+		engine, &ctx->returned_byte);
+
+	switch (operation_result) {
+	case AUX_CHANNEL_OPERATION_SUCCEEDED:
+		if (ctx->returned_byte > ctx->current_read_length) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else {
+			ctx->timed_out_retry_aux = 0;
+			ctx->invalid_reply_retry_aux = 0;
+
+			ctx->reply.length = ctx->returned_byte;
+			ctx->reply.data = ctx->buffer;
+
+			process_read_reply(engine, ctx);
+		}
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
+		++ctx->invalid_reply_retry_aux;
+
+		if (ctx->invalid_reply_retry_aux >
+			AUX_INVALID_REPLY_RETRY_COUNTER) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else
+			dm_delay_in_microseconds(engine->base.ctx, 400);
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
+		++ctx->timed_out_retry_aux;
+
+		if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		} else {
+			/* DP 1.2a, table 2-58:
+			 * "S3: AUX Request CMD PENDING:
+			 * retry 3 times, with 400usec wait on each"
+			 * The HW timeout is set to 550usec,
+			 * so we should not wait here */
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static bool read_command(
+	struct aux_engine *engine,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction)
+{
+	struct read_command_context ctx;
+
+	ctx.buffer = request->payload.data;
+	ctx.current_read_length = request->payload.length;
+	ctx.offset = 0;
+	ctx.timed_out_retry_aux = 0;
+	ctx.invalid_reply_retry_aux = 0;
+	ctx.defer_retry_aux = 0;
+	ctx.defer_retry_i2c = 0;
+	ctx.invalid_reply_retry_aux_on_ack = 0;
+	ctx.transaction_complete = false;
+	ctx.operation_succeeded = true;
+
+	if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_DP;
+		ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ;
+		ctx.request.address = request->payload.address;
+	} else if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
+		ctx.request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_READ;
+		ctx.request.address = request->payload.address >> 1;
+	} else {
+		/* in DAL2, there was no return in such case */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	ctx.request.delay = 0;
+
+	do {
+		dm_memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length);
+
+		ctx.request.data = ctx.buffer + ctx.offset;
+		ctx.request.length = ctx.current_read_length;
+
+		process_read_request(engine, &ctx);
+
+		request->status = ctx.status;
+
+		if (ctx.operation_succeeded && !ctx.transaction_complete)
+			if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
+				dm_sleep_in_milliseconds(engine->base.ctx, engine->delay);
+	} while (ctx.operation_succeeded && !ctx.transaction_complete);
+
+	return ctx.operation_succeeded;
+}
+
+struct write_command_context {
+	bool mot;
+
+	uint8_t *buffer;
+	uint8_t current_write_length;
+	enum i2caux_transaction_status status;
+
+	struct aux_request_transaction_data request;
+	struct aux_reply_transaction_data reply;
+
+	uint8_t returned_byte;
+
+	uint32_t timed_out_retry_aux;
+	uint32_t invalid_reply_retry_aux;
+	uint32_t defer_retry_aux;
+	uint32_t defer_retry_i2c;
+	uint32_t max_defer_retry;
+	uint32_t ack_m_retry;
+
+	uint8_t reply_data[DEFAULT_AUX_MAX_DATA_SIZE];
+
+	bool transaction_complete;
+	bool operation_succeeded;
+};
+
+static void process_write_reply(
+	struct aux_engine *engine,
+	struct write_command_context *ctx)
+{
+	engine->funcs->process_channel_reply(engine, &ctx->reply);
+
+	switch (ctx->reply.status) {
+	case AUX_TRANSACTION_REPLY_AUX_ACK:
+		ctx->operation_succeeded = true;
+
+		if (ctx->returned_byte) {
+			ctx->request.action = ctx->mot ?
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
+
+			ctx->current_write_length = 0;
+
+			++ctx->ack_m_retry;
+
+			if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) {
+				ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+				ctx->operation_succeeded = false;
+			} else
+				dm_delay_in_microseconds(engine->base.ctx, 300);
+		} else {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+			ctx->defer_retry_aux = 0;
+			ctx->ack_m_retry = 0;
+			ctx->transaction_complete = true;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_NACK:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+		ctx->operation_succeeded = false;
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_DEFER:
+		++ctx->defer_retry_aux;
+
+		if (ctx->defer_retry_aux > ctx->max_defer_retry) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_I2C_DEFER:
+		ctx->defer_retry_aux = 0;
+		ctx->current_write_length = 0;
+
+		ctx->request.action = ctx->mot ?
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
+
+		++ctx->defer_retry_i2c;
+
+		if (ctx->defer_retry_i2c > ctx->max_defer_retry) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static void process_write_request(
+	struct aux_engine *engine,
+	struct write_command_context *ctx)
+{
+	enum aux_channel_operation_result operation_result;
+
+	engine->funcs->submit_channel_request(engine, &ctx->request);
+
+	operation_result = engine->funcs->get_channel_status(
+		engine, &ctx->returned_byte);
+
+	switch (operation_result) {
+	case AUX_CHANNEL_OPERATION_SUCCEEDED:
+		ctx->timed_out_retry_aux = 0;
+		ctx->invalid_reply_retry_aux = 0;
+
+		ctx->reply.length = ctx->returned_byte;
+		ctx->reply.data = ctx->reply_data;
+
+		process_write_reply(engine, ctx);
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
+		++ctx->invalid_reply_retry_aux;
+
+		if (ctx->invalid_reply_retry_aux >
+			AUX_INVALID_REPLY_RETRY_COUNTER) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else
+			dm_delay_in_microseconds(engine->base.ctx, 400);
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
+		++ctx->timed_out_retry_aux;
+
+		if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		} else {
+			/* DP 1.2a, table 2-58:
+			 * "S3: AUX Request CMD PENDING:
+			 * retry 3 times, with 400usec wait on each"
+			 * The HW timeout is set to 550usec,
+			 * so we should not wait here */
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static bool write_command(
+	struct aux_engine *engine,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction)
+{
+	struct write_command_context ctx;
+
+	ctx.mot = middle_of_transaction;
+	ctx.buffer = request->payload.data;
+	ctx.current_write_length = request->payload.length;
+	ctx.timed_out_retry_aux = 0;
+	ctx.invalid_reply_retry_aux = 0;
+	ctx.defer_retry_aux = 0;
+	ctx.defer_retry_i2c = 0;
+	ctx.ack_m_retry = 0;
+	ctx.transaction_complete = false;
+	ctx.operation_succeeded = true;
+
+	if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_DP;
+		ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE;
+		ctx.request.address = request->payload.address;
+	} else if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
+		ctx.request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+		ctx.request.address = request->payload.address >> 1;
+	} else {
+		/* in DAL2, there was no return in such case */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	ctx.request.delay = 0;
+
+	ctx.max_defer_retry =
+		(engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ?
+			engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER;
+
+	do {
+		ctx.request.data = ctx.buffer;
+		ctx.request.length = ctx.current_write_length;
+
+		process_write_request(engine, &ctx);
+
+		request->status = ctx.status;
+
+		if (ctx.operation_succeeded && !ctx.transaction_complete)
+			if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
+				dm_sleep_in_milliseconds(engine->base.ctx, engine->delay);
+	} while (ctx.operation_succeeded && !ctx.transaction_complete);
+
+	return ctx.operation_succeeded;
+}
+
+static bool end_of_transaction_command(
+	struct aux_engine *engine,
+	struct i2caux_transaction_request *request)
+{
+	struct i2caux_transaction_request dummy_request;
+	uint8_t dummy_data;
+
+	/* [tcheng] We only need to send the stop (read with MOT = 0)
+	 * for I2C-over-Aux, not native AUX */
+
+	if (request->payload.address_space !=
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C)
+		return false;
+
+	dummy_request.operation = request->operation;
+	dummy_request.payload.address_space = request->payload.address_space;
+	dummy_request.payload.address = request->payload.address;
+
+	/*
+	 * Add a dummy byte due to some receiver quirk
+	 * where one byte is sent along with MOT = 0.
+	 * Ideally this should be 0.
+	 */
+
+	dummy_request.payload.length = 0;
+	dummy_request.payload.data = &dummy_data;
+
+	if (request->operation == I2CAUX_TRANSACTION_READ)
+		return read_command(engine, &dummy_request, false);
+	else
+		return write_command(engine, &dummy_request, false);
+
+	/* according Syed, it does not need now DoDummyMOT */
+}
+
+bool dal_aux_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction)
+{
+	struct aux_engine *aux_engine = FROM_ENGINE(engine);
+
+	bool result;
+	bool mot_used = true;
+
+	switch (request->operation) {
+	case I2CAUX_TRANSACTION_READ:
+		result = read_command(aux_engine, request, mot_used);
+	break;
+	case I2CAUX_TRANSACTION_WRITE:
+		result = write_command(aux_engine, request, mot_used);
+	break;
+	default:
+		result = false;
+	}
+
+	/* [tcheng]
+	 * need to send stop for the last transaction to free up the AUX
+	 * if the above command fails, this would be the last transaction */
+
+	if (!middle_of_transaction || !result)
+		end_of_transaction_command(aux_engine, request);
+
+	/* mask AUX interrupt */
+
+	return result;
+}
+
+bool dal_aux_engine_construct(
+	struct aux_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2caux_construct_engine(&engine->base, ctx))
+		return false;
+	engine->delay = 0;
+	engine->max_defer_write_retry = 0;
+	return true;
+}
+
+void dal_aux_engine_destruct(
+	struct aux_engine *engine)
+{
+	dal_i2caux_destruct_engine(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
new file mode 100644
index 000000000000..474f5e911f49
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
@@ -0,0 +1,119 @@
+/*
+ * 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_AUX_ENGINE_H__
+#define __DAL_AUX_ENGINE_H__
+
+enum aux_transaction_type {
+	AUX_TRANSACTION_TYPE_DP,
+	AUX_TRANSACTION_TYPE_I2C
+};
+
+struct aux_request_transaction_data {
+	enum aux_transaction_type type;
+	enum i2caux_transaction_action action;
+	/* 20-bit AUX channel transaction address */
+	uint32_t address;
+	/* delay, in 100-microsecond units */
+	uint8_t delay;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum aux_transaction_reply {
+	AUX_TRANSACTION_REPLY_AUX_ACK = 0x00,
+	AUX_TRANSACTION_REPLY_AUX_NACK = 0x01,
+	AUX_TRANSACTION_REPLY_AUX_DEFER = 0x02,
+
+	AUX_TRANSACTION_REPLY_I2C_ACK = 0x00,
+	AUX_TRANSACTION_REPLY_I2C_NACK = 0x10,
+	AUX_TRANSACTION_REPLY_I2C_DEFER = 0x20,
+
+	AUX_TRANSACTION_REPLY_INVALID = 0xFF
+};
+
+struct aux_reply_transaction_data {
+	enum aux_transaction_reply status;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum aux_channel_operation_result {
+	AUX_CHANNEL_OPERATION_SUCCEEDED,
+	AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN,
+	AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY,
+	AUX_CHANNEL_OPERATION_FAILED_TIMEOUT
+};
+
+struct aux_engine;
+
+struct aux_engine_funcs {
+	void (*destroy)(
+		struct aux_engine **ptr);
+	bool (*acquire_engine)(
+		struct aux_engine *engine);
+	void (*configure)(
+		struct aux_engine *engine,
+		union aux_config cfg);
+	bool (*start_gtc_sync)(
+		struct aux_engine *engine);
+	void (*stop_gtc_sync)(
+		struct aux_engine *engine);
+	void (*submit_channel_request)(
+		struct aux_engine *engine,
+		struct aux_request_transaction_data *request);
+	void (*process_channel_reply)(
+		struct aux_engine *engine,
+		struct aux_reply_transaction_data *reply);
+	enum aux_channel_operation_result (*get_channel_status)(
+		struct aux_engine *engine,
+		uint8_t *returned_bytes);
+};
+
+struct aux_engine {
+	struct engine base;
+	const struct aux_engine_funcs *funcs;
+	/* following values are expressed in milliseconds */
+	uint32_t delay;
+	uint32_t max_defer_write_retry;
+};
+
+bool dal_aux_engine_construct(
+	struct aux_engine *engine,
+	struct dc_context *ctx);
+
+void dal_aux_engine_destruct(
+	struct aux_engine *engine);
+bool dal_aux_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction);
+bool dal_aux_engine_acquire(
+	struct engine *ptr,
+	struct ddc *ddc);
+enum i2caux_engine_type dal_aux_engine_get_engine_type(
+	const struct engine *engine);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
new file mode 100644
index 000000000000..f9c55435b5a0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
@@ -0,0 +1,788 @@
+/*
+ * 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../engine.h"
+#include "../aux_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "aux_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct aux_engine *'
+ * to 'struct aux_engine_dce110 *'
+ */
+#define FROM_AUX_ENGINE(ptr) \
+	container_of((ptr), struct aux_engine_dce110, base)
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct aux_engine_dce110 *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base))
+
+static void release_engine(
+	struct engine *engine)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_ENGINE(engine);
+
+	const uint32_t addr = aux_engine->addr.aux_arb_control;
+
+	uint32_t value = dm_read_reg(engine->ctx, addr);
+
+	set_reg_field_value(
+		value,
+		1,
+		AUX_ARB_CONTROL,
+		AUX_SW_DONE_USING_AUX_REG);
+
+	dm_write_reg(engine->ctx, addr, value);
+}
+
+static void destruct(
+	struct aux_engine_dce110 *engine);
+
+static void destroy(
+	struct aux_engine **aux_engine)
+{
+	struct aux_engine_dce110 *engine = FROM_AUX_ENGINE(*aux_engine);
+
+	destruct(engine);
+
+	dm_free((*aux_engine)->base.ctx, engine);
+
+	*aux_engine = NULL;
+}
+
+#define SW_CAN_ACCESS_AUX 1
+
+static bool acquire_engine(
+	struct aux_engine *engine)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+	uint32_t value;
+	uint32_t field;
+
+	/* enable AUX before request SW to access AUX */
+	{
+		const uint32_t addr = aux_engine->addr.aux_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		field = get_reg_field_value(
+				value,
+				AUX_CONTROL,
+				AUX_EN);
+
+		if (field == 0) {
+			uint8_t counter = 0;
+
+			set_reg_field_value(
+				value,
+				1,
+				AUX_CONTROL,
+				AUX_EN);
+
+			/*DP_AUX block as part of the enable sequence*/
+			set_reg_field_value(
+				value,
+				1,
+				AUX_CONTROL,
+				AUX_RESET);
+
+			dm_write_reg(engine->base.ctx, addr, value);
+
+			/*poll HW to make sure reset it done*/
+			do {
+				dm_delay_in_microseconds(engine->base.ctx, 1);
+
+				value = dm_read_reg(engine->base.ctx, addr);
+
+				field = get_reg_field_value(
+						value,
+						AUX_CONTROL,
+						AUX_RESET_DONE);
+
+				counter++;
+
+			} while ((field == 0) && (counter < 11));
+
+			set_reg_field_value(
+				value,
+				0,
+				AUX_CONTROL,
+				AUX_RESET);
+
+			dm_write_reg(engine->base.ctx, addr, value);
+
+			counter = 0;
+
+			do {
+				dm_delay_in_microseconds(engine->base.ctx, 1);
+
+				value = dm_read_reg(engine->base.ctx, addr);
+
+				field = get_reg_field_value(
+						value,
+						AUX_CONTROL,
+						AUX_RESET_DONE);
+
+				counter++;
+
+			} while ((field == 1) && (counter < 11));
+		} /*if (field)*/
+	}
+
+	/* request SW to access AUX */
+	{
+		const uint32_t addr = aux_engine->addr.aux_arb_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_ARB_CONTROL,
+			AUX_SW_USE_AUX_REG_REQ);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		field = get_reg_field_value(
+				value,
+				AUX_ARB_CONTROL,
+				AUX_REG_RW_CNTL_STATUS);
+
+		return field == SW_CAN_ACCESS_AUX;
+	}
+}
+
+static void configure(
+	struct aux_engine *engine,
+	union aux_config cfg)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+
+	const uint32_t addr = aux_engine->addr.aux_control;
+
+	uint32_t value = dm_read_reg(engine->base.ctx, addr);
+
+	set_reg_field_value(
+		value,
+		(0 != cfg.bits.ALLOW_AUX_WHEN_HPD_LOW),
+		AUX_CONTROL,
+		AUX_IGNORE_HPD_DISCON);
+
+	dm_write_reg(engine->base.ctx, addr, value);
+}
+
+static bool start_gtc_sync(
+	struct aux_engine *engine)
+{
+	/*TODO*/
+	return false;
+}
+
+static void stop_gtc_sync(
+	struct aux_engine *engine)
+{
+	/*TODO*/
+}
+
+#define COMPOSE_AUX_SW_DATA_16_20(command, address) \
+	((command) | ((0xF0000 & (address)) >> 16))
+
+#define COMPOSE_AUX_SW_DATA_8_15(address) \
+	((0xFF00 & (address)) >> 8)
+
+#define COMPOSE_AUX_SW_DATA_0_7(address) \
+	(0xFF & (address))
+
+static void submit_channel_request(
+	struct aux_engine *engine,
+	struct aux_request_transaction_data *request)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+	uint32_t value;
+	uint32_t length;
+
+	bool is_write =
+		((request->type == AUX_TRANSACTION_TYPE_DP) &&
+		 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
+		((request->type == AUX_TRANSACTION_TYPE_I2C) &&
+		((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
+		 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
+
+	/* clear_aux_error */
+	{
+		const uint32_t addr = mmAUXN_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXN_IMPCAL,
+			AUXN_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXN_IMPCAL,
+			AUXN_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+	{
+		const uint32_t addr = mmAUXP_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXP_IMPCAL,
+			AUXP_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXP_IMPCAL,
+			AUXP_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	/* force_default_calibrate */
+	{
+		const uint32_t addr = mmAUXN_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXN_IMPCAL,
+			AUXN_IMPCAL_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXN_IMPCAL,
+			AUXN_IMPCAL_OVERRIDE_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+	{
+		const uint32_t addr = mmAUXP_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXP_IMPCAL,
+			AUXP_IMPCAL_OVERRIDE_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXP_IMPCAL,
+			AUXP_IMPCAL_OVERRIDE_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	/* set the delay and the number of bytes to write */
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			request->delay,
+			AUX_SW_CONTROL,
+			AUX_SW_START_DELAY);
+
+		/* The length include
+		 * the 4 bit header and the 20 bit address
+		 * (that is 3 byte).
+		 * If the requested length is non zero this means
+		 * an addition byte specifying the length is required. */
+
+		length = request->length ? 4 : 3;
+		if (is_write)
+			length += request->length;
+
+		set_reg_field_value(
+			value,
+			length,
+			AUX_SW_CONTROL,
+			AUX_SW_WR_BYTES);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	/* program action and address and payload data (if 'is_write') */
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_data;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_INDEX);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_DATA_RW);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_DATA,
+			AUX_SW_AUTOINCREMENT_DISABLE);
+
+		set_reg_field_value(
+			value,
+			COMPOSE_AUX_SW_DATA_16_20(
+				request->action, request->address),
+			AUX_SW_DATA,
+			AUX_SW_DATA);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_AUTOINCREMENT_DISABLE);
+
+		set_reg_field_value(
+			value,
+			COMPOSE_AUX_SW_DATA_8_15(request->address),
+			AUX_SW_DATA,
+			AUX_SW_DATA);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			COMPOSE_AUX_SW_DATA_0_7(request->address),
+			AUX_SW_DATA,
+			AUX_SW_DATA);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		if (request->length) {
+			set_reg_field_value(
+				value,
+				request->length - 1,
+				AUX_SW_DATA,
+				AUX_SW_DATA);
+
+			dm_write_reg(engine->base.ctx, addr, value);
+		}
+
+		if (is_write) {
+			/* Load the HW buffer with the Data to be sent.
+			 * This is relevant for write operation.
+			 * For read, the data recived data will be
+			 * processed in process_channel_reply(). */
+			uint32_t i = 0;
+
+			while (i < request->length) {
+
+				set_reg_field_value(
+					value,
+					request->data[i],
+					AUX_SW_DATA,
+					AUX_SW_DATA);
+
+				dm_write_reg(
+					engine->base.ctx, addr, value);
+
+				++i;
+			}
+		}
+	}
+
+	{
+		const uint32_t addr = aux_engine->addr.aux_interrupt_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_INTERRUPT_CONTROL,
+			AUX_SW_DONE_ACK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_CONTROL,
+			AUX_SW_GO);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+}
+
+static void process_channel_reply(
+	struct aux_engine *engine,
+	struct aux_reply_transaction_data *reply)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+
+	/* Need to do a read to get the number of bytes to process
+	 * Alternatively, this information can be passed -
+	 * but that causes coupling which isn't good either. */
+
+	uint32_t bytes_replied;
+	uint32_t value;
+
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_status;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		bytes_replied = get_reg_field_value(
+				value,
+				AUX_SW_STATUS,
+				AUX_SW_REPLY_BYTE_COUNT);
+	}
+
+	if (bytes_replied) {
+		uint32_t reply_result;
+
+		const uint32_t addr = aux_engine->addr.aux_sw_data;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_INDEX);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_DATA,
+			AUX_SW_AUTOINCREMENT_DISABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_DATA,
+			AUX_SW_DATA_RW);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		reply_result = get_reg_field_value(
+				value,
+				AUX_SW_DATA,
+				AUX_SW_DATA);
+
+		reply_result = reply_result >> 4;
+
+		switch (reply_result) {
+		case 0: /* ACK */ {
+			uint32_t i = 0;
+
+			/* first byte was already used
+			 * to get the command status */
+			--bytes_replied;
+
+			while (i < bytes_replied) {
+				value = dm_read_reg(
+					engine->base.ctx, addr);
+
+				reply->data[i] = get_reg_field_value(
+						value,
+						AUX_SW_DATA,
+						AUX_SW_DATA);
+
+				++i;
+			}
+
+			reply->status = AUX_TRANSACTION_REPLY_AUX_ACK;
+		}
+		break;
+		case 1: /* NACK */
+			reply->status = AUX_TRANSACTION_REPLY_AUX_NACK;
+		break;
+		case 2: /* DEFER */
+			reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER;
+		break;
+		case 4: /* AUX ACK / I2C NACK */
+			reply->status = AUX_TRANSACTION_REPLY_I2C_NACK;
+		break;
+		case 8: /* AUX ACK / I2C DEFER */
+			reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER;
+		break;
+		default:
+			reply->status = AUX_TRANSACTION_REPLY_INVALID;
+		}
+	} else {
+		/* Need to handle an error case...
+		 * hopefully, upper layer function won't call this function
+		 * if the number of bytes in the reply was 0
+		 * because there was surely an error that was asserted
+		 * that should have been handled
+		 * for hot plug case, this could happens*/
+		if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
+			ASSERT_CRITICAL(false);
+	}
+}
+
+static enum aux_channel_operation_result get_channel_status(
+	struct aux_engine *engine,
+	uint8_t *returned_bytes)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+
+	const uint32_t addr = aux_engine->addr.aux_sw_status;
+
+	uint32_t value;
+	uint32_t aux_sw_done;
+
+	if (returned_bytes == NULL) {
+		/*caller pass NULL pointer*/
+		ASSERT_CRITICAL(false);
+		return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
+	}
+	*returned_bytes = 0;
+
+	/* poll to make sure that SW_DONE is asserted */
+	{
+		uint32_t time_elapsed = 0;
+
+		do {
+			value = dm_read_reg(engine->base.ctx, addr);
+
+			aux_sw_done = get_reg_field_value(
+					value,
+					AUX_SW_STATUS,
+					AUX_SW_DONE);
+
+			if (aux_sw_done)
+				break;
+
+			dm_delay_in_microseconds(engine->base.ctx, 10);
+
+			time_elapsed += 10;
+		} while (time_elapsed < aux_engine->timeout_period);
+
+
+	}
+
+	/* Note that the following bits are set in 'status.bits'
+	 * during CTS 4.2.1.2:
+	 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
+	 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
+	 *
+	 * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
+	 * HW debugging bit and should be ignored. */
+	if (aux_sw_done) {
+		if (get_reg_field_value(
+			value,
+			AUX_SW_STATUS,
+			AUX_SW_RX_TIMEOUT_STATE) ||
+			get_reg_field_value(
+				value,
+				AUX_SW_STATUS,
+				AUX_SW_RX_TIMEOUT))
+			return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
+		else if (get_reg_field_value(
+			value,
+			AUX_SW_STATUS,
+			AUX_SW_RX_INVALID_STOP))
+			return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
+
+		*returned_bytes = get_reg_field_value(
+				value,
+				AUX_SW_STATUS,
+				AUX_SW_REPLY_BYTE_COUNT);
+		if (*returned_bytes == 0)
+			return
+			AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
+		else {
+			*returned_bytes -= 1;
+			return AUX_CHANNEL_OPERATION_SUCCEEDED;
+		}
+	} else {
+		/*time_elapsed >= aux_engine->timeout_period */
+		if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
+			ASSERT_CRITICAL(false);
+		return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
+	}
+}
+
+static const int32_t aux_channel_offset[] = {
+	mmDP_AUX0_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX1_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX2_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX3_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX4_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX5_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL
+};
+
+static const struct aux_engine_funcs aux_engine_funcs = {
+	.destroy = destroy,
+	.acquire_engine = acquire_engine,
+	.configure = configure,
+	.start_gtc_sync = start_gtc_sync,
+	.stop_gtc_sync = stop_gtc_sync,
+	.submit_channel_request = submit_channel_request,
+	.process_channel_reply = process_channel_reply,
+	.get_channel_status = get_channel_status,
+};
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.submit_request = dal_aux_engine_submit_request,
+	.keep_power_up_count = dal_i2caux_keep_power_up_count,
+	.get_engine_type = dal_aux_engine_get_engine_type,
+	.acquire = dal_aux_engine_acquire,
+};
+
+static bool construct(
+	struct aux_engine_dce110 *engine,
+	const struct aux_engine_dce110_init_data *aux_init_data)
+{
+	int32_t offset;
+
+	if (aux_init_data->engine_id >=
+		sizeof(aux_channel_offset) / sizeof(int32_t)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (!dal_aux_engine_construct(
+		&engine->base, aux_init_data->ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+	engine->base.base.funcs = &engine_funcs;
+	engine->base.funcs = &aux_engine_funcs;
+	offset = aux_channel_offset[aux_init_data->engine_id];
+	engine->addr.aux_control = mmAUX_CONTROL + offset;
+	engine->addr.aux_arb_control = mmAUX_ARB_CONTROL + offset;
+	engine->addr.aux_sw_data = mmAUX_SW_DATA + offset;
+	engine->addr.aux_sw_control = mmAUX_SW_CONTROL + offset;
+	engine->addr.aux_interrupt_control = mmAUX_INTERRUPT_CONTROL + offset;
+	engine->addr.aux_sw_status = mmAUX_SW_STATUS + offset;
+	engine->addr.aux_gtc_sync_control = mmAUX_GTC_SYNC_CONTROL + offset;
+	engine->addr.aux_gtc_sync_status = mmAUX_GTC_SYNC_STATUS + offset;
+	engine->addr.aux_gtc_sync_controller_status =
+		mmAUX_GTC_SYNC_CONTROLLER_STATUS + offset;
+
+	engine->timeout_period = aux_init_data->timeout_period;
+
+	return true;
+}
+
+static void destruct(
+	struct aux_engine_dce110 *engine)
+{
+	dal_aux_engine_destruct(&engine->base);
+}
+
+struct aux_engine *dal_aux_engine_dce110_create(
+	const struct aux_engine_dce110_init_data *aux_init_data)
+{
+	struct aux_engine_dce110 *engine;
+
+	if (!aux_init_data) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	engine = dm_alloc(aux_init_data->ctx, sizeof(*engine));
+
+	if (!engine) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(engine, aux_init_data))
+		return &engine->base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(aux_init_data->ctx, engine);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
new file mode 100644
index 000000000000..ec6899ed5b40
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
@@ -0,0 +1,56 @@
+/*
+ * 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_AUX_ENGINE_DCE110_H__
+#define __DAL_AUX_ENGINE_DCE110_H__
+
+#include "../aux_engine.h"
+
+struct aux_engine_dce110 {
+	struct aux_engine base;
+	struct {
+		uint32_t aux_control;
+		uint32_t aux_arb_control;
+		uint32_t aux_sw_data;
+		uint32_t aux_sw_control;
+		uint32_t aux_interrupt_control;
+		uint32_t aux_sw_status;
+		uint32_t aux_gtc_sync_control;
+		uint32_t aux_gtc_sync_status;
+		uint32_t aux_gtc_sync_controller_status;
+	} addr;
+	uint32_t timeout_period;
+};
+
+struct aux_engine_dce110_init_data {
+	uint32_t engine_id;
+	uint32_t timeout_period;
+	struct dc_context *ctx;
+};
+
+struct aux_engine *dal_aux_engine_dce110_create(
+	const struct aux_engine_dce110_init_data *aux_init_data);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
new file mode 100644
index 000000000000..e6b6a972a0e5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
@@ -0,0 +1,25 @@
+/*
+ * 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
+ *
+ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
new file mode 100644
index 000000000000..2517f44f7297
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
@@ -0,0 +1,954 @@
+/*
+ * 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"
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "include/i2caux_interface.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_hw_engine.h"
+#include "../i2c_generic_hw_engine.h"
+/*
+ * Header of this unit
+ */
+
+#include "i2c_hw_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+/*
+ * This unit
+ */
+
+enum dc_i2c_status {
+	DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
+	DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW,
+	DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW
+};
+
+enum dc_i2c_arbitration {
+	DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
+	DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH
+};
+
+enum {
+	/* No timeout in HW
+	 * (timeout implemented in SW by querying status) */
+	I2C_SETUP_TIME_LIMIT = 255,
+	I2C_HW_BUFFER_SIZE = 144
+};
+
+/*
+ * @brief
+ * Cast pointer to 'struct i2c_hw_engine *'
+ * to pointer 'struct i2c_hw_engine_dce110 *'
+ */
+#define FROM_I2C_HW_ENGINE(ptr) \
+	container_of((ptr), struct i2c_hw_engine_dce110, base)
+/*
+ * @brief
+ * Cast pointer to 'struct i2c_engine *'
+ * to pointer to 'struct i2c_hw_engine_dce110 *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
+
+/*
+ * @brief
+ * Cast pointer to 'struct engine *'
+ * to 'pointer to struct i2c_hw_engine_dce110 *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+
+static void disable_i2c_hw_engine(
+	struct i2c_hw_engine_dce110 *engine)
+{
+	const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
+	uint32_t value = 0;
+
+	struct dc_context *ctx = NULL;
+
+	ctx = engine->base.base.base.ctx;
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		DC_I2C_DDC1_SETUP,
+		DC_I2C_DDC1_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void release_engine(
+	struct engine *engine)
+{
+	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
+
+	struct i2c_engine *base = NULL;
+	bool safe_to_reset;
+	uint32_t value = 0;
+
+	base = &hw_engine->base.base;
+
+	/* Restore original HW engine speed */
+
+	base->funcs->set_speed(base, hw_engine->base.original_speed);
+
+	/* Release I2C */
+	{
+		value = dm_read_reg(engine->ctx, mmDC_I2C_ARBITRATION);
+
+		set_reg_field_value(
+				value,
+				1,
+				DC_I2C_ARBITRATION,
+				DC_I2C_SW_DONE_USING_I2C_REG);
+
+		dm_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value);
+	}
+
+	/* Reset HW engine */
+	{
+		uint32_t i2c_sw_status = 0;
+
+		value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
+
+		i2c_sw_status = get_reg_field_value(
+				value,
+				DC_I2C_SW_STATUS,
+				DC_I2C_SW_STATUS);
+		/* if used by SW, safe to reset */
+		safe_to_reset = (i2c_sw_status == 1);
+	}
+	{
+		value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
+
+		if (safe_to_reset)
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_CONTROL,
+				DC_I2C_SOFT_RESET);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_CONTROL,
+			DC_I2C_SW_STATUS_RESET);
+
+		dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
+	}
+
+	/* HW I2c engine - clock gating feature */
+	if (!hw_engine->engine_keep_power_up_count)
+		disable_i2c_hw_engine(hw_engine);
+}
+
+static void keep_power_up_count(
+	struct engine *engine,
+	bool keep_power_up)
+{
+	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
+
+	if (keep_power_up)
+		++hw_engine->engine_keep_power_up_count;
+	else {
+		--hw_engine->engine_keep_power_up_count;
+
+		if (!hw_engine->engine_keep_power_up_count)
+			disable_i2c_hw_engine(hw_engine);
+	}
+}
+
+static bool setup_engine(
+	struct i2c_engine *i2c_engine)
+{
+	uint32_t value = 0;
+	struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine);
+
+	/* Program pin select */
+	{
+		const uint32_t addr = mmDC_I2C_CONTROL;
+
+		value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_GO);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SOFT_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SEND_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SW_STATUS_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_TRANSACTION_COUNT);
+
+		set_reg_field_value(
+			value,
+			engine->engine_id,
+			DC_I2C_CONTROL,
+			DC_I2C_DDC_SELECT);
+
+
+		dm_write_reg(i2c_engine->base.ctx, addr, value);
+	}
+
+	/* Program time limit */
+	{
+		const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
+
+		value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			I2C_SETUP_TIME_LIMIT,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_TIME_LIMIT);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_ENABLE);
+
+		dm_write_reg(i2c_engine->base.ctx, addr, value);
+	}
+
+	/* Program HW priority
+	 * set to High - interrupt software I2C at any time
+	 * Enable restart of SW I2C that was interrupted by HW
+	 * disable queuing of software while I2C is in use by HW */
+	{
+		value = dm_read_reg(i2c_engine->base.ctx,
+				mmDC_I2C_ARBITRATION);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_ARBITRATION,
+			DC_I2C_NO_QUEUED_SW_GO);
+
+		set_reg_field_value(
+			value,
+			DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
+			DC_I2C_ARBITRATION,
+			DC_I2C_SW_PRIORITY);
+
+		dm_write_reg(i2c_engine->base.ctx,
+				mmDC_I2C_ARBITRATION, value);
+	}
+
+	return true;
+}
+
+static uint32_t get_speed(
+	const struct i2c_engine *i2c_engine)
+{
+	const struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine);
+
+	const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
+
+	uint32_t pre_scale = 0;
+
+	uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+	pre_scale = get_reg_field_value(
+			value,
+			DC_I2C_DDC1_SPEED,
+			DC_I2C_DDC1_PRESCALE);
+
+	/* [anaumov] it seems following is unnecessary */
+	/*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
+
+	return pre_scale ?
+		engine->reference_frequency / pre_scale :
+		engine->base.default_speed;
+}
+
+static void set_speed(
+	struct i2c_engine *i2c_engine,
+	uint32_t speed)
+{
+	struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine);
+
+	if (speed) {
+		const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
+
+		uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			engine->reference_frequency / speed,
+			DC_I2C_DDC1_SPEED,
+			DC_I2C_DDC1_PRESCALE);
+
+		set_reg_field_value(
+			value,
+			2,
+			DC_I2C_DDC1_SPEED,
+			DC_I2C_DDC1_THRESHOLD);
+
+		/*DCE11, HW add 100Khz support for I2c*/
+		if (speed > 50) {
+			set_reg_field_value(
+				value,
+				2,
+				DC_I2C_DDC1_SPEED,
+				DC_I2C_DDC1_START_STOP_TIMING_CNTL);
+		} else {
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_DDC1_SPEED,
+				DC_I2C_DDC1_START_STOP_TIMING_CNTL);
+		}
+
+		dm_write_reg(i2c_engine->base.ctx, addr, value);
+	}
+}
+
+static inline void reset_hw_engine(struct engine *engine)
+{
+	uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_CONTROL,
+		DC_I2C_SOFT_RESET);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_CONTROL,
+		DC_I2C_SW_STATUS_RESET);
+
+	dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
+}
+
+static bool is_hw_busy(struct engine *engine)
+{
+	uint32_t i2c_sw_status = 0;
+
+	uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
+
+	i2c_sw_status = get_reg_field_value(
+			value,
+			DC_I2C_SW_STATUS,
+			DC_I2C_SW_STATUS);
+
+	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
+		return false;
+
+	reset_hw_engine(engine);
+
+	value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
+
+	i2c_sw_status = get_reg_field_value(
+			value,
+			DC_I2C_SW_STATUS,
+			DC_I2C_SW_STATUS);
+
+	return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
+}
+
+/*
+ * @brief
+ * DC_GPIO_DDC MM register offsets
+ */
+static const uint32_t transaction_addr[] = {
+	mmDC_I2C_TRANSACTION0,
+	mmDC_I2C_TRANSACTION1,
+	mmDC_I2C_TRANSACTION2,
+	mmDC_I2C_TRANSACTION3
+};
+
+static bool process_transaction(
+	struct i2c_hw_engine_dce110 *engine,
+	struct i2c_request_transaction_data *request)
+{
+	uint8_t length = request->length;
+	uint8_t *buffer = request->data;
+
+	bool last_transaction = false;
+	uint32_t value = 0;
+
+	struct dc_context *ctx = NULL;
+
+	ctx = engine->base.base.base.ctx;
+
+	{
+		const uint32_t addr =
+			transaction_addr[engine->transaction_count];
+
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_TRANSACTION0,
+			DC_I2C_STOP_ON_NACK0);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_TRANSACTION0,
+			DC_I2C_START0);
+
+
+		if ((engine->transaction_count == 3) ||
+		(request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
+		(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
+
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_TRANSACTION0,
+				DC_I2C_STOP0);
+
+			last_transaction = true;
+		} else
+			set_reg_field_value(
+				value,
+				0,
+				DC_I2C_TRANSACTION0,
+				DC_I2C_STOP0);
+
+		set_reg_field_value(
+			value,
+			(0 != (request->action &
+					I2CAUX_TRANSACTION_ACTION_I2C_READ)),
+			DC_I2C_TRANSACTION0,
+			DC_I2C_RW0);
+
+		set_reg_field_value(
+			value,
+			length,
+			DC_I2C_TRANSACTION0,
+			DC_I2C_COUNT0);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* Write the I2C address and I2C data
+	 * into the hardware circular buffer, one byte per entry.
+	 * As an example, the 7-bit I2C slave address for CRT monitor
+	 * for reading DDC/EDID information is 0b1010001.
+	 * For an I2C send operation, the LSB must be programmed to 0;
+	 * for I2C receive operation, the LSB must be programmed to 1. */
+
+	{
+		value = 0;
+
+		set_reg_field_value(
+			value,
+			false,
+			DC_I2C_DATA,
+			DC_I2C_DATA_RW);
+
+		set_reg_field_value(
+			value,
+			request->address,
+			DC_I2C_DATA,
+			DC_I2C_DATA);
+
+		if (engine->transaction_count == 0) {
+			set_reg_field_value(
+				value,
+				0,
+				DC_I2C_DATA,
+				DC_I2C_INDEX);
+
+			/*enable index write*/
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_DATA,
+				DC_I2C_INDEX_WRITE);
+
+			engine->buffer_used_write = 0;
+		}
+
+		dm_write_reg(ctx, mmDC_I2C_DATA, value);
+
+		engine->buffer_used_write++;
+
+		if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
+
+			set_reg_field_value(
+				value,
+				0,
+				DC_I2C_DATA,
+				DC_I2C_INDEX_WRITE);
+
+			while (length) {
+
+				set_reg_field_value(
+					value,
+					*buffer++,
+					DC_I2C_DATA,
+					DC_I2C_DATA);
+
+				dm_write_reg(ctx, mmDC_I2C_DATA, value);
+
+				engine->buffer_used_write++;
+				--length;
+			}
+		}
+	}
+
+	++engine->transaction_count;
+	engine->buffer_used_bytes += length + 1;
+
+	return last_transaction;
+}
+
+static void execute_transaction(
+	struct i2c_hw_engine_dce110 *engine)
+{
+	uint32_t value = 0;
+	struct dc_context *ctx = NULL;
+
+	ctx = engine->base.base.base.ctx;
+
+	{
+		const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
+
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_DATA_DRIVE_EN);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_CLK_DRIVE_EN);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_DATA_DRIVE_SEL);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_INTRA_TRANSACTION_DELAY);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_INTRA_BYTE_DELAY);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = mmDC_I2C_CONTROL;
+
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SOFT_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SW_STATUS_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SEND_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_GO);
+
+		set_reg_field_value(
+			value,
+			engine->transaction_count - 1,
+			DC_I2C_CONTROL,
+			DC_I2C_TRANSACTION_COUNT);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* start I2C transfer */
+	{
+		const uint32_t addr = mmDC_I2C_CONTROL;
+
+		value	= dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_CONTROL,
+			DC_I2C_GO);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* all transactions were executed and HW buffer became empty
+	 * (even though it actually happens when status becomes DONE) */
+	engine->transaction_count = 0;
+	engine->buffer_used_bytes = 0;
+}
+
+static void submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *request)
+{
+	request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
+
+	if (!process_transaction(FROM_I2C_ENGINE(engine), request))
+		return;
+
+	if (is_hw_busy(&engine->base)) {
+		request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
+		return;
+	}
+
+	execute_transaction(FROM_I2C_ENGINE(engine));
+}
+
+static void process_channel_reply(
+	struct i2c_engine *engine,
+	struct i2c_reply_transaction_data *reply)
+{
+	uint8_t length = reply->length;
+	uint8_t *buffer = reply->data;
+
+	struct i2c_hw_engine_dce110 *i2c_hw_engine_dce110 =
+		FROM_I2C_ENGINE(engine);
+
+	uint32_t value = 0;
+
+	/*set index*/
+	set_reg_field_value(
+		value,
+		i2c_hw_engine_dce110->buffer_used_write,
+		DC_I2C_DATA,
+		DC_I2C_INDEX);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_DATA,
+		DC_I2C_DATA_RW);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_DATA,
+		DC_I2C_INDEX_WRITE);
+
+	dm_write_reg(engine->base.ctx, mmDC_I2C_DATA, value);
+
+	while (length) {
+		/* after reading the status,
+		 * if the I2C operation executed successfully
+		 * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
+		 * should read data bytes from I2C circular data buffer */
+
+		value = dm_read_reg(engine->base.ctx, mmDC_I2C_DATA);
+
+		*buffer++ = get_reg_field_value(
+				value,
+				DC_I2C_DATA,
+				DC_I2C_DATA);
+
+		--length;
+	}
+}
+
+static enum i2c_channel_operation_result get_channel_status(
+	struct i2c_engine *engine,
+	uint8_t *returned_bytes)
+{
+	uint32_t i2c_sw_status = 0;
+	uint32_t value = dm_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS);
+
+	i2c_sw_status = get_reg_field_value(
+			value,
+			DC_I2C_SW_STATUS,
+			DC_I2C_SW_STATUS);
+
+	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
+		return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK)
+		return I2C_CHANNEL_OPERATION_NO_RESPONSE;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK)
+		return I2C_CHANNEL_OPERATION_TIMEOUT;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK)
+		return I2C_CHANNEL_OPERATION_FAILED;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK)
+		return I2C_CHANNEL_OPERATION_SUCCEEDED;
+
+	/* in DAL2, I2C_RESULT_OK was returned */
+	return I2C_CHANNEL_OPERATION_NOT_STARTED;
+}
+
+static uint8_t get_hw_buffer_available_size(
+	const struct i2c_hw_engine *engine)
+{
+	return I2C_HW_BUFFER_SIZE -
+		FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes;
+}
+
+static uint32_t get_transaction_timeout(
+	const struct i2c_hw_engine *engine,
+	uint32_t length)
+{
+	uint32_t speed = engine->base.funcs->get_speed(&engine->base);
+
+	uint32_t period_timeout;
+	uint32_t num_of_clock_stretches;
+
+	if (!speed)
+		return 0;
+
+	period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
+
+	num_of_clock_stretches = 1 + (length << 3) + 1;
+	num_of_clock_stretches +=
+		(FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) +
+		(FROM_I2C_HW_ENGINE(engine)->transaction_count << 1);
+
+	return period_timeout * num_of_clock_stretches;
+}
+
+static void destroy(
+	struct i2c_engine **i2c_engine)
+{
+	struct i2c_hw_engine_dce110 *engine_dce110 =
+			FROM_I2C_ENGINE(*i2c_engine);
+
+	dal_i2c_hw_engine_destruct(&engine_dce110->base);
+
+	dm_free((*i2c_engine)->base.ctx, engine_dce110);
+
+	*i2c_engine = NULL;
+}
+/*
+ * @brief
+ * DC_I2C_DDC1_SETUP MM register offsets
+ *
+ * @note
+ * The indices of this offset array are DDC engine IDs
+ */
+static const int32_t ddc_setup_offset[] = {
+
+	mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */
+	mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */
+	mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */
+	mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */
+	mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */
+	mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */
+	mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */
+};
+
+/*
+ * @brief
+ * DC_I2C_DDC1_SPEED MM register offsets
+ *
+ * @note
+ * The indices of this offset array are DDC engine IDs
+ */
+static const int32_t ddc_speed_offset[] = {
+	mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */
+	mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */
+	mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */
+	mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */
+	mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */
+	mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */
+	mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */
+};
+
+static const struct i2c_engine_funcs i2c_engine_funcs = {
+	.destroy = destroy,
+	.get_speed = get_speed,
+	.set_speed = set_speed,
+	.setup_engine = setup_engine,
+	.submit_channel_request = submit_channel_request,
+	.process_channel_reply = process_channel_reply,
+	.get_channel_status = get_channel_status,
+	.acquire_engine = dal_i2c_hw_engine_acquire_engine,
+};
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.keep_power_up_count = keep_power_up_count,
+	.get_engine_type = dal_i2c_hw_engine_get_engine_type,
+	.acquire = dal_i2c_engine_acquire,
+	.submit_request = dal_i2c_hw_engine_submit_request,
+};
+
+static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = {
+	.get_hw_buffer_available_size = get_hw_buffer_available_size,
+	.get_transaction_timeout = get_transaction_timeout,
+	.wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result,
+};
+
+static bool construct(
+	struct i2c_hw_engine_dce110 *engine_dce110,
+	const struct i2c_hw_engine_dce110_create_arg *arg)
+{
+	uint32_t xtal_ref_div = 0;
+	uint32_t value = 0;
+
+	/*ddc_setup_offset of dce80 and dce110 have the same register name
+	 * but different offset. Do not need different array*/
+	if (arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t))
+		return false;
+	if (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t))
+		return false;
+	if (!arg->reference_frequency)
+		return false;
+
+	if (!dal_i2c_hw_engine_construct(&engine_dce110->base, arg->ctx))
+		return false;
+
+	engine_dce110->base.base.base.funcs = &engine_funcs;
+	engine_dce110->base.base.funcs = &i2c_engine_funcs;
+	engine_dce110->base.funcs = &i2c_hw_engine_funcs;
+	engine_dce110->base.default_speed = arg->default_speed;
+
+	engine_dce110->engine_id = arg->engine_id;
+
+	engine_dce110->buffer_used_bytes = 0;
+	engine_dce110->transaction_count = 0;
+	engine_dce110->engine_keep_power_up_count = 1;
+
+	/*values which are not included by arg*/
+	engine_dce110->addr.DC_I2C_DDCX_SETUP =
+		mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id];
+	engine_dce110->addr.DC_I2C_DDCX_SPEED =
+		mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id];
+
+
+	value = dm_read_reg(
+		engine_dce110->base.base.base.ctx,
+		mmMICROSECOND_TIME_BASE_DIV);
+
+	xtal_ref_div = get_reg_field_value(
+			value,
+			MICROSECOND_TIME_BASE_DIV,
+			XTAL_REF_DIV);
+
+	if (xtal_ref_div == 0) {
+		dal_logger_write(
+				engine_dce110->base.base.base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_I2C_AUX,
+				"Invalid base timer divider\n",
+				__func__);
+		xtal_ref_div = 2;
+	}
+
+	/*Calculating Reference Clock by divding original frequency by
+	 * XTAL_REF_DIV.
+	 * At upper level, uint32_t reference_frequency =
+	 *  dal_i2caux_get_reference_clock(as) >> 1
+	 *  which already divided by 2. So we need x2 to get original
+	 *  reference clock from ppll_info
+	 */
+	engine_dce110->reference_frequency =
+		(arg->reference_frequency * 2) / xtal_ref_div;
+
+
+	return true;
+}
+
+struct i2c_engine *dal_i2c_hw_engine_dce110_create(
+	const struct i2c_hw_engine_dce110_create_arg *arg)
+{
+	struct i2c_hw_engine_dce110 *engine_dce10;
+
+	if (!arg) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	engine_dce10 = dm_alloc(arg->ctx, sizeof(struct i2c_hw_engine_dce110));
+
+	if (!engine_dce10) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(engine_dce10, arg))
+		return &engine_dce10->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(arg->ctx, engine_dce10);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
new file mode 100644
index 000000000000..fc2ae365f8ed
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
@@ -0,0 +1,58 @@
+/*
+ * 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_I2C_HW_ENGINE_DCE110_H__
+#define __DAL_I2C_HW_ENGINE_DCE110_H__
+
+struct i2c_hw_engine_dce110 {
+	struct i2c_hw_engine base;
+	struct {
+		uint32_t DC_I2C_DDCX_SETUP;
+		uint32_t DC_I2C_DDCX_SPEED;
+	} addr;
+	uint32_t engine_id;
+	/* expressed in kilohertz */
+	uint32_t reference_frequency;
+	/* number of bytes currently used in HW buffer */
+	uint32_t buffer_used_bytes;
+	/* number of bytes used for write transaction in HW buffer
+	 * - this will be used as the index to read from*/
+	uint32_t buffer_used_write;
+	/* number of pending transactions (before GO) */
+	uint32_t transaction_count;
+	uint32_t engine_keep_power_up_count;
+};
+
+struct i2c_hw_engine_dce110_create_arg {
+	uint32_t engine_id;
+	uint32_t reference_frequency;
+	uint32_t default_speed;
+	struct dc_context *ctx;
+};
+
+struct i2c_engine *dal_i2c_hw_engine_dce110_create(
+	const struct i2c_hw_engine_dce110_create_arg *arg);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
new file mode 100644
index 000000000000..f060b25d1618
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
@@ -0,0 +1,172 @@
+/*
+ * 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_sw_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_sw_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct i2c_sw_engine *'
+ * to 'struct i2c_sw_engine_dce110 *'
+ */
+#define FROM_I2C_SW_ENGINE(ptr) \
+	container_of((ptr), struct i2c_sw_engine_dce110, base)
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_sw_engine_dce80 *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base))
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_sw_engine_dce80 *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+static void release_engine(
+	struct engine *engine)
+{
+}
+
+static void destruct(
+	struct i2c_sw_engine_dce110 *engine)
+{
+	dal_i2c_sw_engine_destruct(&engine->base);
+}
+
+static void destroy(
+	struct i2c_engine **engine)
+{
+	struct i2c_sw_engine_dce110 *sw_engine = FROM_I2C_ENGINE(*engine);
+
+	destruct(sw_engine);
+
+	dm_free((*engine)->base.ctx, sw_engine);
+
+	*engine = NULL;
+}
+
+static bool acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc_handle)
+{
+	return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle);
+}
+
+static const struct i2c_engine_funcs i2c_engine_funcs = {
+	.acquire_engine = acquire_engine,
+	.destroy = destroy,
+	.get_speed = dal_i2c_sw_engine_get_speed,
+	.set_speed = dal_i2c_sw_engine_set_speed,
+	.setup_engine = dal_i2c_engine_setup_i2c_engine,
+	.submit_channel_request = dal_i2c_sw_engine_submit_channel_request,
+	.process_channel_reply = dal_i2c_engine_process_channel_reply,
+	.get_channel_status = dal_i2c_sw_engine_get_channel_status,
+};
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.get_engine_type = dal_i2c_sw_engine_get_engine_type,
+	.acquire = dal_i2c_engine_acquire,
+	.submit_request = dal_i2c_sw_engine_submit_request,
+	.keep_power_up_count = dal_i2caux_keep_power_up_count,
+};
+
+static bool construct(
+	struct i2c_sw_engine_dce110 *engine_dce110,
+	const struct i2c_sw_engine_dce110_create_arg *arg_dce110)
+{
+	struct i2c_sw_engine_create_arg arg_base;
+
+	arg_base.ctx = arg_dce110->ctx;
+	arg_base.default_speed = arg_dce110->default_speed;
+
+	if (!dal_i2c_sw_engine_construct(
+			&engine_dce110->base, &arg_base)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	/*struct engine   struct engine_funcs*/
+	engine_dce110->base.base.base.funcs = &engine_funcs;
+	/*struct i2c_engine  struct i2c_engine_funcs*/
+	engine_dce110->base.base.funcs = &i2c_engine_funcs;
+	engine_dce110->base.default_speed = arg_dce110->default_speed;
+	engine_dce110->engine_id = arg_dce110->engine_id;
+
+	return true;
+}
+
+struct i2c_engine *dal_i2c_sw_engine_dce110_create(
+	const struct i2c_sw_engine_dce110_create_arg *arg)
+{
+	struct i2c_sw_engine_dce110 *engine_dce110;
+
+	if (!arg) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	engine_dce110 = dm_alloc(arg->ctx, sizeof(struct i2c_sw_engine_dce110));
+
+	if (!engine_dce110) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(engine_dce110, arg))
+		return &engine_dce110->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(arg->ctx, engine_dce110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
new file mode 100644
index 000000000000..c48c61f540a8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
@@ -0,0 +1,43 @@
+/*
+ * 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_I2C_SW_ENGINE_DCE110_H__
+#define __DAL_I2C_SW_ENGINE_DCE110_H__
+
+struct i2c_sw_engine_dce110 {
+	struct i2c_sw_engine base;
+	uint32_t engine_id;
+};
+
+struct i2c_sw_engine_dce110_create_arg {
+	uint32_t engine_id;
+	uint32_t default_speed;
+	struct dc_context *ctx;
+};
+
+struct i2c_engine *dal_i2c_sw_engine_dce110_create(
+	const struct i2c_sw_engine_dce110_create_arg *arg);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
new file mode 100644
index 000000000000..9c88762dbd0c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
@@ -0,0 +1,266 @@
+/*
+ * 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../i2caux.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_sw_engine.h"
+#include "../i2c_hw_engine.h"
+
+/*
+ * Header of this unit
+ */
+#include "i2caux_dce110.h"
+
+#include "i2c_sw_engine_dce110.h"
+#include "i2c_hw_engine_dce110.h"
+#include "aux_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+/*cast pointer to struct i2caux TO pointer to struct i2caux_dce110*/
+#define FROM_I2C_AUX(ptr) \
+	container_of((ptr), struct i2caux_dce110, base)
+
+static void destruct(
+	struct i2caux_dce110 *i2caux_dce110)
+{
+	dal_i2caux_destruct(&i2caux_dce110->base);
+}
+
+static void destroy(
+	struct i2caux **i2c_engine)
+{
+	struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(*i2c_engine);
+
+	destruct(i2caux_dce110);
+
+	dm_free((*i2c_engine)->ctx, i2caux_dce110);
+
+	*i2c_engine = NULL;
+}
+
+static struct i2c_engine *acquire_i2c_hw_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux);
+
+	struct i2c_engine *engine = NULL;
+	/* generic hw engine is not used for EDID read
+	 * It may be needed for external i2c device, like thermal chip,
+	 * TODO will be implemented when needed.
+	 * check dce80 bool non_generic for generic hw engine;
+	 */
+
+	if (!ddc)
+		return NULL;
+
+	if (dal_ddc_is_hw_supported(ddc)) {
+		enum gpio_ddc_line line = dal_ddc_get_line(ddc);
+
+		if (line < GPIO_DDC_LINE_COUNT)
+			engine = i2caux->i2c_hw_engines[line];
+	}
+
+	if (!engine)
+		return NULL;
+
+	if (!i2caux_dce110->i2c_hw_buffer_in_use &&
+		engine->base.funcs->acquire(&engine->base, ddc)) {
+		i2caux_dce110->i2c_hw_buffer_in_use = true;
+		return engine;
+	}
+
+	return NULL;
+}
+
+static void release_engine(
+	struct i2caux *i2caux,
+	struct engine *engine)
+{
+	struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux);
+
+	if (engine->funcs->get_engine_type(engine) ==
+		I2CAUX_ENGINE_TYPE_I2C_DDC_HW)
+		i2caux_dce110->i2c_hw_buffer_in_use = false;
+
+	dal_i2caux_release_engine(i2caux, engine);
+}
+
+static const enum gpio_ddc_line hw_ddc_lines[] = {
+	GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_DDC2,
+	GPIO_DDC_LINE_DDC3,
+	GPIO_DDC_LINE_DDC4,
+	GPIO_DDC_LINE_DDC5,
+	GPIO_DDC_LINE_DDC6,
+};
+
+static const enum gpio_ddc_line hw_aux_lines[] = {
+	GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_DDC2,
+	GPIO_DDC_LINE_DDC3,
+	GPIO_DDC_LINE_DDC4,
+	GPIO_DDC_LINE_DDC5,
+	GPIO_DDC_LINE_DDC6,
+};
+
+/* function table */
+static const struct i2caux_funcs i2caux_funcs = {
+	.destroy = destroy,
+	.acquire_i2c_hw_engine = acquire_i2c_hw_engine,
+	.release_engine = release_engine,
+	.acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine,
+	.acquire_aux_engine = dal_i2caux_acquire_aux_engine,
+};
+
+static bool construct(
+	struct i2caux_dce110 *i2caux_dce110,
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	uint32_t i = 0;
+	uint32_t reference_frequency = 0;
+	bool use_i2c_sw_engine = false;
+	struct i2caux *base = NULL;
+	/*TODO: For CZ bring up, if dal_i2caux_get_reference_clock
+	 * does not return 48KHz, we need hard coded for 48Khz.
+	 * Some BIOS setting incorrect cause this
+	 * For production, we always get value from BIOS*/
+	reference_frequency =
+		dal_i2caux_get_reference_clock(as) >> 1;
+
+	use_i2c_sw_engine = dal_adapter_service_is_feature_supported(
+		FEATURE_RESTORE_USAGE_I2C_SW_ENGINE);
+
+	base = &i2caux_dce110->base;
+
+	if (!dal_i2caux_construct(base, as, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	i2caux_dce110->base.funcs = &i2caux_funcs;
+	i2caux_dce110->i2c_hw_buffer_in_use = false;
+	/* Create I2C engines (DDC lines per connector)
+	 * different I2C/AUX usage cases, DDC, Generic GPIO, AUX.
+	 */
+	do {
+		enum gpio_ddc_line line_id = hw_ddc_lines[i];
+
+		struct i2c_hw_engine_dce110_create_arg hw_arg_dce110;
+
+		if (use_i2c_sw_engine) {
+			struct i2c_sw_engine_dce110_create_arg sw_arg;
+
+			sw_arg.engine_id = i;
+			sw_arg.default_speed = base->default_i2c_sw_speed;
+			sw_arg.ctx = ctx;
+			base->i2c_sw_engines[line_id] =
+				dal_i2c_sw_engine_dce110_create(&sw_arg);
+		}
+
+		hw_arg_dce110.engine_id = i;
+		hw_arg_dce110.reference_frequency = reference_frequency;
+		hw_arg_dce110.default_speed = base->default_i2c_hw_speed;
+		hw_arg_dce110.ctx = ctx;
+
+		base->i2c_hw_engines[line_id] =
+			dal_i2c_hw_engine_dce110_create(&hw_arg_dce110);
+
+		++i;
+	} while (i < ARRAY_SIZE(hw_ddc_lines));
+
+	/* Create AUX engines for all lines which has assisted HW AUX
+	 * 'i' (loop counter) used as DDC/AUX engine_id */
+
+	i = 0;
+
+	do {
+		enum gpio_ddc_line line_id = hw_aux_lines[i];
+
+		struct aux_engine_dce110_init_data aux_init_data;
+
+		aux_init_data.engine_id = i;
+		aux_init_data.timeout_period = base->aux_timeout_period;
+		aux_init_data.ctx = ctx;
+
+		base->aux_engines[line_id] =
+			dal_aux_engine_dce110_create(&aux_init_data);
+
+		++i;
+	} while (i < ARRAY_SIZE(hw_aux_lines));
+
+	/*TODO Generic I2C SW and HW*/
+
+	return true;
+}
+
+/*
+ * dal_i2caux_dce110_create
+ *
+ * @brief
+ * public interface to allocate memory for DCE11 I2CAUX
+ *
+ * @param
+ * struct adapter_service *as - [in]
+ * struct dc_context *ctx - [in]
+ *
+ * @return
+ * pointer to the base struct of DCE11 I2CAUX
+ */
+struct i2caux *dal_i2caux_dce110_create(
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	struct i2caux_dce110 *i2caux_dce110 =
+		dm_alloc(ctx, sizeof(struct i2caux_dce110));
+
+	if (!i2caux_dce110) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(i2caux_dce110, as, ctx))
+		return &i2caux_dce110->base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, i2caux_dce110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
new file mode 100644
index 000000000000..1a7ba1baf3d0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
@@ -0,0 +1,39 @@
+/*
+ * 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_I2C_AUX_DCE110_H__
+#define __DAL_I2C_AUX_DCE110_H__
+
+struct i2caux_dce110 {
+	struct i2caux base;
+	/* indicate the I2C HW circular buffer is in use */
+	bool i2c_hw_buffer_in_use;
+};
+
+struct i2caux *dal_i2caux_dce110_create(
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+#endif /* __DAL_I2C_AUX_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
new file mode 100644
index 000000000000..f4bc39d786c8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012-16 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../i2caux.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_sw_engine.h"
+#include "../i2c_hw_engine.h"
+
+/*
+ * Header of this unit
+ */
+#include "i2caux_diag.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+static void destruct(
+	struct i2caux *i2caux)
+{
+	dal_i2caux_destruct(i2caux);
+}
+
+static void destroy(
+	struct i2caux **i2c_engine)
+{
+	destruct(*i2c_engine);
+
+	dm_free((*i2c_engine)->ctx, *i2c_engine);
+
+	*i2c_engine = NULL;
+}
+
+
+
+/* function table */
+static const struct i2caux_funcs i2caux_funcs = {
+	.destroy = destroy,
+	.acquire_i2c_hw_engine = NULL,
+	.release_engine = NULL,
+	.acquire_i2c_sw_engine = NULL,
+	.acquire_aux_engine = NULL,
+};
+
+static bool construct(
+	struct i2caux *i2caux,
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	if (!dal_i2caux_construct(i2caux, as, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	i2caux->funcs = &i2caux_funcs;
+
+	return true;
+}
+
+struct i2caux *dal_i2caux_diag_fpga_create(
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	struct i2caux *i2caux =	dm_alloc(ctx, sizeof(struct i2caux));
+
+	if (!i2caux) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(i2caux, as, ctx))
+		return i2caux;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, i2caux);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
new file mode 100644
index 000000000000..3de250bd7660
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-16 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_I2C_AUX_DIAG_FPGA_H__
+#define __DAL_I2C_AUX_DIAG_FPGA_H__
+
+struct i2caux *dal_i2caux_diag_fpga_create(
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+#endif /* __DAL_I2C_AUX_DIAG_FPGA_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
new file mode 100644
index 000000000000..d3635f884579
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
@@ -0,0 +1,129 @@
+/*
+ * 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_ENGINE_H__
+#define __DAL_ENGINE_H__
+
+enum i2caux_transaction_operation {
+	I2CAUX_TRANSACTION_READ,
+	I2CAUX_TRANSACTION_WRITE
+};
+
+enum i2caux_transaction_address_space {
+	I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C = 1,
+	I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD
+};
+
+struct i2caux_transaction_payload {
+	enum i2caux_transaction_address_space address_space;
+	uint32_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum i2caux_transaction_status {
+	I2CAUX_TRANSACTION_STATUS_UNKNOWN = (-1L),
+	I2CAUX_TRANSACTION_STATUS_SUCCEEDED,
+	I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY,
+	I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT,
+	I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR,
+	I2CAUX_TRANSACTION_STATUS_FAILED_NACK,
+	I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE,
+	I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION,
+	I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION,
+	I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW
+};
+
+struct i2caux_transaction_request {
+	enum i2caux_transaction_operation operation;
+	struct i2caux_transaction_payload payload;
+	enum i2caux_transaction_status status;
+};
+
+enum i2caux_engine_type {
+	I2CAUX_ENGINE_TYPE_UNKNOWN = (-1L),
+	I2CAUX_ENGINE_TYPE_AUX,
+	I2CAUX_ENGINE_TYPE_I2C_DDC_HW,
+	I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW,
+	I2CAUX_ENGINE_TYPE_I2C_SW
+};
+
+enum i2c_default_speed {
+	I2CAUX_DEFAULT_I2C_HW_SPEED = 50,
+	I2CAUX_DEFAULT_I2C_SW_SPEED = 50
+};
+
+enum i2caux_transaction_action {
+	I2CAUX_TRANSACTION_ACTION_I2C_WRITE = 0x00,
+	I2CAUX_TRANSACTION_ACTION_I2C_READ = 0x10,
+	I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST = 0x20,
+
+	I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT = 0x40,
+	I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT = 0x50,
+	I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT = 0x60,
+
+	I2CAUX_TRANSACTION_ACTION_DP_WRITE = 0x80,
+	I2CAUX_TRANSACTION_ACTION_DP_READ = 0x90
+};
+
+struct engine;
+
+struct engine_funcs {
+	enum i2caux_engine_type (*get_engine_type)(
+		const struct engine *engine);
+	bool (*acquire)(
+		struct engine *engine,
+		struct ddc *ddc);
+	bool (*submit_request)(
+		struct engine *engine,
+		struct i2caux_transaction_request *request,
+		bool middle_of_transaction);
+	/* [anaumov] Actually, following method is meaningful
+	 * only in I2C HW engines */
+	void (*keep_power_up_count)(
+		struct engine *engine,
+		bool keep_power_up);
+	void (*release_engine)(
+		struct engine *engine);
+};
+
+struct engine {
+	const struct engine_funcs *funcs;
+	struct ddc *ddc;
+	struct dc_context *ctx;
+};
+
+bool dal_i2caux_construct_engine(
+	struct engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2caux_destruct_engine(
+	struct engine *engine);
+
+void dal_i2caux_keep_power_up_count(
+	struct engine *engine,
+	bool keep_power_up);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c b/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
new file mode 100644
index 000000000000..9c472b9db5ba
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
@@ -0,0 +1,67 @@
+/*
+ * 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+void dal_i2caux_keep_power_up_count(
+	struct engine *engine,
+	bool keep_power_up)
+{
+
+}
+
+bool dal_i2caux_construct_engine(
+	struct engine *engine,
+	struct dc_context *ctx)
+{
+	engine->ddc = NULL;
+	engine->ctx = ctx;
+	return true;
+}
+
+void dal_i2caux_destruct_engine(
+	struct engine *engine)
+{
+	/* nothing to do */
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
new file mode 100644
index 000000000000..dccb1c51a3be
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
@@ -0,0 +1,121 @@
+/*
+ * 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define FROM_ENGINE(ptr) \
+	container_of((ptr), struct i2c_engine, base)
+
+bool dal_i2c_engine_acquire(
+	struct engine *engine,
+	struct ddc *ddc_handle)
+{
+	struct i2c_engine *i2c_engine = FROM_ENGINE(engine);
+
+	uint32_t counter = 0;
+	bool result;
+
+	do {
+		result = i2c_engine->funcs->acquire_engine(
+			i2c_engine, ddc_handle);
+
+		if (result)
+			break;
+
+		/* i2c_engine is busy by VBios, lets wait and retry */
+
+		dm_delay_in_microseconds(engine->ctx, 10);
+
+		++counter;
+	} while (counter < 2);
+
+	if (result) {
+		if (!i2c_engine->funcs->setup_engine(i2c_engine)) {
+			engine->funcs->release_engine(engine);
+			result = false;
+		}
+	}
+
+	return result;
+}
+
+bool dal_i2c_engine_setup_i2c_engine(
+	struct i2c_engine *engine)
+{
+	/* Derivative classes do not have to override this */
+
+	return true;
+}
+
+void dal_i2c_engine_submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *request)
+{
+
+}
+
+void dal_i2c_engine_process_channel_reply(
+	struct i2c_engine *engine,
+	struct i2c_reply_transaction_data *reply)
+{
+
+}
+
+bool dal_i2c_engine_construct(
+	struct i2c_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2caux_construct_engine(&engine->base, ctx))
+		return false;
+
+	engine->timeout_delay = 0;
+	return true;
+}
+
+void dal_i2c_engine_destruct(
+	struct i2c_engine *engine)
+{
+	dal_i2caux_destruct_engine(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
new file mode 100644
index 000000000000..20299fd08e9c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
@@ -0,0 +1,113 @@
+/*
+ * 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_I2C_ENGINE_H__
+#define __DAL_I2C_ENGINE_H__
+
+enum i2c_channel_operation_result {
+	I2C_CHANNEL_OPERATION_SUCCEEDED,
+	I2C_CHANNEL_OPERATION_FAILED,
+	I2C_CHANNEL_OPERATION_NOT_GRANTED,
+	I2C_CHANNEL_OPERATION_IS_BUSY,
+	I2C_CHANNEL_OPERATION_NO_HANDLE_PROVIDED,
+	I2C_CHANNEL_OPERATION_CHANNEL_IN_USE,
+	I2C_CHANNEL_OPERATION_CHANNEL_CLIENT_MAX_ALLOWED,
+	I2C_CHANNEL_OPERATION_ENGINE_BUSY,
+	I2C_CHANNEL_OPERATION_TIMEOUT,
+	I2C_CHANNEL_OPERATION_NO_RESPONSE,
+	I2C_CHANNEL_OPERATION_HW_REQUEST_I2C_BUS,
+	I2C_CHANNEL_OPERATION_WRONG_PARAMETER,
+	I2C_CHANNEL_OPERATION_OUT_NB_OF_RETRIES,
+	I2C_CHANNEL_OPERATION_NOT_STARTED
+};
+
+struct i2c_request_transaction_data {
+	enum i2caux_transaction_action action;
+	enum i2c_channel_operation_result status;
+	uint8_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+struct i2c_reply_transaction_data {
+	uint8_t length;
+	uint8_t *data;
+};
+
+struct i2c_engine;
+
+struct i2c_engine_funcs {
+	void (*destroy)(
+		struct i2c_engine **ptr);
+	uint32_t (*get_speed)(
+		const struct i2c_engine *engine);
+	void (*set_speed)(
+		struct i2c_engine *engine,
+		uint32_t speed);
+	bool (*acquire_engine)(
+		struct i2c_engine *engine,
+		struct ddc *ddc);
+	bool (*setup_engine)(
+		struct i2c_engine *engine);
+	void (*submit_channel_request)(
+		struct i2c_engine *engine,
+		struct i2c_request_transaction_data *request);
+	void (*process_channel_reply)(
+		struct i2c_engine *engine,
+		struct i2c_reply_transaction_data *reply);
+	enum i2c_channel_operation_result (*get_channel_status)(
+		struct i2c_engine *engine,
+		uint8_t *returned_bytes);
+};
+
+struct i2c_engine {
+	struct engine base;
+	const struct i2c_engine_funcs *funcs;
+	uint32_t timeout_delay;
+};
+
+bool dal_i2c_engine_construct(
+	struct i2c_engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2c_engine_destruct(
+	struct i2c_engine *engine);
+
+bool dal_i2c_engine_setup_i2c_engine(
+	struct i2c_engine *engine);
+
+void dal_i2c_engine_submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *request);
+
+void dal_i2c_engine_process_channel_reply(
+	struct i2c_engine *engine,
+	struct i2c_reply_transaction_data *reply);
+
+bool dal_i2c_engine_acquire(
+	struct engine *ptr,
+	struct ddc *ddc_handle);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
new file mode 100644
index 000000000000..6429b55dd697
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
@@ -0,0 +1,286 @@
+/*
+ * 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+#include "i2c_engine.h"
+#include "i2c_hw_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_generic_hw_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct i2c_hw_engine *'
+ * to 'struct i2c_generic_hw_engine *'
+ */
+#define FROM_I2C_HW_ENGINE(ptr) \
+	container_of((ptr), struct i2c_generic_hw_engine, base)
+
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_generic_hw_engine *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_generic_hw_engine *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW;
+}
+
+/*
+ * @brief
+ * Single transaction handling.
+ * Since transaction may be bigger than HW buffer size,
+ * it divides transaction to sub-transactions
+ * and uses batch transaction feature of the engine.
+ */
+bool dal_i2c_generic_hw_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction)
+{
+	struct i2c_generic_hw_engine *hw_engine = FROM_ENGINE(engine);
+
+	struct i2c_hw_engine *base = &hw_engine->base;
+
+	uint8_t max_payload_size =
+		base->funcs->get_hw_buffer_available_size(base);
+
+	bool initial_stop_bit = !middle_of_transaction;
+
+	struct i2c_generic_transaction_attributes attributes;
+
+	enum i2c_channel_operation_result operation_result =
+		I2C_CHANNEL_OPERATION_FAILED;
+
+	bool result = false;
+
+	/* setup transaction initial properties */
+
+	uint8_t address = i2caux_request->payload.address;
+	uint8_t *current_payload = i2caux_request->payload.data;
+	uint8_t remaining_payload_size = i2caux_request->payload.length;
+
+	bool first_iteration = true;
+
+	if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+		attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_READ;
+	else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+		attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+	else {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
+		return false;
+	}
+
+	/* Do batch transaction.
+	 * Divide read/write data into payloads which fit HW buffer size.
+	 * 1. Single transaction:
+	 *    start_bit = 1, stop_bit depends on session state, ack_on_read = 0;
+	 * 2. Start of batch transaction:
+	 *    start_bit = 1, stop_bit = 0, ack_on_read = 1;
+	 * 3. Middle of batch transaction:
+	 *    start_bit = 0, stop_bit = 0, ack_on_read = 1;
+	 * 4. End of batch transaction:
+	 *    start_bit = 0, stop_bit depends on session state, ack_on_read = 0.
+	 * Session stop bit is set if 'middle_of_transaction' = 0. */
+
+	while (remaining_payload_size) {
+		uint8_t current_transaction_size;
+		uint8_t current_payload_size;
+
+		bool last_iteration;
+		bool stop_bit;
+
+		/* Calculate current transaction size and payload size.
+		 * Transaction size = total number of bytes in transaction,
+		 * including slave's address;
+		 * Payload size = number of data bytes in transaction. */
+
+		if (first_iteration) {
+			/* In the first sub-transaction we send slave's address
+			 * thus we need to reserve one byte for it */
+			current_transaction_size =
+			(remaining_payload_size > max_payload_size - 1) ?
+				max_payload_size :
+				remaining_payload_size + 1;
+
+			current_payload_size = current_transaction_size - 1;
+		} else {
+			/* Second and further sub-transactions will have
+			 * entire buffer reserved for data */
+			current_transaction_size =
+				(remaining_payload_size > max_payload_size) ?
+				max_payload_size :
+				remaining_payload_size;
+
+			current_payload_size = current_transaction_size;
+		}
+
+		last_iteration =
+			(remaining_payload_size == current_payload_size);
+
+		stop_bit = last_iteration ? initial_stop_bit : false;
+
+		/* write slave device address */
+
+		if (first_iteration)
+			hw_engine->funcs->write_address(hw_engine, address);
+
+		/* write current portion of data, if requested */
+
+		if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+			hw_engine->funcs->write_data(
+				hw_engine,
+				current_payload,
+				current_payload_size);
+
+		/* execute transaction */
+
+		attributes.start_bit = first_iteration;
+		attributes.stop_bit = stop_bit;
+		attributes.last_read = last_iteration;
+		attributes.transaction_size = current_transaction_size;
+
+		hw_engine->funcs->execute_transaction(hw_engine, &attributes);
+
+		/* wait until transaction is processed; if it fails - quit */
+
+		operation_result = base->funcs->wait_on_operation_result(
+			base,
+			base->funcs->get_transaction_timeout(
+				base, current_transaction_size),
+			I2C_CHANNEL_OPERATION_ENGINE_BUSY);
+
+		if (operation_result != I2C_CHANNEL_OPERATION_SUCCEEDED)
+			break;
+
+		/* read current portion of data, if requested */
+
+		/* the read offset should be 1 for first sub-transaction,
+		 * and 0 for any next one */
+
+		if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+			hw_engine->funcs->read_data(hw_engine, current_payload,
+				current_payload_size, first_iteration ? 1 : 0);
+
+		/* update loop variables */
+
+		first_iteration = false;
+		current_payload += current_payload_size;
+		remaining_payload_size -= current_payload_size;
+	}
+
+	/* update transaction status */
+
+	switch (operation_result) {
+	case I2C_CHANNEL_OPERATION_SUCCEEDED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+		result = true;
+	break;
+	case I2C_CHANNEL_OPERATION_NO_RESPONSE:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+	break;
+	case I2C_CHANNEL_OPERATION_TIMEOUT:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+	break;
+	case I2C_CHANNEL_OPERATION_FAILED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
+	break;
+	default:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
+	}
+
+	return result;
+}
+
+/*
+ * @brief
+ * Returns number of microseconds to wait until timeout to be considered
+ */
+uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout(
+	const struct i2c_hw_engine *engine,
+	uint32_t length)
+{
+	const struct i2c_engine *base = &engine->base;
+
+	uint32_t speed = base->funcs->get_speed(base);
+
+	if (!speed)
+		return 0;
+
+	/* total timeout = period_timeout * (start + data bits count + stop) */
+
+	return ((1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed) *
+		(1 + (length << 3) + 1);
+}
+
+bool dal_i2c_generic_hw_engine_construct(
+	struct i2c_generic_hw_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2c_hw_engine_construct(&engine->base, ctx))
+		return false;
+	return true;
+}
+
+void dal_i2c_generic_hw_engine_destruct(
+	struct i2c_generic_hw_engine *engine)
+{
+	dal_i2c_hw_engine_destruct(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
new file mode 100644
index 000000000000..52f2aa248d95
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
@@ -0,0 +1,77 @@
+/*
+ * 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_I2C_GENERIC_HW_ENGINE_H__
+#define __DAL_I2C_GENERIC_HW_ENGINE_H__
+
+struct i2c_generic_transaction_attributes {
+	enum i2caux_transaction_action action;
+	uint8_t transaction_size;
+	bool start_bit;
+	bool stop_bit;
+	bool last_read;
+};
+
+struct i2c_generic_hw_engine;
+
+struct i2c_generic_hw_engine_funcs {
+	void (*write_address)(
+		struct i2c_generic_hw_engine *engine,
+		uint8_t address);
+	void (*write_data)(
+		struct i2c_generic_hw_engine *engine,
+		const uint8_t *buffer,
+		uint8_t length);
+	void (*read_data)(
+		struct i2c_generic_hw_engine *engine,
+		uint8_t *buffer,
+		uint8_t length,
+		uint32_t offset);
+	void (*execute_transaction)(
+		struct i2c_generic_hw_engine *engine,
+		struct i2c_generic_transaction_attributes *attributes);
+};
+
+struct i2c_generic_hw_engine {
+	struct i2c_hw_engine base;
+	const struct i2c_generic_hw_engine_funcs *funcs;
+};
+
+bool dal_i2c_generic_hw_engine_construct(
+	struct i2c_generic_hw_engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2c_generic_hw_engine_destruct(
+	struct i2c_generic_hw_engine *engine);
+enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type(
+	const struct engine *engine);
+bool dal_i2c_generic_hw_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction);
+uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout(
+	const struct i2c_hw_engine *engine,
+	uint32_t length);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
new file mode 100644
index 000000000000..b02ba7927d5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
@@ -0,0 +1,246 @@
+/*
+ * 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+#include "i2c_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_hw_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_hw_engine *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	container_of((ptr), struct i2c_hw_engine, base)
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_hw_engine *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_I2C_DDC_HW;
+}
+
+bool dal_i2c_hw_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction)
+{
+	struct i2c_hw_engine *hw_engine = FROM_ENGINE(engine);
+
+	struct i2c_request_transaction_data request;
+
+	uint32_t transaction_timeout;
+
+	enum i2c_channel_operation_result operation_result;
+
+	bool result = false;
+
+	/* We need following:
+	 * transaction length will not exceed
+	 * the number of free bytes in HW buffer (minus one for address)*/
+
+	if (i2caux_request->payload.length >=
+		hw_engine->funcs->get_hw_buffer_available_size(hw_engine)) {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW;
+		return false;
+	}
+
+	if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_READ;
+	else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+	else {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
+		/* [anaumov] in DAL2, there was no "return false" */
+		return false;
+	}
+
+	request.address = (uint8_t)i2caux_request->payload.address;
+	request.length = i2caux_request->payload.length;
+	request.data = i2caux_request->payload.data;
+
+	/* obtain timeout value before submitting request */
+
+	transaction_timeout = hw_engine->funcs->get_transaction_timeout(
+		hw_engine, i2caux_request->payload.length + 1);
+
+	hw_engine->base.funcs->submit_channel_request(
+		&hw_engine->base, &request);
+
+	if ((request.status == I2C_CHANNEL_OPERATION_FAILED) ||
+		(request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY)) {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY;
+		return false;
+	}
+
+	/* wait until transaction proceed */
+
+	operation_result = hw_engine->funcs->wait_on_operation_result(
+		hw_engine,
+		transaction_timeout,
+		I2C_CHANNEL_OPERATION_ENGINE_BUSY);
+
+	/* update transaction status */
+
+	switch (operation_result) {
+	case I2C_CHANNEL_OPERATION_SUCCEEDED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+		result = true;
+	break;
+	case I2C_CHANNEL_OPERATION_NO_RESPONSE:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+	break;
+	case I2C_CHANNEL_OPERATION_TIMEOUT:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+	break;
+	case I2C_CHANNEL_OPERATION_FAILED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
+	break;
+	default:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
+	}
+
+	if (result && (i2caux_request->operation == I2CAUX_TRANSACTION_READ)) {
+		struct i2c_reply_transaction_data reply;
+
+		reply.data = i2caux_request->payload.data;
+		reply.length = i2caux_request->payload.length;
+
+		hw_engine->base.funcs->
+			process_channel_reply(&hw_engine->base, &reply);
+	}
+
+	return result;
+}
+
+bool dal_i2c_hw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc)
+{
+	enum gpio_result result;
+	uint32_t current_speed;
+
+	result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
+		GPIO_DDC_CONFIG_TYPE_MODE_I2C);
+
+	if (result != GPIO_RESULT_OK)
+		return false;
+
+	engine->base.ddc = ddc;
+
+	current_speed = engine->funcs->get_speed(engine);
+
+	if (current_speed)
+		FROM_I2C_ENGINE(engine)->original_speed = current_speed;
+
+	return true;
+}
+/*
+ * @brief
+ * Queries in a loop for current engine status
+ * until retrieved status matches 'expected_result', or timeout occurs.
+ * Timeout given in microseconds
+ * and the status query frequency is also one per microsecond.
+ */
+enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result(
+	struct i2c_hw_engine *engine,
+	uint32_t timeout,
+	enum i2c_channel_operation_result expected_result)
+{
+	enum i2c_channel_operation_result result;
+	uint32_t i = 0;
+
+	if (!timeout)
+		return I2C_CHANNEL_OPERATION_SUCCEEDED;
+
+	do {
+		result = engine->base.funcs->get_channel_status(
+			&engine->base, NULL);
+
+		if (result != expected_result)
+			break;
+
+		dm_delay_in_microseconds(engine->base.base.ctx, 1);
+
+		++i;
+	} while (i < timeout);
+
+	return result;
+}
+
+bool dal_i2c_hw_engine_construct(
+	struct i2c_hw_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2c_engine_construct(&engine->base, ctx))
+		return false;
+	engine->original_speed = I2CAUX_DEFAULT_I2C_HW_SPEED;
+	engine->default_speed = I2CAUX_DEFAULT_I2C_HW_SPEED;
+	return true;
+}
+
+void dal_i2c_hw_engine_destruct(
+	struct i2c_hw_engine *engine)
+{
+	dal_i2c_engine_destruct(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
new file mode 100644
index 000000000000..5afbd7067a1f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
@@ -0,0 +1,80 @@
+/*
+ * 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_I2C_HW_ENGINE_H__
+#define __DAL_I2C_HW_ENGINE_H__
+
+enum {
+	TRANSACTION_TIMEOUT_IN_I2C_CLOCKS = 32
+};
+
+struct i2c_hw_engine;
+
+struct i2c_hw_engine_funcs {
+	uint8_t (*get_hw_buffer_available_size)(
+		const struct i2c_hw_engine *engine);
+	enum i2c_channel_operation_result (*wait_on_operation_result)(
+		struct i2c_hw_engine *engine,
+		uint32_t timeout,
+		enum i2c_channel_operation_result expected_result);
+	uint32_t (*get_transaction_timeout)(
+		const struct i2c_hw_engine *engine,
+		uint32_t length);
+};
+
+struct i2c_hw_engine {
+	struct i2c_engine base;
+	const struct i2c_hw_engine_funcs *funcs;
+
+	/* Values below are in kilohertz */
+	uint32_t original_speed;
+	uint32_t default_speed;
+};
+
+bool dal_i2c_hw_engine_construct(
+	struct i2c_hw_engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2c_hw_engine_destruct(
+	struct i2c_hw_engine *engine);
+
+enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result(
+	struct i2c_hw_engine *engine,
+	uint32_t timeout,
+	enum i2c_channel_operation_result expected_result);
+
+bool dal_i2c_hw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc);
+
+bool dal_i2c_hw_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction);
+
+enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type(
+	const struct engine *engine);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
new file mode 100644
index 000000000000..21e8fa2c08ee
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
@@ -0,0 +1,614 @@
+/*
+ * 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+#include "i2c_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_sw_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define SCL false
+#define SDA true
+
+static inline bool read_bit_from_ddc(
+	struct ddc *ddc,
+	bool data_nor_clock)
+{
+	uint32_t value = 0;
+
+	if (data_nor_clock)
+		dal_ddc_get_data(ddc, &value);
+	else
+		dal_ddc_get_clock(ddc, &value);
+
+	return (value != 0);
+}
+
+static inline void write_bit_to_ddc(
+	struct ddc *ddc,
+	bool data_nor_clock,
+	bool bit)
+{
+	uint32_t value = bit ? 1 : 0;
+
+	if (data_nor_clock)
+		dal_ddc_set_data(ddc, value);
+	else
+		dal_ddc_set_clock(ddc, value);
+}
+
+static bool wait_for_scl_high(
+	struct dc_context *ctx,
+	struct ddc *ddc,
+	uint16_t clock_delay_div_4)
+{
+	uint32_t scl_retry = 0;
+	uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	/* 3 milliseconds delay
+	 * to wake up some displays from "low power" state.
+	 */
+
+	do {
+		if (read_bit_from_ddc(ddc, SCL))
+			return true;
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		++scl_retry;
+	} while (scl_retry <= scl_retry_max);
+
+	return false;
+}
+
+static bool start_sync(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4)
+{
+	uint32_t retry = 0;
+
+	/* The I2C communications start signal is:
+	 * the SDA going low from high, while the SCL is high. */
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	do {
+		write_bit_to_ddc(ddc_handle, SDA, true);
+
+		if (!read_bit_from_ddc(ddc_handle, SDA)) {
+			++retry;
+			continue;
+		}
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SCL, true);
+
+		if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+			break;
+
+		write_bit_to_ddc(ddc_handle, SDA, false);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SCL, false);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		return true;
+	} while (retry <= I2C_SW_RETRIES);
+
+	return false;
+}
+
+static bool stop_sync(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4)
+{
+	uint32_t retry = 0;
+
+	/* The I2C communications stop signal is:
+	 * the SDA going high from low, while the SCL is high. */
+
+	write_bit_to_ddc(ddc_handle, SCL, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SDA, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+		return false;
+
+	write_bit_to_ddc(ddc_handle, SDA, true);
+
+	do {
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		if (read_bit_from_ddc(ddc_handle, SDA))
+			return true;
+
+		++retry;
+	} while (retry <= 2);
+
+	return false;
+}
+
+static bool write_byte(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t byte)
+{
+	int32_t shift = 7;
+	bool ack;
+
+	/* bits are transmitted serially, starting from MSB */
+
+	do {
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SCL, true);
+
+		if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+			return false;
+
+		write_bit_to_ddc(ddc_handle, SCL, false);
+
+		--shift;
+	} while (shift >= 0);
+
+	/* The display sends ACK by preventing the SDA from going high
+	 * after the SCL pulse we use to send our last data bit.
+	 * If the SDA goes high after that bit, it's a NACK */
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SDA, true);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+		return false;
+
+	/* read ACK bit */
+
+	ack = !read_bit_from_ddc(ddc_handle, SDA);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4 << 1);
+
+	write_bit_to_ddc(ddc_handle, SCL, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4 << 1);
+
+	return ack;
+}
+
+static bool read_byte(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t *byte,
+	bool more)
+{
+	int32_t shift = 7;
+
+	uint8_t data = 0;
+
+	/* The data bits are read from MSB to LSB;
+	 * bit is read while SCL is high */
+
+	do {
+		write_bit_to_ddc(ddc_handle, SCL, true);
+
+		if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+			return false;
+
+		if (read_bit_from_ddc(ddc_handle, SDA))
+			data |= (1 << shift);
+
+		write_bit_to_ddc(ddc_handle, SCL, false);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4 << 1);
+
+		--shift;
+	} while (shift >= 0);
+
+	/* read only whole byte */
+
+	*byte = data;
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	/* send the acknowledge bit:
+	 * SDA low means ACK, SDA high means NACK */
+
+	write_bit_to_ddc(ddc_handle, SDA, !more);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+		return false;
+
+	write_bit_to_ddc(ddc_handle, SCL, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SDA, true);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	return true;
+}
+
+static bool i2c_write(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t address,
+	uint8_t length,
+	const uint8_t *data)
+{
+	uint32_t i = 0;
+
+	if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address))
+		return false;
+
+	while (i < length) {
+		if (!write_byte(ctx, ddc_handle, clock_delay_div_4, data[i]))
+			return false;
+		++i;
+	}
+
+	return true;
+}
+
+static bool i2c_read(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t address,
+	uint8_t length,
+	uint8_t *data)
+{
+	uint32_t i = 0;
+
+	if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address))
+		return false;
+
+	while (i < length) {
+		if (!read_byte(ctx, ddc_handle, clock_delay_div_4, data + i,
+			i < length - 1))
+			return false;
+		++i;
+	}
+
+	return true;
+}
+
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_sw_engine *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	container_of((ptr), struct i2c_sw_engine, base)
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_sw_engine *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_I2C_SW;
+}
+
+bool dal_i2c_sw_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction)
+{
+	struct i2c_sw_engine *sw_engine = FROM_ENGINE(engine);
+
+	struct i2c_engine *base = &sw_engine->base;
+
+	struct i2c_request_transaction_data request;
+	bool operation_succeeded = false;
+
+	if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_READ;
+	else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+	else {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
+		/* in DAL2, there was no "return false" */
+		return false;
+	}
+
+	request.address = (uint8_t)i2caux_request->payload.address;
+	request.length = i2caux_request->payload.length;
+	request.data = i2caux_request->payload.data;
+
+	base->funcs->submit_channel_request(base, &request);
+
+	if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
+		(request.status == I2C_CHANNEL_OPERATION_FAILED))
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY;
+	else {
+		enum i2c_channel_operation_result operation_result;
+
+		do {
+			operation_result =
+				base->funcs->get_channel_status(base, NULL);
+
+			switch (operation_result) {
+			case I2C_CHANNEL_OPERATION_SUCCEEDED:
+				i2caux_request->status =
+					I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+				operation_succeeded = true;
+			break;
+			case I2C_CHANNEL_OPERATION_NO_RESPONSE:
+				i2caux_request->status =
+					I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+			break;
+			case I2C_CHANNEL_OPERATION_TIMEOUT:
+				i2caux_request->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			break;
+			case I2C_CHANNEL_OPERATION_FAILED:
+				i2caux_request->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
+			break;
+			default:
+				i2caux_request->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
+			break;
+			}
+		} while (operation_result == I2C_CHANNEL_OPERATION_ENGINE_BUSY);
+	}
+
+	return operation_succeeded;
+}
+
+uint32_t dal_i2c_sw_engine_get_speed(
+	const struct i2c_engine *engine)
+{
+	return FROM_I2C_ENGINE(engine)->speed;
+}
+
+void dal_i2c_sw_engine_set_speed(
+	struct i2c_engine *engine,
+	uint32_t speed)
+{
+	struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine);
+
+	ASSERT(speed);
+
+	sw_engine->speed = speed ? speed : I2CAUX_DEFAULT_I2C_SW_SPEED;
+
+	sw_engine->clock_delay = 1000 / sw_engine->speed;
+
+	if (sw_engine->clock_delay < 12)
+		sw_engine->clock_delay = 12;
+}
+
+bool dal_i2caux_i2c_sw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc)
+{
+	enum gpio_result result;
+
+	result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
+		GPIO_DDC_CONFIG_TYPE_MODE_I2C);
+
+	if (result != GPIO_RESULT_OK)
+		return false;
+
+	engine->base.ddc = ddc;
+
+	return true;
+}
+
+void dal_i2c_sw_engine_submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *req)
+{
+	struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine);
+
+	struct ddc *ddc = engine->base.ddc;
+	uint16_t clock_delay_div_4 = sw_engine->clock_delay >> 2;
+
+	/* send sync (start / repeated start) */
+
+	bool result = start_sync(engine->base.ctx, ddc, clock_delay_div_4);
+
+	/* process payload */
+
+	if (result) {
+		switch (req->action) {
+		case I2CAUX_TRANSACTION_ACTION_I2C_WRITE:
+		case I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT:
+			result = i2c_write(engine->base.ctx, ddc, clock_delay_div_4,
+				req->address, req->length, req->data);
+		break;
+		case I2CAUX_TRANSACTION_ACTION_I2C_READ:
+		case I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT:
+			result = i2c_read(engine->base.ctx, ddc, clock_delay_div_4,
+				req->address, req->length, req->data);
+		break;
+		default:
+			result = false;
+		break;
+		}
+	}
+
+	/* send stop if not 'mot' or operation failed */
+
+	if (!result ||
+		(req->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
+		(req->action == I2CAUX_TRANSACTION_ACTION_I2C_READ))
+		if (!stop_sync(engine->base.ctx, ddc, clock_delay_div_4))
+			result = false;
+
+	req->status = result ?
+		I2C_CHANNEL_OPERATION_SUCCEEDED :
+		I2C_CHANNEL_OPERATION_FAILED;
+}
+
+enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status(
+	struct i2c_engine *engine,
+	uint8_t *returned_bytes)
+{
+	return dal_ddc_check_line_aborted(engine->base.ddc) ?
+		I2C_CHANNEL_OPERATION_FAILED :
+		I2C_CHANNEL_OPERATION_SUCCEEDED;
+}
+
+void dal_i2c_sw_engine_destruct(
+	struct i2c_sw_engine *engine)
+{
+	dal_i2c_engine_destruct(&engine->base);
+}
+
+static void destroy(
+	struct i2c_engine **ptr)
+{
+	dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr));
+
+	dm_free((*ptr)->base.ctx, *ptr);
+	*ptr = NULL;
+}
+
+static const struct i2c_engine_funcs i2c_engine_funcs = {
+	.acquire_engine = dal_i2caux_i2c_sw_engine_acquire_engine,
+	.destroy = destroy,
+	.get_speed = dal_i2c_sw_engine_get_speed,
+	.set_speed = dal_i2c_sw_engine_set_speed,
+	.setup_engine = dal_i2c_engine_setup_i2c_engine,
+	.submit_channel_request = dal_i2c_sw_engine_submit_channel_request,
+	.process_channel_reply = dal_i2c_engine_process_channel_reply,
+	.get_channel_status = dal_i2c_sw_engine_get_channel_status,
+};
+
+static void release_engine(
+	struct engine *engine)
+{
+
+}
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.get_engine_type = dal_i2c_sw_engine_get_engine_type,
+	.acquire = dal_i2c_engine_acquire,
+	.submit_request = dal_i2c_sw_engine_submit_request,
+	.keep_power_up_count = dal_i2caux_keep_power_up_count,
+};
+
+bool dal_i2c_sw_engine_construct(
+	struct i2c_sw_engine *engine,
+	const struct i2c_sw_engine_create_arg *arg)
+{
+	if (!dal_i2c_engine_construct(&engine->base, arg->ctx))
+		return false;
+
+	dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed);
+	engine->base.funcs = &i2c_engine_funcs;
+	engine->base.base.funcs = &engine_funcs;
+	return true;
+}
+
+
+
+struct i2c_engine *dal_i2c_sw_engine_create(
+	const struct i2c_sw_engine_create_arg *arg)
+{
+	struct i2c_sw_engine *engine;
+
+	if (!arg) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	engine = dm_alloc(arg->ctx, sizeof(struct i2c_sw_engine));
+
+	if (!engine) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (dal_i2c_sw_engine_construct(engine, arg))
+		return &engine->base;
+
+	BREAK_TO_DEBUGGER();
+
+	dm_free(arg->ctx, engine);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
new file mode 100644
index 000000000000..e0cb4c3d483d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
@@ -0,0 +1,81 @@
+/*
+ * 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_I2C_SW_ENGINE_H__
+#define __DAL_I2C_SW_ENGINE_H__
+
+enum {
+	I2C_SW_RETRIES = 10,
+	I2C_SW_SCL_READ_RETRIES = 128,
+	/* following value is in microseconds */
+	I2C_SW_TIMEOUT_DELAY = 3000
+};
+
+struct i2c_sw_engine;
+
+struct i2c_sw_engine {
+	struct i2c_engine base;
+	uint32_t clock_delay;
+	/* Values below are in KHz */
+	uint32_t speed;
+	uint32_t default_speed;
+};
+
+struct i2c_sw_engine_create_arg {
+	uint32_t default_speed;
+	struct dc_context *ctx;
+};
+
+bool dal_i2c_sw_engine_construct(
+	struct i2c_sw_engine *engine,
+	const struct i2c_sw_engine_create_arg *arg);
+
+bool dal_i2caux_i2c_sw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc_handle);
+
+void dal_i2c_sw_engine_destruct(
+	struct i2c_sw_engine *engine);
+
+struct i2c_engine *dal_i2c_sw_engine_create(
+	const struct i2c_sw_engine_create_arg *arg);
+enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type(
+	const struct engine *engine);
+bool dal_i2c_sw_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction);
+uint32_t dal_i2c_sw_engine_get_speed(
+	const struct i2c_engine *engine);
+void dal_i2c_sw_engine_set_speed(
+	struct i2c_engine *ptr,
+	uint32_t speed);
+void dal_i2c_sw_engine_submit_channel_request(
+	struct i2c_engine *ptr,
+	struct i2c_request_transaction_data *req);
+enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status(
+	struct i2c_engine *engine,
+	uint8_t *returned_bytes);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
new file mode 100644
index 000000000000..4c2f2cb64315
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
@@ -0,0 +1,529 @@
+/*
+ * 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"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2caux.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "engine.h"
+#include "i2c_engine.h"
+#include "aux_engine.h"
+
+/*
+ * This unit
+ */
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) || defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce110/i2caux_dce110.h"
+#endif
+
+#include "diagnostics/i2caux_diag.h"
+
+/*
+ * @brief
+ * Plain API, available publicly
+ */
+
+struct i2caux *dal_i2caux_create(
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	enum dce_version dce_version;
+	enum dce_environment dce_environment;
+
+	if (!as) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	dce_version = dal_adapter_service_get_dce_version(as);
+	dce_environment = dal_adapter_service_get_dce_environment(as);
+
+	if (IS_FPGA_MAXIMUS_DC(dce_environment)) {
+		return dal_i2caux_diag_fpga_create(as, ctx);
+	}
+
+	switch (dce_version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+#endif
+	case DCE_VERSION_11_0:
+		return dal_i2caux_dce110_create(as, ctx);
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+}
+
+bool dal_i2caux_submit_i2c_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct i2c_command *cmd)
+{
+	struct i2c_engine *engine;
+	uint8_t index_of_payload = 0;
+	bool result;
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!cmd) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	switch (cmd->engine) {
+	case I2C_COMMAND_ENGINE_SW:
+		/* try to acquire SW engine first,
+		 * acquire HW engine if SW engine not available */
+		engine = i2caux->funcs->acquire_i2c_sw_engine(i2caux, ddc);
+
+		if (!engine)
+			engine = i2caux->funcs->acquire_i2c_hw_engine(
+				i2caux, ddc);
+	break;
+	case I2C_COMMAND_ENGINE_HW:
+	case I2C_COMMAND_ENGINE_DEFAULT:
+	default:
+		/* try to acquire HW engine first,
+		 * acquire SW engine if HW engine not available */
+		engine = i2caux->funcs->acquire_i2c_hw_engine(i2caux, ddc);
+
+		if (!engine)
+			engine = i2caux->funcs->acquire_i2c_sw_engine(
+				i2caux, ddc);
+	}
+
+	if (!engine)
+		return false;
+
+	engine->funcs->set_speed(engine, cmd->speed);
+
+	result = true;
+
+	while (index_of_payload < cmd->number_of_payloads) {
+		bool mot = (index_of_payload != cmd->number_of_payloads - 1);
+
+		struct i2c_payload *payload = cmd->payloads + index_of_payload;
+
+		struct i2caux_transaction_request request = { 0 };
+
+		request.operation = payload->write ?
+			I2CAUX_TRANSACTION_WRITE :
+			I2CAUX_TRANSACTION_READ;
+
+		request.payload.address_space =
+			I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C;
+		request.payload.address = (payload->address << 1) |
+			!payload->write;
+		request.payload.length = payload->length;
+		request.payload.data = payload->data;
+
+		if (!engine->base.funcs->submit_request(
+			&engine->base, &request, mot)) {
+			result = false;
+			break;
+		}
+
+		++index_of_payload;
+	}
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return result;
+}
+
+bool dal_i2caux_submit_aux_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct aux_command *cmd)
+{
+	struct aux_engine *engine;
+	uint8_t index_of_payload = 0;
+	bool result;
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!cmd) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	engine = i2caux->funcs->acquire_aux_engine(i2caux, ddc);
+
+	if (!engine)
+		return false;
+
+	engine->delay = cmd->defer_delay;
+	engine->max_defer_write_retry = cmd->max_defer_write_retry;
+
+	result = true;
+
+	while (index_of_payload < cmd->number_of_payloads) {
+		bool mot = (index_of_payload != cmd->number_of_payloads - 1);
+
+		struct aux_payload *payload = cmd->payloads + index_of_payload;
+
+		struct i2caux_transaction_request request = { 0 };
+
+		request.operation = payload->write ?
+			I2CAUX_TRANSACTION_WRITE :
+			I2CAUX_TRANSACTION_READ;
+
+		if (payload->i2c_over_aux) {
+			request.payload.address_space =
+				I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C;
+
+			request.payload.address = (payload->address << 1) |
+				!payload->write;
+		} else {
+			request.payload.address_space =
+				I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD;
+
+			request.payload.address = payload->address;
+		}
+
+		request.payload.length = payload->length;
+		request.payload.data = payload->data;
+
+		if (!engine->base.funcs->submit_request(
+			&engine->base, &request, mot)) {
+			result = false;
+			break;
+		}
+
+		++index_of_payload;
+	}
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return result;
+}
+
+static bool get_hw_supported_ddc_line(
+	struct ddc *ddc,
+	enum gpio_ddc_line *line)
+{
+	enum gpio_ddc_line line_found;
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!dal_ddc_is_hw_supported(ddc))
+		return false;
+
+	line_found = dal_ddc_get_line(ddc);
+
+	if (line_found >= GPIO_DDC_LINE_COUNT)
+		return false;
+
+	*line = line_found;
+
+	return true;
+}
+
+void dal_i2caux_keep_engine_power_up(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	bool keep_power_up)
+{
+	enum gpio_ddc_line line;
+	struct i2c_engine *engine;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return;
+
+	engine = i2caux->i2c_hw_engines[line];
+
+	engine->base.funcs->keep_power_up_count(&engine->base, keep_power_up);
+}
+
+bool dal_i2caux_start_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+
+	struct aux_engine *engine;
+
+	bool result;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return false;
+
+	engine = i2caux->aux_engines[line];
+
+	if (!engine)
+		return false;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return false;
+
+	result = engine->funcs->start_gtc_sync(engine);
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return result;
+}
+
+bool dal_i2caux_stop_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+
+	struct aux_engine *engine;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return false;
+
+	engine = i2caux->aux_engines[line];
+
+	if (!engine)
+		return false;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return false;
+
+	engine->funcs->stop_gtc_sync(engine);
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return true;
+}
+
+void dal_i2caux_configure_aux(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	union aux_config cfg)
+{
+	struct aux_engine *engine =
+		i2caux->funcs->acquire_aux_engine(i2caux, ddc);
+
+	if (!engine)
+		return;
+
+	engine->funcs->configure(engine, cfg);
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+}
+
+void dal_i2caux_destroy(
+	struct i2caux **i2caux)
+{
+	if (!i2caux || !*i2caux) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*i2caux)->funcs->destroy(i2caux);
+
+	*i2caux = NULL;
+}
+
+/*
+ * @brief
+ * An utility function used by 'struct i2caux' and its descendants
+ */
+
+uint32_t dal_i2caux_get_reference_clock(
+	struct adapter_service *as)
+{
+	struct firmware_info info = { { 0 } };
+
+	if (!dal_adapter_service_get_firmware_info(as, &info))
+		return 0;
+
+	return info.pll_info.crystal_frequency;
+}
+
+/*
+ * @brief
+ * i2caux
+ */
+
+enum {
+	/* following are expressed in KHz */
+	DEFAULT_I2C_SW_SPEED = 50,
+	DEFAULT_I2C_HW_SPEED = 50,
+
+	/* This is the timeout as defined in DP 1.2a,
+	 * 2.3.4 "Detailed uPacket TX AUX CH State Description". */
+	AUX_TIMEOUT_PERIOD = 400,
+
+	/* Ideally, the SW timeout should be just above 550usec
+	 * which is programmed in HW.
+	 * But the SW timeout of 600usec is not reliable,
+	 * because on some systems, delay_in_microseconds()
+	 * returns faster than it should.
+	 * EPR #379763: by trial-and-error on different systems,
+	 * 700usec is the minimum reliable SW timeout for polling
+	 * the AUX_SW_STATUS.AUX_SW_DONE bit.
+	 * This timeout expires *only* when there is
+	 * AUX Error or AUX Timeout conditions - not during normal operation.
+	 * During normal operation, AUX_SW_STATUS.AUX_SW_DONE bit is set
+	 * at most within ~240usec. That means,
+	 * increasing this timeout will not affect normal operation,
+	 * and we'll timeout after
+	 * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD = 1600usec.
+	 * This timeout is especially important for
+	 * resume from S3 and CTS. */
+	SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 4
+};
+
+struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+	struct i2c_engine *engine = NULL;
+
+	if (get_hw_supported_ddc_line(ddc, &line))
+		engine = i2caux->i2c_sw_engines[line];
+
+	if (!engine)
+		engine = i2caux->i2c_generic_sw_engine;
+
+	if (!engine)
+		return NULL;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return NULL;
+
+	return engine;
+}
+
+struct aux_engine *dal_i2caux_acquire_aux_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+	struct aux_engine *engine;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return NULL;
+
+	engine = i2caux->aux_engines[line];
+
+	if (!engine)
+		return NULL;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return NULL;
+
+	return engine;
+}
+
+void dal_i2caux_release_engine(
+	struct i2caux *i2caux,
+	struct engine *engine)
+{
+	engine->funcs->release_engine(engine);
+
+	dal_ddc_close(engine->ddc);
+
+	engine->ddc = NULL;
+}
+
+bool dal_i2caux_construct(
+	struct i2caux *i2caux,
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	uint32_t i = 0;
+
+	i2caux->ctx = ctx;
+	do {
+		i2caux->i2c_sw_engines[i] = NULL;
+		i2caux->i2c_hw_engines[i] = NULL;
+		i2caux->aux_engines[i] = NULL;
+
+		++i;
+	} while (i < GPIO_DDC_LINE_COUNT);
+
+	i2caux->i2c_generic_sw_engine = NULL;
+	i2caux->i2c_generic_hw_engine = NULL;
+
+	i2caux->aux_timeout_period =
+		SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD;
+
+	i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED;
+	i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED;
+
+	return true;
+}
+
+void dal_i2caux_destruct(
+	struct i2caux *i2caux)
+{
+	uint32_t i = 0;
+
+	if (i2caux->i2c_generic_hw_engine)
+		i2caux->i2c_generic_hw_engine->funcs->destroy(
+			&i2caux->i2c_generic_hw_engine);
+
+	if (i2caux->i2c_generic_sw_engine)
+		i2caux->i2c_generic_sw_engine->funcs->destroy(
+			&i2caux->i2c_generic_sw_engine);
+
+	do {
+		if (i2caux->aux_engines[i])
+			i2caux->aux_engines[i]->funcs->destroy(
+				&i2caux->aux_engines[i]);
+
+		if (i2caux->i2c_hw_engines[i])
+			i2caux->i2c_hw_engines[i]->funcs->destroy(
+				&i2caux->i2c_hw_engines[i]);
+
+		if (i2caux->i2c_sw_engines[i])
+			i2caux->i2c_sw_engines[i]->funcs->destroy(
+				&i2caux->i2c_sw_engines[i]);
+
+		++i;
+	} while (i < GPIO_DDC_LINE_COUNT);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
new file mode 100644
index 000000000000..76f5b637ec3f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
@@ -0,0 +1,123 @@
+/*
+ * 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_I2C_AUX_H__
+#define __DAL_I2C_AUX_H__
+
+uint32_t dal_i2caux_get_reference_clock(
+	struct adapter_service *as);
+
+struct i2caux;
+
+struct engine;
+
+struct i2caux_funcs {
+	void (*destroy)(struct i2caux **ptr);
+	struct i2c_engine * (*acquire_i2c_sw_engine)(
+		struct i2caux *i2caux,
+		struct ddc *ddc);
+	struct i2c_engine * (*acquire_i2c_hw_engine)(
+		struct i2caux *i2caux,
+		struct ddc *ddc);
+	struct aux_engine * (*acquire_aux_engine)(
+		struct i2caux *i2caux,
+		struct ddc *ddc);
+	void (*release_engine)(
+		struct i2caux *i2caux,
+		struct engine *engine);
+};
+
+struct i2c_engine;
+struct aux_engine;
+
+struct i2caux {
+	struct dc_context *ctx;
+	const struct i2caux_funcs *funcs;
+	/* On ASIC we have certain amount of lines with HW DDC engine
+	 * (4, 6, or maybe more in the future).
+	 * For every such line, we create separate HW DDC engine
+	 * (since we have these engines in HW) and separate SW DDC engine
+	 * (to allow concurrent use of few lines).
+	 * In similar way we have AUX engines. */
+
+	/* I2C SW engines, per DDC line.
+	 * Only lines with HW DDC support will be initialized */
+	struct i2c_engine *i2c_sw_engines[GPIO_DDC_LINE_COUNT];
+
+	/* I2C HW engines, per DDC line.
+	 * Only lines with HW DDC support will be initialized */
+	struct i2c_engine *i2c_hw_engines[GPIO_DDC_LINE_COUNT];
+
+	/* AUX engines, per DDC line.
+	 * Only lines with HW AUX support will be initialized */
+	struct aux_engine *aux_engines[GPIO_DDC_LINE_COUNT];
+
+	/* For all other lines, we can use
+	 * single instance of generic I2C HW engine
+	 * (since in HW, there is single instance of it)
+	 * or single instance of generic I2C SW engine.
+	 * AUX is not supported for other lines. */
+
+	/* General-purpose I2C SW engine.
+	 * Can be assigned dynamically to any line per transaction */
+	struct i2c_engine *i2c_generic_sw_engine;
+
+	/* General-purpose I2C generic HW engine.
+	 * Can be assigned dynamically to almost any line per transaction */
+	struct i2c_engine *i2c_generic_hw_engine;
+
+	/* [anaumov] in DAL2, there is a Mutex */
+
+	uint32_t aux_timeout_period;
+
+	/* expressed in KHz */
+	uint32_t default_i2c_sw_speed;
+	uint32_t default_i2c_hw_speed;
+};
+
+bool dal_i2caux_construct(
+	struct i2caux *i2caux,
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+void dal_i2caux_release_engine(
+	struct i2caux *i2caux,
+	struct engine *engine);
+
+void dal_i2caux_destruct(
+	struct i2caux *i2caux);
+
+void dal_i2caux_destroy(
+	struct i2caux **ptr);
+
+struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+struct aux_engine *dal_i2caux_acquire_aux_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2016-02-16 22:28 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
2016-02-11 17:19 ` [PATCH 01/29] drm/amd/dal: Add dal headers Harry Wentland
2016-02-11 17:19 ` [PATCH 02/29] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
2016-02-11 17:19 ` [PATCH 03/29] drm/amd/dal: Fixed point arithmetic Harry Wentland
2016-02-11 17:19 ` [PATCH 04/29] drm/amd/dal: Asic Capabilities Harry Wentland
2016-02-11 17:19 ` [PATCH 05/29] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-11 17:19 ` [PATCH 06/29] drm/amd/dal: Adapter Service Harry Wentland
2016-02-12  0:26   ` Dave Airlie
2016-02-12 14:30     ` Wentland, Harry
2016-02-11 17:19 ` [PATCH 07/29] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-11 17:19 ` [PATCH 08/29] drm/amd/dal: I2C Aux Manager Harry Wentland
2016-02-11 20:19   ` Rob Clark
2016-02-11 20:52     ` Daniel Vetter
2016-02-17  3:23     ` Harry Wentland
2016-02-11 17:19 ` [PATCH 09/29] drm/amd/dal: IRQ Service Harry Wentland
2016-02-11 17:19 ` [PATCH 10/29] drm/amd/dal: GPU Harry Wentland
2016-02-11 17:19 ` [PATCH 11/29] drm/amd/dal: Audio Harry Wentland
2016-02-11 17:19 ` [PATCH 12/29] drm/amd/dal: Bandwidth calculations Harry Wentland
2016-02-11 17:19 ` [PATCH 13/29] drm/amd/dal: Add encoder HW programming Harry Wentland
2016-02-11 17:19 ` [PATCH 14/29] drm/amd/dal: Add clock source " Harry Wentland
2016-02-11 17:19 ` [PATCH 15/29] drm/amd/dal: Add timing generator " Harry Wentland
2016-02-11 17:19 ` [PATCH 16/29] drm/amd/dal: Add surface " Harry Wentland
2016-02-11 17:19 ` [PATCH 17/29] drm/amd/dal: Add framebuffer compression " Harry Wentland
2016-02-11 17:19 ` [PATCH 18/29] drm/amd/dal: Add input pixel processing " Harry Wentland
2016-02-11 17:19 ` [PATCH 19/29] drm/amd/dal: Add output " Harry Wentland
2016-02-11 17:20 ` [PATCH 20/29] drm/amd/dal: Add transform & scaler " Harry Wentland
2016-02-11 17:20 ` [PATCH 21/29] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
2016-02-11 17:20 ` [PATCH 22/29] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
2016-02-11 17:20 ` [PATCH 23/29] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
2016-02-11 17:20 ` [PATCH 24/29] drm/amd/dal: Add display core Harry Wentland
2016-02-11 17:20 ` [PATCH 25/29] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-11 17:20 ` [PATCH 26/29] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
2016-02-11 17:20 ` [PATCH 27/29] drm/amd/dal: Correctly interpret rotation as bit set Harry Wentland
2016-02-11 21:00   ` Oded Gabbay
2016-02-16 16:46     ` Harry Wentland
2016-02-11 17:20 ` [PATCH 28/29] drm/amd/dal: fix flip clean-up state Harry Wentland
2016-02-11 17:20 ` [PATCH 29/29] drm/amd/dal: Force bw programming for DCE 10 until we start calculate BW Harry Wentland
2016-02-11 20:02 ` [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Mike Lothian
2016-02-11 20:05   ` Wentland, Harry
2016-02-11 20:52 ` Dave Airlie
2016-02-11 21:06   ` Daniel Vetter
2016-02-12  0:57     ` Dave Airlie
2016-02-12  5:34     ` Daniel Vetter
2016-02-13  0:05       ` Wentland, Harry
2016-02-14 11:22         ` Jerome Glisse
2016-02-14 13:23           ` Daniel Vetter
2016-02-17  3:28           ` Harry Wentland
2016-02-14 13:32         ` Rob Clark
2016-02-14 13:51           ` Daniel Vetter
2016-02-17  3:26           ` Harry Wentland
2016-02-14 14:01         ` Daniel Vetter
2016-02-17  3:32           ` Harry Wentland
2016-02-14 21:44         ` Daniel Stone
2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 01/26] drm/amd/dal: Add dal headers Harry Wentland
2016-02-16 22:27   ` [PATCH v2 02/26] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
2016-02-16 22:27   ` [PATCH v2 03/26] drm/amd/dal: Fixed point arithmetic Harry Wentland
2016-02-16 22:27   ` [PATCH v2 04/26] drm/amd/dal: Asic Capabilities Harry Wentland
2016-02-16 22:27   ` [PATCH v2 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-16 22:27   ` [PATCH v2 06/26] drm/amd/dal: Adapter Service Harry Wentland
2016-02-16 22:27   ` [PATCH v2 07/26] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-16 22:27   ` Harry Wentland [this message]
2016-02-16 22:27   ` [PATCH v2 09/26] drm/amd/dal: IRQ Service Harry Wentland
2016-02-16 22:27   ` [PATCH v2 10/26] drm/amd/dal: GPU Harry Wentland
2016-02-16 22:27   ` [PATCH v2 11/26] drm/amd/dal: Audio Harry Wentland
2016-02-16 22:27   ` [PATCH v2 12/26] drm/amd/dal: Bandwidth calculations Harry Wentland
2016-02-16 22:27   ` [PATCH v2 13/26] drm/amd/dal: Add encoder HW programming Harry Wentland
2016-02-16 22:27   ` [PATCH v2 14/26] drm/amd/dal: Add clock source " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 15/26] drm/amd/dal: Add timing generator " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 16/26] drm/amd/dal: Add surface " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 17/26] drm/amd/dal: Add framebuffer compression " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 18/26] drm/amd/dal: Add input pixel processing " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 19/26] drm/amd/dal: Add output " Harry Wentland
2016-02-16 22:28   ` [PATCH v2 20/26] drm/amd/dal: Add transform & scaler " Harry Wentland
2016-02-16 22:28   ` [PATCH v2 21/26] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
2016-02-16 22:28   ` [PATCH v2 22/26] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
2016-02-16 22:28   ` [PATCH v2 23/26] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
2016-02-16 22:28   ` [PATCH v2 24/26] drm/amd/dal: Add display core Harry Wentland
2016-02-16 22:28   ` [PATCH v2 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-16 22:28   ` [PATCH v2 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
2016-02-29 21:56   ` [PATCH v3 01/26] drm/amd/dal: Add dal headers Harry Wentland
2016-02-29 21:56   ` [PATCH v3 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-29 21:56   ` [PATCH v3 07/26] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-29 21:56   ` [PATCH v3 24/26] drm/amd/dal: Add display core Harry Wentland
2016-02-29 21:56   ` [PATCH v3 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-29 21:56   ` [PATCH v3 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cfa0de41e13f5afb8e1368ea127b6bbe7c568e9a.1455660367.git.harry.wentland@amd.com \
    --to=harry.wentland@amd.com \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.