[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