aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/5181-drm-amd-display-Combine-dce80-and-dce100-i2c-hw-func.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/5181-drm-amd-display-Combine-dce80-and-dce100-i2c-hw-func.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/5181-drm-amd-display-Combine-dce80-and-dce100-i2c-hw-func.patch349
1 files changed, 349 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/5181-drm-amd-display-Combine-dce80-and-dce100-i2c-hw-func.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/5181-drm-amd-display-Combine-dce80-and-dce100-i2c-hw-func.patch
new file mode 100644
index 00000000..ed5f8320
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/5181-drm-amd-display-Combine-dce80-and-dce100-i2c-hw-func.patch
@@ -0,0 +1,349 @@
+From f8f33cbd7ae08b2f7f3510ca5729d37e64442037 Mon Sep 17 00:00:00 2001
+From: David Francis <David.Francis@amd.com>
+Date: Thu, 9 Aug 2018 13:15:36 -0400
+Subject: [PATCH 5181/5725] drm/amd/display: Combine dce80 and dce100 i2c hw
+ functions
+
+[Why]
+There are two versions of the hw function pointers: one for dce80
+and one for all other versions. These paired functions are
+nearly identical. dce80 and dce100 should not require
+different i2c access functions.
+
+[How]
+Combine each pair of functions into a single function. Mostly
+the new functions are based on the dce100 versions as those
+versions are newer, support more features, and
+were more maintained.
+
+Signed-off-by: David Francis <David.Francis@amd.com>
+Reviewed-by: Sun peng Li <Sunpeng.Li@amd.com>
+Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c | 237 ++++--------------------
+ 1 file changed, 40 insertions(+), 197 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 6a57c48..3a63e3c 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
+@@ -58,18 +58,7 @@ static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw)
+ return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
+ }
+
+-static void set_speed_hw_dce80(
+- struct dce_i2c_hw *dce_i2c_hw,
+- uint32_t speed)
+-{
+-
+- if (speed) {
+- 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);
+- }
+-}
+-static void set_speed_hw_dce100(
++static void set_speed(
+ struct dce_i2c_hw *dce_i2c_hw,
+ uint32_t speed)
+ {
+@@ -86,6 +75,7 @@ static void set_speed_hw_dce100(
+ 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)
+@@ -172,7 +162,7 @@ struct dce_i2c_hw *acquire_i2c_hw_engine(
+ return NULL;
+ }
+
+-static bool setup_engine_hw_dce100(
++static bool setup_engine(
+ struct dce_i2c_hw *dce_i2c_hw)
+ {
+ uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
+@@ -206,72 +196,11 @@ static bool setup_engine_hw_dce100(
+
+ return true;
+ }
+-static bool setup_engine_hw_dce80(
+- struct dce_i2c_hw *dce_i2c_hw)
+-{
+-
+- /* 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);
+- }
+-
+- /* Program time limit */
+- {
+- REG_UPDATE_2(SETUP,
+- DC_I2C_DDC1_TIME_LIMIT, I2C_SETUP_TIME_LIMIT_DCE,
+- 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_hw_dce80(
+- 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, length - 1,
+- 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 void process_channel_reply_hw_dce100(
++static void process_channel_reply(
+ struct dce_i2c_hw *dce_i2c_hw,
+ struct i2c_reply_transaction_data *reply)
+ {
+@@ -404,7 +333,7 @@ static void execute_transaction_hw(
+ dce_i2c_hw->transaction_count = 0;
+ dce_i2c_hw->buffer_used_bytes = 0;
+ }
+-static bool process_transaction_hw_dce80(
++static bool process_transaction(
+ struct dce_i2c_hw *dce_i2c_hw,
+ struct i2c_request_transaction_data *request)
+ {
+@@ -414,135 +343,49 @@ static bool process_transaction_hw_dce80(
+ bool last_transaction = false;
+ uint32_t value = 0;
+
+- {
+-
+- last_transaction = ((dce_i2c_hw->transaction_count == 3) ||
+- (request->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
+- (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ));
++ last_transaction = ((dce_i2c_hw->transaction_count == 3) ||
++ (request->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
++ (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ));
+
+
+- switch (dce_i2c_hw->transaction_count) {
+- case 0:
+- REG_UPDATE_5(DC_I2C_TRANSACTION0,
+- DC_I2C_STOP_ON_NACK0, 1,
+- DC_I2C_START0, 1,
+- DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
+- DC_I2C_COUNT0, length,
+- DC_I2C_STOP0, last_transaction ? 1 : 0);
+- break;
+- case 1:
+- REG_UPDATE_5(DC_I2C_TRANSACTION1,
+- DC_I2C_STOP_ON_NACK0, 1,
+- DC_I2C_START0, 1,
+- DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
+- DC_I2C_COUNT0, length,
+- DC_I2C_STOP0, last_transaction ? 1 : 0);
+- break;
+- case 2:
+- REG_UPDATE_5(DC_I2C_TRANSACTION2,
+- DC_I2C_STOP_ON_NACK0, 1,
+- DC_I2C_START0, 1,
+- DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
+- DC_I2C_COUNT0, length,
+- DC_I2C_STOP0, last_transaction ? 1 : 0);
+- break;
+- case 3:
+- REG_UPDATE_5(DC_I2C_TRANSACTION3,
+- DC_I2C_STOP_ON_NACK0, 1,
+- DC_I2C_START0, 1,
+- DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
+- DC_I2C_COUNT0, length,
+- DC_I2C_STOP0, last_transaction ? 1 : 0);
+- break;
+- default:
+- /* TODO Warning ? */
+- break;
+- }
+- }
+-
+- /* Write the I2C address and I2C data
+- * into the hardware circular buffer, one byte per entry.
+- * As an example, the 7-bit I2C slave address for CRT monitor
+- * for reading DDC/EDID information is 0b1010001.
+- * For an I2C send operation, the LSB must be programmed to 0;
+- * for I2C receive operation, the LSB must be programmed to 1.
+- */
+-
+- {
+- if (dce_i2c_hw->transaction_count == 0) {
+- value = REG_SET_4(DC_I2C_DATA, 0,
+- DC_I2C_DATA_RW, false,
+- DC_I2C_DATA, request->address,
+- DC_I2C_INDEX, 0,
+- DC_I2C_INDEX_WRITE, 1);
+- } else
+- value = REG_SET_2(DC_I2C_DATA, 0,
+- DC_I2C_DATA_RW, false,
+- DC_I2C_DATA, request->address);
+-
+- if (!(request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ)) {
+-
+- while (length) {
+- REG_SET_2(DC_I2C_DATA, value,
+- DC_I2C_INDEX_WRITE, 0,
+- DC_I2C_DATA, *buffer++);
+- --length;
+- }
+- }
+- }
+-
+- ++dce_i2c_hw->transaction_count;
+- dce_i2c_hw->buffer_used_bytes += length + 1;
+-
+- return last_transaction;
+-}
+-
+-#define STOP_TRANS_PREDICAT \
+- ((dce_i2c_hw->transaction_count == 3) || \
+- (request->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) || \
+- (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ))
+-
+-#define SET_I2C_TRANSACTION(id) \
+- do { \
+- REG_UPDATE_N(DC_I2C_TRANSACTION##id, 5, \
+- FN(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0), 1, \
+- FN(DC_I2C_TRANSACTION0, DC_I2C_START0), 1, \
+- FN(DC_I2C_TRANSACTION0, DC_I2C_STOP0), STOP_TRANS_PREDICAT ? 1:0, \
+- FN(DC_I2C_TRANSACTION0, DC_I2C_RW0), (0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ)), \
+- FN(DC_I2C_TRANSACTION0, DC_I2C_COUNT0), length); \
+- if (STOP_TRANS_PREDICAT) \
+- last_transaction = true; \
+- } while (false)
+-
+-static bool process_transaction_hw_dce100(
+- struct dce_i2c_hw *dce_i2c_hw,
+- struct i2c_request_transaction_data *request)
+-{
+- uint32_t length = request->length;
+- uint8_t *buffer = request->data;
+- uint32_t value = 0;
+-
+- bool last_transaction = false;
+-
+ switch (dce_i2c_hw->transaction_count) {
+ case 0:
+- SET_I2C_TRANSACTION(0);
++ REG_UPDATE_5(DC_I2C_TRANSACTION0,
++ DC_I2C_STOP_ON_NACK0, 1,
++ DC_I2C_START0, 1,
++ DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
++ DC_I2C_COUNT0, length,
++ DC_I2C_STOP0, last_transaction ? 1 : 0);
+ break;
+ case 1:
+- SET_I2C_TRANSACTION(1);
++ REG_UPDATE_5(DC_I2C_TRANSACTION1,
++ DC_I2C_STOP_ON_NACK0, 1,
++ DC_I2C_START0, 1,
++ DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
++ DC_I2C_COUNT0, length,
++ DC_I2C_STOP0, last_transaction ? 1 : 0);
+ break;
+ case 2:
+- SET_I2C_TRANSACTION(2);
++ REG_UPDATE_5(DC_I2C_TRANSACTION2,
++ DC_I2C_STOP_ON_NACK0, 1,
++ DC_I2C_START0, 1,
++ DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
++ DC_I2C_COUNT0, length,
++ DC_I2C_STOP0, last_transaction ? 1 : 0);
+ break;
+ case 3:
+- SET_I2C_TRANSACTION(3);
++ REG_UPDATE_5(DC_I2C_TRANSACTION3,
++ DC_I2C_STOP_ON_NACK0, 1,
++ DC_I2C_START0, 1,
++ DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
++ DC_I2C_COUNT0, length,
++ DC_I2C_STOP0, last_transaction ? 1 : 0);
+ break;
+ default:
+ /* TODO Warning ? */
+ break;
+ }
+
+-
+ /* Write the I2C address and I2C data
+ * into the hardware circular buffer, one byte per entry.
+ * As an example, the 7-bit I2C slave address for CRT monitor
+@@ -828,24 +671,24 @@ bool dce_i2c_submit_command_hw(
+ return result;
+ }
+ static const struct dce_i2c_hw_funcs dce100_i2c_hw_funcs = {
+- .setup_engine = setup_engine_hw_dce100,
+- .set_speed = set_speed_hw_dce100,
++ .setup_engine = setup_engine,
++ .set_speed = set_speed,
+ .get_speed = get_speed_hw,
+ .release_engine = release_engine_hw,
+- .process_transaction = process_transaction_hw_dce100,
+- .process_channel_reply = process_channel_reply_hw_dce100,
++ .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_hw_dce80,
+- .set_speed = set_speed_hw_dce80,
++ .setup_engine = setup_engine,
++ .set_speed = set_speed,
+ .get_speed = get_speed_hw,
+ .release_engine = release_engine_hw,
+- .process_transaction = process_transaction_hw_dce80,
+- .process_channel_reply = process_channel_reply_hw_dce80,
++ .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,
+--
+2.7.4
+