Factor generic parts of intelfb out into a drmfb. Adapting radeondrmkmsfb should not be hard. This will make nouveaufb easier too.diff -r0 -r1.1 src/sys/external/bsd/drm2/drm/drmfb.c
(riastradh)
/* $NetBSD: drmfb.c,v 1.1 2015/03/05 17:50:41 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.
*/
/*
* drmfb: wsdisplay support, via genfb, for any drm device. Use this
* if you're too lazy to write a hardware-accelerated framebuffer using
* wsdisplay directly.
*
* This doesn't actually do anything interesting -- just hooks up
* drmkms crap and genfb crap.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: drmfb.c,v 1.1 2015/03/05 17:50:41 riastradh Exp $");
#ifdef _KERNEL_OPT
#include "vga.h"
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/device.h>
#include <sys/kauth.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 <dev/wsfb/genfbvar.h>
#include <drm/drmP.h>
#include <drm/drm_fb_helper.h>
#include <drm/drmfb.h>
static int drmfb_genfb_ioctl(void *, void *, unsigned long, void *, int,
struct lwp *);
static paddr_t drmfb_genfb_mmap(void *, void *, off_t, int);
static int drmfb_genfb_enable_polling(void *);
static int drmfb_genfb_disable_polling(void *);
static bool drmfb_genfb_setmode(struct genfb_softc *, int);
static const struct genfb_mode_callback drmfb_genfb_mode_callback = {
.gmc_setmode = drmfb_genfb_setmode,
};
int
drmfb_attach(struct drmfb_softc *sc, const struct drmfb_attach_args *da)
{
const struct drm_fb_helper_surface_size *const sizes = da->da_fb_sizes;
const prop_dictionary_t dict = device_properties(da->da_dev);
#if NVGA > 0
struct drm_device *const dev = da->da_fb_helper->dev;
#endif
static const struct genfb_ops zero_genfb_ops;
struct genfb_ops genfb_ops = zero_genfb_ops;
enum { CONS_VGA, CONS_GENFB, CONS_NONE } what_was_cons;
int error;
/* genfb requires this. */
KASSERTMSG((void *)&sc->sc_genfb == device_private(da->da_dev),
"drmfb_softc must be first member of device softc");
sc->sc_da = *da;
prop_dictionary_set_uint32(dict, "width", sizes->surface_width);
prop_dictionary_set_uint32(dict, "height", sizes->surface_height);
prop_dictionary_set_uint8(dict, "depth", sizes->surface_bpp);
prop_dictionary_set_uint16(dict, "linebytes",
roundup2((sizes->surface_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)da->da_fb_vaddr);
prop_dictionary_set_uint64(dict, "mode_callback",
(uint64_t)(uintptr_t)&drmfb_genfb_mode_callback);
/* XXX Whattakludge! */
#if NVGA > 0
if ((da->da_params->dp_is_vga_console != NULL) &&
(*da->da_params->dp_is_vga_console)(dev)) {
what_was_cons = CONS_VGA;
prop_dictionary_set_bool(dict, "is_console", true);
vga_cndetach();
if (da->da_params->dp_disable_vga)
(*da->da_params->dp_disable_vga)(dev);
} 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_da.da_dev;
genfb_init(&sc->sc_genfb);
genfb_ops.genfb_ioctl = drmfb_genfb_ioctl;
genfb_ops.genfb_mmap = drmfb_genfb_mmap;
genfb_ops.genfb_enable_polling = drmfb_genfb_enable_polling;
genfb_ops.genfb_disable_polling = drmfb_genfb_disable_polling;
error = genfb_attach(&sc->sc_genfb, &genfb_ops);
if (error) {
aprint_error_dev(sc->sc_da.da_dev,
"failed to attach genfb: %d\n", error);
goto fail0;
}
/* Success! */
return 0;
fail0: KASSERT(error);
/* XXX Restore console... */
switch (what_was_cons) {
case CONS_VGA:
break;
case CONS_GENFB:
break;
case CONS_NONE:
break;
default:
break;
}
return error;
}
int
drmfb_detach(struct drmfb_softc *sc, int flags)
{
/* XXX genfb detach? */
return 0;
}
static int
drmfb_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag,
struct lwp *l)
{
struct genfb_softc *const genfb = v;
struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
sc_genfb);
int error;
if (sc->sc_da.da_params->dp_ioctl) {
error = (*sc->sc_da.da_params->dp_ioctl)(sc, cmd, data, flag,
l);
if (error != EPASSTHROUGH)
return error;
}
switch (cmd) {
/*
* 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;
const int dpms_mode = on? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF;
struct drm_fb_helper *const fb_helper = sc->sc_da.da_fb_helper;
struct drm_device *const dev = fb_helper->dev;
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;
}
default:
return EPASSTHROUGH;
}
}
static paddr_t
drmfb_genfb_mmap(void *v, void *vs, off_t offset, int prot)
{
struct genfb_softc *const genfb = v;
struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
sc_genfb);
KASSERT(0 <= offset);
if (offset < genfb->sc_fbsize) {
if (sc->sc_da.da_params->dp_mmapfb == NULL)
return -1;
return (*sc->sc_da.da_params->dp_mmapfb)(sc, offset, prot);
} else {
if (kauth_authorize_machdep(kauth_cred_get(),
KAUTH_MACHDEP_UNMANAGEDMEM, NULL, NULL, NULL, NULL)
!= 0)
return -1;
if (sc->sc_da.da_params->dp_mmap == NULL)
return -1;
return (*sc->sc_da.da_params->dp_mmap)(sc, offset, prot);
}
}
static int
drmfb_genfb_enable_polling(void *cookie)
{
struct genfb_softc *const genfb = cookie;
struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
sc_genfb);
return drm_fb_helper_debug_enter_fb(sc->sc_da.da_fb_helper);
}
static int
drmfb_genfb_disable_polling(void *cookie)
{
struct genfb_softc *const genfb = cookie;
struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
sc_genfb);
return drm_fb_helper_debug_leave_fb(sc->sc_da.da_fb_helper);
}
static bool
drmfb_genfb_setmode(struct genfb_softc *genfb, int mode)
{
struct drmfb_softc *sc = container_of(genfb, struct drmfb_softc,
sc_genfb);
if (mode == WSDISPLAYIO_MODE_EMUL)
drm_fb_helper_set_config(sc->sc_da.da_fb_helper);
return true;
}
bool
drmfb_shutdown(struct drmfb_softc *sc, int flags __unused)
{
genfb_enable_polling(sc->sc_da.da_dev);
return true;
}
--- src/sys/external/bsd/drm2/drm/files.drmkms 2015/03/05 17:42:48 1.10
+++ src/sys/external/bsd/drm2/drm/files.drmkms 2015/03/05 17:50:41 1.11
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | # $NetBSD: files.drmkms,v 1.10 2015/03/05 17:42:48 riastradh Exp $ | 1 | # $NetBSD: files.drmkms,v 1.11 2015/03/05 17:50:41 riastradh Exp $ | |
2 | 2 | |||
3 | include "external/bsd/drm2/linux/files.drmkms_linux" | 3 | include "external/bsd/drm2/linux/files.drmkms_linux" | |
4 | 4 | |||
5 | # i2c code is not separated out, but it is marked so that it could be | 5 | # i2c code is not separated out, but it is marked so that it could be | |
6 | # if we wanted. Not clear that this provides as much advantage as | 6 | # if we wanted. Not clear that this provides as much advantage as | |
7 | # separating out PCI code, which will be necessary for, e.g., PCIless | 7 | # separating out PCI code, which will be necessary for, e.g., PCIless | |
8 | # ARM SoC graphics drivers. | 8 | # ARM SoC graphics drivers. | |
9 | define drmkms_i2c: drmkms_linux | 9 | define drmkms_i2c: drmkms_linux | |
10 | 10 | |||
11 | define drmkms: drmkms_linux, drmkms_i2c | 11 | define drmkms: drmkms_linux, drmkms_i2c | |
12 | 12 | |||
13 | defflag opt_drmkms.h DRMKMS_DEBUG | 13 | defflag opt_drmkms.h DRMKMS_DEBUG | |
14 | makeoptions drmkms CPPFLAGS+="-I$S/external/bsd/drm2/include" | 14 | makeoptions drmkms CPPFLAGS+="-I$S/external/bsd/drm2/include" | |
@@ -57,14 +57,18 @@ file external/bsd/drm2/dist/drm/drm_plan | @@ -57,14 +57,18 @@ file external/bsd/drm2/dist/drm/drm_plan | |||
57 | #file external/bsd/drm2/dist/drm/drm_prime.c drmkms | 57 | #file external/bsd/drm2/dist/drm/drm_prime.c drmkms | |
58 | file external/bsd/drm2/dist/drm/drm_probe_helper.c drmkms | 58 | file external/bsd/drm2/dist/drm/drm_probe_helper.c drmkms | |
59 | file external/bsd/drm2/dist/drm/drm_rect.c drmkms | 59 | file external/bsd/drm2/dist/drm/drm_rect.c drmkms | |
60 | file external/bsd/drm2/drm/drm_scatter.c drmkms | 60 | file external/bsd/drm2/drm/drm_scatter.c drmkms | |
61 | file external/bsd/drm2/dist/drm/drm_stub.c drmkms | 61 | file external/bsd/drm2/dist/drm/drm_stub.c drmkms | |
62 | file external/bsd/drm2/drm/drm_sysfs.c drmkms | 62 | file external/bsd/drm2/drm/drm_sysfs.c drmkms | |
63 | file external/bsd/drm2/drm/drm_vm.c drmkms | 63 | file external/bsd/drm2/drm/drm_vm.c drmkms | |
64 | file external/bsd/drm2/drm/drm_vma_manager.c drmkms | 64 | file external/bsd/drm2/drm/drm_vma_manager.c drmkms | |
65 | 65 | |||
66 | file external/bsd/drm2/drm/drm_gem_vm.c drmkms | 66 | file external/bsd/drm2/drm/drm_gem_vm.c drmkms | |
67 | file external/bsd/drm2/drm/drm_module.c drmkms | 67 | file external/bsd/drm2/drm/drm_module.c drmkms | |
68 | file external/bsd/drm2/drm/drm_sysctl.c drmkms | 68 | file external/bsd/drm2/drm/drm_sysctl.c drmkms | |
69 | 69 | |||
70 | # Generic, unaccelerated drm-based framebuffer. | |||
71 | define drmfb: genfb | |||
72 | file external/bsd/drm2/drm/drmfb.c drmfb | |||
73 | ||||
70 | include "external/bsd/drm2/ttm/files.ttm" | 74 | include "external/bsd/drm2/ttm/files.ttm" |
--- src/sys/external/bsd/drm2/i915drm/files.i915drmkms 2014/11/14 14:32:49 1.9
+++ src/sys/external/bsd/drm2/i915drm/files.i915drmkms 2015/03/05 17:50:41 1.10
@@ -1,20 +1,20 @@ | @@ -1,20 +1,20 @@ | |||
1 | # $NetBSD: files.i915drmkms,v 1.9 2014/11/14 14:32:49 joerg Exp $ | 1 | # $NetBSD: files.i915drmkms,v 1.10 2015/03/05 17:50:41 riastradh Exp $ | |
2 | 2 | |||
3 | define intelfbbus { } | 3 | define intelfbbus { } | |
4 | device i915drmkms: drmkms, drmkms_pci, intelfbbus, agp_i810 | 4 | device i915drmkms: drmkms, drmkms_pci, intelfbbus, agp_i810 | |
5 | attach i915drmkms at pci | 5 | attach i915drmkms at pci | |
6 | 6 | |||
7 | device intelfb: intelfbbus, genfb, wsemuldisplaydev | 7 | device intelfb: intelfbbus, drmfb, drmfb_pci, wsemuldisplaydev | |
8 | attach intelfb at intelfbbus | 8 | attach intelfb at intelfbbus | |
9 | 9 | |||
10 | makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/dist/drm/i915" | 10 | makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/dist/drm/i915" | |
11 | makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/i915drm" | 11 | makeoptions i915drmkms CPPFLAGS+="-I$S/external/bsd/drm2/i915drm" | |
12 | 12 | |||
13 | makeoptions i915drmkms "CWARNFLAGS.i915_drv.c"+="${${ACTIVE_CC} == gcc:? -Wno-override-init :}" | 13 | makeoptions i915drmkms "CWARNFLAGS.i915_drv.c"+="${${ACTIVE_CC} == gcc:? -Wno-override-init :}" | |
14 | makeoptions i915drmkms "CWARNFLAGS.i915_drv.c"+="${${ACTIVE_CC} == clang:? -Wno-initializer-overrides :}" | 14 | makeoptions i915drmkms "CWARNFLAGS.i915_drv.c"+="${${ACTIVE_CC} == clang:? -Wno-initializer-overrides :}" | |
15 | makeoptions i915drmkms "CWARNFLAGS.intel_display.c"+="-Wno-shadow -Wno-conversion" | 15 | makeoptions i915drmkms "CWARNFLAGS.intel_display.c"+="-Wno-shadow -Wno-conversion" | |
16 | makeoptions i915drmkms "CWARNFLAGS.intel_panel.c"+="-Wno-shadow" | 16 | makeoptions i915drmkms "CWARNFLAGS.intel_panel.c"+="-Wno-shadow" | |
17 | makeoptions i915drmkms "CWARNFLAGS.intel_pm.c"+="-Wno-shadow" | 17 | makeoptions i915drmkms "CWARNFLAGS.intel_pm.c"+="-Wno-shadow" | |
18 | 18 | |||
19 | # XXX x86 kludge. | 19 | # XXX x86 kludge. | |
20 | makeoptions i915drmkms CPPFLAGS+="-DCONFIG_DRM_I915_FBDEV" | 20 | makeoptions i915drmkms CPPFLAGS+="-DCONFIG_DRM_I915_FBDEV" |
--- src/sys/external/bsd/drm2/i915drm/intelfb.c 2014/09/14 16:02:15 1.10
+++ src/sys/external/bsd/drm2/i915drm/intelfb.c 2015/03/05 17:50:41 1.11
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: intelfb.c,v 1.10 2014/09/14 16:02:15 riastradh Exp $ */ | 1 | /* $NetBSD: intelfb.c,v 1.11 2015/03/05 17:50:41 riastradh Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Taylor R. Campbell. | 8 | * by Taylor R. Campbell. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -20,91 +20,84 @@ | @@ -20,91 +20,84 @@ | |||
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: intelfb.c,v 1.10 2014/09/14 16:02:15 riastradh Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: intelfb.c,v 1.11 2015/03/05 17:50:41 riastradh Exp $"); | |
34 | 34 | |||
35 | #ifdef _KERNEL_OPT | 35 | #ifdef _KERNEL_OPT | |
36 | #include "vga.h" | 36 | #include "vga.h" | |
37 | #endif | 37 | #endif | |
38 | 38 | |||
39 | #include <sys/types.h> | 39 | #include <sys/types.h> | |
40 | #include <sys/bus.h> | 40 | #include <sys/bus.h> | |
41 | #include <sys/device.h> | 41 | #include <sys/device.h> | |
42 | 42 | |||
43 | #include <dev/pci/pciio.h> | |||
44 | #include <dev/pci/pcireg.h> | |||
45 | #include <dev/pci/pcivar.h> | |||
46 | ||||
47 | #include <dev/pci/wsdisplay_pci.h> | |||
48 | #include <dev/wsfb/genfbvar.h> | |||
49 | ||||
50 | #if NVGA > 0 | 43 | #if NVGA > 0 | |
51 | /* | 44 | /* | |
52 | * XXX All we really need is vga_is_console from vgavar.h, but the | 45 | * XXX All we really need is vga_is_console from vgavar.h, but the | |
53 | * header files are missing their own dependencies, so we need to | 46 | * header files are missing their own dependencies, so we need to | |
54 | * explicitly drag in the other crap. | 47 | * explicitly drag in the other crap. | |
55 | */ | 48 | */ | |
56 | #include <dev/ic/mc6845reg.h> | 49 | #include <dev/ic/mc6845reg.h> | |
57 | #include <dev/ic/pcdisplayvar.h> | 50 | #include <dev/ic/pcdisplayvar.h> | |
58 | #include <dev/ic/vgareg.h> | 51 | #include <dev/ic/vgareg.h> | |
59 | #include <dev/ic/vgavar.h> | 52 | #include <dev/ic/vgavar.h> | |
60 | #endif | 53 | #endif | |
61 | 54 | |||
62 | #include <drm/drmP.h> | 55 | #include <drm/drmP.h> | |
63 | #include <drm/drm_fb_helper.h> | 56 | #include <drm/drmfb.h> | |
57 | #include <drm/drmfb_pci.h> | |||
64 | 58 | |||
65 | #include "i915_drv.h" | 59 | #include "i915_drv.h" | |
66 | #include "i915_pci.h" | 60 | #include "i915_pci.h" | |
67 | #include "intelfb.h" | 61 | #include "intelfb.h" | |
68 | 62 | |||
63 | static int intelfb_match(device_t, cfdata_t, void *); | |||
64 | static void intelfb_attach(device_t, device_t, void *); | |||
65 | static int intelfb_detach(device_t, int); | |||
66 | ||||
67 | static void intelfb_attach_task(struct i915drmkms_task *); | |||
68 | ||||
69 | static bool intel_is_vga_console(struct drm_device *); | |||
70 | static bool intelfb_shutdown(device_t, int); | |||
71 | ||||
72 | static paddr_t intelfb_drmfb_mmapfb(struct drmfb_softc *, off_t, int); | |||
73 | ||||
69 | struct intelfb_softc { | 74 | struct intelfb_softc { | |
70 | /* XXX genfb requires the genfb_softc to be first. */ | 75 | struct drmfb_softc sc_drmfb; /* XXX Must be first. */ | |
71 | struct genfb_softc sc_genfb; | |||
72 | device_t sc_dev; | 76 | device_t sc_dev; | |
73 | struct intelfb_attach_args sc_ifa; | 77 | struct intelfb_attach_args sc_ifa; | |
74 | bus_space_handle_t sc_fb_bsh; | 78 | bus_space_handle_t sc_fb_bsh; | |
75 | struct i915drmkms_task sc_setconfig_task; | 79 | struct i915drmkms_task sc_attach_task; | |
76 | bool sc_mapped:1; | 80 | bool sc_mapped:1; | |
77 | bool sc_scheduled:1; | 81 | bool sc_scheduled:1; | |
78 | bool sc_attached:1; | 82 | bool sc_attached:1; | |
79 | }; | 83 | }; | |
80 | 84 | |||
81 | static int intelfb_match(device_t, cfdata_t, void *); | 85 | static const struct drmfb_params intelfb_drmfb_params = { | |
82 | static void intelfb_attach(device_t, device_t, void *); | 86 | .dp_mmapfb = intelfb_drmfb_mmapfb, | |
83 | static int intelfb_detach(device_t, int); | 87 | .dp_mmap = drmfb_pci_mmap, | |
84 | 88 | .dp_ioctl = drmfb_pci_ioctl, | ||
85 | static void intelfb_setconfig_task(struct i915drmkms_task *); | 89 | .dp_is_vga_console = intel_is_vga_console, | |
86 | 90 | .dp_disable_vga = i915_disable_vga, | ||
87 | static int intelfb_genfb_dpms(struct drm_device *, int); | |||
88 | static int intelfb_genfb_ioctl(void *, void *, unsigned long, void *, | |||
89 | int, struct lwp *); | |||
90 | static paddr_t intelfb_genfb_mmap(void *, void *, off_t, int); | |||
91 | static int intelfb_genfb_enable_polling(void *); | |||
92 | static int intelfb_genfb_disable_polling(void *); | |||
93 | static bool intelfb_genfb_shutdown(device_t, int); | |||
94 | static bool intelfb_genfb_setmode(struct genfb_softc *, int); | |||
95 | ||||
96 | static const struct genfb_mode_callback intelfb_genfb_mode_callback = { | |||
97 | .gmc_setmode = intelfb_genfb_setmode, | |||
98 | }; | 91 | }; | |
99 | 92 | |||
100 | CFATTACH_DECL_NEW(intelfb, sizeof(struct intelfb_softc), | 93 | CFATTACH_DECL_NEW(intelfb, sizeof(struct intelfb_softc), | |
101 | intelfb_match, intelfb_attach, intelfb_detach, NULL); | 94 | intelfb_match, intelfb_attach, intelfb_detach, NULL); | |
102 | 95 | |||
103 | static int | 96 | static int | |
104 | intelfb_match(device_t parent, cfdata_t match, void *aux) | 97 | intelfb_match(device_t parent, cfdata_t match, void *aux) | |
105 | { | 98 | { | |
106 | 99 | |||
107 | return 1; | 100 | return 1; | |
108 | } | 101 | } | |
109 | 102 | |||
110 | static void | 103 | static void | |
@@ -116,327 +109,135 @@ intelfb_attach(device_t parent, device_t | @@ -116,327 +109,135 @@ intelfb_attach(device_t parent, device_t | |||
116 | 109 | |||
117 | sc->sc_dev = self; | 110 | sc->sc_dev = self; | |
118 | sc->sc_ifa = *ifa; | 111 | sc->sc_ifa = *ifa; | |
119 | sc->sc_mapped = false; | 112 | sc->sc_mapped = false; | |
120 | sc->sc_scheduled = false; | 113 | sc->sc_scheduled = false; | |
121 | sc->sc_attached = false; | 114 | sc->sc_attached = false; | |
122 | 115 | |||
123 | aprint_naive("\n"); | 116 | aprint_naive("\n"); | |
124 | aprint_normal("\n"); | 117 | aprint_normal("\n"); | |
125 | 118 | |||
126 | /* XXX Defer this too? */ | 119 | /* XXX Defer this too? */ | |
127 | error = bus_space_map(ifa->ifa_fb_bst, ifa->ifa_fb_addr, | 120 | error = bus_space_map(ifa->ifa_fb_bst, ifa->ifa_fb_addr, | |
128 | ifa->ifa_fb_size, | 121 | ifa->ifa_fb_size, | |
129 | (BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE), | 122 | BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE, | |
130 | &sc->sc_fb_bsh); | 123 | &sc->sc_fb_bsh); | |
131 | if (error) { | 124 | if (error) { | |
132 | aprint_error_dev(self, "unable to map framebuffer: %d\n", | 125 | aprint_error_dev(self, "unable to map framebuffer: %d\n", | |
133 | error); | 126 | error); | |
134 | goto fail0; | 127 | goto fail0; | |
135 | } | 128 | } | |
136 | sc->sc_mapped = true; | 129 | sc->sc_mapped = true; | |
137 | 130 | |||
138 | i915drmkms_task_init(&sc->sc_setconfig_task, &intelfb_setconfig_task); | 131 | i915drmkms_task_init(&sc->sc_attach_task, &intelfb_attach_task); | |
139 | error = i915drmkms_task_schedule(parent, &sc->sc_setconfig_task); | 132 | error = i915drmkms_task_schedule(parent, &sc->sc_attach_task); | |
140 | if (error) { | 133 | if (error) { | |
141 | aprint_error_dev(self, "failed to schedule mode set: %d\n", | 134 | aprint_error_dev(self, "failed to schedule mode set: %d\n", | |
142 | error); | 135 | error); | |
143 | goto fail1; | 136 | goto fail1; | |
144 | } | 137 | } | |
145 | sc->sc_scheduled = true; | 138 | sc->sc_scheduled = true; | |
146 | 139 | |||
147 | /* Success! */ | 140 | /* Success! */ | |
148 | return; | 141 | return; | |
149 | 142 | |||
150 | fail1: bus_space_unmap(ifa->ifa_fb_bst, sc->sc_fb_bsh, ifa->ifa_fb_size); | 143 | fail1: bus_space_unmap(ifa->ifa_fb_bst, sc->sc_fb_bsh, ifa->ifa_fb_size); | |
151 | sc->sc_mapped = false; | 144 | sc->sc_mapped = false; | |
152 | fail0: return; | 145 | fail0: return; | |
153 | } | 146 | } | |
154 | 147 | |||
155 | static int | 148 | static int | |
156 | intelfb_detach(device_t self, int flags) | 149 | intelfb_detach(device_t self, int flags) | |
157 | { | 150 | { | |
158 | struct intelfb_softc *const sc = device_private(self); | 151 | struct intelfb_softc *const sc = device_private(self); | |
152 | int error; | |||
159 | 153 | |||
160 | if (sc->sc_scheduled) | 154 | if (sc->sc_scheduled) | |
161 | return EBUSY; | 155 | return EBUSY; | |
162 | 156 | |||
163 | if (sc->sc_attached) { | 157 | if (sc->sc_attached) { | |
164 | /* XXX genfb detach? Help? */ | 158 | pmf_device_deregister(self); | |
159 | error = drmfb_detach(&sc->sc_drmfb, flags); | |||
160 | if (error) { | |||
161 | /* XXX Ugh. */ | |||
162 | (void)pmf_device_register1(self, NULL, NULL, | |||
163 | &intelfb_shutdown); | |||
164 | return error; | |||
165 | } | |||
165 | sc->sc_attached = false; | 166 | sc->sc_attached = false; | |
166 | } | 167 | } | |
167 | 168 | |||
168 | if (sc->sc_mapped) { | 169 | if (sc->sc_mapped) { | |
169 | bus_space_unmap(sc->sc_ifa.ifa_fb_bst, sc->sc_fb_bsh, | 170 | bus_space_unmap(sc->sc_ifa.ifa_fb_bst, sc->sc_fb_bsh, | |
170 | sc->sc_ifa.ifa_fb_size); | 171 | sc->sc_ifa.ifa_fb_size); | |
171 | sc->sc_mapped = false; | 172 | sc->sc_mapped = false; | |
172 | } | 173 | } | |
173 | 174 | |||
174 | return 0; | 175 | return 0; | |
175 | } | 176 | } | |
176 | 177 | |||
177 | static void | 178 | static void | |
178 | intelfb_setconfig_task(struct i915drmkms_task *task) | 179 | intelfb_attach_task(struct i915drmkms_task *task) | |
179 | { | 180 | { | |
180 | struct intelfb_softc *const sc = container_of(task, | 181 | struct intelfb_softc *const sc = container_of(task, | |
181 | struct intelfb_softc, sc_setconfig_task); | 182 | struct intelfb_softc, sc_attach_task); | |
182 | const prop_dictionary_t dict = device_properties(sc->sc_dev); | |||
183 | const struct intelfb_attach_args *const ifa = &sc->sc_ifa; | 183 | const struct intelfb_attach_args *const ifa = &sc->sc_ifa; | |
184 | const struct drm_fb_helper_surface_size *const sizes = | 184 | const struct drmfb_attach_args da = { | |
185 | &ifa->ifa_fb_sizes; | 185 | .da_dev = sc->sc_dev, | |
186 | #if NVGA > 0 /* XXX no workie for modules */ | 186 | .da_fb_helper = ifa->ifa_fb_helper, | |
187 | struct drm_device *const dev = sc->sc_ifa.ifa_drm_dev; | 187 | .da_fb_sizes = &ifa->ifa_fb_sizes, | |
188 | #endif | 188 | .da_fb_vaddr = bus_space_vaddr(ifa->ifa_fb_bst, sc->sc_fb_bsh), | |
189 | enum { CONS_VGA, CONS_GENFB, CONS_NONE } what_was_cons; | 189 | .da_params = &intelfb_drmfb_params, | |
190 | static const struct genfb_ops zero_genfb_ops; | 190 | }; | |
191 | struct genfb_ops genfb_ops = zero_genfb_ops; | |||
192 | int error; | 191 | int error; | |
193 | 192 | |||
194 | KASSERT(sc->sc_scheduled); | 193 | error = drmfb_attach(&sc->sc_drmfb, &da); | |
195 | ||||
196 | if (ifa->ifa_fb_zero) | |||
197 | bus_space_set_region_1(sc->sc_ifa.ifa_fb_bst, sc->sc_fb_bsh, 0, | |||
198 | 0, sc->sc_ifa.ifa_fb_size); | |||
199 | ||||
200 | /* XXX Ugh... Pass these parameters some other way! */ | |||
201 | prop_dictionary_set_uint32(dict, "width", sizes->surface_width); | |||
202 | prop_dictionary_set_uint32(dict, "height", sizes->surface_height); | |||
203 | prop_dictionary_set_uint8(dict, "depth", sizes->surface_bpp); | |||
204 | prop_dictionary_set_uint16(dict, "linebytes", | |||
205 | roundup2((sizes->surface_width * howmany(sizes->surface_bpp, 8)), | |||
206 | 64)); | |||
207 | prop_dictionary_set_uint32(dict, "address", 0); /* XXX >32-bit */ | |||
208 | CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t)); | |||
209 | prop_dictionary_set_uint64(dict, "virtual_address", | |||
210 | (uint64_t)(uintptr_t)bus_space_vaddr(sc->sc_ifa.ifa_fb_bst, | |||
211 | sc->sc_fb_bsh)); | |||
212 | ||||
213 | prop_dictionary_set_uint64(dict, "mode_callback", | |||
214 | (uint64_t)(uintptr_t)&intelfb_genfb_mode_callback); | |||
215 | ||||
216 | /* XXX Whattakludge! */ | |||
217 | #if NVGA > 0 | |||
218 | if (vga_is_console(dev->pdev->pd_pa.pa_iot, -1)) { | |||
219 | what_was_cons = CONS_VGA; | |||
220 | prop_dictionary_set_bool(dict, "is_console", true); | |||
221 | vga_cndetach(); | |||
222 | i915_disable_vga(dev); | |||
223 | } else | |||
224 | #endif | |||
225 | if (genfb_is_console() && genfb_is_enabled()) { | |||
226 | what_was_cons = CONS_GENFB; | |||
227 | prop_dictionary_set_bool(dict, "is_console", true); | |||
228 | } else { | |||
229 | what_was_cons = CONS_NONE; | |||
230 | prop_dictionary_set_bool(dict, "is_console", false); | |||
231 | } | |||
232 | ||||
233 | sc->sc_genfb.sc_dev = sc->sc_dev; | |||
234 | genfb_init(&sc->sc_genfb); | |||
235 | genfb_ops.genfb_ioctl = intelfb_genfb_ioctl; | |||
236 | genfb_ops.genfb_mmap = intelfb_genfb_mmap; | |||
237 | genfb_ops.genfb_enable_polling = intelfb_genfb_enable_polling; | |||
238 | genfb_ops.genfb_disable_polling = intelfb_genfb_disable_polling; | |||
239 | ||||
240 | error = genfb_attach(&sc->sc_genfb, &genfb_ops); | |||
241 | if (error) { | 194 | if (error) { | |
242 | aprint_error_dev(sc->sc_dev, "failed to attach genfb: %d\n", | 195 | aprint_error_dev(sc->sc_dev, "failed to attach drmfb: %d\n", | |
243 | error); | 196 | error); | |
244 | goto fail0; | 197 | return; | |
245 | } | 198 | } | |
246 | sc->sc_attached = true; | |||
247 | ||||
248 | pmf_device_register1(sc->sc_dev, NULL, NULL, | |||
249 | intelfb_genfb_shutdown); | |||
250 | 199 | |||
251 | /* Success! */ | 200 | if (pmf_device_register1(sc->sc_dev, NULL, NULL, &intelfb_shutdown)) | |
252 | sc->sc_scheduled = false; | 201 | aprint_error_dev(sc->sc_dev, | |
253 | return; | 202 | "failed to register shutdown handler\n"); | |
254 | 203 | |||
255 | fail0: /* XXX Restore console... */ | 204 | sc->sc_attached = true; | |
256 | switch (what_was_cons) { | |||
257 | case CONS_VGA: | |||
258 | break; | |||
259 | case CONS_GENFB: | |||
260 | break; | |||
261 | case CONS_NONE: | |||
262 | break; | |||
263 | default: | |||
264 | break; | |||
265 | } | |||
266 | } | 205 | } | |
267 | 206 | |||
268 | static int | 207 | static bool | |
269 | intelfb_genfb_dpms(struct drm_device *dev, int dpms_mode) | 208 | intel_is_vga_console(struct drm_device *dev) | |
270 | { | 209 | { | |
271 | struct drm_i915_private *const dev_priv = dev->dev_private; | |||
272 | /* XXX What guarantees dev_priv->fbdev stays around? */ | |||
273 | struct drm_fb_helper *const fb_helper = &dev_priv->fbdev->helper; | |||
274 | unsigned i; | |||
275 | ||||
276 | drm_modeset_lock_all(dev); | |||
277 | for (i = 0; i < fb_helper->connector_count; i++) { | |||
278 | struct drm_connector *const connector = | |||
279 | fb_helper->connector_info[i]->connector; | |||
280 | (*connector->funcs->dpms)(connector, dpms_mode); | |||
281 | drm_object_property_set_value(&connector->base, | |||
282 | dev->mode_config.dpms_property, dpms_mode); | |||
283 | } | |||
284 | drm_modeset_unlock_all(dev); | |||
285 | 210 | |||
286 | return 0; | 211 | #if NVGA > 0 | |
212 | return vga_is_console(dev->pdev->pd_pa.pa_iot, -1); | |||
213 | #else | |||
214 | return false; | |||
215 | #endif | |||
287 | } | 216 | } | |
288 | 217 | |||
289 | static int | 218 | static bool | |
290 | intelfb_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag, | 219 | intelfb_shutdown(device_t self, int flags) | |
291 | struct lwp *l) | |||
292 | { | 220 | { | |
293 | struct genfb_softc *const genfb = v; | 221 | struct intelfb_softc *const sc = device_private(self); | |
294 | struct intelfb_softc *const sc = container_of(genfb, | |||
295 | struct intelfb_softc, sc_genfb); | |||
296 | struct drm_device *const dev = sc->sc_ifa.ifa_fb_helper->dev; | |||
297 | const struct pci_attach_args *const pa = &dev->pdev->pd_pa; | |||
298 | ||||
299 | switch (cmd) { | |||
300 | case WSDISPLAYIO_GTYPE: | |||
301 | *(unsigned int *)data = WSDISPLAY_TYPE_PCIVGA; | |||
302 | return 0; | |||
303 | ||||
304 | /* PCI config read/write passthrough. */ | |||
305 | case PCI_IOC_CFGREAD: | |||
306 | case PCI_IOC_CFGWRITE: | |||
307 | return pci_devioctl(pa->pa_pc, pa->pa_tag, cmd, data, flag, l); | |||
308 | ||||
309 | case WSDISPLAYIO_GET_BUSID: | |||
310 | return wsdisplayio_busid_pci(dev->dev, pa->pa_pc, pa->pa_tag, | |||
311 | data); | |||
312 | ||||
313 | /* | |||
314 | * Screen blanking ioctls. Not to be confused with backlight | |||
315 | * (can be disabled while stuff is still drawn on the screen), | |||
316 | * brightness, or contrast (which we don't support). Backlight | |||
317 | * and brightness are done through WSDISPLAYIO_{GET,SET}PARAM. | |||
318 | * This toggles between DPMS ON and DPMS OFF; backlight toggles | |||
319 | * between DPMS ON and DPMS SUSPEND. | |||
320 | */ | |||
321 | case WSDISPLAYIO_GVIDEO: { | |||
322 | int *onp = (int *)data; | |||
323 | ||||
324 | /* XXX Can't really determine a single answer here. */ | |||
325 | *onp = 1; | |||
326 | return 0; | |||
327 | } | |||
328 | ||||
329 | case WSDISPLAYIO_SVIDEO: { | |||
330 | const int on = *(const int *)data; | |||
331 | ||||
332 | return intelfb_genfb_dpms(dev, | |||
333 | on? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); | |||
334 | } | |||
335 | 222 | |||
336 | default: | 223 | return drmfb_shutdown(&sc->sc_drmfb, flags); | |
337 | return EPASSTHROUGH; | |||
338 | } | |||
339 | } | 224 | } | |
340 | 225 | |||
341 | static paddr_t | 226 | static paddr_t | |
342 | intelfb_genfb_mmap(void *v, void *vs, off_t offset, int prot) | 227 | intelfb_drmfb_mmapfb(struct drmfb_softc *drmfb, off_t offset, int prot) | |
343 | { | 228 | { | |
344 | struct genfb_softc *const genfb = v; | 229 | struct intelfb_softc *const sc = container_of(drmfb, | |
345 | struct intelfb_softc *const sc = container_of(genfb, | 230 | struct intelfb_softc, sc_drmfb); | |
346 | struct intelfb_softc, sc_genfb); | |||
347 | struct drm_fb_helper *const helper = sc->sc_ifa.ifa_fb_helper; | 231 | struct drm_fb_helper *const helper = sc->sc_ifa.ifa_fb_helper; | |
348 | struct intel_fbdev *const fbdev = container_of(helper, | 232 | struct intel_fbdev *const fbdev = container_of(helper, | |
349 | struct intel_fbdev, helper); | 233 | struct intel_fbdev, helper); | |
350 | struct drm_device *const dev = helper->dev; | 234 | struct drm_device *const dev = helper->dev; | |
351 | struct drm_i915_private *const dev_priv = dev->dev_private; | 235 | struct drm_i915_private *const dev_priv = dev->dev_private; | |
352 | const struct pci_attach_args *const pa = &dev->pdev->pd_pa; | |||
353 | unsigned int i; | |||
354 | ||||
355 | if (offset < 0) | |||
356 | return -1; | |||
357 | ||||
358 | /* Treat low memory as the framebuffer itself. */ | |||
359 | if (offset < genfb->sc_fbsize) | |||
360 | return bus_space_mmap(dev->bst, | |||
361 | (dev_priv->gtt.mappable_base + | |||
362 | i915_gem_obj_ggtt_offset(fbdev->fb->obj)), | |||
363 | offset, prot, | |||
364 | (BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE)); | |||
365 | ||||
366 | /* XXX Cargo-culted from genfb_pci. */ | |||
367 | if (kauth_authorize_machdep(kauth_cred_get(), | |||
368 | KAUTH_MACHDEP_UNMANAGEDMEM, NULL, NULL, NULL, NULL) != 0) { | |||
369 | aprint_normal_dev(dev->dev, "mmap at %"PRIxMAX" rejected\n", | |||
370 | (uintmax_t)offset); | |||
371 | return -1; | |||
372 | } | |||
373 | ||||
374 | for (i = 0; PCI_BAR(i) <= PCI_MAPREG_ROM; i++) { | |||
375 | pcireg_t type; | |||
376 | bus_addr_t addr; | |||
377 | bus_size_t size; | |||
378 | int flags; | |||
379 | ||||
380 | /* Interrogate the BAR. */ | |||
381 | if (!pci_mapreg_probe(pa->pa_pc, pa->pa_tag, PCI_BAR(i), | |||
382 | &type)) | |||
383 | continue; | |||
384 | if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM) | |||
385 | continue; | |||
386 | if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(i), type, | |||
387 | &addr, &size, &flags)) | |||
388 | continue; | |||
389 | ||||
390 | /* Try to map it if it's in range. */ | |||
391 | if ((addr <= offset) && (offset < (addr + size))) | |||
392 | return bus_space_mmap(pa->pa_memt, addr, | |||
393 | (offset - addr), prot, flags); | |||
394 | ||||
395 | /* Skip a slot if this was a 64-bit BAR. */ | |||
396 | if ((PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) && | |||
397 | (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT)) | |||
398 | i += 1; | |||
399 | } | |||
400 | ||||
401 | /* Failure! */ | |||
402 | return -1; | |||
403 | } | |||
404 | 236 | |||
405 | static int | 237 | KASSERT(0 <= offset); | |
406 | intelfb_genfb_enable_polling(void *cookie) | 238 | KASSERT(offset < fbdev->fb->obj->base.size); | |
407 | { | |||
408 | struct genfb_softc *const genfb = cookie; | |||
409 | struct intelfb_softc *const sc = container_of(genfb, | |||
410 | struct intelfb_softc, sc_genfb); | |||
411 | ||||
412 | return drm_fb_helper_debug_enter_fb(sc->sc_ifa.ifa_fb_helper); | |||
413 | } | |||
414 | ||||
415 | static int | |||
416 | intelfb_genfb_disable_polling(void *cookie) | |||
417 | { | |||
418 | struct genfb_softc *const genfb = cookie; | |||
419 | struct intelfb_softc *const sc = container_of(genfb, | |||
420 | struct intelfb_softc, sc_genfb); | |||
421 | ||||
422 | return drm_fb_helper_debug_leave_fb(sc->sc_ifa.ifa_fb_helper); | |||
423 | } | |||
424 | ||||
425 | static bool | |||
426 | intelfb_genfb_shutdown(device_t self, int flags) | |||
427 | { | |||
428 | genfb_enable_polling(self); | |||
429 | return true; | |||
430 | } | |||
431 | ||||
432 | static bool | |||
433 | intelfb_genfb_setmode(struct genfb_softc *genfb, int mode) | |||
434 | { | |||
435 | struct intelfb_softc *sc = (struct intelfb_softc *)genfb; | |||
436 | ||||
437 | if (mode == WSDISPLAYIO_MODE_EMUL) { | |||
438 | drm_fb_helper_set_config(sc->sc_ifa.ifa_fb_helper); | |||
439 | } | |||
440 | 239 | |||
441 | return true; | 240 | return bus_space_mmap(dev->bst, dev_priv->gtt.mappable_base, | |
241 | i915_gem_obj_ggtt_offset(fbdev->fb->obj) + offset, | |||
242 | prot, BUS_SPACE_MAP_PREFETCHABLE); | |||
442 | } | 243 | } |
/* $NetBSD: drmfb.h,v 1.1 2015/03/05 17:50:41 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 _DRM_DRMFB_H_
#define _DRM_DRMFB_H_
#include <sys/device_if.h>
#include <dev/wsfb/genfbvar.h>
struct drm_fb_helper;
struct drm_fb_helper_surface_sizes;
struct drmfb_attach_args;
struct drmfb_params;
struct drmfb_softc;
struct drmfb_params {
/*
* Framebuffer mmap.
*/
paddr_t (*dp_mmapfb)(struct drmfb_softc *, off_t, int);
/*
* Other mmap, e.g. for arbitrary PCI BARs. Available only to
* users with privileges for access to unmanaged memory.
*/
paddr_t (*dp_mmap)(struct drmfb_softc *, off_t, int);
/*
* Ioctl handler. Must handle:
*
* - WSDISPLAYIO_GET_BUSID
* - WSDISPLAYIO_GTYPE
*
* May add or override anything else. Return EPASSTHROUGH to
* defer.
*/
int (*dp_ioctl)(struct drmfb_softc *, unsigned long,
void *, int, struct lwp *);
/* XXX Kludge! */
bool (*dp_is_vga_console)(struct drm_device *);
void (*dp_disable_vga)(struct drm_device *);
};
struct drmfb_attach_args {
device_t da_dev;
struct drm_fb_helper *da_fb_helper;
const struct drm_fb_helper_surface_size *da_fb_sizes;
void *da_fb_vaddr;
const struct drmfb_params *da_params;
};
/* Treat as opaque. Must be first member of device softc. */
struct drmfb_softc {
struct genfb_softc sc_genfb; /* XXX Must be first. */
struct drmfb_attach_args sc_da;
};
int drmfb_attach(struct drmfb_softc *, const struct drmfb_attach_args *);
int drmfb_detach(struct drmfb_softc *, int);
bool drmfb_shutdown(struct drmfb_softc *, int);
#endif /* _DRM_DRMFB_H_ */
/* $NetBSD: drmfb_pci.h,v 1.1 2015/03/05 17:50:41 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 _DRM_DRMFB_PCI_H_
#define _DRM_DRMFB_PCI_H_
#include <sys/types.h>
struct drmfb_softc;
struct lwp;
paddr_t drmfb_pci_mmap(struct drmfb_softc *, off_t, int);
int drmfb_pci_ioctl(struct drmfb_softc *, unsigned long, void *, int,
struct lwp *);
#endif /* _DRM_DRMFB_PCI_H_ */
/* $NetBSD: drmfb_pci.c,v 1.1 2015/03/05 17:50:41 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.
*/
/*
* drmfb_pci: drmfb hooks for PCI devices.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: drmfb_pci.c,v 1.1 2015/03/05 17:50:41 riastradh Exp $");
#include <sys/types.h>
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/systm.h>
#include <dev/pci/pciio.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/wsdisplay_pci.h>
#include <drm/drmP.h>
#include <drm/drm_fb_helper.h>
#include "drmfb.h"
#include "drmfb_pci.h"
/*
* drmfb_pci_mmap: Implementation of drmfb_params::dp_mmap. Don't use
* this for dp_mmapfb -- how to get at the framebuffer is device-
* specific.
*/
paddr_t
drmfb_pci_mmap(struct drmfb_softc *sc, off_t offset, int prot)
{
struct drm_device *const dev = sc->sc_da.da_fb_helper->dev;
const struct pci_attach_args *const pa = &dev->pdev->pd_pa;
unsigned i;
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;
}
/*
* drmfb_pci_ioctl: Implementation of drmfb_params::dp_ioctl. Provides:
*
* - WSDISPLAY_GET_BUSID
* - WSDISPLAY_GTYPE
*
* Additionally allows access to PCI registers.
*
* XXX Do we need to provide access to PCI registers? I can't find
* anything that uses this functionality, and as is it is very
* dangerous.
*/
int
drmfb_pci_ioctl(struct drmfb_softc *sc, unsigned long cmd, void *data,
int flag, struct lwp *l)
{
struct drm_device *const dev = sc->sc_da.da_fb_helper->dev;
struct pci_attach_args *const pa = &dev->pdev->pd_pa;
switch (cmd) {
/* 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);
/* PCI-specific wsdisplay ioctls. */
case WSDISPLAYIO_GET_BUSID:
return wsdisplayio_busid_pci(dev->dev, pa->pa_pc, pa->pa_tag,
data);
case WSDISPLAYIO_GTYPE:
*(unsigned int *)data = WSDISPLAY_TYPE_PCIVGA;
return 0;
default:
return EPASSTHROUGH;
}
}
--- src/sys/external/bsd/drm2/pci/files.drmkms_pci 2014/08/06 13:54:40 1.4
+++ src/sys/external/bsd/drm2/pci/files.drmkms_pci 2015/03/05 17:50:41 1.5
@@ -1,16 +1,19 @@ | @@ -1,16 +1,19 @@ | |||
1 | # $NetBSD: files.drmkms_pci,v 1.4 2014/08/06 13:54:40 riastradh Exp $ | 1 | # $NetBSD: files.drmkms_pci,v 1.5 2015/03/05 17:50:41 riastradh Exp $ | |
2 | 2 | |||
3 | define drmkms_pci: drmkms | 3 | define drmkms_pci: drmkms | |
4 | 4 | |||
5 | # XXX Not quite right! Should AGP stuff be kept separate? | 5 | # XXX Not quite right! Should AGP stuff be kept separate? | |
6 | makeoptions drmkms_pci CPPFLAGS+="-DCONFIG_AGP" | 6 | makeoptions drmkms_pci CPPFLAGS+="-DCONFIG_AGP" | |
7 | 7 | |||
8 | #file external/bsd/drm2/dist/drm/ati_pcigart.c drmkms_pci | 8 | #file external/bsd/drm2/dist/drm/ati_pcigart.c drmkms_pci | |
9 | file external/bsd/drm2/dist/drm/drm_agpsupport.c drmkms_pci | 9 | file external/bsd/drm2/dist/drm/drm_agpsupport.c drmkms_pci | |
10 | file external/bsd/drm2/pci/drm_pci.c drmkms_pci | 10 | file external/bsd/drm2/pci/drm_pci.c drmkms_pci | |
11 | file external/bsd/drm2/pci/drm_pci_module.c drmkms_pci | 11 | file external/bsd/drm2/pci/drm_pci_module.c drmkms_pci | |
12 | 12 | |||
13 | define drmfb_pci: drmfb, drmkms_pci | |||
14 | file external/bsd/drm2/pci/drmfb_pci.c drmfb_pci | |||
15 | ||||
13 | include "external/bsd/drm2/i915drm/files.i915drmkms" | 16 | include "external/bsd/drm2/i915drm/files.i915drmkms" | |
14 | include "external/bsd/drm2/radeon/files.radeon" | 17 | include "external/bsd/drm2/radeon/files.radeon" | |
15 | include "external/bsd/drm2/nouveau/files.nouveau" | 18 | include "external/bsd/drm2/nouveau/files.nouveau" | |
16 | #... | 19 | #... |
--- src/sys/modules/drmkms/Makefile 2015/03/05 17:42:48 1.8
+++ src/sys/modules/drmkms/Makefile 2015/03/05 17:50:41 1.9
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | # $NetBSD: Makefile,v 1.8 2015/03/05 17:42:48 riastradh Exp $ | 1 | # $NetBSD: Makefile,v 1.9 2015/03/05 17:50:41 riastradh Exp $ | |
2 | 2 | |||
3 | .include "../Makefile.inc" | 3 | .include "../Makefile.inc" | |
4 | .include "Makefile.inc" | 4 | .include "Makefile.inc" | |
5 | 5 | |||
6 | .PATH: ${S}/external/bsd/drm2/drm | 6 | .PATH: ${S}/external/bsd/drm2/drm | |
7 | .PATH: ${S}/external/bsd/drm2/i2c | 7 | .PATH: ${S}/external/bsd/drm2/i2c | |
8 | .PATH: ${S}/external/bsd/drm2/pci | 8 | .PATH: ${S}/external/bsd/drm2/pci | |
9 | .PATH: ${S}/external/bsd/drm2/dist/drm | 9 | .PATH: ${S}/external/bsd/drm2/dist/drm | |
10 | 10 | |||
11 | MKLDSCRIPT=yes | 11 | MKLDSCRIPT=yes | |
12 | KMOD= drmkms | 12 | KMOD= drmkms | |
13 | 13 | |||
14 | # Upstream source files. | 14 | # Upstream source files. | |
@@ -46,21 +46,22 @@ SRCS+= drm_plane_helper.c | @@ -46,21 +46,22 @@ SRCS+= drm_plane_helper.c | |||
46 | #SRCS+= drm_prime.c # XXX Revisit later. | 46 | #SRCS+= drm_prime.c # XXX Revisit later. | |
47 | SRCS+= drm_probe_helper.c | 47 | SRCS+= drm_probe_helper.c | |
48 | SRCS+= drm_rect.c | 48 | SRCS+= drm_rect.c | |
49 | SRCS+= drm_scatter.c | 49 | SRCS+= drm_scatter.c | |
50 | SRCS+= drm_stub.c | 50 | SRCS+= drm_stub.c | |
51 | SRCS+= drm_sysctl.c | 51 | SRCS+= drm_sysctl.c | |
52 | SRCS+= drm_sysfs.c | 52 | SRCS+= drm_sysfs.c | |
53 | SRCS+= drm_vm.c | 53 | SRCS+= drm_vm.c | |
54 | SRCS+= drm_vma_manager.c | 54 | SRCS+= drm_vma_manager.c | |
55 | 55 | |||
56 | # NetBSD additions. | 56 | # NetBSD additions. | |
57 | SRCS+= drm_gem_vm.c | 57 | SRCS+= drm_gem_vm.c | |
58 | SRCS+= drm_module.c | 58 | SRCS+= drm_module.c | |
59 | SRCS+= drmfb.c | |||
59 | 60 | |||
60 | COPTS.drm_crtc.c+= -Wno-shadow | 61 | COPTS.drm_crtc.c+= -Wno-shadow | |
61 | COPTS.drm_crtc.c+= -Wno-missing-field-initializers | 62 | COPTS.drm_crtc.c+= -Wno-missing-field-initializers | |
62 | COPTS.drm_edid.c+= -Wno-shadow | 63 | COPTS.drm_edid.c+= -Wno-shadow | |
63 | 64 | |||
64 | CPPFLAGS+= -DNACPICA=1 | 65 | CPPFLAGS+= -DNACPICA=1 | |
65 | 66 | |||
66 | .include <bsd.kmodule.mk> | 67 | .include <bsd.kmodule.mk> |
--- src/sys/modules/drmkms_pci/Makefile 2014/11/22 19:18:08 1.4
+++ src/sys/modules/drmkms_pci/Makefile 2015/03/05 17:50:41 1.5
@@ -1,16 +1,18 @@ | @@ -1,16 +1,18 @@ | |||
1 | # $NetBSD: Makefile,v 1.4 2014/11/22 19:18:08 riastradh Exp $ | 1 | # $NetBSD: Makefile,v 1.5 2015/03/05 17:50:41 riastradh Exp $ | |
2 | 2 | |||
3 | .include "../Makefile.inc" | 3 | .include "../Makefile.inc" | |
4 | .include "../drmkms/Makefile.inc" | 4 | .include "../drmkms/Makefile.inc" | |
5 | 5 | |||
6 | .PATH: ${S}/external/bsd/drm2/pci | 6 | .PATH: ${S}/external/bsd/drm2/pci | |
7 | .PATH: ${S}/external/bsd/drm2/dist/drm | 7 | .PATH: ${S}/external/bsd/drm2/dist/drm | |
8 | 8 | |||
9 | KMOD= drmkms_pci | 9 | KMOD= drmkms_pci | |
10 | 10 | |||
11 | #SRCS+= ati_pcigart.c # XXX Restore for ATI support. | 11 | #SRCS+= ati_pcigart.c # XXX Restore for ATI support. | |
12 | SRCS+= drm_agpsupport.c | 12 | SRCS+= drm_agpsupport.c | |
13 | SRCS+= drm_pci.c | 13 | SRCS+= drm_pci.c | |
14 | SRCS+= drm_pci_module.c | 14 | SRCS+= drm_pci_module.c | |
15 | 15 | |||
16 | SRCS+= drmfb_pci.c | |||
17 | ||||
16 | .include <bsd.kmodule.mk> | 18 | .include <bsd.kmodule.mk> |