Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/riastradh-drm2]: src/sys/external/bsd/drm2/i915drm First draft of genfb ...



details:   https://anonhg.NetBSD.org/src/rev/44a1a5d6e71d
branches:  riastradh-drm2
changeset: 788570:44a1a5d6e71d
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Sep 08 16:41:07 2013 +0000

description:
First draft of genfb attachment for i915.

diffstat:

 sys/external/bsd/drm2/i915drm/i915_pci.c |  373 ++++++++++++++++++++++++++++++-
 1 files changed, 365 insertions(+), 8 deletions(-)

diffs (truncated from 430 to 300 lines):

diff -r d9fcdf100402 -r 44a1a5d6e71d sys/external/bsd/drm2/i915drm/i915_pci.c
--- a/sys/external/bsd/drm2/i915drm/i915_pci.c  Sun Sep 08 16:40:36 2013 +0000
+++ b/sys/external/bsd/drm2/i915drm/i915_pci.c  Sun Sep 08 16:41:07 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: i915_pci.c,v 1.1.2.3 2013/07/24 03:54:43 riastradh Exp $       */
+/*     $NetBSD: i915_pci.c,v 1.1.2.4 2013/09/08 16:41:07 riastradh Exp $       */
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,27 +30,51 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: i915_pci.c,v 1.1.2.3 2013/07/24 03:54:43 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i915_pci.c,v 1.1.2.4 2013/09/08 16:41:07 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/systm.h>
 
+#include <dev/pci/pciio.h>
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
 
+#if 0                          /* XXX genfb */
+#include <dev/pci/wsdisplay_pci.h>
+#include <dev/wsfb/genfbvar.h>
+#endif
+
 #include <drm/drmP.h>
 
 #include "i915_drv.h"
 
 struct i915drm_softc {
-       struct drm_device       sc_drm_dev;
-       struct pci_dev          sc_pci_dev;
+       device_t                        sc_dev;
+       struct drm_device               sc_drm_dev;
+       struct pci_dev                  sc_pci_dev;
+       struct drm_i915_gem_object      *sc_fb_obj;
+       bus_space_handle_t              sc_fb_bsh;
+#if 0                          /* XXX genfb */
+       struct genfb_softc              sc_genfb;
+#endif
 };
 
 static int     i915drm_match(device_t, cfdata_t, void *);
 static void    i915drm_attach(device_t, device_t, void *);
 static int     i915drm_detach(device_t, int);
 
+static void    i915drm_attach_framebuffer(device_t);
+static int     i915drm_detach_framebuffer(device_t, int);
+
+static int     i915drm_fb_probe(struct drm_fb_helper *,
+                   struct drm_fb_helper_surface_size *);
+
+#if 0                          /* XXX genfb */
+static int     i915drm_genfb_ioctl(void *, void *, unsigned long, void *,
+                   int, struct lwp *);
+static paddr_t i915drm_genfb_mmap(void *, void *, off_t, int);
+#endif
+
 CFATTACH_DECL_NEW(i915drm, sizeof(struct i915drm_softc),
     i915drm_match, i915drm_attach, i915drm_detach, NULL);
 
@@ -115,10 +139,9 @@
 
        KASSERT(info != NULL);
 
-       /* XXX Show more information...  */
-       aprint_naive("\n");
-       aprint_normal(": vendor 0x%04x, device 0x%04x, gen %u\n",
-           PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id), info->gen);
+       sc->sc_dev = self;
+
+       pci_aprint_devinfo(pa, NULL);
 
        /* XXX Whattakludge!  */
        if (info->gen != 3) {
@@ -132,6 +155,8 @@
 
        /* Attach the drm driver.  */
        drm_config_found(self, i915_drm_driver, flags, &sc->sc_drm_dev);
+
+       i915drm_attach_framebuffer(self);
 }
 
 static int
@@ -145,6 +170,10 @@
        if (error)
                return error;
 
+       error = i915drm_detach_framebuffer(self, flags);
+       if (error)
+               return error;
+
        /* drm driver is gone.  We can safely drop drm pci driver state.  */
        error = drm_pci_detach(&sc->sc_drm_dev, flags);
        if (error)
@@ -152,3 +181,331 @@
 
        return 0;
 }
