Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2018 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include <linux/delay.h>
0027 
0028 #include "resource.h"
0029 #include "dce_i2c.h"
0030 #include "dce_i2c_hw.h"
0031 #include "reg_helper.h"
0032 #include "include/gpio_service_interface.h"
0033 
0034 #define CTX \
0035     dce_i2c_hw->ctx
0036 #define REG(reg)\
0037     dce_i2c_hw->regs->reg
0038 
0039 #undef FN
0040 #define FN(reg_name, field_name) \
0041     dce_i2c_hw->shifts->field_name, dce_i2c_hw->masks->field_name
0042 
0043 static void execute_transaction(
0044     struct dce_i2c_hw *dce_i2c_hw)
0045 {
0046     REG_UPDATE_N(SETUP, 5,
0047              FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0,
0048              FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0,
0049              FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0,
0050              FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0,
0051              FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0);
0052 
0053 
0054     REG_UPDATE_5(DC_I2C_CONTROL,
0055              DC_I2C_SOFT_RESET, 0,
0056              DC_I2C_SW_STATUS_RESET, 0,
0057              DC_I2C_SEND_RESET, 0,
0058              DC_I2C_GO, 0,
0059              DC_I2C_TRANSACTION_COUNT, dce_i2c_hw->transaction_count - 1);
0060 
0061     /* start I2C transfer */
0062     REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1);
0063 
0064     /* all transactions were executed and HW buffer became empty
0065      * (even though it actually happens when status becomes DONE)
0066      */
0067     dce_i2c_hw->transaction_count = 0;
0068     dce_i2c_hw->buffer_used_bytes = 0;
0069 }
0070 
0071 static enum i2c_channel_operation_result get_channel_status(
0072     struct dce_i2c_hw *dce_i2c_hw,
0073     uint8_t *returned_bytes)
0074 {
0075     uint32_t i2c_sw_status = 0;
0076     uint32_t value =
0077         REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
0078     if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
0079         return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
0080     else if (value & dce_i2c_hw->masks->DC_I2C_SW_STOPPED_ON_NACK)
0081         return I2C_CHANNEL_OPERATION_NO_RESPONSE;
0082     else if (value & dce_i2c_hw->masks->DC_I2C_SW_TIMEOUT)
0083         return I2C_CHANNEL_OPERATION_TIMEOUT;
0084     else if (value & dce_i2c_hw->masks->DC_I2C_SW_ABORTED)
0085         return I2C_CHANNEL_OPERATION_FAILED;
0086     else if (value & dce_i2c_hw->masks->DC_I2C_SW_DONE)
0087         return I2C_CHANNEL_OPERATION_SUCCEEDED;
0088 
0089     /*
0090      * this is the case when HW used for communication, I2C_SW_STATUS
0091      * could be zero
0092      */
0093     return I2C_CHANNEL_OPERATION_SUCCEEDED;
0094 }
0095 
0096 static uint32_t get_hw_buffer_available_size(
0097     const struct dce_i2c_hw *dce_i2c_hw)
0098 {
0099     return dce_i2c_hw->buffer_size -
0100             dce_i2c_hw->buffer_used_bytes;
0101 }
0102 
0103 static void process_channel_reply(
0104     struct dce_i2c_hw *dce_i2c_hw,
0105     struct i2c_payload *reply)
0106 {
0107     uint32_t length = reply->length;
0108     uint8_t *buffer = reply->data;
0109 
0110     REG_SET_3(DC_I2C_DATA, 0,
0111          DC_I2C_INDEX, dce_i2c_hw->buffer_used_write,
0112          DC_I2C_DATA_RW, 1,
0113          DC_I2C_INDEX_WRITE, 1);
0114 
0115     while (length) {
0116         /* after reading the status,
0117          * if the I2C operation executed successfully
0118          * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
0119          * should read data bytes from I2C circular data buffer
0120          */
0121 
0122         uint32_t i2c_data;
0123 
0124         REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data);
0125         *buffer++ = i2c_data;
0126 
0127         --length;
0128     }
0129 }
0130 
0131 static bool is_engine_available(struct dce_i2c_hw *dce_i2c_hw)
0132 {
0133     unsigned int arbitrate;
0134     unsigned int i2c_hw_status;
0135 
0136     REG_GET(HW_STATUS, DC_I2C_DDC1_HW_STATUS, &i2c_hw_status);
0137     if (i2c_hw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW)
0138         return false;
0139 
0140     REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate);
0141     if (arbitrate == DC_I2C_REG_RW_CNTL_STATUS_DMCU_ONLY)
0142         return false;
0143 
0144     return true;
0145 }
0146 
0147 static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw)
0148 {
0149     uint32_t i2c_sw_status = 0;
0150 
0151     REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
0152     if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
0153         return false;
0154 
0155     if (is_engine_available(dce_i2c_hw))
0156         return false;
0157 
0158     return true;
0159 }
0160 
0161 static bool process_transaction(
0162     struct dce_i2c_hw *dce_i2c_hw,
0163     struct i2c_request_transaction_data *request)
0164 {
0165     uint32_t length = request->length;
0166     uint8_t *buffer = request->data;
0167 
0168     bool last_transaction = false;
0169     uint32_t value = 0;
0170 
0171     if (is_hw_busy(dce_i2c_hw)) {
0172         request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
0173         return false;
0174     }
0175 
0176     last_transaction = ((dce_i2c_hw->transaction_count == 3) ||
0177             (request->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
0178             (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ));
0179 
0180 
0181     switch (dce_i2c_hw->transaction_count) {
0182     case 0:
0183         REG_UPDATE_5(DC_I2C_TRANSACTION0,
0184                  DC_I2C_STOP_ON_NACK0, 1,
0185                  DC_I2C_START0, 1,
0186                  DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
0187                  DC_I2C_COUNT0, length,
0188                  DC_I2C_STOP0, last_transaction ? 1 : 0);
0189         break;
0190     case 1:
0191         REG_UPDATE_5(DC_I2C_TRANSACTION1,
0192                  DC_I2C_STOP_ON_NACK0, 1,
0193                  DC_I2C_START0, 1,
0194                  DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
0195                  DC_I2C_COUNT0, length,
0196                  DC_I2C_STOP0, last_transaction ? 1 : 0);
0197         break;
0198     case 2:
0199         REG_UPDATE_5(DC_I2C_TRANSACTION2,
0200                  DC_I2C_STOP_ON_NACK0, 1,
0201                  DC_I2C_START0, 1,
0202                  DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
0203                  DC_I2C_COUNT0, length,
0204                  DC_I2C_STOP0, last_transaction ? 1 : 0);
0205         break;
0206     case 3:
0207         REG_UPDATE_5(DC_I2C_TRANSACTION3,
0208                  DC_I2C_STOP_ON_NACK0, 1,
0209                  DC_I2C_START0, 1,
0210                  DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
0211                  DC_I2C_COUNT0, length,
0212                  DC_I2C_STOP0, last_transaction ? 1 : 0);
0213         break;
0214     default:
0215         /* TODO Warning ? */
0216         break;
0217     }
0218 
0219     /* Write the I2C address and I2C data
0220      * into the hardware circular buffer, one byte per entry.
0221      * As an example, the 7-bit I2C slave address for CRT monitor
0222      * for reading DDC/EDID information is 0b1010001.
0223      * For an I2C send operation, the LSB must be programmed to 0;
0224      * for I2C receive operation, the LSB must be programmed to 1.
0225      */
0226     if (dce_i2c_hw->transaction_count == 0) {
0227         value = REG_SET_4(DC_I2C_DATA, 0,
0228                   DC_I2C_DATA_RW, false,
0229                   DC_I2C_DATA, request->address,
0230                   DC_I2C_INDEX, 0,
0231                   DC_I2C_INDEX_WRITE, 1);
0232         dce_i2c_hw->buffer_used_write = 0;
0233     } else
0234         value = REG_SET_2(DC_I2C_DATA, 0,
0235               DC_I2C_DATA_RW, false,
0236               DC_I2C_DATA, request->address);
0237 
0238     dce_i2c_hw->buffer_used_write++;
0239 
0240     if (!(request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ)) {
0241         while (length) {
0242             REG_SET_2(DC_I2C_DATA, value,
0243                   DC_I2C_INDEX_WRITE, 0,
0244                   DC_I2C_DATA, *buffer++);
0245             dce_i2c_hw->buffer_used_write++;
0246             --length;
0247         }
0248     }
0249 
0250     ++dce_i2c_hw->transaction_count;
0251     dce_i2c_hw->buffer_used_bytes += length + 1;
0252 
0253     return last_transaction;
0254 }
0255 
0256 static inline void reset_hw_engine(struct dce_i2c_hw *dce_i2c_hw)
0257 {
0258     REG_UPDATE_2(DC_I2C_CONTROL,
0259              DC_I2C_SW_STATUS_RESET, 1,
0260              DC_I2C_SW_STATUS_RESET, 1);
0261 }
0262 
0263 static void set_speed(
0264     struct dce_i2c_hw *dce_i2c_hw,
0265     uint32_t speed)
0266 {
0267     uint32_t xtal_ref_div = 0, ref_base_div = 0;
0268     uint32_t prescale = 0;
0269     uint32_t i2c_ref_clock = 0;
0270 
0271     if (speed == 0)
0272         return;
0273 
0274     REG_GET_2(MICROSECOND_TIME_BASE_DIV, MICROSECOND_TIME_BASE_DIV, &ref_base_div,
0275         XTAL_REF_DIV, &xtal_ref_div);
0276 
0277     if (xtal_ref_div == 0)
0278         xtal_ref_div = 2;
0279 
0280     if (ref_base_div == 0)
0281         i2c_ref_clock = (dce_i2c_hw->reference_frequency * 2);
0282     else
0283         i2c_ref_clock = ref_base_div * 1000;
0284 
0285     prescale = (i2c_ref_clock / xtal_ref_div) / speed;
0286 
0287     if (dce_i2c_hw->masks->DC_I2C_DDC1_START_STOP_TIMING_CNTL)
0288         REG_UPDATE_N(SPEED, 3,
0289                  FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), prescale,
0290                  FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2,
0291                  FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1);
0292     else
0293         REG_UPDATE_N(SPEED, 2,
0294                  FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), prescale,
0295                  FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2);
0296 }
0297 
0298 static bool setup_engine(
0299     struct dce_i2c_hw *dce_i2c_hw)
0300 {
0301     uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
0302     uint32_t  reset_length = 0;
0303 
0304         if (dce_i2c_hw->ctx->dc->debug.enable_mem_low_power.bits.i2c) {
0305          if (dce_i2c_hw->regs->DIO_MEM_PWR_CTRL) {
0306              REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 0);
0307              REG_WAIT(DIO_MEM_PWR_STATUS, I2C_MEM_PWR_STATE, 0, 0, 5);
0308              }
0309          }
0310 
0311     /* we have checked I2c not used by DMCU, set SW use I2C REQ to 1 to indicate SW using it*/
0312     REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, 1);
0313 
0314     /* we have checked I2c not used by DMCU, set SW use I2C REQ to 1 to indicate SW using it*/
0315     REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, 1);
0316 
0317     /*set SW requested I2c speed to default, if API calls in it will be override later*/
0318     set_speed(dce_i2c_hw, dce_i2c_hw->ctx->dc->caps.i2c_speed_in_khz);
0319 
0320     if (dce_i2c_hw->setup_limit != 0)
0321         i2c_setup_limit = dce_i2c_hw->setup_limit;
0322 
0323     /* Program pin select */
0324     REG_UPDATE_6(DC_I2C_CONTROL,
0325              DC_I2C_GO, 0,
0326              DC_I2C_SOFT_RESET, 0,
0327              DC_I2C_SEND_RESET, 0,
0328              DC_I2C_SW_STATUS_RESET, 1,
0329              DC_I2C_TRANSACTION_COUNT, 0,
0330              DC_I2C_DDC_SELECT, dce_i2c_hw->engine_id);
0331 
0332     /* Program time limit */
0333     if (dce_i2c_hw->send_reset_length == 0) {
0334         /*pre-dcn*/
0335         REG_UPDATE_N(SETUP, 2,
0336                  FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit,
0337                  FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
0338     } else {
0339         reset_length = dce_i2c_hw->send_reset_length;
0340         REG_UPDATE_N(SETUP, 3,
0341                  FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit,
0342                  FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_SEND_RESET_LENGTH), reset_length,
0343                  FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
0344     }
0345     /* Program HW priority
0346      * set to High - interrupt software I2C at any time
0347      * Enable restart of SW I2C that was interrupted by HW
0348      * disable queuing of software while I2C is in use by HW
0349      */
0350     REG_UPDATE(DC_I2C_ARBITRATION,
0351             DC_I2C_NO_QUEUED_SW_GO, 0);
0352 
0353     return true;
0354 }
0355 
0356 static void release_engine(
0357     struct dce_i2c_hw *dce_i2c_hw)
0358 {
0359     bool safe_to_reset;
0360 
0361 
0362     /* Reset HW engine */
0363     {
0364         uint32_t i2c_sw_status = 0;
0365 
0366         REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
0367         /* if used by SW, safe to reset */
0368         safe_to_reset = (i2c_sw_status == 1);
0369     }
0370 
0371     if (safe_to_reset)
0372         REG_UPDATE_2(DC_I2C_CONTROL,
0373                  DC_I2C_SOFT_RESET, 1,
0374                  DC_I2C_SW_STATUS_RESET, 1);
0375     else
0376         REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1);
0377     /* HW I2c engine - clock gating feature */
0378     if (!dce_i2c_hw->engine_keep_power_up_count)
0379         REG_UPDATE_N(SETUP, 1, FN(SETUP, DC_I2C_DDC1_ENABLE), 0);
0380 
0381     /*for HW HDCP Ri polling failure w/a test*/
0382     set_speed(dce_i2c_hw, dce_i2c_hw->ctx->dc->caps.i2c_speed_in_khz_hdcp);
0383     /* Release I2C after reset, so HW or DMCU could use it */
0384     REG_UPDATE_2(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1,
0385         DC_I2C_SW_USE_I2C_REG_REQ, 0);
0386 
0387     if (dce_i2c_hw->ctx->dc->debug.enable_mem_low_power.bits.i2c) {
0388         if (dce_i2c_hw->regs->DIO_MEM_PWR_CTRL)
0389             REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1);
0390     }
0391 }
0392 
0393 struct dce_i2c_hw *acquire_i2c_hw_engine(
0394     struct resource_pool *pool,
0395     struct ddc *ddc)
0396 {
0397     uint32_t counter = 0;
0398     enum gpio_result result;
0399     struct dce_i2c_hw *dce_i2c_hw = NULL;
0400 
0401     if (!ddc)
0402         return NULL;
0403 
0404     if (ddc->hw_info.hw_supported) {
0405         enum gpio_ddc_line line = dal_ddc_get_line(ddc);
0406 
0407         if (line < pool->res_cap->num_ddc)
0408             dce_i2c_hw = pool->hw_i2cs[line];
0409     }
0410 
0411     if (!dce_i2c_hw)
0412         return NULL;
0413 
0414     if (pool->i2c_hw_buffer_in_use || !is_engine_available(dce_i2c_hw))
0415         return NULL;
0416 
0417     do {
0418         result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
0419             GPIO_DDC_CONFIG_TYPE_MODE_I2C);
0420 
0421         if (result == GPIO_RESULT_OK)
0422             break;
0423 
0424         /* i2c_engine is busy by VBios, lets wait and retry */
0425 
0426         udelay(10);
0427 
0428         ++counter;
0429     } while (counter < 2);
0430 
0431     if (result != GPIO_RESULT_OK)
0432         return NULL;
0433 
0434     dce_i2c_hw->ddc = ddc;
0435 
0436     if (!setup_engine(dce_i2c_hw)) {
0437         release_engine(dce_i2c_hw);
0438         return NULL;
0439     }
0440 
0441     pool->i2c_hw_buffer_in_use = true;
0442     return dce_i2c_hw;
0443 }
0444 
0445 static enum i2c_channel_operation_result dce_i2c_hw_engine_wait_on_operation_result(
0446     struct dce_i2c_hw *dce_i2c_hw,
0447     uint32_t timeout,
0448     enum i2c_channel_operation_result expected_result)
0449 {
0450     enum i2c_channel_operation_result result;
0451     uint32_t i = 0;
0452 
0453     if (!timeout)
0454         return I2C_CHANNEL_OPERATION_SUCCEEDED;
0455 
0456     do {
0457 
0458         result = get_channel_status(
0459                 dce_i2c_hw, NULL);
0460 
0461         if (result != expected_result)
0462             break;
0463 
0464         udelay(1);
0465 
0466         ++i;
0467     } while (i < timeout);
0468     return result;
0469 }
0470 
0471 static void submit_channel_request_hw(
0472     struct dce_i2c_hw *dce_i2c_hw,
0473     struct i2c_request_transaction_data *request)
0474 {
0475     request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
0476 
0477     if (!process_transaction(dce_i2c_hw, request))
0478         return;
0479 
0480     if (is_hw_busy(dce_i2c_hw)) {
0481         request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
0482         return;
0483     }
0484     reset_hw_engine(dce_i2c_hw);
0485 
0486     execute_transaction(dce_i2c_hw);
0487 
0488 
0489 }
0490 
0491 static uint32_t get_transaction_timeout_hw(
0492     const struct dce_i2c_hw *dce_i2c_hw,
0493     uint32_t length,
0494     uint32_t speed)
0495 {
0496     uint32_t period_timeout;
0497     uint32_t num_of_clock_stretches;
0498 
0499     if (!speed)
0500         return 0;
0501 
0502     period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
0503 
0504     num_of_clock_stretches = 1 + (length << 3) + 1;
0505     num_of_clock_stretches +=
0506         (dce_i2c_hw->buffer_used_bytes << 3) +
0507         (dce_i2c_hw->transaction_count << 1);
0508 
0509     return period_timeout * num_of_clock_stretches;
0510 }
0511 
0512 static bool dce_i2c_hw_engine_submit_payload(
0513     struct dce_i2c_hw *dce_i2c_hw,
0514     struct i2c_payload *payload,
0515     bool middle_of_transaction,
0516     uint32_t speed)
0517 {
0518 
0519     struct i2c_request_transaction_data request;
0520 
0521     uint32_t transaction_timeout;
0522 
0523     enum i2c_channel_operation_result operation_result;
0524 
0525     bool result = false;
0526 
0527     /* We need following:
0528      * transaction length will not exceed
0529      * the number of free bytes in HW buffer (minus one for address)
0530      */
0531 
0532     if (payload->length >=
0533             get_hw_buffer_available_size(dce_i2c_hw)) {
0534         return false;
0535     }
0536 
0537     if (!payload->write)
0538         request.action = middle_of_transaction ?
0539             DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
0540             DCE_I2C_TRANSACTION_ACTION_I2C_READ;
0541     else
0542         request.action = middle_of_transaction ?
0543             DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
0544             DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
0545 
0546 
0547     request.address = (uint8_t) ((payload->address << 1) | !payload->write);
0548     request.length = payload->length;
0549     request.data = payload->data;
0550 
0551     /* obtain timeout value before submitting request */
0552 
0553     transaction_timeout = get_transaction_timeout_hw(
0554         dce_i2c_hw, payload->length + 1, speed);
0555 
0556     submit_channel_request_hw(
0557         dce_i2c_hw, &request);
0558 
0559     if ((request.status == I2C_CHANNEL_OPERATION_FAILED) ||
0560         (request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY))
0561         return false;
0562 
0563     /* wait until transaction proceed */
0564 
0565     operation_result = dce_i2c_hw_engine_wait_on_operation_result(
0566         dce_i2c_hw,
0567         transaction_timeout,
0568         I2C_CHANNEL_OPERATION_ENGINE_BUSY);
0569 
0570     /* update transaction status */
0571 
0572     if (operation_result == I2C_CHANNEL_OPERATION_SUCCEEDED)
0573         result = true;
0574 
0575     if (result && (!payload->write))
0576         process_channel_reply(dce_i2c_hw, payload);
0577 
0578     return result;
0579 }
0580 
0581 bool dce_i2c_submit_command_hw(
0582     struct resource_pool *pool,
0583     struct ddc *ddc,
0584     struct i2c_command *cmd,
0585     struct dce_i2c_hw *dce_i2c_hw)
0586 {
0587     uint8_t index_of_payload = 0;
0588     bool result;
0589 
0590     set_speed(dce_i2c_hw, cmd->speed);
0591 
0592     result = true;
0593 
0594     while (index_of_payload < cmd->number_of_payloads) {
0595         bool mot = (index_of_payload != cmd->number_of_payloads - 1);
0596 
0597         struct i2c_payload *payload = cmd->payloads + index_of_payload;
0598 
0599         if (!dce_i2c_hw_engine_submit_payload(
0600                 dce_i2c_hw, payload, mot, cmd->speed)) {
0601             result = false;
0602             break;
0603         }
0604 
0605         ++index_of_payload;
0606     }
0607 
0608     pool->i2c_hw_buffer_in_use = false;
0609 
0610     release_engine(dce_i2c_hw);
0611     dal_ddc_close(dce_i2c_hw->ddc);
0612 
0613     dce_i2c_hw->ddc = NULL;
0614 
0615     return result;
0616 }
0617 
0618 void dce_i2c_hw_construct(
0619     struct dce_i2c_hw *dce_i2c_hw,
0620     struct dc_context *ctx,
0621     uint32_t engine_id,
0622     const struct dce_i2c_registers *regs,
0623     const struct dce_i2c_shift *shifts,
0624     const struct dce_i2c_mask *masks)
0625 {
0626     dce_i2c_hw->ctx = ctx;
0627     dce_i2c_hw->engine_id = engine_id;
0628     dce_i2c_hw->reference_frequency = (ctx->dc_bios->fw_info.pll_info.crystal_frequency) >> 1;
0629     dce_i2c_hw->regs = regs;
0630     dce_i2c_hw->shifts = shifts;
0631     dce_i2c_hw->masks = masks;
0632     dce_i2c_hw->buffer_used_bytes = 0;
0633     dce_i2c_hw->transaction_count = 0;
0634     dce_i2c_hw->engine_keep_power_up_count = 1;
0635     dce_i2c_hw->default_speed = DEFAULT_I2C_HW_SPEED;
0636     dce_i2c_hw->send_reset_length = 0;
0637     dce_i2c_hw->setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
0638     dce_i2c_hw->buffer_size = I2C_HW_BUFFER_SIZE_DCE;
0639 }
0640 
0641 void dce100_i2c_hw_construct(
0642     struct dce_i2c_hw *dce_i2c_hw,
0643     struct dc_context *ctx,
0644     uint32_t engine_id,
0645     const struct dce_i2c_registers *regs,
0646     const struct dce_i2c_shift *shifts,
0647     const struct dce_i2c_mask *masks)
0648 {
0649     dce_i2c_hw_construct(dce_i2c_hw,
0650             ctx,
0651             engine_id,
0652             regs,
0653             shifts,
0654             masks);
0655     dce_i2c_hw->buffer_size = I2C_HW_BUFFER_SIZE_DCE100;
0656 }
0657 
0658 void dce112_i2c_hw_construct(
0659     struct dce_i2c_hw *dce_i2c_hw,
0660     struct dc_context *ctx,
0661     uint32_t engine_id,
0662     const struct dce_i2c_registers *regs,
0663     const struct dce_i2c_shift *shifts,
0664     const struct dce_i2c_mask *masks)
0665 {
0666     dce100_i2c_hw_construct(dce_i2c_hw,
0667             ctx,
0668             engine_id,
0669             regs,
0670             shifts,
0671             masks);
0672     dce_i2c_hw->default_speed = DEFAULT_I2C_HW_SPEED_100KHZ;
0673 }
0674 
0675 void dcn1_i2c_hw_construct(
0676     struct dce_i2c_hw *dce_i2c_hw,
0677     struct dc_context *ctx,
0678     uint32_t engine_id,
0679     const struct dce_i2c_registers *regs,
0680     const struct dce_i2c_shift *shifts,
0681     const struct dce_i2c_mask *masks)
0682 {
0683     dce112_i2c_hw_construct(dce_i2c_hw,
0684             ctx,
0685             engine_id,
0686             regs,
0687             shifts,
0688             masks);
0689     dce_i2c_hw->setup_limit = I2C_SETUP_TIME_LIMIT_DCN;
0690 }
0691 
0692 void dcn2_i2c_hw_construct(
0693     struct dce_i2c_hw *dce_i2c_hw,
0694     struct dc_context *ctx,
0695     uint32_t engine_id,
0696     const struct dce_i2c_registers *regs,
0697     const struct dce_i2c_shift *shifts,
0698     const struct dce_i2c_mask *masks)
0699 {
0700     dcn1_i2c_hw_construct(dce_i2c_hw,
0701             ctx,
0702             engine_id,
0703             regs,
0704             shifts,
0705             masks);
0706     dce_i2c_hw->send_reset_length = I2C_SEND_RESET_LENGTH_9;
0707     if (ctx->dc->debug.scl_reset_length10)
0708         dce_i2c_hw->send_reset_length = I2C_SEND_RESET_LENGTH_10;
0709 }