1/* 2 * Line 6 Pod HD 3 * 4 * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation, version 2. 9 * 10 */ 11 12#include <linux/usb.h> 13#include <linux/slab.h> 14#include <linux/module.h> 15#include <sound/core.h> 16#include <sound/pcm.h> 17 18#include "driver.h" 19#include "pcm.h" 20 21enum { 22 LINE6_PODHD300, 23 LINE6_PODHD400, 24 LINE6_PODHD500_0, 25 LINE6_PODHD500_1, 26}; 27 28#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ 29 30static struct snd_ratden podhd_ratden = { 31 .num_min = 48000, 32 .num_max = 48000, 33 .num_step = 1, 34 .den = 1, 35}; 36 37static struct line6_pcm_properties podhd_pcm_properties = { 38 .playback_hw = { 39 .info = (SNDRV_PCM_INFO_MMAP | 40 SNDRV_PCM_INFO_INTERLEAVED | 41 SNDRV_PCM_INFO_BLOCK_TRANSFER | 42 SNDRV_PCM_INFO_MMAP_VALID | 43 SNDRV_PCM_INFO_PAUSE | 44 SNDRV_PCM_INFO_SYNC_START), 45 .formats = SNDRV_PCM_FMTBIT_S24_3LE, 46 .rates = SNDRV_PCM_RATE_48000, 47 .rate_min = 48000, 48 .rate_max = 48000, 49 .channels_min = 2, 50 .channels_max = 2, 51 .buffer_bytes_max = 60000, 52 .period_bytes_min = 64, 53 .period_bytes_max = 8192, 54 .periods_min = 1, 55 .periods_max = 1024}, 56 .capture_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_SYNC_START), 62 .formats = SNDRV_PCM_FMTBIT_S24_3LE, 63 .rates = SNDRV_PCM_RATE_48000, 64 .rate_min = 48000, 65 .rate_max = 48000, 66 .channels_min = 2, 67 .channels_max = 2, 68 .buffer_bytes_max = 60000, 69 .period_bytes_min = 64, 70 .period_bytes_max = 8192, 71 .periods_min = 1, 72 .periods_max = 1024}, 73 .rates = { 74 .nrats = 1, 75 .rats = &podhd_ratden}, 76 .bytes_per_frame = PODHD_BYTES_PER_FRAME 77}; 78 79/* 80 Try to init POD HD device. 81*/ 82static int podhd_init(struct usb_line6 *line6, 83 const struct usb_device_id *id) 84{ 85 int err; 86 87 /* initialize MIDI subsystem: */ 88 err = line6_init_midi(line6); 89 if (err < 0) 90 return err; 91 92 /* initialize PCM subsystem: */ 93 err = line6_init_pcm(line6, &podhd_pcm_properties); 94 if (err < 0) 95 return err; 96 97 /* register USB audio system: */ 98 return snd_card_register(line6->card); 99} 100 101#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod) 102#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n) 103 104/* table of devices that work with this driver */ 105static const struct usb_device_id podhd_id_table[] = { 106 { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 }, 107 { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 }, 108 { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 }, 109 { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 }, 110 {} 111}; 112 113MODULE_DEVICE_TABLE(usb, podhd_id_table); 114 115static const struct line6_properties podhd_properties_table[] = { 116 [LINE6_PODHD300] = { 117 .id = "PODHD300", 118 .name = "POD HD300", 119 .capabilities = LINE6_CAP_CONTROL 120 | LINE6_CAP_PCM 121 | LINE6_CAP_HWMON, 122 .altsetting = 5, 123 .ep_ctrl_r = 0x84, 124 .ep_ctrl_w = 0x03, 125 .ep_audio_r = 0x82, 126 .ep_audio_w = 0x01, 127 }, 128 [LINE6_PODHD400] = { 129 .id = "PODHD400", 130 .name = "POD HD400", 131 .capabilities = LINE6_CAP_CONTROL 132 | LINE6_CAP_PCM 133 | LINE6_CAP_HWMON, 134 .altsetting = 5, 135 .ep_ctrl_r = 0x84, 136 .ep_ctrl_w = 0x03, 137 .ep_audio_r = 0x82, 138 .ep_audio_w = 0x01, 139 }, 140 [LINE6_PODHD500_0] = { 141 .id = "PODHD500", 142 .name = "POD HD500", 143 .capabilities = LINE6_CAP_CONTROL 144 | LINE6_CAP_PCM 145 | LINE6_CAP_HWMON, 146 .altsetting = 1, 147 .ep_ctrl_r = 0x81, 148 .ep_ctrl_w = 0x01, 149 .ep_audio_r = 0x86, 150 .ep_audio_w = 0x02, 151 }, 152 [LINE6_PODHD500_1] = { 153 .id = "PODHD500", 154 .name = "POD HD500", 155 .capabilities = LINE6_CAP_CONTROL 156 | LINE6_CAP_PCM 157 | LINE6_CAP_HWMON, 158 .altsetting = 1, 159 .ep_ctrl_r = 0x81, 160 .ep_ctrl_w = 0x01, 161 .ep_audio_r = 0x86, 162 .ep_audio_w = 0x02, 163 }, 164}; 165 166/* 167 Probe USB device. 168*/ 169static int podhd_probe(struct usb_interface *interface, 170 const struct usb_device_id *id) 171{ 172 return line6_probe(interface, id, "Line6-PODHD", 173 &podhd_properties_table[id->driver_info], 174 podhd_init, sizeof(struct usb_line6)); 175} 176 177static struct usb_driver podhd_driver = { 178 .name = KBUILD_MODNAME, 179 .probe = podhd_probe, 180 .disconnect = line6_disconnect, 181#ifdef CONFIG_PM 182 .suspend = line6_suspend, 183 .resume = line6_resume, 184 .reset_resume = line6_resume, 185#endif 186 .id_table = podhd_id_table, 187}; 188 189module_usb_driver(podhd_driver); 190 191MODULE_DESCRIPTION("Line 6 PODHD USB driver"); 192MODULE_LICENSE("GPL"); 193