1/* 2 * Line6 Linux USB driver - 0.8.0 3 * 4 * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) 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 "driver.h" 13 14#include <linux/slab.h> 15 16#include <sound/core.h> 17#include <sound/control.h> 18#include <sound/pcm.h> 19#include <sound/pcm_params.h> 20 21#include "audio.h" 22#include "capture.h" 23#include "playback.h" 24#include "pod.h" 25 26 27/* trigger callback */ 28int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) 29{ 30 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 31 struct snd_pcm_substream *s; 32 int err; 33 unsigned long flags; 34 35 spin_lock_irqsave(&line6pcm->lock_trigger, flags); 36 clear_bit(BIT_PREPARED, &line6pcm->flags); 37 38 snd_pcm_group_for_each_entry(s, substream) { 39 switch (s->stream) { 40 case SNDRV_PCM_STREAM_PLAYBACK: 41 err = snd_line6_playback_trigger(s, cmd); 42 43 if (err < 0) { 44 spin_unlock_irqrestore(&line6pcm->lock_trigger, 45 flags); 46 return err; 47 } 48 49 break; 50 51 case SNDRV_PCM_STREAM_CAPTURE: 52 err = snd_line6_capture_trigger(s, cmd); 53 54 if (err < 0) { 55 spin_unlock_irqrestore(&line6pcm->lock_trigger, 56 flags); 57 return err; 58 } 59 60 break; 61 62 default: 63 dev_err(s2m(substream), "Unknown stream direction %d\n", 64 s->stream); 65 } 66 } 67 68 spin_unlock_irqrestore(&line6pcm->lock_trigger, flags); 69 return 0; 70} 71 72/* control info callback */ 73static int snd_line6_control_info(struct snd_kcontrol *kcontrol, 74 struct snd_ctl_elem_info *uinfo) 75{ 76 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 77 uinfo->count = 2; 78 uinfo->value.integer.min = 0; 79 uinfo->value.integer.max = 256; 80 return 0; 81} 82 83/* control get callback */ 84static int snd_line6_control_get(struct snd_kcontrol *kcontrol, 85 struct snd_ctl_elem_value *ucontrol) 86{ 87 int i; 88 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 89 90 for (i = 2; i--;) 91 ucontrol->value.integer.value[i] = line6pcm->volume[i]; 92 93 return 0; 94} 95 96/* control put callback */ 97static int snd_line6_control_put(struct snd_kcontrol *kcontrol, 98 struct snd_ctl_elem_value *ucontrol) 99{ 100 int i, changed = 0; 101 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 102 103 for (i = 2; i--;) 104 if (line6pcm->volume[i] != ucontrol->value.integer.value[i]) { 105 line6pcm->volume[i] = ucontrol->value.integer.value[i]; 106 changed = 1; 107 } 108 109 return changed; 110} 111 112/* control definition */ 113static struct snd_kcontrol_new line6_control = { 114 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 115 .name = "PCM Playback Volume", 116 .index = 0, 117 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 118 .info = snd_line6_control_info, 119 .get = snd_line6_control_get, 120 .put = snd_line6_control_put 121}; 122 123/* 124 Cleanup the PCM device. 125*/ 126static void line6_cleanup_pcm(struct snd_pcm *pcm) 127{ 128 int i; 129 struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm); 130 131 for (i = LINE6_ISO_BUFFERS; i--;) { 132 if (line6pcm->urb_audio_out[i]) { 133 usb_kill_urb(line6pcm->urb_audio_out[i]); 134 usb_free_urb(line6pcm->urb_audio_out[i]); 135 } 136 if (line6pcm->urb_audio_in[i]) { 137 usb_kill_urb(line6pcm->urb_audio_in[i]); 138 usb_free_urb(line6pcm->urb_audio_in[i]); 139 } 140 } 141} 142 143/* create a PCM device */ 144static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm) 145{ 146 struct snd_pcm *pcm; 147 int err; 148 149 err = snd_pcm_new(line6pcm->line6->card, 150 (char *)line6pcm->line6->properties->name, 151 0, 1, 1, &pcm); 152 if (err < 0) 153 return err; 154 155 pcm->private_data = line6pcm; 156 pcm->private_free = line6_cleanup_pcm; 157 line6pcm->pcm = pcm; 158 strcpy(pcm->name, line6pcm->line6->properties->name); 159 160 /* set operators */ 161 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 162 &snd_line6_playback_ops); 163 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops); 164 165 /* pre-allocation of buffers */ 166 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, 167 snd_dma_continuous_data(GFP_KERNEL), 168 64 * 1024, 128 * 1024); 169 170 return 0; 171} 172 173/* PCM device destructor */ 174static int snd_line6_pcm_free(struct snd_device *device) 175{ 176 return 0; 177} 178 179/* 180 Create and register the PCM device and mixer entries. 181 Create URBs for playback and capture. 182*/ 183int line6_init_pcm(struct usb_line6 *line6, 184 struct line6_pcm_properties *properties) 185{ 186 static struct snd_device_ops pcm_ops = { 187 .dev_free = snd_line6_pcm_free, 188 }; 189 190 int err; 191 int ep_read = 0, ep_write = 0; 192 struct snd_line6_pcm *line6pcm; 193 194 if (!(line6->properties->capabilities & LINE6_BIT_PCM)) 195 return 0; /* skip PCM initialization and report success */ 196 197 /* initialize PCM subsystem based on product id: */ 198 switch (line6->product) { 199 case LINE6_DEVID_BASSPODXT: 200 case LINE6_DEVID_BASSPODXTLIVE: 201 case LINE6_DEVID_BASSPODXTPRO: 202 case LINE6_DEVID_PODXT: 203 case LINE6_DEVID_PODXTLIVE: 204 case LINE6_DEVID_PODXTPRO: 205 ep_read = 0x82; 206 ep_write = 0x01; 207 break; 208 209 case LINE6_DEVID_PODX3: 210 case LINE6_DEVID_PODX3LIVE: 211 ep_read = 0x86; 212 ep_write = 0x02; 213 break; 214 215 case LINE6_DEVID_POCKETPOD: 216 ep_read = 0x82; 217 ep_write = 0x02; 218 break; 219 220 case LINE6_DEVID_GUITARPORT: 221 case LINE6_DEVID_TONEPORT_GX: 222 ep_read = 0x82; 223 ep_write = 0x01; 224 break; 225 226 case LINE6_DEVID_TONEPORT_UX1: 227 ep_read = 0x00; 228 ep_write = 0x00; 229 break; 230 231 case LINE6_DEVID_TONEPORT_UX2: 232 ep_read = 0x87; 233 ep_write = 0x00; 234 break; 235 236 default: 237 MISSING_CASE; 238 } 239 240 line6pcm = kzalloc(sizeof(struct snd_line6_pcm), GFP_KERNEL); 241 242 if (line6pcm == NULL) 243 return -ENOMEM; 244 245 line6pcm->volume[0] = line6pcm->volume[1] = 128; 246 line6pcm->line6 = line6; 247 line6pcm->ep_audio_read = ep_read; 248 line6pcm->ep_audio_write = ep_write; 249 line6pcm->max_packet_size = usb_maxpacket(line6->usbdev, 250 usb_rcvintpipe(line6->usbdev, 251 ep_read), 252 0); 253 line6pcm->properties = properties; 254 line6->line6pcm = line6pcm; 255 256 /* PCM device: */ 257 err = snd_device_new(line6->card, SNDRV_DEV_PCM, line6, &pcm_ops); 258 if (err < 0) 259 return err; 260 261 snd_card_set_dev(line6->card, line6->ifcdev); 262 263 err = snd_line6_new_pcm(line6pcm); 264 if (err < 0) 265 return err; 266 267 spin_lock_init(&line6pcm->lock_audio_out); 268 spin_lock_init(&line6pcm->lock_audio_in); 269 spin_lock_init(&line6pcm->lock_trigger); 270 271 err = create_audio_out_urbs(line6pcm); 272 if (err < 0) 273 return err; 274 275 err = create_audio_in_urbs(line6pcm); 276 if (err < 0) 277 return err; 278 279 /* mixer: */ 280 err = snd_ctl_add(line6->card, snd_ctl_new1(&line6_control, line6pcm)); 281 if (err < 0) 282 return err; 283 284 return 0; 285} 286 287/* prepare pcm callback */ 288int snd_line6_prepare(struct snd_pcm_substream *substream) 289{ 290 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 291 292 if (!test_and_set_bit(BIT_PREPARED, &line6pcm->flags)) { 293 unlink_wait_clear_audio_out_urbs(line6pcm); 294 line6pcm->pos_out = 0; 295 line6pcm->pos_out_done = 0; 296 297 unlink_wait_clear_audio_in_urbs(line6pcm); 298 line6pcm->bytes_out = 0; 299 line6pcm->pos_in_done = 0; 300 line6pcm->bytes_in = 0; 301 } 302 303 return 0; 304} 305