[PATCH 01/11] drm/amd/display: Eliminate i2c hw function pointers

sunpeng.li at amd.com sunpeng.li at amd.com
Wed Aug 22 20:06:32 UTC 2018


From: David Francis <David.Francis at amd.com>

[Why]
The function pointers of the dce_i2c_hw struct were never
accessed from outside dce_i2c_hw.c and had only one version.
As function pointers take up space and make debugging difficult,
and they are not needed in this case, they should be removed.

[How]
Remove the dce_i2c_hw_funcs struct and make static all
functions that were previously a part of it.  Reorder
the functions in dce_i2c_hw.c.

Signed-off-by: David Francis <David.Francis at amd.com>
Reviewed-by: Sun peng Li <Sunpeng.Li at amd.com>
Acked-by: Leo Li <sunpeng.li at amd.com>
---
 drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c | 607 ++++++++++++------------
 drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h |  29 --
 2 files changed, 291 insertions(+), 345 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
index 3a63e3c..cd7da59 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
@@ -36,223 +36,41 @@
 #define FN(reg_name, field_name) \
 	dce_i2c_hw->shifts->field_name, dce_i2c_hw->masks->field_name
 
-
-static inline void reset_hw_engine(struct dce_i2c_hw *dce_i2c_hw)
-{
-	REG_UPDATE_2(DC_I2C_CONTROL,
-		     DC_I2C_SW_STATUS_RESET, 1,
-		     DC_I2C_SW_STATUS_RESET, 1);
-}
-
-static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw)
-{
-	uint32_t i2c_sw_status = 0;
-
-	REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
-		return false;
-
-	reset_hw_engine(dce_i2c_hw);
-
-	REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-	return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
-}
-
-static void set_speed(
-	struct dce_i2c_hw *dce_i2c_hw,
-	uint32_t speed)
-{
-
-	if (speed) {
-		if (dce_i2c_hw->masks->DC_I2C_DDC1_START_STOP_TIMING_CNTL)
-			REG_UPDATE_N(SPEED, 3,
-				     FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), dce_i2c_hw->reference_frequency / speed,
-				     FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2,
-				     FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1);
-		else
-			REG_UPDATE_N(SPEED, 2,
-				     FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), dce_i2c_hw->reference_frequency / speed,
-				     FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2);
-	}
-}
-
-bool dce_i2c_hw_engine_acquire_engine(
-	struct dce_i2c_hw *dce_i2c_hw,
-	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;
-
-	dce_i2c_hw->ddc = ddc;
-
-
-	current_speed = dce_i2c_hw->funcs->get_speed(dce_i2c_hw);
-
-	if (current_speed)
-		dce_i2c_hw->original_speed = current_speed;
-
-	return true;
-}
-bool dce_i2c_engine_acquire_hw(
-	struct dce_i2c_hw *dce_i2c_hw,
-	struct ddc *ddc_handle)
-{
-
-	uint32_t counter = 0;
-	bool result;
-
-	do {
-		result = dce_i2c_hw_engine_acquire_engine(
-				dce_i2c_hw, ddc_handle);
-
-		if (result)
-			break;
-
-		/* i2c_engine is busy by VBios, lets wait and retry */
-
-		udelay(10);
-
-		++counter;
-	} while (counter < 2);
-
-	if (result) {
-		if (!dce_i2c_hw->funcs->setup_engine(dce_i2c_hw)) {
-			dce_i2c_hw->funcs->release_engine(dce_i2c_hw);
-			result = false;
-		}
-	}
-
-	return result;
-}
-struct dce_i2c_hw *acquire_i2c_hw_engine(
-	struct resource_pool *pool,
-	struct ddc *ddc)
+static void disable_i2c_hw_engine(
+	struct dce_i2c_hw *dce_i2c_hw)
 {
-
-	struct dce_i2c_hw *engine = NULL;
-
-	if (!ddc)
-		return NULL;
-
-	if (ddc->hw_info.hw_supported) {
-		enum gpio_ddc_line line = dal_ddc_get_line(ddc);
-
-		if (line < pool->pipe_count)
-			engine = pool->hw_i2cs[line];
-	}
-
-	if (!engine)
-		return NULL;
-
-
-	if (!pool->i2c_hw_buffer_in_use &&
-			dce_i2c_engine_acquire_hw(engine, ddc)) {
-		pool->i2c_hw_buffer_in_use = true;
-		return engine;
-	}
-
-
-	return NULL;
+	REG_UPDATE_N(SETUP, 1, FN(SETUP, DC_I2C_DDC1_ENABLE), 0);
 }
 
