Loading...
1/*
2 * Copyright 2018 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 "dce_i2c.h"
27#include "dce_i2c_sw.h"
28#include "include/gpio_service_interface.h"
29#define SCL false
30#define SDA true
31
32void dce_i2c_sw_construct(
33 struct dce_i2c_sw *dce_i2c_sw,
34 struct dc_context *ctx)
35{
36 dce_i2c_sw->ctx = ctx;
37}
38
39static inline bool read_bit_from_ddc(
40 struct ddc *ddc,
41 bool data_nor_clock)
42{
43 uint32_t value = 0;
44
45 if (data_nor_clock)
46 dal_gpio_get_value(ddc->pin_data, &value);
47 else
48 dal_gpio_get_value(ddc->pin_clock, &value);
49
50 return (value != 0);
51}
52
53static inline void write_bit_to_ddc(
54 struct ddc *ddc,
55 bool data_nor_clock,
56 bool bit)
57{
58 uint32_t value = bit ? 1 : 0;
59
60 if (data_nor_clock)
61 dal_gpio_set_value(ddc->pin_data, value);
62 else
63 dal_gpio_set_value(ddc->pin_clock, value);
64}
65
66static void release_engine_dce_sw(
67 struct resource_pool *pool,
68 struct dce_i2c_sw *dce_i2c_sw)
69{
70 dal_ddc_close(dce_i2c_sw->ddc);
71 dce_i2c_sw->ddc = NULL;
72}
73
74static bool wait_for_scl_high_sw(
75 struct dc_context *ctx,
76 struct ddc *ddc,
77 uint16_t clock_delay_div_4)
78{
79 uint32_t scl_retry = 0;
80 uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
81
82 udelay(clock_delay_div_4);
83
84 do {
85 if (read_bit_from_ddc(ddc, SCL))
86 return true;
87
88 udelay(clock_delay_div_4);
89
90 ++scl_retry;
91 } while (scl_retry <= scl_retry_max);
92
93 return false;
94}
95static bool write_byte_sw(
96 struct dc_context *ctx,
97 struct ddc *ddc_handle,
98 uint16_t clock_delay_div_4,
99 uint8_t byte)
100{
101 int32_t shift = 7;
102 bool ack;
103
104 /* bits are transmitted serially, starting from MSB */
105
106 do {
107 udelay(clock_delay_div_4);
108
109 write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
110
111 udelay(clock_delay_div_4);
112
113 write_bit_to_ddc(ddc_handle, SCL, true);
114
115 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
116 return false;
117
118 write_bit_to_ddc(ddc_handle, SCL, false);
119
120 --shift;
121 } while (shift >= 0);
122
123 /* The display sends ACK by preventing the SDA from going high
124 * after the SCL pulse we use to send our last data bit.
125 * If the SDA goes high after that bit, it's a NACK
126 */
127
128 udelay(clock_delay_div_4);
129
130 write_bit_to_ddc(ddc_handle, SDA, true);
131
132 udelay(clock_delay_div_4);
133
134 write_bit_to_ddc(ddc_handle, SCL, true);
135
136 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
137 return false;
138
139 /* read ACK bit */
140
141 ack = !read_bit_from_ddc(ddc_handle, SDA);
142
143 udelay(clock_delay_div_4 << 1);
144
145 write_bit_to_ddc(ddc_handle, SCL, false);
146
147 udelay(clock_delay_div_4 << 1);
148
149 return ack;
150}
151
152static bool read_byte_sw(
153 struct dc_context *ctx,
154 struct ddc *ddc_handle,
155 uint16_t clock_delay_div_4,
156 uint8_t *byte,
157 bool more)
158{
159 int32_t shift = 7;
160
161 uint8_t data = 0;
162
163 /* The data bits are read from MSB to LSB;
164 * bit is read while SCL is high
165 */
166
167 do {
168 write_bit_to_ddc(ddc_handle, SCL, true);
169
170 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
171 return false;
172
173 if (read_bit_from_ddc(ddc_handle, SDA))
174 data |= (1 << shift);
175
176 write_bit_to_ddc(ddc_handle, SCL, false);
177
178 udelay(clock_delay_div_4 << 1);
179
180 --shift;
181 } while (shift >= 0);
182
183 /* read only whole byte */
184
185 *byte = data;
186
187 udelay(clock_delay_div_4);
188
189 /* send the acknowledge bit:
190 * SDA low means ACK, SDA high means NACK
191 */
192
193 write_bit_to_ddc(ddc_handle, SDA, !more);
194
195 udelay(clock_delay_div_4);
196
197 write_bit_to_ddc(ddc_handle, SCL, true);
198
199 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
200 return false;
201
202 write_bit_to_ddc(ddc_handle, SCL, false);
203
204 udelay(clock_delay_div_4);
205
206 write_bit_to_ddc(ddc_handle, SDA, true);
207
208 udelay(clock_delay_div_4);
209
210 return true;
211}
212static bool stop_sync_sw(
213 struct dc_context *ctx,
214 struct ddc *ddc_handle,
215 uint16_t clock_delay_div_4)
216{
217 uint32_t retry = 0;
218
219 /* The I2C communications stop signal is:
220 * the SDA going high from low, while the SCL is high.
221 */
222
223 write_bit_to_ddc(ddc_handle, SCL, false);
224
225 udelay(clock_delay_div_4);
226
227 write_bit_to_ddc(ddc_handle, SDA, false);
228
229 udelay(clock_delay_div_4);
230
231 write_bit_to_ddc(ddc_handle, SCL, true);
232
233 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
234 return false;
235
236 write_bit_to_ddc(ddc_handle, SDA, true);
237
238 do {
239 udelay(clock_delay_div_4);
240
241 if (read_bit_from_ddc(ddc_handle, SDA))
242 return true;
243
244 ++retry;
245 } while (retry <= 2);
246
247 return false;
248}
249static bool i2c_write_sw(
250 struct dc_context *ctx,
251 struct ddc *ddc_handle,
252 uint16_t clock_delay_div_4,
253 uint8_t address,
254 uint32_t length,
255 const uint8_t *data)
256{
257 uint32_t i = 0;
258
259 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
260 return false;
261
262 while (i < length) {
263 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, data[i]))
264 return false;
265 ++i;
266 }
267
268 return true;
269}
270
271static bool i2c_read_sw(
272 struct dc_context *ctx,
273 struct ddc *ddc_handle,
274 uint16_t clock_delay_div_4,
275 uint8_t address,
276 uint32_t length,
277 uint8_t *data)
278{
279 uint32_t i = 0;
280
281 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
282 return false;
283
284 while (i < length) {
285 if (!read_byte_sw(ctx, ddc_handle, clock_delay_div_4, data + i,
286 i < length - 1))
287 return false;
288 ++i;
289 }
290
291 return true;
292}
293
294
295
296static bool start_sync_sw(
297 struct dc_context *ctx,
298 struct ddc *ddc_handle,
299 uint16_t clock_delay_div_4)
300{
301 uint32_t retry = 0;
302
303 /* The I2C communications start signal is:
304 * the SDA going low from high, while the SCL is high.
305 */
306
307 write_bit_to_ddc(ddc_handle, SCL, true);
308
309 udelay(clock_delay_div_4);
310
311 do {
312 write_bit_to_ddc(ddc_handle, SDA, true);
313
314 if (!read_bit_from_ddc(ddc_handle, SDA)) {
315 ++retry;
316 continue;
317 }
318
319 udelay(clock_delay_div_4);
320
321 write_bit_to_ddc(ddc_handle, SCL, true);
322
323 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
324 break;
325
326 write_bit_to_ddc(ddc_handle, SDA, false);
327
328 udelay(clock_delay_div_4);
329
330 write_bit_to_ddc(ddc_handle, SCL, false);
331
332 udelay(clock_delay_div_4);
333
334 return true;
335 } while (retry <= I2C_SW_RETRIES);
336
337 return false;
338}
339
340static void dce_i2c_sw_engine_set_speed(
341 struct dce_i2c_sw *engine,
342 uint32_t speed)
343{
344 ASSERT(speed);
345
346 engine->speed = speed ? speed : DCE_I2C_DEFAULT_I2C_SW_SPEED;
347
348 engine->clock_delay = 1000 / engine->speed;
349
350 if (engine->clock_delay < 12)
351 engine->clock_delay = 12;
352}
353
354static bool dce_i2c_sw_engine_acquire_engine(
355 struct dce_i2c_sw *engine,
356 struct ddc *ddc)
357{
358 enum gpio_result result;
359
360 result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
361 GPIO_DDC_CONFIG_TYPE_MODE_I2C);
362
363 if (result != GPIO_RESULT_OK)
364 return false;
365
366 engine->ddc = ddc;
367
368 return true;
369}
370bool dce_i2c_engine_acquire_sw(
371 struct dce_i2c_sw *dce_i2c_sw,
372 struct ddc *ddc_handle)
373{
374 uint32_t counter = 0;
375 bool result;
376
377 do {
378
379 result = dce_i2c_sw_engine_acquire_engine(
380 dce_i2c_sw, ddc_handle);
381
382 if (result)
383 break;
384
385 /* i2c_engine is busy by VBios, lets wait and retry */
386
387 udelay(10);
388
389 ++counter;
390 } while (counter < 2);
391
392 return result;
393}
394
395
396
397
398static void dce_i2c_sw_engine_submit_channel_request(
399 struct dce_i2c_sw *engine,
400 struct i2c_request_transaction_data *req)
401{
402 struct ddc *ddc = engine->ddc;
403 uint16_t clock_delay_div_4 = engine->clock_delay >> 2;
404
405 /* send sync (start / repeated start) */
406
407 bool result = start_sync_sw(engine->ctx, ddc, clock_delay_div_4);
408
409 /* process payload */
410
411 if (result) {
412 switch (req->action) {
413 case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE:
414 case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT:
415 result = i2c_write_sw(engine->ctx, ddc, clock_delay_div_4,
416 req->address, req->length, req->data);
417 break;
418 case DCE_I2C_TRANSACTION_ACTION_I2C_READ:
419 case DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT:
420 result = i2c_read_sw(engine->ctx, ddc, clock_delay_div_4,
421 req->address, req->length, req->data);
422 break;
423 default:
424 result = false;
425 break;
426 }
427 }
428
429 /* send stop if not 'mot' or operation failed */
430
431 if (!result ||
432 (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
433 (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_READ))
434 if (!stop_sync_sw(engine->ctx, ddc, clock_delay_div_4))
435 result = false;
436
437 req->status = result ?
438 I2C_CHANNEL_OPERATION_SUCCEEDED :
439 I2C_CHANNEL_OPERATION_FAILED;
440}
441
442static bool dce_i2c_sw_engine_submit_payload(
443 struct dce_i2c_sw *engine,
444 struct i2c_payload *payload,
445 bool middle_of_transaction)
446{
447 struct i2c_request_transaction_data request;
448
449 if (!payload->write)
450 request.action = middle_of_transaction ?
451 DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
452 DCE_I2C_TRANSACTION_ACTION_I2C_READ;
453 else
454 request.action = middle_of_transaction ?
455 DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
456 DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
457
458 request.address = (uint8_t) ((payload->address << 1) | !payload->write);
459 request.length = payload->length;
460 request.data = payload->data;
461
462 dce_i2c_sw_engine_submit_channel_request(engine, &request);
463
464 if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
465 (request.status == I2C_CHANNEL_OPERATION_FAILED))
466 return false;
467
468 return true;
469}
470bool dce_i2c_submit_command_sw(
471 struct resource_pool *pool,
472 struct ddc *ddc,
473 struct i2c_command *cmd,
474 struct dce_i2c_sw *dce_i2c_sw)
475{
476 uint8_t index_of_payload = 0;
477 bool result;
478
479 dce_i2c_sw_engine_set_speed(dce_i2c_sw, cmd->speed);
480
481 result = true;
482
483 while (index_of_payload < cmd->number_of_payloads) {
484 bool mot = (index_of_payload != cmd->number_of_payloads - 1);
485
486 struct i2c_payload *payload = cmd->payloads + index_of_payload;
487
488 if (!dce_i2c_sw_engine_submit_payload(
489 dce_i2c_sw, payload, mot)) {
490 result = false;
491 break;
492 }
493
494 ++index_of_payload;
495 }
496
497 release_engine_dce_sw(pool, dce_i2c_sw);
498
499 return result;
500}
1/*
2 * Copyright 2018 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 <linux/delay.h>
27
28#include "dce_i2c.h"
29#include "dce_i2c_sw.h"
30#include "include/gpio_service_interface.h"
31#define SCL false
32#define SDA true
33
34void dce_i2c_sw_construct(
35 struct dce_i2c_sw *dce_i2c_sw,
36 struct dc_context *ctx)
37{
38 dce_i2c_sw->ctx = ctx;
39}
40
41static inline bool read_bit_from_ddc(
42 struct ddc *ddc,
43 bool data_nor_clock)
44{
45 uint32_t value = 0;
46
47 if (data_nor_clock)
48 dal_gpio_get_value(ddc->pin_data, &value);
49 else
50 dal_gpio_get_value(ddc->pin_clock, &value);
51
52 return (value != 0);
53}
54
55static inline void write_bit_to_ddc(
56 struct ddc *ddc,
57 bool data_nor_clock,
58 bool bit)
59{
60 uint32_t value = bit ? 1 : 0;
61
62 if (data_nor_clock)
63 dal_gpio_set_value(ddc->pin_data, value);
64 else
65 dal_gpio_set_value(ddc->pin_clock, value);
66}
67
68static void release_engine_dce_sw(
69 struct resource_pool *pool,
70 struct dce_i2c_sw *dce_i2c_sw)
71{
72 dal_ddc_close(dce_i2c_sw->ddc);
73 dce_i2c_sw->ddc = NULL;
74}
75
76static bool get_hw_supported_ddc_line(
77 struct ddc *ddc,
78 enum gpio_ddc_line *line)
79{
80 enum gpio_ddc_line line_found;
81
82 *line = GPIO_DDC_LINE_UNKNOWN;
83
84 if (!ddc) {
85 BREAK_TO_DEBUGGER();
86 return false;
87 }
88
89 if (!ddc->hw_info.hw_supported)
90 return false;
91
92 line_found = dal_ddc_get_line(ddc);
93
94 if (line_found >= GPIO_DDC_LINE_COUNT)
95 return false;
96
97 *line = line_found;
98
99 return true;
100}
101static bool wait_for_scl_high_sw(
102 struct dc_context *ctx,
103 struct ddc *ddc,
104 uint16_t clock_delay_div_4)
105{
106 uint32_t scl_retry = 0;
107 uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
108
109 udelay(clock_delay_div_4);
110
111 do {
112 if (read_bit_from_ddc(ddc, SCL))
113 return true;
114
115 udelay(clock_delay_div_4);
116
117 ++scl_retry;
118 } while (scl_retry <= scl_retry_max);
119
120 return false;
121}
122static bool write_byte_sw(
123 struct dc_context *ctx,
124 struct ddc *ddc_handle,
125 uint16_t clock_delay_div_4,
126 uint8_t byte)
127{
128 int32_t shift = 7;
129 bool ack;
130
131 /* bits are transmitted serially, starting from MSB */
132
133 do {
134 udelay(clock_delay_div_4);
135
136 write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
137
138 udelay(clock_delay_div_4);
139
140 write_bit_to_ddc(ddc_handle, SCL, true);
141
142 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
143 return false;
144
145 write_bit_to_ddc(ddc_handle, SCL, false);
146
147 --shift;
148 } while (shift >= 0);
149
150 /* The display sends ACK by preventing the SDA from going high
151 * after the SCL pulse we use to send our last data bit.
152 * If the SDA goes high after that bit, it's a NACK
153 */
154
155 udelay(clock_delay_div_4);
156
157 write_bit_to_ddc(ddc_handle, SDA, true);
158
159 udelay(clock_delay_div_4);
160
161 write_bit_to_ddc(ddc_handle, SCL, true);
162
163 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
164 return false;
165
166 /* read ACK bit */
167
168 ack = !read_bit_from_ddc(ddc_handle, SDA);
169
170 udelay(clock_delay_div_4 << 1);
171
172 write_bit_to_ddc(ddc_handle, SCL, false);
173
174 udelay(clock_delay_div_4 << 1);
175
176 return ack;
177}
178
179static bool read_byte_sw(
180 struct dc_context *ctx,
181 struct ddc *ddc_handle,
182 uint16_t clock_delay_div_4,
183 uint8_t *byte,
184 bool more)
185{
186 int32_t shift = 7;
187
188 uint8_t data = 0;
189
190 /* The data bits are read from MSB to LSB;
191 * bit is read while SCL is high
192 */
193
194 do {
195 write_bit_to_ddc(ddc_handle, SCL, true);
196
197 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
198 return false;
199
200 if (read_bit_from_ddc(ddc_handle, SDA))
201 data |= (1 << shift);
202
203 write_bit_to_ddc(ddc_handle, SCL, false);
204
205 udelay(clock_delay_div_4 << 1);
206
207 --shift;
208 } while (shift >= 0);
209
210 /* read only whole byte */
211
212 *byte = data;
213
214 udelay(clock_delay_div_4);
215
216 /* send the acknowledge bit:
217 * SDA low means ACK, SDA high means NACK
218 */
219
220 write_bit_to_ddc(ddc_handle, SDA, !more);
221
222 udelay(clock_delay_div_4);
223
224 write_bit_to_ddc(ddc_handle, SCL, true);
225
226 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
227 return false;
228
229 write_bit_to_ddc(ddc_handle, SCL, false);
230
231 udelay(clock_delay_div_4);
232
233 write_bit_to_ddc(ddc_handle, SDA, true);
234
235 udelay(clock_delay_div_4);
236
237 return true;
238}
239static bool stop_sync_sw(
240 struct dc_context *ctx,
241 struct ddc *ddc_handle,
242 uint16_t clock_delay_div_4)
243{
244 uint32_t retry = 0;
245
246 /* The I2C communications stop signal is:
247 * the SDA going high from low, while the SCL is high.
248 */
249
250 write_bit_to_ddc(ddc_handle, SCL, false);
251
252 udelay(clock_delay_div_4);
253
254 write_bit_to_ddc(ddc_handle, SDA, false);
255
256 udelay(clock_delay_div_4);
257
258 write_bit_to_ddc(ddc_handle, SCL, true);
259
260 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
261 return false;
262
263 write_bit_to_ddc(ddc_handle, SDA, true);
264
265 do {
266 udelay(clock_delay_div_4);
267
268 if (read_bit_from_ddc(ddc_handle, SDA))
269 return true;
270
271 ++retry;
272 } while (retry <= 2);
273
274 return false;
275}
276static bool i2c_write_sw(
277 struct dc_context *ctx,
278 struct ddc *ddc_handle,
279 uint16_t clock_delay_div_4,
280 uint8_t address,
281 uint32_t length,
282 const uint8_t *data)
283{
284 uint32_t i = 0;
285
286 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
287 return false;
288
289 while (i < length) {
290 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, data[i]))
291 return false;
292 ++i;
293 }
294
295 return true;
296}
297
298static bool i2c_read_sw(
299 struct dc_context *ctx,
300 struct ddc *ddc_handle,
301 uint16_t clock_delay_div_4,
302 uint8_t address,
303 uint32_t length,
304 uint8_t *data)
305{
306 uint32_t i = 0;
307
308 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
309 return false;
310
311 while (i < length) {
312 if (!read_byte_sw(ctx, ddc_handle, clock_delay_div_4, data + i,
313 i < length - 1))
314 return false;
315 ++i;
316 }
317
318 return true;
319}
320
321
322
323static bool start_sync_sw(
324 struct dc_context *ctx,
325 struct ddc *ddc_handle,
326 uint16_t clock_delay_div_4)
327{
328 uint32_t retry = 0;
329
330 /* The I2C communications start signal is:
331 * the SDA going low from high, while the SCL is high.
332 */
333
334 write_bit_to_ddc(ddc_handle, SCL, true);
335
336 udelay(clock_delay_div_4);
337
338 do {
339 write_bit_to_ddc(ddc_handle, SDA, true);
340
341 if (!read_bit_from_ddc(ddc_handle, SDA)) {
342 ++retry;
343 continue;
344 }
345
346 udelay(clock_delay_div_4);
347
348 write_bit_to_ddc(ddc_handle, SCL, true);
349
350 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
351 break;
352
353 write_bit_to_ddc(ddc_handle, SDA, false);
354
355 udelay(clock_delay_div_4);
356
357 write_bit_to_ddc(ddc_handle, SCL, false);
358
359 udelay(clock_delay_div_4);
360
361 return true;
362 } while (retry <= I2C_SW_RETRIES);
363
364 return false;
365}
366
367void dce_i2c_sw_engine_set_speed(
368 struct dce_i2c_sw *engine,
369 uint32_t speed)
370{
371 ASSERT(speed);
372
373 engine->speed = speed ? speed : DCE_I2C_DEFAULT_I2C_SW_SPEED;
374
375 engine->clock_delay = 1000 / engine->speed;
376
377 if (engine->clock_delay < 12)
378 engine->clock_delay = 12;
379}
380
381bool dce_i2c_sw_engine_acquire_engine(
382 struct dce_i2c_sw *engine,
383 struct ddc *ddc)
384{
385 enum gpio_result result;
386
387 result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
388 GPIO_DDC_CONFIG_TYPE_MODE_I2C);
389
390 if (result != GPIO_RESULT_OK)
391 return false;
392
393 engine->ddc = ddc;
394
395 return true;
396}
397bool dce_i2c_engine_acquire_sw(
398 struct dce_i2c_sw *dce_i2c_sw,
399 struct ddc *ddc_handle)
400{
401 uint32_t counter = 0;
402 bool result;
403
404 do {
405
406 result = dce_i2c_sw_engine_acquire_engine(
407 dce_i2c_sw, ddc_handle);
408
409 if (result)
410 break;
411
412 /* i2c_engine is busy by VBios, lets wait and retry */
413
414 udelay(10);
415
416 ++counter;
417 } while (counter < 2);
418
419 return result;
420}
421
422
423
424
425void dce_i2c_sw_engine_submit_channel_request(
426 struct dce_i2c_sw *engine,
427 struct i2c_request_transaction_data *req)
428{
429 struct ddc *ddc = engine->ddc;
430 uint16_t clock_delay_div_4 = engine->clock_delay >> 2;
431
432 /* send sync (start / repeated start) */
433
434 bool result = start_sync_sw(engine->ctx, ddc, clock_delay_div_4);
435
436 /* process payload */
437
438 if (result) {
439 switch (req->action) {
440 case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE:
441 case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT:
442 result = i2c_write_sw(engine->ctx, ddc, clock_delay_div_4,
443 req->address, req->length, req->data);
444 break;
445 case DCE_I2C_TRANSACTION_ACTION_I2C_READ:
446 case DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT:
447 result = i2c_read_sw(engine->ctx, ddc, clock_delay_div_4,
448 req->address, req->length, req->data);
449 break;
450 default:
451 result = false;
452 break;
453 }
454 }
455
456 /* send stop if not 'mot' or operation failed */
457
458 if (!result ||
459 (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
460 (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_READ))
461 if (!stop_sync_sw(engine->ctx, ddc, clock_delay_div_4))
462 result = false;
463
464 req->status = result ?
465 I2C_CHANNEL_OPERATION_SUCCEEDED :
466 I2C_CHANNEL_OPERATION_FAILED;
467}
468bool dce_i2c_sw_engine_submit_payload(
469 struct dce_i2c_sw *engine,
470 struct i2c_payload *payload,
471 bool middle_of_transaction)
472{
473 struct i2c_request_transaction_data request;
474
475 if (!payload->write)
476 request.action = middle_of_transaction ?
477 DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
478 DCE_I2C_TRANSACTION_ACTION_I2C_READ;
479 else
480 request.action = middle_of_transaction ?
481 DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
482 DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
483
484 request.address = (uint8_t) ((payload->address << 1) | !payload->write);
485 request.length = payload->length;
486 request.data = payload->data;
487
488 dce_i2c_sw_engine_submit_channel_request(engine, &request);
489
490 if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
491 (request.status == I2C_CHANNEL_OPERATION_FAILED))
492 return false;
493
494 return true;
495}
496bool dce_i2c_submit_command_sw(
497 struct resource_pool *pool,
498 struct ddc *ddc,
499 struct i2c_command *cmd,
500 struct dce_i2c_sw *dce_i2c_sw)
501{
502 uint8_t index_of_payload = 0;
503 bool result;
504
505 dce_i2c_sw_engine_set_speed(dce_i2c_sw, cmd->speed);
506
507 result = true;
508
509 while (index_of_payload < cmd->number_of_payloads) {
510 bool mot = (index_of_payload != cmd->number_of_payloads - 1);
511
512 struct i2c_payload *payload = cmd->payloads + index_of_payload;
513
514 if (!dce_i2c_sw_engine_submit_payload(
515 dce_i2c_sw, payload, mot)) {
516 result = false;
517 break;
518 }
519
520 ++index_of_payload;
521 }
522
523 release_engine_dce_sw(pool, dce_i2c_sw);
524
525 return result;
526}
527struct dce_i2c_sw *dce_i2c_acquire_i2c_sw_engine(
528 struct resource_pool *pool,
529 struct ddc *ddc)
530{
531 enum gpio_ddc_line line;
532 struct dce_i2c_sw *engine = NULL;
533
534 if (get_hw_supported_ddc_line(ddc, &line))
535 engine = pool->sw_i2cs[line];
536
537 if (!engine)
538 return NULL;
539
540 if (!dce_i2c_engine_acquire_sw(engine, ddc))
541 return NULL;
542
543 return engine;
544}