From patchwork Mon Oct 4 17:43:38 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Packard X-Patchwork-Id: 229171 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o94Hi4mg012759 for ; Mon, 4 Oct 2010 17:44:25 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1BD889EF4B for ; Mon, 4 Oct 2010 10:44:04 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from keithp.com (home.keithp.com [63.227.221.253]) by gabe.freedesktop.org (Postfix) with ESMTP id 0D3DF9EF13; Mon, 4 Oct 2010 10:43:47 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by keithp.com (Postfix) with ESMTP id 9A4277600FF; Mon, 4 Oct 2010 10:43:47 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at keithp.com Received: from keithp.com ([127.0.0.1]) by localhost (keithp.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 5DhOImjvqy9d; Mon, 4 Oct 2010 10:43:41 -0700 (PDT) Received: by keithp.com (Postfix, from userid 1033) id EDAE77600C2; Mon, 4 Oct 2010 10:43:41 -0700 (PDT) Received: from koto.keithp.com (localhost [127.0.0.1]) by keithp.com (Postfix) with ESMTP id EAEDF76008E; Mon, 4 Oct 2010 10:43:41 -0700 (PDT) Received: by koto.keithp.com (Postfix, from userid 1488) id 958311984D7; Mon, 4 Oct 2010 10:43:41 -0700 (PDT) From: Keith Packard To: intel-gfx@lists.freedesktop.org Subject: [PATCH] intel: Listen for hotplug uevents (V3) Date: Mon, 4 Oct 2010 10:43:38 -0700 Message-Id: <1286214218-10551-1-git-send-email-keithp@keithp.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: References: Cc: dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Mon, 04 Oct 2010 17:44:25 +0000 (UTC) diff --git a/configure.ac b/configure.ac index e066b3d..58fa929 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,11 @@ AC_PROG_LIBTOOL PKG_CHECK_MODULES(GEN4ASM, [intel-gen4asm >= 1.0], [gen4asm=yes], [gen4asm=no]) AM_CONDITIONAL(HAVE_GEN4ASM, test x$gen4asm = xyes) +PKG_CHECK_MODULES(UDEV, [libudev], [udev=yes], [udev=no]) +if test x"$udev" = xyes; then + AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection]) +fi + AH_TOP([#include "xorg-server.h"]) # Define a configure option for an alternate module directory diff --git a/man/intel.man b/man/intel.man index 31860f2..fa7f7dc 100644 --- a/man/intel.man +++ b/man/intel.man @@ -192,6 +192,12 @@ Enable XvMC driver. Current support MPEG2 MC on 915/945 and G33 series. User should provide absolute path to libIntelXvMC.so in XvMCConfig file. .IP Default: Disabled. +.TP +.BI "Option \*qHotplug\*q \*q" boolean \*q +This option controls whether the driver automatically notifies +applications when monitors are connected or disconnected. +.IP +Default: enabled. .SH OUTPUT CONFIGURATION On 830M and better chipsets, the driver supports runtime configuration of diff --git a/src/Makefile.am b/src/Makefile.am index b0a1cf7..ab70207 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,13 +26,13 @@ SUBDIRS = xvmc render_program legacy # _ladir passes a dummy rpath to libtool so the thing will actually link # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. -AM_CFLAGS = @CWARNFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \ +AM_CFLAGS = @CWARNFLAGS@ @XORG_CFLAGS@ @UDEV_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \ @PCIACCESS_CFLAGS@ -I$(top_srcdir)/uxa -I$(top_srcdir)/src/render_program intel_drv_la_LTLIBRARIES = intel_drv.la intel_drv_la_LDFLAGS = -module -avoid-version intel_drv_ladir = @moduledir@/drivers -intel_drv_la_LIBADD = -lm @DRM_LIBS@ -ldrm_intel ../uxa/libuxa.la legacy/liblegacy.la +intel_drv_la_LIBADD = @UDEV_LIBS@ -lm @DRM_LIBS@ -ldrm_intel ../uxa/libuxa.la legacy/liblegacy.la intel_drv_la_LIBADD += @PCIACCESS_LIBS@ NULL:=# diff --git a/src/intel.h b/src/intel.h index b816aeb..1234b94 100644 --- a/src/intel.h +++ b/src/intel.h @@ -34,6 +34,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #if 0 #define I830DEBUG #endif @@ -70,6 +74,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "intel_driver.h" +#if HAVE_UDEV +#include +#endif + #include "uxa.h" /* XXX * The X server gained an *almost* identical implementation in 1.9. @@ -435,6 +443,10 @@ typedef struct intel_screen_private { */ Bool fallback_debug; unsigned debug_flush; +#if HAVE_UDEV + struct udev_monitor *uevent_monitor; + InputHandlerProc uevent_handler; +#endif } intel_screen_private; enum { diff --git a/src/intel_driver.c b/src/intel_driver.c index 4391672..63b26a4 100644 --- a/src/intel_driver.c +++ b/src/intel_driver.c @@ -107,6 +107,7 @@ typedef enum { OPTION_DEBUG_FLUSH_BATCHES, OPTION_DEBUG_FLUSH_CACHES, OPTION_DEBUG_WAIT, + OPTION_HOTPLUG, } I830Opts; static OptionInfoRec I830Options[] = { @@ -125,6 +126,7 @@ static OptionInfoRec I830Options[] = { {OPTION_DEBUG_FLUSH_BATCHES, "DebugFlushBatches", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_DEBUG_FLUSH_CACHES, "DebugFlushCaches", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_DEBUG_WAIT, "DebugWait", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_HOTPLUG, "HotPlug", OPTV_BOOLEAN, {0}, TRUE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ @@ -801,6 +803,110 @@ intel_flush_callback(CallbackListPtr *list, } } +#if HAVE_UDEV +static void +I830HandleUEvents(int fd, void *closure) +{ + ScrnInfoPtr scrn = closure; + intel_screen_private *intel = intel_get_screen_private(scrn); + struct udev_device *dev; + const char *hotplug; + struct stat s; + dev_t udev_devnum; + + dev = udev_monitor_receive_device(intel->uevent_monitor); + if (!dev) + return; + + udev_devnum = udev_device_get_devnum(dev); + fstat(intel->drmSubFD, &s); + /* + * Check to make sure this event is directed at our + * device (by comparing dev_t values), then make + * sure it's a hotplug event (HOTPLUG=1) + */ + + hotplug = udev_device_get_property_value(dev, "HOTPLUG"); + + if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 && + hotplug && atoi(hotplug) == 1) + RRGetInfo(screenInfo.screens[scrn->scrnIndex], TRUE); + + udev_device_unref(dev); +} + +static void +I830UeventInit(ScrnInfoPtr scrn) +{ + intel_screen_private *intel = intel_get_screen_private(scrn); + struct udev *u; + struct udev_monitor *mon; + Bool hotplug; + MessageType from = X_CONFIG; + + if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) { + from = X_DEFAULT; + hotplug = TRUE; + } + + xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n", + hotplug ? "enabled" : "disabled"); + if (!hotplug) + return; + + u = udev_new(); + if (!u) + return; + + mon = udev_monitor_new_from_netlink(u, "udev"); + + if (!mon) { + udev_unref(u); + return; + } + + if (udev_monitor_filter_add_match_subsystem_devtype(mon, + "drm", + "drm_minor") < 0 || + udev_monitor_enable_receiving(mon) < 0) + { + udev_monitor_unref(mon); + udev_unref(u); + return; + } + + intel->uevent_handler = + xf86AddGeneralHandler(udev_monitor_get_fd(mon), + I830HandleUEvents, + scrn); + if (!intel->uevent_handler) { + udev_monitor_unref(mon); + udev_unref(u); + return; + } + + intel->uevent_monitor = mon; +} + +static void +I830UeventFini(ScrnInfoPtr scrn) +{ + intel_screen_private *intel = intel_get_screen_private(scrn); + + if (intel->uevent_handler) + { + struct udev *u = udev_monitor_get_udev(intel->uevent_monitor); + + xf86RemoveGeneralHandler(intel->uevent_handler); + + udev_monitor_unref(intel->uevent_monitor); + udev_unref(u); + intel->uevent_handler = NULL; + intel->uevent_monitor = NULL; + } +} +#endif /* HAVE_UDEV */ + static Bool I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv) { @@ -1007,6 +1113,10 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv) intel->suspended = FALSE; +#if HAVE_UDEV + I830UeventInit(scrn); +#endif + return uxa_resources_init(screen); } @@ -1088,6 +1198,10 @@ static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen) ScrnInfoPtr scrn = xf86Screens[scrnIndex]; intel_screen_private *intel = intel_get_screen_private(scrn); +#if HAVE_UDEV + I830UeventFini(scrn); +#endif + if (scrn->vtSema == TRUE) { I830LeaveVT(scrnIndex, 0); }