toneport.c revision 188e664502dc47f83775a556e6db52cd8cc0b5fc
1/* 2 * Line6 Linux USB driver - 0.9.1beta 3 * 4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) 5 * Emil Myhrman (emil.myhrman@gmail.com) 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation, version 2. 10 * 11 */ 12 13#include <linux/wait.h> 14#include <sound/control.h> 15 16#include "audio.h" 17#include "capture.h" 18#include "driver.h" 19#include "playback.h" 20#include "toneport.h" 21 22static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); 23 24#define TONEPORT_PCM_DELAY 1 25 26static struct snd_ratden toneport_ratden = { 27 .num_min = 44100, 28 .num_max = 44100, 29 .num_step = 1, 30 .den = 1 31}; 32 33static struct line6_pcm_properties toneport_pcm_properties = { 34 .snd_line6_playback_hw = { 35 .info = (SNDRV_PCM_INFO_MMAP | 36 SNDRV_PCM_INFO_INTERLEAVED | 37 SNDRV_PCM_INFO_BLOCK_TRANSFER | 38 SNDRV_PCM_INFO_MMAP_VALID | 39 SNDRV_PCM_INFO_PAUSE | 40#ifdef CONFIG_PM 41 SNDRV_PCM_INFO_RESUME | 42#endif 43 SNDRV_PCM_INFO_SYNC_START), 44 .formats = SNDRV_PCM_FMTBIT_S16_LE, 45 .rates = SNDRV_PCM_RATE_KNOT, 46 .rate_min = 44100, 47 .rate_max = 44100, 48 .channels_min = 2, 49 .channels_max = 2, 50 .buffer_bytes_max = 60000, 51 .period_bytes_min = 64, 52 .period_bytes_max = 8192, 53 .periods_min = 1, 54 .periods_max = 1024}, 55 .snd_line6_capture_hw = { 56 .info = (SNDRV_PCM_INFO_MMAP | 57 SNDRV_PCM_INFO_INTERLEAVED | 58 SNDRV_PCM_INFO_BLOCK_TRANSFER | 59 SNDRV_PCM_INFO_MMAP_VALID | 60#ifdef CONFIG_PM 61 SNDRV_PCM_INFO_RESUME | 62#endif 63 SNDRV_PCM_INFO_SYNC_START), 64 .formats = SNDRV_PCM_FMTBIT_S16_LE, 65 .rates = SNDRV_PCM_RATE_KNOT, 66 .rate_min = 44100, 67 .rate_max = 44100, 68 .channels_min = 2, 69 .channels_max = 2, 70 .buffer_bytes_max = 60000, 71 .period_bytes_min = 64, 72 .period_bytes_max = 8192, 73 .periods_min = 1, 74 .periods_max = 1024}, 75 .snd_line6_rates = { 76 .nrats = 1, 77 .rats = &toneport_ratden}, 78 .bytes_per_frame = 4 79}; 80 81/* 82 For the led on Guitarport. 83 Brightness goes from 0x00 to 0x26. Set a value above this to have led 84 blink. 85 (void cmd_0x02(byte red, byte green) 86*/ 87static int led_red = 0x00; 88static int led_green = 0x26; 89 90struct ToneportSourceInfo { 91 const char *name; 92 int code; 93}; 94 95static const struct ToneportSourceInfo toneport_source_info[] = { 96 {"Microphone", 0x0a01}, 97 {"Line", 0x0801}, 98 {"Instrument", 0x0b01}, 99 {"Inst & Mic", 0x0901} 100}; 101 102static bool toneport_has_led(short product) 103{ 104 return 105 (product == LINE6_DEVID_GUITARPORT) || 106 (product == LINE6_DEVID_TONEPORT_GX); 107 /* add your device here if you are missing support for the LEDs */ 108} 109 110static void toneport_update_led(struct device *dev) 111{ 112 struct usb_interface *interface = to_usb_interface(dev); 113 struct usb_line6_toneport *tp = usb_get_intfdata(interface); 114 struct usb_line6 *line6; 115 116 if (!tp) 117 return; 118 119 line6 = &tp->line6; 120 if (line6) 121 toneport_send_cmd(line6->usbdev, (led_red << 8) | 0x0002, 122 led_green); 123} 124 125static ssize_t toneport_set_led_red(struct device *dev, 126 struct device_attribute *attr, 127 const char *buf, size_t count) 128{ 129 int retval; 130 long value; 131 132 retval = strict_strtol(buf, 10, &value); 133 if (retval) 134 return retval; 135 136 led_red = value; 137 toneport_update_led(dev); 138 return count; 139} 140 141static ssize_t toneport_set_led_green(struct device *dev, 142 struct device_attribute *attr, 143 const char *buf, size_t count) 144{ 145 int retval; 146 long value; 147 148 retval = strict_strtol(buf, 10, &value); 149 if (retval) 150 return retval; 151 152 led_green = value; 153 toneport_update_led(dev); 154 return count; 155} 156 157static DEVICE_ATTR(led_red, S_IWUSR | S_IRUGO, line6_nop_read, 158 toneport_set_led_red); 159static DEVICE_ATTR(led_green, S_IWUSR | S_IRUGO, line6_nop_read, 160 toneport_set_led_green); 161 162static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) 163{ 164 int ret; 165 166 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, 167 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 168 cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ); 169 170 if (ret < 0) { 171 err("send failed (error %d)\n", ret); 172 return ret; 173 } 174 175 return 0; 176} 177 178/* monitor info callback */ 179static int snd_toneport_monitor_info(struct snd_kcontrol *kcontrol, 180 struct snd_ctl_elem_info *uinfo) 181{ 182 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 183 uinfo->count = 1; 184 uinfo->value.integer.min = 0; 185 uinfo->value.integer.max = 256; 186 return 0; 187} 188 189/* monitor get callback */ 190static int snd_toneport_monitor_get(struct snd_kcontrol *kcontrol, 191 struct snd_ctl_elem_value *ucontrol) 192{ 193 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 194 ucontrol->value.integer.value[0] = line6pcm->volume_monitor; 195 return 0; 196} 197 198/* monitor put callback */ 199static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol, 200 struct snd_ctl_elem_value *ucontrol) 201{ 202 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 203 204 if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor) 205 return 0; 206 207 line6pcm->volume_monitor = ucontrol->value.integer.value[0]; 208 209 if (line6pcm->volume_monitor > 0) 210 line6_pcm_start(line6pcm, MASK_PCM_MONITOR); 211 else 212 line6_pcm_stop(line6pcm, MASK_PCM_MONITOR); 213 214 return 1; 215} 216 217/* source info callback */ 218static int snd_toneport_source_info(struct snd_kcontrol *kcontrol, 219 struct snd_ctl_elem_info *uinfo) 220{ 221 const int size = ARRAY_SIZE(toneport_source_info); 222 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 223 uinfo->count = 1; 224 uinfo->value.enumerated.items = size; 225 226 if (uinfo->value.enumerated.item >= size) 227 uinfo->value.enumerated.item = size - 1; 228 229 strcpy(uinfo->value.enumerated.name, 230 toneport_source_info[uinfo->value.enumerated.item].name); 231 232 return 0; 233} 234 235/* source get callback */ 236static int snd_toneport_source_get(struct snd_kcontrol *kcontrol, 237 struct snd_ctl_elem_value *ucontrol) 238{ 239 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 240 struct usb_line6_toneport *toneport = 241 (struct usb_line6_toneport *)line6pcm->line6; 242 ucontrol->value.enumerated.item[0] = toneport->source; 243 return 0; 244} 245 246/* source put callback */ 247static int snd_toneport_source_put(struct snd_kcontrol *kcontrol, 248 struct snd_ctl_elem_value *ucontrol) 249{ 250 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 251 struct usb_line6_toneport *toneport = 252 (struct usb_line6_toneport *)line6pcm->line6; 253 254 if (ucontrol->value.enumerated.item[0] == toneport->source) 255 return 0; 256 257 toneport->source = ucontrol->value.enumerated.item[0]; 258 toneport_send_cmd(toneport->line6.usbdev, 259 toneport_source_info[toneport->source].code, 0x0000); 260 return 1; 261} 262 263static void toneport_start_pcm(unsigned long arg) 264{ 265 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg; 266 struct usb_line6 *line6 = &toneport->line6; 267 line6_pcm_start(line6->line6pcm, MASK_PCM_MONITOR); 268} 269 270/* control definition */ 271static struct snd_kcontrol_new toneport_control_monitor = { 272 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 273 .name = "Monitor Playback Volume", 274 .index = 0, 275 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 276 .info = snd_toneport_monitor_info, 277 .get = snd_toneport_monitor_get, 278 .put = snd_toneport_monitor_put 279}; 280 281/* source selector definition */ 282static struct snd_kcontrol_new toneport_control_source = { 283 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 284 .name = "PCM Capture Source", 285 .index = 0, 286 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 287 .info = snd_toneport_source_info, 288 .get = snd_toneport_source_get, 289 .put = snd_toneport_source_put 290}; 291 292/* 293 Toneport destructor. 294*/ 295static void toneport_destruct(struct usb_interface *interface) 296{ 297 struct usb_line6_toneport *toneport = usb_get_intfdata(interface); 298 299 if (toneport == NULL) 300 return; 301 line6_cleanup_audio(&toneport->line6); 302} 303 304/* 305 Setup Toneport device. 306*/ 307static void toneport_setup(struct usb_line6_toneport *toneport) 308{ 309 int ticks; 310 struct usb_line6 *line6 = &toneport->line6; 311 struct usb_device *usbdev = line6->usbdev; 312 313 /* sync time on device with host: */ 314 ticks = (int)get_seconds(); 315 line6_write_data(line6, 0x80c6, &ticks, 4); 316 317 /* enable device: */ 318 toneport_send_cmd(usbdev, 0x0301, 0x0000); 319 320 /* initialize source select: */ 321 switch (usbdev->descriptor.idProduct) { 322 case LINE6_DEVID_TONEPORT_UX1: 323 case LINE6_DEVID_PODSTUDIO_UX1: 324 toneport_send_cmd(usbdev, 325 toneport_source_info[toneport->source].code, 326 0x0000); 327 } 328 329 if (toneport_has_led(usbdev->descriptor.idProduct)) 330 toneport_update_led(&usbdev->dev); 331} 332 333/* 334 Try to init Toneport device. 335*/ 336static int toneport_try_init(struct usb_interface *interface, 337 struct usb_line6_toneport *toneport) 338{ 339 int err; 340 struct usb_line6 *line6 = &toneport->line6; 341 struct usb_device *usbdev = line6->usbdev; 342 343 if ((interface == NULL) || (toneport == NULL)) 344 return -ENODEV; 345 346 /* initialize audio system: */ 347 err = line6_init_audio(line6); 348 if (err < 0) 349 return err; 350 351 /* initialize PCM subsystem: */ 352 err = line6_init_pcm(line6, &toneport_pcm_properties); 353 if (err < 0) 354 return err; 355 356 /* register monitor control: */ 357 err = snd_ctl_add(line6->card, 358 snd_ctl_new1(&toneport_control_monitor, 359 line6->line6pcm)); 360 if (err < 0) 361 return err; 362 363 /* register source select control: */ 364 switch (usbdev->descriptor.idProduct) { 365 case LINE6_DEVID_TONEPORT_UX1: 366 case LINE6_DEVID_PODSTUDIO_UX1: 367 err = 368 snd_ctl_add(line6->card, 369 snd_ctl_new1(&toneport_control_source, 370 line6->line6pcm)); 371 if (err < 0) 372 return err; 373 } 374 375 /* register audio system: */ 376 err = line6_register_audio(line6); 377 if (err < 0) 378 return err; 379 380 line6_read_serial_number(line6, &toneport->serial_number); 381 line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); 382 383 if (toneport_has_led(usbdev->descriptor.idProduct)) { 384 CHECK_RETURN(device_create_file 385 (&interface->dev, &dev_attr_led_red)); 386 CHECK_RETURN(device_create_file 387 (&interface->dev, &dev_attr_led_green)); 388 } 389 390 toneport_setup(toneport); 391 392 init_timer(&toneport->timer); 393 toneport->timer.expires = jiffies + TONEPORT_PCM_DELAY * HZ; 394 toneport->timer.function = toneport_start_pcm; 395 toneport->timer.data = (unsigned long)toneport; 396 add_timer(&toneport->timer); 397 398 return 0; 399} 400 401/* 402 Init Toneport device (and clean up in case of failure). 403*/ 404int line6_toneport_init(struct usb_interface *interface, 405 struct usb_line6_toneport *toneport) 406{ 407 int err = toneport_try_init(interface, toneport); 408 409 if (err < 0) 410 toneport_destruct(interface); 411 412 return err; 413} 414 415/* 416 Resume Toneport device after reset. 417*/ 418void line6_toneport_reset_resume(struct usb_line6_toneport *toneport) 419{ 420 toneport_setup(toneport); 421} 422 423/* 424 Toneport device disconnected. 425*/ 426void line6_toneport_disconnect(struct usb_interface *interface) 427{ 428 struct usb_line6_toneport *toneport; 429 430 if (interface == NULL) 431 return; 432 433 toneport = usb_get_intfdata(interface); 434 del_timer_sync(&toneport->timer); 435 436 if (toneport_has_led(toneport->line6.usbdev->descriptor.idProduct)) { 437 device_remove_file(&interface->dev, &dev_attr_led_red); 438 device_remove_file(&interface->dev, &dev_attr_led_green); 439 } 440 441 if (toneport != NULL) { 442 struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm; 443 444 if (line6pcm != NULL) { 445 line6_pcm_stop(line6pcm, MASK_PCM_MONITOR); 446 line6_pcm_disconnect(line6pcm); 447 } 448 } 449 450 toneport_destruct(interface); 451} 452