summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2015-09-10 10:21:00 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2015-09-10 10:23:45 +0100
commit2c08d72393e4c8ddf5926571b087459aaa225cb1 (patch)
tree388d64b0ce40198315c07e53d458ffea86fc5145
parentd50d336605e9be7280529b0eb565402d7646c913 (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.c138
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;
}