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