diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2014-04-07 10:33:43 -0400 |
---|---|---|
committer | Christian König <christian.koenig@amd.com> | 2014-04-08 10:12:38 -0400 |
commit | 25377b921b4078a509f384fdd328b50d46414d9c (patch) | |
tree | ca69352840b0a944703fe040198edf4e3adfcbd2 /drivers/gpu/drm | |
parent | a6c8aff022d4d06e4b41455ae9b2a5d3d503bf76 (diff) |
drm/radeon/dp: handle zero sized i2c over aux transactions (v2)
Needed for proper i2c over aux handling for certain
monitors and configurations (e.g., dp bridges or
adapters).
v2: add comments clarifying tx_size setting.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_dp.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 8b0ab170cef9..e4483042aee0 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c | |||
@@ -142,7 +142,8 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, | |||
142 | return recv_bytes; | 142 | return recv_bytes; |
143 | } | 143 | } |
144 | 144 | ||
145 | #define HEADER_SIZE 4 | 145 | #define BARE_ADDRESS_SIZE 3 |
146 | #define HEADER_SIZE (BARE_ADDRESS_SIZE + 1) | ||
146 | 147 | ||
147 | static ssize_t | 148 | static ssize_t |
148 | radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | 149 | radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
@@ -160,13 +161,19 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
160 | tx_buf[0] = msg->address & 0xff; | 161 | tx_buf[0] = msg->address & 0xff; |
161 | tx_buf[1] = msg->address >> 8; | 162 | tx_buf[1] = msg->address >> 8; |
162 | tx_buf[2] = msg->request << 4; | 163 | tx_buf[2] = msg->request << 4; |
163 | tx_buf[3] = msg->size - 1; | 164 | tx_buf[3] = msg->size ? (msg->size - 1) : 0; |
164 | 165 | ||
165 | switch (msg->request & ~DP_AUX_I2C_MOT) { | 166 | switch (msg->request & ~DP_AUX_I2C_MOT) { |
166 | case DP_AUX_NATIVE_WRITE: | 167 | case DP_AUX_NATIVE_WRITE: |
167 | case DP_AUX_I2C_WRITE: | 168 | case DP_AUX_I2C_WRITE: |
169 | /* tx_size needs to be 4 even for bare address packets since the atom | ||
170 | * table needs the info in tx_buf[3]. | ||
171 | */ | ||
168 | tx_size = HEADER_SIZE + msg->size; | 172 | tx_size = HEADER_SIZE + msg->size; |
169 | tx_buf[3] |= tx_size << 4; | 173 | if (msg->size == 0) |
174 | tx_buf[3] |= BARE_ADDRESS_SIZE << 4; | ||
175 | else | ||
176 | tx_buf[3] |= tx_size << 4; | ||
170 | memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size); | 177 | memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size); |
171 | ret = radeon_process_aux_ch(chan, | 178 | ret = radeon_process_aux_ch(chan, |
172 | tx_buf, tx_size, NULL, 0, delay, &ack); | 179 | tx_buf, tx_size, NULL, 0, delay, &ack); |
@@ -176,8 +183,14 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
176 | break; | 183 | break; |
177 | case DP_AUX_NATIVE_READ: | 184 | case DP_AUX_NATIVE_READ: |
178 | case DP_AUX_I2C_READ: | 185 | case DP_AUX_I2C_READ: |
186 | /* tx_size needs to be 4 even for bare address packets since the atom | ||
187 | * table needs the info in tx_buf[3]. | ||
188 | */ | ||
179 | tx_size = HEADER_SIZE; | 189 | tx_size = HEADER_SIZE; |
180 | tx_buf[3] |= tx_size << 4; | 190 | if (msg->size == 0) |
191 | tx_buf[3] |= BARE_ADDRESS_SIZE << 4; | ||
192 | else | ||
193 | tx_buf[3] |= tx_size << 4; | ||
181 | ret = radeon_process_aux_ch(chan, | 194 | ret = radeon_process_aux_ch(chan, |
182 | tx_buf, tx_size, msg->buffer, msg->size, delay, &ack); | 195 | tx_buf, tx_size, msg->buffer, msg->size, delay, &ack); |
183 | break; | 196 | break; |
@@ -186,7 +199,7 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
186 | break; | 199 | break; |
187 | } | 200 | } |
188 | 201 | ||
189 | if (ret > 0) | 202 | if (ret >= 0) |
190 | msg->reply = ack >> 4; | 203 | msg->reply = ack >> 4; |
191 | 204 | ||
192 | return ret; | 205 | return ret; |