1 /*
2 * Copyright 2012-15 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26 #include <linux/delay.h>
27 #include <linux/slab.h>
28
29 #include "dm_services.h"
30 #include "core_types.h"
31 #include "dce_aux.h"
32 #include "dce/dce_11_0_sh_mask.h"
33 #include "dm_event_log.h"
34
35 #define CTX \
36 aux110->base.ctx
37 #define REG(reg_name)\
38 (aux110->regs->reg_name)
39
40 #define DC_LOGGER \
41 engine->ctx->logger
42
43 #include "reg_helper.h"
44
45 #undef FN
46 #define FN(reg_name, field_name) \
47 aux110->shift->field_name, aux110->mask->field_name
48
49 #define FROM_AUX_ENGINE(ptr) \
50 container_of((ptr), struct aux_engine_dce110, base)
51
52 #define FROM_ENGINE(ptr) \
53 FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base))
54
55 #define FROM_AUX_ENGINE_ENGINE(ptr) \
56 container_of((ptr), struct dce_aux, base)
57 enum {
58 AUX_INVALID_REPLY_RETRY_COUNTER = 1,
59 AUX_TIMED_OUT_RETRY_COUNTER = 2,
60 AUX_DEFER_RETRY_COUNTER = 6
61 };
62
63 #define TIME_OUT_INCREMENT 1016
64 #define TIME_OUT_MULTIPLIER_8 8
65 #define TIME_OUT_MULTIPLIER_16 16
66 #define TIME_OUT_MULTIPLIER_32 32
67 #define TIME_OUT_MULTIPLIER_64 64
68 #define MAX_TIMEOUT_LENGTH 127
69 #define DEFAULT_AUX_ENGINE_MULT 0
70 #define DEFAULT_AUX_ENGINE_LENGTH 69
71
release_engine(struct dce_aux * engine)72 static void release_engine(
73 struct dce_aux *engine)
74 {
75 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
76
77 dal_ddc_close(engine->ddc);
78
79 engine->ddc = NULL;
80
81 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1);
82 }
83
84 #define SW_CAN_ACCESS_AUX 1
85 #define DMCU_CAN_ACCESS_AUX 2
86
is_engine_available(struct dce_aux * engine)87 static bool is_engine_available(
88 struct dce_aux *engine)
89 {
90 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
91
92 uint32_t value = REG_READ(AUX_ARB_CONTROL);
93 uint32_t field = get_reg_field_value(
94 value,
95 AUX_ARB_CONTROL,
96 AUX_REG_RW_CNTL_STATUS);
97
98 return (field != DMCU_CAN_ACCESS_AUX);
99 }
acquire_engine(struct dce_aux * engine)100 static bool acquire_engine(
101 struct dce_aux *engine)
102 {
103 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
104
105 uint32_t value = REG_READ(AUX_ARB_CONTROL);
106 uint32_t field = get_reg_field_value(
107 value,
108 AUX_ARB_CONTROL,
109 AUX_REG_RW_CNTL_STATUS);
110 if (field == DMCU_CAN_ACCESS_AUX)
111 return false;
112 /* enable AUX before request SW to access AUX */
113 value = REG_READ(AUX_CONTROL);
114 field = get_reg_field_value(value,
115 AUX_CONTROL,
116 AUX_EN);
117
118 if (field == 0) {
119 set_reg_field_value(
120 value,
121 1,
122 AUX_CONTROL,
123 AUX_EN);
124
125 if (REG(AUX_RESET_MASK)) {
126 /*DP_AUX block as part of the enable sequence*/
127 set_reg_field_value(
128 value,
129 1,
130 AUX_CONTROL,
131 AUX_RESET);
132 }
133
134 REG_WRITE(AUX_CONTROL, value);
135
136 if (REG(AUX_RESET_MASK)) {
137 /*poll HW to make sure reset it done*/
138
139 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1,
140 1, 11);
141
142 set_reg_field_value(
143 value,
144 0,
145 AUX_CONTROL,
146 AUX_RESET);
147
148 REG_WRITE(AUX_CONTROL, value);
149
150 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0,
151 1, 11);
152 }
153 } /*if (field)*/
154
155 /* request SW to access AUX */
156 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1);
157
158 value = REG_READ(AUX_ARB_CONTROL);
159 field = get_reg_field_value(
160 value,
161 AUX_ARB_CONTROL,
162 AUX_REG_RW_CNTL_STATUS);
163
164 return (field == SW_CAN_ACCESS_AUX);
165 }
166
167 #define COMPOSE_AUX_SW_DATA_16_20(command, address) \
168 ((command) | ((0xF0000 & (address)) >> 16))
169
170 #define COMPOSE_AUX_SW_DATA_8_15(address) \
171 ((0xFF00 & (address)) >> 8)
172
173 #define COMPOSE_AUX_SW_DATA_0_7(address) \
174 (0xFF & (address))
175
submit_channel_request(struct dce_aux * engine,struct aux_request_transaction_data * request)176 static void submit_channel_request(
177 struct dce_aux *engine,
178 struct aux_request_transaction_data *request)
179 {
180 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
181 uint32_t value;
182 uint32_t length;
183
184 bool is_write =
185 ((request->type == AUX_TRANSACTION_TYPE_DP) &&
186 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
187 ((request->type == AUX_TRANSACTION_TYPE_I2C) &&
188 ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
189 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
190 if (REG(AUXN_IMPCAL)) {
191 /* clear_aux_error */
192 REG_UPDATE_SEQ_2(AUXN_IMPCAL,
193 AUXN_CALOUT_ERROR_AK, 1,
194 AUXN_CALOUT_ERROR_AK, 0);
195
196 REG_UPDATE_SEQ_2(AUXP_IMPCAL,
197 AUXP_CALOUT_ERROR_AK, 1,
198 AUXP_CALOUT_ERROR_AK, 0);
199
200 /* force_default_calibrate */
201 REG_UPDATE_SEQ_2(AUXN_IMPCAL,
202 AUXN_IMPCAL_ENABLE, 1,
203 AUXN_IMPCAL_OVERRIDE_ENABLE, 0);
204
205 /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */
206
207 REG_UPDATE_SEQ_2(AUXP_IMPCAL,
208 AUXP_IMPCAL_OVERRIDE_ENABLE, 1,
209 AUXP_IMPCAL_OVERRIDE_ENABLE, 0);
210 }
211
212 REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1);
213
214 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,
215 10, aux110->polling_timeout_period/10);
216
217 /* set the delay and the number of bytes to write */
218
219 /* The length include
220 * the 4 bit header and the 20 bit address
221 * (that is 3 byte).
222 * If the requested length is non zero this means
223 * an addition byte specifying the length is required.
224 */
225
226 length = request->length ? 4 : 3;
227 if (is_write)
228 length += request->length;
229
230 REG_UPDATE_2(AUX_SW_CONTROL,
231 AUX_SW_START_DELAY, request->delay,
232 AUX_SW_WR_BYTES, length);
233
234 /* program action and address and payload data (if 'is_write') */
235 value = REG_UPDATE_4(AUX_SW_DATA,
236 AUX_SW_INDEX, 0,
237 AUX_SW_DATA_RW, 0,
238 AUX_SW_AUTOINCREMENT_DISABLE, 1,
239 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address));
240
241 value = REG_SET_2(AUX_SW_DATA, value,
242 AUX_SW_AUTOINCREMENT_DISABLE, 0,
243 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address));
244
245 value = REG_SET(AUX_SW_DATA, value,
246 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address));
247
248 if (request->length) {
249 value = REG_SET(AUX_SW_DATA, value,
250 AUX_SW_DATA, request->length - 1);
251 }
252
253 if (is_write) {
254 /* Load the HW buffer with the Data to be sent.
255 * This is relevant for write operation.
256 * For read, the data recived data will be
257 * processed in process_channel_reply().
258 */
259 uint32_t i = 0;
260
261 while (i < request->length) {
262 value = REG_SET(AUX_SW_DATA, value,
263 AUX_SW_DATA, request->data[i]);
264
265 ++i;
266 }
267 }
268
269 REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
270 EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE,
271 request->action, request->address, request->length, request->data);
272 }
273
read_channel_reply(struct dce_aux * engine,uint32_t size,uint8_t * buffer,uint8_t * reply_result,uint32_t * sw_status)274 static int read_channel_reply(struct dce_aux *engine, uint32_t size,
275 uint8_t *buffer, uint8_t *reply_result,
276 uint32_t *sw_status)
277 {
278 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
279 uint32_t bytes_replied;
280 uint32_t reply_result_32;
281
282 *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT,
283 &bytes_replied);
284
285 /* In case HPD is LOW, exit AUX transaction */
286 if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
287 return -1;
288
289 /* Need at least the status byte */
290 if (!bytes_replied)
291 return -1;
292
293 REG_UPDATE_SEQ_3(AUX_SW_DATA,
294 AUX_SW_INDEX, 0,
295 AUX_SW_AUTOINCREMENT_DISABLE, 1,
296 AUX_SW_DATA_RW, 1);
297
298 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32);
299 reply_result_32 = reply_result_32 >> 4;
300 if (reply_result != NULL)
301 *reply_result = (uint8_t)reply_result_32;
302
303 if (reply_result_32 == 0) { /* ACK */
304 uint32_t i = 0;
305
306 /* First byte was already used to get the command status */
307 --bytes_replied;
308
309 /* Do not overflow buffer */
310 if (bytes_replied > size)
311 return -1;
312
313 while (i < bytes_replied) {
314 uint32_t aux_sw_data_val;
315
316 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val);
317 buffer[i] = aux_sw_data_val;
318 ++i;
319 }
320
321 return i;
322 }
323
324 return 0;
325 }
326
get_channel_status(struct dce_aux * engine,uint8_t * returned_bytes)327 static enum aux_channel_operation_result get_channel_status(
328 struct dce_aux *engine,
329 uint8_t *returned_bytes)
330 {
331 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
332
333 uint32_t value;
334
335 if (returned_bytes == NULL) {
336 /*caller pass NULL pointer*/
337 ASSERT_CRITICAL(false);
338 return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
339 }
340 *returned_bytes = 0;
341
342 /* poll to make sure that SW_DONE is asserted */
343 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
344 10, aux110->polling_timeout_period/10);
345
346 value = REG_READ(AUX_SW_STATUS);
347 /* in case HPD is LOW, exit AUX transaction */
348 if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
349 return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
350
351 /* Note that the following bits are set in 'status.bits'
352 * during CTS 4.2.1.2 (FW 3.3.1):
353 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
354 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
355 *
356 * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
357 * HW debugging bit and should be ignored.
358 */
359 if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) {
360 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) ||
361 (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK))
362 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
363
364 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) ||
365 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) ||
366 (value &
367 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) ||
368 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK))
369 return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
370
371 *returned_bytes = get_reg_field_value(value,
372 AUX_SW_STATUS,
373 AUX_SW_REPLY_BYTE_COUNT);
374
375 if (*returned_bytes == 0)
376 return
377 AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
378 else {
379 *returned_bytes -= 1;
380 return AUX_CHANNEL_OPERATION_SUCCEEDED;
381 }
382 } else {
383 /*time_elapsed >= aux_engine->timeout_period
384 * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point
385 */
386 ASSERT_CRITICAL(false);
387 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
388 }
389 }
390
get_engine_type(const struct dce_aux * engine)391 enum i2caux_engine_type get_engine_type(
392 const struct dce_aux *engine)
393 {
394 return I2CAUX_ENGINE_TYPE_AUX;
395 }
396
acquire(struct dce_aux * engine,struct ddc * ddc)397 static bool acquire(
398 struct dce_aux *engine,
399 struct ddc *ddc)
400 {
401 enum gpio_result result;
402
403 if ((engine == NULL) || !is_engine_available(engine))
404 return false;
405
406 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
407 GPIO_DDC_CONFIG_TYPE_MODE_AUX);
408
409 if (result != GPIO_RESULT_OK)
410 return false;
411
412 if (!acquire_engine(engine)) {
413 dal_ddc_close(ddc);
414 return false;
415 }
416
417 engine->ddc = ddc;
418
419 return true;
420 }
421
dce110_engine_destroy(struct dce_aux ** engine)422 void dce110_engine_destroy(struct dce_aux **engine)
423 {
424
425 struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine);
426
427 kfree(engine110);
428 *engine = NULL;
429
430 }
431
dce_aux_configure_timeout(struct ddc_service * ddc,uint32_t timeout_in_us)432 static uint32_t dce_aux_configure_timeout(struct ddc_service *ddc,
433 uint32_t timeout_in_us)
434 {
435 uint32_t multiplier = 0;
436 uint32_t length = 0;
437 uint32_t prev_length = 0;
438 uint32_t prev_mult = 0;
439 uint32_t prev_timeout_val = 0;
440 struct ddc *ddc_pin = ddc->ddc_pin;
441 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
442 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine);
443
444 /* 1-Update polling timeout period */
445 aux110->polling_timeout_period = timeout_in_us * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER;
446
447 /* 2-Update aux timeout period length and multiplier */
448 if (timeout_in_us == 0) {
449 multiplier = DEFAULT_AUX_ENGINE_MULT;
450 length = DEFAULT_AUX_ENGINE_LENGTH;
451 } else if (timeout_in_us <= TIME_OUT_INCREMENT) {
452 multiplier = 0;
453 length = timeout_in_us/TIME_OUT_MULTIPLIER_8;
454 if (timeout_in_us % TIME_OUT_MULTIPLIER_8 != 0)
455 length++;
456 } else if (timeout_in_us <= 2 * TIME_OUT_INCREMENT) {
457 multiplier = 1;
458 length = timeout_in_us/TIME_OUT_MULTIPLIER_16;
459 if (timeout_in_us % TIME_OUT_MULTIPLIER_16 != 0)
460 length++;
461 } else if (timeout_in_us <= 4 * TIME_OUT_INCREMENT) {
462 multiplier = 2;
463 length = timeout_in_us/TIME_OUT_MULTIPLIER_32;
464 if (timeout_in_us % TIME_OUT_MULTIPLIER_32 != 0)
465 length++;
466 } else if (timeout_in_us > 4 * TIME_OUT_INCREMENT) {
467 multiplier = 3;
468 length = timeout_in_us/TIME_OUT_MULTIPLIER_64;
469 if (timeout_in_us % TIME_OUT_MULTIPLIER_64 != 0)
470 length++;
471 }
472
473 length = (length < MAX_TIMEOUT_LENGTH) ? length : MAX_TIMEOUT_LENGTH;
474
475 REG_GET_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, &prev_length, AUX_RX_TIMEOUT_LEN_MUL, &prev_mult);
476
477 switch (prev_mult) {
478 case 0:
479 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_8;
480 break;
481 case 1:
482 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_16;
483 break;
484 case 2:
485 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_32;
486 break;
487 case 3:
488 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_64;
489 break;
490 default:
491 prev_timeout_val = DEFAULT_AUX_ENGINE_LENGTH * TIME_OUT_MULTIPLIER_8;
492 break;
493 }
494
495 REG_UPDATE_SEQ_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, length, AUX_RX_TIMEOUT_LEN_MUL, multiplier);
496
497 return prev_timeout_val;
498 }
499
500 static struct dce_aux_funcs aux_functions = {
501 .configure_timeout = NULL,
502 .destroy = NULL,
503 };
504
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,const struct dce110_aux_registers_mask * mask,const struct dce110_aux_registers_shift * shift,bool is_ext_aux_timeout_configurable)505 struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110,
506 struct dc_context *ctx,
507 uint32_t inst,
508 uint32_t timeout_period,
509 const struct dce110_aux_registers *regs,
510 const struct dce110_aux_registers_mask *mask,
511 const struct dce110_aux_registers_shift *shift,
512 bool is_ext_aux_timeout_configurable)
513 {
514 aux_engine110->base.ddc = NULL;
515 aux_engine110->base.ctx = ctx;
516 aux_engine110->base.delay = 0;
517 aux_engine110->base.max_defer_write_retry = 0;
518 aux_engine110->base.inst = inst;
519 aux_engine110->polling_timeout_period = timeout_period;
520 aux_engine110->regs = regs;
521
522 aux_engine110->mask = mask;
523 aux_engine110->shift = shift;
524 aux_engine110->base.funcs = &aux_functions;
525 if (is_ext_aux_timeout_configurable)
526 aux_engine110->base.funcs->configure_timeout = &dce_aux_configure_timeout;
527
528 return &aux_engine110->base;
529 }
530
i2caux_action_from_payload(struct aux_payload * payload)531 static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload)
532 {
533 if (payload->i2c_over_aux) {
534 if (payload->write) {
535 if (payload->mot)
536 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT;
537 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
538 }
539 if (payload->mot)
540 return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT;
541 return I2CAUX_TRANSACTION_ACTION_I2C_READ;
542 }
543 if (payload->write)
544 return I2CAUX_TRANSACTION_ACTION_DP_WRITE;
545 return I2CAUX_TRANSACTION_ACTION_DP_READ;
546 }
547
dce_aux_transfer_raw(struct ddc_service * ddc,struct aux_payload * payload,enum aux_channel_operation_result * operation_result)548 int dce_aux_transfer_raw(struct ddc_service *ddc,
549 struct aux_payload *payload,
550 enum aux_channel_operation_result *operation_result)
551 {
552 struct ddc *ddc_pin = ddc->ddc_pin;
553 struct dce_aux *aux_engine;
554 struct aux_request_transaction_data aux_req;
555 struct aux_reply_transaction_data aux_rep;
556 uint8_t returned_bytes = 0;
557 int res = -1;
558 uint32_t status;
559
560 memset(&aux_req, 0, sizeof(aux_req));
561 memset(&aux_rep, 0, sizeof(aux_rep));
562
563 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
564 if (!acquire(aux_engine, ddc_pin)) {
565 *operation_result = AUX_CHANNEL_OPERATION_FAILED_ENGINE_ACQUIRE;
566 return -1;
567 }
568
569 if (payload->i2c_over_aux)
570 aux_req.type = AUX_TRANSACTION_TYPE_I2C;
571 else
572 aux_req.type = AUX_TRANSACTION_TYPE_DP;
573
574 aux_req.action = i2caux_action_from_payload(payload);
575
576 aux_req.address = payload->address;
577 aux_req.delay = 0;
578 aux_req.length = payload->length;
579 aux_req.data = payload->data;
580
581 submit_channel_request(aux_engine, &aux_req);
582 *operation_result = get_channel_status(aux_engine, &returned_bytes);
583
584 if (*operation_result == AUX_CHANNEL_OPERATION_SUCCEEDED) {
585 int bytes_replied = 0;
586 bytes_replied = read_channel_reply(aux_engine, payload->length,
587 payload->data, payload->reply,
588 &status);
589 EVENT_LOG_AUX_REP(aux_engine->ddc->pin_data->en,
590 EVENT_LOG_AUX_ORIGIN_NATIVE, *payload->reply,
591 bytes_replied, payload->data);
592 res = returned_bytes;
593 } else {
594 res = -1;
595 }
596
597 release_engine(aux_engine);
598 return res;
599 }
600
601 #define AUX_MAX_RETRIES 7
602 #define AUX_MAX_DEFER_RETRIES 7
603 #define AUX_MAX_I2C_DEFER_RETRIES 7
604 #define AUX_MAX_INVALID_REPLY_RETRIES 2
605 #define AUX_MAX_TIMEOUT_RETRIES 3
606
dce_aux_transfer_with_retries(struct ddc_service * ddc,struct aux_payload * payload)607 bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
608 struct aux_payload *payload)
609 {
610 int i, ret = 0;
611 uint8_t reply;
612 bool payload_reply = true;
613 enum aux_channel_operation_result operation_result;
614 bool retry_on_defer = false;
615
616 int aux_ack_retries = 0,
617 aux_defer_retries = 0,
618 aux_i2c_defer_retries = 0,
619 aux_timeout_retries = 0,
620 aux_invalid_reply_retries = 0;
621
622 if (!payload->reply) {
623 payload_reply = false;
624 payload->reply = &reply;
625 }
626
627 for (i = 0; i < AUX_MAX_RETRIES; i++) {
628 ret = dce_aux_transfer_raw(ddc, payload, &operation_result);
629 switch (operation_result) {
630 case AUX_CHANNEL_OPERATION_SUCCEEDED:
631 aux_timeout_retries = 0;
632 aux_invalid_reply_retries = 0;
633
634 switch (*payload->reply) {
635 case AUX_TRANSACTION_REPLY_AUX_ACK:
636 if (!payload->write && payload->length != ret) {
637 if (++aux_ack_retries >= AUX_MAX_RETRIES)
638 goto fail;
639 else
640 udelay(300);
641 } else
642 return true;
643 break;
644
645 case AUX_TRANSACTION_REPLY_AUX_DEFER:
646 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
647 retry_on_defer = true;
648 fallthrough;
649 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
650 if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) {
651 goto fail;
652 } else {
653 if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) ||
654 (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) {
655 if (payload->defer_delay > 0)
656 msleep(payload->defer_delay);
657 }
658 }
659 break;
660
661 case AUX_TRANSACTION_REPLY_I2C_DEFER:
662 aux_defer_retries = 0;
663 if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES)
664 goto fail;
665 break;
666
667 case AUX_TRANSACTION_REPLY_AUX_NACK:
668 case AUX_TRANSACTION_REPLY_HPD_DISCON:
669 default:
670 goto fail;
671 }
672 break;
673
674 case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
675 if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES)
676 goto fail;
677 else
678 udelay(400);
679 break;
680
681 case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
682 // Check whether a DEFER had occurred before the timeout.
683 // If so, treat timeout as a DEFER.
684 if (retry_on_defer) {
685 if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES)
686 goto fail;
687 else if (payload->defer_delay > 0)
688 msleep(payload->defer_delay);
689 } else {
690 if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES)
691 goto fail;
692 else {
693 /*
694 * DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts
695 * According to the DP spec there should be 3 retries total
696 * with a 400us wait inbetween each. Hardware already waits
697 * for 550us therefore no wait is required here.
698 */
699 }
700 }
701 break;
702
703 case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
704 case AUX_CHANNEL_OPERATION_FAILED_ENGINE_ACQUIRE:
705 case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN:
706 default:
707 goto fail;
708 }
709 }
710
711 fail:
712 if (!payload_reply)
713 payload->reply = NULL;
714 return false;
715 }
716