linux/drivers/gpu/drm/gud/gud_drv.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright 2020 Noralf Trønnes
   4 */
   5
   6#include <linux/dma-buf.h>
   7#include <linux/dma-mapping.h>
   8#include <linux/lz4.h>
   9#include <linux/module.h>
  10#include <linux/platform_device.h>
  11#include <linux/string_helpers.h>
  12#include <linux/usb.h>
  13#include <linux/vmalloc.h>
  14#include <linux/workqueue.h>
  15
  16#include <drm/drm_atomic_helper.h>
  17#include <drm/drm_damage_helper.h>
  18#include <drm/drm_debugfs.h>
  19#include <drm/drm_drv.h>
  20#include <drm/drm_fb_helper.h>
  21#include <drm/drm_fourcc.h>
  22#include <drm/drm_gem_atomic_helper.h>
  23#include <drm/drm_gem_framebuffer_helper.h>
  24#include <drm/drm_gem_shmem_helper.h>
  25#include <drm/drm_managed.h>
  26#include <drm/drm_print.h>
  27#include <drm/drm_probe_helper.h>
  28#include <drm/drm_simple_kms_helper.h>
  29#include <drm/gud.h>
  30
  31#include "gud_internal.h"
  32
  33/* Only used internally */
  34static const struct drm_format_info gud_drm_format_r1 = {
  35        .format = GUD_DRM_FORMAT_R1,
  36        .num_planes = 1,
  37        .char_per_block = { 1, 0, 0 },
  38        .block_w = { 8, 0, 0 },
  39        .block_h = { 1, 0, 0 },
  40        .hsub = 1,
  41        .vsub = 1,
  42};
  43
  44static const struct drm_format_info gud_drm_format_xrgb1111 = {
  45        .format = GUD_DRM_FORMAT_XRGB1111,
  46        .num_planes = 1,
  47        .char_per_block = { 1, 0, 0 },
  48        .block_w = { 2, 0, 0 },
  49        .block_h = { 1, 0, 0 },
  50        .hsub = 1,
  51        .vsub = 1,
  52};
  53
  54static int gud_usb_control_msg(struct usb_interface *intf, bool in,
  55                               u8 request, u16 value, void *buf, size_t len)
  56{
  57        u8 requesttype = USB_TYPE_VENDOR | USB_RECIP_INTERFACE;
  58        u8 ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
  59        struct usb_device *usb = interface_to_usbdev(intf);
  60        unsigned int pipe;
  61
  62        if (len && !buf)
  63                return -EINVAL;
  64
  65        if (in) {
  66                pipe = usb_rcvctrlpipe(usb, 0);
  67                requesttype |= USB_DIR_IN;
  68        } else {
  69                pipe = usb_sndctrlpipe(usb, 0);
  70                requesttype |= USB_DIR_OUT;
  71        }
  72
  73        return usb_control_msg(usb, pipe, request, requesttype, value,
  74                               ifnum, buf, len, USB_CTRL_GET_TIMEOUT);
  75}
  76
  77static int gud_get_display_descriptor(struct usb_interface *intf,
  78                                      struct gud_display_descriptor_req *desc)
  79{
  80        void *buf;
  81        int ret;
  82
  83        buf = kmalloc(sizeof(*desc), GFP_KERNEL);
  84        if (!buf)
  85                return -ENOMEM;
  86
  87        ret = gud_usb_control_msg(intf, true, GUD_REQ_GET_DESCRIPTOR, 0, buf, sizeof(*desc));
  88        memcpy(desc, buf, sizeof(*desc));
  89        kfree(buf);
  90        if (ret < 0)
  91                return ret;
  92        if (ret != sizeof(*desc))
  93                return -EIO;
  94
  95        if (desc->magic != le32_to_cpu(GUD_DISPLAY_MAGIC))
  96                return -ENODATA;
  97
  98        DRM_DEV_DEBUG_DRIVER(&intf->dev,
  99                             "version=%u flags=0x%x compression=0x%x max_buffer_size=%u\n",
 100                             desc->version, le32_to_cpu(desc->flags), desc->compression,
 101                             le32_to_cpu(desc->max_buffer_size));
 102
 103        if (!desc->version || !desc->max_width || !desc->max_height ||
 104            le32_to_cpu(desc->min_width) > le32_to_cpu(desc->max_width) ||
 105            le32_to_cpu(desc->min_height) > le32_to_cpu(desc->max_height))
 106                return -EINVAL;
 107
 108        return 0;
 109}
 110
 111static int gud_status_to_errno(u8 status)
 112{
 113        switch (status) {
 114        case GUD_STATUS_OK:
 115                return 0;
 116        case GUD_STATUS_BUSY:
 117                return -EBUSY;
 118        case GUD_STATUS_REQUEST_NOT_SUPPORTED:
 119                return -EOPNOTSUPP;
 120        case GUD_STATUS_PROTOCOL_ERROR:
 121                return -EPROTO;
 122        case GUD_STATUS_INVALID_PARAMETER:
 123                return -EINVAL;
 124        case GUD_STATUS_ERROR:
 125                return -EREMOTEIO;
 126        default:
 127                return -EREMOTEIO;
 128        }
 129}
 130
 131static int gud_usb_get_status(struct usb_interface *intf)
 132{
 133        int ret, status = -EIO;
 134        u8 *buf;
 135
 136        buf = kmalloc(sizeof(*buf), GFP_KERNEL);
 137        if (!buf)
 138                return -ENOMEM;
 139
 140        ret = gud_usb_control_msg(intf, true, GUD_REQ_GET_STATUS, 0, buf, sizeof(*buf));
 141        if (ret == sizeof(*buf))
 142                status = gud_status_to_errno(*buf);
 143        kfree(buf);
 144
 145        if (ret < 0)
 146                return ret;
 147
 148        return status;
 149}
 150
 151static int gud_usb_transfer(struct gud_device *gdrm, bool in, u8 request, u16 index,
 152                            void *buf, size_t len)
 153{
 154        struct usb_interface *intf = to_usb_interface(gdrm->drm.dev);
 155        int idx, ret;
 156
 157        drm_dbg(&gdrm->drm, "%s: request=0x%x index=%u len=%zu\n",
 158                in ? "get" : "set", request, index, len);
 159
 160        if (!drm_dev_enter(&gdrm->drm, &idx))
 161                return -ENODEV;
 162
 163        mutex_lock(&gdrm->ctrl_lock);
 164
 165        ret = gud_usb_control_msg(intf, in, request, index, buf, len);
 166        if (ret == -EPIPE || ((gdrm->flags & GUD_DISPLAY_FLAG_STATUS_ON_SET) && !in && ret >= 0)) {
 167                int status;
 168
 169                status = gud_usb_get_status(intf);
 170                if (status < 0) {
 171                        ret = status;
 172                } else if (ret < 0) {
 173                        dev_err_once(gdrm->drm.dev,
 174                                     "Unexpected status OK for failed transfer\n");
 175                        ret = -EPIPE;
 176                }
 177        }
 178
 179        if (ret < 0) {
 180                drm_dbg(&gdrm->drm, "ret=%d\n", ret);
 181                gdrm->stats_num_errors++;
 182        }
 183
 184        mutex_unlock(&gdrm->ctrl_lock);
 185        drm_dev_exit(idx);
 186
 187        return ret;
 188}
 189
 190/*
 191 * @buf cannot be allocated on the stack.
 192 * Returns number of bytes received or negative error code on failure.
 193 */
 194int gud_usb_get(struct gud_device *gdrm, u8 request, u16 index, void *buf, size_t max_len)
 195{
 196        return gud_usb_transfer(gdrm, true, request, index, buf, max_len);
 197}
 198
 199/*
 200 * @buf can be allocated on the stack or NULL.
 201 * Returns zero on success or negative error code on failure.
 202 */
 203int gud_usb_set(struct gud_device *gdrm, u8 request, u16 index, void *buf, size_t len)
 204{
 205        void *trbuf = NULL;
 206        int ret;
 207
 208        if (buf && len) {
 209                trbuf = kmemdup(buf, len, GFP_KERNEL);
 210                if (!trbuf)
 211                        return -ENOMEM;
 212        }
 213
 214        ret = gud_usb_transfer(gdrm, false, request, index, trbuf, len);
 215        kfree(trbuf);
 216        if (ret < 0)
 217                return ret;
 218
 219        return ret != len ? -EIO : 0;
 220}
 221
 222/*
 223 * @val can be allocated on the stack.
 224 * Returns zero on success or negative error code on failure.
 225 */
 226int gud_usb_get_u8(struct gud_device *gdrm, u8 request, u16 index, u8 *val)
 227{
 228        u8 *buf;
 229        int ret;
 230
 231        buf = kmalloc(sizeof(*val), GFP_KERNEL);
 232        if (!buf)
 233                return -ENOMEM;
 234
 235        ret = gud_usb_get(gdrm, request, index, buf, sizeof(*val));
 236        *val = *buf;
 237        kfree(buf);
 238        if (ret < 0)
 239                return ret;
 240
 241        return ret != sizeof(*val) ? -EIO : 0;
 242}
 243
 244/* Returns zero on success or negative error code on failure. */
 245int gud_usb_set_u8(struct gud_device *gdrm, u8 request, u8 val)
 246{
 247        return gud_usb_set(gdrm, request, 0, &val, sizeof(val));
 248}
 249
 250static int gud_get_properties(struct gud_device *gdrm)
 251{
 252        struct gud_property_req *properties;
 253        unsigned int i, num_properties;
 254        int ret;
 255
 256        properties = kcalloc(GUD_PROPERTIES_MAX_NUM, sizeof(*properties), GFP_KERNEL);
 257        if (!properties)
 258                return -ENOMEM;
 259
 260        ret = gud_usb_get(gdrm, GUD_REQ_GET_PROPERTIES, 0,
 261                          properties, GUD_PROPERTIES_MAX_NUM * sizeof(*properties));
 262        if (ret <= 0)
 263                goto out;
 264        if (ret % sizeof(*properties)) {
 265                ret = -EIO;
 266                goto out;
 267        }
 268
 269        num_properties = ret / sizeof(*properties);
 270        ret = 0;
 271
 272        gdrm->properties = drmm_kcalloc(&gdrm->drm, num_properties, sizeof(*gdrm->properties),
 273                                        GFP_KERNEL);
 274        if (!gdrm->properties) {
 275                ret = -ENOMEM;
 276                goto out;
 277        }
 278
 279        for (i = 0; i < num_properties; i++) {
 280                u16 prop = le16_to_cpu(properties[i].prop);
 281                u64 val = le64_to_cpu(properties[i].val);
 282
 283                switch (prop) {
 284                case GUD_PROPERTY_ROTATION:
 285                        /*
 286                         * DRM UAPI matches the protocol so use the value directly,
 287                         * but mask out any additions on future devices.
 288                         */
 289                        val &= GUD_ROTATION_MASK;
 290                        ret = drm_plane_create_rotation_property(&gdrm->pipe.plane,
 291                                                                 DRM_MODE_ROTATE_0, val);
 292                        break;
 293                default:
 294                        /* New ones might show up in future devices, skip those we don't know. */
 295                        drm_dbg(&gdrm->drm, "Ignoring unknown property: %u\n", prop);
 296                        continue;
 297                }
 298
 299                if (ret)
 300                        goto out;
 301
 302                gdrm->properties[gdrm->num_properties++] = prop;
 303        }
 304out:
 305        kfree(properties);
 306
 307        return ret;
 308}
 309
 310/*
 311 * FIXME: Dma-buf sharing requires DMA support by the importing device.
 312 *        This function is a workaround to make USB devices work as well.
 313 *        See todo.rst for how to fix the issue in the dma-buf framework.
 314 */
 315static struct drm_gem_object *gud_gem_prime_import(struct drm_device *drm, struct dma_buf *dma_buf)
 316{
 317        struct gud_device *gdrm = to_gud_device(drm);
 318
 319        if (!gdrm->dmadev)
 320                return ERR_PTR(-ENODEV);
 321
 322        return drm_gem_prime_import_dev(drm, dma_buf, gdrm->dmadev);
 323}
 324
 325static int gud_stats_debugfs(struct seq_file *m, void *data)
 326{
 327        struct drm_info_node *node = m->private;
 328        struct gud_device *gdrm = to_gud_device(node->minor->dev);
 329        char buf[10];
 330
 331        string_get_size(gdrm->bulk_len, 1, STRING_UNITS_2, buf, sizeof(buf));
 332        seq_printf(m, "Max buffer size: %s\n", buf);
 333        seq_printf(m, "Number of errors:  %u\n", gdrm->stats_num_errors);
 334
 335        seq_puts(m, "Compression:      ");
 336        if (gdrm->compression & GUD_COMPRESSION_LZ4)
 337                seq_puts(m, " lz4");
 338        if (!gdrm->compression)
 339                seq_puts(m, " none");
 340        seq_puts(m, "\n");
 341
 342        if (gdrm->compression) {
 343                u64 remainder;
 344                u64 ratio = div64_u64_rem(gdrm->stats_length, gdrm->stats_actual_length,
 345                                          &remainder);
 346                u64 ratio_frac = div64_u64(remainder * 10, gdrm->stats_actual_length);
 347
 348                seq_printf(m, "Compression ratio: %llu.%llu\n", ratio, ratio_frac);
 349        }
 350
 351        return 0;
 352}
 353
 354static const struct drm_info_list gud_debugfs_list[] = {
 355        { "stats", gud_stats_debugfs, 0, NULL },
 356};
 357
 358static void gud_debugfs_init(struct drm_minor *minor)
 359{
 360        drm_debugfs_create_files(gud_debugfs_list, ARRAY_SIZE(gud_debugfs_list),
 361                                 minor->debugfs_root, minor);
 362}
 363
 364static const struct drm_simple_display_pipe_funcs gud_pipe_funcs = {
 365        .check      = gud_pipe_check,
 366        .update     = gud_pipe_update,
 367        .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
 368};
 369
 370static const struct drm_mode_config_funcs gud_mode_config_funcs = {
 371        .fb_create = drm_gem_fb_create_with_dirty,
 372        .atomic_check = drm_atomic_helper_check,
 373        .atomic_commit = drm_atomic_helper_commit,
 374};
 375
 376static const u64 gud_pipe_modifiers[] = {
 377        DRM_FORMAT_MOD_LINEAR,
 378        DRM_FORMAT_MOD_INVALID
 379};
 380
 381DEFINE_DRM_GEM_FOPS(gud_fops);
 382
 383static const struct drm_driver gud_drm_driver = {
 384        .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
 385        .fops                   = &gud_fops,
 386        DRM_GEM_SHMEM_DRIVER_OPS,
 387        .gem_prime_import       = gud_gem_prime_import,
 388        .debugfs_init           = gud_debugfs_init,
 389
 390        .name                   = "gud",
 391        .desc                   = "Generic USB Display",
 392        .date                   = "20200422",
 393        .major                  = 1,
 394        .minor                  = 0,
 395};
 396
 397static void gud_free_buffers_and_mutex(struct drm_device *drm, void *unused)
 398{
 399        struct gud_device *gdrm = to_gud_device(drm);
 400
 401        vfree(gdrm->compress_buf);
 402        kfree(gdrm->bulk_buf);
 403        mutex_destroy(&gdrm->ctrl_lock);
 404        mutex_destroy(&gdrm->damage_lock);
 405}
 406
 407static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
 408{
 409        const struct drm_format_info *xrgb8888_emulation_format = NULL;
 410        bool rgb565_supported = false, xrgb8888_supported = false;
 411        unsigned int num_formats_dev, num_formats = 0;
 412        struct usb_endpoint_descriptor *bulk_out;
 413        struct gud_display_descriptor_req desc;
 414        struct device *dev = &intf->dev;
 415        size_t max_buffer_size = 0;
 416        struct gud_device *gdrm;
 417        struct drm_device *drm;
 418        u8 *formats_dev;
 419        u32 *formats;
 420        int ret, i;
 421
 422        ret = usb_find_bulk_out_endpoint(intf->cur_altsetting, &bulk_out);
 423        if (ret)
 424                return ret;
 425
 426        ret = gud_get_display_descriptor(intf, &desc);
 427        if (ret) {
 428                DRM_DEV_DEBUG_DRIVER(dev, "Not a display interface: ret=%d\n", ret);
 429                return -ENODEV;
 430        }
 431
 432        if (desc.version > 1) {
 433                dev_err(dev, "Protocol version %u is not supported\n", desc.version);
 434                return -ENODEV;
 435        }
 436
 437        gdrm = devm_drm_dev_alloc(dev, &gud_drm_driver, struct gud_device, drm);
 438        if (IS_ERR(gdrm))
 439                return PTR_ERR(gdrm);
 440
 441        drm = &gdrm->drm;
 442        drm->mode_config.funcs = &gud_mode_config_funcs;
 443        ret = drmm_mode_config_init(drm);
 444        if (ret)
 445                return ret;
 446
 447        gdrm->flags = le32_to_cpu(desc.flags);
 448        gdrm->compression = desc.compression & GUD_COMPRESSION_LZ4;
 449
 450        if (gdrm->flags & GUD_DISPLAY_FLAG_FULL_UPDATE && gdrm->compression)
 451                return -EINVAL;
 452
 453        mutex_init(&gdrm->ctrl_lock);
 454        mutex_init(&gdrm->damage_lock);
 455        INIT_WORK(&gdrm->work, gud_flush_work);
 456        gud_clear_damage(gdrm);
 457
 458        ret = drmm_add_action_or_reset(drm, gud_free_buffers_and_mutex, NULL);
 459        if (ret)
 460                return ret;
 461
 462        drm->mode_config.min_width = le32_to_cpu(desc.min_width);
 463        drm->mode_config.max_width = le32_to_cpu(desc.max_width);
 464        drm->mode_config.min_height = le32_to_cpu(desc.min_height);
 465        drm->mode_config.max_height = le32_to_cpu(desc.max_height);
 466
 467        formats_dev = devm_kmalloc(dev, GUD_FORMATS_MAX_NUM, GFP_KERNEL);
 468        /* Add room for emulated XRGB8888 */
 469        formats = devm_kmalloc_array(dev, GUD_FORMATS_MAX_NUM + 1, sizeof(*formats), GFP_KERNEL);
 470        if (!formats_dev || !formats)
 471                return -ENOMEM;
 472
 473        ret = gud_usb_get(gdrm, GUD_REQ_GET_FORMATS, 0, formats_dev, GUD_FORMATS_MAX_NUM);
 474        if (ret < 0)
 475                return ret;
 476
 477        num_formats_dev = ret;
 478        for (i = 0; i < num_formats_dev; i++) {
 479                const struct drm_format_info *info;
 480                size_t fmt_buf_size;
 481                u32 format;
 482
 483                format = gud_to_fourcc(formats_dev[i]);
 484                if (!format) {
 485                        drm_dbg(drm, "Unsupported format: 0x%02x\n", formats_dev[i]);
 486                        continue;
 487                }
 488
 489                if (format == GUD_DRM_FORMAT_R1)
 490                        info = &gud_drm_format_r1;
 491                else if (format == GUD_DRM_FORMAT_XRGB1111)
 492                        info = &gud_drm_format_xrgb1111;
 493                else
 494                        info = drm_format_info(format);
 495
 496                switch (format) {
 497                case GUD_DRM_FORMAT_R1:
 498                        fallthrough;
 499                case GUD_DRM_FORMAT_XRGB1111:
 500                        if (!xrgb8888_emulation_format)
 501                                xrgb8888_emulation_format = info;
 502                        break;
 503                case DRM_FORMAT_RGB565:
 504                        rgb565_supported = true;
 505                        if (!xrgb8888_emulation_format)
 506                                xrgb8888_emulation_format = info;
 507                        break;
 508                case DRM_FORMAT_XRGB8888:
 509                        xrgb8888_supported = true;
 510                        break;
 511                }
 512
 513                fmt_buf_size = drm_format_info_min_pitch(info, 0, drm->mode_config.max_width) *
 514                               drm->mode_config.max_height;
 515                max_buffer_size = max(max_buffer_size, fmt_buf_size);
 516
 517                if (format == GUD_DRM_FORMAT_R1 || format == GUD_DRM_FORMAT_XRGB1111)
 518                        continue; /* Internal not for userspace */
 519
 520                formats[num_formats++] = format;
 521        }
 522
 523        if (!num_formats && !xrgb8888_emulation_format) {
 524                dev_err(dev, "No supported pixel formats found\n");
 525                return -EINVAL;
 526        }
 527
 528        /* Prefer speed over color depth */
 529        if (rgb565_supported)
 530                drm->mode_config.preferred_depth = 16;
 531
 532        if (!xrgb8888_supported && xrgb8888_emulation_format) {
 533                gdrm->xrgb8888_emulation_format = xrgb8888_emulation_format;
 534                formats[num_formats++] = DRM_FORMAT_XRGB8888;
 535        }
 536
 537        if (desc.max_buffer_size)
 538                max_buffer_size = le32_to_cpu(desc.max_buffer_size);
 539retry:
 540        /*
 541         * Use plain kmalloc here since devm_kmalloc() places struct devres at the beginning
 542         * of the buffer it allocates. This wastes a lot of memory when allocating big buffers.
 543         * Asking for 2M would actually allocate 4M. This would also prevent getting the biggest
 544         * possible buffer potentially leading to split transfers.
 545         */
 546        gdrm->bulk_buf = kmalloc(max_buffer_size, GFP_KERNEL | __GFP_NOWARN);
 547        if (!gdrm->bulk_buf) {
 548                max_buffer_size = roundup_pow_of_two(max_buffer_size) / 2;
 549                if (max_buffer_size < SZ_512K)
 550                        return -ENOMEM;
 551                goto retry;
 552        }
 553
 554        gdrm->bulk_pipe = usb_sndbulkpipe(interface_to_usbdev(intf), usb_endpoint_num(bulk_out));
 555        gdrm->bulk_len = max_buffer_size;
 556
 557        if (gdrm->compression & GUD_COMPRESSION_LZ4) {
 558                gdrm->lz4_comp_mem = devm_kmalloc(dev, LZ4_MEM_COMPRESS, GFP_KERNEL);
 559                if (!gdrm->lz4_comp_mem)
 560                        return -ENOMEM;
 561
 562                gdrm->compress_buf = vmalloc(gdrm->bulk_len);
 563                if (!gdrm->compress_buf)
 564                        return -ENOMEM;
 565        }
 566
 567        ret = drm_simple_display_pipe_init(drm, &gdrm->pipe, &gud_pipe_funcs,
 568                                           formats, num_formats,
 569                                           gud_pipe_modifiers, NULL);
 570        if (ret)
 571                return ret;
 572
 573        devm_kfree(dev, formats);
 574        devm_kfree(dev, formats_dev);
 575
 576        ret = gud_get_properties(gdrm);
 577        if (ret) {
 578                dev_err(dev, "Failed to get properties (error=%d)\n", ret);
 579                return ret;
 580        }
 581
 582        drm_plane_enable_fb_damage_clips(&gdrm->pipe.plane);
 583
 584        ret = gud_get_connectors(gdrm);
 585        if (ret) {
 586                dev_err(dev, "Failed to get connectors (error=%d)\n", ret);
 587                return ret;
 588        }
 589
 590        drm_mode_config_reset(drm);
 591
 592        usb_set_intfdata(intf, gdrm);
 593
 594        gdrm->dmadev = usb_intf_get_dma_device(intf);
 595        if (!gdrm->dmadev)
 596                dev_warn(dev, "buffer sharing not supported");
 597
 598        ret = drm_dev_register(drm, 0);
 599        if (ret) {
 600                put_device(gdrm->dmadev);
 601                return ret;
 602        }
 603
 604        drm_kms_helper_poll_init(drm);
 605
 606        drm_fbdev_generic_setup(drm, 0);
 607
 608        return 0;
 609}
 610
 611static void gud_disconnect(struct usb_interface *interface)
 612{
 613        struct gud_device *gdrm = usb_get_intfdata(interface);
 614        struct drm_device *drm = &gdrm->drm;
 615
 616        drm_dbg(drm, "%s:\n", __func__);
 617
 618        drm_kms_helper_poll_fini(drm);
 619        drm_dev_unplug(drm);
 620        drm_atomic_helper_shutdown(drm);
 621        put_device(gdrm->dmadev);
 622        gdrm->dmadev = NULL;
 623}
 624
 625static int gud_suspend(struct usb_interface *intf, pm_message_t message)
 626{
 627        struct gud_device *gdrm = usb_get_intfdata(intf);
 628
 629        return drm_mode_config_helper_suspend(&gdrm->drm);
 630}
 631
 632static int gud_resume(struct usb_interface *intf)
 633{
 634        struct gud_device *gdrm = usb_get_intfdata(intf);
 635
 636        drm_mode_config_helper_resume(&gdrm->drm);
 637
 638        return 0;
 639}
 640
 641static const struct usb_device_id gud_id_table[] = {
 642        { USB_DEVICE_INTERFACE_CLASS(0x1d50, 0x614d, USB_CLASS_VENDOR_SPEC) },
 643        { }
 644};
 645
 646MODULE_DEVICE_TABLE(usb, gud_id_table);
 647
 648static struct usb_driver gud_usb_driver = {
 649        .name           = "gud",
 650        .probe          = gud_probe,
 651        .disconnect     = gud_disconnect,
 652        .id_table       = gud_id_table,
 653        .suspend        = gud_suspend,
 654        .resume         = gud_resume,
 655        .reset_resume   = gud_resume,
 656};
 657
 658module_usb_driver(gud_usb_driver);
 659
 660MODULE_AUTHOR("Noralf Trønnes");
 661MODULE_LICENSE("Dual MIT/GPL");
 662