Skip to content

Commit d1031d5

Browse files
committed
Merge tag 'topic/drm-fixes-2015-09-09' of git://anongit.freedesktop.org/drm-intel into drm-next
bunch of drm fixes. * tag 'topic/drm-fixes-2015-09-09' of git://anongit.freedesktop.org/drm-intel: drm/dp: Add dp_aux_i2c_speed_khz module param to set the assume i2c bus speed drm/dp: Adjust i2c-over-aux retry count based on message size and i2c bus speed drm/dp: Define AUX_RETRY_INTERVAL as 500 us drm/atomic: Fix bookkeeping with TEST_ONLY, v3.
2 parents 91b6fc0 + f36203b commit d1031d5

File tree

2 files changed

+117
-21
lines changed

2 files changed

+117
-21
lines changed

drivers/gpu/drm/drm_atomic.c

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,7 +1515,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
15151515
copied_props++;
15161516
}
15171517

1518-
if (obj->type == DRM_MODE_OBJECT_PLANE && count_props) {
1518+
if (obj->type == DRM_MODE_OBJECT_PLANE && count_props &&
1519+
!(arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
15191520
plane = obj_to_plane(obj);
15201521
plane_mask |= (1 << drm_plane_index(plane));
15211522
plane->old_fb = plane->fb;
@@ -1537,10 +1538,11 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
15371538
}
15381539

15391540
if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
1541+
/*
1542+
* Unlike commit, check_only does not clean up state.
1543+
* Below we call drm_atomic_state_free for it.
1544+
*/
15401545
ret = drm_atomic_check_only(state);
1541-
/* _check_only() does not free state, unlike _commit() */
1542-
if (!ret)
1543-
drm_atomic_state_free(state);
15441546
} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
15451547
ret = drm_atomic_async_commit(state);
15461548
} else {
@@ -1567,25 +1569,30 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
15671569
plane->old_fb = NULL;
15681570
}
15691571

1572+
if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1573+
/*
1574+
* TEST_ONLY and PAGE_FLIP_EVENT are mutually exclusive,
1575+
* if they weren't, this code should be called on success
1576+
* for TEST_ONLY too.
1577+
*/
1578+
1579+
for_each_crtc_in_state(state, crtc, crtc_state, i) {
1580+
if (!crtc_state->event)
1581+
continue;
1582+
1583+
destroy_vblank_event(dev, file_priv,
1584+
crtc_state->event);
1585+
}
1586+
}
1587+
15701588
if (ret == -EDEADLK) {
15711589
drm_atomic_state_clear(state);
15721590
drm_modeset_backoff(&ctx);
15731591
goto retry;
15741592
}
15751593

1576-
if (ret) {
1577-
if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1578-
for_each_crtc_in_state(state, crtc, crtc_state, i) {
1579-
if (!crtc_state->event)
1580-
continue;
1581-
1582-
destroy_vblank_event(dev, file_priv,
1583-
crtc_state->event);
1584-
}
1585-
}
1586-
1594+
if (ret || arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
15871595
drm_atomic_state_free(state);
1588-
}
15891596

15901597
drm_modeset_drop_locks(&ctx);
15911598
drm_modeset_acquire_fini(&ctx);

drivers/gpu/drm/drm_dp_helper.c

Lines changed: 94 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ int drm_dp_bw_code_to_link_rate(u8 link_bw)
159159
}
160160
EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
161161