-static bool setup_engine(
+static void execute_transaction(
 	struct dce_i2c_hw *dce_i2c_hw)
 {
-	uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
+	REG_UPDATE_N(SETUP, 5,
+		     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0,
+		     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0,
+		     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0,
+		     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0,
+		     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0);
 
-	if (dce_i2c_hw->setup_limit != 0)
-		i2c_setup_limit = dce_i2c_hw->setup_limit;
-	/* Program pin select */
-	REG_UPDATE_6(DC_I2C_CONTROL,
-		     DC_I2C_GO, 0,
+
+	REG_UPDATE_5(DC_I2C_CONTROL,
 		     DC_I2C_SOFT_RESET, 0,
+		     DC_I2C_SW_STATUS_RESET, 0,
 		     DC_I2C_SEND_RESET, 0,
-		     DC_I2C_SW_STATUS_RESET, 1,
-		     DC_I2C_TRANSACTION_COUNT, 0,
-		     DC_I2C_DDC_SELECT, dce_i2c_hw->engine_id);
-
-	/* Program time limit */
-	if (dce_i2c_hw->send_reset_length == 0) {
-		/*pre-dcn*/
-		REG_UPDATE_N(SETUP, 2,
-			     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit,
-			     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
-	}
-	/* 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
-	 */
-	REG_UPDATE_2(DC_I2C_ARBITRATION,
-		     DC_I2C_NO_QUEUED_SW_GO, 0,
-		     DC_I2C_SW_PRIORITY, DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL);
-
-	return true;
-}
-
-
-
-
-static void process_channel_reply(
-	struct dce_i2c_hw *dce_i2c_hw,
-	struct i2c_reply_transaction_data *reply)
-{
-	uint32_t length = reply->length;
-	uint8_t *buffer = reply->data;
-
-	REG_SET_3(DC_I2C_DATA, 0,
-		 DC_I2C_INDEX, dce_i2c_hw->buffer_used_write,
-		 DC_I2C_DATA_RW, 1,
-		 DC_I2C_INDEX_WRITE, 1);
-
-	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
-		 */
-
-		uint32_t i2c_data;
+		     DC_I2C_GO, 0,
+		     DC_I2C_TRANSACTION_COUNT, dce_i2c_hw->transaction_count - 1);
 
-		REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data);
-		*buffer++ = i2c_data;
+	/* start I2C transfer */
+	REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1);
 
-		--length;
-	}
+	/* all transactions were executed and HW buffer became empty
+	 * (even though it actually happens when status becomes DONE)
+	 */
+	dce_i2c_hw->transaction_count = 0;
+	dce_i2c_hw->buffer_used_bytes = 0;
 }
