GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / gpu / drm / amd / display / dc / dce / dce_aux.c
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 "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)
48 enum {
49         AUX_INVALID_REPLY_RETRY_COUNTER = 1,
50         AUX_TIMED_OUT_RETRY_COUNTER = 2,
51         AUX_DEFER_RETRY_COUNTER = 6
52 };
53 static 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
68 static 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 }
81 static 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         /* enable AUX before request SW to access AUX */
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                         /*DP_AUX block as part of the enable sequence*/
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                         /*poll HW to make sure reset it done*/
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         } /*if (field)*/
135
136         /* request SW to access AUX */
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
157 static 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                 /* clear_aux_error */
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                 /* force_default_calibrate */
182                 REG_UPDATE_1BY1_2(AUXN_IMPCAL,
183                                 AUXN_IMPCAL_ENABLE, 1,
184                                 AUXN_IMPCAL_OVERRIDE_ENABLE, 0);
185
186                 /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */
187
188                 REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE,
189                                 1,
190                                 0);
191         }
192
193         REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1);
194
195         REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,
196                                 10, aux110->timeout_period/10);
197
198         /* set the delay and the number of bytes to write */
199
200         /* The length include
201          * the 4 bit header and the 20 bit address
202          * (that is 3 byte).
203          * If the requested length is non zero this means
204          * an addition byte specifying the length is required.
205          */
206
207         length = request->length ? 4 : 3;
208         if (is_write)
209                 length += request->length;
210
211         REG_UPDATE_2(AUX_SW_CONTROL,
212                         AUX_SW_START_DELAY, request->delay,
213                         AUX_SW_WR_BYTES, length);
214
215         /* program action and address and payload data (if 'is_write') */
216         value = REG_UPDATE_4(AUX_SW_DATA,
217                         AUX_SW_INDEX, 0,
218                         AUX_SW_DATA_RW, 0,
219                         AUX_SW_AUTOINCREMENT_DISABLE, 1,
220                         AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address));
221
222         value = REG_SET_2(AUX_SW_DATA, value,
223                         AUX_SW_AUTOINCREMENT_DISABLE, 0,
224                         AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address));
225
226         value = REG_SET(AUX_SW_DATA, value,
227                         AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address));
228
229         if (request->length) {
230                 value = REG_SET(AUX_SW_DATA, value,
231                                 AUX_SW_DATA, request->length - 1);
232         }
233
234         if (is_write) {
235                 /* Load the HW buffer with the Data to be sent.
236                  * This is relevant for write operation.
237                  * For read, the data recived data will be
238                  * processed in process_channel_reply().
239                  */
240                 uint32_t i = 0;
241
242                 while (i < request->length) {
243                         value = REG_SET(AUX_SW_DATA, value,
244                                         AUX_SW_DATA, request->data[i]);
245
246                         ++i;
247                 }
248         }
249
250         REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
251 }
252
253 static int read_channel_reply(struct aux_engine *engine, uint32_t size,
254                               uint8_t *buffer, uint8_t *reply_result,
255                               uint32_t *sw_status)
256 {
257         struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
258         uint32_t bytes_replied;
259         uint32_t reply_result_32;
260
261         *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT,
262                              &bytes_replied);
263
264         /* In case HPD is LOW, exit AUX transaction */
265         if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
266                 return -1;
267
268         /* Need at least the status byte */
269         if (!bytes_replied)
270                 return -1;
271
272         REG_UPDATE_1BY1_3(AUX_SW_DATA,
273                           AUX_SW_INDEX, 0,
274                           AUX_SW_AUTOINCREMENT_DISABLE, 1,
275                           AUX_SW_DATA_RW, 1);
276
277         REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32);
278         reply_result_32 = reply_result_32 >> 4;
279         *reply_result = (uint8_t)reply_result_32;
280
281         if (reply_result_32 == 0) { /* ACK */
282                 uint32_t i = 0;
283
284                 /* First byte was already used to get the command status */
285                 --bytes_replied;
286
287                 /* Do not overflow buffer */
288                 if (bytes_replied > size)
289                         return -1;
290
291                 while (i < bytes_replied) {
292                         uint32_t aux_sw_data_val;
293
294                         REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val);
295                         buffer[i] = aux_sw_data_val;
296                         ++i;
297                 }
298
299                 return i;
300         }
301
302         return 0;
303 }
304
305 static void process_channel_reply(
306         struct aux_engine *engine,
307         struct aux_reply_transaction_data *reply)
308 {
309         int bytes_replied;
310         uint8_t reply_result;
311         uint32_t sw_status;
312
313         bytes_replied = read_channel_reply(engine, reply->length, reply->data,
314                                            &reply_result, &sw_status);
315
316         /* in case HPD is LOW, exit AUX transaction */
317         if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
318                 reply->status = AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
319                 return;
320         }
321
322         if (bytes_replied < 0) {
323                 /* Need to handle an error case...
324                  * Hopefully, upper layer function won't call this function if
325                  * the number of bytes in the reply was 0, because there was
326                  * surely an error that was asserted that should have been
327                  * handled for hot plug case, this could happens
328                  */
329                 if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
330                         reply->status = AUX_TRANSACTION_REPLY_INVALID;
331                         ASSERT_CRITICAL(false);
332                         return;
333                 }
334         } else {
335
336                 switch (reply_result) {
337                 case 0: /* ACK */
338                         reply->status = AUX_TRANSACTION_REPLY_AUX_ACK;
339                 break;
340                 case 1: /* NACK */
341                         reply->status = AUX_TRANSACTION_REPLY_AUX_NACK;
342                 break;
343                 case 2: /* DEFER */
344                         reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER;
345                 break;
346                 case 4: /* AUX ACK / I2C NACK */
347                         reply->status = AUX_TRANSACTION_REPLY_I2C_NACK;
348                 break;
349                 case 8: /* AUX ACK / I2C DEFER */
350                         reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER;
351                 break;
352                 default:
353                         reply->status = AUX_TRANSACTION_REPLY_INVALID;
354                 }
355         }
356 }
357
358 static enum aux_channel_operation_result get_channel_status(
359         struct aux_engine *engine,
360         uint8_t *returned_bytes)
361 {
362         struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
363
364         uint32_t value;
365
366         if (returned_bytes == NULL) {
367                 /*caller pass NULL pointer*/
368                 ASSERT_CRITICAL(false);
369                 return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
370         }
371         *returned_bytes = 0;
372
373         /* poll to make sure that SW_DONE is asserted */
374         value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
375                                 10, aux110->timeout_period/10);
376
377         /* in case HPD is LOW, exit AUX transaction */
378         if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
379                 return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
380
381         /* Note that the following bits are set in 'status.bits'
382          * during CTS 4.2.1.2 (FW 3.3.1):
383          * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
384          * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
385          *
386          * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
387          * HW debugging bit and should be ignored.
388          */
389         if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) {
390                 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) ||
391                         (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK))
392                         return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
393
394                 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) ||
395                         (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) ||
396                         (value &
397                                 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) ||
398                         (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK))
399                         return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
400
401                 *returned_bytes = get_reg_field_value(value,
402                                 AUX_SW_STATUS,
403                                 AUX_SW_REPLY_BYTE_COUNT);
404
405                 if (*returned_bytes == 0)
406                         return
407                         AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
408                 else {
409                         *returned_bytes -= 1;
410                         return AUX_CHANNEL_OPERATION_SUCCEEDED;
411                 }
412         } else {
413                 /*time_elapsed >= aux_engine->timeout_period
414                  *  AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point
415                  */
416                 ASSERT_CRITICAL(false);
417                 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
418         }
419 }
420 static void process_read_reply(
421         struct aux_engine *engine,
422         struct read_command_context *ctx)
423 {
424         engine->funcs->process_channel_reply(engine, &ctx->reply);
425
426         switch (ctx->reply.status) {
427         case AUX_TRANSACTION_REPLY_AUX_ACK:
428                 ctx->defer_retry_aux = 0;
429                 if (ctx->returned_byte > ctx->current_read_length) {
430                         ctx->status =
431                                 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
432                         ctx->operation_succeeded = false;
433                 } else if (ctx->returned_byte < ctx->current_read_length) {
434                         ctx->current_read_length -= ctx->returned_byte;
435
436                         ctx->offset += ctx->returned_byte;
437
438                         ++ctx->invalid_reply_retry_aux_on_ack;
439
440                         if (ctx->invalid_reply_retry_aux_on_ack >
441                                 AUX_INVALID_REPLY_RETRY_COUNTER) {
442                                 ctx->status =
443                                 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
444                                 ctx->operation_succeeded = false;
445                         }
446                 } else {
447                         ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
448                         ctx->transaction_complete = true;
449                         ctx->operation_succeeded = true;
450                 }
451         break;
452         case AUX_TRANSACTION_REPLY_AUX_NACK:
453                 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
454                 ctx->operation_succeeded = false;
455         break;
456         case AUX_TRANSACTION_REPLY_AUX_DEFER:
457                 ++ctx->defer_retry_aux;
458
459                 if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) {
460                         ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
461                         ctx->operation_succeeded = false;
462                 }
463         break;
464         case AUX_TRANSACTION_REPLY_I2C_DEFER:
465                 ctx->defer_retry_aux = 0;
466
467                 ++ctx->defer_retry_i2c;
468
469                 if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) {
470                         ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
471                         ctx->operation_succeeded = false;
472                 }
473         break;
474         case AUX_TRANSACTION_REPLY_HPD_DISCON:
475                 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
476                 ctx->operation_succeeded = false;
477         break;
478         default:
479                 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
480                 ctx->operation_succeeded = false;
481         }
482 }
483 static void process_read_request(
484         struct aux_engine *engine,
485         struct read_command_context *ctx)
486 {
487         enum aux_channel_operation_result operation_result;
488
489         engine->funcs->submit_channel_request(engine, &ctx->request);
490
491         operation_result = engine->funcs->get_channel_status(
492                 engine, &ctx->returned_byte);
493
494         switch (operation_result) {
495         case AUX_CHANNEL_OPERATION_SUCCEEDED:
496                 if (ctx->returned_byte > ctx->current_read_length) {
497                         ctx->status =
498                                 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
499                         ctx->operation_succeeded = false;
500                 } else {
501                         ctx->timed_out_retry_aux = 0;
502                         ctx->invalid_reply_retry_aux = 0;
503
504                         ctx->reply.length = ctx->returned_byte;
505                         ctx->reply.data = ctx->buffer;
506
507                         process_read_reply(engine, ctx);
508                 }
509         break;
510         case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
511                 ++ctx->invalid_reply_retry_aux;
512
513                 if (ctx->invalid_reply_retry_aux >
514                         AUX_INVALID_REPLY_RETRY_COUNTER) {
515                         ctx->status =
516                                 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
517                         ctx->operation_succeeded = false;
518                 } else
519                         udelay(400);
520         break;
521         case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
522                 ++ctx->timed_out_retry_aux;
523
524                 if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
525                         ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
526                         ctx->operation_succeeded = false;
527                 } else {
528                         /* DP 1.2a, table 2-58:
529                          * "S3: AUX Request CMD PENDING:
530                          * retry 3 times, with 400usec wait on each"
531                          * The HW timeout is set to 550usec,
532                          * so we should not wait here
533                          */
534                 }
535         break;
536         case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
537                 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
538                 ctx->operation_succeeded = false;
539         break;
540         default:
541                 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
542                 ctx->operation_succeeded = false;
543         }
544 }
545 static bool read_command(
546         struct aux_engine *engine,
547         struct i2caux_transaction_request *request,
548         bool middle_of_transaction)
549 {
550         struct read_command_context ctx;
551
552         ctx.buffer = request->payload.data;
553         ctx.current_read_length = request->payload.length;
554         ctx.offset = 0;
555         ctx.timed_out_retry_aux = 0;
556         ctx.invalid_reply_retry_aux = 0;
557         ctx.defer_retry_aux = 0;
558         ctx.defer_retry_i2c = 0;
559         ctx.invalid_reply_retry_aux_on_ack = 0;
560         ctx.transaction_complete = false;
561         ctx.operation_succeeded = true;
562
563         if (request->payload.address_space ==
564                 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
565                 ctx.request.type = AUX_TRANSACTION_TYPE_DP;
566                 ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ;
567                 ctx.request.address = request->payload.address;
568         } else if (request->payload.address_space ==
569                 I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
570                 ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
571                 ctx.request.action = middle_of_transaction ?
572                         I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
573                         I2CAUX_TRANSACTION_ACTION_I2C_READ;
574                 ctx.request.address = request->payload.address >> 1;
575         } else {
576                 /* in DAL2, there was no return in such case */
577                 BREAK_TO_DEBUGGER();
578                 return false;
579         }
580
581         ctx.request.delay = 0;
582
583         do {
584                 memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length);
585
586                 ctx.request.data = ctx.buffer + ctx.offset;
587                 ctx.request.length = ctx.current_read_length;
588
589                 process_read_request(engine, &ctx);
590
591                 request->status = ctx.status;
592
593                 if (ctx.operation_succeeded && !ctx.transaction_complete)
594                         if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
595                                 msleep(engine->delay);
596         } while (ctx.operation_succeeded && !ctx.transaction_complete);
597
598         if (request->payload.address_space ==
599                 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
600                 DC_LOG_I2C_AUX("READ: addr:0x%x  value:0x%x Result:%d",
601                                 request->payload.address,
602                                 request->payload.data[0],
603                                 ctx.operation_succeeded);
604         }
605
606         return ctx.operation_succeeded;
607 }
608
609 static void process_write_reply(
610         struct aux_engine *engine,
611         struct write_command_context *ctx)
612 {
613         engine->funcs->process_channel_reply(engine, &ctx->reply);
614
615         switch (ctx->reply.status) {
616         case AUX_TRANSACTION_REPLY_AUX_ACK:
617                 ctx->operation_succeeded = true;
618
619                 if (ctx->returned_byte) {
620                         ctx->request.action = ctx->mot ?
621                         I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
622                         I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
623
624                         ctx->current_write_length = 0;
625
626                         ++ctx->ack_m_retry;
627
628                         if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) {
629                                 ctx->status =
630                                 I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
631                                 ctx->operation_succeeded = false;
632                         } else
633                                 udelay(300);
634                 } else {
635                         ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
636                         ctx->defer_retry_aux = 0;
637                         ctx->ack_m_retry = 0;
638                         ctx->transaction_complete = true;
639                 }
640         break;
641         case AUX_TRANSACTION_REPLY_AUX_NACK:
642                 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
643                 ctx->operation_succeeded = false;
644         break;
645         case AUX_TRANSACTION_REPLY_AUX_DEFER:
646                 ++ctx->defer_retry_aux;
647
648                 if (ctx->defer_retry_aux > ctx->max_defer_retry) {
649                         ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
650                         ctx->operation_succeeded = false;
651                 }
652         break;
653         case AUX_TRANSACTION_REPLY_I2C_DEFER:
654                 ctx->defer_retry_aux = 0;
655                 ctx->current_write_length = 0;
656
657                 ctx->request.action = ctx->mot ?
658                         I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
659                         I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
660
661                 ++ctx->defer_retry_i2c;
662
663                 if (ctx->defer_retry_i2c > ctx->max_defer_retry) {
664                         ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
665                         ctx->operation_succeeded = false;
666                 }
667         break;
668         case AUX_TRANSACTION_REPLY_HPD_DISCON:
669                 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
670                 ctx->operation_succeeded = false;
671         break;
672         default:
673                 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
674                 ctx->operation_succeeded = false;
675         }
676 }
677 static void process_write_request(
678         struct aux_engine *engine,
679         struct write_command_context *ctx)
680 {
681         enum aux_channel_operation_result operation_result;
682
683         engine->funcs->submit_channel_request(engine, &ctx->request);
684
685         operation_result = engine->funcs->get_channel_status(
686                 engine, &ctx->returned_byte);
687
688         switch (operation_result) {
689         case AUX_CHANNEL_OPERATION_SUCCEEDED:
690                 ctx->timed_out_retry_aux = 0;
691                 ctx->invalid_reply_retry_aux = 0;
692
693                 ctx->reply.length = ctx->returned_byte;
694                 ctx->reply.data = ctx->reply_data;
695
696                 process_write_reply(engine, ctx);
697         break;
698         case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
699                 ++ctx->invalid_reply_retry_aux;
700
701                 if (ctx->invalid_reply_retry_aux >
702                         AUX_INVALID_REPLY_RETRY_COUNTER) {
703                         ctx->status =
704                                 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
705                         ctx->operation_succeeded = false;
706                 } else
707                         udelay(400);
708         break;
709         case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
710                 ++ctx->timed_out_retry_aux;
711
712                 if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
713                         ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
714                         ctx->operation_succeeded = false;
715                 } else {
716                         /* DP 1.2a, table 2-58:
717                          * "S3: AUX Request CMD PENDING:
718                          * retry 3 times, with 400usec wait on each"
719                          * The HW timeout is set to 550usec,
720                          * so we should not wait here
721                          */
722                 }
723         break;
724         case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
725                 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
726                 ctx->operation_succeeded = false;
727         break;
728         default:
729                 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
730                 ctx->operation_succeeded = false;
731         }
732 }
733 static bool write_command(
734         struct aux_engine *engine,
735         struct i2caux_transaction_request *request,
736         bool middle_of_transaction)
737 {
738         struct write_command_context ctx;
739
740         ctx.mot = middle_of_transaction;
741         ctx.buffer = request->payload.data;
742         ctx.current_write_length = request->payload.length;
743         ctx.timed_out_retry_aux = 0;
744         ctx.invalid_reply_retry_aux = 0;
745         ctx.defer_retry_aux = 0;
746         ctx.defer_retry_i2c = 0;
747         ctx.ack_m_retry = 0;
748         ctx.transaction_complete = false;
749         ctx.operation_succeeded = true;
750
751         if (request->payload.address_space ==
752                 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
753                 ctx.request.type = AUX_TRANSACTION_TYPE_DP;
754                 ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE;
755                 ctx.request.address = request->payload.address;
756         } else if (request->payload.address_space ==
757                 I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
758                 ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
759                 ctx.request.action = middle_of_transaction ?
760                         I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
761                         I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
762                 ctx.request.address = request->payload.address >> 1;
763         } else {
764                 /* in DAL2, there was no return in such case */
765                 BREAK_TO_DEBUGGER();
766                 return false;
767         }
768
769         ctx.request.delay = 0;
770
771         ctx.max_defer_retry =
772                 (engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ?
773                         engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER;
774
775         do {
776                 ctx.request.data = ctx.buffer;
777                 ctx.request.length = ctx.current_write_length;
778
779                 process_write_request(engine, &ctx);
780
781                 request->status = ctx.status;
782
783                 if (ctx.operation_succeeded && !ctx.transaction_complete)
784                         if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
785                                 msleep(engine->delay);
786         } while (ctx.operation_succeeded && !ctx.transaction_complete);
787
788         if (request->payload.address_space ==
789                 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
790                 DC_LOG_I2C_AUX("WRITE: addr:0x%x  value:0x%x Result:%d",
791                                 request->payload.address,
792                                 request->payload.data[0],
793                                 ctx.operation_succeeded);
794         }
795
796         return ctx.operation_succeeded;
797 }
798 static bool end_of_transaction_command(
799         struct aux_engine *engine,
800         struct i2caux_transaction_request *request)
801 {
802         struct i2caux_transaction_request dummy_request;
803         uint8_t dummy_data;
804
805         /* [tcheng] We only need to send the stop (read with MOT = 0)
806          * for I2C-over-Aux, not native AUX
807          */
808
809         if (request->payload.address_space !=
810                 I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C)
811                 return false;
812
813         dummy_request.operation = request->operation;
814         dummy_request.payload.address_space = request->payload.address_space;
815         dummy_request.payload.address = request->payload.address;
816
817         /*
818          * Add a dummy byte due to some receiver quirk
819          * where one byte is sent along with MOT = 0.
820          * Ideally this should be 0.
821          */
822
823         dummy_request.payload.length = 0;
824         dummy_request.payload.data = &dummy_data;
825
826         if (request->operation == I2CAUX_TRANSACTION_READ)
827                 return read_command(engine, &dummy_request, false);
828         else
829                 return write_command(engine, &dummy_request, false);
830
831         /* according Syed, it does not need now DoDummyMOT */
832 }
833 static bool submit_request(
834         struct aux_engine *engine,
835         struct i2caux_transaction_request *request,
836         bool middle_of_transaction)
837 {
838
839         bool result;
840         bool mot_used = true;
841
842         switch (request->operation) {
843         case I2CAUX_TRANSACTION_READ:
844                 result = read_command(engine, request, mot_used);
845         break;
846         case I2CAUX_TRANSACTION_WRITE:
847                 result = write_command(engine, request, mot_used);
848         break;
849         default:
850                 result = false;
851         }
852
853         /* [tcheng]
854          * need to send stop for the last transaction to free up the AUX
855          * if the above command fails, this would be the last transaction
856          */
857
858         if (!middle_of_transaction || !result)
859                 end_of_transaction_command(engine, request);
860
861         /* mask AUX interrupt */
862
863         return result;
864 }
865 enum i2caux_engine_type get_engine_type(
866                 const struct aux_engine *engine)
867 {
868         return I2CAUX_ENGINE_TYPE_AUX;
869 }
870
871 static bool acquire(
872         struct aux_engine *engine,
873         struct ddc *ddc)
874 {
875
876         enum gpio_result result;
877
878         if (engine->funcs->is_engine_available) {
879                 /*check whether SW could use the engine*/
880                 if (!engine->funcs->is_engine_available(engine))
881                         return false;
882         }
883
884         result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
885                 GPIO_DDC_CONFIG_TYPE_MODE_AUX);
886
887         if (result != GPIO_RESULT_OK)
888                 return false;
889
890         if (!engine->funcs->acquire_engine(engine)) {
891                 dal_ddc_close(ddc);
892                 return false;
893         }
894
895         engine->ddc = ddc;
896
897         return true;
898 }
899
900 static const struct aux_engine_funcs aux_engine_funcs = {
901         .acquire_engine = acquire_engine,
902         .submit_channel_request = submit_channel_request,
903         .process_channel_reply = process_channel_reply,
904         .read_channel_reply = read_channel_reply,
905         .get_channel_status = get_channel_status,
906         .is_engine_available = is_engine_available,
907         .release_engine = release_engine,
908         .destroy_engine = dce110_engine_destroy,
909         .submit_request = submit_request,
910         .get_engine_type = get_engine_type,
911         .acquire = acquire,
912 };
913
914 void dce110_engine_destroy(struct aux_engine **engine)
915 {
916
917         struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine);
918
919         kfree(engine110);
920         *engine = NULL;
921
922 }
923 struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110,
924                 struct dc_context *ctx,
925                 uint32_t inst,
926                 uint32_t timeout_period,
927                 const struct dce110_aux_registers *regs)
928 {
929         aux_engine110->base.ddc = NULL;
930         aux_engine110->base.ctx = ctx;
931         aux_engine110->base.delay = 0;
932         aux_engine110->base.max_defer_write_retry = 0;
933         aux_engine110->base.funcs = &aux_engine_funcs;
934         aux_engine110->base.inst = inst;
935         aux_engine110->timeout_period = timeout_period;
936         aux_engine110->regs = regs;
937
938         return &aux_engine110->base;
939 }
940