162+
#define AUX_RETRY_INTERVAL 500 /* us */
163+
162164
/**
163165
* DOC: dp helpers
164166
*
@@ -213,7 +215,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
213215
return -EIO;
214216

215217
case DP_AUX_NATIVE_REPLY_DEFER:
216-
usleep_range(400, 500);
218+
usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
217219
break;
218220
}
219221
}
@@ -422,6 +424,90 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter)
422424
I2C_FUNC_10BIT_ADDR;
423425
}
424426

427+
#define AUX_PRECHARGE_LEN 10 /* 10 to 16 */
428+
#define AUX_SYNC_LEN (16 + 4) /* preamble + AUX_SYNC_END */
429+
#define AUX_STOP_LEN 4
430+
#define AUX_CMD_LEN 4
431+
#define AUX_ADDRESS_LEN 20
432+
#define AUX_REPLY_PAD_LEN 4
433+
#define AUX_LENGTH_LEN 8
434+
435+
/*
436+
* Calculate the duration of the AUX request/reply in usec. Gives the
437+
* "best" case estimate, ie. successful while as short as possible.
438+
*/
439+
static int drm_dp_aux_req_duration(const struct drm_dp_aux_msg *msg)
440+
{
441+
int len = AUX_PRECHARGE_LEN + AUX_SYNC_LEN + AUX_STOP_LEN +
442+
AUX_CMD_LEN + AUX_ADDRESS_LEN + AUX_LENGTH_LEN;
443+
444+
if ((msg->request & DP_AUX_I2C_READ) == 0)
445+
len += msg->size * 8;
446+
447+
return len;
448+
}
449+
450+
static int drm_dp_aux_reply_duration(const struct drm_dp_aux_msg *msg)
451+
{
452+
int len = AUX_PRECHARGE_LEN + AUX_SYNC_LEN + AUX_STOP_LEN +
453+
AUX_CMD_LEN + AUX_REPLY_PAD_LEN;
454+
455+
/*
456+
* For read we expect what was asked. For writes there will
457+
* be 0 or 1 data bytes. Assume 0 for the "best" case.
458+
*/
459+
if (msg->request & DP_AUX_I2C_READ)
460+
len += msg->size * 8;
461+
462+
return len;
463+
}
464+
465+
#define I2C_START_LEN 1
466+
#define I2C_STOP_LEN 1
467+
#define I2C_ADDR_LEN 9 /* ADDRESS + R/W + ACK/NACK */
468+
#define I2C_DATA_LEN 9 /* DATA + ACK/NACK */
469+
470+
/*
471+
* Calculate the length of the i2c transfer in usec, assuming
472+
* the i2c bus speed is as specified. Gives the the "worst"
473+
* case estimate, ie. successful while as long as possible.
474+
* Doesn't account the the "MOT" bit, and instead assumes each
475+
* message includes a START, ADDRESS and STOP. Neither does it
476+
* account for additional random variables such as clock stretching.
477+
*/
478+
static int drm_dp_i2c_msg_duration(const struct drm_dp_aux_msg *msg,
479+
int i2c_speed_khz)
480+
{
481+
/* AUX bitrate is 1MHz, i2c bitrate as specified */
482+
return DIV_ROUND_UP((I2C_START_LEN + I2C_ADDR_LEN +
483+
msg->size * I2C_DATA_LEN +
484+
I2C_STOP_LEN) * 1000, i2c_speed_khz);
485+
}
486+
487+
/*
488+
* Deterine how many retries should be attempted to successfully transfer
489+
* the specified message, based on the estimated durations of the
490+
* i2c and AUX transfers.
491+
*/
492+
static int drm_dp_i2c_retry_count(const struct drm_dp_aux_msg *msg,
493+
int i2c_speed_khz)
494+
{
495+
int aux_time_us = drm_dp_aux_req_duration(msg) +
496+
drm_dp_aux_reply_duration(msg);
497+
int i2c_time_us = drm_dp_i2c_msg_duration(msg, i2c_speed_khz);
498+
499+
return DIV_ROUND_UP(i2c_time_us, aux_time_us + AUX_RETRY_INTERVAL);
500+
}
501+
502+
/*
503+
* FIXME currently assumes 10 kHz as some real world devices seem
504+
* to require it. We should query/set the speed via DPCD if supported.
505+
*/
506+
static int dp_aux_i2c_speed_khz __read_mostly = 10;
507+
module_param_unsafe(dp_aux_i2c_speed_khz, int, 0644);
508+
MODULE_PARM_DESC(dp_aux_i2c_speed_khz,
509+
"Assumed speed of the i2c bus in kHz, (1-400, default 10)");
510+
425511
/*
426512
* Transfer a single I2C-over-AUX message and handle various error conditions,
427513
* retrying the transaction as appropriate. It is assumed that the
@@ -434,13 +520,16 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
434520
{
435521
unsigned int retry, defer_i2c;
436522
int ret;
437-
438523
/*
439524
* DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device
440525
* is required to retry at least seven times upon receiving AUX_DEFER
441526
* before giving up the AUX transaction.
527+
*
528+
* We also try to account for the i2c bus speed.
442529
*/
443-
for (retry = 0, defer_i2c = 0; retry < (7 + defer_i2c); retry++) {
530+
int max_retries = max(7, drm_dp_i2c_retry_count(msg, dp_aux_i2c_speed_khz));
531+
532+
for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c); retry++) {
444533
mutex_lock(&aux->hw_mutex);
445534
ret = aux->transfer(aux, msg);
446535
mutex_unlock(&aux->hw_mutex);
@@ -476,7 +565,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
476565
* For now just defer for long enough to hopefully be
477566
* safe for all use-cases.
478567
*/
479-
usleep_range(500, 600);
568+
usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
480569
continue;
481570

482571
default:
@@ -506,7 +595,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
506595
aux->i2c_defer_count++;
507596
if (defer_i2c < 7)
508597
defer_i2c++;
509-
usleep_range(400, 500);
598+
usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
510599
continue;
511600

512601
default:

0 commit comments

Comments
 (0)