1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "dm_services.h"
27#include "dce_aux.h"
28#include "dce/dce_11_0_sh_mask.h"
29
30#define CTX \
31 aux110->base.ctx
32#define REG(reg_name)\
33 (aux110->regs->reg_name)
34
35#define DC_LOGGER \
36 engine->ctx->logger
37
38#include "reg_helper.h"
39
40#define FROM_AUX_ENGINE(ptr) \
41 container_of((ptr), struct aux_engine_dce110, base)
42
43#define FROM_ENGINE(ptr) \
44 FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base))
45
46#define FROM_AUX_ENGINE_ENGINE(ptr) \
47 container_of((ptr), struct aux_engine, base)
48enum {
49 AUX_INVALID_REPLY_RETRY_COUNTER = 1,
50 AUX_TIMED_OUT_RETRY_COUNTER = 2,
51 AUX_DEFER_RETRY_COUNTER = 6
52};
53static void release_engine(
54 struct aux_engine *engine)
55{
56 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
57
58 dal_ddc_close(engine->ddc);
59
60 engine->ddc = NULL;
61
62 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1);
63}
64
65#define SW_CAN_ACCESS_AUX 1
66#define DMCU_CAN_ACCESS_AUX 2
67
68static bool is_engine_available(
69 struct aux_engine *engine)
70{
71 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
72
73 uint32_t value = REG_READ(AUX_ARB_CONTROL);
74 uint32_t field = get_reg_field_value(
75 value,
76 AUX_ARB_CONTROL,
77 AUX_REG_RW_CNTL_STATUS);
78
79 return (field != DMCU_CAN_ACCESS_AUX);
80}
81static bool acquire_engine(
82 struct aux_engine *engine)
83{
84 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
85
86 uint32_t value = REG_READ(AUX_ARB_CONTROL);
87 uint32_t field = get_reg_field_value(
88 value,
89 AUX_ARB_CONTROL,
90 AUX_REG_RW_CNTL_STATUS);
91 if (field == DMCU_CAN_ACCESS_AUX)
92 return false;
93
94 value = REG_READ(AUX_CONTROL);
95 field = get_reg_field_value(value,
96 AUX_CONTROL,
97 AUX_EN);
98
99 if (field == 0) {
100 set_reg_field_value(
101 value,
102 1,
103 AUX_CONTROL,
104 AUX_EN);
105
106 if (REG(AUX_RESET_MASK)) {
107
108 set_reg_field_value(
109 value,
110 1,
111 AUX_CONTROL,
112 AUX_RESET);
113 }
114
115 REG_WRITE(AUX_CONTROL, value);
116
117 if (REG(AUX_RESET_MASK)) {
118
119
120 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1,
121 1, 11);
122
123 set_reg_field_value(
124 value,
125 0,
126 AUX_CONTROL,
127 AUX_RESET);
128
129 REG_WRITE(AUX_CONTROL, value);
130
131 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0,
132 1, 11);
133 }
134 }
135
136
137 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1);
138
139 value = REG_READ(AUX_ARB_CONTROL);
140 field = get_reg_field_value(
141 value,
142 AUX_ARB_CONTROL,
143 AUX_REG_RW_CNTL_STATUS);
144
145 return (field == SW_CAN_ACCESS_AUX);
146}
147
148#define COMPOSE_AUX_SW_DATA_16_20(command, address) \
149 ((command) | ((0xF0000 & (address)) >> 16))
150
151#define COMPOSE_AUX_SW_DATA_8_15(address) \
152 ((0xFF00 & (address)) >> 8)
153
154#define COMPOSE_AUX_SW_DATA_0_7(address) \
155 (0xFF & (address))
156
157static void submit_channel_request(
158 struct aux_engine *engine,
159 struct aux_request_transaction_data *request)
160{
161 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
162 uint32_t value;
163 uint32_t length;
164
165 bool is_write =
166 ((request->type == AUX_TRANSACTION_TYPE_DP) &&
167 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
168 ((request->type == AUX_TRANSACTION_TYPE_I2C) &&
169 ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
170 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
171 if (REG(AUXN_IMPCAL)) {
172
173 REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK,
174 1,
175 0);
176
177 REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK,
178 1,
179 0);
180
181
182 REG_UPDATE_1BY1_2(AUXN_IMPCAL,
183 AUXN_IMPCAL_ENABLE, 1,
184 AUXN_IMPCAL_OVERRIDE_ENABLE, 0);
185
186
187
188 REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE,
189 1,
190 0);
191 }
192
193
194
195
196
197
198
199
200
201 length = request->length ? 4 : 3;
202 if (is_write)
203 length += request->length;
204
205 REG_UPDATE_2(AUX_SW_CONTROL,
206 AUX_SW_START_DELAY, request->delay,
207 AUX_SW_WR_BYTES, length);
208
209
210 value = REG_UPDATE_4(AUX_SW_DATA,
211 AUX_SW_INDEX, 0,
212 AUX_SW_DATA_RW, 0,
213 AUX_SW_AUTOINCREMENT_DISABLE, 1,
214 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address));
215
216 value = REG_SET_2(AUX_SW_DATA, value,
217 AUX_SW_AUTOINCREMENT_DISABLE, 0,
218 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address));
219
220 value = REG_SET(AUX_SW_DATA, value,
221 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address));
222
223 if (request->length) {
224 value = REG_SET(AUX_SW_DATA, value,
225 AUX_SW_DATA, request->length - 1);
226 }
227
228 if (is_write) {
229
230
231
232
233
234 uint32_t i = 0;
235
236 while (i < request->length) {
237 value = REG_SET(AUX_SW_DATA, value,
238 AUX_SW_DATA, request->data[i]);
239
240 ++i;
241 }
242 }
243
244 REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1);
245 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,
246 10, aux110->timeout_period/10);
247 REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
248}
249
250static int read_channel_reply(struct aux_engine *engine, uint32_t size,
251 uint8_t *buffer, uint8_t *reply_result,
252 uint32_t *sw_status)
253{
254 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
255 uint32_t bytes_replied;
256 uint32_t reply_result_32;
257
258 *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT,
259 &bytes_replied);
260
261
262 if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
263 return -1;
264
265
266 if (!bytes_replied)
267 return -1;
268
269 REG_UPDATE_1BY1_3(AUX_SW_DATA,
270 AUX_SW_INDEX, 0,
271 AUX_SW_AUTOINCREMENT_DISABLE, 1,
272 AUX_SW_DATA_RW, 1);
273
274 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32);
275 reply_result_32 = reply_result_32 >> 4;
276 *reply_result = (uint8_t)reply_result_32;
277
278 if (reply_result_32 == 0) {
279 uint32_t i = 0;
280
281
282 --bytes_replied;
283
284
285 if (bytes_replied > size)
286 return -1;
287
288 while (i < bytes_replied) {
289 uint32_t aux_sw_data_val;
290
291 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val);
292 buffer[i] = aux_sw_data_val;
293 ++i;
294 }
295
296 return i;
297 }
298
299 return 0;
300}
301
302static void process_channel_reply(
303 struct aux_engine *engine,
304 struct aux_reply_transaction_data *reply)
305{
306 int bytes_replied;
307 uint8_t reply_result;
308 uint32_t sw_status;
309
310 bytes_replied = read_channel_reply(engine, reply->length, reply->data,
311 &reply_result, &sw_status);
312
313
314 if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
315 reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON;
316 return;
317 }
318
319 if (bytes_replied < 0) {
320
321
322
323
324
325
326 if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
327 reply->status = AUX_TRANSACTION_REPLY_INVALID;
328 ASSERT_CRITICAL(false);
329 return;
330 }
331 } else {
332
333 switch (reply_result) {
334 case 0:
335 reply->status = AUX_TRANSACTION_REPLY_AUX_ACK;
336 break;
337 case 1:
338 reply->status = AUX_TRANSACTION_REPLY_AUX_NACK;
339 break;
340 case 2:
341 reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER;
342 break;
343 case 4:
344 reply->status = AUX_TRANSACTION_REPLY_I2C_NACK;
345 break;
346 case 8:
347 reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER;
348 break;
349 default:
350 reply->status = AUX_TRANSACTION_REPLY_INVALID;
351 }
352 }
353}
354
355static enum aux_channel_operation_result get_channel_status(
356 struct aux_engine *engine,
357 uint8_t *returned_bytes)
358{
359 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
360
361 uint32_t value;
362
363 if (returned_bytes == NULL) {
364
365 ASSERT_CRITICAL(false);
366 return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
367 }
368 *returned_bytes = 0;
369
370
371 value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
372 10, aux110->timeout_period/10);
373
374
375 if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
376 return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
377
378
379
380
381
382
383
384
385
386 if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) {
387 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) ||
388 (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK))
389 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
390
391 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) ||
392 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) ||
393 (value &
394 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) ||
395 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK))
396 return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
397
398 *returned_bytes = get_reg_field_value(value,
399 AUX_SW_STATUS,
400 AUX_SW_REPLY_BYTE_COUNT);
401
402 if (*returned_bytes == 0)
403 return
404 AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
405 else {
406 *returned_bytes -= 1;
407 return AUX_CHANNEL_OPERATION_SUCCEEDED;
408 }
409 } else {
410
411
412
413 ASSERT_CRITICAL(false);
414 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
415 }
416}
417static void process_read_reply(
418 struct aux_engine *engine,
419 struct read_command_context *ctx)
420{
421 engine->funcs->process_channel_reply(engine, &ctx->reply);
422
423 switch (ctx->reply.status) {
424 case AUX_TRANSACTION_REPLY_AUX_ACK:
425 ctx->defer_retry_aux = 0;
426 if (ctx->returned_byte > ctx->current_read_length) {
427 ctx->status =
428 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
429 ctx->operation_succeeded = false;
430 } else if (ctx->returned_byte < ctx->current_read_length) {
431 ctx->current_read_length -= ctx->returned_byte;
432
433 ctx->offset += ctx->returned_byte;
434
435 ++ctx->invalid_reply_retry_aux_on_ack;
436
437 if (ctx->invalid_reply_retry_aux_on_ack >
438 AUX_INVALID_REPLY_RETRY_COUNTER) {
439 ctx->status =
440 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
441 ctx->operation_succeeded = false;
442 }
443 } else {
444 ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
445 ctx->transaction_complete = true;
446 ctx->operation_succeeded = true;
447 }
448 break;
449 case AUX_TRANSACTION_REPLY_AUX_NACK:
450 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
451 ctx->operation_succeeded = false;
452 break;
453 case AUX_TRANSACTION_REPLY_AUX_DEFER:
454 ++ctx->defer_retry_aux;
455
456 if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) {
457 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
458 ctx->operation_succeeded = false;
459 }
460 break;
461 case AUX_TRANSACTION_REPLY_I2C_DEFER:
462 ctx->defer_retry_aux = 0;
463
464 ++ctx->defer_retry_i2c;
465
466 if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) {
467 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
468 ctx->operation_succeeded = false;
469 }
470 break;
471 case AUX_TRANSACTION_REPLY_HPD_DISCON:
472 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
473 ctx->operation_succeeded = false;
474 break;
475 default:
476 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
477 ctx->operation_succeeded = false;
478 }
479}
480static void process_read_request(
481 struct aux_engine *engine,
482 struct read_command_context *ctx)
483{
484 enum aux_channel_operation_result operation_result;
485
486 engine->funcs->submit_channel_request(engine, &ctx->request);
487
488 operation_result = engine->funcs->get_channel_status(
489 engine, &ctx->returned_byte);
490
491 switch (operation_result) {
492 case AUX_CHANNEL_OPERATION_SUCCEEDED:
493 if (ctx->returned_byte > ctx->current_read_length) {
494 ctx->status =
495 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
496 ctx->operation_succeeded = false;
497 } else {
498 ctx->timed_out_retry_aux = 0;
499 ctx->invalid_reply_retry_aux = 0;
500
501 ctx->reply.length = ctx->returned_byte;
502 ctx->reply.data = ctx->buffer;
503
504 process_read_reply(engine, ctx);
505 }
506 break;
507 case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
508 ++ctx->invalid_reply_retry_aux;
509
510 if (ctx->invalid_reply_retry_aux >
511 AUX_INVALID_REPLY_RETRY_COUNTER) {
512 ctx->status =
513 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
514 ctx->operation_succeeded = false;
515 } else
516 udelay(400);
517 break;
518 case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
519 ++ctx->timed_out_retry_aux;
520
521 if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
522 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
523 ctx->operation_succeeded = false;
524 } else {
525
526
527
528
529
530
531 }
532 break;
533 case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
534 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
535 ctx->operation_succeeded = false;
536 break;
537 default:
538 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
539 ctx->operation_succeeded = false;
540 }
541}
542static bool read_command(
543 struct aux_engine *engine,
544 struct i2caux_transaction_request *request,
545 bool middle_of_transaction)
546{
547 struct read_command_context ctx;
548
549 ctx.buffer = request->payload.data;
550 ctx.current_read_length = request->payload.length;
551 ctx.offset = 0;
552 ctx.timed_out_retry_aux = 0;
553 ctx.invalid_reply_retry_aux = 0;
554 ctx.defer_retry_aux = 0;
555 ctx.defer_retry_i2c = 0;
556 ctx.invalid_reply_retry_aux_on_ack = 0;
557 ctx.transaction_complete = false;
558 ctx.operation_succeeded = true;
559
560 if (request->payload.address_space ==
561 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
562 ctx.request.type = AUX_TRANSACTION_TYPE_DP;
563 ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ;
564 ctx.request.address = request->payload.address;
565 } else if (request->payload.address_space ==
566 I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
567 ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
568 ctx.request.action = middle_of_transaction ?
569 I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
570 I2CAUX_TRANSACTION_ACTION_I2C_READ;
571 ctx.request.address = request->payload.address >> 1;
572 } else {
573
574 BREAK_TO_DEBUGGER();
575 return false;
576 }
577
578 ctx.request.delay = 0;
579
580 do {
581 memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length);
582
583 ctx.request.data = ctx.buffer + ctx.offset;
584 ctx.request.length = ctx.current_read_length;
585
586 process_read_request(engine, &ctx);
587
588 request->status = ctx.status;
589
590 if (ctx.operation_succeeded && !ctx.transaction_complete)
591 if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
592 msleep(engine->delay);
593 } while (ctx.operation_succeeded && !ctx.transaction_complete);
594
595 if (request->payload.address_space ==
596 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
597 DC_LOG_I2C_AUX("READ: addr:0x%x value:0x%x Result:%d",
598 request->payload.address,
599 request->payload.data[0],
600 ctx.operation_succeeded);
601 }
602
603 return ctx.operation_succeeded;
604}
605
606static void process_write_reply(
607 struct aux_engine *engine,
608 struct write_command_context *ctx)
609{
610 engine->funcs->process_channel_reply(engine, &ctx->reply);
611
612 switch (ctx->reply.status) {
613 case AUX_TRANSACTION_REPLY_AUX_ACK:
614 ctx->operation_succeeded = true;
615
616 if (ctx->returned_byte) {
617 ctx->request.action = ctx->mot ?
618 I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
619 I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
620
621 ctx->current_write_length = 0;
622
623 ++ctx->ack_m_retry;
624
625 if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) {
626 ctx->status =
627 I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
628 ctx->operation_succeeded = false;
629 } else
630 udelay(300);
631 } else {
632 ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
633 ctx->defer_retry_aux = 0;
634 ctx->ack_m_retry = 0;
635 ctx->transaction_complete = true;
636 }
637 break;
638 case AUX_TRANSACTION_REPLY_AUX_NACK:
639 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
640 ctx->operation_succeeded = false;
641 break;
642 case AUX_TRANSACTION_REPLY_AUX_DEFER:
643 ++ctx->defer_retry_aux;
644
645 if (ctx->defer_retry_aux > ctx->max_defer_retry) {
646 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
647 ctx->operation_succeeded = false;
648 }
649 break;
650 case AUX_TRANSACTION_REPLY_I2C_DEFER:
651 ctx->defer_retry_aux = 0;
652 ctx->current_write_length = 0;
653
654 ctx->request.action = ctx->mot ?
655 I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
656 I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
657
658 ++ctx->defer_retry_i2c;
659
660 if (ctx->defer_retry_i2c > ctx->max_defer_retry) {
661 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
662 ctx->operation_succeeded = false;
663 }
664 break;
665 case AUX_TRANSACTION_REPLY_HPD_DISCON:
666 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
667 ctx->operation_succeeded = false;
668 break;
669 default:
670 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
671 ctx->operation_succeeded = false;
672 }
673}
674static void process_write_request(
675 struct aux_engine *engine,
676 struct write_command_context *ctx)
677{
678 enum aux_channel_operation_result operation_result;
679
680 engine->funcs->submit_channel_request(engine, &ctx->request);
681
682 operation_result = engine->funcs->get_channel_status(
683 engine, &ctx->returned_byte);
684
685 switch (operation_result) {
686 case AUX_CHANNEL_OPERATION_SUCCEEDED:
687 ctx->timed_out_retry_aux = 0;
688 ctx->invalid_reply_retry_aux = 0;
689
690 ctx->reply.length = ctx->returned_byte;
691 ctx->reply.data = ctx->reply_data;
692
693 process_write_reply(engine, ctx);
694 break;
695 case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
696 ++ctx->invalid_reply_retry_aux;
697
698 if (ctx->invalid_reply_retry_aux >
699 AUX_INVALID_REPLY_RETRY_COUNTER) {
700 ctx->status =
701 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
702 ctx->operation_succeeded = false;
703 } else
704 udelay(400);
705 break;
706 case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
707 ++ctx->timed_out_retry_aux;
708
709 if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
710 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
711 ctx->operation_succeeded = false;
712 } else {
713
714
715
716
717
718
719 }
720 break;
721 case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
722 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
723 ctx->operation_succeeded = false;
724 break;
725 default:
726 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
727 ctx->operation_succeeded = false;
728 }
729}
730static bool write_command(
731 struct aux_engine *engine,
732 struct i2caux_transaction_request *request,
733 bool middle_of_transaction)
734{
735 struct write_command_context ctx;
736
737 ctx.mot = middle_of_transaction;
738 ctx.buffer = request->payload.data;
739 ctx.current_write_length = request->payload.length;
740 ctx.timed_out_retry_aux = 0;
741 ctx.invalid_reply_retry_aux = 0;
742 ctx.defer_retry_aux = 0;
743 ctx.defer_retry_i2c = 0;
744 ctx.ack_m_retry = 0;
745 ctx.transaction_complete = false;
746 ctx.operation_succeeded = true;
747
748 if (request->payload.address_space ==
749 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
750 ctx.request.type = AUX_TRANSACTION_TYPE_DP;
751 ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE;
752 ctx.request.address = request->payload.address;
753 } else if (request->payload.address_space ==
754 I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
755 ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
756 ctx.request.action = middle_of_transaction ?
757 I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
758 I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
759 ctx.request.address = request->payload.address >> 1;
760 } else {
761
762 BREAK_TO_DEBUGGER();
763 return false;
764 }
765
766 ctx.request.delay = 0;
767
768 ctx.max_defer_retry =
769 (engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ?
770 engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER;
771
772 do {
773 ctx.request.data = ctx.buffer;
774 ctx.request.length = ctx.current_write_length;
775
776 process_write_request(engine, &ctx);
777
778 request->status = ctx.status;
779
780 if (ctx.operation_succeeded && !ctx.transaction_complete)
781 if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
782 msleep(engine->delay);
783 } while (ctx.operation_succeeded && !ctx.transaction_complete);
784
785 if (request->payload.address_space ==
786 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
787 DC_LOG_I2C_AUX("WRITE: addr:0x%x value:0x%x Result:%d",
788 request->payload.address,
789 request->payload.data[0],
790 ctx.operation_succeeded);
791 }
792
793 return ctx.operation_succeeded;
794}
795static bool end_of_transaction_command(
796 struct aux_engine *engine,
797 struct i2caux_transaction_request *request)
798{
799 struct i2caux_transaction_request dummy_request;
800 uint8_t dummy_data;
801
802
803
804
805
806 if (request->payload.address_space !=
807 I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C)
808 return false;
809
810 dummy_request.operation = request->operation;
811 dummy_request.payload.address_space = request->payload.address_space;
812 dummy_request.payload.address = request->payload.address;
813
814
815
816
817
818
819
820 dummy_request.payload.length = 0;
821 dummy_request.payload.data = &dummy_data;
822
823 if (request->operation == I2CAUX_TRANSACTION_READ)
824 return read_command(engine, &dummy_request, false);
825 else
826 return write_command(engine, &dummy_request, false);
827
828
829}
830static bool submit_request(
831 struct aux_engine *engine,
832 struct i2caux_transaction_request *request,
833 bool middle_of_transaction)
834{
835
836 bool result;
837 bool mot_used = true;
838
839 switch (request->operation) {
840 case I2CAUX_TRANSACTION_READ:
841 result = read_command(engine, request, mot_used);
842 break;
843 case I2CAUX_TRANSACTION_WRITE:
844 result = write_command(engine, request, mot_used);
845 break;
846 default:
847 result = false;
848 }
849
850
851
852
853
854
855 if (!middle_of_transaction || !result)
856 end_of_transaction_command(engine, request);
857
858
859
860 return result;
861}
862enum i2caux_engine_type get_engine_type(
863 const struct aux_engine *engine)
864{
865 return I2CAUX_ENGINE_TYPE_AUX;
866}
867
868static bool acquire(
869 struct aux_engine *engine,
870 struct ddc *ddc)
871{
872
873 enum gpio_result result;
874
875 if (engine->funcs->is_engine_available) {
876
877 if (!engine->funcs->is_engine_available(engine))
878 return false;
879 }
880
881 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
882 GPIO_DDC_CONFIG_TYPE_MODE_AUX);
883
884 if (result != GPIO_RESULT_OK)
885 return false;
886
887 if (!engine->funcs->acquire_engine(engine)) {
888 dal_ddc_close(ddc);
889 return false;
890 }
891
892 engine->ddc = ddc;
893
894 return true;
895}
896
897static const struct aux_engine_funcs aux_engine_funcs = {
898 .acquire_engine = acquire_engine,
899 .submit_channel_request = submit_channel_request,
900 .process_channel_reply = process_channel_reply,
901 .read_channel_reply = read_channel_reply,
902 .get_channel_status = get_channel_status,
903 .is_engine_available = is_engine_available,
904 .release_engine = release_engine,
905 .destroy_engine = dce110_engine_destroy,
906 .submit_request = submit_request,
907 .get_engine_type = get_engine_type,
908 .acquire = acquire,
909};
910
911void dce110_engine_destroy(struct aux_engine **engine)
912{
913
914 struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine);
915
916 kfree(engine110);
917 *engine = NULL;
918
919}
920struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110,
921 struct dc_context *ctx,
922 uint32_t inst,
923 uint32_t timeout_period,
924 const struct dce110_aux_registers *regs)
925{
926 aux_engine110->base.ddc = NULL;
927 aux_engine110->base.ctx = ctx;
928 aux_engine110->base.delay = 0;
929 aux_engine110->base.max_defer_write_retry = 0;
930 aux_engine110->base.funcs = &aux_engine_funcs;
931 aux_engine110->base.inst = inst;
932 aux_engine110->timeout_period = timeout_period;
933 aux_engine110->regs = regs;
934
935 return &aux_engine110->base;
936}
937
938