Linux Audio

Check our new training course

Loading...
v6.2
  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}
v5.4
  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}