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_acquire(line6pcm, LINE6_BITS_PCM_MONITOR);
211	else
212		line6_pcm_release(line6pcm, LINE6_BITS_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_acquire(line6->line6pcm, LINE6_BITS_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_TONEPORT_UX2:
324	case LINE6_DEVID_PODSTUDIO_UX1:
325	case LINE6_DEVID_PODSTUDIO_UX2:
326		toneport_send_cmd(usbdev,
327				  toneport_source_info[toneport->source].code,
328				  0x0000);
329	}
330
331	if (toneport_has_led(usbdev->descriptor.idProduct))
332		toneport_update_led(&usbdev->dev);
333}
334
335/*
336	 Try to init Toneport device.
337*/
338static int toneport_try_init(struct usb_interface *interface,
339			     struct usb_line6_toneport *toneport)
340{
341	int err;
342	struct usb_line6 *line6 = &toneport->line6;
343	struct usb_device *usbdev = line6->usbdev;
344
345	if ((interface == NULL) || (toneport == NULL))
346		return -ENODEV;
347
348	/* initialize audio system: */
349	err = line6_init_audio(line6);
350	if (err < 0)
351		return err;
352
353	/* initialize PCM subsystem: */
354	err = line6_init_pcm(line6, &toneport_pcm_properties);
355	if (err < 0)
356		return err;
357
358	/* register monitor control: */
359	err = snd_ctl_add(line6->card,
360			  snd_ctl_new1(&toneport_control_monitor,
361				       line6->line6pcm));
362	if (err < 0)
363		return err;
364
365	/* register source select control: */
366	switch (usbdev->descriptor.idProduct) {
367	case LINE6_DEVID_TONEPORT_UX1:
368	case LINE6_DEVID_TONEPORT_UX2:
369	case LINE6_DEVID_PODSTUDIO_UX1:
370	case LINE6_DEVID_PODSTUDIO_UX2:
371		err =
372		    snd_ctl_add(line6->card,
373				snd_ctl_new1(&toneport_control_source,
374					     line6->line6pcm));
375		if (err < 0)
376			return err;
377	}
378
379	/* register audio system: */
380	err = line6_register_audio(line6);
381	if (err < 0)
382		return err;
383
384	line6_read_serial_number(line6, &toneport->serial_number);
385	line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
386
387	if (toneport_has_led(usbdev->descriptor.idProduct)) {
388		CHECK_RETURN(device_create_file
389			     (&interface->dev, &dev_attr_led_red));
390		CHECK_RETURN(device_create_file
391			     (&interface->dev, &dev_attr_led_green));
392	}
393
394	toneport_setup(toneport);
395
396	init_timer(&toneport->timer);
397	toneport->timer.expires = jiffies + TONEPORT_PCM_DELAY * HZ;
398	toneport->timer.function = toneport_start_pcm;
399	toneport->timer.data = (unsigned long)toneport;
400	add_timer(&toneport->timer);
401
402	return 0;
403}
404
405/*
406	 Init Toneport device (and clean up in case of failure).
407*/
408int line6_toneport_init(struct usb_interface *interface,
409			struct usb_line6_toneport *toneport)
410{
411	int err = toneport_try_init(interface, toneport);
412
413	if (err < 0)
414		toneport_destruct(interface);
415
416	return err;
417}
418
419/*
420	Resume Toneport device after reset.
421*/
422void line6_toneport_reset_resume(struct usb_line6_toneport *toneport)
423{
424	toneport_setup(toneport);
425}
426
427/*
428	Toneport device disconnected.
429*/
430void line6_toneport_disconnect(struct usb_interface *interface)
431{
432	struct usb_line6_toneport *toneport;
433
434	if (interface == NULL)
435		return;
436
437	toneport = usb_get_intfdata(interface);
438	del_timer_sync(&toneport->timer);
439
440	if (toneport_has_led(toneport->line6.usbdev->descriptor.idProduct)) {
441		device_remove_file(&interface->dev, &dev_attr_led_red);
442		device_remove_file(&interface->dev, &dev_attr_led_green);
443	}
444
445	if (toneport != NULL) {
446		struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm;
447
448		if (line6pcm != NULL) {
449			line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR);
450			line6_pcm_disconnect(line6pcm);
451		}
452	}
453
454	toneport_destruct(interface);
455}
456