Subversion Repositories Kolibri OS

Rev

Rev 5060 | Rev 6084 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5060 Rev 5271
Line 25... Line 25...
25
//#include 
25
//#include 
26
//#include 
26
//#include 
27
#include 
27
#include 
28
#include 
28
#include 
29
#include 
29
#include 
30
#include 
-
 
31
#include 
30
#include 
-
 
31
#include 
Line 32... Line 32...
32
 
32
 
33
/**
33
/**
34
 * DOC: dp helpers
34
 * DOC: dp helpers
35
 *
35
 *
36
 * These functions contain some common logic and helpers at various abstraction
36
 * These functions contain some common logic and helpers at various abstraction
37
 * levels to deal with Display Port sink devices and related things like DP aux
37
 * levels to deal with Display Port sink devices and related things like DP aux
38
 * channel transfers, EDID reading over DP aux channels, decoding certain DPCD
38
 * channel transfers, EDID reading over DP aux channels, decoding certain DPCD
39
 * blocks, ...
39
 * blocks, ...
Line 40... Line -...
40
 */
-
 
41
 
-
 
42
/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
-
 
43
static int
-
 
44
i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
-
 
45
			    uint8_t write_byte, uint8_t *read_byte)
-
 
46
{
-
 
47
	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-
 
48
	int ret;
-
 
49
 
-
 
50
	ret = (*algo_data->aux_ch)(adapter, mode,
-
 
51
				   write_byte, read_byte);
-
 
52
	return ret;
-
 
53
}
-
 
54
 
-
 
55
/*
-
 
56
 * I2C over AUX CH
-
 
57
 */
-
 
58
 
-
 
59
/*
-
 
60
 * Send the address. If the I2C link is running, this 'restarts'
-
 
61
 * the connection with the new address, this is used for doing
-
 
62
 * a write followed by a read (as needed for DDC)
-
 
63
 */
-
 
64
static int
-
 
65
i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
-
 
66
{
-
 
67
	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-
 
68
	int mode = MODE_I2C_START;
-
 
69
	int ret;
-
 
70
 
-
 
71
	if (reading)
-
 
72
		mode |= MODE_I2C_READ;
-
 
73
	else
-
 
74
		mode |= MODE_I2C_WRITE;
-
 
75
	algo_data->address = address;
-
 
76
	algo_data->running = true;
-
 
77
	ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
-
 
78
	return ret;
-
 
79
}
-
 
80
 
-
 
81
/*
-
 
82
 * Stop the I2C transaction. This closes out the link, sending
-
 
83
 * a bare address packet with the MOT bit turned off
-
 
84
 */
-
 
85
static void
-
 
86
i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
-
 
87
{
-
 
88
	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-
 
89
	int mode = MODE_I2C_STOP;
-
 
90
 
-
 
91
	if (reading)
-
 
92
		mode |= MODE_I2C_READ;
-
 
93
	else
-
 
94
		mode |= MODE_I2C_WRITE;
-
 
95
	if (algo_data->running) {
-
 
96
		(void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
-
 
97
		algo_data->running = false;
-
 
98
	}
-
 
99
}
-
 
100
 
-
 
101
/*
-
 
102
 * Write a single byte to the current I2C address, the
-
 
103
 * the I2C link must be running or this returns -EIO
-
 
104
 */
-
 
105
static int
-
 
106
i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
-
 
107
{
-
 
108
	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-
 
109
	int ret;
-
 
110
 
-
 
111
	if (!algo_data->running)
-
 
112
		return -EIO;
-
 
113
 
-
 
114
	ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
-
 
115
	return ret;
-
 
116
}
-
 
117
 
-
 
118
/*
-
 
119
 * Read a single byte from the current I2C address, the
-
 
120
 * I2C link must be running or this returns -EIO
-
 
121
 */
-
 
122
static int
-
 
123
i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
-
 
124
{
-
 
125
	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-
 
126
	int ret;
-
 
127
 
-
 
128
	if (!algo_data->running)
-
 
129
		return -EIO;
-
 
130
 
-
 
131
	ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
-
 
132
	return ret;
-
 
133
}
-
 
134
 
-
 
135
static int
-
 
136
i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
-
 
137
		     struct i2c_msg *msgs,
-
 
138
		     int num)
-
 