-enum i2c_channel_operation_result dce_i2c_hw_engine_wait_on_operation_result(
-	struct dce_i2c_hw *dce_i2c_hw,
-	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 = dce_i2c_hw->funcs->get_channel_status(
-				dce_i2c_hw, NULL);
-
-		if (result != expected_result)
-			break;
-
-		udelay(1);
-
-		++i;
-	} while (i < timeout);
-	return result;
-}
-static enum i2c_channel_operation_result get_channel_status_hw(
+static enum i2c_channel_operation_result get_channel_status(
 	struct dce_i2c_hw *dce_i2c_hw,
 	uint8_t *returned_bytes)
 {
@@ -277,24 +95,13 @@ static enum i2c_channel_operation_result get_channel_status_hw(
 	return I2C_CHANNEL_OPERATION_SUCCEEDED;
 }
 
-static void submit_channel_request_hw(
-	struct dce_i2c_hw *dce_i2c_hw,
-	struct i2c_request_transaction_data *request)
+static uint32_t get_hw_buffer_available_size(
+	const struct dce_i2c_hw *dce_i2c_hw)
 {
-	request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
-
-	if (!dce_i2c_hw->funcs->process_transaction(dce_i2c_hw, request))
-		return;
-
-	if (dce_i2c_hw->funcs->is_hw_busy(dce_i2c_hw)) {
-		request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
-		return;
-	}
-
-	dce_i2c_hw->funcs->execute_transaction(dce_i2c_hw);
-
-
+	return dce_i2c_hw->buffer_size -
+			dce_i2c_hw->buffer_used_bytes;
 }
+
 uint32_t get_reference_clock(
 		struct dc_bios *bios)
 {
@@ -306,33 +113,48 @@ uint32_t get_reference_clock(
 	return info.pll_info.crystal_frequency;
 }
 
-static void execute_transaction_hw(
-	struct dce_i2c_hw *dce_i2c_hw)
+static uint32_t get_speed(
+	const struct dce_i2c_hw *dce_i2c_hw)
 {
-	REG_UPDATE_N(SETUP, 5,
-		     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0,
-		     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0,
-		     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0,
-		     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0,
-		     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0);
+	uint32_t pre_scale = 0;
 
+	REG_GET(SPEED, DC_I2C_DDC1_PRESCALE, &pre_scale);
 
-	REG_UPDATE_5(DC_I2C_CONTROL,
-		     DC_I2C_SOFT_RESET, 0,
-		     DC_I2C_SW_STATUS_RESET, 0,
-		     DC_I2C_SEND_RESET, 0,
-		     DC_I2C_GO, 0,
-		     DC_I2C_TRANSACTION_COUNT, dce_i2c_hw->transaction_count - 1);
+	/* [anaumov] it seems following is unnecessary */
+	/*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
+	return pre_scale ?
+		dce_i2c_hw->reference_frequency / pre_scale :
+		dce_i2c_hw->default_speed;
+}
 
-	/* start I2C transfer */
-	REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1);
+static void process_channel_reply(
+	struct dce_i2c_hw *dce_i2c_hw,
+	struct i2c_reply_transaction_data *reply)
+{
+	uint32_t length = reply->length;
+	uint8_t *buffer = reply->data;
 
-	/* all transactions were executed and HW buffer became empty
-	 * (even though it actually happens when status becomes DONE)
-	 */
-	dce_i2c_hw->transaction_count = 0;
-	dce_i2c_hw->buffer_used_bytes = 0;
+	REG_SET_3(DC_I2C_DATA, 0,
+		 DC_I2C_INDEX, dce_i2c_hw->buffer_used_write,
+		 DC_I2C_DATA_RW, 1,
+		 DC_I2C_INDEX_WRITE, 1);
+
+	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
+		 */
+
+		uint32_t i2c_data;
+
+		REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data);
+		*buffer++ = i2c_data;
+
+		--length;
+	}
 }
+
 static bool process_transaction(
 	struct dce_i2c_hw *dce_i2c_hw,
 	struct i2c_request_transaction_data *request)
@@ -422,51 +244,89 @@ static bool process_transaction(
 
 	return last_transaction;
 }
-static uint32_t get_transaction_timeout_hw(
-	const struct dce_i2c_hw *dce_i2c_hw,
-	uint32_t length)
-{
-
-	uint32_t speed = dce_i2c_hw->funcs->get_speed(dce_i2c_hw);
 
+static inline void reset_hw_engine(struct dce_i2c_hw *dce_i2c_hw)
+{
+	REG_UPDATE_2(DC_I2C_CONTROL,
+		     DC_I2C_SW_STATUS_RESET, 1,
+		     DC_I2C_SW_STATUS_RESET, 1);
+}
 
+static void set_speed(
+	struct dce_i2c_hw *dce_i2c_hw,
+	uint32_t speed)
+{
 
-	uint32_t period_timeout;
-	uint32_t num_of_clock_stretches;
+	if (speed) {
+		if (dce_i2c_hw->masks->DC_I2C_DDC1_START_STOP_TIMING_CNTL)
+			REG_UPDATE_N(SPEED, 3,
+				     FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), dce_i2c_hw->reference_frequency / speed,
+				     FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2,
+				     FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1);
+		else
+			REG_UPDATE_N(SPEED, 2,
+				     FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), dce_i2c_hw->reference_frequency / speed,
+				     FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2);
+	}
+}
 
