Module Name: src Committed By: riastradh Date: Thu Jul 24 21:18:40 UTC 2014
Modified Files: src/sys/arch/amd64/conf: DRMKMS src/sys/external/bsd/drm2/dist/drm/i915: i915_drv.h intel_display.c intel_fbdev.c src/sys/external/bsd/drm2/dist/include/drm: drm_fb_helper.h src/sys/external/bsd/drm2/i915drm: files.i915drmkms i915_pci.c src/sys/modules/i915drmkms: Makefile i915drmkms.ioconf Added Files: src/sys/external/bsd/drm2/i915drm: i915_pci.h intelfb.c intelfb.h Log Message: Rework Intel framebuffer attachment. Turns out genfb_softc must be at the start of its own device_private, so we can't have it in the middle of a structure, and certainly can't have potentially multiple genfbs per graphics device. Failing to do this is why entering ddb didn't work with an i915drmkms console. Instead of putting a genfb_softc into each drm_fb_helper, put a device_t into each drm_fb_helper and create a new intelfb(4) device for each Intel framebuffer. This will be more flexible, too, in case we want accelerated framebuffers later on. (XXX Need to adapt the radeon code, which I'm disabling until that happens to avoid breaking the build.) While here, defer disabling VGA, vga_cndetach, and genfb_attach until we're actually ready to do them all together along with the mode switch. This should reduce the amount of time during which the screen is blanked, in case it hangs. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/sys/arch/amd64/conf/DRMKMS cvs rdiff -u -r1.6 -r1.7 src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h cvs rdiff -u -r1.9 -r1.10 \ src/sys/external/bsd/drm2/dist/drm/i915/intel_display.c cvs rdiff -u -r1.2 -r1.3 \ src/sys/external/bsd/drm2/dist/drm/i915/intel_fbdev.c cvs rdiff -u -r1.4 -r1.5 \ src/sys/external/bsd/drm2/dist/include/drm/drm_fb_helper.h cvs rdiff -u -r1.3 -r1.4 src/sys/external/bsd/drm2/i915drm/files.i915drmkms cvs rdiff -u -r1.13 -r1.14 src/sys/external/bsd/drm2/i915drm/i915_pci.c cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/i915drm/i915_pci.h \ src/sys/external/bsd/drm2/i915drm/intelfb.c \ src/sys/external/bsd/drm2/i915drm/intelfb.h cvs rdiff -u -r1.3 -r1.4 src/sys/modules/i915drmkms/Makefile cvs rdiff -u -r1.2 -r1.3 src/sys/modules/i915drmkms/i915drmkms.ioconf Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/amd64/conf/DRMKMS diff -u src/sys/arch/amd64/conf/DRMKMS:1.4 src/sys/arch/amd64/conf/DRMKMS:1.5 --- src/sys/arch/amd64/conf/DRMKMS:1.4 Wed Jul 16 20:59:57 2014 +++ src/sys/arch/amd64/conf/DRMKMS Thu Jul 24 21:18:40 2014 @@ -1,7 +1,9 @@ include "arch/amd64/conf/NO_DRM" i915drmkms* at pci? dev ? function ? -radeondrmkms* at pci? dev ? function ? +intelfb* at intelfbbus? +#nouveau* at pci? dev ? function ? +#radeondrmkms* at pci? dev ? function ? no options DIAGNOSTIC options DIAGNOSTIC # expensive kernel consistency check Index: src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h diff -u src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h:1.6 src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h:1.7 --- src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h:1.6 Wed Jul 16 23:25:18 2014 +++ src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h Thu Jul 24 21:18:40 2014 @@ -2756,6 +2756,7 @@ static inline void intel_unregister_dsm_ #endif /* CONFIG_ACPI */ /* modesetting */ +extern void i915_disable_vga(struct drm_device *dev); extern void intel_modeset_init_hw(struct drm_device *dev); extern void intel_modeset_suspend_hw(struct drm_device *dev); extern void intel_modeset_init(struct drm_device *dev); Index: src/sys/external/bsd/drm2/dist/drm/i915/intel_display.c diff -u src/sys/external/bsd/drm2/dist/drm/i915/intel_display.c:1.9 src/sys/external/bsd/drm2/dist/drm/i915/intel_display.c:1.10 --- src/sys/external/bsd/drm2/dist/drm/i915/intel_display.c:1.9 Wed Jul 16 21:28:50 2014 +++ src/sys/external/bsd/drm2/dist/drm/i915/intel_display.c Thu Jul 24 21:18:40 2014 @@ -11318,7 +11318,7 @@ static void intel_init_quirks(struct drm } /* Disable the VGA plane that we never use */ -static void i915_disable_vga(struct drm_device *dev) +void i915_disable_vga(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u8 sr1; @@ -11326,7 +11326,7 @@ static void i915_disable_vga(struct drm_ #ifdef __NetBSD__ { - const bus_size_t vgabase = 0x3c0; + const bus_addr_t vgabase = 0x3c0; const bus_space_tag_t iot = dev->pdev->pd_pa.pa_iot; bus_space_handle_t ioh; int error; @@ -11435,8 +11435,10 @@ void intel_modeset_init(struct drm_devic intel_cpu_pll_init(dev); intel_shared_dpll_init(dev); +#ifndef __NetBSD__ /* XXX We wait until intelfb is ready. */ /* Just disable it once at startup */ i915_disable_vga(dev); +#endif intel_setup_outputs(dev); /* Just in case the BIOS is doing something questionable. */ Index: src/sys/external/bsd/drm2/dist/drm/i915/intel_fbdev.c diff -u src/sys/external/bsd/drm2/dist/drm/i915/intel_fbdev.c:1.2 src/sys/external/bsd/drm2/dist/drm/i915/intel_fbdev.c:1.3 --- src/sys/external/bsd/drm2/dist/drm/i915/intel_fbdev.c:1.2 Wed Jul 16 20:56:25 2014 +++ src/sys/external/bsd/drm2/dist/drm/i915/intel_fbdev.c Thu Jul 24 21:18:40 2014 @@ -44,6 +44,8 @@ #include <drm/i915_drm.h> #include "i915_drv.h" +#include "intelfb.h" + #ifndef __NetBSD__ static struct fb_ops intelfb_ops = { .owner = THIS_MODULE, @@ -174,30 +176,31 @@ static int intelfb_create(struct drm_fb_ size = obj->base.size; #ifdef __NetBSD__ - /* XXX errno NetBSD->Linux */ - helper->fb_bst = dev->pdev->pd_pa.pa_memt; - ret = -bus_space_map(helper->fb_bst, - (dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj)), - size, (BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE), - &helper->fb_bsh); - if (ret) { - DRM_ERROR("unable to map framebuffer: %d\n", ret); - goto out_unpin; - } + { + static const struct intelfb_attach_args zero_ifa; + struct intelfb_attach_args ifa = zero_ifa; + + ifa.ifa_drm_dev = dev; + ifa.ifa_fb_helper = helper; + ifa.ifa_fb_sizes = *sizes; + ifa.ifa_fb_bst = dev->pdev->pd_pa.pa_memt; + ifa.ifa_fb_addr = (dev_priv->gtt.mappable_base + + i915_gem_obj_ggtt_offset(obj)); + ifa.ifa_fb_size = size; + ifa.ifa_fb_zero = (ifbdev->fb->obj->stolen && !prealloc); - ret = intel_genfb_attach(dev, helper, sizes); - if (ret) { - DRM_ERROR("unable to attach genfb: %d\n", ret); - bus_space_unmap(helper->fb_bst, helper->fb_bsh, size); + /* + * XXX Should do this asynchronously, since we hold + * dev->struct_mutex. + */ + helper->fbdev = config_found_ia(dev->dev, "intelfbbus", &ifa, NULL); + if (helper->fbdev == NULL) { + DRM_ERROR("unable to attach intelfb\n"); goto out_unpin; } - helper->genfb_attached = true; fb = &ifbdev->fb->base; ifbdev->helper.fb = fb; - - if (ifbdev->fb->obj->stolen && !prealloc) - bus_space_set_region_1(helper->fb_bst, helper->fb_bsh, 0, 0, - size); + } #else info = framebuffer_alloc(0, &dev->pdev->dev); if (!info) { @@ -503,13 +506,15 @@ static void intel_fbdev_destroy(struct d struct intel_fbdev *ifbdev) { #ifdef __NetBSD__ - if (ifbdev->helper.genfb_attached) { - /* XXX genfb doesn't give us a child device_t! */ - (void)config_detach_children(dev->dev, DETACH_FORCE); - bus_space_unmap(ifbdev->helper.fb_bst, ifbdev->helper.fb_bsh, - ifbdev->fb->obj->base.size); - ifbdev->helper.genfb_attached = false; - } + int ret; +#endif + +#ifdef __NetBSD__ + /* XXX errno NetBSD->Linux */ + ret = -config_detach(ifbdev->helper.fbdev, DETACH_FORCE); + if (ret) + DRM_ERROR("failed to detach intelfb: %d\n", ret); + ifbdev->helper.fbdev = NULL; #else if (ifbdev->helper.fbdev) { struct fb_info *info = ifbdev->helper.fbdev; Index: src/sys/external/bsd/drm2/dist/include/drm/drm_fb_helper.h diff -u src/sys/external/bsd/drm2/dist/include/drm/drm_fb_helper.h:1.4 src/sys/external/bsd/drm2/dist/include/drm/drm_fb_helper.h:1.5 --- src/sys/external/bsd/drm2/dist/include/drm/drm_fb_helper.h:1.4 Wed Jul 16 20:56:25 2014 +++ src/sys/external/bsd/drm2/dist/include/drm/drm_fb_helper.h Thu Jul 24 21:18:40 2014 @@ -35,7 +35,7 @@ struct drm_fb_helper; #include <linux/kgdb.h> #ifdef __NetBSD__ -#include <dev/wsfb/genfbvar.h> +#include <sys/device_if.h> #endif struct drm_fb_helper_crtc { @@ -93,14 +93,7 @@ struct drm_fb_helper { struct drm_fb_helper_connector **connector_info; struct drm_fb_helper_funcs *funcs; #ifdef __NetBSD__ /* XXX fb info */ - bus_space_tag_t fb_bst; - bus_space_handle_t fb_bsh; - /* - * XXX Should be a child, not genfb, but genfb doesn't have its - * own independent device_t concept. - */ - struct genfb_softc genfb; - bool genfb_attached:1; + device_t fbdev; #else struct fb_info *fbdev; #endif Index: src/sys/external/bsd/drm2/i915drm/files.i915drmkms diff -u src/sys/external/bsd/drm2/i915drm/files.i915drmkms:1.3 src/sys/external/bsd/drm2/i915drm/files.i915drmkms:1.4 --- src/sys/external/bsd/drm2/i915drm/files.i915drmkms:1.3 Wed Jul 16 20:56:25 2014 +++ src/sys/external/bsd/drm2/i915drm/files.i915drmkms Thu Jul 24 21:18:40 2014 @@ -1,9 +1,14 @@ -# $NetBSD: files.i915drmkms,v 1.3 2014/07/16 20:56:25 riastradh Exp $ +# $NetBSD: files.i915drmkms,v 1.4 2014/07/24 21:18:40 riastradh Exp $ -device i915drmkms: drmkms, drmkms_pci, genfb, wsemuldisplaydev +define intelfbbus { } +device i915drmkms: drmkms, drmkms_pci, intelfbbus attach i915drmkms at pci +device intelfb: intelfbbus, genfb, wsemuldisplaydev +attach intelfb at intelfbbus + makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/dist/drm/i915" +makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/i915drm" makeoptions i915drmkms "CWARNFLAGS.i915_drv.c"+="-Wno-override-init" makeoptions i915drmkms "CWARNFLAGS.intel_display.c"+="-Wno-shadow" @@ -71,3 +76,5 @@ file external/bsd/drm2/dist/drm/i915/int file external/bsd/drm2/i915drm/i915_module.c i915drmkms file external/bsd/drm2/i915drm/i915_pci.c i915drmkms file external/bsd/drm2/i915drm/intel_gtt.c i915drmkms + +file external/bsd/drm2/i915drm/intelfb.c intelfb Index: src/sys/external/bsd/drm2/i915drm/i915_pci.c diff -u src/sys/external/bsd/drm2/i915drm/i915_pci.c:1.13 src/sys/external/bsd/drm2/i915drm/i915_pci.c:1.14 --- src/sys/external/bsd/drm2/i915drm/i915_pci.c:1.13 Wed Jul 23 18:05:44 2014 +++ src/sys/external/bsd/drm2/i915drm/i915_pci.c Thu Jul 24 21:18:40 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: i915_pci.c,v 1.13 2014/07/23 18:05:44 riastradh Exp $ */ +/* $NetBSD: i915_pci.c,v 1.14 2014/07/24 21:18:40 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -30,61 +30,33 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: i915_pci.c,v 1.13 2014/07/23 18:05:44 riastradh Exp $"); - -#ifdef _KERNEL_OPT -#include "vga.h" -#endif +__KERNEL_RCSID(0, "$NetBSD: i915_pci.c,v 1.14 2014/07/24 21:18:40 riastradh Exp $"); #include <sys/types.h> #include <sys/queue.h> #include <sys/systm.h> +#include <sys/queue.h> #include <sys/workqueue.h> -#include <dev/pci/pciio.h> -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> - -#include <dev/pci/wsdisplay_pci.h> -#include <dev/wsfb/genfbvar.h> - -#if NVGA > 0 -/* - * XXX All we really need is vga_is_console from vgavar.h, but the - * header files are missing their own dependencies, so we need to - * explicitly drag in the other crap. - */ -#include <dev/ic/mc6845reg.h> -#include <dev/ic/pcdisplayvar.h> -#include <dev/ic/vgareg.h> -#include <dev/ic/vgavar.h> -#endif - #include <drm/drmP.h> #include "i915_drv.h" +#include "i915_pci.h" -struct intel_genfb_work; -SIMPLEQ_HEAD(intel_genfb_work_head, intel_genfb_work); +SIMPLEQ_HEAD(i915drmkms_task_head, i915drmkms_task); struct i915drmkms_softc { device_t sc_dev; - struct workqueue *sc_genfb_wq; - struct intel_genfb_work_head sc_genfb_work; + enum { + I915DRMKMS_TASK_ATTACH, + I915DRMKMS_TASK_WORKQUEUE, + } sc_task_state; + union { + struct workqueue *workqueue; + struct i915drmkms_task_head attach; + } sc_task_u; struct drm_device *sc_drm_dev; struct pci_dev sc_pci_dev; -#if 0 /* XXX backlight/brightness */ - struct genfb_parameter_callback sc_genfb_backlight_callback; - struct genfb_parameter_callback sc_genfb_brightness_callback; -#endif -}; - -struct intel_genfb_work { - struct drm_fb_helper *igw_fb_helper; - union { - SIMPLEQ_ENTRY(intel_genfb_work) queue; - struct work work; - } igw_u; }; static const struct intel_device_info * @@ -97,22 +69,7 @@ static int i915drmkms_detach(device_t, i static bool i915drmkms_suspend(device_t, const pmf_qual_t *); static bool i915drmkms_resume(device_t, const pmf_qual_t *); -static void intel_genfb_defer_set_config(struct drm_fb_helper *); -static void intel_genfb_set_config_work(struct work *, void *); -static void intel_genfb_set_config(struct intel_genfb_work *); -static int intel_genfb_dpms(struct drm_device *, int); -static int intel_genfb_ioctl(void *, void *, unsigned long, void *, - int, struct lwp *); -static paddr_t intel_genfb_mmap(void *, void *, off_t, int); - -#if 0 /* XXX backlight/brightness */ -static int intel_genfb_get_backlight(void *, int *); -static int intel_genfb_set_backlight(void *, int); -static int intel_genfb_upd_backlight(void *, int); -static int intel_genfb_get_brightness(void *, int *); -static int intel_genfb_set_brightness(void *, int); -static int intel_genfb_upd_brightness(void *, int); -#endif +static void i915drmkms_task_work(struct work *, void *); CFATTACH_DECL_NEW(i915drmkms, sizeof(struct i915drmkms_softc), i915drmkms_match, i915drmkms_attach, i915drmkms_detach, NULL); @@ -197,7 +154,8 @@ i915drmkms_attach(device_t parent, devic &i915drmkms_resume)) aprint_error_dev(self, "unable to establish power handler\n"); - SIMPLEQ_INIT(&sc->sc_genfb_work); + sc->sc_task_state = I915DRMKMS_TASK_ATTACH; + SIMPLEQ_INIT(&sc->sc_task_u.attach); /* XXX errno Linux->NetBSD */ error = -drm_pci_attach(self, pa, &sc->sc_pci_dev, i915_drm_driver, @@ -207,19 +165,21 @@ i915drmkms_attach(device_t parent, devic return; } - while (!SIMPLEQ_EMPTY(&sc->sc_genfb_work)) { - struct intel_genfb_work *const work = - SIMPLEQ_FIRST(&sc->sc_genfb_work); + while (!SIMPLEQ_EMPTY(&sc->sc_task_u.attach)) { + struct i915drmkms_task *const task = + SIMPLEQ_FIRST(&sc->sc_task_u.attach); - SIMPLEQ_REMOVE_HEAD(&sc->sc_genfb_work, igw_u.queue); - intel_genfb_set_config(work); + SIMPLEQ_REMOVE_HEAD(&sc->sc_task_u.attach, ift_u.queue); + (*task->ift_fn)(task); } - error = workqueue_create(&sc->sc_genfb_wq, "intelfb", - &intel_genfb_set_config_work, NULL, PRI_NONE, IPL_NONE, WQ_MPSAFE); + sc->sc_task_state = I915DRMKMS_TASK_WORKQUEUE; + error = workqueue_create(&sc->sc_task_u.workqueue, "intelfb", + &i915drmkms_task_work, NULL, PRI_NONE, IPL_NONE, WQ_MPSAFE); if (error) { aprint_error_dev(self, "unable to create workqueue: %d\n", error); + sc->sc_task_u.workqueue = NULL; return; } } @@ -235,9 +195,10 @@ i915drmkms_detach(device_t self, int fla if (error) return error; - if (sc->sc_genfb_wq == NULL) + KASSERT(sc->sc_task_state == I915DRMKMS_TASK_WORKQUEUE); + if (sc->sc_task_u.workqueue == NULL) goto out; - workqueue_destroy(sc->sc_genfb_wq); + workqueue_destroy(sc->sc_task_u.workqueue); if (sc->sc_drm_dev == NULL) goto out; @@ -288,324 +249,34 @@ i915drmkms_resume(device_t self, const p return true; } -int -intel_genfb_attach(struct drm_device *dev, struct drm_fb_helper *helper, - const struct drm_fb_helper_surface_size *sizes) -{ - struct i915drmkms_softc *const sc = container_of(dev->pdev, - struct i915drmkms_softc, sc_pci_dev); - static const struct genfb_ops zero_genfb_ops; - struct genfb_ops genfb_ops = zero_genfb_ops; - const prop_dictionary_t dict = device_properties(sc->sc_dev); - enum { CONS_VGA, CONS_GENFB, CONS_NONE } what_was_cons; - int ret; - -#if NVGA > 0 - if (vga_is_console(dev->pdev->pd_pa.pa_iot, -1)) { - what_was_cons = CONS_VGA; - prop_dictionary_set_bool(dict, "is_console", true); - /* - * There is a window from here until genfb attaches in - * which kernel messages will go into a black hole, - * until genfb replays the console. Whattakludge. - */ - vga_cndetach(); - } else -#endif - if (genfb_is_console() && genfb_is_enabled()) { - what_was_cons = CONS_GENFB; - prop_dictionary_set_bool(dict, "is_console", true); - } else { - what_was_cons = CONS_NONE; - prop_dictionary_set_bool(dict, "is_console", false); - } - - /* XXX Ugh... Pass these parameters some other way! */ - prop_dictionary_set_uint32(dict, "width", sizes->fb_width); - prop_dictionary_set_uint32(dict, "height", sizes->fb_height); - prop_dictionary_set_uint8(dict, "depth", sizes->surface_bpp); - prop_dictionary_set_uint16(dict, "linebytes", - roundup2((sizes->fb_width * howmany(sizes->surface_bpp, 8)), 64)); - prop_dictionary_set_uint32(dict, "address", 0); /* XXX >32-bit */ - CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t)); - prop_dictionary_set_uint64(dict, "virtual_address", - (uint64_t)(uintptr_t)bus_space_vaddr(helper->fb_bst, - helper->fb_bsh)); - -#if 0 /* XXX backlight/brightness */ - /* XXX What happens with multi-head, multi-fb displays? */ - sc->sc_genfb_backlight_callback = (struct genfb_parameter_callback) { - .gpc_cookie = dev, - .gpc_get_parameter = &intel_genfb_get_backlight, - .gpc_set_parameter = &intel_genfb_set_backlight, - .gpc_upd_parameter = &intel_genfb_upd_backlight, - }; - prop_dictionary_set_uint64(dict, "backlight_callback", - (uint64_t)(uintptr_t)&sc->sc_genfb_backlight_callback); - - sc->sc_genfb_brightness_callback = (struct genfb_parameter_callback) { - .gpc_cookie = dev, - .gpc_get_parameter = &intel_genfb_get_brightness, - .gpc_set_parameter = &intel_genfb_set_brightness, - .gpc_upd_parameter = &intel_genfb_upd_brightness, - }; - prop_dictionary_set_uint64(dict, "brightness_callback", - (uint64_t)(uintptr_t)&sc->sc_genfb_brightness_callback); -#endif - - helper->genfb.sc_dev = sc->sc_dev; - genfb_init(&helper->genfb); - genfb_ops.genfb_ioctl = intel_genfb_ioctl; - genfb_ops.genfb_mmap = intel_genfb_mmap; - - /* XXX errno NetBSD->Linux */ - ret = -genfb_attach(&helper->genfb, &genfb_ops); - if (ret) { - DRM_ERROR("failed to attach genfb: %d\n", ret); - switch (what_was_cons) { /* XXX Restore console... */ - case CONS_VGA: break; - case CONS_GENFB: break; - case CONS_NONE: break; - default: break; - } - return ret; - } - - intel_genfb_defer_set_config(helper); - - return 0; -} - -static void -intel_genfb_defer_set_config(struct drm_fb_helper *helper) -{ - struct drm_device *const dev = helper->dev; - struct i915drmkms_softc *const sc = container_of(dev->pdev, - struct i915drmkms_softc, sc_pci_dev); - struct intel_genfb_work *work; - - /* Really shouldn't sleep here... */ - work = kmem_alloc(sizeof(*work), KM_SLEEP); - work->igw_fb_helper = helper; - - if (sc->sc_genfb_wq == NULL) /* during attachment */ - SIMPLEQ_INSERT_TAIL(&sc->sc_genfb_work, work, igw_u.queue); - else - workqueue_enqueue(sc->sc_genfb_wq, &work->igw_u.work, NULL); -} - -static void -intel_genfb_set_config_work(struct work *work, void *cookie __unused) -{ - - intel_genfb_set_config(container_of(work, struct intel_genfb_work, - igw_u.work)); -} - static void -intel_genfb_set_config(struct intel_genfb_work *work) +i915drmkms_task_work(struct work *work, void *cookie __unused) { + struct i915drmkms_task *const task = container_of(work, + struct i915drmkms_task, ift_u.work); - drm_fb_helper_set_config(work->igw_fb_helper); - kmem_free(work, sizeof(*work)); + (*task->ift_fn)(task); } -static int -intel_genfb_dpms(struct drm_device *dev, int dpms_mode) +int +i915drmkms_task_schedule(device_t self, struct i915drmkms_task *task) { - struct drm_i915_private *const dev_priv = dev->dev_private; - /* XXX What guarantees dev_priv->fbdev stays around? */ - struct drm_fb_helper *const fb_helper = &dev_priv->fbdev->helper; - unsigned i; - - drm_modeset_lock_all(dev); - for (i = 0; i < fb_helper->connector_count; i++) { - struct drm_connector *const connector = - fb_helper->connector_info[i]->connector; - (*connector->funcs->dpms)(connector, dpms_mode); - drm_object_property_set_value(&connector->base, - dev->mode_config.dpms_property, dpms_mode); - } - drm_modeset_unlock_all(dev); - - return 0; -} + struct i915drmkms_softc *const sc = device_private(self); -static int -intel_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag, - struct lwp *l) -{ - struct genfb_softc *const genfb = v; - struct drm_fb_helper *const helper = container_of(genfb, - struct drm_fb_helper, genfb); - struct drm_device *const dev = helper->dev; - const struct pci_attach_args *const pa = &dev->pdev->pd_pa; - - switch (cmd) { - case WSDISPLAYIO_GTYPE: - *(unsigned int *)data = WSDISPLAY_TYPE_PCIVGA; + switch (sc->sc_task_state) { + case I915DRMKMS_TASK_ATTACH: + SIMPLEQ_INSERT_TAIL(&sc->sc_task_u.attach, task, ift_u.queue); return 0; - - /* PCI config read/write passthrough. */ - case PCI_IOC_CFGREAD: - case PCI_IOC_CFGWRITE: - return pci_devioctl(pa->pa_pc, pa->pa_tag, cmd, data, flag, l); - - case WSDISPLAYIO_GET_BUSID: - return wsdisplayio_busid_pci(genfb->sc_dev, - pa->pa_pc, pa->pa_tag, data); - - /* - * Screen blanking ioctls. Not to be confused with backlight - * (can be disabled while stuff is still drawn on the screen), - * brightness, or contrast (which we don't support). Backlight - * and brightness are done through WSDISPLAYIO_{GET,SET}PARAM. - * This toggles between DPMS ON and DPMS OFF; backlight toggles - * between DPMS ON and DPMS SUSPEND. - */ - case WSDISPLAYIO_GVIDEO: { - int *onp = (int *)data; - - /* XXX Can't really determine a single answer here. */ - *onp = 1; + case I915DRMKMS_TASK_WORKQUEUE: + if (sc->sc_task_u.workqueue == NULL) { + aprint_error_dev(self, "unable to schedule task\n"); + return EIO; + } + workqueue_enqueue(sc->sc_task_u.workqueue, &task->ift_u.work, + NULL); return 0; - } - - case WSDISPLAYIO_SVIDEO: { - const int on = *(const int *)data; - - return intel_genfb_dpms(dev, - on? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); - } - default: - return EPASSTHROUGH; - } -} - -static paddr_t -intel_genfb_mmap(void *v, void *vs, off_t offset, int prot) -{ - struct genfb_softc *const genfb = v; - struct drm_fb_helper *const helper = container_of(genfb, - struct drm_fb_helper, genfb); - struct intel_fbdev *const fbdev = container_of(helper, - struct intel_fbdev, helper); - struct drm_device *const dev = helper->dev; - struct drm_i915_private *const dev_priv = dev->dev_private; - const struct pci_attach_args *const pa = &dev->pdev->pd_pa; - unsigned int i; - - if (offset < 0) - return -1; - - /* Treat low memory as the framebuffer itself. */ - if (offset < genfb->sc_fbsize) - return bus_space_mmap(dev->bst, - (dev_priv->gtt.mappable_base + - i915_gem_obj_ggtt_offset(fbdev->fb->obj)), - offset, prot, - (BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE)); - - /* XXX Cargo-culted from genfb_pci. */ - if (kauth_authorize_machdep(kauth_cred_get(), - KAUTH_MACHDEP_UNMANAGEDMEM, NULL, NULL, NULL, NULL) != 0) { - aprint_normal_dev(dev->dev, "mmap at %"PRIxMAX" rejected\n", - (uintmax_t)offset); - return -1; - } - - for (i = 0; PCI_BAR(i) <= PCI_MAPREG_ROM; i++) { - pcireg_t type; - bus_addr_t addr; - bus_size_t size; - int flags; - - /* Interrogate the BAR. */ - if (!pci_mapreg_probe(pa->pa_pc, pa->pa_tag, PCI_BAR(i), - &type)) - continue; - if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM) - continue; - if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(i), type, - &addr, &size, &flags)) - continue; - - /* Try to map it if it's in range. */ - if ((addr <= offset) && (offset < (addr + size))) - return bus_space_mmap(pa->pa_memt, addr, - (offset - addr), prot, flags); - - /* Skip a slot if this was a 64-bit BAR. */ - if ((PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) && - (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT)) - i += 1; + panic("i915drmkms in invalid task state: %d\n", + (int)sc->sc_task_state); } - - /* Failure! */ - return -1; -} - -#if 0 /* XXX backlight/brightness */ -static int -intel_genfb_get_backlight(void *cookie, int *enablep) -{ - struct drm_device *const dev = cookie; - struct drm_i915_private *const dev_priv = dev->dev_private; - - *enablep = dev_priv->backlight.present; - - return 0; -} - -static int -intel_genfb_set_backlight(void *cookie, int enable) -{ - struct drm_device *const dev = cookie; - - return intel_genfb_dpms(dev, - enable? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_SUSPEND); -} - -static int -intel_genfb_upd_backlight(void *cookie __unused, int step __unused) -{ - - panic("can't update i915drm backlight"); -} - -static int -intel_genfb_get_brightness(void *cookie, int *brightnessp) -{ - struct drm_device *const dev = cookie; - struct drm_i915_private *const dev_priv = dev->dev_private; - - *brightnessp = dev_priv->backlight_level; - - return 0; -} - -static int -intel_genfb_set_brightness(void *cookie, int brightness) -{ - struct drm_device *const dev = cookie; - - intel_panel_set_backlight(dev, - MIN(brightness, intel_panel_get_max_backlight(dev))); - - return 0; -} - -static int -intel_genfb_upd_brightness(void *cookie, int delta) -{ - struct drm_device *const dev = cookie; - struct drm_i915_private *const dev_priv = dev->dev_private; - - intel_panel_set_backlight(dev, - MIN(dev_priv->backlight_level + delta, - intel_panel_get_max_backlight(dev))); - - return 0; } -#endif Index: src/sys/modules/i915drmkms/Makefile diff -u src/sys/modules/i915drmkms/Makefile:1.3 src/sys/modules/i915drmkms/Makefile:1.4 --- src/sys/modules/i915drmkms/Makefile:1.3 Wed Jul 16 20:56:26 2014 +++ src/sys/modules/i915drmkms/Makefile Thu Jul 24 21:18:40 2014 @@ -1,9 +1,10 @@ -# $NetBSD: Makefile,v 1.3 2014/07/16 20:56:26 riastradh Exp $ +# $NetBSD: Makefile,v 1.4 2014/07/24 21:18:40 riastradh Exp $ .include "../Makefile.inc" .include "../drmkms/Makefile.inc" CPPFLAGS+= -I${S}/external/bsd/drm2/dist/drm/i915 +CPPFLAGS+= -I${S}/external/bsd/drm2/i915drm .PATH: ${S}/external/bsd/drm2/i915drm .PATH: ${S}/external/bsd/drm2/dist/drm/i915 @@ -66,6 +67,7 @@ SRCS+= intel_uncore.c SRCS+= i915_module.c SRCS+= i915_pci.c SRCS+= intel_gtt.c +SRCS+= intelfb.c COPTS.i915_drv.c+= -Wno-override-init COPTS.intel_display.c+= -Wno-shadow Index: src/sys/modules/i915drmkms/i915drmkms.ioconf diff -u src/sys/modules/i915drmkms/i915drmkms.ioconf:1.2 src/sys/modules/i915drmkms/i915drmkms.ioconf:1.3 --- src/sys/modules/i915drmkms/i915drmkms.ioconf:1.2 Tue Mar 18 18:20:43 2014 +++ src/sys/modules/i915drmkms/i915drmkms.ioconf Thu Jul 24 21:18:40 2014 @@ -1,4 +1,4 @@ -# $NetBSD: i915drmkms.ioconf,v 1.2 2014/03/18 18:20:43 riastradh Exp $ +# $NetBSD: i915drmkms.ioconf,v 1.3 2014/07/24 21:18:40 riastradh Exp $ ioconf i915drmkms @@ -6,5 +6,7 @@ include "conf/files" include "dev/pci/files.pci" pseudo-root pci* +pseudo-root intelfbbus* i915drmkms* at pci? dev ? function ? +intelfb* at intelfbbus? Added files: Index: src/sys/external/bsd/drm2/i915drm/i915_pci.h diff -u /dev/null src/sys/external/bsd/drm2/i915drm/i915_pci.h:1.1 --- /dev/null Thu Jul 24 21:18:40 2014 +++ src/sys/external/bsd/drm2/i915drm/i915_pci.h Thu Jul 24 21:18:40 2014 @@ -0,0 +1,56 @@ +/* $NetBSD: i915_pci.h,v 1.1 2014/07/24 21:18:40 riastradh Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _I915DRM_I915_PCI_H_ +#define _I915DRM_I915_PCI_H_ + +#include <sys/queue.h> +#include <sys/workqueue.h> + +struct i915drmkms_task { + union { + SIMPLEQ_ENTRY(i915drmkms_task) queue; + struct work work; + } ift_u; + void (*ift_fn)(struct i915drmkms_task *); +}; + +static inline void +i915drmkms_task_init(struct i915drmkms_task *task, + void (*fn)(struct i915drmkms_task *)) +{ + + task->ift_fn = fn; +} + +int i915drmkms_task_schedule(device_t, struct i915drmkms_task *); + +#endif /* _I915DRM_I915_PCI_H_ */ Index: src/sys/external/bsd/drm2/i915drm/intelfb.c diff -u /dev/null src/sys/external/bsd/drm2/i915drm/intelfb.c:1.1 --- /dev/null Thu Jul 24 21:18:40 2014 +++ src/sys/external/bsd/drm2/i915drm/intelfb.c Thu Jul 24 21:18:40 2014 @@ -0,0 +1,434 @@ +/* $NetBSD: intelfb.c,v 1.1 2014/07/24 21:18:40 riastradh Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: intelfb.c,v 1.1 2014/07/24 21:18:40 riastradh Exp $"); + +#ifdef _KERNEL_OPT +#include "vga.h" +#endif + +#include <sys/types.h> +#include <sys/bus.h> +#include <sys/device.h> + +#include <dev/pci/pciio.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <dev/pci/wsdisplay_pci.h> +#include <dev/wsfb/genfbvar.h> + +#if NVGA > 0 +/* + * XXX All we really need is vga_is_console from vgavar.h, but the + * header files are missing their own dependencies, so we need to + * explicitly drag in the other crap. + */ +#include <dev/ic/mc6845reg.h> +#include <dev/ic/pcdisplayvar.h> +#include <dev/ic/vgareg.h> +#include <dev/ic/vgavar.h> +#endif + +#include <drm/drmP.h> +#include <drm/drm_fb_helper.h> + +#include "i915_drv.h" +#include "i915_pci.h" +#include "intelfb.h" + +extern void comcnputc(dev_t, int); +static void __printflike(1,2) __unused +comprintf(const char *fmt, ...) +{ + char buf[1024], *p; + va_list va; + + va_start(va, fmt); + vsnprintf(buf, sizeof buf, fmt, va); + va_end(va); + + buf[sizeof buf - 1] = '\0'; + for (p = buf; *p != '\0'; p++) { + comcnputc(NODEV, *p); + if (*p == '\n') + comcnputc(NODEV, '\r'); + } +} + +struct intelfb_softc { + /* XXX genfb requires the genfb_softc to be first. */ + struct genfb_softc sc_genfb; + device_t sc_dev; + struct intelfb_attach_args sc_ifa; + bus_space_handle_t sc_fb_bsh; + struct i915drmkms_task sc_setconfig_task; + bool sc_mapped:1; + bool sc_scheduled:1; + bool sc_attached:1; +}; + +static int intelfb_match(device_t, cfdata_t, void *); +static void intelfb_attach(device_t, device_t, void *); +static int intelfb_detach(device_t, int); + +static void intelfb_setconfig_task(struct i915drmkms_task *); + +static int intelfb_genfb_dpms(struct drm_device *, int); +static int intelfb_genfb_ioctl(void *, void *, unsigned long, void *, + int, struct lwp *); +static paddr_t intelfb_genfb_mmap(void *, void *, off_t, int); +#if notyet /* XXX */ +static int intelfb_genfb_enable_polling(void *); +static int intelfb_genfb_disable_polling(void *); +#endif + +CFATTACH_DECL_NEW(intelfb, sizeof(struct intelfb_softc), + intelfb_match, intelfb_attach, intelfb_detach, NULL); + +static int +intelfb_match(device_t parent, cfdata_t match, void *aux) +{ + + return 1; +} + +static void +intelfb_attach(device_t parent, device_t self, void *aux) +{ + struct intelfb_softc *const sc = device_private(self); + const struct intelfb_attach_args *const ifa = aux; + int error; + + sc->sc_dev = self; + sc->sc_ifa = *ifa; + sc->sc_mapped = false; + sc->sc_scheduled = false; + sc->sc_attached = false; + + /* XXX Defer this too? */ + error = bus_space_map(ifa->ifa_fb_bst, ifa->ifa_fb_addr, + ifa->ifa_fb_size, + (BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE), + &sc->sc_fb_bsh); + if (error) { + aprint_error_dev(self, "unable to map framebuffer: %d\n", + error); + goto fail0; + } + sc->sc_mapped = true; + + i915drmkms_task_init(&sc->sc_setconfig_task, &intelfb_setconfig_task); + error = i915drmkms_task_schedule(parent, &sc->sc_setconfig_task); + if (error) { + aprint_error_dev(self, "failed to schedule mode set: %d\n", + error); + goto fail1; + } + sc->sc_scheduled = true; + + /* Success! */ + return; + +fail1: bus_space_unmap(ifa->ifa_fb_bst, sc->sc_fb_bsh, ifa->ifa_fb_size); + sc->sc_mapped = false; +fail0: return; +} + +static int +intelfb_detach(device_t self, int flags) +{ + struct intelfb_softc *const sc = device_private(self); + + if (sc->sc_scheduled) + return EBUSY; + + if (sc->sc_attached) { + /* XXX genfb detach? Help? */ + sc->sc_attached = false; + } + + if (sc->sc_mapped) { + bus_space_unmap(sc->sc_ifa.ifa_fb_bst, sc->sc_fb_bsh, + sc->sc_ifa.ifa_fb_size); + sc->sc_mapped = false; + } + + return 0; +} + +static void +intelfb_setconfig_task(struct i915drmkms_task *task) +{ + struct intelfb_softc *const sc = container_of(task, + struct intelfb_softc, sc_setconfig_task); + const prop_dictionary_t dict = device_properties(sc->sc_dev); + const struct intelfb_attach_args *const ifa = &sc->sc_ifa; + const struct drm_fb_helper_surface_size *const sizes = + &ifa->ifa_fb_sizes; +#if NVGA > 0 /* XXX no workie for modules */ + struct drm_device *const dev = sc->sc_ifa.ifa_drm_dev; +#endif + enum { CONS_VGA, CONS_GENFB, CONS_NONE } what_was_cons; + static const struct genfb_ops zero_genfb_ops; + struct genfb_ops genfb_ops = zero_genfb_ops; + int error; + + KASSERT(sc->sc_scheduled); + + if (ifa->ifa_fb_zero) + bus_space_set_region_1(sc->sc_ifa.ifa_fb_bst, sc->sc_fb_bsh, 0, + 0, sc->sc_ifa.ifa_fb_size); + + /* XXX Ugh... Pass these parameters some other way! */ + prop_dictionary_set_uint32(dict, "width", sizes->fb_width); + prop_dictionary_set_uint32(dict, "height", sizes->fb_height); + prop_dictionary_set_uint8(dict, "depth", sizes->surface_bpp); + prop_dictionary_set_uint16(dict, "linebytes", + roundup2((sizes->fb_width * howmany(sizes->surface_bpp, 8)), 64)); + prop_dictionary_set_uint32(dict, "address", 0); /* XXX >32-bit */ + CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t)); + prop_dictionary_set_uint64(dict, "virtual_address", + (uint64_t)(uintptr_t)bus_space_vaddr(sc->sc_ifa.ifa_fb_bst, + sc->sc_fb_bsh)); + + /* XXX Whattakludge! */ +#if NVGA > 0 + if (vga_is_console(dev->pdev->pd_pa.pa_iot, -1)) { + what_was_cons = CONS_VGA; + prop_dictionary_set_bool(dict, "is_console", true); + i915_disable_vga(dev); + vga_cndetach(); + } else +#endif + if (genfb_is_console() && genfb_is_enabled()) { + what_was_cons = CONS_GENFB; + prop_dictionary_set_bool(dict, "is_console", true); + } else { + what_was_cons = CONS_NONE; + prop_dictionary_set_bool(dict, "is_console", false); + } + + sc->sc_genfb.sc_dev = sc->sc_dev; + genfb_init(&sc->sc_genfb); + genfb_ops.genfb_ioctl = intelfb_genfb_ioctl; + genfb_ops.genfb_mmap = intelfb_genfb_mmap; +#if notyet /* XXX */ + genfb_ops.genfb_enable_polling = intelfb_genfb_enable_polling; + genfb_ops.genfb_disable_polling = intelfb_genfb_disable_polling; +#endif + + error = genfb_attach(&sc->sc_genfb, &genfb_ops); + if (error) { + aprint_error_dev(sc->sc_dev, "failed to attach genfb: %d\n", + error); + goto fail0; + } + sc->sc_attached = true; + + drm_fb_helper_set_config(sc->sc_ifa.ifa_fb_helper); + + /* Success! */ + sc->sc_scheduled = false; + return; + +fail0: /* XXX Restore console... */ + switch (what_was_cons) { + case CONS_VGA: + break; + case CONS_GENFB: + break; + case CONS_NONE: + break; + default: + break; + } +} + +static int +intelfb_genfb_dpms(struct drm_device *dev, int dpms_mode) +{ + struct drm_i915_private *const dev_priv = dev->dev_private; + /* XXX What guarantees dev_priv->fbdev stays around? */ + struct drm_fb_helper *const fb_helper = &dev_priv->fbdev->helper; + unsigned i; + + drm_modeset_lock_all(dev); + for (i = 0; i < fb_helper->connector_count; i++) { + struct drm_connector *const connector = + fb_helper->connector_info[i]->connector; + (*connector->funcs->dpms)(connector, dpms_mode); + drm_object_property_set_value(&connector->base, + dev->mode_config.dpms_property, dpms_mode); + } + drm_modeset_unlock_all(dev); + + return 0; +} + +static int +intelfb_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag, + struct lwp *l) +{ + struct genfb_softc *const genfb = v; + struct intelfb_softc *const sc = container_of(genfb, + struct intelfb_softc, sc_genfb); + struct drm_device *const dev = sc->sc_ifa.ifa_fb_helper->dev; + const struct pci_attach_args *const pa = &dev->pdev->pd_pa; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(unsigned int *)data = WSDISPLAY_TYPE_PCIVGA; + return 0; + + /* PCI config read/write passthrough. */ + case PCI_IOC_CFGREAD: + case PCI_IOC_CFGWRITE: + return pci_devioctl(pa->pa_pc, pa->pa_tag, cmd, data, flag, l); + + case WSDISPLAYIO_GET_BUSID: + return wsdisplayio_busid_pci(genfb->sc_dev, + pa->pa_pc, pa->pa_tag, data); + + /* + * Screen blanking ioctls. Not to be confused with backlight + * (can be disabled while stuff is still drawn on the screen), + * brightness, or contrast (which we don't support). Backlight + * and brightness are done through WSDISPLAYIO_{GET,SET}PARAM. + * This toggles between DPMS ON and DPMS OFF; backlight toggles + * between DPMS ON and DPMS SUSPEND. + */ + case WSDISPLAYIO_GVIDEO: { + int *onp = (int *)data; + + /* XXX Can't really determine a single answer here. */ + *onp = 1; + return 0; + } + + case WSDISPLAYIO_SVIDEO: { + const int on = *(const int *)data; + + return intelfb_genfb_dpms(dev, + on? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); + } + + default: + return EPASSTHROUGH; + } +} + +static paddr_t +intelfb_genfb_mmap(void *v, void *vs, off_t offset, int prot) +{ + struct genfb_softc *const genfb = v; + struct intelfb_softc *const sc = container_of(genfb, + struct intelfb_softc, sc_genfb); + struct drm_fb_helper *const helper = sc->sc_ifa.ifa_fb_helper; + struct intel_fbdev *const fbdev = container_of(helper, + struct intel_fbdev, helper); + struct drm_device *const dev = helper->dev; + struct drm_i915_private *const dev_priv = dev->dev_private; + const struct pci_attach_args *const pa = &dev->pdev->pd_pa; + unsigned int i; + + if (offset < 0) + return -1; + + /* Treat low memory as the framebuffer itself. */ + if (offset < genfb->sc_fbsize) + return bus_space_mmap(dev->bst, + (dev_priv->gtt.mappable_base + + i915_gem_obj_ggtt_offset(fbdev->fb->obj)), + offset, prot, + (BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE)); + + /* XXX Cargo-culted from genfb_pci. */ + if (kauth_authorize_machdep(kauth_cred_get(), + KAUTH_MACHDEP_UNMANAGEDMEM, NULL, NULL, NULL, NULL) != 0) { + aprint_normal_dev(dev->dev, "mmap at %"PRIxMAX" rejected\n", + (uintmax_t)offset); + return -1; + } + + for (i = 0; PCI_BAR(i) <= PCI_MAPREG_ROM; i++) { + pcireg_t type; + bus_addr_t addr; + bus_size_t size; + int flags; + + /* Interrogate the BAR. */ + if (!pci_mapreg_probe(pa->pa_pc, pa->pa_tag, PCI_BAR(i), + &type)) + continue; + if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM) + continue; + if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(i), type, + &addr, &size, &flags)) + continue; + + /* Try to map it if it's in range. */ + if ((addr <= offset) && (offset < (addr + size))) + return bus_space_mmap(pa->pa_memt, addr, + (offset - addr), prot, flags); + + /* Skip a slot if this was a 64-bit BAR. */ + if ((PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) && + (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT)) + i += 1; + } + + /* Failure! */ + return -1; +} + +#if notyet /* XXX */ +static int +intelfb_genfb_enable_polling(void *cookie) +{ + struct genfb_softc *const genfb = cookie; + struct intelfb_softc *const sc = container_of(genfb, + struct intelfb_softc, sc_genfb); + + return drm_fb_helper_debug_enter_fb(sc->sc_ifa.ifa_fb_helper); +} + +static int +intelfb_genfb_disable_polling(void *cookie) +{ + struct genfb_softc *const genfb = cookie; + struct intelfb_softc *const sc = container_of(genfb, + struct intelfb_softc, sc_genfb); + + return drm_fb_helper_debug_leave_fb(sc->sc_ifa.ifa_fb_helper); +} +#endif Index: src/sys/external/bsd/drm2/i915drm/intelfb.h diff -u /dev/null src/sys/external/bsd/drm2/i915drm/intelfb.h:1.1 --- /dev/null Thu Jul 24 21:18:40 2014 +++ src/sys/external/bsd/drm2/i915drm/intelfb.h Thu Jul 24 21:18:40 2014 @@ -0,0 +1,50 @@ +/* $NetBSD: intelfb.h,v 1.1 2014/07/24 21:18:40 riastradh Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _I915DRM_INTELFB_H_ +#define _I915DRM_INTELFB_H_ + +#include <sys/bus.h> + +#include <drm/drmP.h> +#include <drm/drm_fb_helper.h> + +struct intelfb_attach_args { + struct drm_device *ifa_drm_dev; + struct drm_fb_helper *ifa_fb_helper; + struct drm_fb_helper_surface_size ifa_fb_sizes; + bus_space_tag_t ifa_fb_bst; + bus_addr_t ifa_fb_addr; + bus_size_t ifa_fb_size; + bool ifa_fb_zero; +}; + +#endif /* _I915DRM_INTELFB_H_ */