linux/sound/usb/line6/podhd.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Line 6 Pod HD
   4 *
   5 * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
   6 * Copyright (C) 2015 Andrej Krutak <dev@andree.sk>
   7 * Copyright (C) 2017 Hans P. Moller <hmoller@uc.cl>
   8 */
   9
  10#include <linux/usb.h>
  11#include <linux/slab.h>
  12#include <linux/module.h>
  13#include <sound/core.h>
  14#include <sound/control.h>
  15#include <sound/pcm.h>
  16
  17#include "driver.h"
  18#include "pcm.h"
  19
  20#define PODHD_STARTUP_DELAY 500
  21
  22enum {
  23        LINE6_PODHD300,
  24        LINE6_PODHD400,
  25        LINE6_PODHD500,
  26        LINE6_PODX3,
  27        LINE6_PODX3LIVE,
  28        LINE6_PODHD500X,
  29        LINE6_PODHDDESKTOP
  30};
  31
  32struct usb_line6_podhd {
  33        /* Generic Line 6 USB data */
  34        struct usb_line6 line6;
  35
  36        /* Serial number of device */
  37        u32 serial_number;
  38
  39        /* Firmware version */
  40        int firmware_version;
  41
  42        /* Monitor level */
  43        int monitor_level;
  44};
  45
  46#define line6_to_podhd(x)       container_of(x, struct usb_line6_podhd, line6)
  47
  48static const struct snd_ratden podhd_ratden = {
  49        .num_min = 48000,
  50        .num_max = 48000,
  51        .num_step = 1,
  52        .den = 1,
  53};
  54
  55static struct line6_pcm_properties podhd_pcm_properties = {
  56        .playback_hw = {
  57                                  .info = (SNDRV_PCM_INFO_MMAP |
  58                                           SNDRV_PCM_INFO_INTERLEAVED |
  59                                           SNDRV_PCM_INFO_BLOCK_TRANSFER |
  60                                           SNDRV_PCM_INFO_MMAP_VALID |
  61                                           SNDRV_PCM_INFO_PAUSE |
  62                                           SNDRV_PCM_INFO_SYNC_START),
  63                                  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
  64                                  .rates = SNDRV_PCM_RATE_48000,
  65                                  .rate_min = 48000,
  66                                  .rate_max = 48000,
  67                                  .channels_min = 2,
  68                                  .channels_max = 2,
  69                                  .buffer_bytes_max = 60000,
  70                                  .period_bytes_min = 64,
  71                                  .period_bytes_max = 8192,
  72                                  .periods_min = 1,
  73                                  .periods_max = 1024},
  74        .capture_hw = {
  75                                 .info = (SNDRV_PCM_INFO_MMAP |
  76                                          SNDRV_PCM_INFO_INTERLEAVED |
  77                                          SNDRV_PCM_INFO_BLOCK_TRANSFER |
  78                                          SNDRV_PCM_INFO_MMAP_VALID |
  79                                          SNDRV_PCM_INFO_SYNC_START),
  80                                 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
  81                                 .rates = SNDRV_PCM_RATE_48000,
  82                                 .rate_min = 48000,
  83                                 .rate_max = 48000,
  84                                 .channels_min = 2,
  85                                 .channels_max = 2,
  86                                 .buffer_bytes_max = 60000,
  87                                 .period_bytes_min = 64,
  88                                 .period_bytes_max = 8192,
  89                                 .periods_min = 1,
  90                                 .periods_max = 1024},
  91        .rates = {
  92                            .nrats = 1,
  93                            .rats = &podhd_ratden},
  94        .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
  95};
  96
  97static struct line6_pcm_properties podx3_pcm_properties = {
  98        .playback_hw = {
  99                                  .info = (SNDRV_PCM_INFO_MMAP |
 100                                           SNDRV_PCM_INFO_INTERLEAVED |
 101                                           SNDRV_PCM_INFO_BLOCK_TRANSFER |
 102                                           SNDRV_PCM_INFO_MMAP_VALID |
 103                                           SNDRV_PCM_INFO_PAUSE |
 104                                           SNDRV_PCM_INFO_SYNC_START),
 105                                  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
 106                                  .rates = SNDRV_PCM_RATE_48000,
 107                                  .rate_min = 48000,
 108                                  .rate_max = 48000,
 109                                  .channels_min = 2,
 110                                  .channels_max = 2,
 111                                  .buffer_bytes_max = 60000,
 112                                  .period_bytes_min = 64,
 113                                  .period_bytes_max = 8192,
 114                                  .periods_min = 1,
 115                                  .periods_max = 1024},
 116        .capture_hw = {
 117                                 .info = (SNDRV_PCM_INFO_MMAP |
 118                                          SNDRV_PCM_INFO_INTERLEAVED |
 119                                          SNDRV_PCM_INFO_BLOCK_TRANSFER |
 120                                          SNDRV_PCM_INFO_MMAP_VALID |
 121                                          SNDRV_PCM_INFO_SYNC_START),
 122                                 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
 123                                 .rates = SNDRV_PCM_RATE_48000,
 124                                 .rate_min = 48000,
 125                                 .rate_max = 48000,
 126                                 /* 1+2: Main signal (out), 3+4: Tone 1,
 127                                  * 5+6: Tone 2, 7+8: raw
 128                                  */
 129                                 .channels_min = 8,
 130                                 .channels_max = 8,
 131                                 .buffer_bytes_max = 60000,
 132                                 .period_bytes_min = 64,
 133                                 .period_bytes_max = 8192,
 134                                 .periods_min = 1,
 135                                 .periods_max = 1024},
 136        .rates = {
 137                            .nrats = 1,
 138                            .rats = &podhd_ratden},
 139        .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
 140};
 141static struct usb_driver podhd_driver;
 142
 143static ssize_t serial_number_show(struct device *dev,
 144                                  struct device_attribute *attr, char *buf)
 145{
 146        struct snd_card *card = dev_to_snd_card(dev);
 147        struct usb_line6_podhd *pod = card->private_data;
 148
 149        return sprintf(buf, "%u\n", pod->serial_number);
 150}
 151
 152static ssize_t firmware_version_show(struct device *dev,
 153                                     struct device_attribute *attr, char *buf)
 154{
 155        struct snd_card *card = dev_to_snd_card(dev);
 156        struct usb_line6_podhd *pod = card->private_data;
 157
 158        return sprintf(buf, "%06x\n", pod->firmware_version);
 159}
 160
 161static DEVICE_ATTR_RO(firmware_version);
 162static DEVICE_ATTR_RO(serial_number);
 163
 164static struct attribute *podhd_dev_attrs[] = {
 165        &dev_attr_firmware_version.attr,
 166        &dev_attr_serial_number.attr,
 167        NULL
 168};
 169
 170static const struct attribute_group podhd_dev_attr_group = {
 171        .name = "podhd",
 172        .attrs = podhd_dev_attrs,
 173};
 174
 175/*
 176 * POD X3 startup procedure.
 177 *
 178 * May be compatible with other POD HD's, since it's also similar to the
 179 * previous POD setup. In any case, it doesn't seem to be required for the
 180 * audio nor bulk interfaces to work.
 181 */
 182
 183static int podhd_dev_start(struct usb_line6_podhd *pod)
 184{
 185        int ret;
 186        u8 init_bytes[8];
 187        int i;
 188        struct usb_device *usbdev = pod->line6.usbdev;
 189
 190        ret = usb_control_msg_send(usbdev, 0,
 191                                        0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
 192                                        0x11, 0,
 193                                        NULL, 0, LINE6_TIMEOUT * HZ, GFP_KERNEL);
 194        if (ret) {
 195                dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret);
 196                goto exit;
 197        }
 198
 199        /* NOTE: looks like some kind of ping message */
 200        ret = usb_control_msg_recv(usbdev, 0, 0x67,
 201                                        USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 202                                        0x11, 0x0,
 203                                        init_bytes, 3, LINE6_TIMEOUT * HZ, GFP_KERNEL);
 204        if (ret) {
 205                dev_err(pod->line6.ifcdev,
 206                        "receive length failed (error %d)\n", ret);
 207                goto exit;
 208        }
 209
 210        pod->firmware_version =
 211                (init_bytes[0] << 16) | (init_bytes[1] << 8) | (init_bytes[2] << 0);
 212
 213        for (i = 0; i <= 16; i++) {
 214                ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8);
 215                if (ret < 0)
 216                        goto exit;
 217        }
 218
 219        ret = usb_control_msg_send(usbdev, 0,
 220                                        USB_REQ_SET_FEATURE,
 221                                        USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT,
 222                                        1, 0,
 223                                        NULL, 0, LINE6_TIMEOUT * HZ, GFP_KERNEL);
 224exit:
 225        return ret;
 226}
 227
 228static void podhd_startup(struct usb_line6 *line6)
 229{
 230        struct usb_line6_podhd *pod = line6_to_podhd(line6);
 231
 232        podhd_dev_start(pod);
 233        line6_read_serial_number(&pod->line6, &pod->serial_number);
 234        if (snd_card_register(line6->card))
 235                dev_err(line6->ifcdev, "Failed to register POD HD card.\n");
 236}
 237
 238static void podhd_disconnect(struct usb_line6 *line6)
 239{
 240        struct usb_line6_podhd *pod = line6_to_podhd(line6);
 241
 242        if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) {
 243                struct usb_interface *intf;
 244
 245                intf = usb_ifnum_to_if(line6->usbdev,
 246                                        pod->line6.properties->ctrl_if);
 247                if (intf)
 248                        usb_driver_release_interface(&podhd_driver, intf);
 249        }
 250}
 251
 252static const unsigned int float_zero_to_one_lookup[] = {
 2530x00000000, 0x3c23d70a, 0x3ca3d70a, 0x3cf5c28f, 0x3d23d70a, 0x3d4ccccd,
 2540x3d75c28f, 0x3d8f5c29, 0x3da3d70a, 0x3db851ec, 0x3dcccccd, 0x3de147ae,
 2550x3df5c28f, 0x3e051eb8, 0x3e0f5c29, 0x3e19999a, 0x3e23d70a, 0x3e2e147b,
 2560x3e3851ec, 0x3e428f5c, 0x3e4ccccd, 0x3e570a3d, 0x3e6147ae, 0x3e6b851f,
 2570x3e75c28f, 0x3e800000, 0x3e851eb8, 0x3e8a3d71, 0x3e8f5c29, 0x3e947ae1,
 2580x3e99999a, 0x3e9eb852, 0x3ea3d70a, 0x3ea8f5c3, 0x3eae147b, 0x3eb33333,
 2590x3eb851ec, 0x3ebd70a4, 0x3ec28f5c, 0x3ec7ae14, 0x3ecccccd, 0x3ed1eb85,
 2600x3ed70a3d, 0x3edc28f6, 0x3ee147ae, 0x3ee66666, 0x3eeb851f, 0x3ef0a3d7,
 2610x3ef5c28f, 0x3efae148, 0x3f000000, 0x3f028f5c, 0x3f051eb8, 0x3f07ae14,
 2620x3f0a3d71, 0x3f0ccccd, 0x3f0f5c29, 0x3f11eb85, 0x3f147ae1, 0x3f170a3d,
 2630x3f19999a, 0x3f1c28f6, 0x3f1eb852, 0x3f2147ae, 0x3f23d70a, 0x3f266666,
 2640x3f28f5c3, 0x3f2b851f, 0x3f2e147b, 0x3f30a3d7, 0x3f333333, 0x3f35c28f,
 2650x3f3851ec, 0x3f3ae148, 0x3f3d70a4, 0x3f400000, 0x3f428f5c, 0x3f451eb8,
 2660x3f47ae14, 0x3f4a3d71, 0x3f4ccccd, 0x3f4f5c29, 0x3f51eb85, 0x3f547ae1,
 2670x3f570a3d, 0x3f59999a, 0x3f5c28f6, 0x3f5eb852, 0x3f6147ae, 0x3f63d70a,
 2680x3f666666, 0x3f68f5c3, 0x3f6b851f, 0x3f6e147b, 0x3f70a3d7, 0x3f733333,
 2690x3f75c28f, 0x3f7851ec, 0x3f7ae148, 0x3f7d70a4, 0x3f800000
 270};
 271
 272static void podhd_set_monitor_level(struct usb_line6_podhd *podhd, int value)
 273{
 274        unsigned int fl;
 275        static const unsigned char msg[16] = {
 276                /* Chunk is 0xc bytes (without first word) */
 277                0x0c, 0x00,
 278                /* First chunk in the message */
 279                0x01, 0x00,
 280                /* Message size is 2 4-byte words */
 281                0x02, 0x00,
 282                /* Unknown */
 283                0x04, 0x41,
 284                /* Unknown */
 285                0x04, 0x00, 0x13, 0x00,
 286                /* Volume, LE float32, 0.0 - 1.0 */
 287                0x00, 0x00, 0x00, 0x00
 288        };
 289        unsigned char *buf;
 290
 291        buf = kmemdup(msg, sizeof(msg), GFP_KERNEL);
 292        if (!buf)
 293                return;
 294
 295        if (value < 0)
 296                value = 0;
 297
 298        if (value >= ARRAY_SIZE(float_zero_to_one_lookup))
 299                value = ARRAY_SIZE(float_zero_to_one_lookup) - 1;
 300
 301        fl = float_zero_to_one_lookup[value];
 302
 303        buf[12] = (fl >> 0) & 0xff;
 304        buf[13] = (fl >> 8) & 0xff;
 305        buf[14] = (fl >> 16) & 0xff;
 306        buf[15] = (fl >> 24) & 0xff;
 307
 308        line6_send_raw_message(&podhd->line6, buf, sizeof(msg));
 309        kfree(buf);
 310
 311        podhd->monitor_level = value;
 312}
 313
 314/* control info callback */
 315static int snd_podhd_control_monitor_info(struct snd_kcontrol *kcontrol,
 316                                        struct snd_ctl_elem_info *uinfo)
 317{
 318        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 319        uinfo->count = 1;
 320        uinfo->value.integer.min = 0;
 321        uinfo->value.integer.max = 100;
 322        uinfo->value.integer.step = 1;
 323        return 0;
 324}
 325
 326/* control get callback */
 327static int snd_podhd_control_monitor_get(struct snd_kcontrol *kcontrol,
 328                                       struct snd_ctl_elem_value *ucontrol)
 329{
 330        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 331        struct usb_line6_podhd *podhd = line6_to_podhd(line6pcm->line6);
 332
 333        ucontrol->value.integer.value[0] = podhd->monitor_level;
 334        return 0;
 335}
 336
 337/* control put callback */
 338static int snd_podhd_control_monitor_put(struct snd_kcontrol *kcontrol,
 339                                       struct snd_ctl_elem_value *ucontrol)
 340{
 341        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 342        struct usb_line6_podhd *podhd = line6_to_podhd(line6pcm->line6);
 343
 344        if (ucontrol->value.integer.value[0] == podhd->monitor_level)
 345                return 0;
 346
 347        podhd_set_monitor_level(podhd, ucontrol->value.integer.value[0]);
 348        return 1;
 349}
 350
 351/* control definition */
 352static const struct snd_kcontrol_new podhd_control_monitor = {
 353        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 354        .name = "Monitor Playback Volume",
 355        .index = 0,
 356        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 357        .info = snd_podhd_control_monitor_info,
 358        .get = snd_podhd_control_monitor_get,
 359        .put = snd_podhd_control_monitor_put
 360};
 361
 362/*
 363        Try to init POD HD device.
 364*/
 365static int podhd_init(struct usb_line6 *line6,
 366                      const struct usb_device_id *id)
 367{
 368        int err;
 369        struct usb_line6_podhd *pod = line6_to_podhd(line6);
 370        struct usb_interface *intf;
 371
 372        line6->disconnect = podhd_disconnect;
 373        line6->startup = podhd_startup;
 374
 375        if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
 376                /* claim the data interface */
 377                intf = usb_ifnum_to_if(line6->usbdev,
 378                                        pod->line6.properties->ctrl_if);
 379                if (!intf) {
 380                        dev_err(pod->line6.ifcdev, "interface %d not found\n",
 381                                pod->line6.properties->ctrl_if);
 382                        return -ENODEV;
 383                }
 384
 385                err = usb_driver_claim_interface(&podhd_driver, intf, NULL);
 386                if (err != 0) {
 387                        dev_err(pod->line6.ifcdev, "can't claim interface %d, error %d\n",
 388                                pod->line6.properties->ctrl_if, err);
 389                        return err;
 390                }
 391        }
 392
 393        if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) {
 394                /* create sysfs entries: */
 395                err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group);
 396                if (err < 0)
 397                        return err;
 398        }
 399
 400        if (pod->line6.properties->capabilities & LINE6_CAP_PCM) {
 401                /* initialize PCM subsystem: */
 402                err = line6_init_pcm(line6,
 403                        (id->driver_info == LINE6_PODX3 ||
 404                        id->driver_info == LINE6_PODX3LIVE) ? &podx3_pcm_properties :
 405                        &podhd_pcm_properties);
 406                if (err < 0)
 407                        return err;
 408        }
 409
 410        if (pod->line6.properties->capabilities & LINE6_CAP_HWMON_CTL) {
 411                podhd_set_monitor_level(pod, 100);
 412                err = snd_ctl_add(line6->card,
 413                                  snd_ctl_new1(&podhd_control_monitor,
 414                                               line6->line6pcm));
 415                if (err < 0)
 416                        return err;
 417        }
 418
 419        if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) {
 420                /* register USB audio system directly */
 421                return snd_card_register(line6->card);
 422        }
 423
 424        /* init device and delay registering */
 425        schedule_delayed_work(&line6->startup_work,
 426                              msecs_to_jiffies(PODHD_STARTUP_DELAY));
 427        return 0;
 428}
 429
 430#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
 431#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
 432
 433/* table of devices that work with this driver */
 434static const struct usb_device_id podhd_id_table[] = {
 435        /* TODO: no need to alloc data interfaces when only audio is used */
 436        { LINE6_DEVICE(0x5057),    .driver_info = LINE6_PODHD300 },
 437        { LINE6_DEVICE(0x5058),    .driver_info = LINE6_PODHD400 },
 438        { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500 },
 439        { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 },
 440        { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE },
 441        { LINE6_IF_NUM(0x4159, 0), .driver_info = LINE6_PODHD500X },
 442        { LINE6_IF_NUM(0x4156, 0), .driver_info = LINE6_PODHDDESKTOP },
 443        {}
 444};
 445
 446MODULE_DEVICE_TABLE(usb, podhd_id_table);
 447
 448static const struct line6_properties podhd_properties_table[] = {
 449        [LINE6_PODHD300] = {
 450                .id = "PODHD300",
 451                .name = "POD HD300",
 452                .capabilities   = LINE6_CAP_PCM
 453                                | LINE6_CAP_HWMON,
 454                .altsetting = 5,
 455                .ep_ctrl_r = 0x84,
 456                .ep_ctrl_w = 0x03,
 457                .ep_audio_r = 0x82,
 458                .ep_audio_w = 0x01,
 459        },
 460        [LINE6_PODHD400] = {
 461                .id = "PODHD400",
 462                .name = "POD HD400",
 463                .capabilities   = LINE6_CAP_PCM
 464                                | LINE6_CAP_HWMON,
 465                .altsetting = 5,
 466                .ep_ctrl_r = 0x84,
 467                .ep_ctrl_w = 0x03,
 468                .ep_audio_r = 0x82,
 469                .ep_audio_w = 0x01,
 470        },
 471        [LINE6_PODHD500] = {
 472                .id = "PODHD500",
 473                .name = "POD HD500",
 474                .capabilities   = LINE6_CAP_PCM | LINE6_CAP_CONTROL
 475                                | LINE6_CAP_HWMON | LINE6_CAP_HWMON_CTL,
 476                .altsetting = 1,
 477                .ctrl_if = 1,
 478                .ep_ctrl_r = 0x81,
 479                .ep_ctrl_w = 0x01,
 480                .ep_audio_r = 0x86,
 481                .ep_audio_w = 0x02,
 482        },
 483        [LINE6_PODX3] = {
 484                .id = "PODX3",
 485                .name = "POD X3",
 486                .capabilities   = LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO
 487                                | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT,
 488                .altsetting = 1,
 489                .ep_ctrl_r = 0x81,
 490                .ep_ctrl_w = 0x01,
 491                .ctrl_if = 1,
 492                .ep_audio_r = 0x86,
 493                .ep_audio_w = 0x02,
 494        },
 495        [LINE6_PODX3LIVE] = {
 496                .id = "PODX3LIVE",
 497                .name = "POD X3 LIVE",
 498                .capabilities   = LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO
 499                                | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT,
 500                .altsetting = 1,
 501                .ep_ctrl_r = 0x81,
 502                .ep_ctrl_w = 0x01,
 503                .ctrl_if = 1,
 504                .ep_audio_r = 0x86,
 505                .ep_audio_w = 0x02,
 506        },
 507        [LINE6_PODHD500X] = {
 508                .id = "PODHD500X",
 509                .name = "POD HD500X",
 510                .capabilities   = LINE6_CAP_CONTROL
 511                                | LINE6_CAP_PCM | LINE6_CAP_HWMON,
 512                .altsetting = 1,
 513                .ep_ctrl_r = 0x81,
 514                .ep_ctrl_w = 0x01,
 515                .ctrl_if = 1,
 516                .ep_audio_r = 0x86,
 517                .ep_audio_w = 0x02,
 518        },
 519        [LINE6_PODHDDESKTOP] = {
 520                .id = "PODHDDESKTOP",
 521                .name = "POD HDDESKTOP",
 522                .capabilities    = LINE6_CAP_CONTROL
 523                        | LINE6_CAP_PCM | LINE6_CAP_HWMON,
 524                .altsetting = 1,
 525                .ep_ctrl_r = 0x81,
 526                .ep_ctrl_w = 0x01,
 527                .ctrl_if = 1,
 528                .ep_audio_r = 0x86,
 529                .ep_audio_w = 0x02,
 530        },
 531};
 532
 533/*
 534        Probe USB device.
 535*/
 536static int podhd_probe(struct usb_interface *interface,
 537                       const struct usb_device_id *id)
 538{
 539        return line6_probe(interface, id, "Line6-PODHD",
 540                           &podhd_properties_table[id->driver_info],
 541                           podhd_init, sizeof(struct usb_line6_podhd));
 542}
 543
 544static struct usb_driver podhd_driver = {
 545        .name = KBUILD_MODNAME,
 546        .probe = podhd_probe,
 547        .disconnect = line6_disconnect,
 548#ifdef CONFIG_PM
 549        .suspend = line6_suspend,
 550        .resume = line6_resume,
 551        .reset_resume = line6_resume,
 552#endif
 553        .id_table = podhd_id_table,
 554};
 555
 556module_usb_driver(podhd_driver);
 557
 558MODULE_DESCRIPTION("Line 6 PODHD USB driver");
 559MODULE_LICENSE("GPL");
 560