-	if (!speed)
-		return 0;
+static bool setup_engine(
+	struct dce_i2c_hw *dce_i2c_hw)
+{
+	uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
 
-	period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
+	if (dce_i2c_hw->setup_limit != 0)
+		i2c_setup_limit = dce_i2c_hw->setup_limit;
+	/* Program pin select */
+	REG_UPDATE_6(DC_I2C_CONTROL,
+		     DC_I2C_GO, 0,
+		     DC_I2C_SOFT_RESET, 0,
+		     DC_I2C_SEND_RESET, 0,
+		     DC_I2C_SW_STATUS_RESET, 1,
+		     DC_I2C_TRANSACTION_COUNT, 0,
+		     DC_I2C_DDC_SELECT, dce_i2c_hw->engine_id);
 
-	num_of_clock_stretches = 1 + (length << 3) + 1;
-	num_of_clock_stretches +=
-		(dce_i2c_hw->buffer_used_bytes << 3) +
-		(dce_i2c_hw->transaction_count << 1);
+	/* Program time limit */
+	if (dce_i2c_hw->send_reset_length == 0) {
+		/*pre-dcn*/
+		REG_UPDATE_N(SETUP, 2,
+			     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit,
+			     FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
+	}
+	/* 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
+	 */
+	REG_UPDATE_2(DC_I2C_ARBITRATION,
+		     DC_I2C_NO_QUEUED_SW_GO, 0,
+		     DC_I2C_SW_PRIORITY, DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL);
 
-	return period_timeout * num_of_clock_stretches;
+	return true;
 }
 
-static void release_engine_dce_hw(
-	struct resource_pool *pool,
-	struct dce_i2c_hw *dce_i2c_hw)
+static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw)
 {
-	pool->i2c_hw_buffer_in_use = false;
+	uint32_t i2c_sw_status = 0;
 
-	dce_i2c_hw->funcs->release_engine(dce_i2c_hw);
-	dal_ddc_close(dce_i2c_hw->ddc);
+	REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
+	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
+		return false;
 
-	dce_i2c_hw->ddc = NULL;
+	reset_hw_engine(dce_i2c_hw);
+
+	REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
+	return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
 }
 
-static void release_engine_hw(
+static void release_engine(
 	struct dce_i2c_hw *dce_i2c_hw)
 {
 	bool safe_to_reset;
 
 	/* Restore original HW engine speed */
 
-	dce_i2c_hw->funcs->set_speed(dce_i2c_hw, dce_i2c_hw->original_speed);
+	set_speed(dce_i2c_hw, dce_i2c_hw->original_speed);
 
 	/* Release I2C */
 	REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1);
@@ -488,35 +348,180 @@ static void release_engine_hw(
 		REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1);
 	/* HW I2c engine - clock gating feature */
 	if (!dce_i2c_hw->engine_keep_power_up_count)
-		dce_i2c_hw->funcs->disable_i2c_hw_engine(dce_i2c_hw);
+		disable_i2c_hw_engine(dce_i2c_hw);
 
 }
 