139
{
-
 
140
	int ret = 0;
-
 
141
	bool reading = false;
-
 
142
	int m;
-
 
143
	int b;
-
 
144
 
-
 
145
	for (m = 0; m < num; m++) {
-
 
146
		u16 len = msgs[m].len;
-
 
147
		u8 *buf = msgs[m].buf;
-
 
148
		reading = (msgs[m].flags & I2C_M_RD) != 0;
-
 
149
		ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
-
 
150
		if (ret < 0)
-
 
151
			break;
-
 
152
		if (reading) {
-
 
153
			for (b = 0; b < len; b++) {
-
 
154
				ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
-
 
155
				if (ret < 0)
-
 
156
					break;
-
 
157
			}
-
 
158
		} else {
-
 
159
			for (b = 0; b < len; b++) {
-
 
160
				ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
-
 
161
				if (ret < 0)
-
 
162
					break;
-
 
163
			}
-
 
164
		}
-
 
165
		if (ret < 0)
-
 
166
			break;
-
 
167
	}
-
 
168
	if (ret >= 0)
-
 
169
		ret = num;
-
 
170
	i2c_algo_dp_aux_stop(adapter, reading);
-
 
171
	DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
-
 
172
	return ret;
-
 
173
}
-
 
174
 
-
 
175
static u32
-
 
176
i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
-
 
177
{
-
 
178
	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
-
 
179
	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
-
 
180
	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
-
 
181
	       I2C_FUNC_10BIT_ADDR;
-
 
182
}
-
 
183
 
-
 
184
static const struct i2c_algorithm i2c_dp_aux_algo = {
-
 
185
	.master_xfer	= i2c_algo_dp_aux_xfer,
-
 
186
	.functionality	= i2c_algo_dp_aux_functionality,
-
 
187
};
-
 
188
 
-
 
189
static void
-
 
190
i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
-
 
191
{
-
 
192
	(void) i2c_algo_dp_aux_address(adapter, 0, false);
-
 
193
	(void) i2c_algo_dp_aux_stop(adapter, false);
-
 
194
}
-
 
195
 
-
 
196
static int
-
 
197
i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
-
 
198
{
-
 
199
	adapter->algo = &i2c_dp_aux_algo;
-
 
200
	adapter->retries = 3;
-
 
201
	i2c_dp_aux_reset_bus(adapter);
-
 
202
	return 0;
-
 
203
}
-
 
204
 
-
 
205
/**
-
 
206
 * i2c_dp_aux_add_bus() - register an i2c adapter using the aux ch helper
-
 
207
 * @adapter: i2c adapter to register
-
 
208
 *
-
 
209
 * This registers an i2c adapter that uses dp aux channel as it's underlaying
-
 
210
 * transport. The driver needs to fill out the &i2c_algo_dp_aux_data structure
-
 
211
 * and store it in the algo_data member of the @adapter argument. This will be
-
 
212
 * used by the i2c over dp aux algorithm to drive the hardware.
-
 
213
 *
-
 
214
 * RETURNS:
-
 
215
 * 0 on success, -ERRNO on failure.
-
 
216
 *
-
 
217
 * IMPORTANT:
-
 
218
 * This interface is deprecated, please switch to the new dp aux helpers and
-
 
219
 * drm_dp_aux_register().
-
 
220
 */
-
 
221
int
-
 
222
i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
-
 
223
{
-
 
224
	int error;
-
 
225
 
-
 
226
	error = i2c_dp_aux_prepare_bus(adapter);
-
 
227
	if (error)
-
 
228
		return error;
-
 
229
	error = i2c_add_adapter(adapter);
-
 
230
	return error;
-
 
231
}
-
 
232
EXPORT_SYMBOL(i2c_dp_aux_add_bus);
40
 */
233
 
41
 
234
/* Helpers for DP link training */
42
/* Helpers for DP link training */
235
static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
43
static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
236
{
44
{
Line 376... Line 184...
376
	msg.buffer = buffer;
184
	msg.buffer = buffer;
377
	msg.size = size;
185
	msg.size = size;
Line 378... Line 186...
378
 
186
 
379
	/*
187
	/*
380
	 * The specification doesn't give any recommendation on how often to
188
	 * The specification doesn't give any recommendation on how often to
381
	 * retry native transactions, so retry 7 times like for I2C-over-AUX
189
	 * retry native transactions. We used to retry 7 times like for
-
 
190
	 * aux i2c transactions but real world devices this wasn't
382
	 * transactions.
191
	 * sufficient, bump to 32 which makes Dell 4k monitors happier.
383
	 */
192
	 */
Line 384... Line 193...
384
	for (retry = 0; retry < 7; retry++) {
193
	for (retry = 0; retry < 32; retry++) {
385
 
194
 
386
		mutex_lock(&aux->hw_mutex);
195
		mutex_lock(&aux->hw_mutex);
387
		err = aux->transfer(aux, &msg);
196
		err = aux->transfer(aux, &msg);