The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/nvidia/drm2/tegra_host1x.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2015 Michal Meloun
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/clock.h>
   34 #include <sys/kernel.h>
   35 #include <sys/limits.h>
   36 #include <sys/lock.h>
   37 
   38 #include <sys/module.h>
   39 #include <sys/resource.h>
   40 #include <sys/sx.h>
   41 #include <sys/rman.h>
   42 
   43 #include <machine/bus.h>
   44 #include <machine/resource.h>
   45 
   46 #include <dev/extres/clk/clk.h>
   47 #include <dev/extres/hwreset/hwreset.h>
   48 #include <dev/drm2/drmP.h>
   49 #include <dev/drm2/drm_crtc_helper.h>
   50 #include <dev/drm2/drm_fb_helper.h>
   51 #include <dev/fdt/simplebus.h>
   52 #include <dev/ofw/ofw_bus.h>
   53 #include <dev/ofw/ofw_bus_subr.h>
   54 
   55 #include <arm/nvidia/drm2/tegra_drm.h>
   56 
   57 #include "fb_if.h"
   58 #include "tegra_drm_if.h"
   59 
   60 #define WR4(_sc, _r, _v)        bus_rite_4((_sc)->mem_res, (_r), (_v))
   61 #define RD4(_sc, _r)            bus_read_4((_sc)->mem_res, (_r))
   62 
   63 #define LOCK(_sc)               sx_xlock(&(_sc)->lock)
   64 #define UNLOCK(_sc)             sx_xunlock(&(_sc)->lock)
   65 #define SLEEP(_sc, timeout)     sx_sleep(sc, &sc->lock, 0, "host1x", timeout);
   66 #define LOCK_INIT(_sc)          sx_init(&_sc->lock, "host1x")
   67 #define LOCK_DESTROY(_sc)       sx_destroy(&_sc->lock)
   68 #define ASSERT_LOCKED(_sc)      sx_assert(&_sc->lock, SA_LOCKED)
   69 #define ASSERT_UNLOCKED(_sc)    sx_assert(&_sc->lock, SA_UNLOCKED)
   70 
   71 static struct ofw_compat_data compat_data[] = {
   72         {"nvidia,tegra124-host1x",      1},
   73         {NULL,                          0}
   74 };
   75 
   76 #define DRIVER_NAME "tegra"
   77 #define DRIVER_DESC "NVIDIA Tegra TK1"
   78 #define DRIVER_DATE "20151101"
   79 #define DRIVER_MAJOR 0
   80 #define DRIVER_MINOR 0
   81 #define DRIVER_PATCHLEVEL 0
   82 
   83 struct client_info;
   84 TAILQ_HEAD(client_list, client_info);
   85 typedef struct client_list client_list_t;
   86 
   87 struct client_info {
   88         TAILQ_ENTRY(client_info) list_e;
   89         device_t client;
   90         int     activated;
   91 };
   92 
   93 struct host1x_softc {
   94         struct simplebus_softc  simplebus_sc;   /* must be first */
   95         device_t                dev;
   96         struct sx               lock;
   97         int                     attach_done;
   98 
   99         struct resource         *mem_res;
  100         struct resource         *syncpt_irq_res;
  101         void                    *syncpt_irq_h;
  102         struct resource         *gen_irq_res;
  103         void                    *gen_irq_h;
  104 
  105         clk_t                   clk;
  106         hwreset_t                       reset;
  107         struct intr_config_hook irq_hook;
  108 
  109         int                     drm_inited;
  110         client_list_t           clients;
  111 
  112         struct tegra_drm        *tegra_drm;
  113 };
  114 
  115 static void
  116 host1x_output_poll_changed(struct drm_device *drm_dev)
  117 {
  118         struct tegra_drm *drm;
  119 
  120         drm = container_of(drm_dev, struct tegra_drm, drm_dev);
  121         if (drm->fb != NULL)
  122                 drm_fb_helper_hotplug_event(&drm->fb->fb_helper);
  123 }
  124 
  125 static const struct drm_mode_config_funcs mode_config_funcs = {
  126         .fb_create = tegra_drm_fb_create,
  127         .output_poll_changed = host1x_output_poll_changed,
  128 };
  129 
  130 static int
  131 host1x_drm_init(struct host1x_softc *sc)
  132 {
  133         struct client_info *entry;
  134         int rv;
  135 
  136         LOCK(sc);
  137 
  138         TAILQ_FOREACH(entry, &sc->clients, list_e) {
  139                 if (entry->activated)
  140                         continue;
  141                 rv = TEGRA_DRM_INIT_CLIENT(entry->client, sc->dev,
  142                     sc->tegra_drm);
  143                 if (rv != 0) {
  144                         device_printf(sc->dev,
  145                             "Cannot init DRM client %s: %d\n",
  146                             device_get_name(entry->client), rv);
  147                         return (rv);
  148                 }
  149                 entry->activated = 1;
  150         }
  151         UNLOCK(sc);
  152 
  153         return (0);
  154 }
  155 
  156 static int
  157 host1x_drm_exit(struct host1x_softc *sc)
  158 {
  159         struct client_info *entry;
  160         int rv;
  161 #ifdef FREEBSD_NOTYET
  162         struct drm_device *dev, *tmp;
  163 #endif
  164         LOCK(sc);
  165         if (!sc->drm_inited) {
  166                 UNLOCK(sc);
  167                 return (0);
  168         }
  169         TAILQ_FOREACH_REVERSE(entry, &sc->clients, client_list, list_e) {
  170                 if (!entry->activated)
  171                         continue;
  172                 rv = TEGRA_DRM_EXIT_CLIENT(entry->client, sc->dev,
  173                     sc->tegra_drm);
  174                 if (rv != 0) {
  175                         device_printf(sc->dev,
  176                             "Cannot exit DRM client %s: %d\n",
  177                             device_get_name(entry->client), rv);
  178                 }
  179                 entry->activated = 0;
  180         }
  181 
  182 #ifdef FREEBSD_NOTYET
  183         list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
  184                 drm_put_dev(dev);
  185 #endif
  186         sc->drm_inited = 0;
  187         UNLOCK(sc);
  188 
  189         return (0);
  190 }
  191 
  192 static int
  193 host1x_drm_load(struct drm_device *drm_dev, unsigned long flags)
  194 {
  195         struct host1x_softc *sc;
  196         int rv;
  197 
  198         sc = device_get_softc(drm_dev->dev);
  199 
  200         drm_mode_config_init(drm_dev);
  201         drm_dev->mode_config.min_width = 32;
  202         drm_dev->mode_config.min_height = 32;
  203         drm_dev->mode_config.max_width = 4096;
  204         drm_dev->mode_config.max_height = 4096;
  205         drm_dev->mode_config.funcs = &mode_config_funcs;
  206 
  207         rv = host1x_drm_init(sc);
  208         if (rv != 0)
  209                 goto fail_host1x;
  210 
  211         drm_dev->irq_enabled = true;
  212         drm_dev->max_vblank_count = 0xffffffff;
  213         drm_dev->vblank_disable_allowed = true;
  214 
  215         rv = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
  216         if (rv != 0)
  217                 goto fail_vblank;
  218 
  219         drm_mode_config_reset(drm_dev);
  220 
  221         rv = tegra_drm_fb_init(drm_dev);
  222         if (rv != 0)
  223                 goto fail_fb;
  224         drm_kms_helper_poll_init(drm_dev);
  225 
  226         return (0);
  227 
  228 fail_fb:
  229         tegra_drm_fb_destroy(drm_dev);
  230         drm_vblank_cleanup(drm_dev);
  231 fail_vblank:
  232         host1x_drm_exit(sc);
  233 fail_host1x:
  234         drm_mode_config_cleanup(drm_dev);
  235 
  236         return (rv);
  237 }
  238 
  239 static int
  240 host1x_drm_unload(struct drm_device *drm_dev)
  241 {
  242         struct host1x_softc *sc;
  243         int rv;
  244 
  245         sc = device_get_softc(drm_dev->dev);
  246 
  247         drm_kms_helper_poll_fini(drm_dev);
  248         tegra_drm_fb_destroy(drm_dev);
  249         drm_mode_config_cleanup(drm_dev);
  250 
  251         rv = host1x_drm_exit(sc);
  252         if (rv < 0)
  253                 return (rv);
  254         return (0);
  255 }
  256 
  257 static int
  258 host1x_drm_open(struct drm_device *drm_dev, struct drm_file *filp)
  259 {
  260 
  261         return (0);
  262 }
  263 
  264 static void
  265 tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
  266 {
  267         struct drm_crtc *crtc;
  268 
  269         list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
  270                 tegra_dc_cancel_page_flip(crtc, file);
  271 }
  272 
  273 static void
  274 host1x_drm_lastclose(struct drm_device *drm_dev)
  275 {
  276 
  277         struct tegra_drm *drm;
  278 
  279         drm = container_of(drm_dev, struct tegra_drm, drm_dev);
  280         if (drm->fb  != NULL)
  281                 drm_fb_helper_restore_fbdev_mode(&drm->fb->fb_helper);
  282 }
  283 
  284 static int
  285 host1x_drm_enable_vblank(struct drm_device *drm_dev, int pipe)
  286 {
  287         struct drm_crtc *crtc;
  288 
  289         list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) {
  290                 if (pipe == tegra_dc_get_pipe(crtc)) {
  291                         tegra_dc_enable_vblank(crtc);
  292                         return (0);
  293                 }
  294         }
  295         return (-ENODEV);
  296 }
  297 
  298 static void
  299 host1x_drm_disable_vblank(struct drm_device *drm_dev, int pipe)
  300 {
  301         struct drm_crtc *crtc;
  302 
  303         list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) {
  304                 if (pipe == tegra_dc_get_pipe(crtc)) {
  305                         tegra_dc_disable_vblank(crtc);
  306                         return;
  307                 }
  308         }
  309 }
  310 
  311 static struct drm_ioctl_desc host1x_drm_ioctls[] = {
  312 };
  313 
  314 struct drm_driver tegra_drm_driver = {
  315         .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
  316         .load = host1x_drm_load,
  317         .unload = host1x_drm_unload,
  318         .open = host1x_drm_open,
  319         .preclose = tegra_drm_preclose,
  320         .lastclose = host1x_drm_lastclose,
  321 
  322         .get_vblank_counter = drm_vblank_count,
  323         .enable_vblank = host1x_drm_enable_vblank,
  324         .disable_vblank = host1x_drm_disable_vblank,
  325 
  326         /* Fields filled by tegra_bo_driver_register()
  327         .gem_free_object
  328         .gem_pager_ops
  329         .dumb_create
  330         .dumb_map_offset
  331         .dumb_destroy
  332         */
  333         .ioctls = host1x_drm_ioctls,
  334         .num_ioctls = nitems(host1x_drm_ioctls),
  335 
  336         .name = DRIVER_NAME,
  337         .desc = DRIVER_DESC,
  338         .date = DRIVER_DATE,
  339         .major = DRIVER_MAJOR,
  340         .minor = DRIVER_MINOR,
  341         .patchlevel = DRIVER_PATCHLEVEL,
  342 };
  343 
  344 /*
  345  * ----------------- Device methods -------------------------
  346  */
  347 static void
  348 host1x_irq_hook(void *arg)
  349 {
  350         struct host1x_softc *sc;
  351         int rv;
  352 
  353         sc = arg;
  354         config_intrhook_disestablish(&sc->irq_hook);
  355 
  356         tegra_bo_driver_register(&tegra_drm_driver);
  357         rv = drm_get_platform_dev(sc->dev, &sc->tegra_drm->drm_dev,
  358             &tegra_drm_driver);
  359         if (rv != 0) {
  360                 device_printf(sc->dev, "drm_get_platform_dev(): %d\n", rv);
  361                 return;
  362         }
  363 
  364         sc->drm_inited = 1;
  365 }
  366 
  367 static struct fb_info *
  368 host1x_fb_helper_getinfo(device_t dev)
  369 {
  370         struct host1x_softc *sc;
  371 
  372         sc = device_get_softc(dev);
  373         if (sc->tegra_drm == NULL)
  374                 return (NULL);
  375         return (tegra_drm_fb_getinfo(&sc->tegra_drm->drm_dev));
  376 }
  377 
  378 static int
  379 host1x_register_client(device_t dev, device_t client)
  380 {
  381         struct host1x_softc *sc;
  382         struct client_info *entry;
  383 
  384         sc = device_get_softc(dev);
  385 
  386         entry = malloc(sizeof(struct client_info), M_DEVBUF, M_WAITOK | M_ZERO);
  387         entry->client = client;
  388         entry->activated = 0;
  389 
  390         LOCK(sc);
  391         TAILQ_INSERT_TAIL(&sc->clients, entry, list_e);
  392         UNLOCK(sc);
  393 
  394         return (0);
  395 }
  396 
  397 static int
  398 host1x_deregister_client(device_t dev, device_t client)
  399 {
  400         struct host1x_softc *sc;
  401         struct client_info *entry;
  402 
  403         sc = device_get_softc(dev);
  404 
  405         LOCK(sc);
  406         TAILQ_FOREACH(entry, &sc->clients, list_e) {
  407                 if (entry->client == client) {
  408                         if (entry->activated)
  409                                 panic("Tegra DRM: Attempt to deregister "
  410                                     "activated client");
  411                         TAILQ_REMOVE(&sc->clients, entry, list_e);
  412                         free(entry, M_DEVBUF);
  413                         UNLOCK(sc);
  414                         return (0);
  415                 }
  416         }
  417         UNLOCK(sc);
  418 
  419         return (0);
  420 }
  421 
  422 static void
  423 host1x_gen_intr(void *arg)
  424 {
  425         struct host1x_softc *sc;
  426 
  427         sc = (struct host1x_softc *)arg;
  428         LOCK(sc);
  429         UNLOCK(sc);
  430 }
  431 
  432 static void
  433 host1x_syncpt_intr(void *arg)
  434 {
  435         struct host1x_softc *sc;
  436 
  437         sc = (struct host1x_softc *)arg;
  438         LOCK(sc);
  439         UNLOCK(sc);
  440 }
  441 
  442 static void
  443 host1x_new_pass(device_t dev)
  444 {
  445         struct host1x_softc *sc;
  446         int rv, rid;
  447         phandle_t node;
  448 
  449         /*
  450          * We attach during BUS_PASS_BUS (because we must overcome simplebus),
  451          * but some of our FDT resources are not ready until BUS_PASS_DEFAULT
  452          */
  453         sc = device_get_softc(dev);
  454         if (sc->attach_done || bus_current_pass < BUS_PASS_DEFAULT) {
  455                 bus_generic_new_pass(dev);
  456                 return;
  457         }
  458 
  459         sc->attach_done = 1;
  460         node = ofw_bus_get_node(dev);
  461 
  462         /* Allocate our IRQ resource. */
  463         rid = 0;
  464         sc->syncpt_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  465             RF_ACTIVE);
  466         if (sc->syncpt_irq_res == NULL) {
  467                 device_printf(dev, "Cannot allocate interrupt.\n");
  468                 rv = ENXIO;
  469                 goto fail;
  470         }
  471         rid = 1;
  472         sc->gen_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  473             RF_ACTIVE);
  474         if (sc->gen_irq_res == NULL) {
  475                 device_printf(dev, "Cannot allocate interrupt.\n");
  476                 rv = ENXIO;
  477                 goto fail;
  478         }
  479 
  480         /* FDT resources */
  481         rv = hwreset_get_by_ofw_name(sc->dev, 0, "host1x", &sc->reset);
  482         if (rv != 0) {
  483                 device_printf(dev, "Cannot get fuse reset\n");
  484                 goto fail;
  485         }
  486         rv = clk_get_by_ofw_index(sc->dev, 0, 0, &sc->clk);
  487         if (rv != 0) {
  488                 device_printf(dev, "Cannot get i2c clock: %d\n", rv);
  489                 goto fail;
  490         }
  491 
  492         rv = clk_enable(sc->clk);
  493         if (rv != 0) {
  494                 device_printf(dev, "Cannot enable clock: %d\n", rv);
  495                 goto fail;
  496         }
  497         rv = hwreset_deassert(sc->reset);
  498         if (rv != 0) {
  499                 device_printf(sc->dev, "Cannot clear reset\n");
  500                 goto fail;
  501         }
  502 
  503         /* Setup  interrupts */
  504         rv = bus_setup_intr(dev, sc->gen_irq_res,
  505             INTR_TYPE_MISC | INTR_MPSAFE, NULL, host1x_gen_intr,
  506             sc, &sc->gen_irq_h);
  507         if (rv) {
  508                 device_printf(dev, "Cannot setup gen interrupt.\n");
  509                 goto fail;
  510         }
  511 
  512         rv = bus_setup_intr(dev, sc->syncpt_irq_res,
  513             INTR_TYPE_MISC | INTR_MPSAFE, NULL, host1x_syncpt_intr,
  514             sc, &sc->syncpt_irq_h);
  515         if (rv) {
  516                 device_printf(dev, "Cannot setup syncpt interrupt.\n");
  517                 goto fail;
  518         }
  519 
  520         simplebus_init(dev, 0);
  521         for (node = OF_child(node); node > 0; node = OF_peer(node))
  522             simplebus_add_device(dev, node, 0, NULL, -1, NULL);
  523 
  524         sc->irq_hook.ich_func = host1x_irq_hook;
  525         sc->irq_hook.ich_arg = sc;
  526         config_intrhook_establish(&sc->irq_hook);
  527         bus_generic_new_pass(dev);
  528         return;
  529 
  530 fail:
  531         device_detach(dev);
  532         return;
  533 }
  534 
  535 static int
  536 host1x_probe(device_t dev)
  537 {
  538 
  539         if (!ofw_bus_status_okay(dev))
  540                 return (ENXIO);
  541 
  542         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  543                 return (ENXIO);
  544 
  545         return (BUS_PROBE_DEFAULT);
  546 }
  547 
  548 static int
  549 host1x_attach(device_t dev)
  550 {
  551         int rv, rid;
  552         struct host1x_softc *sc;
  553 
  554         sc = device_get_softc(dev);
  555         sc->tegra_drm = malloc(sizeof(struct tegra_drm), DRM_MEM_DRIVER,
  556             M_WAITOK | M_ZERO);
  557 
  558         /* crosslink together all worlds */
  559         sc->dev = dev;
  560         sc->tegra_drm->drm_dev.dev_private = &sc->tegra_drm;
  561         sc->tegra_drm->drm_dev.dev = dev;
  562 
  563         TAILQ_INIT(&sc->clients);
  564 
  565         LOCK_INIT(sc);
  566 
  567         /* Get the memory resource for the register mapping. */
  568         rid = 0;
  569         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  570             RF_ACTIVE);
  571         if (sc->mem_res == NULL) {
  572                 device_printf(dev, "Cannot map registers.\n");
  573                 rv = ENXIO;
  574                 goto fail;
  575         }
  576 
  577         return (bus_generic_attach(dev));
  578 
  579 fail:
  580         if (sc->tegra_drm != NULL)
  581                 free(sc->tegra_drm, DRM_MEM_DRIVER);
  582         if (sc->mem_res != NULL)
  583                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
  584         LOCK_DESTROY(sc);
  585         return (rv);
  586 }
  587 
  588 static int
  589 host1x_detach(device_t dev)
  590 {
  591         struct host1x_softc *sc;
  592 
  593         sc = device_get_softc(dev);
  594 
  595         host1x_drm_exit(sc);
  596 
  597         if (sc->gen_irq_h != NULL)
  598                 bus_teardown_intr(dev, sc->gen_irq_res, sc->gen_irq_h);
  599         if (sc->tegra_drm != NULL)
  600                 free(sc->tegra_drm, DRM_MEM_DRIVER);
  601         if (sc->clk != NULL)
  602                 clk_release(sc->clk);
  603         if (sc->reset != NULL)
  604                 hwreset_release(sc->reset);
  605         if (sc->syncpt_irq_h != NULL)
  606                 bus_teardown_intr(dev, sc->syncpt_irq_res, sc->syncpt_irq_h);
  607         if (sc->gen_irq_res != NULL)
  608                 bus_release_resource(dev, SYS_RES_IRQ, 1, sc->gen_irq_res);
  609         if (sc->syncpt_irq_res != NULL)
  610                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->syncpt_irq_res);
  611         if (sc->mem_res != NULL)
  612                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
  613         LOCK_DESTROY(sc);
  614         return (bus_generic_detach(dev));
  615 }
  616 
  617 static device_method_t host1x_methods[] = {
  618         /* Device interface */
  619         DEVMETHOD(device_probe,         host1x_probe),
  620         DEVMETHOD(device_attach,        host1x_attach),
  621         DEVMETHOD(device_detach,        host1x_detach),
  622 
  623         /* Bus interface */
  624         DEVMETHOD(bus_new_pass,         host1x_new_pass),
  625 
  626         /* Framebuffer service methods */
  627         DEVMETHOD(fb_getinfo,           host1x_fb_helper_getinfo),
  628 
  629         /* tegra drm interface */
  630         DEVMETHOD(tegra_drm_register_client,    host1x_register_client),
  631         DEVMETHOD(tegra_drm_deregister_client,  host1x_deregister_client),
  632 
  633         DEVMETHOD_END
  634 };
  635 
  636 DEFINE_CLASS_1(host1x, host1x_driver, host1x_methods,
  637     sizeof(struct host1x_softc), simplebus_driver);
  638 EARLY_DRIVER_MODULE(host1x, simplebus, host1x_driver, 0, 0, BUS_PASS_BUS);
  639 
  640 /* Bindings for fbd device. */
  641 extern driver_t fbd_driver;
  642 DRIVER_MODULE(fbd, host1x, fbd_driver, 0, 0);

Cache object: 897a84670367cd60f31eb5756f16b602


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.