+
+static struct drm_fb_helper_funcs i915drm_fb_helper_funcs = {
+       .gamma_set = &intel_crtc_fb_gamma_set,
+       .gamma_get = &intel_crtc_fb_gamma_get,
+       .fb_probe = &i915drm_fb_probe,
+};
+
+static void
+i915drm_attach_framebuffer(device_t self)
+{
+       struct i915drm_softc *const sc = device_private(self);
+       struct drm_device *const dev = &sc->sc_drm_dev;
+       struct drm_i915_private *const dev_priv = dev->dev_private;
+       int ret;
+
+       aprint_debug_dev(self, "attach framebuffer\n");
+       dev_priv->fbdev = kmem_zalloc(sizeof(*dev_priv->fbdev), KM_SLEEP);
+
+       struct drm_fb_helper *const fb_helper = &dev_priv->fbdev->helper;
+
+       aprint_debug_dev(self, "drm_fb_helper_init\n");
+       fb_helper->funcs = &i915drm_fb_helper_funcs;
+       ret = drm_fb_helper_init(dev, fb_helper, dev_priv->num_pipe,
+           INTELFB_CONN_LIMIT);
+       if (ret) {
+               aprint_error_dev(self, "unable to init drm fb helper: %d\n",
+                   ret);
+               goto fail0;
+       }
+
+       aprint_debug_dev(self, "drm_fb_helper_single_add_all_connectors\n");
+       drm_fb_helper_single_add_all_connectors(fb_helper);
+       aprint_debug_dev(self, "drm_fb_helper_initial_config\n");
+       drm_fb_helper_initial_config(fb_helper, 32 /* XXX ? */);
+
+       /* Success!  */
+       return;
+
+fail0: kmem_free(dev_priv->fbdev, sizeof(*dev_priv->fbdev));
+       dev_priv->fbdev = NULL;
+}
+
+static int
+i915drm_detach_framebuffer(device_t self, int flags)
+{
+       struct i915drm_softc *const sc = device_private(self);
+       struct drm_device *const dev = &sc->sc_drm_dev;
+       struct drm_i915_private *const dev_priv = dev->dev_private;
+       struct intel_fbdev *const fbdev = dev_priv->fbdev;
+
+       if (fbdev != NULL) {
+               struct drm_fb_helper *const fb_helper = &fbdev->helper;
+
+               if (fb_helper->fb != NULL) {
+                       struct drm_i915_gem_object *const obj = sc->sc_fb_obj;
+
+                       /*
+                        * genfb children have already been detached,
+                        * so all we need do is unmap the space and
+                        * clean up the drm structures.
+                        */
+                       bus_space_unmap(dev->bst, sc->sc_fb_bsh,
+                           obj->base.size);
+                       drm_framebuffer_unreference(fb_helper->fb);
+                       fb_helper->fb = NULL;
+                       drm_gem_object_unreference_unlocked(&obj->base);
+                       sc->sc_fb_obj = NULL;
+               }
+
+               KASSERT(sc->sc_fb_obj == NULL);
+               drm_fb_helper_fini(fb_helper);
+               kmem_free(fbdev, sizeof(*fbdev));
+               dev_priv->fbdev = NULL;
+       }
+
+       return 0;
+}
+
+static int
+i915drm_fb_probe(struct drm_fb_helper *fb_helper,
+    struct drm_fb_helper_surface_size *sizes)
+{
+       struct drm_device *const dev = fb_helper->dev;
+       struct drm_i915_private *const dev_priv = dev->dev_private;
+       struct i915drm_softc *const sc = container_of(dev,
+           struct i915drm_softc, sc_drm_dev);
+#if 0                          /* XXX genfb */
+       const prop_dictionary_t dict = device_properties(sc->sc_dev);
+       static const struct genfb_ops zero_genfb_ops;
+       struct genfb_ops genfb_ops = zero_genfb_ops;
+#endif
+       static const struct drm_mode_fb_cmd2 zero_mode_cmd;
+       struct drm_mode_fb_cmd2 mode_cmd = zero_mode_cmd;
+       bus_size_t size;
+       int ret;
+
+       aprint_debug_dev(sc->sc_dev, "probe framebuffer"
+           ": %"PRIu32" by %"PRIu32"\n",
+           sizes->surface_width,
+           sizes->surface_height);
+
+       if (fb_helper->fb != NULL) {
+               aprint_debug_dev(sc->sc_dev, "already have a framebuffer"
+                   ": %p\n", fb_helper->fb);
+               return 0;
+       }
+
+       /*
+        * XXX Cargo-culted from Linux.  Using sizes as an input/output
+        * parameter seems sketchy...
+        */
+       if (sizes->surface_bpp == 24)
+               sizes->surface_bpp = 32;
+
+       mode_cmd.width = sizes->surface_width;
+       mode_cmd.height = sizes->surface_height;
+       KASSERT(sizes->surface_bpp <= (UINT32_MAX - 7));
+       KASSERT(mode_cmd.width <=
+           ((UINT32_MAX / howmany(sizes->surface_bpp, 8)) - 63));
+       mode_cmd.pitches[0] = round_up((mode_cmd.width *
+               howmany(sizes->surface_bpp, 8)), 64);
+       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+           sizes->surface_depth);
+
+       KASSERT(mode_cmd.pitches[0] <=
+           ((__type_max(bus_size_t) / mode_cmd.height) - 63));
+       size = round_up((mode_cmd.pitches[0] * mode_cmd.height), PAGE_SIZE);
+
+       sc->sc_fb_obj = i915_gem_alloc_object(dev, size);
+       if (sc->sc_fb_obj == NULL) {
+               aprint_error_dev(sc->sc_dev, "unable to create framebuffer\n");
+               ret = -ENODEV; /* XXX ? */
+               goto fail0;
+       }
+
+       mutex_lock(&dev->struct_mutex);
+       ret = intel_pin_and_fence_fb_obj(dev, sc->sc_fb_obj, NULL);
+       if (ret) {
+               aprint_error_dev(sc->sc_dev, "unable to pin fb: %d\n", ret);
+               goto fail1;
+       }
+
+       ret = intel_framebuffer_init(dev, &dev_priv->fbdev->ifb, &mode_cmd,
+           sc->sc_fb_obj);
+       if (ret) {
+               aprint_error_dev(sc->sc_dev, "unable to init framebuffer"
+                   ": %d\n", ret);
+               goto fail2;
+       }
+
+       /*
+        * XXX Kludge: The intel_framebuffer abstraction `steals' a
+        * reference to the object.  intel_framebuffer_init doesn't add
+        * a reference, but when the drm_framebuffer inside is
+        * destroyed, it will drop a reference.
+        */
+       drm_gem_object_reference(&sc->sc_fb_obj->base);
+
+       fb_helper->fb = &dev_priv->fbdev->ifb.base;
+       mutex_unlock(&dev->struct_mutex);
+
+       aprint_error_dev(sc->sc_dev, "GTT base 0x%"PRIxMAX
+           ", GTT offset 0x%"PRIxMAX"\n",
+           (uintmax_t)dev_priv->mm.gtt_base_addr,
+           (uintmax_t)sc->sc_fb_obj->gtt_offset);
+       /* XXX errno NetBSD->Linux */
+       ret = -bus_space_map(dev->bst,
+           (dev_priv->mm.gtt_base_addr + sc->sc_fb_obj->gtt_offset),
+           size,
+           (BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE),
+           &sc->sc_fb_bsh);
+       if (ret) {
+               aprint_error_dev(sc->sc_dev, "unable to map framebuffer: %d\n",
+                   ret);
+               goto fail3;
+       }
+
+       if (0)
+               goto fail4;
+
+       aprint_error_dev(sc->sc_dev, "write crap to the framebuffer\n");
+    {
+       bus_size_t i;
+
+       for (i = 0; i < size; i++)
+               bus_space_write_1(dev->bst, sc->sc_fb_bsh, i,
+                   ((i % 4) == 0? 0x53 :
+                    (i % 4) == 1? 0x00 :
+                    (i % 4) == 2? 0x35 :
+                       0xff));
+    }
+#if 0
+       (void)memset(bus_space_vaddr(dev->bst, sc->sc_fb_bsh), 0x53, size/4);
+       (void)kpause("drmfbxxx", false, hz, NULL);
+       (void)memset((char *)bus_space_vaddr(dev->bst, sc->sc_fb_bsh) + size/4,
+           0x00, size/4);
+       (void)kpause("drmfbxxx", false, hz, NULL);
+       (void)memset((char *)bus_space_vaddr(dev->bst, sc->sc_fb_bsh) + size/2,



Home | Main Index | Thread Index | Old Index