diff options
Diffstat (limited to 'meta-r1000/recipes-kernel/linux/linux-yocto-4.14.71/5001-drm-amd-display-Decouple-aux-from-i2c.patch')
-rw-r--r-- | meta-r1000/recipes-kernel/linux/linux-yocto-4.14.71/5001-drm-amd-display-Decouple-aux-from-i2c.patch | 1949 |
1 files changed, 0 insertions, 1949 deletions
diff --git a/meta-r1000/recipes-kernel/linux/linux-yocto-4.14.71/5001-drm-amd-display-Decouple-aux-from-i2c.patch b/meta-r1000/recipes-kernel/linux/linux-yocto-4.14.71/5001-drm-amd-display-Decouple-aux-from-i2c.patch deleted file mode 100644 index 27ed2499..00000000 --- a/meta-r1000/recipes-kernel/linux/linux-yocto-4.14.71/5001-drm-amd-display-Decouple-aux-from-i2c.patch +++ /dev/null @@ -1,1949 +0,0 @@ -From 2e972f9d807a5d585a1d05bea81e34cf21389ee4 Mon Sep 17 00:00:00 2001 -From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> -Date: Tue, 10 Jul 2018 17:20:17 -0400 -Subject: [PATCH 5001/5725] drm/amd/display: Decouple aux from i2c - -[Why] -Aux engine is created from i2caux layer. We want to remove this layer -and use the engine directly. - -[How] -Decouple aux engine from i2caux. Move aux engine related code to dce folder and use -dc resource pool to manage the engine. And use the engine functions directly - -Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> -Reviewed-by: Harry Wentland <Harry.Wentland@amd.com> -Acked-by: Leo Li <sunpeng.li@amd.com> -Signed-off-by: Alex Deucher <alexander.deucher@amd.com> ---- - drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 22 +- - drivers/gpu/drm/amd/display/dc/dce/Makefile | 2 +- - drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 942 +++++++++++++++++++++ - drivers/gpu/drm/amd/display/dc/dce/dce_aux.h | 111 +++ - .../drm/amd/display/dc/dce100/dce100_resource.c | 42 + - .../drm/amd/display/dc/dce110/dce110_resource.c | 45 + - .../drm/amd/display/dc/dce112/dce112_resource.c | 47 + - .../drm/amd/display/dc/dce120/dce120_resource.c | 42 + - .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 44 + - .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 44 + - drivers/gpu/drm/amd/display/dc/i2caux/engine.h | 1 + - drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- - drivers/gpu/drm/amd/display/dc/inc/hw/aux_engine.h | 113 +++ - drivers/gpu/drm/amd/display/dc/inc/hw/engine.h | 106 +++ - 14 files changed, 1549 insertions(+), 14 deletions(-) - create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_aux.c - create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_aux.h - create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/aux_engine.h - create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/engine.h - -diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c -index 08c9d73..4019fe07 100644 ---- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c -+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c -@@ -33,10 +33,8 @@ - #include "include/vector.h" - #include "core_types.h" - #include "dc_link_ddc.h" --#include "i2caux/engine.h" --#include "i2caux/i2c_engine.h" --#include "i2caux/aux_engine.h" --#include "i2caux/i2caux.h" -+#include "engine.h" -+#include "aux_engine.h" - - #define AUX_POWER_UP_WA_DELAY 500 - #define I2C_OVER_AUX_DEFER_WA_DELAY 70 -@@ -641,9 +639,9 @@ int dc_link_aux_transfer(struct ddc_service *ddc, - enum aux_transaction_type type, - enum i2caux_transaction_action action) - { -- struct i2caux *i2caux = ddc->ctx->i2caux; - struct ddc *ddc_pin = ddc->ddc_pin; -- struct aux_engine *engine; -+ struct engine *engine; -+ struct aux_engine *aux_engine; - enum aux_channel_operation_result operation_result; - struct aux_request_transaction_data aux_req; - struct aux_reply_transaction_data aux_rep; -@@ -654,7 +652,8 @@ int dc_link_aux_transfer(struct ddc_service *ddc, - memset(&aux_req, 0, sizeof(aux_req)); - memset(&aux_rep, 0, sizeof(aux_rep)); - -- engine = i2caux->funcs->acquire_aux_engine(i2caux, ddc_pin); -+ engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; -+ aux_engine = engine->funcs->acquire(engine, ddc_pin); - - aux_req.type = type; - aux_req.action = action; -@@ -664,15 +663,15 @@ int dc_link_aux_transfer(struct ddc_service *ddc, - aux_req.length = size; - aux_req.data = buffer; - -- engine->funcs->submit_channel_request(engine, &aux_req); -- operation_result = engine->funcs->get_channel_status(engine, &returned_bytes); -+ aux_engine->funcs->submit_channel_request(aux_engine, &aux_req); -+ operation_result = aux_engine->funcs->get_channel_status(aux_engine, &returned_bytes); - - switch (operation_result) { - case AUX_CHANNEL_OPERATION_SUCCEEDED: - res = returned_bytes; - - if (res <= size && res >= 0) -- res = engine->funcs->read_channel_reply(engine, size, -+ res = aux_engine->funcs->read_channel_reply(aux_engine, size, - buffer, reply, - &status); - -@@ -686,8 +685,7 @@ int dc_link_aux_transfer(struct ddc_service *ddc, - res = -1; - break; - } -- -- i2caux->funcs->release_engine(i2caux, &engine->base); -+ aux_engine->base.funcs->release_engine(&aux_engine->base); - return res; - } - -diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile -index 8abec0b..67b0852 100644 ---- a/drivers/gpu/drm/amd/display/dc/dce/Makefile -+++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile -@@ -7,7 +7,7 @@ - - DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ - dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ --dce_clocks.o dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o -+dce_clocks.o dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o - - - AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) -diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c -new file mode 100644 -index 0000000..b28e212 ---- /dev/null -+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c -@@ -0,0 +1,942 @@ -+/* -+ * 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 "dce_aux.h" -+#include "dce/dce_11_0_sh_mask.h" -+ -+#define CTX \ -+ aux110->base.base.ctx -+#define REG(reg_name)\ -+ (aux110->regs->reg_name) -+ -+#define DC_LOGGER \ -+ engine->base.ctx->logger -+ -+#include "reg_helper.h" -+ -+#define FROM_AUX_ENGINE(ptr) \ -+ container_of((ptr), struct aux_engine_dce110, base) -+ -+#define FROM_ENGINE(ptr) \ -+ FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base)) -+ -+#define FROM_AUX_ENGINE_ENGINE(ptr) \ -+ container_of((ptr), struct aux_engine, base) -+enum { -+ AUX_INVALID_REPLY_RETRY_COUNTER = 1, -+ AUX_TIMED_OUT_RETRY_COUNTER = 2, -+ AUX_DEFER_RETRY_COUNTER = 6 -+}; -+static void release_engine( -+ struct engine *engine) -+{ -+ struct aux_engine_dce110 *aux110 = FROM_ENGINE(engine); -+ -+ dal_ddc_close(engine->ddc); -+ -+ engine->ddc = NULL; -+ -+ REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1); -+} -+ -+#define SW_CAN_ACCESS_AUX 1 -+#define DMCU_CAN_ACCESS_AUX 2 -+ -+static bool is_engine_available( -+ struct aux_engine *engine) -+{ -+ struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); -+ -+ uint32_t value = REG_READ(AUX_ARB_CONTROL); -+ uint32_t field = get_reg_field_value( -+ value, -+ AUX_ARB_CONTROL, -+ AUX_REG_RW_CNTL_STATUS); -+ -+ return (field != DMCU_CAN_ACCESS_AUX); -+} -+static bool acquire_engine( -+ struct aux_engine *engine) -+{ -+ struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); -+ -+ uint32_t value = REG_READ(AUX_ARB_CONTROL); -+ uint32_t field = get_reg_field_value( -+ value, -+ AUX_ARB_CONTROL, -+ AUX_REG_RW_CNTL_STATUS); -+ if (field == DMCU_CAN_ACCESS_AUX) -+ return false; -+ /* enable AUX before request SW to access AUX */ -+ value = REG_READ(AUX_CONTROL); -+ field = get_reg_field_value(value, -+ AUX_CONTROL, -+ AUX_EN); -+ -+ if (field == 0) { -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_CONTROL, -+ AUX_EN); -+ -+ if (REG(AUX_RESET_MASK)) { -+ /*DP_AUX block as part of the enable sequence*/ -+ set_reg_field_value( -+ value, -+ 1, -+ AUX_CONTROL, -+ AUX_RESET); -+ } -+ -+ REG_WRITE(AUX_CONTROL, value); -+ -+ if (REG(AUX_RESET_MASK)) { -+ /*poll HW to make sure reset it done*/ -+ -+ REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1, -+ 1, 11); -+ -+ set_reg_field_value( -+ value, -+ 0, -+ AUX_CONTROL, -+ AUX_RESET); -+ -+ REG_WRITE(AUX_CONTROL, value); -+ -+ REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0, -+ 1, 11); -+ } -+ } /*if (field)*/ -+ -+ /* request SW to access AUX */ -+ REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1); -+ -+ value = REG_READ(AUX_ARB_CONTROL); -+ field = get_reg_field_value( -+ value, -+ AUX_ARB_CONTROL, -+ AUX_REG_RW_CNTL_STATUS); -+ -+ return (field == SW_CAN_ACCESS_AUX); -+} -+ -+#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 *aux110 = 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))); -+ if (REG(AUXN_IMPCAL)) { -+ /* clear_aux_error */ -+ REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, -+ 1, -+ 0); -+ -+ REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, -+ 1, -+ 0); -+ -+ /* force_default_calibrate */ -+ REG_UPDATE_1BY1_2(AUXN_IMPCAL, -+ AUXN_IMPCAL_ENABLE, 1, -+ AUXN_IMPCAL_OVERRIDE_ENABLE, 0); -+ -+ /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ -+ -+ REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, -+ 1, -+ 0); -+ } -+ /* set the delay and the number of bytes to write */ -+ -+ /* 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; -+ -+ REG_UPDATE_2(AUX_SW_CONTROL, -+ AUX_SW_START_DELAY, request->delay, -+ AUX_SW_WR_BYTES, length); -+ -+ /* program action and address and payload data (if 'is_write') */ -+ value = REG_UPDATE_4(AUX_SW_DATA, -+ AUX_SW_INDEX, 0, -+ AUX_SW_DATA_RW, 0, -+ AUX_SW_AUTOINCREMENT_DISABLE, 1, -+ AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address)); -+ -+ value = REG_SET_2(AUX_SW_DATA, value, -+ AUX_SW_AUTOINCREMENT_DISABLE, 0, -+ AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address)); -+ -+ value = REG_SET(AUX_SW_DATA, value, -+ AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address)); -+ -+ if (request->length) { -+ value = REG_SET(AUX_SW_DATA, value, -+ AUX_SW_DATA, request->length - 1); -+ } -+ -+ 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) { -+ value = REG_SET(AUX_SW_DATA, value, -+ AUX_SW_DATA, request->data[i]); -+ -+ ++i; -+ } -+ } -+ -+ REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1); -+ REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0, -+ 10, aux110->timeout_period/10); -+ REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); -+} -+ -+static int read_channel_reply(struct aux_engine *engine, uint32_t size, -+ uint8_t *buffer, uint8_t *reply_result, -+ uint32_t *sw_status) -+{ -+ struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); -+ uint32_t bytes_replied; -+ uint32_t reply_result_32; -+ -+ *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, -+ &bytes_replied); -+ -+ /* In case HPD is LOW, exit AUX transaction */ -+ if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) -+ return -1; -+ -+ /* Need at least the status byte */ -+ if (!bytes_replied) -+ return -1; -+ -+ REG_UPDATE_1BY1_3(AUX_SW_DATA, -+ AUX_SW_INDEX, 0, -+ AUX_SW_AUTOINCREMENT_DISABLE, 1, -+ AUX_SW_DATA_RW, 1); -+ -+ REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32); -+ reply_result_32 = reply_result_32 >> 4; -+ *reply_result = (uint8_t)reply_result_32; -+ -+ if (reply_result_32 == 0) { /* ACK */ -+ uint32_t i = 0; -+ -+ /* First byte was already used to get the command status */ -+ --bytes_replied; -+ -+ /* Do not overflow buffer */ -+ if (bytes_replied > size) -+ return -1; -+ -+ while (i < bytes_replied) { -+ uint32_t aux_sw_data_val; -+ -+ REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); -+ buffer[i] = aux_sw_data_val; -+ ++i; -+ } -+ -+ return i; -+ } -+ -+ return 0; -+} -+ -+static void process_channel_reply( -+ struct aux_engine *engine, -+ struct aux_reply_transaction_data *reply) -+{ -+ int bytes_replied; -+ uint8_t reply_result; -+ uint32_t sw_status; -+ -+ bytes_replied = read_channel_reply(engine, reply->length, reply->data, -+ &reply_result, &sw_status); -+ -+ /* in case HPD is LOW, exit AUX transaction */ -+ if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { -+ reply->status = AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON; -+ return; -+ } -+ -+ if (bytes_replied < 0) { -+ /* 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 (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { -+ reply->status = AUX_TRANSACTION_REPLY_INVALID; -+ ASSERT_CRITICAL(false); -+ return; -+ } -+ } else { -+ -+ switch (reply_result) { -+ case 0: /* ACK */ -+ 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; -+ } -+ } -+} -+ -+static enum aux_channel_operation_result get_channel_status( -+ struct aux_engine *engine, -+ uint8_t *returned_bytes) -+{ -+ struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); -+ -+ uint32_t value; -+ -+ 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 */ -+ value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, -+ 10, aux110->timeout_period/10); -+ -+ /* in case HPD is LOW, exit AUX transaction */ -+ if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) -+ return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON; -+ -+ /* Note that the following bits are set in 'status.bits' -+ * during CTS 4.2.1.2 (FW 3.3.1): -+ * 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 (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) { -+ if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) || -+ (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK)) -+ return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; -+ -+ else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) || -+ (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) || -+ (value & -+ AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) || -+ (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK)) -+ 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 -+ * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point -+ */ -+ ASSERT_CRITICAL(false); -+ return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; -+ } -+} -+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; -+ case AUX_TRANSACTION_REPLY_HPD_DISCON: -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; -+ 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 -+ udelay(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; -+ case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; -+ ctx->operation_succeeded = false; -+ 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 { -+ 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) -+ msleep(engine->delay); -+ } while (ctx.operation_succeeded && !ctx.transaction_complete); -+ -+ if (request->payload.address_space == -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { -+ DC_LOG_I2C_AUX("READ: addr:0x%x value:0x%x Result:%d", -+ request->payload.address, -+ request->payload.data[0], -+ ctx.operation_succeeded); -+ } -+ -+ return ctx.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 -+ udelay(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; -+ case AUX_TRANSACTION_REPLY_HPD_DISCON: -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; -+ 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 -+ udelay(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; -+ case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: -+ ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; -+ ctx->operation_succeeded = false; -+ 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) -+ msleep(engine->delay); -+ } while (ctx.operation_succeeded && !ctx.transaction_complete); -+ -+ if (request->payload.address_space == -+ I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { -+ DC_LOG_I2C_AUX("WRITE: addr:0x%x value:0x%x Result:%d", -+ request->payload.address, -+ request->payload.data[0], -+ ctx.operation_succeeded); -+ } -+ -+ 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 submit_request( -+ struct engine *engine, -+ struct i2caux_transaction_request *request, -+ bool middle_of_transaction) -+{ -+ struct aux_engine *aux_engine = FROM_AUX_ENGINE_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; -+} -+enum i2caux_engine_type get_engine_type( -+ const struct engine *engine) -+{ -+ return I2CAUX_ENGINE_TYPE_AUX; -+} -+ -+static struct aux_engine *acquire( -+ struct engine *engine, -+ struct ddc *ddc) -+{ -+ struct aux_engine *aux_engine = FROM_AUX_ENGINE_ENGINE(engine); -+ enum gpio_result result; -+ -+ if (aux_engine->funcs->is_engine_available) { -+ /*check whether SW could use the engine*/ -+ if (!aux_engine->funcs->is_engine_available(aux_engine)) -+ return NULL; -+ } -+ -+ result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, -+ GPIO_DDC_CONFIG_TYPE_MODE_AUX); -+ -+ if (result != GPIO_RESULT_OK) -+ return NULL; -+ -+ if (!aux_engine->funcs->acquire_engine(aux_engine)) { -+ dal_ddc_close(ddc); -+ return NULL; -+ } -+ -+ engine->ddc = ddc; -+ -+ return aux_engine; -+} -+ -+static const struct aux_engine_funcs aux_engine_funcs = { -+ .acquire_engine = acquire_engine, -+ .submit_channel_request = submit_channel_request, -+ .process_channel_reply = process_channel_reply, -+ .read_channel_reply = read_channel_reply, -+ .get_channel_status = get_channel_status, -+ .is_engine_available = is_engine_available, -+}; -+ -+static const struct engine_funcs engine_funcs = { -+ .release_engine = release_engine, -+ .destroy_engine = dce110_engine_destroy, -+ .submit_request = submit_request, -+ .get_engine_type = get_engine_type, -+ .acquire = acquire, -+}; -+ -+void dce110_engine_destroy(struct engine **engine) -+{ -+ -+ struct aux_engine_dce110 *engine110 = FROM_ENGINE(*engine); -+ -+ kfree(engine110); -+ *engine = NULL; -+ -+} -+struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110, -+ struct dc_context *ctx, -+ uint32_t inst, -+ uint32_t timeout_period, -+ const struct dce110_aux_registers *regs) -+{ -+ aux_engine110->base.base.ddc = NULL; -+ aux_engine110->base.base.ctx = ctx; -+ aux_engine110->base.delay = 0; -+ aux_engine110->base.max_defer_write_retry = 0; -+ aux_engine110->base.base.funcs = &engine_funcs; -+ aux_engine110->base.funcs = &aux_engine_funcs; -+ aux_engine110->base.base.inst = inst; -+ aux_engine110->timeout_period = timeout_period; -+ aux_engine110->regs = regs; -+ -+ return &aux_engine110->base; -+} -+ -diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h -new file mode 100644 -index 0000000..c6b2aec ---- /dev/null -+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h -@@ -0,0 +1,111 @@ -+/* -+ * 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" -+ -+#define AUX_COMMON_REG_LIST(id)\ -+ SRI(AUX_CONTROL, DP_AUX, id), \ -+ SRI(AUX_ARB_CONTROL, DP_AUX, id), \ -+ SRI(AUX_SW_DATA, DP_AUX, id), \ -+ SRI(AUX_SW_CONTROL, DP_AUX, id), \ -+ SRI(AUX_INTERRUPT_CONTROL, DP_AUX, id), \ -+ SRI(AUX_SW_STATUS, DP_AUX, id), \ -+ SR(AUXN_IMPCAL), \ -+ SR(AUXP_IMPCAL) -+ -+struct dce110_aux_registers { -+ 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 AUXN_IMPCAL; -+ uint32_t AUXP_IMPCAL; -+ -+ uint32_t AUX_RESET_MASK; -+}; -+ -+enum { /* 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 aux_engine_dce110 { -+ struct aux_engine base; -+ const struct dce110_aux_registers *regs; -+ 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; -+ } addr; -+ uint32_t timeout_period; -+}; -+ -+struct aux_engine_dce110_init_data { -+ uint32_t engine_id; -+ uint32_t timeout_period; -+ struct dc_context *ctx; -+ const struct dce110_aux_registers *regs; -+}; -+ -+struct aux_engine *dce110_aux_engine_construct( -+ struct aux_engine_dce110 *aux_engine110, -+ struct dc_context *ctx, -+ uint32_t inst, -+ uint32_t timeout_period, -+ const struct dce110_aux_registers *regs); -+ -+void dce110_engine_destroy(struct engine **engine); -+ -+bool dce110_aux_engine_acquire( -+ struct engine *aux_engine, -+ struct ddc *ddc); -+#endif -diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c -index ad8ad4e..c34c953 100644 ---- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c -@@ -52,6 +52,7 @@ - #include "dce/dce_10_0_sh_mask.h" - - #include "dce/dce_dmcu.h" -+#include "dce/dce_aux.h" - #include "dce/dce_abm.h" - - #ifndef mmMC_HUB_RDREQ_DMIF_LIMIT -@@ -279,7 +280,20 @@ static const struct dce_opp_shift opp_shift = { - static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_100(_MASK) - }; -+#define aux_engine_regs(id)\ -+[id] = {\ -+ AUX_COMMON_REG_LIST(id), \ -+ .AUX_RESET_MASK = 0 \ -+} - -+static const struct dce110_aux_registers aux_engine_regs[] = { -+ aux_engine_regs(0), -+ aux_engine_regs(1), -+ aux_engine_regs(2), -+ aux_engine_regs(3), -+ aux_engine_regs(4), -+ aux_engine_regs(5) -+}; - - #define audio_regs(id)\ - [id] = {\ -@@ -572,6 +586,23 @@ struct output_pixel_processor *dce100_opp_create( - return &opp->base; - } - -+struct engine *dce100_aux_engine_create( -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ struct aux_engine_dce110 *aux_engine = -+ kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); -+ -+ if (!aux_engine) -+ return NULL; -+ -+ dce110_aux_engine_construct(aux_engine, ctx, inst, -+ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, -+ &aux_engine_regs[inst]); -+ -+ return &aux_engine->base.base; -+} -+ - struct clock_source *dce100_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, -@@ -624,6 +655,10 @@ static void destruct(struct dce110_resource_pool *pool) - kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } -+ -+ if (pool->base.engines[i] != NULL) -+ dce110_engine_destroy(&pool->base.engines[i]); -+ - } - - for (i = 0; i < pool->base.stream_enc_count; i++) { -@@ -928,6 +963,13 @@ static bool construct( - "DC: failed to create output pixel processor!\n"); - goto res_create_fail; - } -+ pool->base.engines[i] = dce100_aux_engine_create(ctx, i); -+ if (pool->base.engines[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error( -+ "DC:failed to create aux engine!!\n"); -+ goto res_create_fail; -+ } - } - - dc->caps.max_planes = pool->base.pipe_count; -diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c -index 1c902e4..4a665a2 100644 ---- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c -@@ -49,6 +49,7 @@ - #include "dce/dce_clock_source.h" - #include "dce/dce_hwseq.h" - #include "dce110/dce110_hw_sequencer.h" -+#include "dce/dce_aux.h" - #include "dce/dce_abm.h" - #include "dce/dce_dmcu.h" - -@@ -306,6 +307,21 @@ static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_110(_MASK) - }; - -+#define aux_engine_regs(id)\ -+[id] = {\ -+ AUX_COMMON_REG_LIST(id), \ -+ .AUX_RESET_MASK = 0 \ -+} -+ -+static const struct dce110_aux_registers aux_engine_regs[] = { -+ aux_engine_regs(0), -+ aux_engine_regs(1), -+ aux_engine_regs(2), -+ aux_engine_regs(3), -+ aux_engine_regs(4), -+ aux_engine_regs(5) -+}; -+ - #define audio_regs(id)\ - [id] = {\ - AUD_COMMON_REG_LIST(id)\ -@@ -588,6 +604,23 @@ static struct output_pixel_processor *dce110_opp_create( - return &opp->base; - } - -+struct engine *dce110_aux_engine_create( -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ struct aux_engine_dce110 *aux_engine = -+ kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); -+ -+ if (!aux_engine) -+ return NULL; -+ -+ dce110_aux_engine_construct(aux_engine, ctx, inst, -+ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, -+ &aux_engine_regs[inst]); -+ -+ return &aux_engine->base.base; -+} -+ - struct clock_source *dce110_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, -@@ -651,6 +684,10 @@ static void destruct(struct dce110_resource_pool *pool) - kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } -+ -+ if (pool->base.engines[i] != NULL) -+ dce110_engine_destroy(&pool->base.engines[i]); -+ - } - - for (i = 0; i < pool->base.stream_enc_count; i++) { -@@ -1258,6 +1295,14 @@ static bool construct( - "DC: failed to create output pixel processor!\n"); - goto res_create_fail; - } -+ -+ pool->base.engines[i] = dce110_aux_engine_create(ctx, i); -+ if (pool->base.engines[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error( -+ "DC:failed to create aux engine!!\n"); -+ goto res_create_fail; -+ } - } - - dc->fbc_compressor = dce110_compressor_create(ctx); -diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c -index 30d5b32..caf90ae 100644 ---- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c -@@ -49,6 +49,7 @@ - #include "dce112/dce112_hw_sequencer.h" - #include "dce/dce_abm.h" - #include "dce/dce_dmcu.h" -+#include "dce/dce_aux.h" - - #include "reg_helper.h" - -@@ -314,6 +315,21 @@ static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_112(_MASK) - }; - -+#define aux_engine_regs(id)\ -+[id] = {\ -+ AUX_COMMON_REG_LIST(id), \ -+ .AUX_RESET_MASK = 0 \ -+} -+ -+static const struct dce110_aux_registers aux_engine_regs[] = { -+ aux_engine_regs(0), -+ aux_engine_regs(1), -+ aux_engine_regs(2), -+ aux_engine_regs(3), -+ aux_engine_regs(4), -+ aux_engine_regs(5) -+}; -+ - #define audio_regs(id)\ - [id] = {\ - AUD_COMMON_REG_LIST(id)\ -@@ -588,6 +604,23 @@ struct output_pixel_processor *dce112_opp_create( - return &opp->base; - } - -+struct engine *dce112_aux_engine_create( -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ struct aux_engine_dce110 *aux_engine = -+ kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); -+ -+ if (!aux_engine) -+ return NULL; -+ -+ dce110_aux_engine_construct(aux_engine, ctx, inst, -+ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, -+ &aux_engine_regs[inst]); -+ -+ return &aux_engine->base.base; -+} -+ - struct clock_source *dce112_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, -@@ -625,6 +658,9 @@ static void destruct(struct dce110_resource_pool *pool) - if (pool->base.opps[i] != NULL) - dce110_opp_destroy(&pool->base.opps[i]); - -+ if (pool->base.engines[i] != NULL) -+ dce110_engine_destroy(&pool->base.engines[i]); -+ - if (pool->base.transforms[i] != NULL) - dce112_transform_destroy(&pool->base.transforms[i]); - -@@ -640,6 +676,10 @@ static void destruct(struct dce110_resource_pool *pool) - kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } -+ -+ if (pool->base.engines[i] != NULL) -+ dce110_engine_destroy(&pool->base.engines[i]); -+ - } - - for (i = 0; i < pool->base.stream_enc_count; i++) { -@@ -1208,6 +1248,13 @@ static bool construct( - "DC:failed to create output pixel processor!\n"); - goto res_create_fail; - } -+ pool->base.engines[i] = dce112_aux_engine_create(ctx, i); -+ if (pool->base.engines[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error( -+ "DC:failed to create aux engine!!\n"); -+ goto res_create_fail; -+ } - } - - if (!resource_construct(num_virtual_links, dc, &pool->base, -diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c -index 8381f27..e389832 100644 ---- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c -@@ -53,6 +53,7 @@ - #include "dce/dce_hwseq.h" - #include "dce/dce_abm.h" - #include "dce/dce_dmcu.h" -+#include "dce/dce_aux.h" - - #include "dce/dce_12_0_offset.h" - #include "dce/dce_12_0_sh_mask.h" -@@ -297,6 +298,20 @@ static const struct dce_opp_shift opp_shift = { - static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_120(_MASK) - }; -+ #define aux_engine_regs(id)\ -+[id] = {\ -+ AUX_COMMON_REG_LIST(id), \ -+ .AUX_RESET_MASK = 0 \ -+} -+ -+static const struct dce110_aux_registers aux_engine_regs[] = { -+ aux_engine_regs(0), -+ aux_engine_regs(1), -+ aux_engine_regs(2), -+ aux_engine_regs(3), -+ aux_engine_regs(4), -+ aux_engine_regs(5) -+}; - - #define audio_regs(id)\ - [id] = {\ -@@ -361,6 +376,22 @@ struct output_pixel_processor *dce120_opp_create( - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; - } -+struct engine *dce120_aux_engine_create( -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ struct aux_engine_dce110 *aux_engine = -+ kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); -+ -+ if (!aux_engine) -+ return NULL; -+ -+ dce110_aux_engine_construct(aux_engine, ctx, inst, -+ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, -+ &aux_engine_regs[inst]); -+ -+ return &aux_engine->base.base; -+} - - static const struct bios_registers bios_regs = { - .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX) -@@ -467,6 +498,10 @@ static void destruct(struct dce110_resource_pool *pool) - kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } -+ -+ if (pool->base.engines[i] != NULL) -+ dce110_engine_destroy(&pool->base.engines[i]); -+ - } - - for (i = 0; i < pool->base.audio_count; i++) { -@@ -984,6 +1019,13 @@ static bool construct( - dm_error( - "DC: failed to create output pixel processor!\n"); - } -+ pool->base.engines[i] = dce120_aux_engine_create(ctx, i); -+ if (pool->base.engines[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error( -+ "DC:failed to create aux engine!!\n"); -+ goto res_create_fail; -+ } - - /* check next valid pipe */ - j++; -diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c -index 2ac95ec..6fb33ad 100644 ---- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c -@@ -54,6 +54,7 @@ - #include "reg_helper.h" - - #include "dce/dce_dmcu.h" -+#include "dce/dce_aux.h" - #include "dce/dce_abm.h" - /* TODO remove this include */ - -@@ -298,6 +299,21 @@ static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK) - }; - -+#define aux_engine_regs(id)\ -+[id] = {\ -+ AUX_COMMON_REG_LIST(id), \ -+ .AUX_RESET_MASK = 0 \ -+} -+ -+static const struct dce110_aux_registers aux_engine_regs[] = { -+ aux_engine_regs(0), -+ aux_engine_regs(1), -+ aux_engine_regs(2), -+ aux_engine_regs(3), -+ aux_engine_regs(4), -+ aux_engine_regs(5) -+}; -+ - #define audio_regs(id)\ - [id] = {\ - AUD_COMMON_REG_LIST(id)\ -@@ -448,6 +464,23 @@ static struct output_pixel_processor *dce80_opp_create( - return &opp->base; - } - -+struct engine *dce80_aux_engine_create( -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ struct aux_engine_dce110 *aux_engine = -+ kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); -+ -+ if (!aux_engine) -+ return NULL; -+ -+ dce110_aux_engine_construct(aux_engine, ctx, inst, -+ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, -+ &aux_engine_regs[inst]); -+ -+ return &aux_engine->base.base; -+} -+ - static struct stream_encoder *dce80_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -@@ -655,6 +688,9 @@ static void destruct(struct dce110_resource_pool *pool) - kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } -+ -+ if (pool->base.engines[i] != NULL) -+ dce110_engine_destroy(&pool->base.engines[i]); - } - - for (i = 0; i < pool->base.stream_enc_count; i++) { -@@ -899,6 +935,14 @@ static bool dce80_construct( - dm_error("DC: failed to create output pixel processor!\n"); - goto res_create_fail; - } -+ -+ pool->base.engines[i] = dce80_aux_engine_create(ctx, i); -+ if (pool->base.engines[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error( -+ "DC:failed to create aux engine!!\n"); -+ goto res_create_fail; -+ } - } - - dc->caps.max_planes = pool->base.pipe_count; -diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c -index f9246d4..3f793a3 100644 ---- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c -@@ -64,6 +64,7 @@ - #include "reg_helper.h" - #include "dce/dce_abm.h" - #include "dce/dce_dmcu.h" -+#include "dce/dce_aux.h" - - const struct _vcs_dpi_ip_params_st dcn1_0_ip = { - .rob_buffer_size_kbytes = 64, -@@ -356,6 +357,21 @@ static const struct dcn10_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN10(_MASK), - }; - -+#define aux_engine_regs(id)\ -+[id] = {\ -+ AUX_COMMON_REG_LIST(id), \ -+ .AUX_RESET_MASK = 0 \ -+} -+ -+static const struct dce110_aux_registers aux_engine_regs[] = { -+ aux_engine_regs(0), -+ aux_engine_regs(1), -+ aux_engine_regs(2), -+ aux_engine_regs(3), -+ aux_engine_regs(4), -+ aux_engine_regs(5) -+}; -+ - #define tf_regs(id)\ - [id] = {\ - TF_REG_LIST_DCN10(id),\ -@@ -578,6 +594,23 @@ static struct output_pixel_processor *dcn10_opp_create( - return &opp->base; - } - -+struct engine *dcn10_aux_engine_create( -+ struct dc_context *ctx, -+ uint32_t inst) -+{ -+ struct aux_engine_dce110 *aux_engine = -+ kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); -+ -+ if (!aux_engine) -+ return NULL; -+ -+ dce110_aux_engine_construct(aux_engine, ctx, inst, -+ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, -+ &aux_engine_regs[inst]); -+ -+ return &aux_engine->base.base; -+} -+ - static struct mpc *dcn10_mpc_create(struct dc_context *ctx) - { - struct dcn10_mpc *mpc10 = kzalloc(sizeof(struct dcn10_mpc), -@@ -826,6 +859,9 @@ static void destruct(struct dcn10_resource_pool *pool) - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } -+ -+ if (pool->base.engines[i] != NULL) -+ pool->base.engines[i]->funcs->destroy_engine(&pool->base.engines[i]); - } - - for (i = 0; i < pool->base.stream_enc_count; i++) -@@ -1257,6 +1293,14 @@ static bool construct( - goto fail; - } - -+ pool->base.engines[i] = dcn10_aux_engine_create(ctx, i); -+ if (pool->base.engines[i] == NULL) { -+ BREAK_TO_DEBUGGER(); -+ dm_error( -+ "DC:failed to create aux engine!!\n"); -+ goto fail; -+ } -+ - /* check next valid pipe */ - j++; - } -diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h -index 1e8a158..b16fb1f 100644 ---- a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h -+++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h -@@ -96,6 +96,7 @@ struct engine_funcs { - - struct engine { - const struct engine_funcs *funcs; -+ uint32_t inst; - struct ddc *ddc; - struct dc_context *ctx; - }; -diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h -index 816da02..3b7e9aa 100644 ---- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h -+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h -@@ -138,7 +138,7 @@ struct resource_pool { - struct output_pixel_processor *opps[MAX_PIPES]; - struct timing_generator *timing_generators[MAX_PIPES]; - struct stream_encoder *stream_enc[MAX_PIPES * 2]; -- -+ struct engine *engines[MAX_PIPES]; - struct hubbub *hubbub; - struct mpc *mpc; - struct pp_smu_funcs_rv *pp_smu; -diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/aux_engine.h b/drivers/gpu/drm/amd/display/dc/inc/hw/aux_engine.h -new file mode 100644 -index 0000000..06d7e5d ---- /dev/null -+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/aux_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_AUX_ENGINE_H__ -+#define __DAL_AUX_ENGINE_H__ -+ -+#include "engine.h" -+#include "include/i2caux_interface.h" -+ -+struct aux_engine; -+union aux_config; -+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); -+ 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); -+ int (*read_channel_reply)( -+ struct aux_engine *engine, -+ uint32_t size, -+ uint8_t *buffer, -+ uint8_t *reply_result, -+ uint32_t *sw_status); -+ enum aux_channel_operation_result (*get_channel_status)( -+ struct aux_engine *engine, -+ uint8_t *returned_bytes); -+ bool (*is_engine_available)(struct aux_engine *engine); -+}; -+struct engine; -+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 acquire_reset; -+}; -+struct read_command_context { -+ uint8_t *buffer; -+ uint32_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; -+}; -+struct write_command_context { -+ bool mot; -+ -+ uint8_t *buffer; -+ uint32_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; -+}; -+#endif -diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/engine.h b/drivers/gpu/drm/amd/display/dc/inc/hw/engine.h -new file mode 100644 -index 0000000..1f5476f ---- /dev/null -+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/engine.h -@@ -0,0 +1,106 @@ -+/* -+ * 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__ -+ -+#include "dc_ddc_types.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; -+ uint32_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, -+ I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON -+}; -+ -+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 -+}; -+ -+struct engine; -+ -+struct engine_funcs { -+ enum i2caux_engine_type (*get_engine_type)( -+ const struct engine *engine); -+ struct aux_engine* (*acquire)( -+ struct engine *engine, -+ struct ddc *ddc); -+ bool (*submit_request)( -+ struct engine *engine, -+ struct i2caux_transaction_request *request, -+ bool middle_of_transaction); -+ void (*release_engine)( -+ struct engine *engine); -+ void (*destroy_engine)( -+ struct engine **engine); -+}; -+ -+struct engine { -+ const struct engine_funcs *funcs; -+ uint32_t inst; -+ struct ddc *ddc; -+ struct dc_context *ctx; -+}; -+ -+#endif --- -2.7.4 - |