GNU Linux-libre 4.19.304-gnu1
[releases.git] / drivers / gpu / drm / amd / display / dc / i2caux / dce80 / i2c_hw_engine_dce80.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
28 /*
29  * Pre-requisites: headers required by header of this unit
30  */
31 #include "include/i2caux_interface.h"
32 #include "../engine.h"
33 #include "../i2c_engine.h"
34 #include "../i2c_hw_engine.h"
35 #include "../i2c_generic_hw_engine.h"
36 /*
37  * Header of this unit
38  */
39
40 #include "i2c_hw_engine_dce80.h"
41
42 /*
43  * Post-requisites: headers required by this unit
44  */
45
46 #include "dce/dce_8_0_d.h"
47 #include "dce/dce_8_0_sh_mask.h"
48 /*
49  * This unit
50  */
51
52 enum dc_i2c_status {
53         DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
54         DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW,
55         DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW
56 };
57
58 enum dc_i2c_arbitration {
59         DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
60         DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH
61 };
62
63 enum {
64         /* No timeout in HW
65          * (timeout implemented in SW by querying status) */
66         I2C_SETUP_TIME_LIMIT = 255,
67         I2C_HW_BUFFER_SIZE = 144
68 };
69
70 /*
71  * @brief
72  * Cast 'struct i2c_hw_engine *'
73  * to 'struct i2c_hw_engine_dce80 *'
74  */
75 #define FROM_I2C_HW_ENGINE(ptr) \
76         container_of((ptr), struct i2c_hw_engine_dce80, base)
77
78 /*
79  * @brief
80  * Cast pointer to 'struct i2c_engine *'
81  * to pointer to 'struct i2c_hw_engine_dce80 *'
82  */
83 #define FROM_I2C_ENGINE(ptr) \
84         FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
85
86 /*
87  * @brief
88  * Cast pointer to 'struct engine *'
89  * to 'pointer to struct i2c_hw_engine_dce80 *'
90  */
91 #define FROM_ENGINE(ptr) \
92         FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
93
94 static void disable_i2c_hw_engine(
95         struct i2c_hw_engine_dce80 *engine)
96 {
97         const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
98         uint32_t value = 0;
99
100         struct dc_context *ctx = NULL;
101
102         ctx = engine->base.base.base.ctx;
103
104         value = dm_read_reg(ctx, addr);
105
106         set_reg_field_value(
107                 value,
108                 0,
109                 DC_I2C_DDC1_SETUP,
110                 DC_I2C_DDC1_ENABLE);
111
112         dm_write_reg(ctx, addr, value);
113 }
114
115 static void release_engine(
116         struct engine *engine)
117 {
118         struct i2c_hw_engine_dce80 *hw_engine = FROM_ENGINE(engine);
119
120         struct i2c_engine *base = NULL;
121         bool safe_to_reset;
122         uint32_t value = 0;
123
124         base = &hw_engine->base.base;
125
126         /* Restore original HW engine speed */
127
128         base->funcs->set_speed(base, hw_engine->base.original_speed);
129
130         /* Release I2C */
131         {
132                 value = dm_read_reg(engine->ctx, mmDC_I2C_ARBITRATION);
133
134                 set_reg_field_value(
135                                 value,
136                                 1,
137                                 DC_I2C_ARBITRATION,
138                                 DC_I2C_SW_DONE_USING_I2C_REG);
139
140                 dm_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value);
141         }
142
143         /* Reset HW engine */
144         {
145                 uint32_t i2c_sw_status = 0;
146
147                 value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
148
149                 i2c_sw_status = get_reg_field_value(
150                                 value,
151                                 DC_I2C_SW_STATUS,
152                                 DC_I2C_SW_STATUS);
153                 /* if used by SW, safe to reset */
154                 safe_to_reset = (i2c_sw_status == 1);
155         }
156         {
157                 value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
158
159                 if (safe_to_reset)
160                         set_reg_field_value(
161                                 value,
162                                 1,
163                                 DC_I2C_CONTROL,
164                                 DC_I2C_SOFT_RESET);
165
166                 set_reg_field_value(
167                         value,
168                         1,
169                         DC_I2C_CONTROL,
170                         DC_I2C_SW_STATUS_RESET);
171
172                 dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
173         }
174
175         /* HW I2c engine - clock gating feature */
176         if (!hw_engine->engine_keep_power_up_count)
177                 disable_i2c_hw_engine(hw_engine);
178 }
179
180 static void destruct(
181         struct i2c_hw_engine_dce80 *engine)
182 {
183         dal_i2c_hw_engine_destruct(&engine->base);
184 }
185
186 static void destroy(
187         struct i2c_engine **i2c_engine)
188 {
189         struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(*i2c_engine);
190
191         destruct(engine);
192
193         kfree(engine);
194
195         *i2c_engine = NULL;
196 }
197
198 static bool setup_engine(
199         struct i2c_engine *i2c_engine)
200 {
201         uint32_t value = 0;
202         struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
203
204         /* Program pin select */
205         {
206                 const uint32_t addr = mmDC_I2C_CONTROL;
207
208                 value = dm_read_reg(i2c_engine->base.ctx, addr);
209
210                 set_reg_field_value(
211                         value,
212                         0,
213                         DC_I2C_CONTROL,
214                         DC_I2C_GO);
215
216                 set_reg_field_value(
217                         value,
218                         0,
219                         DC_I2C_CONTROL,
220                         DC_I2C_SOFT_RESET);
221
222                 set_reg_field_value(
223                         value,
224                         0,
225                         DC_I2C_CONTROL,
226                         DC_I2C_SEND_RESET);
227
228                 set_reg_field_value(
229                         value,
230                         0,
231                         DC_I2C_CONTROL,
232                         DC_I2C_SW_STATUS_RESET);
233
234                 set_reg_field_value(
235                         value,
236                         0,
237                         DC_I2C_CONTROL,
238                         DC_I2C_TRANSACTION_COUNT);
239
240                 set_reg_field_value(
241                         value,
242                         engine->engine_id,
243                         DC_I2C_CONTROL,
244                         DC_I2C_DDC_SELECT);
245
246                 dm_write_reg(i2c_engine->base.ctx, addr, value);
247         }
248
249         /* Program time limit */
250         {
251                 const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
252
253                 value = dm_read_reg(i2c_engine->base.ctx, addr);
254
255                 set_reg_field_value(
256                         value,
257                         I2C_SETUP_TIME_LIMIT,
258                         DC_I2C_DDC1_SETUP,
259                         DC_I2C_DDC1_TIME_LIMIT);
260
261                 set_reg_field_value(
262                         value,
263                         1,
264                         DC_I2C_DDC1_SETUP,
265                         DC_I2C_DDC1_ENABLE);
266
267                 dm_write_reg(i2c_engine->base.ctx, addr, value);
268         }
269
270         /* Program HW priority
271          * set to High - interrupt software I2C at any time
272          * Enable restart of SW I2C that was interrupted by HW
273          * disable queuing of software while I2C is in use by HW */
274         {
275                 value = dm_read_reg(i2c_engine->base.ctx,
276                                 mmDC_I2C_ARBITRATION);
277
278                 set_reg_field_value(
279                         value,
280                         0,
281                         DC_I2C_ARBITRATION,
282                         DC_I2C_NO_QUEUED_SW_GO);
283
284                 set_reg_field_value(
285                         value,
286                         DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
287                         DC_I2C_ARBITRATION,
288                         DC_I2C_SW_PRIORITY);
289
290                 dm_write_reg(i2c_engine->base.ctx,
291                                 mmDC_I2C_ARBITRATION, value);
292         }
293
294         return true;
295 }
296
297 static uint32_t get_speed(
298         const struct i2c_engine *i2c_engine)
299 {
300         const struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
301
302         const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
303
304         uint32_t pre_scale = 0;
305
306         uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
307
308         pre_scale = get_reg_field_value(
309                         value,
310                         DC_I2C_DDC1_SPEED,
311                         DC_I2C_DDC1_PRESCALE);
312
313         /* [anaumov] it seems following is unnecessary */
314         /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
315
316         return pre_scale ?
317                 engine->reference_frequency / pre_scale :
318                 engine->base.default_speed;
319 }
320
321 static void set_speed(
322         struct i2c_engine *i2c_engine,
323         uint32_t speed)
324 {
325         struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
326
327         if (speed) {
328                 const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
329
330                 uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
331
332                 set_reg_field_value(
333                         value,
334                         engine->reference_frequency / speed,
335                         DC_I2C_DDC1_SPEED,
336                         DC_I2C_DDC1_PRESCALE);
337
338                 set_reg_field_value(
339                         value,
340                         2,
341                         DC_I2C_DDC1_SPEED,
342                         DC_I2C_DDC1_THRESHOLD);
343
344                 dm_write_reg(i2c_engine->base.ctx, addr, value);
345         }
346 }
347
348 static inline void reset_hw_engine(struct engine *engine)
349 {
350         uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
351
352         set_reg_field_value(
353                 value,
354                 1,
355                 DC_I2C_CONTROL,
356                 DC_I2C_SOFT_RESET);
357
358         set_reg_field_value(
359                 value,
360                 1,
361                 DC_I2C_CONTROL,
362                 DC_I2C_SW_STATUS_RESET);
363
364         dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
365 }
366
367 static bool is_hw_busy(struct engine *engine)
368 {
369         uint32_t i2c_sw_status = 0;
370
371         uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
372
373         i2c_sw_status = get_reg_field_value(
374                         value,
375                         DC_I2C_SW_STATUS,
376                         DC_I2C_SW_STATUS);
377
378         if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
379                 return false;
380
381         reset_hw_engine(engine);
382
383         value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
384
385         i2c_sw_status = get_reg_field_value(
386                         value,
387                         DC_I2C_SW_STATUS,
388                         DC_I2C_SW_STATUS);
389
390         return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
391 }
392
393 /*
394  * @brief
395  * DC_GPIO_DDC MM register offsets
396  */
397 static const uint32_t transaction_addr[] = {
398         mmDC_I2C_TRANSACTION0,
399         mmDC_I2C_TRANSACTION1,
400         mmDC_I2C_TRANSACTION2,
401         mmDC_I2C_TRANSACTION3
402 };
403
404 static bool process_transaction(
405         struct i2c_hw_engine_dce80 *engine,
406         struct i2c_request_transaction_data *request)
407 {
408         uint32_t length = request->length;
409         uint8_t *buffer = request->data;
410
411         bool last_transaction = false;
412         uint32_t value = 0;
413
414         struct dc_context *ctx = NULL;
415
416         ctx = engine->base.base.base.ctx;
417
418         {
419                 const uint32_t addr =
420                         transaction_addr[engine->transaction_count];
421
422                 value = dm_read_reg(ctx, addr);
423
424                 set_reg_field_value(
425                         value,
426                         1,
427                         DC_I2C_TRANSACTION0,
428                         DC_I2C_STOP_ON_NACK0);
429
430                 set_reg_field_value(
431                         value,
432                         1,
433                         DC_I2C_TRANSACTION0,
434                         DC_I2C_START0);
435
436                 if ((engine->transaction_count == 3) ||
437                 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
438                 (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
439
440                         set_reg_field_value(
441                                 value,
442                                 1,
443                                 DC_I2C_TRANSACTION0,
444                                 DC_I2C_STOP0);
445
446                         last_transaction = true;
447                 } else
448                         set_reg_field_value(
449                                 value,
450                                 0,
451                                 DC_I2C_TRANSACTION0,
452                                 DC_I2C_STOP0);
453
454                 set_reg_field_value(
455                         value,
456                         (0 != (request->action &
457                                         I2CAUX_TRANSACTION_ACTION_I2C_READ)),
458                         DC_I2C_TRANSACTION0,
459                         DC_I2C_RW0);
460
461                 set_reg_field_value(
462                         value,
463                         length,
464                         DC_I2C_TRANSACTION0,
465                         DC_I2C_COUNT0);
466
467                 dm_write_reg(ctx, addr, value);
468         }
469
470         /* Write the I2C address and I2C data
471          * into the hardware circular buffer, one byte per entry.
472          * As an example, the 7-bit I2C slave address for CRT monitor
473          * for reading DDC/EDID information is 0b1010001.
474          * For an I2C send operation, the LSB must be programmed to 0;
475          * for I2C receive operation, the LSB must be programmed to 1. */
476
477         {
478                 value = 0;
479
480                 set_reg_field_value(
481                         value,
482                         false,
483                         DC_I2C_DATA,
484                         DC_I2C_DATA_RW);
485
486                 set_reg_field_value(
487                         value,
488                         request->address,
489                         DC_I2C_DATA,
490                         DC_I2C_DATA);
491
492                 if (engine->transaction_count == 0) {
493                         set_reg_field_value(
494                                 value,
495                                 0,
496                                 DC_I2C_DATA,
497                                 DC_I2C_INDEX);
498
499                         /*enable index write*/
500                         set_reg_field_value(
501                                 value,
502                                 1,
503                                 DC_I2C_DATA,
504                                 DC_I2C_INDEX_WRITE);
505                 }
506
507                 dm_write_reg(ctx, mmDC_I2C_DATA, value);
508
509                 if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
510
511                         set_reg_field_value(
512                                 value,
513                                 0,
514                                 DC_I2C_DATA,
515                                 DC_I2C_INDEX_WRITE);
516
517                         while (length) {
518
519                                 set_reg_field_value(
520                                         value,
521                                         *buffer++,
522                                         DC_I2C_DATA,
523                                         DC_I2C_DATA);
524
525                                 dm_write_reg(ctx, mmDC_I2C_DATA, value);
526                                 --length;
527                         }
528                 }
529         }
530
531         ++engine->transaction_count;
532         engine->buffer_used_bytes += length + 1;
533
534         return last_transaction;
535 }
536
537 static void execute_transaction(
538         struct i2c_hw_engine_dce80 *engine)
539 {
540         uint32_t value = 0;
541         struct dc_context *ctx = NULL;
542
543         ctx = engine->base.base.base.ctx;
544
545         {
546                 const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
547
548                 value = dm_read_reg(ctx, addr);
549
550                 set_reg_field_value(
551                         value,
552                         0,
553                         DC_I2C_DDC1_SETUP,
554                         DC_I2C_DDC1_DATA_DRIVE_EN);
555
556                 set_reg_field_value(
557                         value,
558                         0,
559                         DC_I2C_DDC1_SETUP,
560                         DC_I2C_DDC1_CLK_DRIVE_EN);
561
562                 set_reg_field_value(
563                         value,
564                         0,
565                         DC_I2C_DDC1_SETUP,
566                         DC_I2C_DDC1_DATA_DRIVE_SEL);
567
568                 set_reg_field_value(
569                         value,
570                         0,
571                         DC_I2C_DDC1_SETUP,
572                         DC_I2C_DDC1_INTRA_TRANSACTION_DELAY);
573
574                 set_reg_field_value(
575                         value,
576                         0,
577                         DC_I2C_DDC1_SETUP,
578                         DC_I2C_DDC1_INTRA_BYTE_DELAY);
579
580                 dm_write_reg(ctx, addr, value);
581         }
582
583         {
584                 const uint32_t addr = mmDC_I2C_CONTROL;
585
586                 value = dm_read_reg(ctx, addr);
587
588                 set_reg_field_value(
589                         value,
590                         0,
591                         DC_I2C_CONTROL,
592                         DC_I2C_SOFT_RESET);
593
594                 set_reg_field_value(
595                         value,
596                         0,
597                         DC_I2C_CONTROL,
598                         DC_I2C_SW_STATUS_RESET);
599
600                 set_reg_field_value(
601                         value,
602                         0,
603                         DC_I2C_CONTROL,
604                         DC_I2C_SEND_RESET);
605
606                 set_reg_field_value(
607                         value,
608                         0,
609                         DC_I2C_CONTROL,
610                         DC_I2C_GO);
611
612                 set_reg_field_value(
613                         value,
614                         engine->transaction_count - 1,
615                         DC_I2C_CONTROL,
616                         DC_I2C_TRANSACTION_COUNT);
617
618                 dm_write_reg(ctx, addr, value);
619         }
620
621         /* start I2C transfer */
622         {
623                 const uint32_t addr = mmDC_I2C_CONTROL;
624
625                 value   = dm_read_reg(ctx, addr);
626
627                 set_reg_field_value(
628                         value,
629                         1,
630                         DC_I2C_CONTROL,
631                         DC_I2C_GO);
632
633                 dm_write_reg(ctx, addr, value);
634         }
635
636         /* all transactions were executed and HW buffer became empty
637          * (even though it actually happens when status becomes DONE) */
638         engine->transaction_count = 0;
639         engine->buffer_used_bytes = 0;
640 }
641
642 static void submit_channel_request(
643         struct i2c_engine *engine,
644         struct i2c_request_transaction_data *request)
645 {
646         request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
647
648         if (!process_transaction(FROM_I2C_ENGINE(engine), request))
649                 return;
650
651         if (is_hw_busy(&engine->base)) {
652                 request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
653                 return;
654         }
655
656         execute_transaction(FROM_I2C_ENGINE(engine));
657 }
658
659 static void process_channel_reply(
660         struct i2c_engine *engine,
661         struct i2c_reply_transaction_data *reply)
662 {
663         uint32_t length = reply->length;
664         uint8_t *buffer = reply->data;
665
666         uint32_t value = 0;
667
668         /*set index*/
669         set_reg_field_value(
670                 value,
671                 length - 1,
672                 DC_I2C_DATA,
673                 DC_I2C_INDEX);
674
675         set_reg_field_value(
676                 value,
677                 1,
678                 DC_I2C_DATA,
679                 DC_I2C_DATA_RW);
680
681         set_reg_field_value(
682                 value,
683                 1,
684                 DC_I2C_DATA,
685                 DC_I2C_INDEX_WRITE);
686
687         dm_write_reg(engine->base.ctx, mmDC_I2C_DATA, value);
688
689         while (length) {
690                 /* after reading the status,
691                  * if the I2C operation executed successfully
692                  * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
693                  * should read data bytes from I2C circular data buffer */
694
695                 value = dm_read_reg(engine->base.ctx, mmDC_I2C_DATA);
696
697                 *buffer++ = get_reg_field_value(
698                                 value,
699                                 DC_I2C_DATA,
700                                 DC_I2C_DATA);
701
702                 --length;
703         }
704 }
705
706 static enum i2c_channel_operation_result get_channel_status(
707         struct i2c_engine *engine,
708         uint8_t *returned_bytes)
709 {
710         uint32_t i2c_sw_status = 0;
711         uint32_t value = dm_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS);
712
713         i2c_sw_status = get_reg_field_value(
714                         value,
715                         DC_I2C_SW_STATUS,
716                         DC_I2C_SW_STATUS);
717
718         if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
719                 return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
720         else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK)
721                 return I2C_CHANNEL_OPERATION_NO_RESPONSE;
722         else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK)
723                 return I2C_CHANNEL_OPERATION_TIMEOUT;
724         else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK)
725                 return I2C_CHANNEL_OPERATION_FAILED;
726         else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK)
727                 return I2C_CHANNEL_OPERATION_SUCCEEDED;
728
729         /*
730          * this is the case when HW used for communication, I2C_SW_STATUS
731          * could be zero
732          */
733         return I2C_CHANNEL_OPERATION_SUCCEEDED;
734 }
735
736 static uint32_t get_hw_buffer_available_size(
737         const struct i2c_hw_engine *engine)
738 {
739         return I2C_HW_BUFFER_SIZE -
740                 FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes;
741 }
742
743 static uint32_t get_transaction_timeout(
744         const struct i2c_hw_engine *engine,
745         uint32_t length)
746 {
747         uint32_t speed = engine->base.funcs->get_speed(&engine->base);
748
749         uint32_t period_timeout;
750         uint32_t num_of_clock_stretches;
751
752         if (!speed)
753                 return 0;
754
755         period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
756
757         num_of_clock_stretches = 1 + (length << 3) + 1;
758         num_of_clock_stretches +=
759                 (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) +
760                 (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1);
761
762         return period_timeout * num_of_clock_stretches;
763 }
764
765 /*
766  * @brief
767  * DC_I2C_DDC1_SETUP MM register offsets
768  *
769  * @note
770  * The indices of this offset array are DDC engine IDs
771  */
772 static const int32_t ddc_setup_offset[] = {
773
774         mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */
775         mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */
776         mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */
777         mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */
778         mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */
779         mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */
780         mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */
781 };
782
783 /*
784  * @brief
785  * DC_I2C_DDC1_SPEED MM register offsets
786  *
787  * @note
788  * The indices of this offset array are DDC engine IDs
789  */
790 static const int32_t ddc_speed_offset[] = {
791         mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */
792         mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */
793         mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */
794         mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */
795         mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */
796         mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */
797         mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */
798 };
799
800 static const struct i2c_engine_funcs i2c_engine_funcs = {
801         .destroy = destroy,
802         .get_speed = get_speed,
803         .set_speed = set_speed,
804         .setup_engine = setup_engine,
805         .submit_channel_request = submit_channel_request,
806         .process_channel_reply = process_channel_reply,
807         .get_channel_status = get_channel_status,
808         .acquire_engine = dal_i2c_hw_engine_acquire_engine,
809 };
810
811 static const struct engine_funcs engine_funcs = {
812         .release_engine = release_engine,
813         .get_engine_type = dal_i2c_hw_engine_get_engine_type,
814         .acquire = dal_i2c_engine_acquire,
815         .submit_request = dal_i2c_hw_engine_submit_request,
816 };
817
818 static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = {
819         .get_hw_buffer_available_size =
820                 get_hw_buffer_available_size,
821         .get_transaction_timeout =
822                 get_transaction_timeout,
823         .wait_on_operation_result =
824                 dal_i2c_hw_engine_wait_on_operation_result,
825 };
826
827 static void construct(
828         struct i2c_hw_engine_dce80 *engine,
829         const struct i2c_hw_engine_dce80_create_arg *arg)
830 {
831         dal_i2c_hw_engine_construct(&engine->base, arg->ctx);
832
833         engine->base.base.base.funcs = &engine_funcs;
834         engine->base.base.funcs = &i2c_engine_funcs;
835         engine->base.funcs = &i2c_hw_engine_funcs;
836         engine->base.default_speed = arg->default_speed;
837         engine->addr.DC_I2C_DDCX_SETUP =
838                 mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id];
839         engine->addr.DC_I2C_DDCX_SPEED =
840                 mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id];
841
842         engine->engine_id = arg->engine_id;
843         engine->reference_frequency = arg->reference_frequency;
844         engine->buffer_used_bytes = 0;
845         engine->transaction_count = 0;
846         engine->engine_keep_power_up_count = 1;
847 }
848
849 struct i2c_engine *dal_i2c_hw_engine_dce80_create(
850         const struct i2c_hw_engine_dce80_create_arg *arg)
851 {
852         struct i2c_hw_engine_dce80 *engine;
853
854         if (!arg) {
855                 BREAK_TO_DEBUGGER();
856                 return NULL;
857         }
858
859         if ((arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) ||
860             (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) ||
861             !arg->reference_frequency) {
862                 BREAK_TO_DEBUGGER();
863                 return NULL;
864         }
865
866         engine = kzalloc(sizeof(struct i2c_hw_engine_dce80), GFP_KERNEL);
867
868         if (!engine) {
869                 BREAK_TO_DEBUGGER();
870                 return NULL;
871         }
872
873         construct(engine, arg);
874         return &engine->base.base;
875 }