Merge tag 'v4.20-rc7' of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds...
[linux-2.6-microblaze.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         /* set the delay and the number of bytes to write */
193
194         /* The length include
195          * the 4 bit header and the 20 bit address
196          * (that is 3 byte).
197          * If the requested length is non zero this means
198          * an addition byte specifying the length is required.
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         /* program action and address and payload data (if 'is_write') */
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                 /* Load the HW buffer with the Data to be sent.
230                  * This is relevant for write operation.
231                  * For read, the data recived data will be
232                  * processed in process_channel_reply().
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
250 static 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         /* In case HPD is LOW, exit AUX transaction */
262         if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
263                 return -1;
264
265         /* Need at least the status byte */
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) { /* ACK */
279                 uint32_t i = 0;
280
281                 /* First byte was already used to get the command status */
282                 --bytes_replied;
283
284                 /* Do not overflow buffer */
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
302 static 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         /* in case HPD is LOW, exit AUX transaction */
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                 /* Need to handle an error case...
321                  * Hopefully, upper layer function won't call this function if
322                  * the number of bytes in the reply was 0, because there was
323                  * surely an error that was asserted that should have been
324                  * handled for hot plug case, this could happens
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: /* ACK */
335                         reply->status = AUX_TRANSACTION_REPLY_AUX_ACK;
336                 break;
337                 case 1: /* NACK */
338                         reply->status = AUX_TRANSACTION_REPLY_AUX_NACK;
339                 break;
340                 case 2: /* DEFER */
341                         reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER;
342                 break;
343                 case 4: /* AUX ACK / I2C NACK */
344                         reply->status = AUX_TRANSACTION_REPLY_I2C_NACK;
345                 break;
346                 case 8: /* AUX ACK / I2C DEFER */
347                         reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER;
348                 break;
349                 default:
350                         reply->status = AUX_TRANSACTION_REPLY_INVALID;
351                 }
352         }
353 }
354
355 static 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                 /*caller pass NULL pointer*/
365                 ASSERT_CRITICAL(false);
366                 return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
367         }
368         *returned_bytes = 0;
369
370         /* poll to make sure that SW_DONE is asserted */
371         value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
372                                 10, aux110->timeout_period/10);
373
374         /* in case HPD is LOW, exit AUX transaction */
375         if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
376                 return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
377
378         /* Note that the following bits are set in 'status.bits'
379          * during CTS 4.2.1.2 (FW 3.3.1):
380          * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
381          * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
382          *
383          * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
384          * HW debugging bit and should be ignored.
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                 /*time_elapsed >= aux_engine->timeout_period
411                  *  AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point
412                  */
413                 ASSERT_CRITICAL(false);
414                 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
415         }
416 }
417 static 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 }
480 static 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                         /* DP 1.2a, table 2-58:
526                          * "S3: AUX Request CMD PENDING:
527                          * retry 3 times, with 400usec wait on each"
528                          * The HW timeout is set to 550usec,
529                          * so we should not wait here
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 }
542 static 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                 /* in DAL2, there was no return in such case */
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
606 static 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 }
674 static 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                         /* DP 1.2a, table 2-58:
714                          * "S3: AUX Request CMD PENDING:
715                          * retry 3 times, with 400usec wait on each"
716                          * The HW timeout is set to 550usec,
717                          * so we should not wait here
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 }
730 static 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                 /* in DAL2, there was no return in such case */
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 }
795 static 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         /* [tcheng] We only need to send the stop (read with MOT = 0)
803          * for I2C-over-Aux, not native AUX
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          * Add a dummy byte due to some receiver quirk
816          * where one byte is sent along with MOT = 0.
817          * Ideally this should be 0.
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         /* according Syed, it does not need now DoDummyMOT */
829 }
830 static 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         /* [tcheng]
851          * need to send stop for the last transaction to free up the AUX
852          * if the above command fails, this would be the last transaction
853          */
854
855         if (!middle_of_transaction || !result)
856                 end_of_transaction_command(engine, request);
857
858         /* mask AUX interrupt */
859
860         return result;
861 }
862 enum i2caux_engine_type get_engine_type(
863                 const struct aux_engine *engine)
864 {
865         return I2CAUX_ENGINE_TYPE_AUX;
866 }
867
868 static 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                 /*check whether SW could use the engine*/
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
897 static 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
911 void 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 }
920 struct 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