-
-static void disable_i2c_hw_engine(
+static void release_engine_dce_hw(
+	struct resource_pool *pool,
 	struct dce_i2c_hw *dce_i2c_hw)
 {
-	REG_UPDATE_N(SETUP, 1, FN(SETUP, DC_I2C_DDC1_ENABLE), 0);
+	pool->i2c_hw_buffer_in_use = false;
+
+	release_engine(dce_i2c_hw);
+	dal_ddc_close(dce_i2c_hw->ddc);
+
+	dce_i2c_hw->ddc = NULL;
 }
-static uint32_t get_speed_hw(
-	const struct dce_i2c_hw *dce_i2c_hw)
+
+bool dce_i2c_hw_engine_acquire_engine(
+	struct dce_i2c_hw *dce_i2c_hw,
+	struct ddc *ddc)
 {
-	uint32_t pre_scale = 0;
 
-	REG_GET(SPEED, DC_I2C_DDC1_PRESCALE, &pre_scale);
+	enum gpio_result result;
+	uint32_t current_speed;
 
-	/* [anaumov] it seems following is unnecessary */
-	/*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
-	return pre_scale ?
-		dce_i2c_hw->reference_frequency / pre_scale :
-		dce_i2c_hw->default_speed;
+	result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
+		GPIO_DDC_CONFIG_TYPE_MODE_I2C);
+
+	if (result != GPIO_RESULT_OK)
+		return false;
+
+	dce_i2c_hw->ddc = ddc;
+
+
+	current_speed = get_speed(dce_i2c_hw);
+
+	if (current_speed)
+		dce_i2c_hw->original_speed = current_speed;
+
+	return true;
 }
-static uint32_t get_hw_buffer_available_size(
-	const struct dce_i2c_hw *dce_i2c_hw)
+
+bool dce_i2c_engine_acquire_hw(
+	struct dce_i2c_hw *dce_i2c_hw,
+	struct ddc *ddc_handle)
 {
-	return dce_i2c_hw->buffer_size -
-			dce_i2c_hw->buffer_used_bytes;
+
+	uint32_t counter = 0;
+	bool result;
+
+	do {
+		result = dce_i2c_hw_engine_acquire_engine(
+				dce_i2c_hw, ddc_handle);
+
+		if (result)
+			break;
+
+		/* i2c_engine is busy by VBios, lets wait and retry */
+
+		udelay(10);
+
+		++counter;
+	} while (counter < 2);
+
+	if (result) {
+		if (!setup_engine(dce_i2c_hw)) {
+			release_engine(dce_i2c_hw);
+			result = false;
+		}
+	}
+
+	return result;
+}
+
+struct dce_i2c_hw *acquire_i2c_hw_engine(
+	struct resource_pool *pool,
+	struct ddc *ddc)
+{
+
+	struct dce_i2c_hw *engine = NULL;
+
+	if (!ddc)
+		return NULL;
+
+	if (ddc->hw_info.hw_supported) {
+		enum gpio_ddc_line line = dal_ddc_get_line(ddc);
+
+		if (line < pool->pipe_count)
+			engine = pool->hw_i2cs[line];
+	}
+
+	if (!engine)
+		return NULL;
+
+
+	if (!pool->i2c_hw_buffer_in_use &&
+			dce_i2c_engine_acquire_hw(engine, ddc)) {
+		pool->i2c_hw_buffer_in_use = true;
+		return engine;
+	}
+
+
+	return NULL;
+}
+
+enum i2c_channel_operation_result dce_i2c_hw_engine_wait_on_operation_result(
+	struct dce_i2c_hw *dce_i2c_hw,
+	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 = get_channel_status(
+				dce_i2c_hw, NULL);
+
+		if (result != expected_result)
+			break;
+
+		udelay(1);
+
+		++i;
+	} while (i < timeout);
+	return result;
+}
+
+static void submit_channel_request_hw(
+	struct dce_i2c_hw *dce_i2c_hw,
+	struct i2c_request_transaction_data *request)
+{
+	request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
+
+	if (!process_transaction(dce_i2c_hw, request))
+		return;
+
+	if (is_hw_busy(dce_i2c_hw)) {
+		request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
+		return;
+	}
+
+	execute_transaction(dce_i2c_hw);
+
+
+}
+
+static uint32_t get_transaction_timeout_hw(
+	const struct dce_i2c_hw *dce_i2c_hw,
+	uint32_t length)
+{
+
+	uint32_t speed = get_speed(dce_i2c_hw);
+
+
+
+	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 +=
+		(dce_i2c_hw->buffer_used_bytes << 3) +
+		(dce_i2c_hw->transaction_count << 1);
+
+	return period_timeout * num_of_clock_stretches;
 }
