Merge tag 'mfd-3.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
[deliverable/linux.git] / drivers / staging / line6 / toneport.c
CommitLineData
705ececd 1/*
e1a164d7 2 * Line6 Linux USB driver - 0.9.1beta
705ececd 3 *
1027f476 4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
705ececd
MG
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
1027f476
MG
13#include <linux/wait.h>
14#include <sound/control.h>
705ececd
MG
15
16#include "audio.h"
17#include "capture.h"
1027f476 18#include "driver.h"
705ececd
MG
19#include "playback.h"
20#include "toneport.h"
21
705ececd
MG
22static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
23
1027f476
MG
24#define TONEPORT_PCM_DELAY 1
25
705ececd
MG
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 = {
63a4a8ba 34 .snd_line6_playback_hw = {
e1a164d7
MG
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 |
1027f476 40#ifdef CONFIG_PM
e1a164d7 41 SNDRV_PCM_INFO_RESUME |
1027f476 42#endif
e1a164d7
MG
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},
63a4a8ba 55 .snd_line6_capture_hw = {
e1a164d7
MG
56 .info = (SNDRV_PCM_INFO_MMAP |
57 SNDRV_PCM_INFO_INTERLEAVED |
58 SNDRV_PCM_INFO_BLOCK_TRANSFER |
59 SNDRV_PCM_INFO_MMAP_VALID |
1027f476 60#ifdef CONFIG_PM
e1a164d7 61 SNDRV_PCM_INFO_RESUME |
1027f476 62#endif
e1a164d7
MG
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},
705ececd 75 .snd_line6_rates = {
e1a164d7
MG
76 .nrats = 1,
77 .rats = &toneport_ratden},
705ececd
MG
78 .bytes_per_frame = 4
79};
80
81/*
82 For the led on Guitarport.
6353773b
GKH
83 Brightness goes from 0x00 to 0x26. Set a value above this to have led
84 blink.
705ececd
MG
85 (void cmd_0x02(byte red, byte green)
86*/
87static int led_red = 0x00;
88static int led_green = 0x26;
89
e1a164d7 90struct ToneportSourceInfo {
1027f476
MG
91 const char *name;
92 int code;
93};
94
95static const struct ToneportSourceInfo toneport_source_info[] = {
e1a164d7
MG
96 {"Microphone", 0x0a01},
97 {"Line", 0x0801},
98 {"Instrument", 0x0b01},
99 {"Inst & Mic", 0x0901}
1027f476
MG
100};
101
102static bool toneport_has_led(short product)
103{
104 return
e1a164d7
MG
105 (product == LINE6_DEVID_GUITARPORT) ||
106 (product == LINE6_DEVID_TONEPORT_GX);
1027f476
MG
107 /* add your device here if you are missing support for the LEDs */
108}
109
6353773b
GKH
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;
705ececd 115
6353773b
GKH
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);
705ececd 123}
6353773b 124
77491e52
GKH
125static ssize_t toneport_set_led_red(struct device *dev,
126 struct device_attribute *attr,
6353773b
GKH
127 const char *buf, size_t count)
128{
bb950a16 129 int retval;
bb950a16 130
b07d9452 131 retval = kstrtoint(buf, 10, &led_red);
bb950a16
SB
132 if (retval)
133 return retval;
134
705ececd
MG
135 toneport_update_led(dev);
136 return count;
137}
6353773b 138
77491e52
GKH
139static ssize_t toneport_set_led_green(struct device *dev,
140 struct device_attribute *attr,
6353773b
GKH
141 const char *buf, size_t count)
142{
bb950a16 143 int retval;
bb950a16 144
b07d9452 145 retval = kstrtoint(buf, 10, &led_green);
bb950a16
SB
146 if (retval)
147 return retval;
148
705ececd
MG
149 toneport_update_led(dev);
150 return count;
151}
152
a3a972a0 153static DEVICE_ATTR(led_red, S_IWUSR | S_IRUGO, line6_nop_read,
63a4a8ba 154 toneport_set_led_red);
a3a972a0 155static DEVICE_ATTR(led_green, S_IWUSR | S_IRUGO, line6_nop_read,
63a4a8ba 156 toneport_set_led_green);
705ececd
MG
157
158static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
159{
160 int ret;
705ececd 161
6353773b
GKH
162 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
163 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
164 cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ);
165
166 if (ret < 0) {
d86938fb 167 dev_err(&usbdev->dev, "send failed (error %d)\n", ret);
705ececd
MG
168 return ret;
169 }
170
171 return 0;
172}
173
1027f476
MG
174/* monitor info callback */
175static int snd_toneport_monitor_info(struct snd_kcontrol *kcontrol,
176 struct snd_ctl_elem_info *uinfo)
177{
178 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
179 uinfo->count = 1;
180 uinfo->value.integer.min = 0;
181 uinfo->value.integer.max = 256;
182 return 0;
183}
184
185/* monitor get callback */
186static int snd_toneport_monitor_get(struct snd_kcontrol *kcontrol,
187 struct snd_ctl_elem_value *ucontrol)
188{
189 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
190 ucontrol->value.integer.value[0] = line6pcm->volume_monitor;
191 return 0;
192}
193
194/* monitor put callback */
195static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
196 struct snd_ctl_elem_value *ucontrol)
197{
198 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
199
e1a164d7 200 if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor)
1027f476
MG
201 return 0;
202
203 line6pcm->volume_monitor = ucontrol->value.integer.value[0];
e1a164d7
MG
204
205 if (line6pcm->volume_monitor > 0)
0ca54888 206 line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_MONITOR);
e1a164d7 207 else
0ca54888 208 line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR);
e1a164d7 209
1027f476
MG
210 return 1;
211}
212
213/* source info callback */
214static int snd_toneport_source_info(struct snd_kcontrol *kcontrol,
215 struct snd_ctl_elem_info *uinfo)
216{
217 const int size = ARRAY_SIZE(toneport_source_info);
218 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
219 uinfo->count = 1;
220 uinfo->value.enumerated.items = size;
221
e1a164d7 222 if (uinfo->value.enumerated.item >= size)
1027f476
MG
223 uinfo->value.enumerated.item = size - 1;
224
225 strcpy(uinfo->value.enumerated.name,
226 toneport_source_info[uinfo->value.enumerated.item].name);
227
228 return 0;
229}
230
231/* source get callback */
232static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
233 struct snd_ctl_elem_value *ucontrol)
234{
235 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
e1a164d7
MG
236 struct usb_line6_toneport *toneport =
237 (struct usb_line6_toneport *)line6pcm->line6;
1027f476
MG
238 ucontrol->value.enumerated.item[0] = toneport->source;
239 return 0;
240}
241
242/* source put callback */
243static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
244 struct snd_ctl_elem_value *ucontrol)
245{
246 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
e1a164d7
MG
247 struct usb_line6_toneport *toneport =
248 (struct usb_line6_toneport *)line6pcm->line6;
1027f476 249
e1a164d7 250 if (ucontrol->value.enumerated.item[0] == toneport->source)
1027f476
MG
251 return 0;
252
253 toneport->source = ucontrol->value.enumerated.item[0];
e1a164d7
MG
254 toneport_send_cmd(toneport->line6.usbdev,
255 toneport_source_info[toneport->source].code, 0x0000);
1027f476
MG
256 return 1;
257}
258
259static void toneport_start_pcm(unsigned long arg)
260{
261 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
262 struct usb_line6 *line6 = &toneport->line6;
0ca54888 263 line6_pcm_acquire(line6->line6pcm, LINE6_BITS_PCM_MONITOR);
1027f476
MG
264}
265
266/* control definition */
267static struct snd_kcontrol_new toneport_control_monitor = {
268 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
269 .name = "Monitor Playback Volume",
270 .index = 0,
271 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
272 .info = snd_toneport_monitor_info,
273 .get = snd_toneport_monitor_get,
274 .put = snd_toneport_monitor_put
275};
276
277/* source selector definition */
278static struct snd_kcontrol_new toneport_control_source = {
279 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
280 .name = "PCM Capture Source",
281 .index = 0,
282 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
283 .info = snd_toneport_source_info,
284 .get = snd_toneport_source_get,
285 .put = snd_toneport_source_put
286};
287
705ececd
MG
288/*
289 Toneport destructor.
290*/
291static void toneport_destruct(struct usb_interface *interface)
292{
293 struct usb_line6_toneport *toneport = usb_get_intfdata(interface);
705ececd 294
6353773b
GKH
295 if (toneport == NULL)
296 return;
188e6645 297 line6_cleanup_audio(&toneport->line6);
705ececd
MG
298}
299
300/*
1027f476 301 Setup Toneport device.
705ececd 302*/
1027f476 303static void toneport_setup(struct usb_line6_toneport *toneport)
705ececd 304{
1027f476 305 int ticks;
705ececd 306 struct usb_line6 *line6 = &toneport->line6;
1027f476
MG
307 struct usb_device *usbdev = line6->usbdev;
308
309 /* sync time on device with host: */
310 ticks = (int)get_seconds();
311 line6_write_data(line6, 0x80c6, &ticks, 4);
312
313 /* enable device: */
314 toneport_send_cmd(usbdev, 0x0301, 0x0000);
315
316 /* initialize source select: */
e1a164d7 317 switch (usbdev->descriptor.idProduct) {
1027f476 318 case LINE6_DEVID_TONEPORT_UX1:
12177acd 319 case LINE6_DEVID_TONEPORT_UX2:
1027f476 320 case LINE6_DEVID_PODSTUDIO_UX1:
12177acd 321 case LINE6_DEVID_PODSTUDIO_UX2:
e1a164d7
MG
322 toneport_send_cmd(usbdev,
323 toneport_source_info[toneport->source].code,
324 0x0000);
1027f476
MG
325 }
326
327 if (toneport_has_led(usbdev->descriptor.idProduct))
328 toneport_update_led(&usbdev->dev);
329}
330
331/*
332 Try to init Toneport device.
333*/
334static int toneport_try_init(struct usb_interface *interface,
335 struct usb_line6_toneport *toneport)
336{
337 int err;
338 struct usb_line6 *line6 = &toneport->line6;
339 struct usb_device *usbdev = line6->usbdev;
705ececd 340
6353773b 341 if ((interface == NULL) || (toneport == NULL))
705ececd
MG
342 return -ENODEV;
343
344 /* initialize audio system: */
6353773b 345 err = line6_init_audio(line6);
027360c5 346 if (err < 0)
705ececd 347 return err;
705ececd
MG
348
349 /* initialize PCM subsystem: */
6353773b 350 err = line6_init_pcm(line6, &toneport_pcm_properties);
027360c5 351 if (err < 0)
705ececd 352 return err;
705ececd 353
1027f476 354 /* register monitor control: */
027360c5
GKH
355 err = snd_ctl_add(line6->card,
356 snd_ctl_new1(&toneport_control_monitor,
357 line6->line6pcm));
358 if (err < 0)
1027f476 359 return err;
1027f476
MG
360
361 /* register source select control: */
e1a164d7 362 switch (usbdev->descriptor.idProduct) {
1027f476 363 case LINE6_DEVID_TONEPORT_UX1:
12177acd 364 case LINE6_DEVID_TONEPORT_UX2:
1027f476 365 case LINE6_DEVID_PODSTUDIO_UX1:
12177acd 366 case LINE6_DEVID_PODSTUDIO_UX2:
e1a164d7
MG
367 err =
368 snd_ctl_add(line6->card,
369 snd_ctl_new1(&toneport_control_source,
370 line6->line6pcm));
027360c5 371 if (err < 0)
1027f476 372 return err;
1027f476
MG
373 }
374
705ececd 375 /* register audio system: */
6353773b 376 err = line6_register_audio(line6);
027360c5 377 if (err < 0)
705ececd 378 return err;
705ececd 379
705ececd
MG
380 line6_read_serial_number(line6, &toneport->serial_number);
381 line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
382
1027f476 383 if (toneport_has_led(usbdev->descriptor.idProduct)) {
e1a164d7
MG
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));
1027f476 388 }
705ececd 389
1027f476 390 toneport_setup(toneport);
705ececd 391
1027f476
MG
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);
705ececd
MG
397
398 return 0;
399}
400
1027f476
MG
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
027360c5 409 if (err < 0)
1027f476 410 toneport_destruct(interface);
1027f476
MG
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
705ececd
MG
423/*
424 Toneport device disconnected.
425*/
1027f476 426void line6_toneport_disconnect(struct usb_interface *interface)
705ececd
MG
427{
428 struct usb_line6_toneport *toneport;
429
6353773b
GKH
430 if (interface == NULL)
431 return;
1027f476 432
705ececd 433 toneport = usb_get_intfdata(interface);
1027f476 434 del_timer_sync(&toneport->timer);
705ececd 435
1027f476 436 if (toneport_has_led(toneport->line6.usbdev->descriptor.idProduct)) {
705ececd
MG
437 device_remove_file(&interface->dev, &dev_attr_led_red);
438 device_remove_file(&interface->dev, &dev_attr_led_green);
439 }
440
6353773b 441 if (toneport != NULL) {
705ececd
MG
442 struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm;
443
6353773b 444 if (line6pcm != NULL) {
0ca54888 445 line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR);
1027f476 446 line6_pcm_disconnect(line6pcm);
705ececd
MG
447 }
448 }
449
450 toneport_destruct(interface);
451}
This page took 0.316683 seconds and 5 git commands to generate.