diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2015-09-10 10:21:00 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2015-09-10 10:23:45 +0100 |
commit | 2c08d72393e4c8ddf5926571b087459aaa225cb1 (patch) | |
tree | 388d64b0ce40198315c07e53d458ffea86fc5145 | |
parent | d50d336605e9be7280529b0eb565402d7646c913 (diff) |
sna: Use RRGetInfo() for setting hotplug/coldplug information
Force the full reprobe, resetting all the output properties on all
outputs if we detect a status change on hotplug. Rather than simply
translate the kernel mode lists ourselves, use the common functions in
case more settings change.
References: https://bugs.freedesktop.org/show_bug.cgi?id=91929
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_display.c | 138 |
1 files changed, 36 insertions, 102 deletions
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index d75d2821..0d7a2a15 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -4789,108 +4789,35 @@ static bool disable_unused_crtc(struct sna *sna) return update; } -static int modecmp(DisplayModePtr a, DisplayModePtr b) -{ - int diff; - - diff = (b->type & M_T_PREFERRED)- (a->type & M_T_PREFERRED); - if (diff) - return diff; - - diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; - if (diff) - return diff; - - return b->Clock - a->Clock; -} - -static DisplayModePtr sort_modes(DisplayModePtr in) -{ - DisplayModePtr out = NULL, i, o, *op, prev; - - /* sort by preferred status and pixel area */ - while (in) { - i = in; - in = in->next; - for (op = &out; (o = *op); op = &o->next) { - int ret = modecmp(o, i); - if (ret > 0) - break; - if (ret < 0) - continue; - if (!strcmp(o->name, i->name) && xf86ModesEqual(o, i)) { - free((void *)i->name); - free(i); - goto skip; - } - } - i->next = *op; - *op = i; -skip: ; - } - - /* hook up backward links */ - prev = NULL; - for (o = out; o; o = o->next) { - o->prev = prev; - prev = o; - } - return out; -} - -static void output_update_modes(xf86OutputPtr output) +static bool +output_check_status(struct sna *sna, struct sna_output *output) { - DBG(("%s: updating modes on output %s (id=%d): status=%d\n", - __FUNCTION__, output->name, sna_output->id, - sna_output->serial, serial, output->status)); - RROutputChanged(output->randr_output, TRUE); - - while (output->probed_modes) - xf86DeleteMode(&output->probed_modes, output->probed_modes); - - if (output->status != XF86OutputStatusConnected) - return; - - output->probed_modes = NULL; - - if (output->conf_monitor) - output->probed_modes = - xf86ModesAdd(output->probed_modes, - xf86GetMonitorModes(output->scrn, - output->conf_monitor)); - - output->probed_modes = - xf86ModesAdd(output->probed_modes, - output->funcs->get_modes(output)); - - output->probed_modes = sort_modes(output->probed_modes); -} + union compat_mode_get_connector compat_conn; + struct drm_mode_modeinfo dummy; + xf86OutputStatus status; -static bool output_set_status(xf86OutputPtr output, xf86OutputStatus status) -{ - unsigned value; + VG_CLEAR(compat_conn); - if (status == output->status) - return false; + compat_conn.conn.connector_id = output->id; + compat_conn.conn.count_modes = 1; /* skip detect */ + compat_conn.conn.modes_ptr = (uintptr_t)&dummy; + compat_conn.conn.count_encoders = 0; + compat_conn.conn.count_props = 0; - DBG(("%s: output %s (id=%d), changed status %d -> %d\n", - __FUNCTION__, output->name, sna_output->id, output->status, status)); + (void)drmIoctl(sna->kgem.fd, + DRM_IOCTL_MODE_GETCONNECTOR, + &compat_conn.conn); - output->status = status; - switch (status) { - case XF86OutputStatusConnected: - value = RR_Connected; - break; - case XF86OutputStatusDisconnected: - value = RR_Disconnected; - break; + switch (compat_conn.conn.connection) { + case DRM_MODE_CONNECTED: + status = XF86OutputStatusConnected; + case DRM_MODE_DISCONNECTED: + status = XF86OutputStatusDisconnected; default: - case XF86OutputStatusUnknown: - value = RR_UnknownConnection; - break; + case DRM_MODE_UNKNOWNCONNECTION: + status = XF86OutputStatusUnknown; } - RROutputSetConnection(output->randr_output, value); - return true; + return output->status == status; } void sna_mode_discover(struct sna *sna) @@ -4952,11 +4879,13 @@ void sna_mode_discover(struct sna *sna) if (sna_output->id == 0) continue; - sna_output->last_detect = 0; if (sna_output->serial == serial) { - if (output_set_status(output, - sna_output_detect(output))) - output_update_modes(output); + if (!output_check_status(sna, sna_output)) { + DBG(("%s: output %s (id=%d), changed state, reprobing]\n", + __FUNCTION__, output->name, sna_output->id, + sna_output->serial, serial)); + sna_output->last_detect = 0; + } continue; } @@ -4968,6 +4897,7 @@ void sna_mode_discover(struct sna *sna) "Disabled output %s\n", output->name); sna_output->id = 0; + sna_output->last_detect = 0; output->crtc = NULL; RROutputChanged(output->randr_output, TRUE); changed |= 2; @@ -4988,6 +4918,7 @@ void sna_mode_discover(struct sna *sna) xf86RandR12TellChanged(screen); } + RRGetInfo(screen, TRUE); RRTellChanged(screen); } @@ -5000,6 +4931,7 @@ static CARD32 sna_mode_coldplug(OsTimerPtr timer, CARD32 now, void *data) struct sna *sna = data; ScreenPtr screen = xf86ScrnToScreen(sna->scrn); xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn); + bool reprobe = false; int i; DBG(("%s()\n", __FUNCTION__)); @@ -5015,11 +4947,13 @@ static CARD32 sna_mode_coldplug(OsTimerPtr timer, CARD32 now, void *data) if (output->status != XF86OutputStatusConnected) continue; - output_set_status(output, sna_output_detect(output)); - output_update_modes(output); + reprobe = true; } - RRTellChanged(screen); + if (reprobe) { + RRGetInfo(screen, TRUE); + RRTellChanged(screen); + } free(timer); return 0; } |