+
 bool dce_i2c_hw_engine_submit_request(
 	struct dce_i2c_hw *dce_i2c_hw,
 	struct dce_i2c_transaction_request *dce_i2c_request,
@@ -615,9 +620,7 @@ bool dce_i2c_hw_engine_submit_request(
 		reply.data = dce_i2c_request->payload.data;
 		reply.length = dce_i2c_request->payload.length;
 
-		dce_i2c_hw->funcs->process_channel_reply(dce_i2c_hw, &reply);
-
-
+		process_channel_reply(dce_i2c_hw, &reply);
 	}
 
 	return result;
@@ -632,7 +635,7 @@ bool dce_i2c_submit_command_hw(
 	uint8_t index_of_payload = 0;
 	bool result;
 
-	dce_i2c_hw->funcs->set_speed(dce_i2c_hw, cmd->speed);
+	set_speed(dce_i2c_hw, cmd->speed);
 
 	result = true;
 
@@ -670,32 +673,6 @@ bool dce_i2c_submit_command_hw(
 
 	return result;
 }
-static const struct dce_i2c_hw_funcs dce100_i2c_hw_funcs = {
-		.setup_engine = setup_engine,
-		.set_speed = set_speed,
-		.get_speed = get_speed_hw,
-		.release_engine = release_engine_hw,
-		.process_transaction = process_transaction,
-		.process_channel_reply = process_channel_reply,
-		.is_hw_busy = is_hw_busy,
-		.get_channel_status = get_channel_status_hw,
-		.execute_transaction = execute_transaction_hw,
-		.disable_i2c_hw_engine = disable_i2c_hw_engine
-};
-static const struct dce_i2c_hw_funcs dce80_i2c_hw_funcs = {
-		.setup_engine = setup_engine,
-		.set_speed = set_speed,
-		.get_speed = get_speed_hw,
-		.release_engine = release_engine_hw,
-		.process_transaction = process_transaction,
-		.process_channel_reply = process_channel_reply,
-		.is_hw_busy = is_hw_busy,
-		.get_channel_status = get_channel_status_hw,
-		.execute_transaction = execute_transaction_hw,
-		.disable_i2c_hw_engine = disable_i2c_hw_engine
-};
-
-
 
 void dce_i2c_hw_construct(
 	struct dce_i2c_hw *dce_i2c_hw,
@@ -718,7 +695,6 @@ void dce_i2c_hw_construct(
 	dce_i2c_hw->default_speed = DEFAULT_I2C_HW_SPEED;
 	dce_i2c_hw->send_reset_length = 0;
 	dce_i2c_hw->setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
-	dce_i2c_hw->funcs = &dce80_i2c_hw_funcs;
 	dce_i2c_hw->buffer_size = I2C_HW_BUFFER_SIZE_DCE;
 }
 
@@ -739,7 +715,6 @@ void dce100_i2c_hw_construct(
 			regs,
 			shifts,
 			masks);
-	dce_i2c_hw->funcs = &dce100_i2c_hw_funcs;
 	dce_i2c_hw->buffer_size = I2C_HW_BUFFER_SIZE_DCE100;
 
 	REG_GET(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, &xtal_ref_div);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h
index 8baef39..742c1da 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h
@@ -256,40 +256,11 @@ struct dce_i2c_hw {
 	uint32_t buffer_size;
 	struct dc_context *ctx;
 
-	const struct dce_i2c_hw_funcs *funcs;
 	const struct dce_i2c_registers *regs;
 	const struct dce_i2c_shift *shifts;
 	const struct dce_i2c_mask *masks;
 };
 
-
-struct dce_i2c_hw_funcs {
-	bool (*setup_engine)(
-		struct dce_i2c_hw *dce_i2c_hw);
-	void (*set_speed)(
-		struct dce_i2c_hw *dce_i2c_hw,
-		uint32_t speed);
-	uint32_t (*get_speed)(
-		const struct dce_i2c_hw *dce_i2c_hw);
-	void (*release_engine)(
-		struct dce_i2c_hw *dce_i2c_hw);
-	bool (*process_transaction)(
-		struct dce_i2c_hw *dce_i2c_hw,
-		struct i2c_request_transaction_data *request);
-	void (*process_channel_reply)(
-		struct dce_i2c_hw *dce_i2c_hw,
-		struct i2c_reply_transaction_data *reply);
-	bool (*is_hw_busy)(
-		struct dce_i2c_hw *dce_i2c_hw);
-	enum i2c_channel_operation_result (*get_channel_status)(
-		struct dce_i2c_hw *dce_i2c_hw,
-		uint8_t *returned_bytes);
-	void (*execute_transaction)(
-		struct dce_i2c_hw *dce_i2c_hw);
-	void (*disable_i2c_hw_engine)(
-		struct dce_i2c_hw *dce_i2c_hw);
-};
-
 void dce_i2c_hw_construct(
 	struct dce_i2c_hw *dce_i2c_hw,
 	struct dc_context *ctx,
-- 
2.7.4



More information about the amd-gfx mailing list